RF22

- Main Page
- Classes
- Files
- Examples

- File List

RF22Mesh.h
1 // RF22Mesh.h
2 //
3 // Author: Mike McCauley (mikem@airspayce.com)
4 // Copyright (C) 2011 Mike McCauley
5 // $Id: RF22Mesh.h,v 1.5 2014/04/01 05:06:44 mikem Exp mikem $
6
7 #ifndef RF22Mesh_h
8 #define RF22Mesh_h
9
10 #include <RF22Router.h>
11
12 // Types of RF22Mesh message, used to set msgType in the RF22MeshHeader
13 #define RF22_MESH_MESSAGE_TYPE_APPLICATION 0
14 #define RF22_MESH_MESSAGE_TYPE_ROUTE_DISCOVERY_REQUEST 1
15 #define RF22_MESH_MESSAGE_TYPE_ROUTE_DISCOVERY_RESPONSE 2
16 #define RF22_MESH_MESSAGE_TYPE_ROUTE_FAILURE 3
17
18 /////////////////////////////////////////////////////////////////////
19 /// \class RF22Mesh RF22Mesh.h <RF22Mesh.h>
20 /// \brief RF22 subclass for sending addressed, optionally acknowledged datagrams
21 /// multi-hop routed across a network, with automatic route discovery
22 ///
23 /// Extends RF22Router to add automatic route discovery within a mesh of adjacent nodes,
24 /// and route signalling.
25 ///
26 /// Unlike RF22Router, RF22Mesh can be used in networks where the network topology is fluid, or unknown,
27 /// or if nodes can mode around or go in or out of service. When a node wants to send a
28 /// message to another node, it will automcatically discover a route to the destaintion node and use it.
29 /// If the route becomes unavailable, a new route will be discovered.
30 ///
31 /// \par Route Discovery
32 ///
33 /// When a RF22Mesh mesh node is initialised, it doe not know any routes to any other nodes
34 /// (see RF22Router for details on route and the routing table).
35 /// When you attempt to send a message with sendtoWait, will first check to see if there is a route to the
36 /// destinastion node in the routing tabl;e. If not, it wil initialite 'Route Discovery'.
37 /// When a node needs to discover a route to another node, it broadcasts MeshRouteDiscoveryMessage
38 /// with a message type of RF22_MESH_MESSAGE_TYPE_ROUTE_DISCOVERY_REQUEST.
39 /// Any node that receives such a request checks to see if it is a request for a route to itself
40 /// (in which case it makes a unicast reply to the originating node with a
41 /// MeshRouteDiscoveryMessage
42 /// with a message type of RF22_MESH_MESSAGE_TYPE_ROUTE_DISCOVERY_RESPONSE)
43 /// otherwise it rebroadcasts the request, after adding itself to the list of nodes visited so
44 /// far by the request.
45 ///
46 /// If a node receives a RF22_MESH_MESSAGE_TYPE_ROUTE_DISCOVERY_REQUEST that already has itself
47 /// listed in the visited nodes, it knows it has already seen and rebroadcast this request,
48 /// and threfore ignores it. This prevents broadcast storms.
49 /// When a node receives a RF22_MESH_MESSAGE_TYPE_ROUTE_DISCOVERY_REQUEST it can use the list of
50 /// nodes aready visited to deduce routes back towards the originating (requesting node).
51 /// This also means that when the destination node of the request is reached, it (and all
52 /// the previous nodes the request visited) will have a route back to the originating node.
53 /// This means the unicast RF22_MESH_MESSAGE_TYPE_ROUTE_DISCOVERY_RESPONSE
54 /// reply will be routed successfully back to the original route requester.
55 ///
56 /// The RF22_MESH_MESSAGE_TYPE_ROUTE_DISCOVERY_RESPONSE sent back by the destination node contains
57 /// the full list of nodes that were visited on the way to the destination.
58 /// Therefore, intermediate nodes that route the reply back towards the originating node can use the
59 /// node list in the reply to deduce routes to all the nodes between it and the destination node.
60 ///
61 /// Therefore, RF22_MESH_MESSAGE_TYPE_ROUTE_DISCOVERY_REQUEST and
62 /// RF22_MESH_MESSAGE_TYPE_ROUTE_DISCOVERY_RESPONSE together ensure the original requester and all
63 /// the intermediate nodes know how to route to the source and destination nodes and every node along the path.
64 ///
65 /// Note that there is a race condition here that can effect routing on multipath routes. For example,
66 /// if the route to the destination can traverse several paths, last reply from the destination
67 /// will be the one used.
68 ///
69 /// \par Route Failure
70 ///
71 /// RF22Router (and therefore RF22Mesh) use reliable hop-to-hop delivery of messages using
72 /// hop-to-hop acknowledgements, but not end-to-end acknowledgements. When sendtoWait() returns,
73 /// you know that the message has been delivered to the next hop, but not if it is (or even if it can be)
74 /// delivered to the destination node. If during the course of hop-to-hop routing of a message,
75 /// one of the intermediate RF22Mesh nodes finds it cannot deliver to the next hop
76 /// (say due to a lost route or no acknwledgement from the next hop), it replies to the
77 /// originator with a unicast MeshRouteFailureMessage RF22_MESH_MESSAGE_TYPE_ROUTE_FAILURE message.
78 /// Intermediate nodes (on the way beack to the originator)
79 /// and the originating node use this message to delete the route to the destination
80 /// node of the original message. This means that if a route to a destination becomes unusable
81 /// (either because an intermediate node is off the air, or has moved out of range) a new route
82 /// will be established the next time a message is to be sent.
83 ///
84 /// \par Message Format
85 ///
86 /// RF22Mesh uses a number of message formats layered on top of RF22Router:
87 /// - MeshApplicationMessage (message type RF22_MESH_MESSAGE_TYPE_APPLICATION).
88 /// Carries an application layer message for the caller of RF22Mesh
89 /// - MeshRouteDiscoveryMessage (message types RF22_MESH_MESSAGE_TYPE_ROUTE_DISCOVERY_REQUEST
90 /// and RF22_MESH_MESSAGE_TYPE_ROUTE_DISCOVERY_RESPONSE). Carries Route Discovery messages
91 /// (broadcast) and replies (unicast).
92 /// - MeshRouteFailureMessage (message type RF22_MESH_MESSAGE_TYPE_ROUTE_FAILURE) Informs nodes of
93 /// route failures.
94 ///
95 /// Part of the Arduino RF22 library for operating with HopeRF RF22 compatible transceivers
96 /// (see http://www.hoperf.com)
97 class RF22Mesh : public RF22Router
98 {
99 public:
100
101 /// The maximum length permitted for the application payload data in a RF22Mesh message
102 #define RF22_MESH_MAX_MESSAGE_LEN (RF22_ROUTER_MAX_MESSAGE_LEN - sizeof(RF22Mesh::MeshMessageHeader))
103
104 /// Structure of the basic RF22Mesh header.
105 typedef struct
106 {
107 uint8_t msgType; ///< Type of RF22Mesh message, one of RF22_MESH_MESSAGE_TYPE_*
108 } MeshMessageHeader;
109
110 /// Signals an application layer message for the caller of RF22Mesh
111 typedef struct
112 {
113 MeshMessageHeader header; ///< msgType = RF22_MESH_MESSAGE_TYPE_APPLICATION
114 uint8_t data[RF22_MESH_MAX_MESSAGE_LEN]; ///< Applicaiotn layer payload data
115 } MeshApplicationMessage;
116
117 /// Signals a route discovery request or reply
118 /// At present only supports physical dest addresses of length 1 octet
119 typedef struct
120 {
121 MeshMessageHeader header; ///< msgType = RF22_MESH_MESSAGE_TYPE_ROUTE_DISCOVERY_*
122 uint8_t destlen; ///< Reserved. Must be 1.g
123 uint8_t dest; ///< The address of the destination node whose route is being sought
124 uint8_t route[RF22_MESH_MAX_MESSAGE_LEN - 1]; ///< List of node addresses visited so far. Length is implcit
125 } MeshRouteDiscoveryMessage;
126
127 /// Signals a route failure
128 typedef struct
129 {
130 MeshMessageHeader header; ///< msgType = RF22_MESH_MESSAGE_TYPE_ROUTE_FAILURE
131 uint8_t dest; ///< The address of the destination towards which the route failed
132 } MeshRouteFailureMessage;
133
134 /// Constructor.
135 /// \param[in] thisAddress The address to assign to this node. Defaults to 0
136 /// \param[in] slaveSelectPin the Arduino pin number of the output to use to select the RF22 before
137 /// accessing it. Defaults to the normal SS pin for your Arduino (D10 for Diecimila, Uno etc, D53 for Mega)
138 /// \param[in] interrupt The interrupt number to use. Default is interrupt 0 (Arduino input pin 2)
139 RF22Mesh(uint8_t thisAddress = 0, uint8_t slaveSelectPin = SS, uint8_t interrupt = 0);
140
141 /// Sends a message to the destination node. Initialises the RF22Router message header
142 /// (the SOURCE address is set to the address of this node, HOPS to 0) and calls
143 /// route() which looks up in the routing table the next hop to deliver to.
144 /// If no route is known, initiates route discovery and waits for a reply.
145 /// Then sends the message to the next hop
146 /// Then waits for an acknowledgement from the next hop
147 /// (but not from the destination node (if that is different).
148 /// \param [in] buf The application message data
149 /// \param [in] len Number of octets in the application message data. 0 is permitted
150 /// \param [in] dest The destination node address
151 /// \return The result code:
152 /// - RF22_ROUTER_ERROR_NONE Message was routed and deliverd to the next hop
153 /// (not necessarily to the final dest address)
154 /// - RF22_ROUTER_ERROR_NO_ROUTE There was no route for dest in the local routing table
155 /// - RF22_ROUTER_ERROR_UNABLE_TO_DELIVER Noyt able to deliver to the next hop
156 /// (usually because it dod not acknowledge due to being off the air or out of range
157 uint8_t sendtoWait(uint8_t* buf, uint8_t len, uint8_t dest);
158
159 /// Starts the receiver if it is not running already.
160 /// If there is a valid application layer message available for this node (or RF22_BROADCAST_ADDRESS),
161 /// send an acknowledgement to the last hop
162 /// address (blocking until this is complete), then copy the application message payload data
163 /// to buf and return true
164 /// else return false.
165 /// If a message is copied, *len is set to the length..
166 /// If from is not NULL, the originator SOURCE address is placed in *source.
167 /// If to is not NULL, the DEST address is placed in *dest. This might be this nodes address or
168 /// RF22_BROADCAST_ADDRESS.
169 /// This is the preferred function for getting messages addressed to this node.
170 /// If the message is not a broadcast, acknowledge to the sender before returning.
171 /// \param[in] buf Location to copy the received message
172 /// \param[in,out] len Available space in buf. Set to the actual number of octets copied.
173 /// \param[in] source If present and not NULL, the referenced uint8_t will be set to the SOURCE address
174 /// \param[in] dest If present and not NULL, the referenced uint8_t will be set to the DEST address
175 /// \param[in] id If present and not NULL, the referenced uint8_t will be set to the ID
176 /// \param[in] flags If present and not NULL, the referenced uint8_t will be set to the FLAGS
177 /// (not just those addressed to this node).
178 /// \return true if a valid message was recvived for this node and copied to buf
179 boolean recvfromAck(uint8_t* buf, uint8_t* len, uint8_t* source = NULL, uint8_t* dest = NULL, uint8_t* id = NULL, uint8_t* flags = NULL);
180
181 /// Starts the receiver if it is not running already.
182 /// Similar to recvfromAck(), this will block until either a valid application layer
183 /// message available for this node
184 /// or the timeout expires.
185 /// \param[in] buf Location to copy the received message
186 /// \param[in,out] len Available space in buf. Set to the actual number of octets copied.
187 /// \param[in] timeout Maximum time to wait in milliseconds
188 /// \param[in] source If present and not NULL, the referenced uint8_t will be set to the SOURCE address
189 /// \param[in] dest If present and not NULL, the referenced uint8_t will be set to the DEST address
190 /// \param[in] id If present and not NULL, the referenced uint8_t will be set to the ID
191 /// \param[in] flags If present and not NULL, the referenced uint8_t will be set to the FLAGS
192 /// (not just those addressed to this node).
193 /// \return true if a valid message was copied to buf
194 boolean recvfromAckTimeout(uint8_t* buf, uint8_t* len, uint16_t timeout, uint8_t* source = NULL, uint8_t* dest = NULL, uint8_t* id = NULL, uint8_t* flags = NULL);
195
196 protected:
197
198 /// Internal function that inspects messages being received and adjusts the routing table if necessary.
199 /// Called by recvfromAck() immediately after it gets the message from RF22ReliableDatagram
200 /// \param [in] message Pointer to the RF22Router message that was received.
201 /// \param [in] messageLen Length of message in octets
202 virtual void peekAtMessage(RoutedMessage* message, uint8_t messageLen);
203
204 /// Internal function that inspects messages being received and adjusts the routing table if necessary.
205 /// This is virtual, which lets subclasses override or intercept the route() function.
206 /// Called by sendtoWait after the message header has been filled in.
207 /// \param [in] message Pointer to the RF22Router message to be sent.
208 /// \param [in] messageLen Length of message in octets
209 virtual uint8_t route(RoutedMessage* message, uint8_t messageLen);
210
211 /// Try to resolve a route for the given address. Blocks while discovering the route
212 /// which may take up to 4000 msec.
213 /// Virtual so subclasses can override.
214 /// \param [in] address The physical addres to resolve
215 /// \return true if the address was resolved and added to the local routing table
216 virtual boolean doArp(uint8_t address);
217
218 /// Tests if the given address of length addresslen is indentical to the
219 /// physical addres of this node.
220 /// RF22Mesh always ikmplements p[hysical addresses as the 1 octet address of the node
221 /// given by _thisAddress
222 /// Called by recvfromAck() to test whether a RF22_MESH_MESSAGE_TYPE_ROUTE_DISCOVERY_REQUEST
223 /// is for this node.
224 /// Subclasses may want to override to implemnt mode complicated or longer physical addresses
225 /// \param [in] address Address of the pyysical addres being tested
226 /// \param [in] addresslen Lengthof the address in bytes
227 /// \return true if the physical address of this node is identical to address
228 virtual boolean isPhysicalAddress(uint8_t* address, uint8_t addresslen);
229
230 private:
231 /// Temporary mesage buffer
232 static uint8_t _tmpMessage[RF22_ROUTER_MAX_MESSAGE_LEN];
233
234 };
235
236 #endif
237
RF22Mesh::route
virtual uint8_t route(RoutedMessage *message, uint8_t messageLen)
Definition: RF22Mesh.cpp:117
RF22Mesh::MeshRouteDiscoveryMessage::header
MeshMessageHeader header
msgType = RF22_MESH_MESSAGE_TYPE_ROUTE_DISCOVERY_*
Definition: RF22Mesh.h:121
RF22Mesh::MeshRouteDiscoveryMessage
Definition: RF22Mesh.h:119
RF22Mesh::recvfromAck
boolean recvfromAck(uint8_t *buf, uint8_t *len, uint8_t *source=NULL, uint8_t *dest=NULL, uint8_t *id=NULL, uint8_t *flags=NULL)
Definition: RF22Mesh.cpp:149
RF22Mesh::MeshRouteFailureMessage
Signals a route failure.
Definition: RF22Mesh.h:128
RF22Mesh::MeshMessageHeader
Structure of the basic RF22Mesh header.
Definition: RF22Mesh.h:105
RF22Mesh::MeshRouteFailureMessage::header
MeshMessageHeader header
msgType = RF22_MESH_MESSAGE_TYPE_ROUTE_FAILURE
Definition: RF22Mesh.h:130
RF22Router::RoutedMessage
Defines the structure of a RF22Router message.
Definition: RF22Router.h:149
RF22Mesh::MeshApplicationMessage::header
MeshMessageHeader header
msgType = RF22_MESH_MESSAGE_TYPE_APPLICATION
Definition: RF22Mesh.h:113
RF22Mesh::MeshRouteFailureMessage::dest
uint8_t dest
The address of the destination towards which the route failed.
Definition: RF22Mesh.h:131
RF22Mesh::MeshApplicationMessage
Signals an application layer message for the caller of RF22Mesh.
Definition: RF22Mesh.h:111
RF22Mesh::RF22Mesh
RF22Mesh(uint8_t thisAddress=0, uint8_t slaveSelectPin=SS, uint8_t interrupt=0)
Definition: RF22Mesh.cpp:21
RF22Mesh::recvfromAckTimeout
boolean recvfromAckTimeout(uint8_t *buf, uint8_t *len, uint16_t timeout, uint8_t *source=NULL, uint8_t *dest=NULL, uint8_t *id=NULL, uint8_t *flags=NULL)
Definition: RF22Mesh.cpp:221
RF22Mesh::MeshRouteDiscoveryMessage::destlen
uint8_t destlen
Reserved. Must be 1.g.
Definition: RF22Mesh.h:122
RF22Mesh::sendtoWait
uint8_t sendtoWait(uint8_t *buf, uint8_t len, uint8_t dest)
Definition: RF22Mesh.cpp:32
RF22Mesh::peekAtMessage
virtual void peekAtMessage(RoutedMessage *message, uint8_t messageLen)
Definition: RF22Mesh.cpp:86
RF22Mesh::MeshMessageHeader::msgType
uint8_t msgType
Type of RF22Mesh message, one of RF22_MESH_MESSAGE_TYPE_*.
Definition: RF22Mesh.h:107
RF22Mesh::MeshRouteDiscoveryMessage::dest
uint8_t dest
The address of the destination node whose route is being sought.
Definition: RF22Mesh.h:123
RF22Mesh
RF22 subclass for sending addressed, optionally acknowledged datagrams multi-hop routed across a netw...
Definition: RF22Mesh.h:97
RF22Mesh::isPhysicalAddress
virtual boolean isPhysicalAddress(uint8_t *address, uint8_t addresslen)
Definition: RF22Mesh.cpp:142
RF22Mesh::doArp
virtual boolean doArp(uint8_t address)
Definition: RF22Mesh.cpp:49
RF22Router
RF22 subclass for sending addressed, optionally acknowledged datagrams multi-hop routed across a netw...
Definition: RF22Router.h:132