Skip to content

Commit

Permalink
Improve address requests, docs update
Browse files Browse the repository at this point in the history
- getAddress() now returns -1 if failed instead of 0
- Remove sending network address from initial address request & remove
address response struct - shortens request by 2 bytes
- Minor clean up to dhcp function
  • Loading branch information
TMRh20 committed Nov 6, 2015
1 parent 7d0548c commit f7682e3
Show file tree
Hide file tree
Showing 3 changed files with 80 additions and 80 deletions.
94 changes: 39 additions & 55 deletions RF24Mesh.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -128,7 +128,7 @@ bool RF24Mesh::checkConnection(){

/*****************************************************/

uint16_t RF24Mesh::getAddress(uint8_t nodeID){
int16_t RF24Mesh::getAddress(uint8_t nodeID){

//#if defined (ARDUINO_SAM_DUE) || defined (__linux)
#if !defined RF24_TINY && !defined(MESH_NOMASTER)
Expand All @@ -140,23 +140,24 @@ uint16_t RF24Mesh::getAddress(uint8_t nodeID){
return address;
}
}
return 0;
return -1;
}
#endif
if(mesh_address == MESH_DEFAULT_ADDRESS){ return 0; }
if(mesh_address == MESH_DEFAULT_ADDRESS){ return -1; }
if(!nodeID){return 0;}
RF24NetworkHeader header( 00, MESH_ADDR_LOOKUP );
if(network.write(header,&nodeID,sizeof(nodeID)+1) ){
uint32_t timer=millis(), timeout = 500;
while(network.update() != MESH_ADDR_LOOKUP){
if(millis()-timer > timeout){ return 0; }
if(millis()-timer > timeout){ return -1; }
}
}
uint16_t address;
memcpy(&address,network.frame_buffer+sizeof(RF24NetworkHeader),sizeof(address));
return address;
}

