Andrew Lindsay / Mbed 2 deprecated IoTGateway_Basic

Dependencies:   NetServices FatFileSystem csv_parser mbed MQTTClient RF12B DNSResolver SDFileSystem

Embed: (wiki syntax)

« Back to documentation index

Show/hide line numbers main.cpp Source File

main.cpp

00001 /** IoT Gateway main code
00002  *
00003  * @author Andrew Lindsay
00004  *
00005  * @section LICENSE
00006  *
00007  * Copyright (c) 2012 Andrew Lindsay (andrew [at] thiseldo [dot] co [dot] uk)
00008  *
00009  * Permission is hereby granted, free of charge, to any person obtaining a copy
00010  * of this software and associated documentation files (the "Software"), to deal
00011  * in the Software without restriction, including without limitation the rights
00012  * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
00013  * copies of the Software, and to permit persons to whom the Software is
00014  * furnished to do so, subject to the following conditions:
00015 
00016  * The above copyright notice and this permission notice shall be included in
00017  * all copies or substantial portions of the Software.
00018  *
00019  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
00020  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
00021  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
00022  * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
00023  * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
00024  * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
00025  * THE SOFTWARE.
00026  *
00027  * @section DESCRIPTION
00028  *
00029  * Code is to be classed as beta. There is a lot of debug code still includes
00030  * to dump heap sizes and other values. It is still a work in progress and
00031  * should be treated as such.
00032  *
00033  * Further documentation available from
00034  * http://blog.thiseldo.co.uk/wp-filez/IoTGateway.pdf
00035  *
00036  * Sample configuration file IOTSETUP.TXT
00037  *
00038  * @code
00039  * ip.mode=fixed
00040  * ip.address=192.168.1.99
00041  * ip.netmask=255.255.255.0
00042  * ip.gateway=192.168.1.1
00043  * ip.dns=192.168.1.1
00044  * rfm12b.band=868
00045  * rfm12b.id=30
00046  * rfm12b.group=212
00047  * time.host=0.uk.pool.ntp.org
00048  * time.timezone=GMT
00049  * time.dst=yes
00050  * pachube.key=***your Pachube api key***
00051  * pachube.apiurl=http://api.pachube.com/v2/feeds/%d.csv?_method=PUT
00052  * emoncms.key=***your emonCms api key***
00053  * emoncms.apiurl=http://your.host.com/emoncms/api/post?apikey=%s&json=
00054  * sense.key=***your Sen.se api key***
00055  * sense.apiurl=http://api.sen.se/events/?sense_key=%s
00056  * mqtt.host=
00057  * mqtt.port=1883
00058  * mqtt.username=
00059  * mqtt.password=
00060  * @endcode
00061  *
00062  * Some values are not yet used
00063  *
00064  */
00065 
00066 #include "iotgateway.h"
00067 #include "mbed.h"
00068 #include <ctype.h>
00069 #include "SDFileSystem.h"
00070 #include "EthernetNetIf.h"
00071 #include "NTPClient.h"
00072 #include "dnsresolve.h"
00073 #include "RF12B.h"
00074 #include "IoTRouting.h"
00075 
00076 using std::string;
00077 
00078 #undef DEBUG 
00079 
00080 #define VERSION_INFO "IoT Gateway Basic - Version 0.8"
00081 
00082 DigitalOut heartbeatLED(LED1, "heartbeatLED");
00083 DigitalOut led2(LED2, "led2");
00084 DigitalOut led3(LED3, "led3");
00085 //DigitalOut led4(LED4, "led4");
00086 DigitalOut linkLED(p30, "linkLED");
00087 DigitalOut statusLED(p25, "statusLED");
00088 
00089 // Put as much as we can into RAM bank AHBSRAM0 which is reserved for USB that we are not using
00090 
00091 // Setup which filesystem to use, Local or uSD card, both use same name
00092 //__attribute((section("AHBSRAM0"))) LocalFileSystem fs("iotfs");
00093 __attribute((section("AHBSRAM0"))) SDFileSystem sd(p5, p6, p7, p8, "iotfs");
00094 
00095 __attribute((section("AHBSRAM0"))) EthernetNetIf *eth;
00096 __attribute((section("AHBSRAM0"))) NTPClient ntp;
00097 __attribute((section("AHBSRAM0"))) Ethernet ethernet;
00098 __attribute((section("AHBSRAM0"))) DNSResolver resolver;
00099 
00100 // Configuration values loaded from file iotsetup.dat
00101 __attribute((section("AHBSRAM0"))) IpAddr ipAddress(0, 0, 0, 0);
00102 __attribute((section("AHBSRAM0"))) IpAddr netMask(255, 255, 255, 0);
00103 __attribute((section("AHBSRAM0"))) IpAddr gwAddress(0, 0, 0, 0);
00104 __attribute((section("AHBSRAM0"))) IpAddr dnsAddress(0, 0, 0, 0);
00105 __attribute((section("AHBSRAM0"))) bool useDHCP = false;
00106 
00107 // Static buffers
00108 __attribute((section("AHBSRAM0"))) static char lineBuf[MAX_LINE_LENGTH];
00109 __attribute((section("AHBSRAM0"))) static OutputPachube outPachube;
00110 __attribute((section("AHBSRAM0"))) static OutputEmonCms outEmonCms;
00111 __attribute((section("AHBSRAM0"))) static OutputSenSe outSenSe;
00112 __attribute((section("AHBSRAM0"))) static IoTRouting rtr;
00113 
00114 // Pachube config
00115 __attribute((section("AHBSRAM0"))) char pachubeApiUrl[API_URL_LENGTH];
00116 __attribute((section("AHBSRAM0"))) char pachubeApiKey[API_KEY_LENGTH];
00117 __attribute((section("AHBSRAM0"))) char pachubeDataBuffer[DATABUF_SIZE];
00118 
00119 // MQTT config
00120 __attribute((section("AHBSRAM0"))) IpAddr mqttHostAddress( 0, 0, 0, 0);
00121 __attribute((section("AHBSRAM0"))) short mqttPort;
00122 __attribute((section("AHBSRAM0"))) char mqttUsername[MAX_LINE_LENGTH];
00123 __attribute((section("AHBSRAM0"))) char mqttPassword[MAX_LINE_LENGTH];
00124 __attribute((section("AHBSRAM0"))) bool useMQTT = false;
00125 
00126 //char mqttHostName[65];
00127 
00128 // Open energy Monitor emonCMS config
00129 __attribute((section("AHBSRAM0"))) char emonCmsApiUrl[API_URL_LENGTH];
00130 __attribute((section("AHBSRAM0"))) char emonCmsApiKey[API_KEY_LENGTH];
00131 __attribute((section("AHBSRAM0"))) char emonCmsDataBuffer[DATABUF_SIZE];
00132 
00133 // Open energy Monitor Sen.Se config
00134 __attribute((section("AHBSRAM0"))) char senSeApiUrl[API_URL_LENGTH];
00135 __attribute((section("AHBSRAM0"))) char senSeApiKey[API_KEY_LENGTH];
00136 __attribute((section("AHBSRAM0"))) char senSeDataBuffer[DATABUF_SIZE];
00137 
00138 // Time server config
00139 __attribute((section("AHBSRAM0"))) char ntpHost[MAX_LINE_LENGTH] = "0.uk.pool.ntp.org";
00140 
00141 // RFM12B config
00142 __attribute((section("AHBSRAM0"))) static string rfm12bBands[4] = {"xxx", "433", "868", "915" };
00143 __attribute((section("AHBSRAM0"))) static uint8_t rfm12bId;
00144 __attribute((section("AHBSRAM0"))) static uint8_t rfm12bBand;
00145 __attribute((section("AHBSRAM0"))) static uint8_t rfm12bGroup;
00146 
00147 #define iotConfigFile "/iotfs/IOTSETUP.TXT"
00148 
00149 __attribute((section("AHBSRAM0"))) RF12B rfm12b(p11, p12, p13, p14, p18);
00150 __attribute((section("AHBSRAM0"))) Serial pc(USBTX, USBRX); // tx, rx
00151 
00152 // Utility functions
00153 
00154 /** convert string to IP address
00155  *
00156  * @param ipAddrInt  IP address as single 32bit integer
00157  * @param value      The IP address as a string
00158  */
00159 void setIpAddress( int *ipAddrInt, char *value ) {
00160     sscanf(value, "%d.%d.%d.%d", &ipAddrInt[0],&ipAddrInt[1],&ipAddrInt[2],&ipAddrInt[3]);
00161 }
00162 
00163 /** Get the value from a name=value pair
00164  *
00165  * @param buf  The name/value pair character buffer
00166  * @returns pointer to value
00167  */
00168 char *getConfigValue( char *buf ) {
00169     char *ptr = strchr(buf, '=');
00170     if ( ptr == NULL )
00171         return NULL;
00172     ptr++;
00173     return ptr;
00174 }
00175 
00176 /** Copy zero or CR/LF terminated string to new zero terminated string
00177  * Used when reading config values from files to remove CR/LF endings
00178  *
00179  * @param to   Char pointer to destination
00180  * @param from Char pointer to source
00181  */
00182 void strcpynull(char *to, char *from ) {
00183     while ( *from != '\n' && *from != '\r' && *from != '\0' ) {
00184         *to++ = *from++;
00185     }
00186     *to = '\0';
00187 }
00188 
00189 /** Trim a string in buffer, remove leading and trailing spaces
00190  *
00191  */
00192 char *trim(char *str) {
00193     size_t len = 0;
00194     char *frontp = str - 1;
00195     char *endp = NULL;
00196 
00197     if ( str == NULL )
00198         return NULL;
00199 
00200     if ( str[0] == '\0' )
00201         return str;
00202 
00203     len = strlen(str);
00204     endp = str + len;
00205 
00206     /* Move the front and back pointers to address
00207      * the first non-whitespace characters from
00208      * each end.
00209      */
00210     while ( isspace(*(++frontp)) );
00211     while ( isspace(*(--endp)) && endp != frontp );
00212 
00213 //    while( *(++frontp) == ' ' );
00214 //    while( (*(--endp) == ' ') && endp != frontp );
00215 
00216     if ( str + len - 1 != endp )
00217         *(endp + 1) = '\0';
00218     else if ( frontp != str &&  endp == frontp )
00219         *str = '\0';
00220 
00221     /* Shift the string so that it starts at str so
00222      * that if it's dynamically allocated, we can
00223      * still free it on the returned pointer.  Note
00224      * the reuse of endp to mean the front of the
00225      * string buffer now.
00226      */
00227     endp = str;
00228     if ( frontp != str ) {
00229         while ( *frontp ) *endp++ = *frontp++;
00230         *endp = '\0';
00231     }
00232 
00233 
00234     return str;
00235 }
00236 
00237 /** Read IoT gateway configuration file
00238  * File is of format name=value
00239  *
00240  */
00241 bool readConfig() {
00242 
00243     FILE *fp = fopen(iotConfigFile, "r");
00244     if (fp == NULL) {
00245         printf("Could not open file %s for read\n", iotConfigFile);
00246         return false;
00247     }
00248     // read file
00249     while (!feof( fp )) {
00250         fgets(lineBuf,MAX_LINE_LENGTH,fp);
00251 //        printf("[%s] ",lineBuf);
00252         trim( lineBuf );
00253 //        printf("[%s]\n", lineBuf);
00254 
00255         // Need to read each entry and update config
00256         char *nameStr;
00257         char *valueStr;
00258         nameStr = lineBuf;
00259         valueStr = strchr( lineBuf, '=' );
00260         if ( valueStr != NULL ) {
00261             *valueStr++ = '\0';
00262             int tmpAddress[4] = {0,0,0,0};
00263             if ( strcmp( nameStr, "ip.address" ) == 0 ) {
00264                 setIpAddress( &tmpAddress[0], valueStr );
00265                 ipAddress = IpAddr( tmpAddress[0],tmpAddress[1],tmpAddress[2],tmpAddress[3]);
00266 
00267             } else if ( strcmp( nameStr, "ip.netmask" ) == 0 ) {
00268                 setIpAddress( &tmpAddress[0], valueStr );
00269                 netMask = IpAddr( tmpAddress[0],tmpAddress[1],tmpAddress[2],tmpAddress[3]);
00270 
00271             } else if ( strcmp( nameStr, "ip.gateway" ) == 0 ) {
00272                 setIpAddress( &tmpAddress[0], valueStr );
00273                 gwAddress = IpAddr( tmpAddress[0],tmpAddress[1],tmpAddress[2],tmpAddress[3]);
00274 
00275             } else if ( strcmp( nameStr, "ip.dns" ) == 0 ) {
00276                 setIpAddress( &tmpAddress[0], valueStr );
00277                 dnsAddress = IpAddr( tmpAddress[0],tmpAddress[1],tmpAddress[2],tmpAddress[3]);
00278 
00279             }  else if ( strcmp( nameStr, "ip.mode" ) == 0 ) {
00280                 useDHCP = (strncmp( valueStr, "dhcp", 4) == 0 ? true : false);
00281 
00282             }  else if ( strcmp( nameStr, "time.host" ) == 0 ) {
00283                 strcpynull(ntpHost, valueStr );
00284 
00285             }  else if ( strcmp( nameStr, "pachube.apiurl" ) == 0 ) {
00286                 strcpynull(pachubeApiUrl, valueStr );
00287 
00288             }  else if ( strcmp( nameStr, "pachube.key" ) == 0 ) {
00289                 strcpynull(pachubeApiKey, valueStr );
00290 
00291             }  else if ( strcmp( nameStr, "emoncms.apiurl" ) == 0 ) {
00292                 strcpynull(emonCmsApiUrl, valueStr );
00293 
00294             }  else if ( strcmp( nameStr, "emoncms.key" ) == 0 ) {
00295                 strcpynull(emonCmsApiKey, valueStr );
00296 
00297             }  else if ( strcmp( nameStr, "sense.apiurl" ) == 0 ) {
00298                 strcpynull(senSeApiUrl, valueStr );
00299 
00300             }  else if ( strcmp( nameStr, "sense.key" ) == 0 ) {
00301                 strcpynull(senSeApiKey, valueStr );
00302             } else if ( strcmp( nameStr, "mqtt.host" ) == 0 ) {
00303                 setIpAddress( &tmpAddress[0], valueStr );
00304                 mqttHostAddress = IpAddr( tmpAddress[0],tmpAddress[1],tmpAddress[2],tmpAddress[3]);
00305 
00306             } else if ( strcmp( nameStr, "mqtt.port" ) == 0 ) {
00307                 mqttPort = atoi( valueStr );
00308 
00309             }  else if ( strcmp( nameStr, "mqtt.username" ) == 0 ) {
00310                 strcpynull(mqttUsername, valueStr );
00311 
00312             }  else if ( strcmp( nameStr, "mqtt.password" ) == 0 ) {
00313                 strcpynull(mqttPassword, valueStr );
00314 
00315             }  else if ( strcmp( nameStr, "rfm12b.band" ) == 0 ) {
00316                 if ( strncmp( valueStr, "433", 3 ) == 0 )
00317                     rfm12bBand = RF12_433MHZ;
00318                 else if ( strncmp( valueStr, "868", 3 ) == 0 )
00319                     rfm12bBand = RF12_868MHZ;
00320                 else if ( strncmp( valueStr, "915", 3 ) == 0 )
00321                     rfm12bBand = RF12_915MHZ;
00322 
00323             }  else if ( strcmp( nameStr, "rfm12b.id" ) == 0 ) {
00324                 rfm12bId = atoi( valueStr );
00325             }  else if ( strcmp( nameStr, "rfm12b.group" ) == 0 ) {
00326                 rfm12bGroup = atoi( valueStr );
00327             }
00328         }
00329     }
00330     fclose(fp);
00331 
00332     return true;
00333 }
00334 
00335 /** Write the current config to file
00336  */
00337 bool writeConfig() {
00338 
00339 // Doesnt work?
00340     // Rename original file
00341 //    if( rename ( iotConfigFile.c_str(), iotConfigFileBak.c_str() ) != 0 ) {
00342 //        printf("Could not rename file %s\n", iotConfigFile);
00343 //        return false;
00344 //    }
00345 
00346     FILE *fp = fopen(iotConfigFile, "w");
00347     if (fp == NULL) {
00348         printf("Could not open file %s for write\n", iotConfigFile);
00349         return false;
00350     }
00351 
00352     time_t ctTime;
00353     ctTime = time(NULL);
00354 
00355     fprintf(fp, "# iotsetup created (UTC) %s\n", ctime(&ctTime));
00356     fprintf(fp, "ip.mode=%s\n", (useDHCP ? "dhcp" : "fixed") );
00357     // Add msg to say net config being ignored
00358     if ( useDHCP )
00359         fprintf(fp, "# Following ip.* parameters not used in DHCP mode\n");
00360 
00361     fprintf(fp, "ip.address=%hhu.%hhu.%hhu.%hhu\n", ipAddress[0], ipAddress[1],ipAddress[2],ipAddress[3]);
00362     fprintf(fp, "ip.netmask=%hhu.%hhu.%hhu.%hhu\n",netMask[0], netMask[1], netMask[2], netMask[3]);
00363     fprintf(fp, "ip.gateway=%hhu.%hhu.%hhu.%hhu\n",gwAddress[0],gwAddress[1],gwAddress[2],gwAddress[3]);
00364     fprintf(fp, "ip.dns=%hhu.%hhu.%hhu.%hhu\n",dnsAddress[0],dnsAddress[1],dnsAddress[2],dnsAddress[3]);
00365 
00366     fprintf(fp, "rfm12b.band=%s\n",rfm12bBands[rfm12bBand].c_str());
00367     fprintf(fp, "rfm12b.id=%d\n",rfm12bId);
00368     fprintf(fp, "rfm12b.group=%d\n",rfm12bGroup);
00369 
00370     fprintf(fp, "time.timezone=GMT\n");
00371     fprintf(fp, "time.dst=yes\n");
00372 
00373     fprintf(fp, "pachube.key=%s\n", pachubeApiKey );
00374 
00375     fprintf(fp, "mqtt.host=%hhu.%hhu.%hhu.%hhu\n",mqttHostAddress[0],mqttHostAddress[1],mqttHostAddress[2],mqttHostAddress[3]);
00376     fprintf(fp, "mqtt.port=%d\n",mqttPort);
00377     fprintf(fp, "mqtt.username=%s\n", mqttUsername );
00378     fprintf(fp, "mqtt.password=%s\n", mqttPassword );
00379 
00380     fclose(fp);
00381 
00382     return true;
00383 }
00384 
00385 
00386 // These external symbols are maintained by the linker to indicate the
00387 // location of various regions in the device's memory.  They will be used by
00388 // DisplayRAMBanks() to dump the size of each RAM bank to stdout.
00389 extern unsigned int Image$$RW_IRAM1$$Base;
00390 extern unsigned int Image$$RW_IRAM1$$ZI$$Limit;
00391 extern unsigned int Image$$RW_IRAM2$$Base;
00392 extern unsigned int Image$$RW_IRAM2$$ZI$$Limit;
00393 extern unsigned int Image$$RW_IRAM3$$Base;
00394 extern unsigned int Image$$RW_IRAM3$$ZI$$Limit;
00395 
00396 //#ifdef DEBUG
00397 // Displays the size of static allocations for each RAM bank as indicated by
00398 // ARM linker to stdout.
00399 static void DisplayRAMBanks(void) {
00400     printf("Static RAM bank allocations\r\n");
00401     printf("  Main RAM = %u\r\n", (unsigned int)&Image$$RW_IRAM1$$ZI$$Limit -
00402            (unsigned int)&Image$$RW_IRAM1$$Base);
00403     printf("  RAM0     = %u\r\n", (unsigned int)&Image$$RW_IRAM2$$ZI$$Limit -
00404            (unsigned int)&Image$$RW_IRAM2$$Base);
00405     printf("  RAM1     = %u\r\n", (unsigned int)&Image$$RW_IRAM3$$ZI$$Limit -
00406            (unsigned int)&Image$$RW_IRAM3$$Base);
00407 }
00408 //#endif
00409 
00410 /** Main function, where all the magic starts
00411  */
00412 int main() {
00413     linkLED = 1;
00414     statusLED = 0;
00415     pc.baud(115200);
00416 
00417     printf(VERSION_INFO);
00418     printf("\n");
00419     DisplayRAMBanks();
00420 #ifdef DEBUG
00421 
00422     printf("Setting up...\n");
00423     printf("\nHEAP STATS\n");
00424     __heapstats((__heapprt)fprintf,stderr);
00425 #endif
00426 
00427     if ( !readConfig() ) {
00428         error("Setup failed");
00429     }
00430 
00431     if (useDHCP) {
00432         printf("Using DHCP\n");
00433         eth = new EthernetNetIf( "IoTGateway" );
00434     } else {
00435 //        printf("Using Fixed addressing\n");
00436         eth = new EthernetNetIf( ipAddress, netMask, gwAddress, dnsAddress );
00437     }
00438     EthernetErr ethErr = eth->setup();
00439     if (ethErr) {
00440         printf("Error %d in setup.\n", ethErr);
00441         return -1;
00442     }
00443 
00444     linkLED = !ethernet.link();
00445 
00446     if (useDHCP) {
00447         // We are using dhcp so get IP Address
00448         ipAddress = eth->getIp();
00449     }
00450 
00451     // Get Current time
00452     Host server(IpAddr(), 123, ntpHost);    // "0.uk.pool.ntp.org");
00453     ntp.setTime(server);
00454 
00455     time_t ctTime = time(NULL);
00456     printf("\nTime is now (UTC): %s\n", ctime(&ctTime));
00457 
00458     // If Pachube API Key defined, set up output module
00459     if ( strlen(pachubeApiKey) > 0 ) {
00460         outPachube = OutputPachube( pachubeDataBuffer, pachubeApiUrl, pachubeApiKey );
00461 //        outPachube.setApiKey( pachubeApiKey );
00462 //        printf("MAIN: outPachube = %ld\n",(int)&outPachube);
00463         rtr.addOutput( (OutputDef*)&outPachube , OUTPUT_TYPE_PACHUBE);
00464     }
00465 
00466     // If emonCms API Key defined, set up output module
00467     if ( strlen(emonCmsApiKey) > 0 ) {
00468         outEmonCms = OutputEmonCms( emonCmsDataBuffer, emonCmsApiUrl, emonCmsApiKey );
00469         rtr.addOutput( (OutputDef*)&outEmonCms , OUTPUT_TYPE_EMONCMS);
00470     }
00471 
00472     // If Sen.se API Key defined, set up output module
00473     if ( strlen(senSeApiKey) > 0 ) {
00474         outSenSe = OutputSenSe( senSeDataBuffer, senSeApiUrl, senSeApiKey );
00475         rtr.addOutput( (OutputDef*)&outSenSe , OUTPUT_TYPE_SENSE);
00476     }
00477 
00478     //mqttHostAddress = IpAddr(192,168,1,77);
00479     OutputMqtt outMqtt = OutputMqtt();
00480 //    mqttHostAddress = resolver.resolveName("api.pachube.com");
00481     // Only use MQTT is we have a host IP address
00482     if ( mqttHostAddress[0] > 0 && mqttHostAddress[3] > 0 ) {
00483         outMqtt.initConnection( &mqttHostAddress, mqttPort, mqttUsername, mqttPassword );
00484         //( &serverIpAddr );
00485         useMQTT = outMqtt.init();
00486 
00487         if ( useMQTT )
00488             rtr.addOutput( (OutputDef*)&outMqtt , OUTPUT_TYPE_MQTT);
00489     }
00490 
00491     rtr.initRouting();
00492 #ifdef DEBUG
00493     printf("Setup OK\n");
00494 
00495     printf( "Setting RFM12B ID %d, Band %d Group %d\n",rfm12bId, rfm12bBand, rfm12bGroup);
00496 #endif
00497 
00498     rfm12b.init(rfm12bId, rfm12bBand, rfm12bGroup );   //id = 2, band 866, group 5
00499 
00500 //    printf("Listening...\n");
00501 
00502     Timer tm;
00503     tm.start();
00504 #ifdef DEBUG
00505     printf("\nHEAP STATS\n");
00506     __heapstats((__heapprt)fprintf,stderr);
00507 #endif
00508 
00509     short dataLen = 0;
00510     uint8_t *rf12Buf;
00511 
00512     // Start receiving data
00513     rfm12b.rf12_recvStart();
00514     while (true) {
00515         Net::poll();
00516 
00517         // This is RFM12B specific
00518         if ( rfm12b.available() > 0 ) {
00519             statusLED = 1;
00520             rf12Buf =  rfm12b.get_data();
00521             dataLen = rfm12b.length();
00522 
00523             if ( rtr.routePayload( rf12Buf, dataLen + 3 ) ) {
00524                 // Successfully dealt with a packet
00525 
00526                 // Do something different if routed
00527 
00528             }
00529 
00530             // For now, acknowledge everything
00531 
00532             // Send an ack if required
00533             if ((rf12Buf[1] & ~RF12_HDR_MASK) == RF12_HDR_ACK // &&
00534                     //(config.nodeId & 0x20) == 0
00535                ) {
00536 #ifdef DEBUG
00537                 printf("RFM12B -> ack\n");
00538 #endif
00539                 byte addr = rf12Buf[1] & RF12_HDR_MASK;
00540                 rfm12b.rf12_sendStart(RF12_HDR_CTL | RF12_HDR_DST | addr, 0, 1);
00541             }
00542 
00543             statusLED = 0;
00544         }
00545 
00546         if (tm.read()>.5) {
00547             heartbeatLED=!heartbeatLED; //Show that we are alive
00548             tm.start();
00549         }
00550 
00551         // If using mqtt then send heartbeat
00552         if (useMQTT) {
00553             outMqtt.send();     // Used for heartbeat/keepalive packet
00554         }
00555 
00556         linkLED = !ethernet.link();
00557 
00558     }
00559 
00560 }
00561 
00562 // The End!