Library for HopeRF RFM22 / RFM22B transceiver module ported to mbed. Original Software from Mike McCauley (mikem@open.com.au) . See http://www.open.com.au/mikem/arduino/RF22/

Dependents:   RF22_MAX_test_Send Geofence_receiver Geofence_sender Geofence_sender ... more

Embed: (wiki syntax)

« Back to documentation index

Show/hide line numbers RF22Mesh.cpp Source File

RF22Mesh.cpp

00001 // RF22Mesh.cpp
00002 //
00003 // Define addressed datagram
00004 // 
00005 // Part of the Arduino RF22 library for operating with HopeRF RF22 compatible transceivers 
00006 // (see http://www.hoperf.com)
00007 // RF22Datagram will be received only by the addressed node or all nodes within range if the 
00008 // to address is RF22_BROADCAST_ADDRESS
00009 //
00010 // Author: Mike McCauley (mikem@open.com.au)
00011 // Copyright (C) 2011 Mike McCauley
00012 // $Id: RF22Mesh.cpp,v 1.4 2011/02/15 04:51:59 mikem Exp $
00013 // ported to mbed by Karl Zweimueller
00014 
00015 #include <mbed.h>
00016 #include <RF22Mesh.h>
00017 //#include <SPI.h>
00018 
00019 
00020 uint8_t RF22Mesh::_tmpMessage[RF22_ROUTER_MAX_MESSAGE_LEN];
00021 
00022 ////////////////////////////////////////////////////////////////////
00023 // Constructors
00024 RF22Mesh::RF22Mesh(uint8_t thisAddress ,PinName slaveSelectPin , PinName mosi, PinName miso, PinName sclk, PinName interrupt ) 
00025     : RF22Router(thisAddress, slaveSelectPin, mosi,  miso, sclk, interrupt )
00026 {
00027 }
00028 
00029 ////////////////////////////////////////////////////////////////////
00030 // Public methods
00031 
00032 ////////////////////////////////////////////////////////////////////
00033 // Discovers a route to the destination (if necessary), sends and 
00034 // waits for delivery to the next hop (but not for delivery to the final destination)
00035 uint8_t RF22Mesh::sendtoWait(uint8_t* buf, uint8_t len, uint8_t address)
00036 {
00037     if (len > RF22_MESH_MAX_MESSAGE_LEN)
00038     return RF22_ROUTER_ERROR_INVALID_LENGTH;
00039 
00040     RoutingTableEntry* route = getRouteTo(address);
00041     if (!route && !doArp(address))
00042     return RF22_ROUTER_ERROR_NO_ROUTE;
00043 
00044     // Now have a route. Contruct an applicaiotn layer message and dend it via that route
00045     MeshApplicationMessage* a = (MeshApplicationMessage*)&_tmpMessage;
00046     a->header.msgType = RF22_MESH_MESSAGE_TYPE_APPLICATION;
00047     memcpy(a->data, buf, len);
00048     return RF22Router::sendtoWait(_tmpMessage, sizeof(RF22Mesh::MeshMessageHeader) + len, address);
00049 }
00050 
00051 ////////////////////////////////////////////////////////////////////
00052 boolean RF22Mesh::doArp(uint8_t address)
00053 {
00054     // Need to discover a route
00055     // Broadcast a route discovery message with nothing in it
00056     MeshRouteDiscoveryMessage* p = (MeshRouteDiscoveryMessage*)&_tmpMessage;
00057     p->header.msgType = RF22_MESH_MESSAGE_TYPE_ROUTE_DISCOVERY_REQUEST;
00058     p->destlen = 1; 
00059     p->dest = address; // Who we are looking for
00060     uint8_t error = RF22Router::sendtoWait((uint8_t*)p, sizeof(RF22Mesh::MeshMessageHeader) + 2, RF22_BROADCAST_ADDRESS);
00061     if (error !=  RF22_ROUTER_ERROR_NONE)
00062     return false;
00063     
00064     // Wait for a reply, which will be unicast back to us
00065     // It will contain the complete route to the destination
00066     uint8_t messageLen = sizeof(_tmpMessage);
00067     // FIXME: timeout should be configurable
00068     Timer t;
00069     t.start();
00070     unsigned long endtime = t.read_ms() + 4000;
00071     while (t.read_ms() < endtime)
00072     {
00073     if (RF22Router::recvfromAck(_tmpMessage, &messageLen))
00074     {
00075         if (   messageLen > 1
00076         && p->header.msgType == RF22_MESH_MESSAGE_TYPE_ROUTE_DISCOVERY_RESPONSE)
00077         {
00078         MeshRouteDiscoveryMessage* d = (MeshRouteDiscoveryMessage*)p;
00079         // Got a reply, now add the next hop to the dest to the routing table
00080         // The first hop taken is the first octet
00081         addRouteTo(address, headerFrom());
00082         return true;
00083         }
00084     }
00085     }
00086     return false;
00087 }
00088 
00089 ////////////////////////////////////////////////////////////////////
00090 // Called by RF22Router::recvfromAck whenever a message goes past
00091 void RF22Mesh::peekAtMessage(RoutedMessage* message, uint8_t messageLen)
00092 {
00093     MeshMessageHeader* m = (MeshMessageHeader*)message->data;
00094     if (   messageLen > 1 
00095     && m->msgType == RF22_MESH_MESSAGE_TYPE_ROUTE_DISCOVERY_RESPONSE)
00096     {
00097     // This is a unicast RF22_MESH_MESSAGE_TYPE_ROUTE_DISCOVERY_RESPONSE messages 
00098     // being routed back to the originator here. Want to scrape some routing data out of the response
00099     // We can find the routes to all the nodes between here and the responding node
00100     MeshRouteDiscoveryMessage* d = (MeshRouteDiscoveryMessage*)message->data;
00101     addRouteTo(d->dest, headerFrom());
00102     uint8_t numRoutes = messageLen - sizeof(RoutedMessageHeader) - sizeof(MeshMessageHeader) - 2;
00103     uint8_t i;
00104     // Find us in the list of nodes that were traversed to get to the responding node
00105     for (i = 0; i < numRoutes; i++)
00106         if (d->route[i] == _thisAddress)
00107         break;
00108     i++;
00109     while (i++ < numRoutes)
00110         addRouteTo(d->route[i], headerFrom());
00111     }
00112     else if (   messageLen > 1 
00113          && m->msgType == RF22_MESH_MESSAGE_TYPE_ROUTE_FAILURE)
00114     {
00115     MeshRouteFailureMessage* d = (MeshRouteFailureMessage*)message->data;
00116     deleteRouteTo(d->dest);
00117     }
00118 }
00119 
00120 ////////////////////////////////////////////////////////////////////
00121 // This is called when a message is to be delivered to the next hop
00122 uint8_t RF22Mesh::route(RoutedMessage* message, uint8_t messageLen)
00123 {
00124     uint8_t from = headerFrom(); // Might get clobbered during call to superclass route()
00125     uint8_t ret = RF22Router::route(message, messageLen);
00126     if (   ret == RF22_ROUTER_ERROR_NO_ROUTE
00127     || ret == RF22_ROUTER_ERROR_UNABLE_TO_DELIVER)
00128     {
00129     // Cant deliver to the next hop. Delete the route
00130     deleteRouteTo(message->header.dest);
00131     if (message->header.source != _thisAddress)
00132     {
00133         // This is being proxied, so tell the originator about it
00134         MeshRouteFailureMessage* p = (MeshRouteFailureMessage*)&_tmpMessage;
00135         p->header.msgType = RF22_MESH_MESSAGE_TYPE_ROUTE_FAILURE;
00136         p->dest = message->header.dest; // Who you were trying to deliver to
00137         // Make sure there is a route back towards whoever sent the original message
00138         addRouteTo(message->header.source, from);
00139         ret = RF22Router::sendtoWait((uint8_t*)p, sizeof(RF22Mesh::MeshMessageHeader) + 1, message->header.source);
00140     }
00141     }
00142     return ret;
00143 }
00144 
00145 ////////////////////////////////////////////////////////////////////
00146 // Subclasses may want to override
00147 boolean RF22Mesh::isPhysicalAddress(uint8_t* address, uint8_t addresslen)
00148 {
00149     // Can only handle physical addresses 1 octet long, which is the physical node address
00150     return addresslen == 1 && address[0] == _thisAddress;
00151 }
00152 
00153 ////////////////////////////////////////////////////////////////////
00154 boolean RF22Mesh::recvfromAck(uint8_t* buf, uint8_t* len, uint8_t* source, uint8_t* dest, uint8_t* id, uint8_t* flags)
00155 {     
00156     uint8_t tmpMessageLen = sizeof(_tmpMessage);
00157     uint8_t _source;
00158     uint8_t _dest;
00159     uint8_t _id;
00160     uint8_t _flags;
00161     if (RF22Router::recvfromAck(_tmpMessage, &tmpMessageLen, &_source, &_dest, &_id, &_flags))
00162     {
00163     MeshMessageHeader* p = (MeshMessageHeader*)&_tmpMessage;
00164 
00165     if (   tmpMessageLen >= 1 
00166         && p->msgType == RF22_MESH_MESSAGE_TYPE_APPLICATION)
00167     {
00168         MeshApplicationMessage* a = (MeshApplicationMessage*)p;
00169         // Handle application layer messages, presumably for our caller
00170         if (source) *source = _source;
00171         if (dest)   *dest   = _dest;
00172         if (id)     *id     = _id;
00173         if (flags)  *flags  = _flags;
00174         uint8_t msgLen = tmpMessageLen - sizeof(MeshMessageHeader);
00175         if (*len > msgLen)
00176         *len = msgLen;
00177         memcpy(buf, a->data, *len);
00178         
00179         return true;
00180     }
00181     else if (   _dest == RF22_BROADCAST_ADDRESS 
00182          && tmpMessageLen > 1 
00183          && p->msgType == RF22_MESH_MESSAGE_TYPE_ROUTE_DISCOVERY_REQUEST)
00184     {
00185         MeshRouteDiscoveryMessage* d = (MeshRouteDiscoveryMessage*)p;
00186         // Handle Route discovery requests
00187         // Message is an array of node addresses the route request has already passed through
00188         // If it originally came from us, ignore it
00189         if (_source == _thisAddress)
00190         return false;
00191         
00192         uint8_t numRoutes = tmpMessageLen - sizeof(MeshMessageHeader) - 2;
00193         uint8_t i;
00194         // Are we already mentioned?
00195         for (i = 0; i < numRoutes; i++)
00196         if (d->route[i] == _thisAddress)
00197             return false; // Already been through us. Discard
00198         
00199         // Hasnt been past us yet, record routes back to the earlier nodes
00200         addRouteTo(_source, headerFrom()); // The originator
00201         for (i = 0; i < numRoutes; i++)
00202         addRouteTo(d->route[i], headerFrom());
00203         if (isPhysicalAddress(&d->dest, d->destlen))
00204         {
00205         // This route discovery is for us. Unicast the whole route back to the originator
00206         // as a RF22_MESH_MESSAGE_TYPE_ROUTE_DISCOVERY_RESPONSE
00207         // We are certain to have a route there, becuase we just got it
00208         d->header.msgType = RF22_MESH_MESSAGE_TYPE_ROUTE_DISCOVERY_RESPONSE;
00209         RF22Router::sendtoWait((uint8_t*)d, tmpMessageLen, _source);
00210         }
00211         else if (i < _max_hops)
00212         {
00213         // Its for someone else, rebroadcast it, after adding ourselves to the list
00214         d->route[numRoutes] = _thisAddress;
00215         tmpMessageLen++;
00216         // Have to impersonate the source
00217         // REVISIT: if this fails what can we do?
00218         RF22Router::sendtoWait(_tmpMessage, tmpMessageLen, RF22_BROADCAST_ADDRESS, _source);
00219         }
00220     }
00221     }
00222     return false;
00223 }
00224 
00225 ////////////////////////////////////////////////////////////////////
00226 boolean RF22Mesh::recvfromAckTimeout(uint8_t* buf, uint8_t* len, uint16_t timeout, uint8_t* from, uint8_t* to, uint8_t* id, uint8_t* flags)
00227 {  
00228     Timer t;
00229     
00230     t.start();
00231     unsigned long endtime = t.read_ms() + timeout;
00232     while (t.read_ms() < endtime)
00233     {
00234     if (recvfromAck(buf, len, from, to, id, flags))
00235         return true;
00236     }
00237     return false;
00238 }
00239 
00240