Important changes to repositories hosted on mbed.com
Mbed hosted mercurial repositories are deprecated and are due to be permanently deleted in July 2026.
To keep a copy of this software download the repository Zip archive or clone locally using Mercurial.
It is also possible to export all your personal repositories from the account settings page.
Dependents: Threaded_LoRa_Modem
RHMesh.h
00001 // RHMesh.h 00002 // 00003 // Author: Mike McCauley (mikem@airspayce.com) 00004 // Copyright (C) 2011 Mike McCauley 00005 // $Id: RHMesh.h,v 1.15 2015/08/13 02:45:47 mikem Exp $ 00006 00007 #ifndef RHMesh_h 00008 #define RHMesh_h 00009 00010 #include <RHRouter.h> 00011 00012 // Types of RHMesh message, used to set msgType in the RHMeshHeader 00013 #define RH_MESH_MESSAGE_TYPE_APPLICATION 0 00014 #define RH_MESH_MESSAGE_TYPE_ROUTE_DISCOVERY_REQUEST 1 00015 #define RH_MESH_MESSAGE_TYPE_ROUTE_DISCOVERY_RESPONSE 2 00016 #define RH_MESH_MESSAGE_TYPE_ROUTE_FAILURE 3 00017 00018 // Timeout for address resolution in milliecs 00019 #define RH_MESH_ARP_TIMEOUT 4000 00020 00021 ///////////////////////////////////////////////////////////////////// 00022 /// \class RHMesh RHMesh.h <RHMesh.h> 00023 /// \brief RHRouter subclass for sending addressed, optionally acknowledged datagrams 00024 /// multi-hop routed across a network, with automatic route discovery 00025 /// 00026 /// Manager class that extends RHRouter to add automatic route discovery within a mesh of adjacent nodes, 00027 /// and route signalling. 00028 /// 00029 /// Unlike RHRouter, RHMesh can be used in networks where the network topology is fluid, or unknown, 00030 /// or if nodes can mode around or go in or out of service. When a node wants to send a 00031 /// message to another node, it will automatically discover a route to the destination node and use it. 00032 /// If the route becomes unavailable, a new route will be discovered. 00033 /// 00034 /// \par Route Discovery 00035 /// 00036 /// When a RHMesh mesh node is initialised, it doe not know any routes to any other nodes 00037 /// (see RHRouter for details on route and the routing table). 00038 /// When you attempt to send a message with sendtoWait, will first check to see if there is a route to the 00039 /// destinastion node in the routing tabl;e. If not, it wil initialite 'Route Discovery'. 00040 /// When a node needs to discover a route to another node, it broadcasts MeshRouteDiscoveryMessage 00041 /// with a message type of RH_MESH_MESSAGE_TYPE_ROUTE_DISCOVERY_REQUEST. 00042 /// Any node that receives such a request checks to see if it is a request for a route to itself 00043 /// (in which case it makes a unicast reply to the originating node with a 00044 /// MeshRouteDiscoveryMessage 00045 /// with a message type of RH_MESH_MESSAGE_TYPE_ROUTE_DISCOVERY_RESPONSE) 00046 /// otherwise it rebroadcasts the request, after adding itself to the list of nodes visited so 00047 /// far by the request. 00048 /// 00049 /// If a node receives a RH_MESH_MESSAGE_TYPE_ROUTE_DISCOVERY_REQUEST that already has itself 00050 /// listed in the visited nodes, it knows it has already seen and rebroadcast this request, 00051 /// and threfore ignores it. This prevents broadcast storms. 00052 /// When a node receives a RH_MESH_MESSAGE_TYPE_ROUTE_DISCOVERY_REQUEST it can use the list of 00053 /// nodes aready visited to deduce routes back towards the originating (requesting node). 00054 /// This also means that when the destination node of the request is reached, it (and all 00055 /// the previous nodes the request visited) will have a route back to the originating node. 00056 /// This means the unicast RH_MESH_MESSAGE_TYPE_ROUTE_DISCOVERY_RESPONSE 00057 /// reply will be routed successfully back to the original route requester. 00058 /// 00059 /// The RH_MESH_MESSAGE_TYPE_ROUTE_DISCOVERY_RESPONSE sent back by the destination node contains 00060 /// the full list of nodes that were visited on the way to the destination. 00061 /// Therefore, intermediate nodes that route the reply back towards the originating node can use the 00062 /// node list in the reply to deduce routes to all the nodes between it and the destination node. 00063 /// 00064 /// Therefore, RH_MESH_MESSAGE_TYPE_ROUTE_DISCOVERY_REQUEST and 00065 /// RH_MESH_MESSAGE_TYPE_ROUTE_DISCOVERY_RESPONSE together ensure the original requester and all 00066 /// the intermediate nodes know how to route to the source and destination nodes and every node along the path. 00067 /// 00068 /// Note that there is a race condition here that can effect routing on multipath routes. For example, 00069 /// if the route to the destination can traverse several paths, last reply from the destination 00070 /// will be the one used. 00071 /// 00072 /// \par Route Failure 00073 /// 00074 /// RHRouter (and therefore RHMesh) use reliable hop-to-hop delivery of messages using 00075 /// hop-to-hop acknowledgements, but not end-to-end acknowledgements. When sendtoWait() returns, 00076 /// you know that the message has been delivered to the next hop, but not if it is (or even if it can be) 00077 /// delivered to the destination node. If during the course of hop-to-hop routing of a message, 00078 /// one of the intermediate RHMesh nodes finds it cannot deliver to the next hop 00079 /// (say due to a lost route or no acknwledgement from the next hop), it replies to the 00080 /// originator with a unicast MeshRouteFailureMessage RH_MESH_MESSAGE_TYPE_ROUTE_FAILURE message. 00081 /// Intermediate nodes (on the way beack to the originator) 00082 /// and the originating node use this message to delete the route to the destination 00083 /// node of the original message. This means that if a route to a destination becomes unusable 00084 /// (either because an intermediate node is off the air, or has moved out of range) a new route 00085 /// will be established the next time a message is to be sent. 00086 /// 00087 /// \par Message Format 00088 /// 00089 /// RHMesh uses a number of message formats layered on top of RHRouter: 00090 /// - MeshApplicationMessage (message type RH_MESH_MESSAGE_TYPE_APPLICATION). 00091 /// Carries an application layer message for the caller of RHMesh 00092 /// - MeshRouteDiscoveryMessage (message types RH_MESH_MESSAGE_TYPE_ROUTE_DISCOVERY_REQUEST 00093 /// and RH_MESH_MESSAGE_TYPE_ROUTE_DISCOVERY_RESPONSE). Carries Route Discovery messages 00094 /// (broadcast) and replies (unicast). 00095 /// - MeshRouteFailureMessage (message type RH_MESH_MESSAGE_TYPE_ROUTE_FAILURE) Informs nodes of 00096 /// route failures. 00097 /// 00098 /// Part of the Arduino RH library for operating with HopeRF RH compatible transceivers 00099 /// (see http://www.hoperf.com) 00100 /// 00101 /// \par Memory 00102 /// 00103 /// RHMesh programs require significant amount of SRAM, often approaching 2kbytes, 00104 /// which is beyond or at the limits of some Arduinos and other processors. Programs 00105 /// with additional software besides basic RHMesh programs may well require even more. If you have insufficient 00106 /// SRAM for your program, it may result in failure to run, or wierd crashes and other hard to trace behaviour. 00107 /// In this event you should consider a processor with more SRAM, such as the MotienoMEGA with 16k 00108 /// (https://lowpowerlab.com/shop/moteinomega) or others. 00109 /// 00110 /// \par Performance 00111 /// This class (in the interests of simple implemtenation and low memory use) does not have 00112 /// message queueing. This means that only one message at a time can be handled. Message transmission 00113 /// failures can have a severe impact on network performance. 00114 /// If you need high performance mesh networking under all conditions consider XBee or similar. 00115 class RHMesh : public RHRouter 00116 { 00117 public: 00118 00119 /// The maximum length permitted for the application payload data in a RHMesh message 00120 #define RH_MESH_MAX_MESSAGE_LEN (RH_ROUTER_MAX_MESSAGE_LEN - sizeof(RHMesh::MeshMessageHeader)) 00121 00122 /// Structure of the basic RHMesh header. 00123 typedef struct 00124 { 00125 uint8_t msgType; ///< Type of RHMesh message, one of RH_MESH_MESSAGE_TYPE_* 00126 } MeshMessageHeader; 00127 00128 /// Signals an application layer message for the caller of RHMesh 00129 typedef struct 00130 { 00131 MeshMessageHeader header; ///< msgType = RH_MESH_MESSAGE_TYPE_APPLICATION 00132 uint8_t data[RH_MESH_MAX_MESSAGE_LEN]; ///< Application layer payload data 00133 } MeshApplicationMessage; 00134 00135 /// Signals a route discovery request or reply (At present only supports physical dest addresses of length 1 octet) 00136 typedef struct 00137 { 00138 MeshMessageHeader header; ///< msgType = RH_MESH_MESSAGE_TYPE_ROUTE_DISCOVERY_* 00139 uint8_t destlen; ///< Reserved. Must be 1.g 00140 uint8_t dest; ///< The address of the destination node whose route is being sought 00141 uint8_t route[RH_MESH_MAX_MESSAGE_LEN - 1]; ///< List of node addresses visited so far. Length is implcit 00142 } MeshRouteDiscoveryMessage; 00143 00144 /// Signals a route failure 00145 typedef struct 00146 { 00147 MeshMessageHeader header; ///< msgType = RH_MESH_MESSAGE_TYPE_ROUTE_FAILURE 00148 uint8_t dest; ///< The address of the destination towards which the route failed 00149 } MeshRouteFailureMessage; 00150 00151 /// Constructor. 00152 /// \param[in] driver The RadioHead driver to use to transport messages. 00153 /// \param[in] thisAddress The address to assign to this node. Defaults to 0 00154 RHMesh(RHGenericDriver& driver, uint8_t thisAddress = 0); 00155 00156 /// Sends a message to the destination node. Initialises the RHRouter message header 00157 /// (the SOURCE address is set to the address of this node, HOPS to 0) and calls 00158 /// route() which looks up in the routing table the next hop to deliver to. 00159 /// If no route is known, initiates route discovery and waits for a reply. 00160 /// Then sends the message to the next hop 00161 /// Then waits for an acknowledgement from the next hop 00162 /// (but not from the destination node (if that is different). 00163 /// \param [in] buf The application message data 00164 /// \param [in] len Number of octets in the application message data. 0 is permitted 00165 /// \param [in] dest The destination node address. If the address is RH_BROADCAST_ADDRESS (255) 00166 /// the message will be broadcast to all the nearby nodes, but not routed or relayed. 00167 /// \param [in] flags Optional flags for use by subclasses or application layer, 00168 /// delivered end-to-end to the dest address. The receiver can recover the flags with recvFromAck(). 00169 /// \return The result code: 00170 /// - RH_ROUTER_ERROR_NONE Message was routed and delivered to the next hop 00171 /// (not necessarily to the final dest address) 00172 /// - RH_ROUTER_ERROR_NO_ROUTE There was no route for dest in the local routing table 00173 /// - RH_ROUTER_ERROR_UNABLE_TO_DELIVER Not able to deliver to the next hop 00174 /// (usually because it dod not acknowledge due to being off the air or out of range 00175 uint8_t sendtoWait(uint8_t* buf, uint8_t len, uint8_t dest, uint8_t flags = 0); 00176 00177 /// Starts the receiver if it is not running already, processes and possibly routes any received messages 00178 /// addressed to other nodes 00179 /// and delivers any messages addressed to this node. 00180 /// If there is a valid application layer message available for this node (or RH_BROADCAST_ADDRESS), 00181 /// send an acknowledgement to the last hop 00182 /// address (blocking until this is complete), then copy the application message payload data 00183 /// to buf and return true 00184 /// else return false. 00185 /// If a message is copied, *len is set to the length.. 00186 /// If from is not NULL, the originator SOURCE address is placed in *source. 00187 /// If to is not NULL, the DEST address is placed in *dest. This might be this nodes address or 00188 /// RH_BROADCAST_ADDRESS. 00189 /// This is the preferred function for getting messages addressed to this node. 00190 /// If the message is not a broadcast, acknowledge to the sender before returning. 00191 /// \param[in] buf Location to copy the received message 00192 /// \param[in,out] len Available space in buf. Set to the actual number of octets copied. 00193 /// \param[in] source If present and not NULL, the referenced uint8_t will be set to the SOURCE address 00194 /// \param[in] dest If present and not NULL, the referenced uint8_t will be set to the DEST address 00195 /// \param[in] id If present and not NULL, the referenced uint8_t will be set to the ID 00196 /// \param[in] flags If present and not NULL, the referenced uint8_t will be set to the FLAGS 00197 /// (not just those addressed to this node). 00198 /// \return true if a valid message was received for this node and copied to buf 00199 bool recvfromAck(uint8_t* buf, uint8_t* len, uint8_t* source = NULL, uint8_t* dest = NULL, uint8_t* id = NULL, uint8_t* flags = NULL); 00200 00201 /// Starts the receiver if it is not running already. 00202 /// Similar to recvfromAck(), this will block until either a valid application layer 00203 /// message available for this node 00204 /// or the timeout expires. 00205 /// \param[in] buf Location to copy the received message 00206 /// \param[in,out] len Available space in buf. Set to the actual number of octets copied. 00207 /// \param[in] timeout Maximum time to wait in milliseconds 00208 /// \param[in] source If present and not NULL, the referenced uint8_t will be set to the SOURCE address 00209 /// \param[in] dest If present and not NULL, the referenced uint8_t will be set to the DEST address 00210 /// \param[in] id If present and not NULL, the referenced uint8_t will be set to the ID 00211 /// \param[in] flags If present and not NULL, the referenced uint8_t will be set to the FLAGS 00212 /// (not just those addressed to this node). 00213 /// \return true if a valid message was copied to buf 00214 bool 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); 00215 00216 protected: 00217 00218 /// Internal function that inspects messages being received and adjusts the routing table if necessary. 00219 /// Called by recvfromAck() immediately after it gets the message from RHReliableDatagram 00220 /// \param [in] message Pointer to the RHRouter message that was received. 00221 /// \param [in] messageLen Length of message in octets 00222 virtual void peekAtMessage(RoutedMessage* message, uint8_t messageLen); 00223 00224 /// Internal function that inspects messages being received and adjusts the routing table if necessary. 00225 /// This is virtual, which lets subclasses override or intercept the route() function. 00226 /// Called by sendtoWait after the message header has been filled in. 00227 /// \param [in] message Pointer to the RHRouter message to be sent. 00228 /// \param [in] messageLen Length of message in octets 00229 virtual uint8_t route(RoutedMessage* message, uint8_t messageLen); 00230 00231 /// Try to resolve a route for the given address. Blocks while discovering the route 00232 /// which may take up to 4000 msec. 00233 /// Virtual so subclasses can override. 00234 /// \param [in] address The physical address to resolve 00235 /// \return true if the address was resolved and added to the local routing table 00236 virtual bool doArp(uint8_t address); 00237 00238 /// Tests if the given address of length addresslen is indentical to the 00239 /// physical address of this node. 00240 /// RHMesh always implements physical addresses as the 1 octet address of the node 00241 /// given by _thisAddress 00242 /// Called by recvfromAck() to test whether a RH_MESH_MESSAGE_TYPE_ROUTE_DISCOVERY_REQUEST 00243 /// is for this node. 00244 /// Subclasses may want to override to implement more complicated or longer physical addresses 00245 /// \param [in] address Address of the pyysical addres being tested 00246 /// \param [in] addresslen Lengthof the address in bytes 00247 /// \return true if the physical address of this node is identical to address 00248 virtual bool isPhysicalAddress(uint8_t* address, uint8_t addresslen); 00249 00250 private: 00251 /// Temporary message buffer 00252 static uint8_t _tmpMessage[RH_ROUTER_MAX_MESSAGE_LEN]; 00253 00254 }; 00255 00256 /// @example rf22_mesh_client.pde 00257 /// @example rf22_mesh_server1.pde 00258 /// @example rf22_mesh_server2.pde 00259 /// @example rf22_mesh_server3.pde 00260 00261 #endif 00262
Generated on Thu Jul 14 2022 12:14:49 by
1.7.2