diff --git a/.github/workflows/doxygen.yml b/.github/workflows/doxygen.yml index dee16aa..da74cd3 100644 --- a/.github/workflows/doxygen.yml +++ b/.github/workflows/doxygen.yml @@ -28,7 +28,6 @@ jobs: uses: actions/checkout@v2 - name: overwrite doxygen tags run: | - mkdir docs touch doxygenAction echo "PROJECT_NUMBER = ${{ steps.latest_ver.outputs.release }}" >> doxygenAction echo "@INCLUDE = doxygenAction" >> Doxyfile diff --git a/.gitignore b/.gitignore index d8bc424..7e95313 100644 --- a/.gitignore +++ b/.gitignore @@ -6,4 +6,5 @@ *.so.1 # ignore docs folder -docs/ \ No newline at end of file +docs/html/ +docs/xml/ \ No newline at end of file diff --git a/CMakeLists.txt b/CMakeLists.txt new file mode 100644 index 0000000..50109cb --- /dev/null +++ b/CMakeLists.txt @@ -0,0 +1,9 @@ +# Check if we are building a pico-sdk based project +# (or more exactly: if we just got included in a pico-sdk based project) +if (PICO_SDK_PATH) + # If so, load the relevant CMakeLists-file but don't do anything else + include(${CMAKE_CURRENT_LIST_DIR}/usePicoSDK.cmake) + return() +endif() + +## TODO: Non-PicoSDK builds diff --git a/Doxyfile b/Doxyfile index 0432cba..c352cd0 100644 --- a/Doxyfile +++ b/Doxyfile @@ -824,7 +824,8 @@ WARN_LOGFILE = # spaces. See also FILE_PATTERNS and EXTENSION_MAPPING # Note: If this tag is empty the current directory is searched. -INPUT = ./ +INPUT = ./ \ + ./docs/ # This tag can be used to specify the character encoding of the source files # that doxygen parses. Internally doxygen uses the UTF-8 encoding. Doxygen uses @@ -924,7 +925,7 @@ EXCLUDE_SYMLINKS = NO # Note that the wildcards are matched against the file with absolute path, so to # exclude all test directories for example use the pattern */test/* -EXCLUDE_PATTERNS = readme* +EXCLUDE_PATTERNS = *README* # The EXCLUDE_SYMBOLS tag can be used to specify one or more symbol names # (namespaces, classes, functions, etc.) that should be excluded from the @@ -1018,7 +1019,7 @@ FILTER_SOURCE_PATTERNS = # (index.html). This can be useful if you have a project on for instance GitHub # and want to reuse the introduction page also for the doxygen output. -USE_MDFILE_AS_MAINPAGE = +USE_MDFILE_AS_MAINPAGE = ./docs/main_page.md #--------------------------------------------------------------------------- # Configuration options related to source browsing @@ -2202,7 +2203,7 @@ INCLUDE_FILE_PATTERNS = # recursively expanded use the := operator instead of the = operator. # This tag requires that the tag ENABLE_PREPROCESSING is set to YES. -PREDEFINED = +PREDEFINED = DOXYGEN_FORCED # If the MACRO_EXPANSION and EXPAND_ONLY_PREDEF tags are set to YES then this # tag can be used to specify a list of macro names that should be expanded. The @@ -2578,4 +2579,3 @@ GENERATE_LEGEND = YES # This tag requires that the tag HAVE_DOT is set to YES. DOT_CLEANUP = YES - diff --git a/RF24Mesh.cpp b/RF24Mesh.cpp old mode 100755 new mode 100644 index 2b1a537..9e62f62 --- a/RF24Mesh.cpp +++ b/RF24Mesh.cpp @@ -1,6 +1,8 @@ - - - +/** + * @file RF24Mesh.cpp + * + * Class definitions for RF24Mesh + */ #include "RF24Mesh.h" #include "RF24Mesh_config.h" @@ -8,81 +10,83 @@ #include #endif -RF24Mesh::RF24Mesh( RF24& _radio,RF24Network& _network ): radio(_radio),network(_network){ setCallback(NULL); } +RF24Mesh::RF24Mesh(RF24& _radio, RF24Network& _network): radio(_radio), network(_network) { setCallback(NULL); } /*****************************************************/ -bool RF24Mesh::begin(uint8_t channel, rf24_datarate_e data_rate, uint32_t timeout){ - //delay(1); // Found problems w/SPIDEV & ncurses. Without this, getch() returns a stream of garbage - if(meshStarted){ - radio.stopListening(); - } - meshStarted = true; - if(!radio.begin()) - return 0; - radio.setChannel(channel); - radio.setDataRate(data_rate); - network.returnSysMsgs = true; - - if(getNodeID() > 0){ //Not master node - if(!renewAddress(timeout)){ - return false; +bool RF24Mesh::begin(uint8_t channel, rf24_datarate_e data_rate, uint32_t timeout) +{ + //delay(1); // Found problems w/SPIDEV & ncurses. Without this, getch() returns a stream of garbage + if (meshStarted) { + radio.stopListening(); + } + meshStarted = true; + if(!radio.begin()) + return 0; + radio.setChannel(channel); + radio.setDataRate(data_rate); + network.returnSysMsgs = true; + + if (getNodeID() > 0) { //Not master node + if (!renewAddress(timeout)) { + return false; + } } - }else{ - #if !defined(MESH_NOMASTER) - if( !addrMemAllocated ){ - addrMemAllocated = true; - addrList = (addrListStruct*)malloc( (MESH_MEM_ALLOC_SIZE * sizeof(addrListStruct)) ); - addrListTop = 0; - loadDHCP(); + else{ + #if !defined(MESH_NOMASTER) + if (!addrMemAllocated) { + addrMemAllocated = true; + addrList = (addrListStruct*)malloc((MESH_MEM_ALLOC_SIZE * sizeof(addrListStruct))); + addrListTop = 0; + loadDHCP(); + } + #endif + mesh_address = 0; + network.begin(mesh_address); } - #endif - mesh_address = 0; - network.begin(mesh_address); - } - - return true; + + return true; } /*****************************************************/ -uint8_t RF24Mesh::update(){ - +uint8_t RF24Mesh::update() +{ uint8_t type = network.update(); - if(mesh_address == MESH_DEFAULT_ADDRESS){ return type; } - + if (mesh_address == MESH_DEFAULT_ADDRESS) { return type; } + #if !defined(MESH_NOMASTER) - if(type == NETWORK_REQ_ADDRESS){ - doDHCP = 1; + if (type == NETWORK_REQ_ADDRESS) { + doDHCP = 1; } - if(!getNodeID()){ - if( (type == MESH_ADDR_LOOKUP || type == MESH_ID_LOOKUP)) { - RF24NetworkHeader *header = (RF24NetworkHeader*)(&network.frame_buffer); - header->to_node = header->from_node; - - int16_t returnAddr = 0; - if(type==MESH_ADDR_LOOKUP){ - returnAddr = getAddress(network.frame_buffer[sizeof(RF24NetworkHeader)]); - network.write(*header,&returnAddr,sizeof(returnAddr)); - }else{ - int16_t addr = 0; - memcpy(&addr,&network.frame_buffer[sizeof(RF24NetworkHeader)],sizeof(addr)); - returnAddr = getNodeID(addr); - network.write(*header,&returnAddr,sizeof(returnAddr)); - } + if (!getNodeID()) { + if ((type == MESH_ADDR_LOOKUP || type == MESH_ID_LOOKUP)) { + RF24NetworkHeader *header = (RF24NetworkHeader*)(&network.frame_buffer); + header->to_node = header->from_node; - }else - if(type == MESH_ADDR_RELEASE ){ - uint16_t *fromAddr = (uint16_t*)network.frame_buffer; - for(uint8_t i=0; i lookupTimeout || toNode == -2){ - return 0; +bool RF24Mesh::write(const void* data, uint8_t msg_type, size_t size, uint8_t nodeID) +{ + if (mesh_address == MESH_DEFAULT_ADDRESS) { return 0; } + + int16_t toNode = 0; + uint32_t lookupTimeout = millis() + MESH_WRITE_TIMEOUT; + uint32_t retryDelay = 5; + + if (nodeID) { + while( (toNode=getAddress(nodeID)) < 0 ) { + if (millis() > lookupTimeout || toNode == -2) { + return 0; + } + retryDelay+=10; + delay(retryDelay); } - retryDelay+=10; - delay(retryDelay); } - } - return write(toNode,data,msg_type,size); + return write(toNode, data, msg_type, size); } /*****************************************************/ -void RF24Mesh::setChannel(uint8_t _channel){ - +void RF24Mesh::setChannel(uint8_t _channel) +{ radio.stopListening(); radio.setChannel(_channel); radio.startListening(); @@ -129,502 +135,519 @@ void RF24Mesh::setChannel(uint8_t _channel){ /*****************************************************/ -void RF24Mesh::setChild(bool allow){ - - network.networkFlags = allow ? network.networkFlags & ~FLAG_NO_POLL : network.networkFlags | FLAG_NO_POLL; +void RF24Mesh::setChild(bool allow) +{ + network.networkFlags = allow ? network.networkFlags & ~FLAG_NO_POLL : network.networkFlags | FLAG_NO_POLL; } /*****************************************************/ -bool RF24Mesh::checkConnection(){ - - if(getAddress(_nodeID) < 1){ - if(getAddress(_nodeID) < 1){ - return false; - } +bool RF24Mesh::checkConnection() +{ + if (getAddress(_nodeID) < 1) { + if (getAddress(_nodeID) < 1) { + return false; + } } return true; } /*****************************************************/ -int16_t RF24Mesh::getAddress(uint8_t nodeID){ // Master will return and send 00 address for a nodeID with address 0, -1 if not found - - //if(nodeID == _nodeID){ return mesh_address; } - if(!nodeID){return 0;} - if(mesh_address == MESH_DEFAULT_ADDRESS){ return -2; } - +int16_t RF24Mesh::getAddress(uint8_t nodeID) +{ // Master will return and send 00 address for a nodeID with address 0, -1 if not found + + //if (nodeID == _nodeID) { return mesh_address; } + if (!nodeID) { return 0; } + if (mesh_address == MESH_DEFAULT_ADDRESS) { return -2; } + // Lets say 0 if nodeID 0, -1 if write failed or timed out, -2 if not found in list or address is default, #if !defined(MESH_NOMASTER) - if(!getNodeID()){ //Master Node - for(uint8_t i=0; i MESH_LOOKUP_TIMEOUT){ return -1; } - } - int16_t address = 0; - memcpy(&address,network.frame_buffer+sizeof(RF24NetworkHeader),sizeof(address)); - return address; + + RF24NetworkHeader header(00, MESH_ADDR_LOOKUP); + if (network.write(header, &nodeID, sizeof(nodeID))) { + uint32_t timer = millis(); + while(network.update() != MESH_ADDR_LOOKUP) { + MESH_CALLBACK + if (millis() - timer > MESH_LOOKUP_TIMEOUT) { + return -1; + } + } + int16_t address = 0; + memcpy(&address, network.frame_buffer + sizeof(RF24NetworkHeader), sizeof(address)); + return address; } - return -1; + return -1; } /*****************************************************/ -int16_t RF24Mesh::getNodeID(uint16_t address){ +int16_t RF24Mesh::getNodeID(uint16_t address) +{ + if (address == MESH_BLANK_ID) { return _nodeID; } + if (address == 0) { return 0; } + if (mesh_address == MESH_DEFAULT_ADDRESS) { return -2; } - - if(address == MESH_BLANK_ID){ return _nodeID; } - if(address == 0){ return 0; } - if(mesh_address == MESH_DEFAULT_ADDRESS){ return -2; } - - - #if !defined(MESH_NOMASTER) - if(!mesh_address){ //Master Node - for(uint8_t i=0; i MESH_LOOKUP_TIMEOUT){ return -1; } - } - int16_t ID = 0; - memcpy(&ID,&network.frame_buffer[sizeof(RF24NetworkHeader)],sizeof(ID)); - return ID; + if (network.write(header,&address,sizeof(address)) ) { + uint32_t timer = millis(); + while(network.update() != MESH_ID_LOOKUP) { + MESH_CALLBACK + if (millis() - timer > MESH_LOOKUP_TIMEOUT) { return -1; } + } + int16_t ID = 0; + memcpy(&ID, &network.frame_buffer[sizeof(RF24NetworkHeader)], sizeof(ID)); + return ID; } return -1; } /*****************************************************/ -uint8_t RF24Mesh::getLevel(uint16_t address){ - - uint8_t count = 0; - while(address){ - address >>= 3; - count++; - } - return count; +uint8_t RF24Mesh::getLevel(uint16_t address) +{ + uint8_t count = 0; + while (address) { + address >>= 3; + count++; + } + return count; } /*****************************************************/ -void RF24Mesh::beginDefault(){ - radio.stopListening(); - network.begin(MESH_DEFAULT_ADDRESS); - mesh_address=MESH_DEFAULT_ADDRESS; +void RF24Mesh::beginDefault() +{ + radio.stopListening(); + network.begin(MESH_DEFAULT_ADDRESS); + mesh_address = MESH_DEFAULT_ADDRESS; } /*****************************************************/ -bool RF24Mesh::releaseAddress(){ - - if(mesh_address == MESH_DEFAULT_ADDRESS){ return 0; } +bool RF24Mesh::releaseAddress() +{ + if (mesh_address == MESH_DEFAULT_ADDRESS) { return 0; } - RF24NetworkHeader header(00,MESH_ADDR_RELEASE); - if(network.write(header,0,0)){ - beginDefault(); - return 1; + RF24NetworkHeader header(00,MESH_ADDR_RELEASE); + if (network.write(header,0,0)) { + beginDefault(); + return 1; } - return 0; + return 0; } /*****************************************************/ -uint16_t RF24Mesh::renewAddress(uint32_t timeout){ - - if(radio.available()){ network.update(); } - uint8_t reqCounter = 0; - uint8_t totalReqs = 0; - - beginDefault(); - - uint32_t start = millis(); - while(!requestAddress(reqCounter)){ - if(millis()-start > timeout){ return 0; } - delay(50 + ( (totalReqs+1)*(reqCounter+1)) * 2); - reqCounter++; - reqCounter = reqCounter%4; - totalReqs++; - totalReqs = totalReqs%10; - - } - return mesh_address; +uint16_t RF24Mesh::renewAddress(uint32_t timeout) +{ + if (radio.available()) { network.update(); } + + uint8_t reqCounter = 0; + uint8_t totalReqs = 0; + + beginDefault(); + + uint32_t start = millis(); + while (!requestAddress(reqCounter)) { + if (millis() - start > timeout) { return 0; } + + uint32_t timeoutInternal = 50 + ((totalReqs + 1) * (reqCounter + 1)) * 2; + uint32_t startInternal = millis(); + while (millis() - startInternal < timeoutInternal) { + MESH_CALLBACK + delay(1); + } + reqCounter++; + reqCounter = reqCounter % 4; + totalReqs++; + totalReqs = totalReqs % 10; + } + return mesh_address; } /*****************************************************/ -bool RF24Mesh::requestAddress(uint8_t level){ - - RF24NetworkHeader header( 0100, NETWORK_POLL ); - //Find another radio, starting with level 0 multicast - #if defined (MESH_DEBUG_SERIAL) - Serial.print( millis() ); Serial.println(F(" MSH: Poll ")); - #endif - network.multicast(header,0,0,level); - - uint32_t timr = millis(); +bool RF24Mesh::requestAddress(uint8_t level) +{ + RF24NetworkHeader header( 0100, NETWORK_POLL ); + //Find another radio, starting with level 0 multicast + #if defined (MESH_DEBUG_SERIAL) + Serial.print(millis()); Serial.println(F(" MSH: Poll ")); + #endif + network.multicast(header, 0, 0, level); + + uint32_t timr = millis(); #define MESH_MAXPOLLS 4 uint16_t contactNode[MESH_MAXPOLLS]; - uint8_t pollCount=0; - - while(1){ + uint8_t pollCount = 0; + + while (1) { #if defined (MESH_DEBUG_SERIAL) || defined (MESH_DEBUG_PRINTF) - bool goodSignal = radio.testRPD(); + bool goodSignal = radio.testRPD(); #endif - if(network.update() == NETWORK_POLL){ - - memcpy(&contactNode[pollCount],&network.frame_buffer[0],sizeof(uint16_t)); - if( pollCount > 0 && contactNode[pollCount] != contactNode[pollCount-1] ){ //Drop duplicate polls to help prevent dupliacate requests + + if (network.update() == NETWORK_POLL) { + + memcpy(&contactNode[pollCount], &network.frame_buffer[0], sizeof(uint16_t)); + if (pollCount > 0 && contactNode[pollCount] != contactNode[pollCount - 1]) { //Drop duplicate polls to help prevent dupliacate requests ++pollCount; - }else{ + } + else{ ++pollCount; } - - #if defined (MESH_DEBUG_SERIAL) || defined (MESH_DEBUG_PRINTF) - if(goodSignal){ - // This response was better than -64dBm + + #if defined (MESH_DEBUG_SERIAL) || defined (MESH_DEBUG_PRINTF) + if (goodSignal) { + // This response was better than -64dBm #if defined (MESH_DEBUG_SERIAL) - Serial.print( millis() ); Serial.println(F(" MSH: Poll > -64dbm ")); + Serial.print(millis()); Serial.println(F(" MSH: Poll > -64dbm ")); #elif defined (MESH_DEBUG_PRINTF) - printf( "%u MSH: Poll > -64dbm\n", millis() ); - #endif - }else{ + printf("%u MSH: Poll > -64dbm\n", millis()); + #endif + } + else{ #if defined (MESH_DEBUG_SERIAL) - Serial.print( millis() ); Serial.println(F(" MSH: Poll < -64dbm ")); + Serial.print( millis() ); Serial.println(F(" MSH: Poll < -64dbm ")); #elif defined (MESH_DEBUG_PRINTF) - printf( "%u MSH: Poll < -64dbm\n", millis() ); - #endif + printf( "%u MSH: Poll < -64dbm\n", millis() ); + #endif } - #endif - } - - if(millis() - timr > 55 || pollCount >= MESH_MAXPOLLS ){ - if(!pollCount){ - #if defined (MESH_DEBUG_SERIAL) - Serial.print( millis() ); Serial.print(F(" MSH: No poll from level "));Serial.println(level); - #elif defined (MESH_DEBUG_PRINTF) - printf( "%u MSH: No poll from level %d\n", millis(), level); - #endif - return 0; - }else{ - - #if defined (MESH_DEBUG_SERIAL) - Serial.print( millis() ); Serial.println(F(" MSH: Poll OK ")); - #elif defined (MESH_DEBUG_PRINTF) - printf( "%u MSH: Poll OK\n", millis() ); - #endif - break; - } - } + #endif // defined (MESH_DEBUG_SERIAL) || defined (MESH_DEBUG_PRINTF) + } // end if + + if (millis() - timr > 55 || pollCount >= MESH_MAXPOLLS ) { + if (!pollCount) { + #if defined (MESH_DEBUG_SERIAL) + Serial.print( millis() ); Serial.print(F(" MSH: No poll from level ")); Serial.println(level); + #elif defined (MESH_DEBUG_PRINTF) + printf( "%u MSH: No poll from level %d\n", millis(), level); + #endif + return 0; + } + else { + #if defined (MESH_DEBUG_SERIAL) + Serial.print(millis()); Serial.println(F(" MSH: Poll OK ")); + #elif defined (MESH_DEBUG_PRINTF) + printf("%u MSH: Poll OK\n", millis()); + #endif + break; + } + } MESH_CALLBACK - } - - + } // end while + + #ifdef MESH_DEBUG_SERIAL - Serial.print( millis() ); Serial.print(F(" MSH: Got poll from level ")); Serial.print(level); - Serial.print(F(" count "));Serial.print(pollCount); - Serial.print(F(" node "));Serial.println(contactNode[pollCount-1],OCT); // #ML# - #elif defined MESH_DEBUG_PRINTF - printf("%u MSH: Got poll from level %d count %d\n",millis(),level,pollCount); - #endif - - bool gotResponse = 0; - for(uint8_t i=0; i 0 && addrListTop % MESH_MEM_ALLOC_SIZE == 0){ - addrList = (addrListStruct*)realloc(addrList,(addrListTop + MESH_MEM_ALLOC_SIZE) * sizeof(addrListStruct)); - } - addrList[addrListTop].address = address; - addrList[addrListTop++].nodeID = nodeID; //Set the value AND increment Top without another line of code - #if defined (__linux) && !defined(__ARDUINO_X86__) + + if (addrListTop > 0 && addrListTop % MESH_MEM_ALLOC_SIZE == 0) { + addrList = (addrListStruct*)realloc(addrList, (addrListTop + MESH_MEM_ALLOC_SIZE) * sizeof(addrListStruct)); + } + addrList[addrListTop].address = address; + addrList[addrListTop++].nodeID = nodeID; //Set the value AND increment Top without another line of code + #if defined (__linux) && !defined(__ARDUINO_X86__) saveDHCP(); - #endif + #endif } /*****************************************************/ -void RF24Mesh::loadDHCP(){ - -#if defined (__linux) && !defined(__ARDUINO_X86__) - std::ifstream infile ("dhcplist.txt",std::ifstream::binary); - if(!infile){ return; } - - infile.seekg(0,infile.end); - int length = infile.tellg(); - infile.seekg(0,infile.beg); +void RF24Mesh::loadDHCP() { + + #if defined (__linux) && !defined(__ARDUINO_X86__) + std::ifstream infile ("dhcplist.txt",std::ifstream::binary); + if (!infile) { return; } + + infile.seekg(0,infile.end); + int length = infile.tellg(); + infile.seekg(0,infile.beg); addrListStruct tmpNode; - - for(uint8_t i=0; i < (length/sizeof(addrListStruct)); i++){ - infile.read( (char*)&tmpNode,sizeof(addrListStruct)); - setAddress(tmpNode.nodeID,tmpNode.address); - } - infile.close(); -#endif + + for (uint8_t i = 0; i < (length / sizeof(addrListStruct)); i++) { + infile.read((char*)&tmpNode, sizeof(addrListStruct)); + setAddress(tmpNode.nodeID, tmpNode.address); + } + infile.close(); + #endif } /*****************************************************/ -void RF24Mesh::saveDHCP(){ - #if defined (__linux) && !defined(__ARDUINO_X86__) - std::ofstream outfile ("dhcplist.txt",std::ofstream::binary | std::ofstream::trunc); +void RF24Mesh::saveDHCP() { + #if defined (__linux) && !defined(__ARDUINO_X86__) + std::ofstream outfile("dhcplist.txt", std::ofstream::binary | std::ofstream::trunc); - for(int i=0; i< addrListTop; i++){ - outfile.write( (char*)&addrList[i],sizeof(addrListStruct)); + for (int i=0; i< addrListTop; i++) { + outfile.write( (char*)&addrList[i],sizeof(addrListStruct)); } outfile.close(); - - #endif// __linux not X86 + #endif // __linux & not X86 } /*****************************************************/ +void RF24Mesh::DHCP() +{ + if (doDHCP) + doDHCP = false; + else + return; - -void RF24Mesh::DHCP(){ - - if(doDHCP){ - doDHCP = false; - }else{ return; } RF24NetworkHeader header; - memcpy(&header,network.frame_buffer,sizeof(RF24NetworkHeader)); - + memcpy(&header, network.frame_buffer, sizeof(RF24NetworkHeader)); + uint16_t newAddress; - + // Get the unique id of the requester (ID is in header.reserved) - if(!header.reserved || header.type != NETWORK_REQ_ADDRESS){ + if (!header.reserved || header.type != NETWORK_REQ_ADDRESS) { #ifdef MESH_DEBUG_PRINTF - printf("MSH: Invalid id or type rcvd\n"); + printf("MSH: Invalid id or type rcvd\n"); #endif - return; + return; } - + uint16_t fwd_by = 0; uint8_t shiftVal = 0; bool extraChild = false; - - 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+=3; - } - shiftVal = count; //Now we know how many bits to shift when adding a child node 1-5 (B001 to B101) to any address - }else{ - //If request is coming from level 1, add an extra child to the master - extraChild = 1; + + 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+=3; + } + shiftVal = count; //Now we know how many bits to shift when adding a child node 1-5 (B001 to B101) to any address + } + else { + //If request is coming from level 1, add an extra child to the master + extraChild = 1; } #ifdef MESH_DEBUG_PRINTF - // printf("%u MSH: Rcv addr req from_id %d \n",millis(),header.reserved); + // printf("%u MSH: Rcv addr req from_id %d \n",millis(),header.reserved); #endif - - for(int i = MESH_MAX_CHILDREN + extraChild; i > 0; i--){ // For each of the possible addresses (5 max) - - bool found = false; - newAddress = fwd_by | (i << shiftVal); - - if(newAddress == MESH_DEFAULT_ADDRESS){ continue; } - - for(uint8_t i=0; i < addrListTop; i++){ - #if defined (MESH_DEBUG_MINIMAL) + + for (int i = MESH_MAX_CHILDREN + extraChild; i > 0; i--) { // For each of the possible addresses (5 max) + + bool found = false; + newAddress = fwd_by | (i << shiftVal); + + if (newAddress == MESH_DEFAULT_ADDRESS) { continue; } + + for (uint8_t i = 0; i < addrListTop; i++) { + #if defined (MESH_DEBUG_MINIMAL) #if !defined (__linux) && !defined ARDUINO_SAM_DUE || defined TEENSY || defined(__ARDUINO_X86__) - Serial.print("ID: ");Serial.print(addrList[i].nodeID,DEC);Serial.print(" ADDR: "); - uint16_t newAddr = addrList[i].address; - char addr[5] = " "; - uint8_t count=3,mask=7; - while(newAddr){ - addr[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(addr); + Serial.print("ID: ");Serial.print(addrList[i].nodeID,DEC);Serial.print(" ADDR: "); + uint16_t newAddr = addrList[i].address; + char addr[5] = " "; + uint8_t count=3,mask=7; + while(newAddr) { + addr[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(addr); #else - printf("ID: %d ADDR: 0%o\n", addrList[i].nodeID,addrList[i].address); + printf("ID: %d ADDR: 0%o\n", addrList[i].nodeID,addrList[i].address); #endif - #endif - if( (addrList[i].address == newAddress) && (addrList[i].nodeID != header.reserved ) ){ - found = true; - break; + #endif + if ((addrList[i].address == newAddress) && (addrList[i].nodeID != header.reserved)) { + found = true; + break; + } + } // 3 conditions: 1. address in list = assigned to somebody else (bad); 2. address in list = assigned to this nodeID (ok); 3. address not in list (ok) + + if (!found) { + header.type = NETWORK_ADDR_RESPONSE; + header.to_node = header.from_node; + //This is a routed request to 00 + + setAddress(header.reserved, newAddress); + //delay(10); // ML: without this delay, address renewal fails + if (header.from_node != MESH_DEFAULT_ADDRESS) { //Is NOT node 01 to 05 + //delay(2); + if (!network.write(header, &newAddress, sizeof(newAddress))) { + network.write(header, &newAddress, sizeof(newAddress)); + } + } + else { + //delay(2); + network.write(header,&newAddress,sizeof(newAddress),header.to_node); + } + + #ifdef MESH_DEBUG_PRINTF + 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; } - } // 3 conditions, address in list, assigned to somebody else (bad), address in list, assigned to this nodeID (ok), address not in list (ok) - - if(!found){ - header.type = NETWORK_ADDR_RESPONSE; - header.to_node = header.from_node; - //This is a routed request to 00 - - setAddress(header.reserved,newAddress); - //delay(10); // ML: without this delay, address renewal fails - if(header.from_node != MESH_DEFAULT_ADDRESS){ //Is NOT node 01 to 05 - //delay(2); - if( !network.write(header,&newAddress,sizeof(newAddress)) ){ - network.write(header,&newAddress,sizeof(newAddress)); - } - }else{ - //delay(2); - network.write(header,&newAddress,sizeof(newAddress),header.to_node); + else { + #if defined (MESH_DEBUG_PRINTF) + printf("not allocated\n"); + #endif } - - #ifdef MESH_DEBUG_PRINTF - 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; - }else{ - #if defined (MESH_DEBUG_PRINTF) - printf("not allocated\n"); - #endif - } - } + } // end for } /*****************************************************/ #endif // !MESH_NOMASTER -void RF24Mesh::setCallback( void (*meshCallback)(void) ){ - +void RF24Mesh::setCallback( void (*meshCallback)(void) ) { + this->meshCallback = meshCallback; } diff --git a/RF24Mesh.h b/RF24Mesh.h index 98abb26..2ba167b 100644 --- a/RF24Mesh.h +++ b/RF24Mesh.h @@ -1,8 +1,9 @@ - - - - +/** + * @file RF24Mesh.h + * + * Class declaration for RF24Mesh + */ #ifndef __RF24MESH_H__ #define __RF24MESH_H__ @@ -27,532 +28,346 @@ #define MESH_BLANK_ID 65535 -/** - * @file RF24Mesh.h - * - * Class declaration for RF24Mesh - */ - -#if defined (__AVR_ATtiny85__) || defined (__AVR_ATtiny84__) - #define RF24_TINY +#if defined(__AVR_ATtiny85__) || defined(__AVR_ATtiny84__) + #define RF24_TINY #endif - #include "RF24Mesh_config.h" -#if defined (__linux) && !defined(__ARDUINO_X86__) - #include - #include - #define RF24_LINUX +#if defined(__linux) && !defined(__ARDUINO_X86__) + #include + #include + #define RF24_LINUX #else - #include - #include + #include + #include #endif - #include - #include - - +#include +#include class RF24; class RF24Network; - class RF24Mesh { - /** - * @name RF24Mesh - * - * The mesh library and class documentation is currently in active development and usage may change. - */ - /**@{*/ + /** + * @name RF24Mesh + * + * The mesh library and class documentation is currently in active development and usage may change. + */ + /**@{*/ public: + /** + * Construct the mesh: + * + * @code + * RF24 radio(7,8); + * RF24Network network(radio); + * RF24Mesh mesh(radio,network); + * @endcode + * @param _radio The underlying radio driver instance + * @param _network The underlying network instance + */ + RF24Mesh(RF24 &_radio, RF24Network &_network); + + /** + * Call this in setup() to configure the mesh and request an address.
+ * + * @code mesh.begin(); @endcode + * This may take a few moments to complete. + * + * 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:7500 + */ + bool begin(uint8_t channel = MESH_DEFAULT_CHANNEL, rf24_datarate_e data_rate = RF24_1MBPS, uint32_t timeout = MESH_RENEWAL_TIMEOUT); + + /** + * Very similar to network.update(), it needs to be called regularly to keep the network + * and the mesh going. + */ + uint8_t update(); + + /** + * Automatically construct a header and send a payload + * Very similar to the standard network.write() function, which can be used directly. + * + * @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 + * @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 needs to be called before mesh.begin(), can be via serial connection, eeprom etc 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 253 + */ + void setNodeID(uint8_t nodeID); + + /** + * 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 times out after 7.5 seconds if address renewal fails. + * + * @note If all nodes are set to verify connectivity/reconnect at a specified period, restarting the master (and deleting dhcplist.txt on Linux) will result + * in complete network/mesh reconvergence. + * @param timeout How long to attempt address renewal in milliseconds default:7500 + * + * @return Returns the newly assigned RF24Network address + */ + uint16_t renewAddress(uint32_t timeout = MESH_RENEWAL_TIMEOUT); + + #if !defined(MESH_NOMASTER) + /** + * Only to be used on the master node. Provides automatic configuration for sensor nodes, similar to DHCP. + * Call immediately after calling network.update() to ensure address requests are handled appropriately + */ + void DHCP(); + + #endif + + /**@}*/ + /** + * @name Advanced Operation + * + * For advanced configuration and usage of the mesh + */ + /**@{*/ + + /** + * Convert an RF24Network address into a nodeId. + * @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. + */ + int16_t getNodeID(uint16_t address = MESH_BLANK_ID); + + /** + * Tests connectivity of this node to the mesh. + * @note If this function fails, address renewal should typically be done. + * @return Return 1 if connected, 0 if mesh not responding + */ + bool checkConnection(); + + /** + * Releases the currently assigned address lease. Useful for nodes that will be sleeping etc. + * @note Nodes should ensure that addresses are released successfully prior to going offline. + * @return Returns 1 if successfully released, 0 if not + */ + bool releaseAddress(); + + /** + * The assigned RF24Network (Octal) address of this node + * @return Returns an unsigned 16-bit integer containing the RF24Network address in octal format + */ + uint16_t mesh_address; + + /** + * Convert a nodeID into an RF24Network address + * @note If printing or displaying the address, it needs to be converted to octal format: Serial.println(address,OCT); + * + * Results in a lookup request being sent to the master node. + * @param nodeID - The unique identifier (1-253) of the node + * @return Returns the RF24Network address of the node, -2 if successful but not in list, -1 if failed + */ + int16_t getAddress(uint8_t nodeID); + + /** + * Write to a specific node by RF24Network address. + * + */ + bool write(uint16_t to_node, const void *data, uint8_t msg_type, size_t size); + + /** + * Change the active radio channel after the mesh has been started. + */ + void setChannel(uint8_t _channel); + + /** + * Allow child nodes to discover and attach to this node. + * @param allow True to allow children, False to prevent children from attaching automatically. + */ + void setChild(bool allow); + + /** + * RF24Mesh ID and Address lookups as well as address renewal can take some time. + * Set a callback function to enable additional processing while the mesh is working + * + * @code + * void myCallbackFunction(){ + * someValue = someOtherValue; + * } + * mesh.setCallback(myCallbackFunction); + * @endcode + * + * @param meshCallback The name of a function to call + */ + void setCallback(void (*meshCallback)(void)); + + #define MESH_CALLBACK if (meshCallback) { meshCallback(); } + + #if !defined(MESH_NOMASTER) + /** + * Set/change a nodeID/RF24Network Address pair manually on the master node. + * + * @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. + * + * mesh.setAddress(23,02); + * @endcode + * + * @code + * Change/set the nodeID for an existing address + * + * uint16_t address = 012; + * mesh.setAddress(3,address,true); + * @endcode + * + * @param nodeID The nodeID to assign + * @param address The octal RF24Network address to assign + * @param searchBy Optional parameter. Default is search by nodeID and set the address. True allows searching by address and setting nodeID. + * @return If the nodeID exists in the list, + */ + void setAddress(uint8_t nodeID, uint16_t address, bool searchBy = false); + + void saveDHCP(); + void loadDHCP(); + + /** + * @name Deprecated + * + * Methods provided for backwards compabibility with old/testing code. + */ + /**@{*/ + + /** + * Calls setAddress() + */ + void setStaticAddress(uint8_t nodeID, uint16_t address); + + #endif // !defined(MESH_NOMASTER) + + /**@}*/ + /** + * @name Address list struct + * + * See the list struct class reference + */ + /**@{*/ + + /**@}*/ + + uint8_t _nodeID; + + #if !defined(MESH_NOMASTER) + typedef struct { + uint8_t nodeID; /** NodeIDs and addresses are stored in the addrList array using this structure */ + uint16_t address; /** NodeIDs and addresses are stored in the addrList array using this structure */ + } addrListStruct; + + // Pointer used for dynamic memory allocation of address list + addrListStruct *addrList; /** See the addrListStruct class reference */ + uint8_t addrListTop; /** The number of entries in the assigned address list */ + #endif + +private: + RF24 &radio; + RF24Network &network; + + void (*meshCallback)(void); + bool requestAddress(uint8_t level); /** Actual requesting of the address once a contact node is discovered or supplied **/ + bool waitForAvailable(uint32_t timeout); /** Waits for data to become available */ + + #if !defined(MESH_NOMASTER) + bool doDHCP; /** Indicator that an address request is available */ + bool addrMemAllocated; /** Just ensures we don't re-allocate the memory buffer if restarting the mesh on master **/ + #endif + + void beginDefault(); /** Starts up the network layer with default address **/ + bool meshStarted; + uint8_t getLevel(uint16_t address); /** Returns the number of digits in the specified address **/ +}; + +#endif // define __RF24MESH_H__ - /** - * Construct the mesh: - * - * @code - * RF24 radio(7,8); - * RF24Network network(radio); - * RF24Mesh mesh(radio,network); - * @endcode - * @param _radio The underlying radio driver instance - * @param _network The underlying network instance - */ - - RF24Mesh( RF24& _radio,RF24Network& _network ); - - /** - * Call this in setup() to configure the mesh and request an address.
- * - * @code mesh.begin(); @endcode - * This may take a few moments to complete. - * - * 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:7500 - */ - bool begin(uint8_t channel = MESH_DEFAULT_CHANNEL, rf24_datarate_e data_rate = RF24_1MBPS, uint32_t timeout=MESH_RENEWAL_TIMEOUT ); - - /** - * Very similar to network.update(), it needs to be called regularly to keep the network - * and the mesh going. - */ - uint8_t update(); - - /** - * Automatically construct a header and send a payload - * Very similar to the standard network.write() function, which can be used directly. - * - * @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 - * @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 needs to be called before mesh.begin(), can be via serial connection, eeprom etc 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 253 - */ - void setNodeID(uint8_t nodeID); - - - /** - * 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 times out after 7.5 seconds if address renewal fails. - * - * @note If all nodes are set to verify connectivity/reconnect at a specified period, restarting the master (and deleting dhcplist.txt on Linux) will result - * in complete network/mesh reconvergence. - * @param timeout How long to attempt address renewal in milliseconds default:7500 - - * @return Returns the newly assigned RF24Network address - */ - uint16_t renewAddress(uint32_t timeout=MESH_RENEWAL_TIMEOUT); - - #if !defined(MESH_NOMASTER) - /** - * Only to be used on the master node. Provides automatic configuration for sensor nodes, similar to DHCP. - * Call immediately after calling network.update() to ensure address requests are handled appropriately - */ - void DHCP(); - - #endif - - /**@}*/ - /** - * @name Advanced Operation - * - * For advanced configuration and usage of the mesh - */ - /**@{*/ - - /** - * Convert an RF24Network address into a nodeId. - * @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. - */ - int16_t getNodeID(uint16_t address=MESH_BLANK_ID); - - /** - * Tests connectivity of this node to the mesh. - * @note If this function fails, address renewal should typically be done. - * @return Return 1 if connected, 0 if mesh not responding - */ - - bool checkConnection(); - - /** - * Releases the currently assigned address lease. Useful for nodes that will be sleeping etc. - * @note Nodes should ensure that addresses are released successfully prior to going offline. - * @return Returns 1 if successfully released, 0 if not - */ - bool releaseAddress(); - - /** - * The assigned RF24Network (Octal) address of this node - * @return Returns an unsigned 16-bit integer containing the RF24Network address in octal format - */ - uint16_t mesh_address; - - /** - * Convert a nodeID into an RF24Network address - * @note If printing or displaying the address, it needs to be converted to octal format: Serial.println(address,OCT); - * - * Results in a lookup request being sent to the master node. - * @param nodeID - The unique identifier (1-253) of the node - * @return Returns the RF24Network address of the node, -2 if successful but not in list, -1 if failed - */ - int16_t getAddress(uint8_t nodeID); - - /** - * Write to a specific node by RF24Network address. - * - */ - bool write(uint16_t to_node, const void* data, uint8_t msg_type, size_t size ); - - /** - * Change the active radio channel after the mesh has been started. - */ - void setChannel(uint8_t _channel); - - /** - * Allow child nodes to discover and attach to this node. - * @param allow True to allow children, False to prevent children from attaching automatically. - */ - void setChild(bool allow); - - /** - * RF24Mesh ID and Address lookups as well as address renewal can take some time. - * Set a callback function to enable additional processing while the mesh is working - * - * @code - * void myCallbackFunction(){ - * someValue = someOtherValue; - * } - * mesh.setCallback(myCallbackFunction); - * @endcode - * - * @param meshCallback The name of a function to call - */ - void setCallback( void (*meshCallback)(void) ); - - #define MESH_CALLBACK if(meshCallback){ meshCallback(); } - - #if !defined(MESH_NOMASTER) - /** - * Set/change a nodeID/RF24Network Address pair manually on the master node. - * - * @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. - * - * mesh.setAddress(23,02); - * @endcode - * - * @code - * Change/set the nodeID for an existing address - * - * uint16_t address = 012; - * mesh.setAddress(3,address,true); - * @endcode - * - * @param nodeID The nodeID to assign - * @param address The octal RF24Network address to assign - * @param searchBy Optional parameter. Default is search by nodeID and set the address. True allows searching by address and setting nodeID. - * @return If the nodeID exists in the list, - */ - void setAddress(uint8_t nodeID, uint16_t address, bool searchBy = false); - - void saveDHCP(); - void loadDHCP(); - - /** - * @name Deprecated - * - * Methods provided for backwards compabibility with old/testing code. - */ - /**@{*/ - - /** - * Calls setAddress() - */ - void setStaticAddress(uint8_t nodeID, uint16_t address); - - #endif - - /**@}*/ - /** - * @name Address list struct - * - * See the list struct class reference - */ - /**@{*/ - - /**@}*/ - - uint8_t _nodeID; - -#if !defined(MESH_NOMASTER) - typedef struct{ - uint8_t nodeID; /**< NodeIDs and addresses are stored in the addrList array using this structure */ - uint16_t address; /**< NodeIDs and addresses are stored in the addrList array using this structure */ - }addrListStruct; - - // Pointer used for dynamic memory allocation of address list - addrListStruct *addrList; /**< See the addrListStruct class reference */ - uint8_t addrListTop; /**< The number of entries in the assigned address list */ -#endif - - private: - RF24& radio; - RF24Network& network; - - void (*meshCallback)(void); - bool requestAddress(uint8_t level); /**< Actual requesting of the address once a contact node is discovered or supplied **/ - bool waitForAvailable(uint32_t timeout); /**< Waits for data to become available */ - - #if !defined(MESH_NOMASTER) - bool doDHCP; /**< Indicator that an address request is available */ - bool addrMemAllocated; /** Arduino Example Sketch
- * This example sketch shows how to manually configure a node via RF24Mesh, and send data to the - * master node. - * The nodes will refresh their network address as soon as a single write fails. This allows the - * nodes to change position in relation to each other and the master node. - */ - - /** - * @example RF24Mesh_Example_Master.ino - * Arduino Example Sketch
- * @note This sketch only functions on -Arduino Due- - * - * This example sketch shows how to manually configure a node via RF24Mesh as a master node, which - * will receive all data from sensor nodes. - * - * The nodes can change physical or logical position in the network, and reconnect through different - * routing nodes as required. The master node manages the address assignments for the individual nodes - * in a manner similar to DHCP. - * - */ - - /** - * @example RF24Mesh_Example_Node2Node.ino - * Example of node to node communication using RF24Mesh - */ - - /** - * @example RF24Mesh_Example_Node2NodeExtra.ino - * Extended Example of node to node communication using RF24Mesh - */ - - /** - * @example RF24Mesh_SerialConfig.ino - * - * This example sketch shows how the same sketch can be written to a large number of devices, which are - * configured later via Serial input. - * - */ - - /** - * @example RF24Mesh_Example.cpp - * - * Raspberry Pi Example Sketch
- * This example sketch shows how to manually configure a node via RF24Mesh, and send data to the - * master node. - * The nodes will refresh their network address as soon as a single write fails. This allows the - * nodes to change position in relation to each other and the master node. - */ - - /** - * @example RF24Mesh_Example_Master.cpp - * - * Raspberry Pi Example Sketch
- * - * This example sketch shows how to manually configure a node via RF24Mesh as a master node, which - * will receive all data from sensor nodes. - * - * The nodes can change physical or logical position in the network, and reconnect through different - * routing nodes as required. The master node manages the address assignments for the individual nodes - * in a manner similar to DHCP. - * - */ - - /** - * @example RF24Mesh_Ncurses_Master.cpp - * A very limited ncurses interface used for initial monitoring/testing of RF24Mesh - * @image html "images/RF24Mesh_Ncurses.JPG" - */ +/** + * @example RF24Mesh_Example.ino + * Arduino Example Sketch
+ * This example sketch shows how to manually configure a node via RF24Mesh, and send data to the + * master node. + * The nodes will refresh their network address as soon as a single write fails. This allows the + * nodes to change position in relation to each other and the master node. + */ /** - * @mainpage Mesh Networking Layer for RF24 Radios - * - * This class intends to provide a simple and seamless 'mesh' layer for sensor networks, allowing automatic and dynamic configuration - * that can be customized to suit many scenarios. It is currently designed to interface directly with with the - * RF24Network library, an OSI Network Layer using nRF24L01(+) radios driven - * by the newly optimized RF24 library fork. - * - * @section Purpose Purpose/Goals + * @example RF24Mesh_Example_Master.ino + * Arduino Example Sketch
+ * @note This sketch only functions on -Arduino Due- * - * - Provide a simple user interface for creating dynamic sensor networks with the RF24 and RF24Network libraries. - * - Create stable, fully automated/self-managed networks + * This example sketch shows how to manually configure a node via RF24Mesh as a master node, which + * will receive all data from sensor nodes. * - * @section Overview RF24Mesh Overview - * The RF24Network library provides a system of addressing and routing for RF24 radio modules that allows large wireless sensor networks to be constructed.
RF24Mesh - * provides extended features, including automatic addressing and dynamic configuration of wireless sensors. + * The nodes can change physical or logical position in the network, and reconnect through different + * routing nodes as required. The master node manages the address assignments for the individual nodes + * in a manner similar to DHCP. * - * **How does it work?**
- * - * Nodes are assigned a unique number ranging from 1 to 253, and just about everything else, addressing, routing, etc. is managed by the library. - * - * The unique identifier is like an IP address, used to communicate at a high level within the RF24 communication stack and will generally remain static. At the network layer, - * the physical radio addresses, similar to MAC addresses, are allocated as nodes move around and establish connections within the network. - * - * The 'master' node keeps track of the unique nodeIDs and the assigned RF24Network addresses. When a node is moved physically, or just loses its connection to the network, - * it can automatically re-join the mesh and reconfigure itself within the network. + */ - * In the mesh configuration sensors/nodes can move around physically, far from the 'master node' using other nodes to route traffic over extended distances. Addressing and - * topology is reconfigured as connections are broken and re-established within different areas of the network. - * - * RF24Mesh takes advantage of functionality and features within the RF24 and RF24Network libraries, so everything from addressing, routing, fragmentation/re-assembly - * (very large payloads) are handled automatically with processes designed to support a multi-node radio network. - * - * Update: Aug 2020
- * v1.1.3 - * @li More bug fixes, mostly affecting functionality - * - * v1.1.2 - * @li Quite a few bug fixes and cleanup for RF24Mesh and the RF24 libraries recently, updates are recommended - * @li Updates mainly addresses stability and reliability issues - * @li Improvements to address renewal, connection verification and lookups - * - * @section More How to learn more - * - * @li Try it out! - * @li Setup and Configuration - * @li Usage & Overview - * @li RF24Mesh Class Documentation - * @li RF24 Network Class Documentation - * @li RF24Ethernet: TCP/IP based Mesh over RF24 - * @li RF24Gateway: A TCP/IP and RF24 Gateway for RF24 nodes - * @li All Documentation and Downloads - * @li Source Code - * - * @page Setup-Config Setup And Config - * - * The initial testing version of RF24Mesh is built as a simple overlay for RF24Network. Users currently need to be familiar with the basics of sending and receiving data via - * RF24Network, but do not need to understand the topology, routing or addressing systems. RF24Mesh will attempt to construct and maintain a mesh network, keeping all nodes - * connected together. - * - * @section Requirements Requirements - * Hardware Requirements:
- * @li 1 Raspberry Pi or Arduino to act as the Master Node
- * @li 1 or more Arduino,RPi,etc. (Sensor Nodes)
- * @li 2 or more NRF24L01+ radio modules
- * @li 1 or more various sensors for your sensor nodes
- * - * Software Requirements: - * @li RF24 Core Radio Library - * @li RF24Network Library - * @li RF24Mesh - Dynamic Mesh Library - * - * @section Installation Installation - * 1. Use the Arduino Library Manager. Selecting RF24Mesh should also install RF24Network and RF24 Core libraries
- *
- * 2. Configure and test the hardware using examples from RF24 and RF24Network prior to attempting to use RF24Mesh
- * a: In Arduino IDE: File > Examples > RF24 > GettingStarted see: Arduino
- * b: RPi: An installer is provided: Linux RPi
- *
- * 3. Once testing is complete:
- * a: Arduino IDE: File > Examples > RF24Mesh > RF24Mesh_Example
- * b: RPi: Run 'make' from the examples directory. Then 'sudo ./RF24Mesh_Example_Master' to begin as the master node
- *
- * 4. Once configured and running, the Master Node will begin to assign addresses to the sensor nodes, which will find their way onto the network, and - * display incoming data from the sensor examples. Usage is very much the same as RF24Network, except for address assignment and network management. - * - * @section Config Configuration - * - * As per the examples, nodes are configured with a unique value between 1 and 253. This allows them to change positions on the network while still being identified.
- * - * For pre-configuration of the mesh, some options are available by editing RF24Mesh_config.h prior to compiling:
- * - * @code - * #define MESH_MAX_CHILDREN 4 - * @endcode - * The max_children option restricts the maximum number of child nodes/node and limits the number of available addresses on the network. Max: 4
- * - * @code - * #define MESH_NOMASTER - * @endcode - * The nomaster option reduces program space and memory usage. Can be used on any node except for the master (nodeID 0)
- * - * - * @li See General Usage for information on how to work with the mesh once connected. - * - * @page General-Usage General Usage - * - * @section Net_Design Network Design Options - * - * 1. **Static Network** (No Mesh): - * RF24Network can be configured manually, with a static design. RF24Mesh is not used at all. See http://nRF24.github.io/RF24Network/Addressing.html

