diff --git a/.github/workflows/doxygen.yml b/.github/workflows/doxygen.yml index 5e3f23d..032b251 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 e5b6c23..8fe78b1 100644 --- a/.gitignore +++ b/.gitignore @@ -1,2 +1,3 @@ -# ignore docs folder -docs/ \ No newline at end of file +# ignore doxygen generated files +docs/html/ +docs/xml/ diff --git a/.vscode/settings.json b/.vscode/settings.json new file mode 100644 index 0000000..de288e1 --- /dev/null +++ b/.vscode/settings.json @@ -0,0 +1,3 @@ +{ + "python.formatting.provider": "black" +} \ No newline at end of file diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md new file mode 100644 index 0000000..3a08eba --- /dev/null +++ b/CONTRIBUTING.md @@ -0,0 +1,9 @@ +These are the current requirements for getting your code included in RF24: + +* Try your best to follow the rest of the code, if you're unsure then the NASA C style can help as it's closest to the current style: https://ntrs.nasa.gov/archive/nasa/casi.ntrs.nasa.gov/19950022400.pdf + +* Definetly follow [PEP-8](https://www.python.org/dev/peps/pep-0008/) if it's Python code. + +* Follow the [Arduino IDE formatting style](https://www.arduino.cc/en/Reference/StyleGuide) for Arduino examples + +* Add [doxygen-compatible documentation](https://www.doxygen.nl/manual/docblocks.html) to any new functions you add, or update existing documentation if you change behaviour diff --git a/Doxyfile b/Doxyfile index 21fc0d0..99b5d7e 100644 --- a/Doxyfile +++ b/Doxyfile @@ -770,7 +770,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 @@ -867,7 +868,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 = +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 @@ -952,7 +953,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 @@ -2432,4 +2433,3 @@ GENERATE_LEGEND = YES # This tag requires that the tag HAVE_DOT is set to YES. DOT_CLEANUP = YES - diff --git a/RF24Gateway.cpp b/RF24Gateway.cpp index 0bd41e6..46a87d6 100644 --- a/RF24Gateway.cpp +++ b/RF24Gateway.cpp @@ -1,13 +1,15 @@ - - +/** + * @file RF24Gateway.cpp + * + * Class definitions for RF24Gateway + */ #include "RF24Gateway.h" #include "RF24Mesh/RF24Mesh_config.h" /***************************************************************************************/ -RF24Gateway::RF24Gateway(RF24& _radio,RF24Network& _network, RF24Mesh& _mesh): - radio(_radio),network(_network),mesh(_mesh) +RF24Gateway::RF24Gateway(RF24 &_radio, RF24Network &_network, RF24Mesh &_mesh) : radio(_radio), network(_network), mesh(_mesh) { interruptInProgress = 0; interruptsEnabled = 1; @@ -15,211 +17,223 @@ RF24Gateway::RF24Gateway(RF24& _radio,RF24Network& _network, RF24Mesh& _mesh): /***************************************************************************************/ -void RF24Gateway::begin(uint8_t nodeID, uint8_t _channel, rf24_datarate_e data_rate) { - - mesh_enabled = true; - begin(true, mesh_enabled, 0, nodeID, data_rate, _channel); +void RF24Gateway::begin(uint8_t nodeID, uint8_t _channel, rf24_datarate_e data_rate) +{ + mesh_enabled = true; + begin(true, mesh_enabled, 0, nodeID, data_rate, _channel); } /***************************************************************************************/ -void RF24Gateway::begin(uint16_t address, uint8_t _channel, rf24_datarate_e data_rate, bool meshEnable, uint8_t nodeID) { - - begin(0, mesh_enabled, address, nodeID, data_rate, _channel); +void RF24Gateway::begin(uint16_t address, uint8_t _channel, rf24_datarate_e data_rate, bool meshEnable, uint8_t nodeID) +{ + begin(0, mesh_enabled, address, nodeID, data_rate, _channel); } /***************************************************************************************/ -bool RF24Gateway::begin(bool configTUN, bool meshEnable, uint16_t address, uint8_t mesh_nodeID, rf24_datarate_e data_rate, uint8_t _channel) { - - #if(DEBUG>=1) - printf("GW Begin\n"); - printf("Config Device address 0%o nodeID %d\n",address,mesh_nodeID); - #endif - config_TUN = configTUN; - - ///FIX - - channel = _channel;//97; - - dataRate = data_rate; - - configDevice(address); +bool RF24Gateway::begin(bool configTUN, bool meshEnable, uint16_t address, uint8_t mesh_nodeID, rf24_datarate_e data_rate, uint8_t _channel) +{ + #if (DEBUG >= 1) + printf("GW Begin\n"); + printf("Config Device address 0%o nodeID %d\n", address, mesh_nodeID); + #endif + config_TUN = configTUN; + + ///FIX + + channel = _channel; //97; + + dataRate = data_rate; + + configDevice(address); mesh_enabled = meshEnable; - thisNodeID = mesh_nodeID; - thisNodeAddress = address; - - if(meshEnable){ - // GW radio channel setting takes precedence over mesh_default_channel - if(channel == 97 && MESH_DEFAULT_CHANNEL != 97){ - channel = MESH_DEFAULT_CHANNEL; - } - - if(!thisNodeAddress && !mesh_nodeID){ - mesh.setNodeID(0); - }else{ - if(!mesh_nodeID){ - mesh_nodeID = 253; - } - mesh.setNodeID(mesh_nodeID); //Try not to conflict with any low-numbered node-ids - } - mesh.begin(channel,data_rate); - thisNodeAddress = mesh.mesh_address; - - }else{ - radio.begin(); - delay(5); - const uint16_t this_node = address; - radio.setDataRate(dataRate); - radio.setChannel(channel); - - network.begin(/*node address*/ this_node); - thisNodeAddress = this_node; - - } - network.multicastRelay=1; + thisNodeID = mesh_nodeID; + thisNodeAddress = address; + if (meshEnable) { + // GW radio channel setting takes precedence over mesh_default_channel + if (channel == 97 && MESH_DEFAULT_CHANNEL != 97) { + channel = MESH_DEFAULT_CHANNEL; + } + + if (!thisNodeAddress && !mesh_nodeID) { + mesh.setNodeID(0); + } + else { + if (!mesh_nodeID) { + mesh_nodeID = 253; + } + mesh.setNodeID(mesh_nodeID); //Try not to conflict with any low-numbered node-ids + } + mesh.begin(channel, data_rate); + thisNodeAddress = mesh.mesh_address; + } + else { + radio.begin(); + delay(5); + const uint16_t this_node = address; + radio.setDataRate(dataRate); + radio.setChannel(channel); + + network.begin(/*node address*/ this_node); + thisNodeAddress = this_node; + } + network.multicastRelay = 1; //#if (DEBUG >= 1) - radio.printDetails(); + radio.printDetails(); //#endif - + setupSocket(); loadRoutingTable(); - - return true; + + return true; } /***************************************************************************************/ -void RF24Gateway::loadRoutingTable(){ - std::ifstream infile ("routing.txt",std::ifstream::in); - if(!infile){ return; } - +void RF24Gateway::loadRoutingTable() +{ + std::ifstream infile("routing.txt", std::ifstream::in); + if (!infile) { + return; + } + std::string str; std::string ip, mask, gw; uint16_t count = 0; std::string space = " "; - + while (std::getline(infile, str)) { size_t startLen = 0; size_t subLen = str.find(space); - if (subLen!=std::string::npos){ - ip = str.substr(0,subLen); - }else{ continue; } + if (subLen != std::string::npos) { + ip = str.substr(0, subLen); + } + else { + continue; + } startLen = subLen + 1; - subLen = str.find(space,startLen); - if (subLen!=std::string::npos){ - subLen -= (startLen); - mask = str.substr(startLen,subLen); - }else{ continue; } + subLen = str.find(space, startLen); + if (subLen != std::string::npos) { + subLen -= (startLen); + mask = str.substr(startLen, subLen); + } + else { + continue; + } startLen = startLen + subLen + 1; subLen = str.length() - (startLen); gw = str.substr(startLen, subLen); - + routingStruct[count].ip.s_addr = ntohl(inet_network(ip.c_str())); routingStruct[count].mask.s_addr = ntohl(inet_network(mask.c_str())); routingStruct[count].gw.s_addr = ntohl(inet_network(gw.c_str())); count++; - if(count >= 256){ break;} + if (count >= 256) { + break; + } } routingTableSize = count; - + //for(int i=0; i= 1 + else { + flags = IFF_TAP | IFF_NO_PI | IFF_MULTI_QUEUE; + } + tunFd = allocateTunDevice(tunName, flags, address); + #if DEBUG >= 1 if (tunFd >= 0) { - std::cout << "RF24Gw: Successfully attached to tun/tap device " << tunTapDevice << std::endl; - } else { + std::cout << "RF24Gw: Successfully attached to tun/tap device " << tunTapDevice << std::endl; + } + else { std::cerr << "RF24Gw: Error allocating tun/tap interface: " << tunFd << std::endl; exit(1); } - #endif + #endif return tunFd; } /***************************************************************************************/ -int RF24Gateway::allocateTunDevice(char *dev, int flags, uint16_t address) { +int RF24Gateway::allocateTunDevice(char *dev, int flags, uint16_t address) +{ struct ifreq ifr; int fd; - //open the device - if( (fd = open("/dev/net/tun", O_RDWR)) < 0 ) { - return fd; + //open the device + if ((fd = open("/dev/net/tun", O_RDWR)) < 0) { + return fd; } memset(&ifr, 0, sizeof(ifr)); - ifr.ifr_flags = flags; // IFF_TUN or IFF_TAP, plus maybe IFF_NO_PI + ifr.ifr_flags = flags; // IFF_TUN or IFF_TAP, plus maybe IFF_NO_PI if (*dev) { strncpy(ifr.ifr_name, dev, IFNAMSIZ); } // Create device - if(ioctl(fd, TUNSETIFF, (void *) &ifr) < 0) { + if (ioctl(fd, TUNSETIFF, (void *)&ifr) < 0) { //close(fd); - //#if (DEBUG >= 1) + //#if (DEBUG >= 1) std::cerr << "RF24Gw: Error: enabling TUNSETIFF" << std::endl; - std::cerr << "RF24Gw: If changing from TAP/TUN, run 'sudo ip link delete tun_nrf24' to remove the interface" << std::endl; + std::cerr << "RF24Gw: If changing from TAP/TUN, run 'sudo ip link delete tun_nrf24' to remove the interface" << std::endl; return -1; - //#endif + //#endif } //Make persistent - if(ioctl(fd, TUNSETPERSIST, 1) < 0){ - #if (DEBUG >= 1) + if (ioctl(fd, TUNSETPERSIST, 1) < 0) { + #if (DEBUG >= 1) std::cerr << "RF24Gw: Error: enabling TUNSETPERSIST" << std::endl; - #endif + #endif return -1; } - if(!config_TUN){ - struct sockaddr sap; - sap.sa_family = ARPHRD_ETHER; - ((char*)sap.sa_data)[4]=address; - ((char*)sap.sa_data)[5]=address>>8; - ((char*)sap.sa_data)[0]=0x52; - ((char*)sap.sa_data)[1]=0x46; - ((char*)sap.sa_data)[2]=0x32; - ((char*)sap.sa_data)[3]=0x34; - - //printf("Address 0%o first %u last %u\n",address,sap.sa_data[0],sap.sa_data[1]); - memcpy((char *) &ifr.ifr_hwaddr, (char *) &sap, sizeof(struct sockaddr)); - - if (ioctl(fd, SIOCSIFHWADDR, &ifr) < 0) { - #if DEBUG >= 1 - fprintf(stderr, "RF24Gw: Failed to set MAC address\n"); - #endif - } - } + if (!config_TUN) { + struct sockaddr sap; + sap.sa_family = ARPHRD_ETHER; + ((char *)sap.sa_data)[4] = address; + ((char *)sap.sa_data)[5] = address >> 8; + ((char *)sap.sa_data)[0] = 0x52; + ((char *)sap.sa_data)[1] = 0x46; + ((char *)sap.sa_data)[2] = 0x32; + ((char *)sap.sa_data)[3] = 0x34; + + //printf("Address 0%o first %u last %u\n",address,sap.sa_data[0],sap.sa_data[1]); + memcpy((char *)&ifr.ifr_hwaddr, (char *)&sap, sizeof(struct sockaddr)); + + if (ioctl(fd, SIOCSIFHWADDR, &ifr) < 0) { + #if DEBUG >= 1 + fprintf(stderr, "RF24Gw: Failed to set MAC address\n"); + #endif + } + } strcpy(dev, ifr.ifr_name); return fd; @@ -227,345 +241,352 @@ int RF24Gateway::allocateTunDevice(char *dev, int flags, uint16_t address) { /***************************************************************************************/ -int RF24Gateway::setIP( char *ip_addr, char *mask) { - - struct ifreq ifr; - struct sockaddr_in sin; - int sockfd = socket(AF_INET, SOCK_DGRAM, 0); - if(sockfd == -1){ - fprintf(stderr, "Could not get socket.\n"); - return -1; - } - - +int RF24Gateway::setIP(char *ip_addr, char *mask) +{ + struct ifreq ifr; + struct sockaddr_in sin; + int sockfd = socket(AF_INET, SOCK_DGRAM, 0); + if (sockfd == -1) { + fprintf(stderr, "Could not get socket.\n"); + return -1; + } + sin.sin_family = AF_INET; - //inet_aton(ip_addr,&sin.sin_addr.s_addr); - inet_aton(ip_addr,&sin.sin_addr); - strncpy(ifr.ifr_name, tunName, IFNAMSIZ); - - if (ioctl(sockfd, SIOCGIFFLAGS, &ifr) < 0) { - fprintf(stderr, "ifdown: shutdown "); - perror(ifr.ifr_name); - return -1; - } - - #ifdef ifr_flags - # define IRFFLAGS ifr_flags - #else /* Present on kFreeBSD */ - # define IRFFLAGS ifr_flagshigh - #endif + //inet_aton(ip_addr,&sin.sin_addr.s_addr); + inet_aton(ip_addr, &sin.sin_addr); + strncpy(ifr.ifr_name, tunName, IFNAMSIZ); + + if (ioctl(sockfd, SIOCGIFFLAGS, &ifr) < 0) { + fprintf(stderr, "ifdown: shutdown "); + perror(ifr.ifr_name); + return -1; + } + +#ifdef ifr_flags +#define IRFFLAGS ifr_flags +#else /* Present on kFreeBSD */ +#define IRFFLAGS ifr_flagshigh +#endif if (!(ifr.IRFFLAGS & IFF_UP)) { - //fprintf(stdout, "Device is currently down..setting up.-- %u\n",ifr.IRFFLAGS); - ifr.IRFFLAGS |= IFF_UP; - if (ioctl(sockfd, SIOCSIFFLAGS, &ifr) < 0) { - fprintf(stderr, "ifup: failed "); - perror(ifr.ifr_name); - return -1; - } - } - - memcpy(&ifr.ifr_addr, &sin, sizeof(struct sockaddr)); - - // Set interface address - if (ioctl(sockfd, SIOCSIFADDR, &ifr) < 0) { - fprintf(stderr, "Cannot set IP address. "); - perror(ifr.ifr_name); - return -1; - } - - inet_aton(mask, &sin.sin_addr); - memcpy(&ifr.ifr_addr, &sin, sizeof(struct sockaddr)); - - if (ioctl(sockfd, SIOCSIFNETMASK, &ifr) < 0) - { - fprintf(stderr,"Cannot define subnet mask for this device"); - perror(ifr.ifr_name); - return -1; - } - - #undef IRFFLAGS - return 0; + //fprintf(stdout, "Device is currently down..setting up.-- %u\n",ifr.IRFFLAGS); + ifr.IRFFLAGS |= IFF_UP; + if (ioctl(sockfd, SIOCSIFFLAGS, &ifr) < 0) { + fprintf(stderr, "ifup: failed "); + perror(ifr.ifr_name); + return -1; + } + } + + memcpy(&ifr.ifr_addr, &sin, sizeof(struct sockaddr)); + + // Set interface address + if (ioctl(sockfd, SIOCSIFADDR, &ifr) < 0) { + fprintf(stderr, "Cannot set IP address. "); + perror(ifr.ifr_name); + return -1; + } + + inet_aton(mask, &sin.sin_addr); + memcpy(&ifr.ifr_addr, &sin, sizeof(struct sockaddr)); + + if (ioctl(sockfd, SIOCSIFNETMASK, &ifr) < 0) { + fprintf(stderr, "Cannot define subnet mask for this device"); + perror(ifr.ifr_name); + return -1; + } + +#undef IRFFLAGS + return 0; } /***************************************************************************************/ -void RF24Gateway::interrupts(bool enable){ - if(enable){ - interruptsEnabled = enable; - }else{ - while(interruptInProgress){ usleep(100); } - interruptsEnabled = 0; - while(interruptInProgress){ usleep(500); } - } +void RF24Gateway::interrupts(bool enable) +{ + if (enable) { + interruptsEnabled = enable; + } + else { + while (interruptInProgress) { + usleep(100); + } + interruptsEnabled = 0; + while (interruptInProgress) { + usleep(500); + } + } } /***************************************************************************************/ -void RF24Gateway::update(bool interrupts){ - - if(interrupts){ - interruptInProgress = 1; - uint32_t intTimer = millis(); - while(!interruptsEnabled){ - usleep(750); - if(millis()-intTimer>1000){ //Wait up to 1s for interrupts to be re-enabled +void RF24Gateway::update(bool interrupts) +{ + + if (interrupts) { + interruptInProgress = 1; + uint32_t intTimer = millis(); + while (!interruptsEnabled) { + usleep(750); + if (millis() - intTimer > 1000) { //Wait up to 1s for interrupts to be re-enabled + interruptInProgress = 0; + return; + } + } + handleRadioIn(); + handleTX(); interruptInProgress = 0; - return; - } } - handleRadioIn(); - handleTX(); - interruptInProgress = 0; - }else{ - handleRadioIn(); - handleTX(); - handleRX(); - handleRadioOut(); - } + else { + handleRadioIn(); + handleTX(); + handleRX(); + handleRadioOut(); + } } /***************************************************************************************/ -void RF24Gateway::poll(uint32_t waitDelay){ +void RF24Gateway::poll(uint32_t waitDelay) +{ handleRX(waitDelay); - while(interruptInProgress){ usleep(100); } + while (interruptInProgress) { + usleep(100); + } interruptsEnabled = 0; - while(interruptInProgress){ usleep(500); } + while (interruptInProgress) { + usleep(500); + } //gateway.poll() is called manually when using interrupts, so if the radio RX buffer is full, or interrupts have been missed, check for it here. - if(radio.rxFifoFull()){ - fifoCleared=true; - handleRadioIn(); - interruptsEnabled = 1; - return; + if (radio.rxFifoFull()) { + fifoCleared = true; + handleRadioIn(); + interruptsEnabled = 1; + return; } handleRadioOut(); interruptsEnabled = 1; } /***************************************************************************************/ -void RF24Gateway::handleRadioIn(){ - - if(mesh_enabled){ - while(mesh.update()){ - if(!thisNodeAddress){ - mesh.DHCP(); +void RF24Gateway::handleRadioIn() +{ + if (mesh_enabled) { + while (mesh.update()) { + if (!thisNodeAddress) { + mesh.DHCP(); + } } - } - }else{ - while(network.update()); } - + else { + while (network.update()) {} + } + RF24NetworkFrame f; - while(network.external_queue.size() > 0 ){ - f = network.external_queue.front(); + while (network.external_queue.size() > 0) { + f = network.external_queue.front(); - msgStruct msg; + msgStruct msg; - unsigned int bytesRead = f.message_size; + unsigned int bytesRead = f.message_size; - if (bytesRead > 0) { - memcpy(&msg.message,&f.message_buffer,bytesRead); - msg.size=bytesRead; - - #if (DEBUG >= 1) - std::cout << "Radio: Received "<< bytesRead << " bytes ... " << std::endl; - #endif - #if (DEBUG >= 3) - //printPayload(msg.getPayloadStr(),"radio RX"); - std::cout << "TunRead: " << std::endl; - for(size_t i=0; i 0) { + memcpy(&msg.message, &f.message_buffer, bytesRead); + msg.size = bytesRead; - } else { - //std::cerr << "Radio: Error reading data from radio. Read '" << bytesRead << "' Bytes." << std::endl; + #if (DEBUG >= 1) + std::cout << "Radio: Received " << bytesRead << " bytes ... " << std::endl; + #endif + #if (DEBUG >= 3) + //printPayload(msg.getPayloadStr(),"radio RX"); + std::cout << "TunRead: " << std::endl; + for (size_t i = 0; i < msg.size; i++) { + //std::cout << std::hex << buffer[i]; + printf(":%0x :", msg.message[i]); } - network.external_queue.pop(); - + std::cout << std::endl; + + #endif + + rxQueue.push(msg); + } + else { + //std::cerr << "Radio: Error reading data from radio. Read '" << bytesRead << "' Bytes." << std::endl; } + network.external_queue.pop(); + } } /***************************************************************************************/ -struct in_addr RF24Gateway::getLocalIP(){ - - struct ifaddrs *ifap, *ifa; - int family,s,n; - char host[NI_MAXHOST]; - struct in_addr myNet; - - getifaddrs (&ifap); - for (ifa = ifap, n=0; ifa != NULL; ifa = ifa->ifa_next, n++) { - if ( std::string("tun_nrf24").compare(ifa->ifa_name) != 0 || ifa->ifa_addr == NULL){ - if(ifa->ifa_next == NULL ){ - break; - }else{ - continue; - } - } - - family = ifa->ifa_addr->sa_family; - - //This is an IPv4 interface, get the IP - if (family == AF_INET) { - s = getnameinfo(ifa->ifa_addr, sizeof(struct sockaddr_in), host, NI_MAXHOST, NULL, 0, NI_NUMERICHOST); - if (s == 0) { - myNet.s_addr = ntohl(inet_network(host)); - freeifaddrs(ifap); - return myNet; - } - } - } - freeifaddrs(ifap); - return myNet; +struct in_addr RF24Gateway::getLocalIP() +{ + struct ifaddrs *ifap, *ifa; + int family, s, n; + char host[NI_MAXHOST]; + struct in_addr myNet; + + getifaddrs(&ifap); + for (ifa = ifap, n = 0; ifa != NULL; ifa = ifa->ifa_next, n++) { + if (std::string("tun_nrf24").compare(ifa->ifa_name) != 0 || ifa->ifa_addr == NULL) { + if (ifa->ifa_next == NULL) { + break; + } + else { + continue; + } + } + + family = ifa->ifa_addr->sa_family; + + //This is an IPv4 interface, get the IP + if (family == AF_INET) { + s = getnameinfo(ifa->ifa_addr, sizeof(struct sockaddr_in), host, NI_MAXHOST, NULL, 0, NI_NUMERICHOST); + if (s == 0) { + myNet.s_addr = ntohl(inet_network(host)); + freeifaddrs(ifap); + return myNet; + } + } + } + freeifaddrs(ifap); + return myNet; } /***************************************************************************************/ -void RF24Gateway::handleRadioOut(){ +void RF24Gateway::handleRadioOut() +{ + bool ok = 0; - bool ok = 0; - - while(!txQueue.empty() && network.external_queue.size() == 0) { - - - msgStruct *msgTx = &txQueue.front(); + while (!txQueue.empty() && network.external_queue.size() == 0) { - #if (DEBUG >= 1) - std::cout << "Radio: Sending " << msgTx->size << " bytes ... "; - std::cout << std::endl; - #endif - #if (DEBUG >= 3) - //PrintDebug == 1 does not have an endline. - //printPayload(msg.getPayloadStr(),"radio TX"); - #endif + msgStruct *msgTx = &txQueue.front(); + + #if (DEBUG >= 1) + std::cout << "Radio: Sending " << msgTx->size << " bytes ... "; + std::cout << std::endl; + #endif + #if (DEBUG >= 3) + //PrintDebug == 1 does not have an endline. + //printPayload(msg.getPayloadStr(),"radio TX"); + #endif + + std::uint8_t *tmp = msgTx->message; + + if (!config_TUN) { //TAP can use RF24Mesh for address assignment, but will still use ARP for address resolution + + uint32_t RF24_STR = 0x34324652; //Identifies the mac as an RF24 mac + uint32_t ARP_BC = 0xFFFFFFFF; //Broadcast address + struct macStruct { + uint32_t rf24_Verification; + uint16_t rf24_Addr; + }; + + macStruct macData; + memcpy(&macData.rf24_Addr, tmp + 4, 2); + memcpy(&macData.rf24_Verification, tmp, 4); - std::uint8_t *tmp = msgTx->message; - - - if(!config_TUN ){ //TAP can use RF24Mesh for address assignment, but will still use ARP for address resolution - - uint32_t RF24_STR = 0x34324652; //Identifies the mac as an RF24 mac - uint32_t ARP_BC = 0xFFFFFFFF; //Broadcast address - struct macStruct{ - uint32_t rf24_Verification; - uint16_t rf24_Addr; - }; - - - macStruct macData; - memcpy(&macData.rf24_Addr,tmp+4,2); - memcpy(&macData.rf24_Verification,tmp,4); - - - if(macData.rf24_Verification == RF24_STR){ - const uint16_t other_node = macData.rf24_Addr; - RF24NetworkHeader header(/*to node*/ other_node, EXTERNAL_DATA_TYPE); - ok = network.write(header,&msgTx->message,msgTx->size); - - }else - if(macData.rf24_Verification == ARP_BC){ - RF24NetworkHeader header(/*to node*/ 00, EXTERNAL_DATA_TYPE); //Set to master node, will be modified by RF24Network if multi-casting - if(msgTx->size <= 42){ - if(thisNodeAddress == 00){ //Master Node - - uint32_t arp_timeout = millis(); - - ok=network.multicast(header,&msgTx->message,msgTx->size,1 ); //Send to Level 1 - while(millis() - arp_timeout < 5){network.update();} - network.multicast(header,&msgTx->message,msgTx->size,1 ); //Send to Level 1 - arp_timeout=millis(); - while(millis()- arp_timeout < 15){network.update();} - network.multicast(header,&msgTx->message,msgTx->size,1 ); //Send to Level 1 - - }else{ - - ok = network.write(header,&msgTx->message,msgTx->size); - } - } - } - }else{ // TUN always needs to use RF24Mesh for address assignment AND resolution - - uint8_t lastOctet = tmp[19]; - int16_t meshAddr; - - RF24NetworkHeader header(00, EXTERNAL_DATA_TYPE); - bool sendData = false; - - struct in_addr ipDestination; - memcpy(&ipDestination.s_addr,&tmp[16],4); - - if( (getLocalIP().s_addr & 0x00FFFFFF) == (ipDestination.s_addr & 0x00FFFFFF)){ //Is inside the RF24Mesh network - if ( (meshAddr = mesh.getAddress(lastOctet)) > 0 ) { - header.to_node = meshAddr; - sendData = true; - }else{ - if(thisNodeID > 0){//If IP is in mesh range, address lookup fails, and this is not master, - sendData = true; //send to 00 anyway in case destination is master, or the lookup just failed - } - //printf("Could not find matching mesh nodeID for IP ending in %d\n",lastOctet); - } - }else - if( thisNodeID > 0 ){ //If not master, send to master for routing etc. if target not within mesh + if (macData.rf24_Verification == RF24_STR) { + const uint16_t other_node = macData.rf24_Addr; + RF24NetworkHeader header(/*to node*/ other_node, EXTERNAL_DATA_TYPE); + ok = network.write(header, &msgTx->message, msgTx->size); + } + else if (macData.rf24_Verification == ARP_BC) { + RF24NetworkHeader header(/*to node*/ 00, EXTERNAL_DATA_TYPE); //Set to master node, will be modified by RF24Network if multi-casting + if (msgTx->size <= 42) { + if (thisNodeAddress == 00) { //Master Node + + uint32_t arp_timeout = millis(); + + ok = network.multicast(header, &msgTx->message, msgTx->size, 1); //Send to Level 1 + while (millis() - arp_timeout < 5) { + network.update(); + } + network.multicast(header, &msgTx->message, msgTx->size, 1); //Send to Level 1 + arp_timeout = millis(); + while (millis() - arp_timeout < 15) { + network.update(); + } + network.multicast(header, &msgTx->message, msgTx->size, 1); //Send to Level 1 + } + else { + ok = network.write(header, &msgTx->message, msgTx->size); + } + } + } + } + else { // TUN always needs to use RF24Mesh for address assignment AND resolution + + uint8_t lastOctet = tmp[19]; + int16_t meshAddr; + + RF24NetworkHeader header(00, EXTERNAL_DATA_TYPE); + bool sendData = false; + + struct in_addr ipDestination; + memcpy(&ipDestination.s_addr, &tmp[16], 4); + + if ((getLocalIP().s_addr & 0x00FFFFFF) == (ipDestination.s_addr & 0x00FFFFFF)) { //Is inside the RF24Mesh network + if ((meshAddr = mesh.getAddress(lastOctet)) > 0) { + header.to_node = meshAddr; + sendData = true; + } + else { + if (thisNodeID > 0) { //If IP is in mesh range, address lookup fails, and this is not master, + sendData = true; //send to 00 anyway in case destination is master, or the lookup just failed + } + //printf("Could not find matching mesh nodeID for IP ending in %d\n",lastOctet); + } + } + else if (thisNodeID > 0) { //If not master, send to master for routing etc. if target not within mesh sendData = true; - }else - if(routingTableSize > 0){ - for(int i=0; i> 24; - int16_t netAddr = 0; - if( (netAddr = mesh.getAddress(toNode)) > 0 ){ - header.to_node = netAddr; - sendData = true; - break; - } - } - } - } - - if(sendData){ + } + else if (routingTableSize > 0) { + for (int i = 0; i < routingTableSize; i++) { + struct in_addr network; + network.s_addr = routingStruct[i].ip.s_addr & routingStruct[i].mask.s_addr; + struct in_addr destNet; + destNet.s_addr = ipDestination.s_addr & routingStruct[i].mask.s_addr; + //printf("network %s destNet: %s\n",inet_ntoa(network),inet_ntoa(destNet)); + if (destNet.s_addr == network.s_addr) { + uint8_t toNode = routingStruct[i].gw.s_addr >> 24; + int16_t netAddr = 0; + if ((netAddr = mesh.getAddress(toNode)) > 0) { + header.to_node = netAddr; + sendData = true; + break; + } + } + } + } + + if (sendData) { ok = network.write(header, msgTx->message, msgTx->size); //std::cout << "SendData " << header.to_node << std::endl; - } - - - } - //delay( rf24_min(msgTx->size/48,20)); - txQueue.pop(); - - - //printf("Addr: 0%#x\n",macData.rf24_Addr); - //printf("Verif: 0%#x\n",macData.rf24_Verification); - if (ok) { - // std::cout << "ok." << std::endl; - } else { - // std::cerr << "failed." << std::endl; } - - + } + //delay( rf24_min(msgTx->size/48,20)); + txQueue.pop(); + + //printf("Addr: 0%#x\n",macData.rf24_Addr); + //printf("Verif: 0%#x\n",macData.rf24_Verification); + if (ok) { + // std::cout << "ok." << std::endl; + } + else { + // std::cerr << "failed." << std::endl; + } - } //End Tx - + } //End Tx } /***************************************************************************************/ -void RF24Gateway::handleRX(uint32_t waitDelay){ - +void RF24Gateway::handleRX(uint32_t waitDelay) +{ fd_set socketSet; struct timeval selectTimeout; uint8_t buffer[MAX_PAYLOAD_SIZE]; @@ -575,136 +596,141 @@ void RF24Gateway::handleRX(uint32_t waitDelay){ FD_SET(tunFd, &socketSet); selectTimeout.tv_sec = 0; - selectTimeout.tv_usec = waitDelay*1000; - - if (select(tunFd + 1, &socketSet, NULL, NULL,&selectTimeout) != 0) { - if (FD_ISSET(tunFd, &socketSet)) { - if ((nread = read(tunFd, buffer, MAX_PAYLOAD_SIZE)) >= 0) { + selectTimeout.tv_usec = waitDelay * 1000; - #if (DEBUG >= 1) - std::cout << "Tun: Successfully read " << nread << " bytes from tun device" << std::endl; - #endif - #if (DEBUG >= 3) - std::cout << "TunRead: " << std::endl; - for(int i=0; i= 1) - std::cerr << "Tun: Error while reading from tun/tap interface." << std::endl; - #endif - - } - } - } -} - -/***************************************************************************************/ + if (select(tunFd + 1, &socketSet, NULL, NULL, &selectTimeout) != 0) { + if (FD_ISSET(tunFd, &socketSet)) { + if ((nread = read(tunFd, buffer, MAX_PAYLOAD_SIZE)) >= 0) { - void RF24Gateway::handleTX(){ - - if(rxQueue.size() < 1){ - return; - } - msgStruct *msg = &rxQueue.front(); - - if(msg->size > MAX_PAYLOAD_SIZE){ - //printf("*****WTF OVER *****"); - rxQueue.pop(); - return; - } - - if (msg->size > 0 ) { - - size_t writtenBytes = write(tunFd, &msg->message, msg->size); - if (writtenBytes != msg->size) { - //std::cerr << "Tun: Less bytes written to tun/tap device then requested." << std::endl; - #if DEBUG >= 1 - printf("Tun: Less bytes written %d to tun/tap device then requested %d.",writtenBytes,msg->size); - #endif - - } else { #if (DEBUG >= 1) - std::cout << "Tun: Successfully wrote " << writtenBytes << " bytes to tun device" << std::endl; + std::cout << "Tun: Successfully read " << nread << " bytes from tun device" << std::endl; + #endif + #if (DEBUG >= 3) + std::cout << "TunRead: " << std::endl; + for (int i = 0; i < nread; i++) + { + printf(":%0x :", buffer[i]); + } + std::cout << std::endl; + #endif + msgStruct msg; + memcpy(&msg.message, &buffer, nread); + msg.size = nread; + if (txQueue.size() < 2) { + txQueue.push(msg); + } + else { + droppedIncoming++; + } + } + else { + #if (DEBUG >= 1) + std::cerr << "Tun: Error while reading from tun/tap interface." << std::endl; #endif } - - #if (DEBUG >= 3) - //printPayload(msg.message,"tun write"); - std::cout << "TunRead: " << std::endl; - for(size_t i=0; isize;i++){ - //printf(":%0x :",msg->message[i]); - } - std::cout << std::endl; - #endif } - - rxQueue.pop(); + } } /***************************************************************************************/ -void printPayload(std::string buffer, std::string debugMsg = "") { +void RF24Gateway::handleTX() +{ + + if (rxQueue.size() < 1) + { + return; + } + msgStruct *msg = &rxQueue.front(); -} + if (msg->size > MAX_PAYLOAD_SIZE) + { + //printf("*****WTF OVER *****"); + rxQueue.pop(); + return; + } -/***************************************************************************************/ + if (msg->size > 0) + { -void printPayload(char *buffer, int nread, std::string debugMsg = "") { + size_t writtenBytes = write(tunFd, &msg->message, msg->size); + if (writtenBytes != msg->size) + { + //std::cerr << "Tun: Less bytes written to tun/tap device then requested." << std::endl; + #if DEBUG >= 1 + printf("Tun: Less bytes written %d to tun/tap device then requested %d.", writtenBytes, msg->size); + #endif + } + else + { + #if (DEBUG >= 1) + std::cout << "Tun: Successfully wrote " << writtenBytes << " bytes to tun device" << std::endl; + #endif + } + #if (DEBUG >= 3) + //printPayload(msg.message,"tun write"); + std::cout << "TunRead: " << std::endl; + for (size_t i = 0; i < msg->size; i++) { + //printf(":%0x :",msg->message[i]); + } + std::cout << std::endl; + #endif + } + rxQueue.pop(); } /***************************************************************************************/ - -void RF24Gateway::setupSocket(){ - - int ret; - const char* myAddr = "127.0.0.1"; - - addr.sin_family = AF_INET; - ret = inet_aton(myAddr, &addr.sin_addr); - if (ret == 0) { perror("inet_aton"); exit(1); } - addr.sin_port = htons(32001); - //buf = "Hello UDP"; - s = socket(PF_INET, SOCK_DGRAM, 0); - if (s == -1) { perror("socket"); exit(1); } + +void printPayload(std::string buffer, std::string debugMsg = "") +{ } /***************************************************************************************/ -void RF24Gateway::sendUDP(uint8_t nodeID,RF24NetworkFrame frame){ - - uint8_t buffer[MAX_PAYLOAD_SIZE+11]; - - memcpy(&buffer[0], &nodeID,1); - memcpy(&buffer[1],&frame.header,8); - memcpy(&buffer[9],&frame.message_size,2); - memcpy(&buffer[11],&frame.message_buffer,frame.message_size); - - int ret = sendto(s, &buffer, frame.message_size+11, 0, (struct sockaddr *)&addr, sizeof(addr)); - if (ret == -1) { perror("sendto"); exit(1); } +void printPayload(char *buffer, int nread, std::string debugMsg = "") +{ } /***************************************************************************************/ +void RF24Gateway::setupSocket() +{ + int ret; + const char *myAddr = "127.0.0.1"; + addr.sin_family = AF_INET; + ret = inet_aton(myAddr, &addr.sin_addr); + if (ret == 0) { + perror("inet_aton"); + exit(1); + } + addr.sin_port = htons(32001); + //buf = "Hello UDP"; + s = socket(PF_INET, SOCK_DGRAM, 0); + if (s == -1) { + perror("socket"); + exit(1); + } +} +/***************************************************************************************/ +void RF24Gateway::sendUDP(uint8_t nodeID, RF24NetworkFrame frame) +{ + uint8_t buffer[MAX_PAYLOAD_SIZE + 11]; + memcpy(&buffer[0], &nodeID, 1); + memcpy(&buffer[1], &frame.header, 8); + memcpy(&buffer[9], &frame.message_size, 2); + memcpy(&buffer[11], &frame.message_buffer, frame.message_size); - - - - + int ret = sendto(s, &buffer, frame.message_size + 11, 0, (struct sockaddr *)&addr, sizeof(addr)); + if (ret == -1) + { + perror("sendto"); + exit(1); + } +} diff --git a/RF24Gateway.h b/RF24Gateway.h index 3d5a35c..e4d35c0 100644 --- a/RF24Gateway.h +++ b/RF24Gateway.h @@ -9,119 +9,118 @@ * * Class declaration for RF24Gateway */ - #include "net/if_arp.h" - #include - #include - #include - #include - #include - #include - #include - #include - #include - #include - #include - #include - #include - #include - #include - - #include - #include - #include +#include "net/if_arp.h" +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include #ifndef IFF_MULTI_QUEUE - #define IFF_MULTI_QUEUE 0x0100 + #define IFF_MULTI_QUEUE 0x0100 #endif #define DEBUG 0 #define BACKLOG 10 /* Passed to listen() */ - class RF24; - class RF24Network; - class RF24Mesh; +class RF24; +class RF24Network; +class RF24Mesh; class RF24Gateway { - /** - * @name RF24Gateway (RPi/Linux) - * - * RF24Gateway library for devices with an IP stack - */ - /**@{*/ + /** + * @name RF24Gateway (RPi/Linux) + * + * RF24Gateway library for devices with an IP stack + */ + /**@{*/ public: - /** - * RF24Gateway constructor. - */ - RF24Gateway(RF24& _radio,RF24Network& _network, RF24Mesh& _mesh); - - /** - * Begin function for use with RF24Mesh (TUN interface) - * - * @param nodeID The RF24Mesh nodeID to use - * @param channel The radio channel to use (1-127) - * @param data_rate The RF24 datarate to use (RF24_250KBPS, RF24_1MBPS, RF24_2MBPS) - * - * @code gw.begin(); //Start the gateway using RF24Mesh, with nodeID 0 (Master) @endcode - * @code uint8_t nodeID; gw.begin(nodeID); //Start the gateway using RF24Mesh, with nodeID 1 (Child node) @endcode - */ - void begin(uint8_t nodeID=0, uint8_t channel=97,rf24_datarate_e data_rate=RF24_1MBPS); - - /** - * Begin function for use with a TAP (Ethernet) interface. RF24Mesh can be used for address assignment, but - * ARP will be used to perform the lookups. - * - * @param address The RF24Network address to use - * @param channel The radio channel (0-127) to use - * @param data_rate The RF24 datarate to use (RF24_250KBPS, RF24_1MBPS, RF24_2MBPS) - * @param meshEnable Whether to use RF24Mesh for address assignment - * @param nodeID The RF24Mesh nodeID to use **if** meshEnable has been set to true - * - * @code uint16_t address=00; gw.begin(address); //Start the gateway without using RF24Mesh, with RF24Network address 00 (Master) @endcode - * @code uint16_t address=01; gw.begin(address); //Start the gateway without using RF24Mesh, with RF24Network address 01 (Child) @endcode - */ - void begin(uint16_t address, uint8_t channel=97, rf24_datarate_e data_rate=RF24_1MBPS, bool meshEnable=0, uint8_t nodeID=0 ); - - /** - * Once the Gateway has been started via begin() , call setIP to configure the IP and - * subnet mask. - * - * @param ip_addr A character array containing the numeric IP address ie: 192.168.1.1 - * @param mask A character array containing the subnet mask ie: 255.255.255.0 - * @return -1 if failed, 0 on success - */ - int setIP(char *ip_addr, char *mask); - - /** - * Calling update() keeps the network and mesh layers active and processing data. This needs to be called regularly. - * @code - * gw.update(); - * if(network.available()){ - * ...do something - * } - * @endcode - * @param interrupts Set true if called from an interrupt handler & call poll() from the main loop or a thread. - */ - void update(bool interrupts=0); - - /** - * gw.poll(); needs to be called to handle incoming data from the network interface. - * The function will perform a delayed wait of max 3ms unless otherwise specified. - * @param waitDelay How long in milliseconds this function will wait for incoming data. - */ - void poll(uint32_t waitDelay=3); - - /** - * When using interrupts (gwNodeInt, ncursesInt examples) users need to call - * this function to disable interrupts before accessing the radio and again to - * re-enable interrupts when complete - * @param enable 0 to disable interrupts and access the radio, 1 to re-enable - */ - - void interrupts(bool enable = 1); + /** + * RF24Gateway constructor. + */ + RF24Gateway(RF24& _radio,RF24Network& _network, RF24Mesh& _mesh); + + /** + * Begin function for use with RF24Mesh (TUN interface) + * + * @param nodeID The RF24Mesh nodeID to use + * @param channel The radio channel to use (1-127) + * @param data_rate The RF24 datarate to use (RF24_250KBPS, RF24_1MBPS, RF24_2MBPS) + * + * @code gw.begin(); //Start the gateway using RF24Mesh, with nodeID 0 (Master) @endcode + * @code uint8_t nodeID; gw.begin(nodeID); //Start the gateway using RF24Mesh, with nodeID 1 (Child node) @endcode + */ + void begin(uint8_t nodeID=0, uint8_t channel=97,rf24_datarate_e data_rate=RF24_1MBPS); + + /** + * Begin function for use with a TAP (Ethernet) interface. RF24Mesh can be used for address assignment, but + * ARP will be used to perform the lookups. + * + * @param address The RF24Network address to use + * @param channel The radio channel (0-127) to use + * @param data_rate The RF24 datarate to use (RF24_250KBPS, RF24_1MBPS, RF24_2MBPS) + * @param meshEnable Whether to use RF24Mesh for address assignment + * @param nodeID The RF24Mesh nodeID to use **if** meshEnable has been set to true + * + * @code uint16_t address=00; gw.begin(address); //Start the gateway without using RF24Mesh, with RF24Network address 00 (Master) @endcode + * @code uint16_t address=01; gw.begin(address); //Start the gateway without using RF24Mesh, with RF24Network address 01 (Child) @endcode + */ + void begin(uint16_t address, uint8_t channel=97, rf24_datarate_e data_rate=RF24_1MBPS, bool meshEnable=0, uint8_t nodeID=0 ); + + /** + * Once the Gateway has been started via begin() , call setIP to configure the IP and + * subnet mask. + * + * @param ip_addr A character array containing the numeric IP address ie: 192.168.1.1 + * @param mask A character array containing the subnet mask ie: 255.255.255.0 + * @return -1 if failed, 0 on success + */ + int setIP(char *ip_addr, char *mask); + + /** + * Calling update() keeps the network and mesh layers active and processing data. This needs to be called regularly. + * @code + * gw.update(); + * if(network.available()){ + * ...do something + * } + * @endcode + * @param interrupts Set true if called from an interrupt handler & call poll() from the main loop or a thread. + */ + void update(bool interrupts=0); + + /** + * gw.poll(); needs to be called to handle incoming data from the network interface. + * The function will perform a delayed wait of max 3ms unless otherwise specified. + * @param waitDelay How long in milliseconds this function will wait for incoming data. + */ + void poll(uint32_t waitDelay=3); + + /** + * When using interrupts (gwNodeInt, ncursesInt examples) users need to call + * this function to disable interrupts before accessing the radio and again to + * re-enable interrupts when complete + * @param enable 0 to disable interrupts and access the radio, 1 to re-enable + */ + void interrupts(bool enable = 1); /**@}*/ /** @@ -131,123 +130,120 @@ class RF24Gateway { */ /**@{*/ - uint16_t thisNodeAddress; /**< Address of our node in Octal format (01,021, etc) */ - uint8_t thisNodeID; /**< NodeID (0-255) */ + uint16_t thisNodeAddress; /**< Address of our node in Octal format (01,021, etc) */ + uint8_t thisNodeID; /**< NodeID (0-255) */ - bool meshEnabled(); /**< Is RF24Mesh enabled? */ - bool config_TUN; /**< Using a TAP(false) or TUN(true) interface */ - bool fifoCleared; + bool meshEnabled(); /**< Is RF24Mesh enabled? */ + bool config_TUN; /**< Using a TAP(false) or TUN(true) interface */ + bool fifoCleared; - uint32_t ifDropped(){ - return droppedIncoming; - } + uint32_t ifDropped(){ + return droppedIncoming; + } - void sendUDP(uint8_t nodeID,RF24NetworkFrame frame); + void sendUDP(uint8_t nodeID,RF24NetworkFrame frame); /**@}*/ /** * @name Routing Table * - * Utilizing a routing table to provide complete connectivity + * Utilizing a routing table to provide complete connectivity */ /**@{*/ - /** - * If a user has created a file "routing.txt" in the RF24Gateway working directory, it will be loaded
- * at startup into the routing table. The file should contain standard routing table entries as follows:
- * IPNetMaskGateway
- * ie: routing.txt - * @code - * 10.1.4.0 255.255.255.0 10.1.3.33 - * 0.0.0.0 0.0.0.0 10.1.3.34 @endcode - * - * The first example entry would route all traffic to the 10.1.4.x subnet to 10.1.3.33
- * All other traffic not destined for the RF24 nodes will use 10.1.3.34 as the gateway - * - * Data can be accessed using standard linux Internet address manipulation routines as follows: - * @code - * printf("**IP\t\tMask\t\tGateway**\n"); - * for(int i=0; i + * at startup into the routing table. The file should contain standard routing table entries as follows:
+ * IPNetMaskGateway
+ * ie: routing.txt + * @code + * 10.1.4.0 255.255.255.0 10.1.3.33 + * 0.0.0.0 0.0.0.0 10.1.3.34 @endcode + * + * The first example entry would route all traffic to the 10.1.4.x subnet to 10.1.3.33
+ * All other traffic not destined for the RF24 nodes will use 10.1.3.34 as the gateway + * + * Data can be accessed using standard linux Internet address manipulation routines as follows: + * @code + * printf("**IP\t\tMask\t\tGateway**\n"); + * for(int i=0; irxQueue; - std::queuetxQueue; + void handleRadioOut(); + void handleRadioIn(); + void handleRX(uint32_t waitDelay=0); + void handleTX(); + volatile bool interruptInProgress; + volatile bool interruptsEnabled; - void printPayload(std::string buffer, std::string debugMsg = ""); - void printPayload(char *buffer, int nread, std::string debugMsg = ""); + int configDevice(uint16_t address); + int allocateTunDevice(char *dev, int flags, uint16_t address); - int s; //Socket variable for sending UDP - void setupSocket(); - struct sockaddr_in addr; - struct in_addr getLocalIP(); + struct msgStruct{ + std::uint8_t message[MAX_PAYLOAD_SIZE]; + std::size_t size; + }; - void loadRoutingTable(); + std::queuerxQueue; + std::queuetxQueue; -}; + void printPayload(std::string buffer, std::string debugMsg = ""); + void printPayload(char *buffer, int nread, std::string debugMsg = ""); + int s; //Socket variable for sending UDP + void setupSocket(); + struct sockaddr_in addr; + struct in_addr getLocalIP(); + void loadRoutingTable(); +}; /** * @example RF24GatewayNode.cpp @@ -256,9 +252,8 @@ class RF24Gateway { * managing standard RF24Network user payloads independently. */ - /** +/** * @example RF24Gateway_ncurses.cpp - * * RF24Gateway NCurses interface - TMRh20 2015
* This is a generic tool for nodes supporting or combining with RF24Ethernet and/or RF24Network. * @@ -275,145 +270,32 @@ class RF24Gateway { * @image html ncurses.JPG */ - /** +/** * @example RF24GatewayNodeInt.cpp - * * A copy of the RF24GatewayNode example using interrupts. */ - /** +/** * @example RF24Gateway_ncursesInt.cpp - * * A copy of the ncurses example using interrupts. */ - /** @example bClient.sh - * +/** + * @example bClient.sh * Once RF24Gateway and RF24Ethernet are configured, standard tools can be used to interact with * the sensor nodes.
Example of on demand LED/Lighting control using a Bash script. */ - /** @example nodeClient.js - * +/** + * @example nodeClient.js * Once RF24Gateway and RF24Ethernet are configured, standard tools can be used to interact with * the sensor nodes.
Example of on demand LED/Lighting control using a NodeJS script. */ - /** @example pyClient.py - * +/** + * @example pyClient.py * Once RF24Gateway and RF24Ethernet are configured, standard tools can be used to interact with * the sensor nodes.
Example of scheduled LED/Lighting control using a Python script. */ -/** - * @mainpage RF24Gateway - * - * RF24Gateway is a library style replacement for the standalone RF24toTUN application, used with RF24Ethernet. - * - * In addition to passing TCP/IP payloads to a network interface, RF24Gateway also allows users to send and receive - * standard RF24Network payloads. - * - * This allows users to deploy and manage hybrid networks, consisting of nodes communicating via TCP/IP and RF24Network Messages - * - * @section Installation Installation - * - * See http://nRF24.github.io/RF24 for installation instructions using the installer, or clone the RF24 libs and run 'make install' for each one. - * - * After running the installer, RF24Gateway will be installed at rf24libs/RF24Gateway. Examples are included for operating the gateway - * as well as client scripts & programs to control nodes via http requests. - * - * Note: RF24Gateway is tested with and defaults to using RF24Mesh. Sensor nodes must also use RF24Mesh or be statically assigned within RF24Mesh. - * - * See http://nRF24.github.io/RF24Ethernet/ for related documentation for use with RF24Gateway. - * - * @section HowItWorks How It Works - * - * RF24Gateway is relatively simple in design, and uses the Universal TUN/TAP driver for Linux
- * Data incoming from the RF24 communication stack (designated as external data) is passed to the interface without modification. Conversely, incoming TCP/IP or other data - * received on the TUN/TAP interface is passed directly into the radio network and designated as external data. - * - * Linux devices running RF24Gateway can establish network links using the built-in TCP/IP stack, and users can include Arduino/AVR devices or additional RPi devices to automatically - * extend the wireless range.
- * Arduino/AVR devices, etc must utilize a software IP stack such as uIP. - * - * - * @section SimpleConfig Simple Configuration - * - * In the standard configuration, a single Linux/RF24Gateway node is used to provide connectivity to one or more - * Arduino nodes running RF24Ethernet. - * In this case the master node could be configured with IP 10.1.3.1 netmask 255.255.255.0 and nodeID 0 - * The remaining Arduino nodes can used nodeIDs 2-253, and would be assigned IP addresses 10.1.3.2-253 and netmask 255.255.255.0 - * - * If there are problems starting the examples, the following commands can be run to configure the interface: - * - * @code - * ip tuntap add dev tun_nrf24 mode tun user pi multi_queue - * ifconfig tun_nrf24 10.1.3.1/24 @endcode - * - * To enable nat and routing, the following commands can also be run: - * - * @code - * sudo sysctl -w net.ipv4.ip_forward=1 - * sudo iptables -t nat -A POSTROUTING -j MASQUERADE @endcode - * - * See http://nRF24.github.io/RF24Ethernet/ConfigAndSetup.html for more info - * - * @section AdvConfig Advanced Configuration - * - * In a more advanced configuration, users can use two or more nodes running RF24Gateway together, along with Arduino Nodes - * running RF24Ethernet - * In this case the master node could be configured differently with IP 10.1.3.1 netmask 255.255.0.0 and nodeID 0 - * The child RPi2 node could be assigned IP 10.1.3.33 netmask 255.255.0.0 and nodeID 33 - * Another device, lets say usb0 connected to the child RPi2 node is assigned IP 10.1.5.1 netmask 255.255.255.0 - * - * In this configuration, connectivity between all nodes in the mesh would be established, but a routing table is - * needed to include attached and internet devices. - * - * To fully enable routing beyond the RPi devices, a routing table needs to be added to the Master node: - * 1. Rename the file RF24Gateway/examples/routing.txx to routing.txt - * 2. Edit the file accordingly - * 3. Restart the gateway example to reload routing info - * - * @section NetCfg Network Configuration Example - * Local WiFi/Ethernet Network (Windows,Linux,RPi devices etc) - 10.10.1.0 - 255.255.255.0 ( 10.10.1.x network )
- * RPi devices (tun_nrf24 interfaces & all connected devices) - 10.1.0.0 - 255.255.0.0 ( 10.1.x.x network )
- * - * Explanation: The RF24Gateway/RF24Mesh network supports about 253 hosts. I setup the RF24Gateway and all associated - * devices with a much larger subnet in this config to encompass all devices directly accessible via the RF24Gateway network. - * - * ie: RPi master 10.1.3.1/16, RPi2 child 10.1.3.33/16, RPi2 child usb0 10.1.5.1/24 - * - * Routing Configuration: - * - * In the RF24Gateway example working directory, create a file "routing.txt"
- * Add routing entries in a standard kind of format:
- * ie: IPNetMaskGateway
- * Example routing.txt file: - * - * 10.1.5.0 255.255.255.0 10.1.3.33
- * 10.1.4.0 255.255.255.0 10.1.3.34
- * 0.0.0.0 0.0.0.0 10.10.3.33
- * - * First entry: Traffic for 10.1.5.x will use 10.1.3.33 as the gateway
- * 2nd entry: Traffic for 10.1.4.x will use 10.1.3.34 as the gateway
- * 3rd entry: Traffic not in the RF24Gateway network will be sent via 10.10.3.33 by default - * - * Additional Routing Configuration:
- * You can specify any combination of IP/Netmask in the routing.txt file to create unique subnets for routing traffic: - * - * 10.1.5.0 255.255.255.224 10.1.3.33
- * 10.1.5.32 255.255.255.224 10.1.3.34
- * 10.1.5.64 255.255.255.224 10.1.3.35
- * 0.0.0.0 0.0.0.0 10.10.3.32
- * - * First entry: Traffic for 10.1.5.(1-30) will use 10.1.3.33 as the gateway
- * 2nd entry: Traffic for 10.1.5.(33-62) will use 10.1.3.34 as the gateway
- * 3rd entry: Traffic for 10.1.5.(65-94) will use 10.1.3.35 as the gateway
- * 3rd entry: Traffic not in the RF24Gateway network will be sent via 10.10.3.32 by default
- * - * - * - */ - - - #endif \ No newline at end of file +#endif \ No newline at end of file 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/main_page.md b/docs/main_page.md new file mode 100644 index 0000000..bc90e86 --- /dev/null +++ b/docs/main_page.md @@ -0,0 +1,117 @@ +# RF24Gateway +RF24Gateway is a library style replacement for the standalone RF24toTUN application, used with RF24Ethernet. + +In addition to passing TCP/IP payloads to a network interface, RF24Gateway also allows users to send and receive +standard RF24Network payloads. + +This allows users to deploy and manage hybrid networks, consisting of nodes communicating via TCP/IP and RF24Network Messages + +## Installation +See http://nRF24.github.io/RF24 for installation instructions using the installer, or clone the RF24 libs and run 'make install' for each one. + +After running the installer, RF24Gateway will be installed at rf24libs/RF24Gateway. [**Examples**](examples.html) are included for operating the gateway +as well as client scripts & programs to control nodes via http requests. + +Note: RF24Gateway is tested with and defaults to using RF24Mesh. Sensor nodes must also use RF24Mesh or be statically assigned within RF24Mesh. + +See http://nRF24.github.io/RF24Ethernet/ for related documentation for use with RF24Gateway. + +## How It Works +RF24Gateway is relatively simple in design, and uses the [Universal TUN/TAP driver for Linux](https://www.kernel.org/doc/Documentation/networking/tuntap.txt) + +Data incoming from the RF24 communication stack (designated as external data) is passed to the interface without modification. Conversely, incoming TCP/IP or other data +received on the TUN/TAP interface is passed directly into the radio network and designated as external data. + +Linux devices running RF24Gateway can establish network links using the built-in TCP/IP stack, and users can include Arduino/AVR devices or additional RPi devices to automatically +extend the wireless range.
+Arduino/AVR devices, etc must utilize a software IP stack such as uIP. + +## Simple Configuration +In the standard configuration, a single Linux/RF24Gateway node is used to provide connectivity to one or more +Arduino nodes running RF24Ethernet. +In this case the master node could be configured with IP 10.1.3.1 netmask 255.255.255.0 and nodeID 0 +The remaining Arduino nodes can used nodeIDs 2-253, and would be assigned IP addresses 10.1.3.2-253 and netmask 255.255.255.0 + +If there are problems starting the examples, the following commands can be run to configure the interface: + +```shell +ip tuntap add dev tun_nrf24 mode tun user pi multi_queue +ifconfig tun_nrf24 10.1.3.1/24 +``` + +To enable nat and routing, the following commands can also be run: + +```shell +sudo sysctl -w net.ipv4.ip_forward=1 +sudo iptables -t nat -A POSTROUTING -j MASQUERADE +``` + +See http://nRF24.github.io/RF24Ethernet/ConfigAndSetup.html for more info + +## Advanced Configuration +In a more advanced configuration, users can use two or more nodes running RF24Gateway together, along with Arduino Nodes +running RF24Ethernet +In this case the master node could be configured differently with IP 10.1.3.1 netmask 255.255.0.0 and nodeID 0 +The child RPi2 node could be assigned IP 10.1.3.33 netmask 255.255.0.0 and nodeID 33 +Another device, lets say usb0 connected to the child RPi2 node is assigned IP 10.1.5.1 netmask 255.255.255.0 + +In this configuration, connectivity between all nodes in the mesh would be established, but a routing table is +needed to include attached and internet devices. + +To fully enable routing beyond the RPi devices, a routing table needs to be added to the Master node: +1. Rename the file RF24Gateway/examples/routing.txx to routing.txt +2. Edit the file accordingly +3. Restart the gateway example to reload routing info + +## Network Configuration Example +Local WiFi/Ethernet Network (Windows,Linux,RPi devices etc) - 10.10.1.0 - 255.255.255.0 ( 10.10.1.x network )
+RPi devices (tun_nrf24 interfaces & all connected devices) - 10.1.0.0 - 255.255.0.0 ( 10.1.x.x network ) + +### Explanation +The RF24Gateway/RF24Mesh network supports about 253 hosts. I setup the RF24Gateway and all associated +devices with a much larger subnet in this config to encompass all devices directly accessible via the RF24Gateway network. + +ie: RPi master 10.1.3.1/16, RPi2 child 10.1.3.33/16, RPi2 child usb0 10.1.5.1/24 + +### Routing Configuration +In the RF24Gateway example working directory, create a file "routing.txt"
+Add routing entries in a standard kind of format: +```text +IPNetMaskGateway +``` +Example routing.txt file: + +- Traffic for 10.1.5.x will use 10.1.3.33 as the gateway + ```text + 10.1.5.0 255.255.255.0 10.1.3.33 + ``` +- Traffic for 10.1.4.x will use 10.1.3.34 as the gateway + ```text + 10.1.4.0 255.255.255.0 10.1.3.34 + ``` +- Traffic not in the RF24Gateway network will be sent via 10.10.3.33 by default + ```text + 0.0.0.0 0.0.0.0 10.10.3.33 + ``` + +#### Additional Routing Configuration +You can specify any combination of IP/Netmask in the routing.txt file to create unique subnets for routing traffic. + +Examples are: + +- Traffic for 10.1.5.(1-30) will use 10.1.3.33 as the gateway + ```text + 10.1.5.0 255.255.255.224 10.1.3.33 + ``` +- Traffic for 10.1.5.(33-62) will use 10.1.3.34 as the gateway + ```text + 10.1.5.32 255.255.255.224 10.1.3.34 + ``` +- Traffic for 10.1.5.(65-94) will use 10.1.3.35 as the gateway + ```text + 10.1.5.64 255.255.255.224 10.1.3.35 + ``` +- Traffic not in the RF24Gateway network will be sent via 10.10.3.32 by default + ```text + 0.0.0.0 0.0.0.0 10.10.3.32 + ``` diff --git a/examples/addons/RF24Network.lua b/examples/addons/RF24Network.lua index 9364a8f..b609a9c 100644 --- a/examples/addons/RF24Network.lua +++ b/examples/addons/RF24Network.lua @@ -1,11 +1,10 @@ - -- RF24Network LUA dissector for Wireshark -- Usage: 1. Start wireshark on the host machine running RF24Gateway -- 2. Use the command `wireshark -X lua_script:RF24Network.lua` -- 3. In filters, add '!icmp' and apply -- 4. RF24Network user payloads show as Protocol: RF24Net & header information is displayed -rf24network_proto = Proto("rf24network","RF24Network Protocol") +rf24network_proto = Proto("rf24network", "RF24Network Protocol") rf24network_proto.fields.nodeID = ProtoField.uint8("rf24network.nodeID", "Mesh Node", base.DEC) rf24network_proto.fields.from = ProtoField.uint16("rf24network.from", "Network from Node", base.OCT) @@ -15,37 +14,35 @@ rf24network_proto.fields.type = ProtoField.uint8("rf24network.type", "Header Typ rf24network_proto.fields.reserved = ProtoField.uint8("rf24network.reserved", "Header Reserved", base.DEC) rf24network_proto.fields.pSize = ProtoField.uint16("rf24network.payloadSize", "Payload Size", base.DEC) - rf24network_proto.fields.uint16_t = ProtoField.uint32("rf24network.uint16", "16-bit unsigned:", base.DEC) rf24network_proto.fields.int16_t = ProtoField.int32("rf24network.int16", "16-bit signed", base.DEC) rf24network_proto.fields.uint32_t = ProtoField.uint32("rf24network.uint32", "32-bit unsigned", base.DEC) rf24network_proto.fields.int32_t = ProtoField.uint32("rf24network.int32", "32-bit signed", base.DEC) - -function rf24network_proto.dissector(buffer,pinfo,tree) +function rf24network_proto.dissector(buffer, pinfo, tree) pinfo.cols.protocol = "RF24Net" - local subtree = tree:add_le(rf24network_proto,buffer(),"RF24Network Header") - if(buffer:len() >= 11) then - subtree:add(rf24network_proto.fields.nodeID,buffer(0,1)) - subtree:add_le(rf24network_proto.fields.from,buffer(1,2)) - subtree:add_le(rf24network_proto.fields.to,buffer(3,2)) - subtree:add_le(rf24network_proto.fields.hID,buffer(5,2)) - subtree:add(rf24network_proto.fields.type,buffer(7,1)) - subtree:add(rf24network_proto.fields.reserved,buffer(8,1)) - subtree:add_le(rf24network_proto.fields.pSize,buffer(9,2)) - end - subtree:add_le(buffer(11,pSize),"Data(HEX) " .. buffer(11,pSize)) - - local subtree = tree:add_le(rf24network_proto,buffer(),"Decode Payload (First Bytes Only)") + local subtree = tree:add_le(rf24network_proto, buffer(), "RF24Network Header") + if (buffer:len() >= 11) then + subtree:add(rf24network_proto.fields.nodeID, buffer(0, 1)) + subtree:add_le(rf24network_proto.fields.from, buffer(1, 2)) + subtree:add_le(rf24network_proto.fields.to, buffer(3, 2)) + subtree:add_le(rf24network_proto.fields.hID, buffer(5, 2)) + subtree:add(rf24network_proto.fields.type, buffer(7, 1)) + subtree:add(rf24network_proto.fields.reserved, buffer(8, 1)) + subtree:add_le(rf24network_proto.fields.pSize, buffer(9, 2)) + end + subtree:add_le(buffer(11, pSize), "Data(HEX) " .. buffer(11, pSize)) + + local subtree = tree:add_le(rf24network_proto, buffer(), "Decode Payload (First Bytes Only)") if buffer:len() >= 13 then - subtree:add_le(rf24network_proto.fields.uint16_t,buffer(11,2)) - subtree:add_le(rf24network_proto.fields.int16_t,buffer(11,2)) + subtree:add_le(rf24network_proto.fields.uint16_t, buffer(11, 2)) + subtree:add_le(rf24network_proto.fields.int16_t, buffer(11, 2)) end if buffer:len() >= 15 then - subtree:add_le(rf24network_proto.fields.uint32_t,buffer(11,4)) - subtree:add_le(rf24network_proto.fields.int32_t,buffer(11,4)) + subtree:add_le(rf24network_proto.fields.uint32_t, buffer(11, 4)) + subtree:add_le(rf24network_proto.fields.int32_t, buffer(11, 4)) end end udp_table = DissectorTable.get("udp.port") -udp_table:add(32001,rf24network_proto) \ No newline at end of file +udp_table:add(32001, rf24network_proto) diff --git a/examples/addons/mqttLogger.py b/examples/addons/mqttLogger.py index afb4223..d653ac3 100644 --- a/examples/addons/mqttLogger.py +++ b/examples/addons/mqttLogger.py @@ -1,43 +1,41 @@ -# Note: This code requires paho-mqtt -# sudo pip-install paho-mqtt +""" +.. note:: + This code requires paho-mqtt. Install this library with -# Simple MQTT data logger, listens for UDP output from RF24Gateway & logs to an MQTT topic -# For use with RF24Mesh nodes that are not able to communicate directly via TCP/IP etc -# See RF24Gateway examples: -# RF24NetworkFrame frame = RF24NetworkFrame(header,buf,size); -# gw.sendUDP(mesh.getNodeID(header.from_node),frame); -# + sudo pip3 install paho-mqtt -# -*- coding: utf-8 -*- +Simple MQTT data logger, listens for UDP output from RF24Gateway & logs to an MQTT topic +For use with RF24Mesh nodes that are not able to communicate directly via TCP/IP etc +See RF24Gateway examples: + RF24NetworkFrame frame = RF24NetworkFrame(header,buf,size); + gw.sendUDP(mesh.getNodeID(header.from_node),frame); +""" import paho.mqtt.client as mqtt import socket import sys -reload(sys) -sys.setdefaultencoding('utf8') - ### Setup the MQTT host IP & topic to publish to mqttHost = "10.10.2.2" -topic = 'data/RF24' +topic = "data/RF24" ### Bind to UDP port 32001 (default port of RF24Gateway UDP output) sock = socket.socket(socket.AF_INET, socket.SOCK_DGRAM) -server_address = ('localhost', 32001) -print >>sys.stderr, 'Waiting for UDP message on %s port %s\n' % server_address +server_address = ("localhost", 32001) +print("Waiting for UDP message on {} port {}" % server_address) sock.bind(server_address) while True: data, address = sock.recvfrom(2048) - - print >>sys.stderr, 'received %s bytes from %s' % (len(data), address) - print >>sys.stderr, data - + + print("received {} bytes from {}".format(len(data), address)) + print(data) + if data: - ## Just log the entire chunk of data to MQTT for now - ## Todo: Sort, Display and Analyze the data + # Just log the entire chunk of data to MQTT for now + # TODO: Sort, Display and Analyze the data mqttc = mqtt.Client() mqttc.connect(mqttHost, 1883) - data = unicode(data, errors='replace') + data = unicode(data, errors="replace") mqttc.publish(topic, data) mqttc.loop(2) \ No newline at end of file diff --git a/examples/clients/BashClient/readme.md b/examples/clients/BashClient/readme.md index 2acc192..c481740 100644 --- a/examples/clients/BashClient/readme.md +++ b/examples/clients/BashClient/readme.md @@ -3,10 +3,16 @@ bClient.sh example for use with RF24Ethernet/RF24Gateway Once RF24Gateway and RF24Ethernet are configured, standard tools can be used to interact with the sensor nodes. -This is a simple example demonstrating how to connect directly to a sensor node running one of the +This is a simple example demonstrating how to connect directly to a sensor node running one of the included server examples via a bash script and control LEDs/lighting. Usage: -1. Edit bClient.sh and configure the options -2. Run sudo ./bClient.sh ie: ./bClient.sh 10.10.2.4 ON - +1. Edit _bClient.sh_ and configure the options +2. Run + ```shell + sudo ./bClient.sh + ``` + ie: + ```shell + sudo ./bClient.sh 10.10.2.4 ON + ``` diff --git a/examples/clients/NodeJSClient/nodeClient.js b/examples/clients/NodeJSClient/nodeClient.js index 5eb2bc0..026c883 100644 --- a/examples/clients/NodeJSClient/nodeClient.js +++ b/examples/clients/NodeJSClient/nodeClient.js @@ -1,20 +1,18 @@ - - var request = require('request') var url = 'http://10.10.2.4:1000/ON' // input your url here /ON to turn on and /OFF to turn off // use a timeout value of 10 seconds -var timeoutInMilliseconds = 10*1000 +var timeoutInMilliseconds = 10 * 1000 var opts = { - url: url, - timeout: timeoutInMilliseconds + url: url, + timeout: timeoutInMilliseconds } request(opts, function (err, res, body) { - if (err) { - console.dir(err) - return - } - var statusCode = res.statusCode - console.log('status code: ' + statusCode) + if (err) { + console.dir(err) + return + } + var statusCode = res.statusCode + console.log('status code: ' + statusCode) }) \ No newline at end of file diff --git a/examples/clients/NodeJSClient/readme.md b/examples/clients/NodeJSClient/readme.md index 1bacd40..99c6c90 100644 --- a/examples/clients/NodeJSClient/readme.md +++ b/examples/clients/NodeJSClient/readme.md @@ -3,12 +3,21 @@ nodeClient.js example for use with RF24Ethernet/RF24Gateway Once RF24Gateway and RF24Ethernet are configured, standard tools can be used to interact with the sensor nodes. -This is a simple example demonstrating how to connect directly to a sensor node running one of the +This is a simple example demonstrating how to connect directly to a sensor node running one of the included server examples via a NodeJS script and control LEDs/lighting. Usage: -1. a: Edit nodeClient.js and configure the URL( Sensor IP, page to request (OFF,ON) - b: From the example directory, run ```npm install request``` -2. Run ```node nodeClient.js``` -3. Status code: 200 indicates success +1. Edit nodeClient.js and configure the URL + ```text + :/ + ``` +2. From the example directory, run + ```shell + npm install request + ``` +3. Run + ```shell + node nodeClient.js + ``` +Note: The status code `200` indicates success diff --git a/examples/clients/PythonClient/pyClient.py b/examples/clients/PythonClient/pyClient.py index 79a4769..e49d19c 100644 --- a/examples/clients/PythonClient/pyClient.py +++ b/examples/clients/PythonClient/pyClient.py @@ -1,9 +1,9 @@ #!/usr/bin/env python -# -# TMRh20 - 2015 -# A simple example of controlling a RF24Ethernet based sensor node via a python script -# Turn a light on in the evening and off in the morning according to a schedule -# +""" +TMRh20 - 2015 +A simple example of controlling a RF24Ethernet based sensor node via a python script +Turn a light on in the evening and off in the morning according to a schedule +""" import urllib2 from datetime import datetime @@ -12,62 +12,63 @@ ######### Configuration ######### -scheduleON = 21 #The hour (24hr clock) to turn the system on (21:00) -scheduleOFF = 6 #The hour (24hr clock) to turn the system off (06:00) -sensorIP = "10.10.2.4" #The IP of a sensor node running one of the server examples +scheduleON = 21 # The hour (24hr clock) to turn the system on (21:00) +scheduleOFF = 6 # The hour (24hr clock) to turn the system off (06:00) +sensorIP = "10.10.2.4" # The IP of a sensor node running one of the server examples ################################# requestON = "http://" + sensorIP + ":1000/ON" requestOFF = "http://" + sensorIP + ":1000/OFF" lightState = 2 - + while 1: - #Get the current hour + # Get the current hour currentHour = datetime.now().hour - #Check to see if the system should be off + # Check to see if the system should be off if (currentHour >= scheduleON or currentHour < scheduleOFF) and lightState != 1: - - result = 0; - #Connect to our sensor at 10.10.3.44:1000/ and request OFF + + result = 0 + # Connect to our sensor at 10.10.3.44:1000/ and request OFF try: - response = urllib2.urlopen(requestOFF,None,15) #15 second time-out + response = urllib2.urlopen(requestOFF, None, 15) # 15 second time-out result = response.getcode() except urllib2.HTTPError, e: - syslog.syslog('HTTPError = ' + str(e.code)) + syslog.syslog("HTTPError = " + str(e.code)) except urllib2.URLError, e: - syslog.syslog('URLError = ' + str(e.reason)) + syslog.syslog("URLError = " + str(e.reason)) except Exception: import traceback - syslog.syslog('generic exception: ' + traceback.format_exc()) - #Log errors and successful results to /var/log/syslog + + syslog.syslog("generic exception: " + traceback.format_exc()) + # Log errors and successful results to /var/log/syslog if result == 200: - syslog.syslog( "Light off at %s\n" % datetime.now()) - #Only change the light state if successful + syslog.syslog("Light off at %s\n" % datetime.now()) + # Only change the light state if successful lightState = 1 - #Else, check to see if the system should be on + # Else, check to see if the system should be on elif currentHour >= scheduleOFF and lightState != 0: - result = 0; + result = 0 try: - response = urllib2.urlopen(requestON,None,15) #15 second time-out + response = urllib2.urlopen(requestON, None, 15) # 15 second time-out result = response.getcode() except urllib2.HTTPError, e: - syslog.syslog('HTTPError = ' + str(e.code)) + syslog.syslog("HTTPError = " + str(e.code)) except urllib2.URLError, e: - syslog.syslog('URLError = ' + str(e.reason)) + syslog.syslog("URLError = " + str(e.reason)) except Exception: import traceback - syslog.syslog('generic exception: ' + traceback.format_exc()) - #Log errors and successful results to /var/log/syslog - if result == 200: + + syslog.syslog("generic exception: " + traceback.format_exc()) + # Log errors and successful results to /var/log/syslog + if result == 200: syslog.syslog("Light on at %s\n" % datetime.now()) - #Only change the light state if successful + # Only change the light state if successful lightState = 0 - - #Wait 1 minute between retries and status checks + + # Wait 1 minute between retries and status checks time.sleep(60) - diff --git a/examples/clients/PythonClient/readme.md b/examples/clients/PythonClient/readme.md index a0d3e8e..0177c9b 100644 --- a/examples/clients/PythonClient/readme.md +++ b/examples/clients/PythonClient/readme.md @@ -3,10 +3,17 @@ pyClient.py example for use with RF24Ethernet/RF24Gateway Once RF24Gateway and RF24Ethernet are configured, standard tools can be used to interact with the sensor nodes. -This is a simple example demonstrating how to connect directly to a sensor node running one of the +This is a simple example demonstrating how to connect directly to a sensor node running one of the included server examples via python and control LEDs/lighting. Usage: -1. Configure the schedule and IP of the sensor by editing pyClient.py -2. Run sudo ./pyClient.py -3. Run ' cat /var/log/syslog | grep pyClient.py ' to view the output +1. Configure the schedule and IP of the sensor by editing _pyClient.py_ +2. Run + ```shell + sudo ./pyClient.py + ``` +3. Run + ```shell + cat /var/log/syslog | grep pyClient.py + ``` + to view the output