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.
Fork of RF22 by
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
Generated on Wed Jul 13 2022 22:24:22 by
