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
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 Tue Jul 12 2022 12:34:31 by 1.7.2