Dependents:   New

Committer:
SangSTBK
Date:
Mon Jul 02 01:29:58 2012 +0000
Revision:
0:e16ffa7cb900
RF

Who changed what in which revision?

UserRevisionLine numberNew contents of line
SangSTBK 0:e16ffa7cb900 1 // RF22Mesh.cpp
SangSTBK 0:e16ffa7cb900 2 //
SangSTBK 0:e16ffa7cb900 3 // Define addressed datagram
SangSTBK 0:e16ffa7cb900 4 //
SangSTBK 0:e16ffa7cb900 5 // Part of the Arduino RF22 library for operating with HopeRF RF22 compatible transceivers
SangSTBK 0:e16ffa7cb900 6 // (see http://www.hoperf.com)
SangSTBK 0:e16ffa7cb900 7 // RF22Datagram will be received only by the addressed node or all nodes within range if the
SangSTBK 0:e16ffa7cb900 8 // to address is RF22_BROADCAST_ADDRESS
SangSTBK 0:e16ffa7cb900 9 //
SangSTBK 0:e16ffa7cb900 10 // Author: Mike McCauley (mikem@open.com.au)
SangSTBK 0:e16ffa7cb900 11 // Copyright (C) 2011 Mike McCauley
SangSTBK 0:e16ffa7cb900 12 // $Id: RF22Mesh.cpp,v 1.4 2011/02/15 04:51:59 mikem Exp $
SangSTBK 0:e16ffa7cb900 13 // ported to mbed by Karl Zweimueller
SangSTBK 0:e16ffa7cb900 14
SangSTBK 0:e16ffa7cb900 15 #include <mbed.h>
SangSTBK 0:e16ffa7cb900 16 #include <RF22Mesh.h>
SangSTBK 0:e16ffa7cb900 17 //#include <SPI.h>
SangSTBK 0:e16ffa7cb900 18
SangSTBK 0:e16ffa7cb900 19
SangSTBK 0:e16ffa7cb900 20 uint8_t RF22Mesh::_tmpMessage[RF22_ROUTER_MAX_MESSAGE_LEN];
SangSTBK 0:e16ffa7cb900 21
SangSTBK 0:e16ffa7cb900 22 ////////////////////////////////////////////////////////////////////
SangSTBK 0:e16ffa7cb900 23 // Constructors
SangSTBK 0:e16ffa7cb900 24 RF22Mesh::RF22Mesh(uint8_t thisAddress ,PinName slaveSelectPin , PinName mosi, PinName miso, PinName sclk, PinName interrupt )
SangSTBK 0:e16ffa7cb900 25 : RF22Router(thisAddress, slaveSelectPin, mosi, miso, sclk, interrupt )
SangSTBK 0:e16ffa7cb900 26 {
SangSTBK 0:e16ffa7cb900 27 }
SangSTBK 0:e16ffa7cb900 28
SangSTBK 0:e16ffa7cb900 29 ////////////////////////////////////////////////////////////////////
SangSTBK 0:e16ffa7cb900 30 // Public methods
SangSTBK 0:e16ffa7cb900 31
SangSTBK 0:e16ffa7cb900 32 ////////////////////////////////////////////////////////////////////
SangSTBK 0:e16ffa7cb900 33 // Discovers a route to the destination (if necessary), sends and
SangSTBK 0:e16ffa7cb900 34 // waits for delivery to the next hop (but not for delivery to the final destination)
SangSTBK 0:e16ffa7cb900 35 uint8_t RF22Mesh::sendtoWait(uint8_t* buf, uint8_t len, uint8_t address)
SangSTBK 0:e16ffa7cb900 36 {
SangSTBK 0:e16ffa7cb900 37 if (len > RF22_MESH_MAX_MESSAGE_LEN)
SangSTBK 0:e16ffa7cb900 38 return RF22_ROUTER_ERROR_INVALID_LENGTH;
SangSTBK 0:e16ffa7cb900 39
SangSTBK 0:e16ffa7cb900 40 RoutingTableEntry* route = getRouteTo(address);
SangSTBK 0:e16ffa7cb900 41 if (!route && !doArp(address))
SangSTBK 0:e16ffa7cb900 42 return RF22_ROUTER_ERROR_NO_ROUTE;
SangSTBK 0:e16ffa7cb900 43
SangSTBK 0:e16ffa7cb900 44 // Now have a route. Contruct an applicaiotn layer message and dend it via that route
SangSTBK 0:e16ffa7cb900 45 MeshApplicationMessage* a = (MeshApplicationMessage*)&_tmpMessage;
SangSTBK 0:e16ffa7cb900 46 a->header.msgType = RF22_MESH_MESSAGE_TYPE_APPLICATION;
SangSTBK 0:e16ffa7cb900 47 memcpy(a->data, buf, len);
SangSTBK 0:e16ffa7cb900 48 return RF22Router::sendtoWait(_tmpMessage, sizeof(RF22Mesh::MeshMessageHeader) + len, address);
SangSTBK 0:e16ffa7cb900 49 }
SangSTBK 0:e16ffa7cb900 50
SangSTBK 0:e16ffa7cb900 51 ////////////////////////////////////////////////////////////////////
SangSTBK 0:e16ffa7cb900 52 boolean RF22Mesh::doArp(uint8_t address)
SangSTBK 0:e16ffa7cb900 53 {
SangSTBK 0:e16ffa7cb900 54 // Need to discover a route
SangSTBK 0:e16ffa7cb900 55 // Broadcast a route discovery message with nothing in it
SangSTBK 0:e16ffa7cb900 56 MeshRouteDiscoveryMessage* p = (MeshRouteDiscoveryMessage*)&_tmpMessage;
SangSTBK 0:e16ffa7cb900 57 p->header.msgType = RF22_MESH_MESSAGE_TYPE_ROUTE_DISCOVERY_REQUEST;
SangSTBK 0:e16ffa7cb900 58 p->destlen = 1;
SangSTBK 0:e16ffa7cb900 59 p->dest = address; // Who we are looking for
SangSTBK 0:e16ffa7cb900 60 uint8_t error = RF22Router::sendtoWait((uint8_t*)p, sizeof(RF22Mesh::MeshMessageHeader) + 2, RF22_BROADCAST_ADDRESS);
SangSTBK 0:e16ffa7cb900 61 if (error != RF22_ROUTER_ERROR_NONE)
SangSTBK 0:e16ffa7cb900 62 return false;
SangSTBK 0:e16ffa7cb900 63
SangSTBK 0:e16ffa7cb900 64 // Wait for a reply, which will be unicast back to us
SangSTBK 0:e16ffa7cb900 65 // It will contain the complete route to the destination
SangSTBK 0:e16ffa7cb900 66 uint8_t messageLen = sizeof(_tmpMessage);
SangSTBK 0:e16ffa7cb900 67 // FIXME: timeout should be configurable
SangSTBK 0:e16ffa7cb900 68 Timer t;
SangSTBK 0:e16ffa7cb900 69 t.start();
SangSTBK 0:e16ffa7cb900 70 unsigned long endtime = t.read_ms() + 4000;
SangSTBK 0:e16ffa7cb900 71 while (t.read_ms() < endtime)
SangSTBK 0:e16ffa7cb900 72 {
SangSTBK 0:e16ffa7cb900 73 if (RF22Router::recvfromAck(_tmpMessage, &messageLen))
SangSTBK 0:e16ffa7cb900 74 {
SangSTBK 0:e16ffa7cb900 75 if ( messageLen > 1
SangSTBK 0:e16ffa7cb900 76 && p->header.msgType == RF22_MESH_MESSAGE_TYPE_ROUTE_DISCOVERY_RESPONSE)
SangSTBK 0:e16ffa7cb900 77 {
SangSTBK 0:e16ffa7cb900 78 MeshRouteDiscoveryMessage* d = (MeshRouteDiscoveryMessage*)p;
SangSTBK 0:e16ffa7cb900 79 // Got a reply, now add the next hop to the dest to the routing table
SangSTBK 0:e16ffa7cb900 80 // The first hop taken is the first octet
SangSTBK 0:e16ffa7cb900 81 addRouteTo(address, headerFrom());
SangSTBK 0:e16ffa7cb900 82 return true;
SangSTBK 0:e16ffa7cb900 83 }
SangSTBK 0:e16ffa7cb900 84 }
SangSTBK 0:e16ffa7cb900 85 }
SangSTBK 0:e16ffa7cb900 86 return false;
SangSTBK 0:e16ffa7cb900 87 }
SangSTBK 0:e16ffa7cb900 88
SangSTBK 0:e16ffa7cb900 89 ////////////////////////////////////////////////////////////////////
SangSTBK 0:e16ffa7cb900 90 // Called by RF22Router::recvfromAck whenever a message goes past
SangSTBK 0:e16ffa7cb900 91 void RF22Mesh::peekAtMessage(RoutedMessage* message, uint8_t messageLen)
SangSTBK 0:e16ffa7cb900 92 {
SangSTBK 0:e16ffa7cb900 93 MeshMessageHeader* m = (MeshMessageHeader*)message->data;
SangSTBK 0:e16ffa7cb900 94 if ( messageLen > 1
SangSTBK 0:e16ffa7cb900 95 && m->msgType == RF22_MESH_MESSAGE_TYPE_ROUTE_DISCOVERY_RESPONSE)
SangSTBK 0:e16ffa7cb900 96 {
SangSTBK 0:e16ffa7cb900 97 // This is a unicast RF22_MESH_MESSAGE_TYPE_ROUTE_DISCOVERY_RESPONSE messages
SangSTBK 0:e16ffa7cb900 98 // being routed back to the originator here. Want to scrape some routing data out of the response
SangSTBK 0:e16ffa7cb900 99 // We can find the routes to all the nodes between here and the responding node
SangSTBK 0:e16ffa7cb900 100 MeshRouteDiscoveryMessage* d = (MeshRouteDiscoveryMessage*)message->data;
SangSTBK 0:e16ffa7cb900 101 addRouteTo(d->dest, headerFrom());
SangSTBK 0:e16ffa7cb900 102 uint8_t numRoutes = messageLen - sizeof(RoutedMessageHeader) - sizeof(MeshMessageHeader) - 2;
SangSTBK 0:e16ffa7cb900 103 uint8_t i;
SangSTBK 0:e16ffa7cb900 104 // Find us in the list of nodes that were traversed to get to the responding node
SangSTBK 0:e16ffa7cb900 105 for (i = 0; i < numRoutes; i++)
SangSTBK 0:e16ffa7cb900 106 if (d->route[i] == _thisAddress)
SangSTBK 0:e16ffa7cb900 107 break;
SangSTBK 0:e16ffa7cb900 108 i++;
SangSTBK 0:e16ffa7cb900 109 while (i++ < numRoutes)
SangSTBK 0:e16ffa7cb900 110 addRouteTo(d->route[i], headerFrom());
SangSTBK 0:e16ffa7cb900 111 }
SangSTBK 0:e16ffa7cb900 112 else if ( messageLen > 1
SangSTBK 0:e16ffa7cb900 113 && m->msgType == RF22_MESH_MESSAGE_TYPE_ROUTE_FAILURE)
SangSTBK 0:e16ffa7cb900 114 {
SangSTBK 0:e16ffa7cb900 115 MeshRouteFailureMessage* d = (MeshRouteFailureMessage*)message->data;
SangSTBK 0:e16ffa7cb900 116 deleteRouteTo(d->dest);
SangSTBK 0:e16ffa7cb900 117 }
SangSTBK 0:e16ffa7cb900 118 }
SangSTBK 0:e16ffa7cb900 119
SangSTBK 0:e16ffa7cb900 120 ////////////////////////////////////////////////////////////////////
SangSTBK 0:e16ffa7cb900 121 // This is called when a message is to be delivered to the next hop
SangSTBK 0:e16ffa7cb900 122 uint8_t RF22Mesh::route(RoutedMessage* message, uint8_t messageLen)
SangSTBK 0:e16ffa7cb900 123 {
SangSTBK 0:e16ffa7cb900 124 uint8_t from = headerFrom(); // Might get clobbered during call to superclass route()
SangSTBK 0:e16ffa7cb900 125 uint8_t ret = RF22Router::route(message, messageLen);
SangSTBK 0:e16ffa7cb900 126 if ( ret == RF22_ROUTER_ERROR_NO_ROUTE
SangSTBK 0:e16ffa7cb900 127 || ret == RF22_ROUTER_ERROR_UNABLE_TO_DELIVER)
SangSTBK 0:e16ffa7cb900 128 {
SangSTBK 0:e16ffa7cb900 129 // Cant deliver to the next hop. Delete the route
SangSTBK 0:e16ffa7cb900 130 deleteRouteTo(message->header.dest);
SangSTBK 0:e16ffa7cb900 131 if (message->header.source != _thisAddress)
SangSTBK 0:e16ffa7cb900 132 {
SangSTBK 0:e16ffa7cb900 133 // This is being proxied, so tell the originator about it
SangSTBK 0:e16ffa7cb900 134 MeshRouteFailureMessage* p = (MeshRouteFailureMessage*)&_tmpMessage;
SangSTBK 0:e16ffa7cb900 135 p->header.msgType = RF22_MESH_MESSAGE_TYPE_ROUTE_FAILURE;
SangSTBK 0:e16ffa7cb900 136 p->dest = message->header.dest; // Who you were trying to deliver to
SangSTBK 0:e16ffa7cb900 137 // Make sure there is a route back towards whoever sent the original message
SangSTBK 0:e16ffa7cb900 138 addRouteTo(message->header.source, from);
SangSTBK 0:e16ffa7cb900 139 ret = RF22Router::sendtoWait((uint8_t*)p, sizeof(RF22Mesh::MeshMessageHeader) + 1, message->header.source);
SangSTBK 0:e16ffa7cb900 140 }
SangSTBK 0:e16ffa7cb900 141 }
SangSTBK 0:e16ffa7cb900 142 return ret;
SangSTBK 0:e16ffa7cb900 143 }
SangSTBK 0:e16ffa7cb900 144
SangSTBK 0:e16ffa7cb900 145 ////////////////////////////////////////////////////////////////////
SangSTBK 0:e16ffa7cb900 146 // Subclasses may want to override
SangSTBK 0:e16ffa7cb900 147 boolean RF22Mesh::isPhysicalAddress(uint8_t* address, uint8_t addresslen)
SangSTBK 0:e16ffa7cb900 148 {
SangSTBK 0:e16ffa7cb900 149 // Can only handle physical addresses 1 octet long, which is the physical node address
SangSTBK 0:e16ffa7cb900 150 return addresslen == 1 && address[0] == _thisAddress;
SangSTBK 0:e16ffa7cb900 151 }
SangSTBK 0:e16ffa7cb900 152
SangSTBK 0:e16ffa7cb900 153 ////////////////////////////////////////////////////////////////////
SangSTBK 0:e16ffa7cb900 154 boolean RF22Mesh::recvfromAck(uint8_t* buf, uint8_t* len, uint8_t* source, uint8_t* dest, uint8_t* id, uint8_t* flags)
SangSTBK 0:e16ffa7cb900 155 {
SangSTBK 0:e16ffa7cb900 156 uint8_t tmpMessageLen = sizeof(_tmpMessage);
SangSTBK 0:e16ffa7cb900 157 uint8_t _source;
SangSTBK 0:e16ffa7cb900 158 uint8_t _dest;
SangSTBK 0:e16ffa7cb900 159 uint8_t _id;
SangSTBK 0:e16ffa7cb900 160 uint8_t _flags;
SangSTBK 0:e16ffa7cb900 161 if (RF22Router::recvfromAck(_tmpMessage, &tmpMessageLen, &_source, &_dest, &_id, &_flags))
SangSTBK 0:e16ffa7cb900 162 {
SangSTBK 0:e16ffa7cb900 163 MeshMessageHeader* p = (MeshMessageHeader*)&_tmpMessage;
SangSTBK 0:e16ffa7cb900 164
SangSTBK 0:e16ffa7cb900 165 if ( tmpMessageLen >= 1
SangSTBK 0:e16ffa7cb900 166 && p->msgType == RF22_MESH_MESSAGE_TYPE_APPLICATION)
SangSTBK 0:e16ffa7cb900 167 {
SangSTBK 0:e16ffa7cb900 168 MeshApplicationMessage* a = (MeshApplicationMessage*)p;
SangSTBK 0:e16ffa7cb900 169 // Handle application layer messages, presumably for our caller
SangSTBK 0:e16ffa7cb900 170 if (source) *source = _source;
SangSTBK 0:e16ffa7cb900 171 if (dest) *dest = _dest;
SangSTBK 0:e16ffa7cb900 172 if (id) *id = _id;
SangSTBK 0:e16ffa7cb900 173 if (flags) *flags = _flags;
SangSTBK 0:e16ffa7cb900 174 uint8_t msgLen = tmpMessageLen - sizeof(MeshMessageHeader);
SangSTBK 0:e16ffa7cb900 175 if (*len > msgLen)
SangSTBK 0:e16ffa7cb900 176 *len = msgLen;
SangSTBK 0:e16ffa7cb900 177 memcpy(buf, a->data, *len);
SangSTBK 0:e16ffa7cb900 178
SangSTBK 0:e16ffa7cb900 179 return true;
SangSTBK 0:e16ffa7cb900 180 }
SangSTBK 0:e16ffa7cb900 181 else if ( _dest == RF22_BROADCAST_ADDRESS
SangSTBK 0:e16ffa7cb900 182 && tmpMessageLen > 1
SangSTBK 0:e16ffa7cb900 183 && p->msgType == RF22_MESH_MESSAGE_TYPE_ROUTE_DISCOVERY_REQUEST)
SangSTBK 0:e16ffa7cb900 184 {
SangSTBK 0:e16ffa7cb900 185 MeshRouteDiscoveryMessage* d = (MeshRouteDiscoveryMessage*)p;
SangSTBK 0:e16ffa7cb900 186 // Handle Route discovery requests
SangSTBK 0:e16ffa7cb900 187 // Message is an array of node addresses the route request has already passed through
SangSTBK 0:e16ffa7cb900 188 // If it originally came from us, ignore it
SangSTBK 0:e16ffa7cb900 189 if (_source == _thisAddress)
SangSTBK 0:e16ffa7cb900 190 return false;
SangSTBK 0:e16ffa7cb900 191
SangSTBK 0:e16ffa7cb900 192 uint8_t numRoutes = tmpMessageLen - sizeof(MeshMessageHeader) - 2;
SangSTBK 0:e16ffa7cb900 193 uint8_t i;
SangSTBK 0:e16ffa7cb900 194 // Are we already mentioned?
SangSTBK 0:e16ffa7cb900 195 for (i = 0; i < numRoutes; i++)
SangSTBK 0:e16ffa7cb900 196 if (d->route[i] == _thisAddress)
SangSTBK 0:e16ffa7cb900 197 return false; // Already been through us. Discard
SangSTBK 0:e16ffa7cb900 198
SangSTBK 0:e16ffa7cb900 199 // Hasnt been past us yet, record routes back to the earlier nodes
SangSTBK 0:e16ffa7cb900 200 addRouteTo(_source, headerFrom()); // The originator
SangSTBK 0:e16ffa7cb900 201 for (i = 0; i < numRoutes; i++)
SangSTBK 0:e16ffa7cb900 202 addRouteTo(d->route[i], headerFrom());
SangSTBK 0:e16ffa7cb900 203 if (isPhysicalAddress(&d->dest, d->destlen))
SangSTBK 0:e16ffa7cb900 204 {
SangSTBK 0:e16ffa7cb900 205 // This route discovery is for us. Unicast the whole route back to the originator
SangSTBK 0:e16ffa7cb900 206 // as a RF22_MESH_MESSAGE_TYPE_ROUTE_DISCOVERY_RESPONSE
SangSTBK 0:e16ffa7cb900 207 // We are certain to have a route there, becuase we just got it
SangSTBK 0:e16ffa7cb900 208 d->header.msgType = RF22_MESH_MESSAGE_TYPE_ROUTE_DISCOVERY_RESPONSE;
SangSTBK 0:e16ffa7cb900 209 RF22Router::sendtoWait((uint8_t*)d, tmpMessageLen, _source);
SangSTBK 0:e16ffa7cb900 210 }
SangSTBK 0:e16ffa7cb900 211 else if (i < _max_hops)
SangSTBK 0:e16ffa7cb900 212 {
SangSTBK 0:e16ffa7cb900 213 // Its for someone else, rebroadcast it, after adding ourselves to the list
SangSTBK 0:e16ffa7cb900 214 d->route[numRoutes] = _thisAddress;
SangSTBK 0:e16ffa7cb900 215 tmpMessageLen++;
SangSTBK 0:e16ffa7cb900 216 // Have to impersonate the source
SangSTBK 0:e16ffa7cb900 217 // REVISIT: if this fails what can we do?
SangSTBK 0:e16ffa7cb900 218 RF22Router::sendtoWait(_tmpMessage, tmpMessageLen, RF22_BROADCAST_ADDRESS, _source);
SangSTBK 0:e16ffa7cb900 219 }
SangSTBK 0:e16ffa7cb900 220 }
SangSTBK 0:e16ffa7cb900 221 }
SangSTBK 0:e16ffa7cb900 222 return false;
SangSTBK 0:e16ffa7cb900 223 }
SangSTBK 0:e16ffa7cb900 224
SangSTBK 0:e16ffa7cb900 225 ////////////////////////////////////////////////////////////////////
SangSTBK 0:e16ffa7cb900 226 boolean RF22Mesh::recvfromAckTimeout(uint8_t* buf, uint8_t* len, uint16_t timeout, uint8_t* from, uint8_t* to, uint8_t* id, uint8_t* flags)
SangSTBK 0:e16ffa7cb900 227 {
SangSTBK 0:e16ffa7cb900 228 Timer t;
SangSTBK 0:e16ffa7cb900 229
SangSTBK 0:e16ffa7cb900 230 t.start();
SangSTBK 0:e16ffa7cb900 231 unsigned long endtime = t.read_ms() + timeout;
SangSTBK 0:e16ffa7cb900 232 while (t.read_ms() < endtime)
SangSTBK 0:e16ffa7cb900 233 {
SangSTBK 0:e16ffa7cb900 234 if (recvfromAck(buf, len, from, to, id, flags))
SangSTBK 0:e16ffa7cb900 235 return true;
SangSTBK 0:e16ffa7cb900 236 }
SangSTBK 0:e16ffa7cb900 237 return false;
SangSTBK 0:e16ffa7cb900 238 }
SangSTBK 0:e16ffa7cb900 239
SangSTBK 0:e16ffa7cb900 240
SangSTBK 0:e16ffa7cb900 241