- * - * 2. **Static Network w/Dynamic Assignment:** - * RF24Mesh is only used to acquire an address on startup. Nodes are generally expected to remain stationary. Changes to - * the network would be addressed manually, by adding, removing, or resetting nodes. Users can choose to use RF24Network functions directly, or use RF24Mesh.

- * - * 3. **Dynamic Network & Assignment:** - * Nodes join the mesh automatically and re-attach as required. This is the default and how the examples work.

- * - * 4. **Hybrid Network**: - * Utilizes a combination of static & dynamic nodes. Requires initial planning and deployment, but can result in a more stable network, easing - * the use of sleeping nodes.

- * - * @section NetMgmt Network Management - * - * RF24Network addresses can be viewed as MAC addresses, and RF24Mesh nodeIDs viewed as static IP addresses. When joining or re-attaching to the network, nodes - * will request a RF24Network address, and are identified via nodeID. - * - * **Raspberry Pi/Linux:** On Linux devices, the RF24Gateway will save address assignments to file (dhcplist.txt) so they will be restored, even if the - * gateway is restarted. To force network re-convergence, delete the dhcplist.txt file and restart the gateway. If nodes are configured to verify their connection at a set - * interval, they will come back online in time. - * - * **Arduino/AVR:** On all other devices, the address list is not saved. To force network re-convergence, restart the gateway. If nodes are configured to verify their - * connection at a set interval, they will come back online in time. - * - * If a node/nodeID is removed from the network permanently, the address should be released prior to removal. If it is not, the assigned RF24Network address can be - * written to 0 in the RF24Mesh address list. - * - * @section MeshComm Mesh Communication - * - * RF24Mesh nodeIDs are unique identifiers, while RF24Network addresses change dynamically within a statically defined structure. Due to this structure, it is simple - * for any node to communicate with the master node, since the RF24Network address is always known (00). Conversely, the master node maintains a list of every node on the - * network, so address 'lookups' return immediately. - * - * Communication from node-to-node requires address queries to be sent to the master node, since individual nodes may change RF24Network & radio address at any time. - * Due to the extra data transmissions, node-to-node communication is less efficient. - * - * @section General General Usage - * - * One thing to keep in mind is the dynamic nature of RF24Mesh, and the need to verify connectivity to the network. For nodes that are constantly transmitting, - * (every few seconds at most) it is suitable to check the connection, and/or renew the address when connectivity fails. Since data is not saved by the master - * node, if the master node goes down, all child nodes must renew their address. In this case, as long as the master node is down for a few seconds, the nodes - * will all begin requesting an address.
- * - * Nodes that are not actively transmitting, should be configured to test their connection at predefined intervals, to allow them to reconnect as necessary.
+/** + * @example RF24Mesh_Example_Node2Node.ino + * Example of node to node communication using RF24Mesh + */ + +/** + * @example RF24Mesh_Example_Node2NodeExtra.ino + * Extended Example of node to node communication using RF24Mesh + */ + +/** + * @example RF24Mesh_SerialConfig.ino * - * In the case of sleeping nodes, or nodes that will only be online temporarily, it is generally suitable to release the address prior to going offline, and - * requesting an address upon waking. Keep in mind, address requests can generally take anywhere from 10-15ms, up to few seconds in most cases.
+ * This example sketch shows how the same sketch can be written to a large number of devices, which are + * configured later via Serial input. * - * 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. + */ + +/** + * @example RF24Mesh_Example.cpp * - * @section RF24Network RF24Network + * Raspberry Pi Example Sketch
+ * This example sketch shows how to manually configure a node via RF24Mesh, and send data to the + * master node. + * The nodes will refresh their network address as soon as a single write fails. This allows the + * nodes to change position in relation to each other and the master node. + */ + +/** + * @example RF24Mesh_Example_Master.cpp * - * Beyond requesting and releasing addresses, usage is outlined in the class documentation, and further information regarding RF24Network is available at - * http://nRF24.github.io/RF24Network + * Raspberry Pi Example Sketch
* + * This example sketch shows how to manually configure a node via RF24Mesh as a master node, which + * will receive all data from sensor nodes. * + * The nodes can change physical or logical position in the network, and reconnect through different + * routing nodes as required. The master node manages the address assignments for the individual nodes + * in a manner similar to DHCP. * */ + +/** + * @example RF24Mesh_Ncurses_Master.cpp + * A very limited ncurses interface used for initial monitoring/testing of RF24Mesh + * @image html "images/RF24Mesh_Ncurses.JPG" + */ diff --git a/RF24Mesh_config.h b/RF24Mesh_config.h index c5fc4ea..7e4879c 100644 --- a/RF24Mesh_config.h +++ b/RF24Mesh_config.h @@ -1,24 +1,64 @@ - +/** + * @file RF24Mesh_config.h + * + * macro definitions for configuring RF24Mesh + */ #ifndef __RF24MESH_CONFIG_H__ #define __RF24MESH_CONFIG_H__ /*** User Configuration ***/ -#define MESH_MAX_CHILDREN 4 /** Set 1 to 4 (Default: 4) Restricts the maximum children per node. The master node supports MESH_MAX_CHILDREN + 1 nodes **/ -#ifdef RF24_TINY - #define MESH_NOMASTER +/** + * @brief Set 1 to 4 (Default: 4) Restricts the maximum children per node. + * + * The master node supports MESH_MAX_CHILDREN + 1 nodes + */ +#ifndef MESH_MAX_CHILDREN + #define MESH_MAX_CHILDREN 4 +#endif // MESH_MAX_CHILDREN +#if defined (RF24_TINY) || defined (DOXYGEN_FORCED) + /** + * @brief Save on resources for non-master nodes + * + * This can be optionally set to 0 for all nodes except the master (nodeID 0) to save program space. + * Enabled automatically on ATTiny devices + */ + #define MESH_NOMASTER #endif -//#define MESH_NOMASTER /** This can be set to 0 for all nodes except the master (nodeID 0) to save pgm space. Enabled automatically on ATTiny devices **/ + +// un-comment for non-master nodes not running on ATTiny MCUs +//#define MESH_NOMASTER /***Advanced User Config***/ -#define MESH_DEFAULT_CHANNEL 97 /** Radio channel to operate on 1-127. This is normally modified by calling mesh.setChannel() */ -#define MESH_RENEWAL_TIMEOUT 7500 /** How long to attempt address renewal ( renewAddress(); ) */ /** -* On the master node memory for the address list (nodeIDs + RF24Network Addresses) is allocated dynamically and re-allocated using this value -* Example: With a value of 10, space for 10 nodes is allocated on startup. Adding an 11th node will re-allocate the memory space to support 10 more nodes. -* On 8-bit AVRs (Arduino Uno, Nano etc) each entry uses 3-bytes of memory space. Minimize this value to save memory. Allocate enough to prevent memory fragmentation. -*/ -#define MESH_MEM_ALLOC_SIZE 10 + * @brief Radio channel to operate on 1-127. + * + * This is normally modified by calling RF24Mesh::setChannel() + */ +#ifndef MESH_DEFAULT_CHANNEL + #define MESH_DEFAULT_CHANNEL 97 +#endif // MESH_DEFAULT_CHANNEL + +/** + * @brief How long to attempt address renewal in milliseconds + * @see RF24Mesh::renewAddress() + */ +#ifndef MESH_RENEWAL_TIMEOUT + #define MESH_RENEWAL_TIMEOUT 7500 +#endif // MESH_RENEWAL_TIMEOUT + +/** + * @brief master node memory allocation + * + * On the master node memory for the address list (nodeIDs + RF24Network Addresses) is allocated dynamically and re-allocated using this value + * + * Example: With a value of 10, space for 10 nodes is allocated on startup. Adding an 11th node will re-allocate the memory space to support 10 more nodes. + * + * On 8-bit AVRs (Arduino Uno, Nano etc) each entry uses 3-bytes of memory space. Minimize this value to save memory. Allocate enough to prevent memory fragmentation. + */ +#ifndef MESH_MEM_ALLOC_SIZE + #define MESH_MEM_ALLOC_SIZE 10 +#endif // MESH_MEM_ALLOC_SIZE /**************************/ /*** Debug ***/ @@ -26,32 +66,38 @@ //#define MESH_DEBUG /** Uncomment to enable debug output to serial **/ /**************************/ -/** Other Configuration */ +/*** Other Configuration ***/ //#define MESH_MIN_SAVE_TIME 30000 /** UNUSED Minimum time required before changing nodeID. Prevents excessive writing to EEPROM */ -/** - * How long to wait in ms for a response during individual address lookups (getNodeID or getAddress). - * If using distant nodes or a large number of nodes this value can be increased in general or for specific nodes. +/** + * @brief How long to wait in ms for a response during individual address lookups + * @see RF24Mesh::getNodeID and RF24Mesh::getAddress + * If using distant nodes or a large number of nodes this value can be increased in general or for specific nodes. * For Level 1 nodes a response typically takes 2-3ms in good conditions. - * For Level 2 nodes: 4-5ms, Level 3: 6-15ms, Level 4: 10-25ms + * For Level 2 nodes: 4-5ms, Level 3: 6-15ms, Level 4: 10-25ms **/ -#define MESH_LOOKUP_TIMEOUT 135 - -#define MESH_WRITE_TIMEOUT 115 /** How long mesh.write retries address lookups before timing out. Allows multiple attempts */ -#define MESH_DEFAULT_ADDRESS NETWORK_DEFAULT_ADDRESS -//#define MESH_MAX_ADDRESSES 255 /** UNUSED Determines the max size of the array used for storing addresses on the Master Node */ -//#define MESH_ADDRESS_HOLD_TIME 30000 /**UNUSED How long before a released address becomes available */ +#ifndef MESH_LOOKUP_TIMEOUT + #define MESH_LOOKUP_TIMEOUT 135 +#endif // MESH_LOOKUP_TIMEOUT - #if defined (MESH_DEBUG) - #if !defined (__linux) && !defined ARDUINO_SAM_DUE || defined TEENSY || defined(__ARDUINO_X86__) - #define MESH_DEBUG_SERIAL - #else - #define MESH_DEBUG_PRINTF - #endif - #endif - +/** @brief How long RF24Mesh::write retries address lookups before timing out. Allows multiple attempts */ +#ifndef MESH_WRITE_TIMEOUT + #define MESH_WRITE_TIMEOUT 115 +#endif // MESH_WRITE_TIMEOUT +#ifndef MESH_DEFAULT_ADDRESS + #define MESH_DEFAULT_ADDRESS NETWORK_DEFAULT_ADDRESS +#endif // MESH_DEFAULT_ADDRESS +//#define MESH_MAX_ADDRESSES 255 /** UNUSED Determines the max size of the array used for storing addresses on the Master Node */ +//#define MESH_ADDRESS_HOLD_TIME 30000 /**UNUSED How long before a released address becomes available */ +#if defined (MESH_DEBUG) + #if !defined (__linux) && !defined ARDUINO_SAM_DUE || defined TEENSY || defined(__ARDUINO_X86__) + #define MESH_DEBUG_SERIAL + #else + #define MESH_DEBUG_PRINTF + #endif // platform ostream def +#endif // defined (MESH_DEBUG) -#endif +#endif // __RF24MESH_CONFIG_H__ diff --git a/docs/README.md b/docs/README.md new file mode 100644 index 0000000..1fa6589 --- /dev/null +++ b/docs/README.md @@ -0,0 +1 @@ +These markdown files (*.md) contain relative hyperlinks. Any relative hyperlinks will not work when viewing these markdown files in github. \ No newline at end of file diff --git a/docs/general_usage.md b/docs/general_usage.md new file mode 100644 index 0000000..aec34d0 --- /dev/null +++ b/docs/general_usage.md @@ -0,0 +1,59 @@ +# General Usage + +## Network Design Options + +1. **Static Network** (No Mesh)
+ RF24Network can be configured manually, with a static design. RF24Mesh is not used at all. See [Network addressing](http://nRF24.github.io/RF24Network/md_docs_addressing.html) +2. **Static Network w/Dynamic Assignment**
+ RF24Mesh is only used to acquire an address on startup. Nodes are generally expected to remain stationary. Changes to + the network would be addressed manually, by adding, removing, or resetting nodes. Users can choose to use RF24Network functions directly, or use RF24Mesh. +3. **Dynamic Network & Assignment**
+ Nodes join the mesh automatically and re-attach as required. This is the default and how the examples work. +4. **Hybrid Network**
+ Utilizes a combination of static & dynamic nodes. Requires initial planning and deployment, but can result in a more stable network, easing + the use of sleeping nodes. + +## Network Management +RF24Network addresses can be viewed as MAC addresses, and RF24Mesh nodeIDs viewed as static IP addresses. When joining or re-attaching to the network, nodes +will request a RF24Network address, and are identified via nodeID. + +### Raspberry Pi/Linux +On Linux devices, the RF24Gateway will save address assignments to file (dhcplist.txt) so they will be restored, even if the +gateway is restarted. To force network re-convergence, delete the dhcplist.txt file and restart the gateway. If nodes are configured to verify their connection at a set +interval, they will come back online in time. + +### Arduino/AVR +On all other devices, the address list is not saved. To force network re-convergence, restart the gateway. If nodes are configured to verify their +connection at a set interval, they will come back online in time. + +If a node/nodeID is removed from the network permanently, the address should be released prior to removal. If it is not, the assigned RF24Network address can be +written to 0 in the RF24Mesh address list. + +## Mesh Communication +RF24Mesh nodeIDs are unique identifiers, while RF24Network addresses change dynamically within a statically defined structure. Due to this structure, it is simple +for any node to communicate with the master node, since the RF24Network address is always known (00). Conversely, the master node maintains a list of every node on the +network, so address 'lookups' return immediately. + +Communication from node-to-node requires address queries to be sent to the master node, since individual nodes may change RF24Network & radio address at any time. +Due to the extra data transmissions, node-to-node communication is less efficient. + +## General Usage +One thing to keep in mind is the dynamic nature of RF24Mesh, and the need to verify connectivity to the network. For nodes that are constantly transmitting, +(every few seconds at most) it is suitable to check the connection, and/or renew the address when connectivity fails. Since data is not saved by the master +node, if the master node goes down, all child nodes must renew their address. In this case, as long as the master node is down for a few seconds, the nodes +will all begin requesting an address. + + +Nodes that are not actively transmitting, should be configured to test their connection at predefined intervals, to allow them to reconnect as necessary. + + +In the case of sleeping nodes, or nodes that will only be online temporarily, it is generally suitable to release the address prior to going offline, and +requesting an address upon waking. Keep in mind, address requests can generally take anywhere from 10-15ms, up to few seconds in most cases. + + +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. + +## RF24Network +Beyond requesting and releasing addresses, usage is outlined in the class documentation, and further information regarding RF24Network is available at +http://nRF24.github.io/RF24Network diff --git a/docs/main_page.md b/docs/main_page.md new file mode 100644 index 0000000..2fb2593 --- /dev/null +++ b/docs/main_page.md @@ -0,0 +1,42 @@ +# Mesh Networking Layer for RF24 Radios +This class intends to provide a simple and seamless 'mesh' layer for sensor networks, allowing automatic and dynamic configuration +that can be customized to suit many scenarios. It is currently designed to interface directly with with the +[RF24Network library](http://tmrh20.github.com/RF24Network/), an [OSI Network Layer](http://en.wikipedia.org/wiki/Network_layer) using nRF24L01(+) radios driven +by the newly optimized [RF24 library](http://tmrh20.github.com/RF24/) fork. + +## Purpose/Goals +- Provide a simple user interface for creating dynamic sensor networks with the RF24 and RF24Network libraries. +- Create stable, fully automated/self-managed networks + +## News +See a the list of changes on [the Github releases page](https://github.com/nRF24/RF24Mesh/releases/) + +## RF24Mesh Overview +The RF24Network library provides a system of addressing and routing for RF24 radio modules that allows large wireless sensor networks to be constructed.
RF24Mesh +provides extended features, including automatic addressing and dynamic configuration of wireless sensors. + +### How does it work? +Nodes are assigned a unique number ranging from 1 to 253, and just about everything else, addressing, routing, etc. is managed by the library. + +The unique identifier is like an IP address, used to communicate at a high level within the RF24 communication stack and will generally remain static. At the network layer, +the physical radio addresses, similar to MAC addresses, are allocated as nodes move around and establish connections within the network. + +The 'master' node keeps track of the unique nodeIDs and the assigned RF24Network addresses. When a node is moved physically, or just loses its connection to the network, +it can automatically re-join the mesh and reconfigure itself within the network. + +In the mesh configuration sensors/nodes can move around physically, far from the 'master node' using other nodes to route traffic over extended distances. Addressing and +topology is reconfigured as connections are broken and re-established within different areas of the network. + +RF24Mesh takes advantage of functionality and features within the RF24 and RF24Network libraries, so everything from addressing, routing, fragmentation/re-assembly +(very large payloads) are handled automatically with processes designed to support a multi-node radio network. + +## How to learn more +- Try it out! +- [Setup and Configuration](md_docs_setup_config.html) +- [Usage & Overview](md_docs_general_usage.html) +- [RF24Mesh Class Documentation](classRF24Mesh.html) +- [RF24 Network Class Documentation](http://nRF24.github.io/RF24Network/) +- [RF24Ethernet: TCP/IP based Mesh over RF24](http://nRF24.github.io/RF24Ethernet/) +- [RF24Gateway: A TCP/IP and RF24 Gateway for RF24 nodes](http://nRF24.github.io/RF24Gateway/) +- [All Documentation and Downloads](https://tmrh20.github.io) +- [Source Code](https://github.com/TMRh20/RF24Mesh) diff --git a/docs/setup_config.md b/docs/setup_config.md new file mode 100644 index 0000000..25ab14e --- /dev/null +++ b/docs/setup_config.md @@ -0,0 +1,53 @@ +# Setup And Config + +The initial testing version of RF24Mesh is built as a simple overlay for RF24Network. Users currently need to be familiar with the basics of sending and receiving data via +RF24Network, but do not need to understand the topology, routing or addressing systems. RF24Mesh will attempt to construct and maintain a mesh network, keeping all nodes +connected together. + +## Requirements +### Hardware Requirements +- 1 Raspberry Pi or Arduino to act as the Master Node +- 1 or more Arduino, Raspberry Pi, etc. (Sensor Nodes) +- 2 or more NRF24L01+ radio modules +- 1 or more various sensors for your sensor nodes + +### Software Requirements +- [Download RF24 Core Radio Library](https://github.com/TMRh20/RF24/archive/master.zip) +- [Download RF24Network Library](https://github.com/TMRh20/RF24Network/archive/master.zip) +- [Download RF24Mesh - Dynamic Mesh Library](https://github.com/TMRh20/RF24Mesh/archive/master.zip) + +## Installation +1. Use the Arduino Library Manager. Selecting RF24Mesh should also install RF24Network and RF24 Core libraries +2. Configure and test the hardware using examples from RF24 and RF24Network prior to attempting to use RF24Mesh + - In Arduino IDE + - File > Examples > RF24 > GettingStarted + @see [Arduino Support page](http://nRF24.github.io/RF24/md_docs_arduino.html) + - For a Raspberry Pi + - An installer is provided: [Linux Installation](http://nRF24.github.io/RF24/md_docs_linux_install.html) + @see [General Linux/RPi setup and configuration page](http://nRF24.github.io/RF24/md_docs_rpi_general.html) +3. Once testing is complete: + - In Arduino IDE + - File > Examples > RF24Mesh > RF24Mesh_Example + - For a Raspberry Pi + - Run `make` from the examples directory. Then `sudo ./RF24Mesh_Example_Master` to begin an example as the master node +4. Once configured and running, the Master Node will begin to assign addresses to the sensor nodes, which will find their way onto the network, and + display incoming data from the sensor examples. Usage is very much the same as RF24Network, except for address assignment and network management. + +## Configuration +As per the examples, nodes are configured with a unique value between 1 and 253. This allows them to change positions on the network while still being identified. + +For pre-configuration of the mesh, some options are available by editing RF24Mesh_config.h prior to compiling: + +### Restrict number of children +```cpp +#define MESH_MAX_CHILDREN 4 +``` +The @ref MESH_MAX_CHILDREN option restricts the maximum number of child nodes/node and limits the number of available addresses on the network. Max: 4 + +### Reduce resource consumption +```cpp +#define MESH_NOMASTER +``` +The @ref MESH_NOMASTER option reduces program space and memory usage. Can be used on any node except for the master (nodeID 0) + +@see [General Usage](md_docs_general_usage.html) for information on how to work with the mesh once connected diff --git a/library.json b/library.json index f4ba73c..813adf0 100644 --- a/library.json +++ b/library.json @@ -7,7 +7,7 @@ "type": "git", "url": "https://github.com/TMRh20/RF24Mesh.git" }, - "version": "1.1.4", + "version": "1.1.5", "dependencies": [ { "name": "RF24", "authors": "TMRh20", "frameworks": "arduino" }, { "name": "RF24Network", "authors": "TMRh20", "frameworks": "arduino" } diff --git a/library.properties b/library.properties index 0be0e20..36f83dc 100644 --- a/library.properties +++ b/library.properties @@ -1,5 +1,5 @@ name=RF24Mesh -version=1.1.4 +version=1.1.5 author=TMRh20 maintainer=TMRh20,Avamander sentence=OSI Layer 7, Automated 'mesh' style networking for nrf24L01(+) radios. diff --git a/pyRF24Mesh/pyRF24Mesh.cpp b/pyRF24Mesh/pyRF24Mesh.cpp index 26f6afc..2c7ba20 100644 --- a/pyRF24Mesh/pyRF24Mesh.cpp +++ b/pyRF24Mesh/pyRF24Mesh.cpp @@ -74,7 +74,7 @@ BOOST_PYTHON_MODULE(RF24Mesh) .def("write", &write_wrap1, (bp::arg("data"), bp::arg("msg_type"))) .def("write", &write_wrap2, (bp::arg("data"), bp::arg("msg_type"), bp::arg("nodeID"))) //bool write(uint16_t to_node, const void* data, uint8_t msg_type, size_t size ); - .def("write", &write_to_node_wrap, (bp::arg("to_node"), bp::arg("data"), bp::arg("msg_type"), bp::arg("size"))) + .def("write", &write_to_node_wrap, (bp::arg("to_node"), bp::arg("data"), bp::arg("msg_type"))) //void setNodeID(uint8_t nodeID); .def("setNodeID", &RF24Mesh::setNodeID, (bp::arg("nodeID"))) //void DHCP(); @@ -102,4 +102,4 @@ BOOST_PYTHON_MODULE(RF24Mesh) //void setStaticAddress(uint8_t nodeID, uint16_t address); .def("setStaticAddress", &RF24Mesh::setStaticAddress, (bp::arg("nodeID"), bp::arg("address"))); } -} \ No newline at end of file +} diff --git a/usePicoSDK.cmake b/usePicoSDK.cmake new file mode 100644 index 0000000..9eeb9b1 --- /dev/null +++ b/usePicoSDK.cmake @@ -0,0 +1,18 @@ +## Include this file if you want to use the RF24Mesh library +## in YOUR (Pico) project. + +cmake_minimum_required(VERSION 3.12) + +set(CMAKE_C_STANDARD 11) +set(CMAKE_CXX_STANDARD 17) + +# Define the RF24Mesh library +add_library(RF24Mesh INTERFACE) + +target_sources(RF24Mesh INTERFACE + ${CMAKE_CURRENT_LIST_DIR}/RF24Mesh.cpp +) + +target_include_directories(RF24Mesh INTERFACE + ${CMAKE_CURRENT_LIST_DIR}/ +)