int RF24Mesh::getNodeID(uint16_t address){
int16_t RF24Mesh::getNodeID(uint16_t address){

if(address == MESH_BLANK_ID){
return _nodeID;
Expand Down Expand Up @@ -237,12 +238,7 @@ bool RF24Mesh::requestAddress(uint8_t level){
uint32_t timr = millis();
uint16_t *contactNode = 0;

struct addrResponseStruct{
uint16_t requester;
uint16_t new_address;
}addrResponse;

while(1){
while(1){
bool goodSignal = radio.testRPD();
if(network.update() == NETWORK_POLL){
contactNode = (uint16_t*)(&network.frame_buffer);
Expand Down Expand Up @@ -288,9 +284,8 @@ bool RF24Mesh::requestAddress(uint8_t level){
header.reserved = getNodeID();
header.to_node = *contactNode;

uint16_t addr = MESH_DEFAULT_ADDRESS;
// Do a direct write (no ack) to the contact node. Include the nodeId and address.
network.write(header,&addr,sizeof(addrResponse),*contactNode);
network.write(header,0,0,*contactNode);
#ifdef MESH_DEBUG_SERIAL
Serial.print( millis() ); Serial.println(F(" MSH: Request address "));
#elif defined MESH_DEBUG_PRINTF
Expand All @@ -315,40 +310,39 @@ bool RF24Mesh::requestAddress(uint8_t level){
#endif
uint8_t registerAddrCount = 0;

memcpy(&addrResponse,network.frame_buffer+sizeof(RF24NetworkHeader),sizeof(addrResponse));
uint16_t newAddress=0;
//memcpy(&addrResponse,network.frame_buffer+sizeof(RF24NetworkHeader),sizeof(addrResponse));
memcpy(&newAddress,network.frame_buffer+sizeof(RF24NetworkHeader),sizeof(newAddress));

if(!addrResponse.new_address || network.frame_buffer[7] != getNodeID() ){
if(!newAddress || network.frame_buffer[7] != getNodeID() ){
#ifdef MESH_DEBUG_SERIAL
Serial.print(millis()); Serial.println(F(" MSH: Response discarded, wrong node"));
#elif defined MESH_DEBUG_PRINTF
printf("%u Response discarded, wrong node 0%o from node 0%o sending node 0%o\n",millis(),addrResponse.new_address,header.from_node,addrResponse.requester);
printf("%u Response discarded, wrong node 0%o from node 0%o sending node 0%o\n",millis(),newAddress,header.from_node,MESH_DEFAULT_ADDRESS);
#endif
return 0;
}
#ifdef MESH_DEBUG_SERIAL
Serial.print( millis() );Serial.print(F(" Set address: "));
newAddr = addrResponse.new_address;
newAddr = newAddress;
while(newAddr){
addrs[count] = (newAddr & mask)+48; //get the individual Octal numbers, specified in chunks of 3 bits, convert to ASCII by adding 48
newAddr >>= 3;
count--;
}
Serial.println(addrs);
#elif defined (MESH_DEBUG_PRINTF)
printf("Set address 0%o rcvd 0%o\n",mesh_address,addrResponse.new_address);
printf("Set address 0%o rcvd 0%o\n",mesh_address,newAddress);
#endif
mesh_address = addrResponse.new_address;
//radio.begin();
mesh_address = newAddress;

radio.stopListening();
delay(10);
network.begin(mesh_address);
header.to_node = 00;
header.type = MESH_ADDR_CONFIRM;
//network.write(header,0,0);
//delay(55);

while( !network.write(header,0,0) ){
//delay(55);
//printf("Retry register address...\n");
if(registerAddrCount++ >= 6 ){ return 0; }
}

Expand Down Expand Up @@ -452,39 +446,30 @@ void RF24Mesh::DHCP(){
RF24NetworkHeader header;
memcpy(&header,network.frame_buffer,sizeof(RF24NetworkHeader));

struct addrResponseStruct{
uint16_t requester;
uint16_t new_address;
} addrResponse;

uint16_t newAddress;

// Get the unique id of the requester
uint8_t from_id = header.reserved;
if(!from_id){
#ifdef MESH_DEBUG_PRINTF
printf("MSH: Invalid id 0 rcvd\n");
#endif
//network.read(header,0,0);
return;
}

//network.read(header,&addrResponse,sizeof(addrResponse));
memcpy(&addrResponse,network.frame_buffer+sizeof(RF24NetworkHeader),sizeof(addrResponse));

// Get the address of the sender (initial, or intermediary)
uint16_t fwd_by = header.from_node;
uint16_t fwd_by = 0;
uint8_t shiftVal = 0;

if(header.from_node == addrResponse.requester || header.from_node == MESH_DEFAULT_ADDRESS){ //Addresses 01-05
fwd_by = 0; // No forwarding address
}else{ //Addresses 01111-05555

if( header.from_node != MESH_DEFAULT_ADDRESS){
fwd_by = header.from_node;
uint16_t m = fwd_by;
uint8_t count = 0;

while(m){ //Octal addresses convert nicely to binary in threes. Address 03 = B011 Address 033 = B011011
m >>= 3; //Find out how many digits are in the octal address
count++;
}
shiftVal = count*3; //Now we know how many bits to shift when adding a child node 1-5 (B001 to B101) to any address
}
shiftVal = count*3; //Now we know how many bits to shift when adding a child node 1-5 (B001 to B101) to any address
}

#ifdef MESH_DEBUG_PRINTF
Expand All @@ -494,8 +479,8 @@ void RF24Mesh::DHCP(){
for(int i=MESH_MAX_CHILDREN; i> 0; i--){ // For each of the possible addresses (5 max)

bool found = 0;
addrResponse.new_address = fwd_by | (i << shiftVal);
if(!addrResponse.new_address ){ /*printf("dumped 0%o\n",addrResponse.new_address);*/ continue; }
newAddress = fwd_by | (i << shiftVal);
if(!newAddress ){ /*printf("dumped 0%o\n",newAddress);*/ continue; }

for(uint8_t i=0; i < addrListTop; i++){
#if defined (MESH_DEBUG_MINIMAL)
Expand All @@ -513,30 +498,29 @@ void RF24Mesh::DHCP(){
printf("ID: %d ADDR: 0%o\n", addrList[i].nodeID,addrList[i].address);
#endif
#endif
if( (addrList[i].address == addrResponse.new_address && addrList[i].nodeID != from_id ) || addrResponse.new_address == MESH_DEFAULT_ADDRESS){
if( (addrList[i].address == newAddress && addrList[i].nodeID != from_id ) || newAddress == MESH_DEFAULT_ADDRESS){
found = 1;
break;
}
}

if(!found){

header.type = NETWORK_ADDR_RESPONSE;
header.to_node = header.from_node;
//printf("Send resp %d\n",sizeof(addrResponse));
//This is a routed request to 00
if(header.from_node != addrResponse.requester){ //Is NOT node 01 to 05
if(header.from_node != MESH_DEFAULT_ADDRESS){ //Is NOT node 01 to 05
delay(2);
if( network.write(header,&addrResponse,sizeof(addrResponse)) ){
//addrMap[from_id] = addrResponse.new_address;
if( network.write(header,&newAddress,sizeof(newAddress)) ){
//addrMap[from_id] = newAddress;
}else{
network.write(header,&addrResponse,sizeof(addrResponse));
network.write(header,&newAddress,sizeof(newAddress));
}
}else{
delay(2);
network.write(header,&addrResponse,sizeof(addrResponse),header.to_node);
network.write(header,&newAddress,sizeof(newAddress),header.to_node);

//addrMap[from_id] = addrResponse.new_address;
//addrMap[from_id] = newAddress;
}
uint32_t timer=millis();
while(network.update() != MESH_ADDR_CONFIRM){
Expand All @@ -550,7 +534,7 @@ void RF24Mesh::DHCP(){
found = 0;
for(uint8_t i=0; i < addrListTop; i++){
if( addrList[i].nodeID == from_id ){
addrList[i].address = addrResponse.new_address;
addrList[i].address = newAddress;
found = 1;
#if defined (__linux) && !defined(__ARDUINO_X86__)
if(millis()-lastFileSave > 300){
Expand All @@ -563,7 +547,7 @@ void RF24Mesh::DHCP(){
}
if(!found){
addrList[addrListTop].nodeID = from_id;
addrList[addrListTop].address = addrResponse.new_address;
addrList[addrListTop].address = newAddress;
#if defined (__linux) && !defined(__ARDUINO_X86__)
if(millis()-lastFileSave > 300){
lastFileSave = millis();
Expand All @@ -577,7 +561,7 @@ void RF24Mesh::DHCP(){


#ifdef MESH_DEBUG_PRINTF
printf("Sent to 0%o phys: 0%o new: 0%o id: %d\n", header.to_node,addrResponse.requester,addrResponse.new_address,header.reserved);
printf("Sent to 0%o phys: 0%o new: 0%o id: %d\n", header.to_node,MESH_DEFAULT_ADDRESS,newAddress,header.reserved);
#endif

break;
Expand Down
64 changes: 40 additions & 24 deletions RF24Mesh.h
Original file line number Diff line number Diff line change
Expand Up @@ -87,7 +87,11 @@ class RF24Mesh
*
* @code mesh.begin(); @endcode
* This may take a few moments to complete.
* The radio channel and data-rate can be specified optionally as well
*
* The following parameters are optional:
* @param channel The radio channel (1-127) default:97
* @param data_rate The data rate (RF24_250KBPS,RF24_1MBPS,RF24_2MBPS) default:RF24_1MBPS
* @param timeout How long to attempt address renewal in milliseconds default:60000
*/
bool begin(uint8_t channel = MESH_DEFAULT_CHANNEL, rf24_datarate_e data_rate = RF24_1MBPS, uint32_t timeout=MESH_RENEWAL_TIMEOUT );

Expand All @@ -98,20 +102,26 @@ class RF24Mesh
uint8_t update();

/**
* Automatically construct a header and send a payload to the 'master' node.
* Automatically construct a header and send a payload
* Very similar to the standard network.write() function, which can be used directly.
* @param data Send any type of data of any length (Very large payloads will be more error prone)
*
* @note Including the nodeID parameter will result in an automatic address lookup being performed.
* @note Message types 1-64 (decimal) will NOT be acknowledged by the network, types 65-127 will be. Use as appropriate to manage traffic:
* if expecting a response, no ack is needed.
*
* @param data Send any type of data of any length (Max length determined by RF24Network layer)
* @param msg_type The user-defined (1-127) message header_type to send. Used to distinguish between different types of data being transmitted.
* @param size The size of the data being sent
* @param nodeID Optional: The nodeID of the recipient if not sending to master
* @param nodeID **Optional**: The nodeID of the recipient if not sending to master
* @return True if success, False if failed
*/
bool write(const void* data, uint8_t msg_type, size_t size, uint8_t nodeID=0);

/**
* Set a unique nodeID for this node. This value, if changed, will be written to EEPROM on AVR so it will remain set, even after loss of power or code changes.
* Currently not saved on Due or RPi, so should be manually configured.
* This can generally be called before mesh.begin(), or set via serial connection or other methods if configuring a large number of nodes...
* Set a unique nodeID for this node. This value is stored in program memory, so is saved after loss of power.
*
* This should be called before mesh.begin(), or set via serial connection or other methods if configuring a large number of nodes...
* @note If using RF24Gateway and/or RF24Ethernet, nodeIDs 0 & 1 are used by the master node.
* @param nodeID Can be any unique value ranging from 1 to 255.
*/
void setNodeID(uint8_t nodeID);
Expand All @@ -132,14 +142,14 @@ class RF24Mesh

/**
* Convert an RF24Network address into a nodeId.
* When called on any node but the master node, this will result in a lookup request being sent to the master node
*
* @param address If no address is provided, returns the local nodeID, otherwise a lookup request is sent to the master node
* @return Returns the unique identifier (1-255) or -1 if not found.
*/
int getNodeID(uint16_t address=MESH_BLANK_ID);
int16_t getNodeID(uint16_t address=MESH_BLANK_ID);

/**
* Tests connectivity of this node to the mesh.
* @note If this function fails, the radio will be put into standby mode, and will not receive payloads until the address is renewed.
* @return Return 1 if connected, 0 if mesh not responding after up to 1 second
*/

Expand All @@ -148,13 +158,19 @@ class RF24Mesh
/**
* Reconnect to the mesh and renew the current RF24Network address. Used to re-establish a connection to the mesh if physical location etc. has changed, or
* a routing node goes down.
* @note Currently blocks until a connection is established and an address is received.
* @note Currently times out after 1 minute if address renewal fails. Network writes should not be attempted if address renewal fails.
*
* @note If all nodes are set to verify connectivity/reconnect at a specified period, leaving the master offline for this length of time should result
* in complete network/mesh reconvergence.
* @param timeout How long to attempt address renewal in milliseconds default:60000
* @return Returns the newly assigned RF24Network address
*/
uint16_t renewAddress(uint32_t timeout=MESH_RENEWAL_TIMEOUT);

/**
* Releases the currently assigned address lease. Useful for nodes that will be sleeping etc.
* @note Nodes should ensure that addresses are releases successfully prior to renewal.
* @return Returns 1 if successfully released, 0 if not
*/
bool releaseAddress();
Expand All @@ -167,14 +183,13 @@ class RF24Mesh

/**
* Convert a nodeID into an RF24Network address
* @note If printing or displaying the address, it needs to be converted to octal format.
* @note If printing or displaying the address, it needs to be converted to octal format: Serial.println(address,OCT);
*
* When called on any node but the master node, this will result in a name lookup request being sent to the master node, and a response
* returned containing the address corresponding to the included nodeID.
* Results in a lookup request being sent to the master node.
* @param nodeID - The unique identifier (1-255) of the node
* @return Returns the RF24Network address of the node or 0 if not found or lookup failed.
* @return Returns the RF24Network address of the node or -1 if not found or lookup failed.
*/
uint16_t getAddress(uint8_t nodeID);
int16_t getAddress(uint8_t nodeID);

/**
* Write to a specific node by RF24Network address.
Expand All @@ -188,9 +203,9 @@ class RF24Mesh
void setChannel(uint8_t _channel);

/**
* Set a static nodeID/RF24Network Address pair.
* Mainly for use with nodes not using RF24Mesh, but RF24Network only.
* Set a static address assignment, that will not be updated or re-assigned.
* Set a static nodeID/RF24Network Address pair on the master node.
* Mainly for use with nodes not using RF24Mesh at all, but RF24Network only.
*
* @code
* Set a static address for node 02, with nodeID 23, since it will just be a static routing node for example
* running on an ATTiny chip.
Expand Down Expand Up @@ -356,7 +371,7 @@ class RF24Mesh
* @li Try it out!
* @li <a href="Setup-Config.html">Setup and Configuration</a>
* @li <a href="classRF24Mesh.html">RF24Mesh Class Documentation</a>
* @li <a href="http://tmrh20.github.io/RF24Network_Dev/">RF24 Network -DEV- Class Documentation</a>
* @li <a href="http://tmrh20.github.io/RF24Network/">RF24 Network Class Documentation</a>
* @li <a href="https://tmrh20.github.io">Documentation and Downloads</a>
* @li <a href="https://github.com/TMRh20/RF24Mesh">Source Code</a>
*
Expand All @@ -375,15 +390,15 @@ class RF24Mesh
*
* <b>Software Requirements:</b>
* @li <a href="https://github.com/TMRh20/RF24/archive/master.zip">RF24 Core Radio Library</a>
* @li <a href="https://github.com/TMRh20/RF24Network/archive/Development.zip">RF24Network Development Library</a>
* @li <a href="https://github.com/TMRh20/RF24Network/archive/master.zip">RF24Network Library</a>
* @li <a href="https://github.com/TMRh20/RF24Mesh/archive/master.zip">RF24Mesh - Dynamic Mesh Library</a>
*
* @section Installation Installation
* 1. If not installed, download and install the RF24, RF24Network DEV, and RF24Mesh libraries per the above links <br>
* 1. If not installed, use the Arduino Library Manager, or download and install the RF24, RF24Network, and RF24Mesh libraries per the above links <br>
* <br>
* 2. Configure and test the hardware using examples from RF24 and RF24Network prior to attempting to use RF24Mesh <br>
* a: <b>In Arduino IDE:</b> File > Examples > RF24 > GettingStarted <br>
* b: <b>RPi:</b> Follow the Quick-Start instructions on <a href="https://github.com/TMRh20/RF24Network/tree/Development/RPi">GitHub</a> <br>
* b: <b>RPi:</b> Follow the RF24 instructions on <a href="http://tmrh20.github.io/RF24/RPi.html">GitHub</a> <br>
* <br>
* 3. Once testing is complete: <br>
* a: <b>Arduino IDE:</b> File > Examples > RF24Mesh > RF24Mesh_Example <br>
Expand Down Expand Up @@ -426,7 +441,8 @@ class RF24Mesh
* One of the recently introduced features is the ability to transmit payloads without the network returning a network-ack response. If solely using this method
* of transmission, the node should also be configured to verify its connection via mesh.checkConnection(); periodically, to ensure connectivity.
*
* Beyond requesting and releasing addresses, usage is as outlined in the RF24Network Development documentation at http://tmrh20.github.io
* Beyond requesting and releasing addresses, usage is outlined in the class documentation and further information regarding RF24Network is available at
* http://tmrh20.github.io/RF24Network
*
*
*
Expand Down
Loading

0 comments on commit f7682e3

Please sign in to comment.