- Main Page
- Classes
- Files

# RF22Mesh.h

    00001 // RF22Mesh.h
    00002 //
    00003 // Author: Mike McCauley (mikem@open.com.au)
    00004 // Copyright (C) 2011 Mike McCauley
    00005 // $Id: RF22Mesh.h,v 1.3 2011/02/15 04:51:59 mikem Exp $
    00006
    00007 #ifndef RF22Mesh_h
    00008 #define RF22Mesh_h
    00009
    00010 #include <RF22Router.h>
    00011
    00012 // Types of RF22Mesh message, used to set msgType in the RF22MeshHeader
    00013 #define RF22_MESH_MESSAGE_TYPE_APPLICATION                    0
    00014 #define RF22_MESH_MESSAGE_TYPE_ROUTE_DISCOVERY_REQUEST        1
    00015 #define RF22_MESH_MESSAGE_TYPE_ROUTE_DISCOVERY_RESPONSE       2
    00016 #define RF22_MESH_MESSAGE_TYPE_ROUTE_FAILURE                  3
    00017
    00018 /////////////////////////////////////////////////////////////////////
    00019 /// \class RF22Mesh RF22Mesh.h <RF22Mesh.h>
    00020 /// \brief RF22 subclass for sending addressed, optionally acknowledged datagrams
    00021 /// multi-hop routed across a network, with automatic route discovery
    00022 ///
    00023 /// Extends RF22Router to add automatic route discovery within a mesh of adjacent nodes,
    00024 /// and route signalling.
    00025 ///
    00026 /// Unlike RF22Router, RF22Mesh can be used in networks where the network topology is fluid, or unknown,
    00027 /// or if nodes can mode around or go in or out of service. When a node wants to send a
    00028 /// message to another node, it will automcatically discover a route to the destaintion node and use it.
    00029 /// If the route becomes unavailable, a new route will be discovered.
    00030 ///
    00031 /// \par Route Discovery
    00032 ///
    00033 /// When a RF22Mesh mesh node is initialised, it doe not know any routes to any other nodes
    00034 /// (see RF22Router for details on route and the routing table).
    00035 /// When you attempt to send a message with sendtoWait, will first check to see if there is a route to the
    00036 /// destinastion node in the routing tabl;e. If not, it wil initialite 'Route Discovery'.
    00037 /// When a node needs to discover a route to another node, it broadcasts MeshRouteDiscoveryMessage
    00038 /// with a message type of RF22_MESH_MESSAGE_TYPE_ROUTE_DISCOVERY_REQUEST.
    00039 /// Any node that receives such a request checks to see if it is a request for a route to itself
    00040 /// (in which case it makes a unicast reply to the originating node with a
    00041 /// MeshRouteDiscoveryMessage
    00042 /// with a message type of RF22_MESH_MESSAGE_TYPE_ROUTE_DISCOVERY_RESPONSE)
    00043 /// otherwise it rebroadcasts the request, after adding itself to the list of nodes visited so
    00044 /// far by the request.
    00045 ///
    00046 /// If a node receives a RF22_MESH_MESSAGE_TYPE_ROUTE_DISCOVERY_REQUEST that already has itself
    00047 /// listed in the visited nodes, it knows it has already seen and rebroadcast this request,
    00048 /// and threfore ignores it. This prevents broadcast storms.
    00049 /// When a node receives a RF22_MESH_MESSAGE_TYPE_ROUTE_DISCOVERY_REQUEST it can use the list of
    00050 /// nodes aready visited to deduce routes back towards the originating (requesting node).
    00051 /// This also means that when the destination node of the request is reached, it (and all
    00052 /// the previous nodes the request visited) will have a route back to the originating node.
    00053 /// This means the unicast RF22_MESH_MESSAGE_TYPE_ROUTE_DISCOVERY_RESPONSE
    00054 /// reply will be routed successfully back to the original route requester.
    00055 ///
    00056 /// The RF22_MESH_MESSAGE_TYPE_ROUTE_DISCOVERY_RESPONSE sent back by the destination node contains
    00057 /// the full list of nodes that were visited on the way to the destination.
    00058 /// Therefore, intermediate nodes that route the reply back towards the originating node can use the
    00059 /// node list in the reply to deduce routes to all the nodes between it and the destination node.
    00060 ///
    00061 /// Therefore, RF22_MESH_MESSAGE_TYPE_ROUTE_DISCOVERY_REQUEST and
    00062 /// RF22_MESH_MESSAGE_TYPE_ROUTE_DISCOVERY_RESPONSE together ensure the original requester and all
    00063 /// the intermediate nodes know how to route to the source and destination nodes and every node along the path.
    00064 ///
    00065 /// Note that there is a race condition here that can effect routing on multipath routes. For example,
    00066 /// if the route to the destination can traverse several paths, last reply from the destination
    00067 /// will be the one used.
    00068 ///
    00069 /// \par Route Failure
    00070 ///
    00071 /// RF22Router (and therefore RF22Mesh) use reliable hop-to-hop delivery of messages using
    00072 /// hop-to-hop acknowledgements, but not end-to-end acknowledgements. When sendtoWait() returns,
    00073 /// you know that the message has been delivered to the next hop, but not if it is (or even if it can be)
    00074 /// delivered to the destination node. If during the course of hop-to-hop routing of a message,
    00075 /// one of the intermediate RF22Mesh nodes finds it cannot deliver to the next hop
    00076 /// (say due to a lost route or no acknwledgement from the next hop), it replies to the
    00077 /// originator with a unicast MeshRouteFailureMessage RF22_MESH_MESSAGE_TYPE_ROUTE_FAILURE message.
    00078 /// Intermediate nodes (on the way beack to the originator)
    00079 /// and the originating node use this message to delete the route to the destination
    00080 /// node of the original message. This means that if a route to a destination becomes unusable
    00081 /// (either because an intermediate node is off the air, or has moved out of range) a new route
    00082 /// will be established the next time a message is to be sent.
    00083 ///
    00084 /// \par Message Format
    00085 ///
    00086 /// RF22Mesh uses a number of message formats layered on top of RF22Router:
    00087 /// - MeshApplicationMessage (message type RF22_MESH_MESSAGE_TYPE_APPLICATION).
    00088 ///   Carries an application layer message for the caller of RF22Mesh
    00089 /// - MeshRouteDiscoveryMessage (message types RF22_MESH_MESSAGE_TYPE_ROUTE_DISCOVERY_REQUEST
    00090 ///   and RF22_MESH_MESSAGE_TYPE_ROUTE_DISCOVERY_RESPONSE). Carries Route Discovery messages
    00091 ///   (broadcast) and replies (unicast).
    00092 /// - MeshRouteFailureMessage (message type RF22_MESH_MESSAGE_TYPE_ROUTE_FAILURE) Informs nodes of
    00093 ///   route failures.
    00094 ///
    00095 /// Part of the Arduino RF22 library for operating with HopeRF RF22 compatible transceivers
    00096 /// (see http://www.hoperf.com)
    00097 class RF22Mesh : public RF22Router
    00098 {
    00099 public:
    00100
    00101     /// The maximum length permitted for the application payload data in a RF22Mesh message
    00102     #define RF22_MESH_MAX_MESSAGE_LEN (RF22_ROUTER_MAX_MESSAGE_LEN - sizeof(RF22Mesh::MeshMessageHeader))
    00103
    00104     /// Structure of the basic RF22Mesh header.
    00105     typedef struct
    00106     {
    00107         uint8_t             msgType;  ///< Type of RF22Mesh message, one of RF22_MESH_MESSAGE_TYPE_*
    00108     } MeshMessageHeader;
    00109
    00110     /// Signals an application layer message for the caller of RF22Mesh
    00111     typedef struct
    00112     {
    00113         MeshMessageHeader   header; ///< msgType = RF22_MESH_MESSAGE_TYPE_APPLICATION
    00114         uint8_t             data[RF22_MESH_MAX_MESSAGE_LEN]; ///< Applicaiotn layer payload data
    00115     } MeshApplicationMessage;
    00116
    00117     /// Signals a route discovery request or reply
    00118     /// At present only supports physical dest addresses of length 1 octet
    00119     typedef struct
    00120     {
    00121         MeshMessageHeader   header; ///< msgType = RF22_MESH_MESSAGE_TYPE_ROUTE_DISCOVERY_*
    00122         uint8_t             destlen; ///< Reserved. Must be 1.
    00123         uint8_t             dest;   ///< The address of the destination node whose route is being sought
    00124         uint8_t             route[RF22_MESH_MAX_MESSAGE_LEN - 1]; ///< List of node addresses visited so far. Length is implcit
    00125     } MeshRouteDiscoveryMessage;
    00126
    00127     /// Signals a route failure
    00128     typedef struct
    00129     {
    00130         MeshMessageHeader   header; ///< msgType = RF22_MESH_MESSAGE_TYPE_ROUTE_FAILURE
    00131         uint8_t             dest; ///< The address of the destination towards which the route failed
    00132     } MeshRouteFailureMessage;
    00133
    00134     /// Constructor.
    00135     /// \param[in] thisAddress The address to assign to this node. Defaults to 0
    00136     /// \param[in] slaveSelectPin the Arduino pin number of the output to use to select the RF22 before
    00137     /// accessing it
    00138     /// \param[in] interrupt The interrupt number to use. Default is interrupt 0 (Arduino input pin 2)
    00139     RF22Mesh(uint8_t thisAddress = 0, uint8_t slaveSelectPin = 10, uint8_t interrupt = 0);
    00140
    00141     /// Sends a message to the destination node. Initialises the RF22Router message header
    00142     /// (the SOURCE address is set to the address of this node, HOPS to 0) and calls
    00143     /// route() which looks up in the routing table the next hop to deliver to.
    00144     /// If no route is known, initiates route discovery and waits for a reply.
    00145     /// Then sends the message to the next hop
    00146     /// Then waits for an acknowledgement from the next hop
    00147     /// (but not from the destination node (if that is different).
    00148     /// \param [in] buf The application message data
    00149     /// \param [in] len Number of octets in the application message data. 0 is permitted
    00150     /// \param [in] dest The destination node address
    00151     /// \return The result code:
    00152     ///         - RF22_ROUTER_ERROR_NONE Message was routed and deliverd to the next hop
    00153     ///           (not necessarily to the final dest address)
    00154     ///         - RF22_ROUTER_ERROR_NO_ROUTE There was no route for dest in the local routing table
    00155     ///         - RF22_ROUTER_ERROR_UNABLE_TO_DELIVER Noyt able to deliver to the next hop
    00156     ///           (usually because it dod not acknowledge due to being off the air or out of range
    00157     uint8_t sendtoWait(uint8_t* buf, uint8_t len, uint8_t dest);
    00158
    00159     /// Starts the receiver if it is not running already.
    00160     /// If there is a valid application layer message available for this node (or RF22_BROADCAST_ADDRESS),
    00161     /// send an acknowledgement to the last hop
    00162     /// address (blocking until this is complete), then copy the application message payload data
    00163     /// to buf and return true
    00164     /// else return false.
    00165     /// If a message is copied, *len is set to the length..
    00166     /// If from is not NULL, the originator SOURCE address is placed in *source.
    00167     /// If to is not NULL, the DEST address is placed in *dest. This might be this nodes address or
    00168     /// RF22_BROADCAST_ADDRESS.
    00169     /// This is the preferred function for getting messages addressed to this node.
    00170     /// If the message is not a broadcast, acknowledge to the sender before returning.
    00171     /// \param[in] buf Location to copy the received message
    00172     /// \param[in,out] len Available space in buf. Set to the actual number of octets copied.
    00173     /// \param[in] source If present and not NULL, the referenced uint8_t will be set to the SOURCE address
    00174     /// \param[in] dest If present and not NULL, the referenced uint8_t will be set to the DEST address
    00175     /// \param[in] id If present and not NULL, the referenced uint8_t will be set to the ID
    00176     /// \param[in] flags If present and not NULL, the referenced uint8_t will be set to the FLAGS
    00177     /// (not just those addressed to this node).
    00178     /// \return true if a valid message was recvived for this node and copied to buf
    00179     boolean recvfromAck(uint8_t* buf, uint8_t* len, uint8_t* source = NULL, uint8_t* dest = NULL, uint8_t* id = NULL, uint8_t* flags = NULL);
    00180
    00181     /// Starts the receiver if it is not running already.
    00182     /// Similar to recvfromAck(), this will block until either a valid application layer
    00183     /// message available for this node
    00184     /// or the timeout expires.
    00185     /// \param[in] buf Location to copy the received message
    00186     /// \param[in,out] len Available space in buf. Set to the actual number of octets copied.
    00187     /// \param[in] timeout Maximum time to wait in milliseconds
    00188     /// \param[in] source If present and not NULL, the referenced uint8_t will be set to the SOURCE address
    00189     /// \param[in] dest If present and not NULL, the referenced uint8_t will be set to the DEST address
    00190     /// \param[in] id If present and not NULL, the referenced uint8_t will be set to the ID
    00191     /// \param[in] flags If present and not NULL, the referenced uint8_t will be set to the FLAGS
    00192     /// (not just those addressed to this node).
    00193     /// \return true if a valid message was copied to buf
    00194     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);
    00195
    00196 protected:
    00197
    00198     /// Internal function that inspects messages being received and adjusts the routing table if necessary.
    00199     /// Called by recvfromAck() immediately after it gets the message from RF22ReliableDatagram
    00200     /// \param [in] message Pointer to the RF22Router message that was received.
    00201     /// \param [in] messageLen Length of message in octets
    00202     virtual void peekAtMessage(RoutedMessage* message, uint8_t messageLen);
    00203
    00204     /// Internal function that inspects messages being received and adjusts the routing table if necessary.
    00205     /// This is virtual, which lets subclasses override or intercept the route() function.
    00206     /// Called by sendtoWait after the message header has been filled in.
    00207     /// \param [in] message Pointer to the RF22Router message to be sent.
    00208     /// \param [in] messageLen Length of message in octets
    00209     virtual uint8_t route(RoutedMessage* message, uint8_t messageLen);
    00210
    00211     /// Try to resolve a route for the given address. Blocks while discovering the route
    00212     /// which may take up to 4000 msec.
    00213     /// Virtual so subclasses can override.
    00214     /// \param [in] address The physical addres to resolve
    00215     /// \return true if the address was resolved and added to the local routing table
    00216     virtual boolean doArp(uint8_t address);
    00217
    00218     /// Tests if the given address of length addresslen is indentical to the
    00219     /// physical addres of this node.
    00220     /// RF22Mesh always ikmplements p[hysical addresses as the 1 octet address of the node
    00221     /// given by _thisAddress
    00222     /// Called by recvfromAck() to test whether a RF22_MESH_MESSAGE_TYPE_ROUTE_DISCOVERY_REQUEST
    00223     /// is for this node.
    00224     /// Subclasses may want to override to implemnt mode complicated or longer physical addresses
    00225     /// \param [in] address Address of the pyysical addres being tested
    00226     /// \param [in] addresslen Lengthof the address in bytes
    00227     /// \return true if the physical address of this node is identical to address
    00228     virtual boolean isPhysicalAddress(uint8_t* address, uint8_t addresslen);
    00229
    00230 private:
    00231     /// Temporary mesage buffer
    00232     static uint8_t _tmpMessage[RF22_ROUTER_MAX_MESSAGE_LEN];
    00233
    00234 };
    00235
    00236 #endif
    00237