mbed based IoT Gateway More details http://blog.thiseldo.co.uk/wp-filez/IoTGateway.pdf

Dependencies:   NetServices FatFileSystem csv_parser mbed MQTTClient RF12B DNSResolver SDFileSystem

Committer:
SomeRandomBloke
Date:
Fri Apr 20 19:32:34 2012 +0000
Revision:
3:f19f9c62c00b
Parent:
2:27714c8c9c0a
Child:
4:d460406ac780

        

Who changed what in which revision?

UserRevisionLine numberNew contents of line
SomeRandomBloke 0:a29a0225f203 1 /** IoT Gateway main code
SomeRandomBloke 0:a29a0225f203 2 *
SomeRandomBloke 0:a29a0225f203 3 * @author Andrew Lindsay
SomeRandomBloke 0:a29a0225f203 4 *
SomeRandomBloke 0:a29a0225f203 5 * @section LICENSE
SomeRandomBloke 0:a29a0225f203 6 *
SomeRandomBloke 0:a29a0225f203 7 * Copyright (c) 2012 Andrew Lindsay (andrew [at] thiseldo [dot] co [dot] uk)
SomeRandomBloke 0:a29a0225f203 8 *
SomeRandomBloke 0:a29a0225f203 9 * Permission is hereby granted, free of charge, to any person obtaining a copy
SomeRandomBloke 0:a29a0225f203 10 * of this software and associated documentation files (the "Software"), to deal
SomeRandomBloke 0:a29a0225f203 11 * in the Software without restriction, including without limitation the rights
SomeRandomBloke 0:a29a0225f203 12 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
SomeRandomBloke 0:a29a0225f203 13 * copies of the Software, and to permit persons to whom the Software is
SomeRandomBloke 0:a29a0225f203 14 * furnished to do so, subject to the following conditions:
SomeRandomBloke 0:a29a0225f203 15
SomeRandomBloke 0:a29a0225f203 16 * The above copyright notice and this permission notice shall be included in
SomeRandomBloke 0:a29a0225f203 17 * all copies or substantial portions of the Software.
SomeRandomBloke 0:a29a0225f203 18 *
SomeRandomBloke 0:a29a0225f203 19 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
SomeRandomBloke 0:a29a0225f203 20 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
SomeRandomBloke 0:a29a0225f203 21 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
SomeRandomBloke 0:a29a0225f203 22 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
SomeRandomBloke 0:a29a0225f203 23 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
SomeRandomBloke 0:a29a0225f203 24 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
SomeRandomBloke 0:a29a0225f203 25 * THE SOFTWARE.
SomeRandomBloke 0:a29a0225f203 26 *
SomeRandomBloke 0:a29a0225f203 27 * @section DESCRIPTION
SomeRandomBloke 0:a29a0225f203 28 *
SomeRandomBloke 0:a29a0225f203 29 * Code is to be classed as beta. There is a lot of debug code still includes
SomeRandomBloke 0:a29a0225f203 30 * to dump heap sizes and other values. It is still a work in progress and
SomeRandomBloke 0:a29a0225f203 31 * should be treated as such.
SomeRandomBloke 3:f19f9c62c00b 32 *
SomeRandomBloke 3:f19f9c62c00b 33 * Further documentation available from
SomeRandomBloke 2:27714c8c9c0a 34 * http://blog.thiseldo.co.uk/wp-filez/IoTGateway.pdf
SomeRandomBloke 0:a29a0225f203 35 *
SomeRandomBloke 0:a29a0225f203 36 * Sample configuration file IOTSETUP.TXT
SomeRandomBloke 0:a29a0225f203 37 *
SomeRandomBloke 0:a29a0225f203 38 * @code
SomeRandomBloke 0:a29a0225f203 39 * pachube.key=***your pachube api key***
SomeRandomBloke 0:a29a0225f203 40 * ip.mode=fixed
SomeRandomBloke 0:a29a0225f203 41 * ip.address=192.168.1.99
SomeRandomBloke 0:a29a0225f203 42 * ip.netmask=255.255.255.0
SomeRandomBloke 0:a29a0225f203 43 * ip.gateway=192.168.1.1
SomeRandomBloke 0:a29a0225f203 44 * ip.dns=192.168.1.1
SomeRandomBloke 0:a29a0225f203 45 * rfm12b.band=868
SomeRandomBloke 0:a29a0225f203 46 * rfm12b.id=30
SomeRandomBloke 0:a29a0225f203 47 * rfm12b.group=212
SomeRandomBloke 3:f19f9c62c00b 48 * time.host=0.uk.pool.ntp.org
SomeRandomBloke 0:a29a0225f203 49 * time.timezone=GMT
SomeRandomBloke 0:a29a0225f203 50 * time.dst=yes
SomeRandomBloke 0:a29a0225f203 51 * mqtt.host=
SomeRandomBloke 2:27714c8c9c0a 52 * mqtt.port=1883
SomeRandomBloke 2:27714c8c9c0a 53 * mqtt.username=
SomeRandomBloke 2:27714c8c9c0a 54 * mqtt.password=
SomeRandomBloke 0:a29a0225f203 55 * @endcode
SomeRandomBloke 0:a29a0225f203 56 *
SomeRandomBloke 0:a29a0225f203 57 * Some values are not yet used
SomeRandomBloke 0:a29a0225f203 58 *
SomeRandomBloke 0:a29a0225f203 59 */
SomeRandomBloke 0:a29a0225f203 60
SomeRandomBloke 0:a29a0225f203 61
SomeRandomBloke 0:a29a0225f203 62 #include "mbed.h"
SomeRandomBloke 3:f19f9c62c00b 63 #include <ctype.h>
SomeRandomBloke 0:a29a0225f203 64 #include "SDFileSystem.h"
SomeRandomBloke 0:a29a0225f203 65 #include "EthernetNetIf.h"
SomeRandomBloke 0:a29a0225f203 66 #include "NTPClient.h"
SomeRandomBloke 2:27714c8c9c0a 67 #include "dnsresolve.h"
SomeRandomBloke 0:a29a0225f203 68 #include "RF12B.h"
SomeRandomBloke 0:a29a0225f203 69 #include "IoTRouting.h"
SomeRandomBloke 0:a29a0225f203 70
SomeRandomBloke 0:a29a0225f203 71 using std::string;
SomeRandomBloke 0:a29a0225f203 72
SomeRandomBloke 3:f19f9c62c00b 73 #define VERSION_INFO "IoT Gateway Basic - Version 0.6-BETA "
SomeRandomBloke 0:a29a0225f203 74
SomeRandomBloke 0:a29a0225f203 75 DigitalOut heartbeatLED(LED1, "heartbeatLED");
SomeRandomBloke 0:a29a0225f203 76 DigitalOut led2(LED2, "led2");
SomeRandomBloke 0:a29a0225f203 77 DigitalOut led3(LED3, "led3");
SomeRandomBloke 0:a29a0225f203 78 //DigitalOut led4(LED4, "led4");
SomeRandomBloke 0:a29a0225f203 79 DigitalOut linkLED(p30, "linkLED");
SomeRandomBloke 0:a29a0225f203 80 DigitalOut statusLED(p25, "statusLED");
SomeRandomBloke 0:a29a0225f203 81
SomeRandomBloke 2:27714c8c9c0a 82 // Put as much as we can into RAM bank AHBSRAM0 which is reserved for USB that we are not using
SomeRandomBloke 2:27714c8c9c0a 83
SomeRandomBloke 2:27714c8c9c0a 84 // Setup which filesystem to use, Local or uSD card, both use same name
SomeRandomBloke 0:a29a0225f203 85 __attribute((section("AHBSRAM0"))) LocalFileSystem fs("iotfs");
SomeRandomBloke 0:a29a0225f203 86 //__attribute((section("AHBSRAM0"))) SDFileSystem sd(p5, p6, p7, p8, "iotfs");
SomeRandomBloke 0:a29a0225f203 87
SomeRandomBloke 0:a29a0225f203 88 __attribute((section("AHBSRAM0"))) EthernetNetIf *eth;
SomeRandomBloke 0:a29a0225f203 89 __attribute((section("AHBSRAM0"))) NTPClient ntp;
SomeRandomBloke 0:a29a0225f203 90 __attribute((section("AHBSRAM0"))) Ethernet ethernet;
SomeRandomBloke 2:27714c8c9c0a 91 __attribute((section("AHBSRAM0"))) DNSResolver resolver;
SomeRandomBloke 0:a29a0225f203 92
SomeRandomBloke 0:a29a0225f203 93 // Configuration values loaded from file iotsetup.dat
SomeRandomBloke 0:a29a0225f203 94 __attribute((section("AHBSRAM0"))) IpAddr ipAddress(0, 0, 0, 0);
SomeRandomBloke 0:a29a0225f203 95 __attribute((section("AHBSRAM0"))) IpAddr netMask(255, 255, 255, 0);
SomeRandomBloke 0:a29a0225f203 96 __attribute((section("AHBSRAM0"))) IpAddr gwAddress(0, 0, 0, 0);
SomeRandomBloke 0:a29a0225f203 97 __attribute((section("AHBSRAM0"))) IpAddr dnsAddress(0, 0, 0, 0);
SomeRandomBloke 0:a29a0225f203 98 __attribute((section("AHBSRAM0"))) bool useDHCP = false;
SomeRandomBloke 0:a29a0225f203 99
SomeRandomBloke 0:a29a0225f203 100 // Static buffers
SomeRandomBloke 0:a29a0225f203 101 #define MAX_LINE_LENGTH 128
SomeRandomBloke 2:27714c8c9c0a 102 __attribute((section("AHBSRAM0"))) static char lineBuf[MAX_LINE_LENGTH];
SomeRandomBloke 2:27714c8c9c0a 103 __attribute((section("AHBSRAM0"))) static OutputPachube outPachube;
SomeRandomBloke 2:27714c8c9c0a 104 __attribute((section("AHBSRAM0"))) static IoTRouting rtr;
SomeRandomBloke 0:a29a0225f203 105
SomeRandomBloke 0:a29a0225f203 106 // Pachube config
SomeRandomBloke 3:f19f9c62c00b 107 __attribute((section("AHBSRAM0"))) char pachubeApiKey[65];
SomeRandomBloke 0:a29a0225f203 108
SomeRandomBloke 0:a29a0225f203 109 // MQTT config
SomeRandomBloke 3:f19f9c62c00b 110 __attribute((section("AHBSRAM0"))) IpAddr mqttHostAddress( 0, 0, 0, 0);
SomeRandomBloke 2:27714c8c9c0a 111 __attribute((section("AHBSRAM0"))) short mqttPort;
SomeRandomBloke 3:f19f9c62c00b 112 __attribute((section("AHBSRAM0"))) char mqttUsername[MAX_LINE_LENGTH];
SomeRandomBloke 3:f19f9c62c00b 113 __attribute((section("AHBSRAM0"))) char mqttPassword[MAX_LINE_LENGTH];
SomeRandomBloke 2:27714c8c9c0a 114 __attribute((section("AHBSRAM0"))) bool useMQTT = false;
SomeRandomBloke 2:27714c8c9c0a 115
SomeRandomBloke 0:a29a0225f203 116 //char mqttHostName[65];
SomeRandomBloke 0:a29a0225f203 117
SomeRandomBloke 3:f19f9c62c00b 118 // Time server config
SomeRandomBloke 3:f19f9c62c00b 119 __attribute((section("AHBSRAM0"))) char ntpHost[MAX_LINE_LENGTH] = "0.uk.pool.ntp.org";
SomeRandomBloke 3:f19f9c62c00b 120
SomeRandomBloke 0:a29a0225f203 121
SomeRandomBloke 0:a29a0225f203 122 // RFM12B config
SomeRandomBloke 0:a29a0225f203 123 __attribute((section("AHBSRAM0"))) static string rfm12bBands[4] = {"xxx", "433", "868", "915" };
SomeRandomBloke 2:27714c8c9c0a 124 __attribute((section("AHBSRAM0"))) static uint8_t rfm12bId;
SomeRandomBloke 2:27714c8c9c0a 125 __attribute((section("AHBSRAM0"))) static uint8_t rfm12bBand;
SomeRandomBloke 2:27714c8c9c0a 126 __attribute((section("AHBSRAM0"))) static uint8_t rfm12bGroup;
SomeRandomBloke 0:a29a0225f203 127
SomeRandomBloke 0:a29a0225f203 128 #define iotConfigFile "/iotfs/IOTSETUP.TXT"
SomeRandomBloke 2:27714c8c9c0a 129
SomeRandomBloke 0:a29a0225f203 130 __attribute((section("AHBSRAM0"))) RF12B rfm12b(p11, p12, p13, p14, p18);
SomeRandomBloke 0:a29a0225f203 131 __attribute((section("AHBSRAM0"))) Serial pc(USBTX, USBRX); // tx, rx
SomeRandomBloke 0:a29a0225f203 132
SomeRandomBloke 0:a29a0225f203 133 // Utility functions
SomeRandomBloke 0:a29a0225f203 134
SomeRandomBloke 0:a29a0225f203 135 /** convert string to IP address
SomeRandomBloke 0:a29a0225f203 136 *
SomeRandomBloke 0:a29a0225f203 137 * @param ipAddrInt IP address as single 32bit integer
SomeRandomBloke 0:a29a0225f203 138 * @param value The IP address as a string
SomeRandomBloke 0:a29a0225f203 139 */
SomeRandomBloke 0:a29a0225f203 140 void setIpAddress( int *ipAddrInt, char *value ) {
SomeRandomBloke 0:a29a0225f203 141 sscanf(value, "%d.%d.%d.%d", &ipAddrInt[0],&ipAddrInt[1],&ipAddrInt[2],&ipAddrInt[3]);
SomeRandomBloke 0:a29a0225f203 142 }
SomeRandomBloke 0:a29a0225f203 143
SomeRandomBloke 0:a29a0225f203 144 /** Get the value from a name=value pair
SomeRandomBloke 0:a29a0225f203 145 *
SomeRandomBloke 0:a29a0225f203 146 * @param buf The name/value pair character buffer
SomeRandomBloke 0:a29a0225f203 147 * @returns pointer to value
SomeRandomBloke 0:a29a0225f203 148 */
SomeRandomBloke 0:a29a0225f203 149 char *getConfigValue( char *buf ) {
SomeRandomBloke 0:a29a0225f203 150 char *ptr = strchr(buf, '=');
SomeRandomBloke 0:a29a0225f203 151 if ( ptr == NULL )
SomeRandomBloke 0:a29a0225f203 152 return NULL;
SomeRandomBloke 0:a29a0225f203 153 ptr++;
SomeRandomBloke 0:a29a0225f203 154 return ptr;
SomeRandomBloke 0:a29a0225f203 155 }
SomeRandomBloke 0:a29a0225f203 156
SomeRandomBloke 0:a29a0225f203 157 /** Copy zero or CR/LF terminated string to new zero terminated string
SomeRandomBloke 0:a29a0225f203 158 * Used when reading config values from files to remove CR/LF endings
SomeRandomBloke 0:a29a0225f203 159 *
SomeRandomBloke 0:a29a0225f203 160 * @param to Char pointer to destination
SomeRandomBloke 0:a29a0225f203 161 * @param from Char pointer to source
SomeRandomBloke 0:a29a0225f203 162 */
SomeRandomBloke 0:a29a0225f203 163 void strcpynull(char *to, char *from ) {
SomeRandomBloke 0:a29a0225f203 164 while ( *from != '\n' && *from != '\r' && *from != '\0' ) {
SomeRandomBloke 0:a29a0225f203 165 *to++ = *from++;
SomeRandomBloke 0:a29a0225f203 166 }
SomeRandomBloke 0:a29a0225f203 167 *to = '\0';
SomeRandomBloke 0:a29a0225f203 168 }
SomeRandomBloke 0:a29a0225f203 169
SomeRandomBloke 3:f19f9c62c00b 170 /** Trim a string in buffer, remove leading and trailing spaces
SomeRandomBloke 3:f19f9c62c00b 171 *
SomeRandomBloke 3:f19f9c62c00b 172 */
SomeRandomBloke 3:f19f9c62c00b 173 char *trim(char *str) {
SomeRandomBloke 3:f19f9c62c00b 174 size_t len = 0;
SomeRandomBloke 3:f19f9c62c00b 175 char *frontp = str - 1;
SomeRandomBloke 3:f19f9c62c00b 176 char *endp = NULL;
SomeRandomBloke 3:f19f9c62c00b 177
SomeRandomBloke 3:f19f9c62c00b 178 if ( str == NULL )
SomeRandomBloke 3:f19f9c62c00b 179 return NULL;
SomeRandomBloke 3:f19f9c62c00b 180
SomeRandomBloke 3:f19f9c62c00b 181 if ( str[0] == '\0' )
SomeRandomBloke 3:f19f9c62c00b 182 return str;
SomeRandomBloke 3:f19f9c62c00b 183
SomeRandomBloke 3:f19f9c62c00b 184 len = strlen(str);
SomeRandomBloke 3:f19f9c62c00b 185 endp = str + len;
SomeRandomBloke 3:f19f9c62c00b 186
SomeRandomBloke 3:f19f9c62c00b 187 /* Move the front and back pointers to address
SomeRandomBloke 3:f19f9c62c00b 188 * the first non-whitespace characters from
SomeRandomBloke 3:f19f9c62c00b 189 * each end.
SomeRandomBloke 3:f19f9c62c00b 190 */
SomeRandomBloke 3:f19f9c62c00b 191 while ( isspace(*(++frontp)) );
SomeRandomBloke 3:f19f9c62c00b 192 while ( isspace(*(--endp)) && endp != frontp );
SomeRandomBloke 3:f19f9c62c00b 193
SomeRandomBloke 3:f19f9c62c00b 194 // while( *(++frontp) == ' ' );
SomeRandomBloke 3:f19f9c62c00b 195 // while( (*(--endp) == ' ') && endp != frontp );
SomeRandomBloke 3:f19f9c62c00b 196
SomeRandomBloke 3:f19f9c62c00b 197 if ( str + len - 1 != endp )
SomeRandomBloke 3:f19f9c62c00b 198 *(endp + 1) = '\0';
SomeRandomBloke 3:f19f9c62c00b 199 else if ( frontp != str && endp == frontp )
SomeRandomBloke 3:f19f9c62c00b 200 *str = '\0';
SomeRandomBloke 3:f19f9c62c00b 201
SomeRandomBloke 3:f19f9c62c00b 202 /* Shift the string so that it starts at str so
SomeRandomBloke 3:f19f9c62c00b 203 * that if it's dynamically allocated, we can
SomeRandomBloke 3:f19f9c62c00b 204 * still free it on the returned pointer. Note
SomeRandomBloke 3:f19f9c62c00b 205 * the reuse of endp to mean the front of the
SomeRandomBloke 3:f19f9c62c00b 206 * string buffer now.
SomeRandomBloke 3:f19f9c62c00b 207 */
SomeRandomBloke 3:f19f9c62c00b 208 endp = str;
SomeRandomBloke 3:f19f9c62c00b 209 if ( frontp != str ) {
SomeRandomBloke 3:f19f9c62c00b 210 while ( *frontp ) *endp++ = *frontp++;
SomeRandomBloke 3:f19f9c62c00b 211 *endp = '\0';
SomeRandomBloke 3:f19f9c62c00b 212 }
SomeRandomBloke 3:f19f9c62c00b 213
SomeRandomBloke 3:f19f9c62c00b 214
SomeRandomBloke 3:f19f9c62c00b 215 return str;
SomeRandomBloke 3:f19f9c62c00b 216 }
SomeRandomBloke 0:a29a0225f203 217
SomeRandomBloke 0:a29a0225f203 218 /** Read IoT gateway configuration file
SomeRandomBloke 0:a29a0225f203 219 * File is of format name=value
SomeRandomBloke 0:a29a0225f203 220 *
SomeRandomBloke 0:a29a0225f203 221 */
SomeRandomBloke 0:a29a0225f203 222 bool readConfig() {
SomeRandomBloke 0:a29a0225f203 223
SomeRandomBloke 0:a29a0225f203 224 FILE *fp = fopen(iotConfigFile, "r");
SomeRandomBloke 0:a29a0225f203 225 if (fp == NULL) {
SomeRandomBloke 0:a29a0225f203 226 printf("Could not open file %s for read\n", iotConfigFile);
SomeRandomBloke 0:a29a0225f203 227 return false;
SomeRandomBloke 0:a29a0225f203 228 }
SomeRandomBloke 0:a29a0225f203 229 // read file
SomeRandomBloke 0:a29a0225f203 230 while (!feof( fp )) {
SomeRandomBloke 0:a29a0225f203 231 fgets(lineBuf,MAX_LINE_LENGTH,fp);
SomeRandomBloke 3:f19f9c62c00b 232 printf("[%s] ",lineBuf);
SomeRandomBloke 3:f19f9c62c00b 233 trim( lineBuf );
SomeRandomBloke 3:f19f9c62c00b 234 printf("[%s]\n", lineBuf);
SomeRandomBloke 3:f19f9c62c00b 235
SomeRandomBloke 0:a29a0225f203 236 // Need to read each entry and update config
SomeRandomBloke 0:a29a0225f203 237 char *nameStr;
SomeRandomBloke 0:a29a0225f203 238 char *valueStr;
SomeRandomBloke 0:a29a0225f203 239 nameStr = lineBuf;
SomeRandomBloke 0:a29a0225f203 240 valueStr = strchr( lineBuf, '=' );
SomeRandomBloke 0:a29a0225f203 241 if ( valueStr != NULL ) {
SomeRandomBloke 0:a29a0225f203 242 *valueStr++ = '\0';
SomeRandomBloke 0:a29a0225f203 243 int tmpAddress[4] = {0,0,0,0};
SomeRandomBloke 0:a29a0225f203 244 if ( strcmp( nameStr, "ip.address" ) == 0 ) {
SomeRandomBloke 0:a29a0225f203 245 setIpAddress( &tmpAddress[0], valueStr );
SomeRandomBloke 0:a29a0225f203 246 ipAddress = IpAddr( tmpAddress[0],tmpAddress[1],tmpAddress[2],tmpAddress[3]);
SomeRandomBloke 3:f19f9c62c00b 247
SomeRandomBloke 2:27714c8c9c0a 248 } else if ( strcmp( nameStr, "ip.netmask" ) == 0 ) {
SomeRandomBloke 0:a29a0225f203 249 setIpAddress( &tmpAddress[0], valueStr );
SomeRandomBloke 0:a29a0225f203 250 netMask = IpAddr( tmpAddress[0],tmpAddress[1],tmpAddress[2],tmpAddress[3]);
SomeRandomBloke 3:f19f9c62c00b 251
SomeRandomBloke 2:27714c8c9c0a 252 } else if ( strcmp( nameStr, "ip.gateway" ) == 0 ) {
SomeRandomBloke 0:a29a0225f203 253 setIpAddress( &tmpAddress[0], valueStr );
SomeRandomBloke 0:a29a0225f203 254 gwAddress = IpAddr( tmpAddress[0],tmpAddress[1],tmpAddress[2],tmpAddress[3]);
SomeRandomBloke 3:f19f9c62c00b 255
SomeRandomBloke 2:27714c8c9c0a 256 } else if ( strcmp( nameStr, "ip.dns" ) == 0 ) {
SomeRandomBloke 0:a29a0225f203 257 setIpAddress( &tmpAddress[0], valueStr );
SomeRandomBloke 0:a29a0225f203 258 dnsAddress = IpAddr( tmpAddress[0],tmpAddress[1],tmpAddress[2],tmpAddress[3]);
SomeRandomBloke 2:27714c8c9c0a 259
SomeRandomBloke 2:27714c8c9c0a 260 } else if ( strcmp( nameStr, "ip.mode" ) == 0 ) {
SomeRandomBloke 2:27714c8c9c0a 261 useDHCP = (strncmp( valueStr, "dhcp", 4) == 0 ? true : false);
SomeRandomBloke 3:f19f9c62c00b 262
SomeRandomBloke 3:f19f9c62c00b 263 } else if ( strcmp( nameStr, "time.host" ) == 0 ) {
SomeRandomBloke 3:f19f9c62c00b 264 strcpynull(ntpHost, valueStr );
SomeRandomBloke 3:f19f9c62c00b 265
SomeRandomBloke 0:a29a0225f203 266 } else if ( strcmp( nameStr, "pachube.key" ) == 0 ) {
SomeRandomBloke 0:a29a0225f203 267 strcpynull(pachubeApiKey, valueStr );
SomeRandomBloke 3:f19f9c62c00b 268
SomeRandomBloke 2:27714c8c9c0a 269 } else if ( strcmp( nameStr, "mqtt.host" ) == 0 ) {
SomeRandomBloke 2:27714c8c9c0a 270 setIpAddress( &tmpAddress[0], valueStr );
SomeRandomBloke 2:27714c8c9c0a 271 mqttHostAddress = IpAddr( tmpAddress[0],tmpAddress[1],tmpAddress[2],tmpAddress[3]);
SomeRandomBloke 2:27714c8c9c0a 272
SomeRandomBloke 2:27714c8c9c0a 273 } else if ( strcmp( nameStr, "mqtt.port" ) == 0 ) {
SomeRandomBloke 2:27714c8c9c0a 274 mqttPort = atoi( valueStr );
SomeRandomBloke 2:27714c8c9c0a 275
SomeRandomBloke 2:27714c8c9c0a 276 } else if ( strcmp( nameStr, "mqtt.username" ) == 0 ) {
SomeRandomBloke 2:27714c8c9c0a 277 strcpynull(mqttUsername, valueStr );
SomeRandomBloke 3:f19f9c62c00b 278
SomeRandomBloke 2:27714c8c9c0a 279 } else if ( strcmp( nameStr, "mqtt.password" ) == 0 ) {
SomeRandomBloke 2:27714c8c9c0a 280 strcpynull(mqttPassword, valueStr );
SomeRandomBloke 3:f19f9c62c00b 281
SomeRandomBloke 0:a29a0225f203 282 } else if ( strcmp( nameStr, "rfm12b.band" ) == 0 ) {
SomeRandomBloke 0:a29a0225f203 283 if ( strncmp( valueStr, "433", 3 ) == 0 )
SomeRandomBloke 0:a29a0225f203 284 rfm12bBand = RF12_433MHZ;
SomeRandomBloke 0:a29a0225f203 285 else if ( strncmp( valueStr, "868", 3 ) == 0 )
SomeRandomBloke 0:a29a0225f203 286 rfm12bBand = RF12_868MHZ;
SomeRandomBloke 0:a29a0225f203 287 else if ( strncmp( valueStr, "915", 3 ) == 0 )
SomeRandomBloke 0:a29a0225f203 288 rfm12bBand = RF12_915MHZ;
SomeRandomBloke 3:f19f9c62c00b 289
SomeRandomBloke 0:a29a0225f203 290 } else if ( strcmp( nameStr, "rfm12b.id" ) == 0 ) {
SomeRandomBloke 0:a29a0225f203 291 rfm12bId = atoi( valueStr );
SomeRandomBloke 0:a29a0225f203 292 } else if ( strcmp( nameStr, "rfm12b.group" ) == 0 ) {
SomeRandomBloke 0:a29a0225f203 293 rfm12bGroup = atoi( valueStr );
SomeRandomBloke 0:a29a0225f203 294 }
SomeRandomBloke 0:a29a0225f203 295 }
SomeRandomBloke 0:a29a0225f203 296 }
SomeRandomBloke 0:a29a0225f203 297 fclose(fp);
SomeRandomBloke 0:a29a0225f203 298
SomeRandomBloke 0:a29a0225f203 299 return true;
SomeRandomBloke 0:a29a0225f203 300 }
SomeRandomBloke 0:a29a0225f203 301
SomeRandomBloke 0:a29a0225f203 302 /** Write the current config to file
SomeRandomBloke 0:a29a0225f203 303 */
SomeRandomBloke 0:a29a0225f203 304 bool writeConfig() {
SomeRandomBloke 0:a29a0225f203 305
SomeRandomBloke 0:a29a0225f203 306 // Doesnt work?
SomeRandomBloke 0:a29a0225f203 307 // Rename original file
SomeRandomBloke 0:a29a0225f203 308 // if( rename ( iotConfigFile.c_str(), iotConfigFileBak.c_str() ) != 0 ) {
SomeRandomBloke 0:a29a0225f203 309 // printf("Could not rename file %s\n", iotConfigFile);
SomeRandomBloke 0:a29a0225f203 310 // return false;
SomeRandomBloke 0:a29a0225f203 311 // }
SomeRandomBloke 0:a29a0225f203 312
SomeRandomBloke 0:a29a0225f203 313 FILE *fp = fopen(iotConfigFile, "w");
SomeRandomBloke 0:a29a0225f203 314 if (fp == NULL) {
SomeRandomBloke 0:a29a0225f203 315 printf("Could not open file %s for write\n", iotConfigFile);
SomeRandomBloke 0:a29a0225f203 316 return false;
SomeRandomBloke 0:a29a0225f203 317 }
SomeRandomBloke 0:a29a0225f203 318
SomeRandomBloke 0:a29a0225f203 319 time_t ctTime;
SomeRandomBloke 0:a29a0225f203 320 ctTime = time(NULL);
SomeRandomBloke 0:a29a0225f203 321
SomeRandomBloke 0:a29a0225f203 322 fprintf(fp, "# iotsetup created (UTC) %s\n", ctime(&ctTime));
SomeRandomBloke 0:a29a0225f203 323 fprintf(fp, "ip.mode=%s\n", (useDHCP ? "dhcp" : "fixed") );
SomeRandomBloke 0:a29a0225f203 324 // Add msg to say net config being ignored
SomeRandomBloke 0:a29a0225f203 325 if ( useDHCP )
SomeRandomBloke 0:a29a0225f203 326 fprintf(fp, "# Following ip.* parameters not used in DHCP mode\n");
SomeRandomBloke 0:a29a0225f203 327
SomeRandomBloke 0:a29a0225f203 328 fprintf(fp, "ip.address=%hhu.%hhu.%hhu.%hhu\n", ipAddress[0], ipAddress[1],ipAddress[2],ipAddress[3]);
SomeRandomBloke 0:a29a0225f203 329 fprintf(fp, "ip.netmask=%hhu.%hhu.%hhu.%hhu\n",netMask[0], netMask[1], netMask[2], netMask[3]);
SomeRandomBloke 0:a29a0225f203 330 fprintf(fp, "ip.gateway=%hhu.%hhu.%hhu.%hhu\n",gwAddress[0],gwAddress[1],gwAddress[2],gwAddress[3]);
SomeRandomBloke 0:a29a0225f203 331 fprintf(fp, "ip.dns=%hhu.%hhu.%hhu.%hhu\n",dnsAddress[0],dnsAddress[1],dnsAddress[2],dnsAddress[3]);
SomeRandomBloke 0:a29a0225f203 332
SomeRandomBloke 0:a29a0225f203 333 fprintf(fp, "rfm12b.band=%s\n",rfm12bBands[rfm12bBand].c_str());
SomeRandomBloke 0:a29a0225f203 334 fprintf(fp, "rfm12b.id=%d\n",rfm12bId);
SomeRandomBloke 0:a29a0225f203 335 fprintf(fp, "rfm12b.group=%d\n",rfm12bGroup);
SomeRandomBloke 0:a29a0225f203 336
SomeRandomBloke 0:a29a0225f203 337 fprintf(fp, "time.timezone=GMT\n");
SomeRandomBloke 0:a29a0225f203 338 fprintf(fp, "time.dst=yes\n");
SomeRandomBloke 2:27714c8c9c0a 339
SomeRandomBloke 2:27714c8c9c0a 340 fprintf(fp, "pachube.key=%s\n", pachubeApiKey );
SomeRandomBloke 2:27714c8c9c0a 341
SomeRandomBloke 2:27714c8c9c0a 342 fprintf(fp, "mqtt.host=%hhu.%hhu.%hhu.%hhu\n",mqttHostAddress[0],mqttHostAddress[1],mqttHostAddress[2],mqttHostAddress[3]);
SomeRandomBloke 2:27714c8c9c0a 343 fprintf(fp, "mqtt.port=%d\n",mqttPort);
SomeRandomBloke 2:27714c8c9c0a 344 fprintf(fp, "mqtt.username=%s\n", mqttUsername );
SomeRandomBloke 2:27714c8c9c0a 345 fprintf(fp, "mqtt.password=%s\n", mqttPassword );
SomeRandomBloke 2:27714c8c9c0a 346
SomeRandomBloke 0:a29a0225f203 347 fclose(fp);
SomeRandomBloke 0:a29a0225f203 348
SomeRandomBloke 0:a29a0225f203 349 return true;
SomeRandomBloke 0:a29a0225f203 350 }
SomeRandomBloke 0:a29a0225f203 351
SomeRandomBloke 0:a29a0225f203 352
SomeRandomBloke 0:a29a0225f203 353 // These external symbols are maintained by the linker to indicate the
SomeRandomBloke 0:a29a0225f203 354 // location of various regions in the device's memory. They will be used by
SomeRandomBloke 0:a29a0225f203 355 // DisplayRAMBanks() to dump the size of each RAM bank to stdout.
SomeRandomBloke 0:a29a0225f203 356 extern unsigned int Image$$RW_IRAM1$$Base;
SomeRandomBloke 0:a29a0225f203 357 extern unsigned int Image$$RW_IRAM1$$ZI$$Limit;
SomeRandomBloke 0:a29a0225f203 358 extern unsigned int Image$$RW_IRAM2$$Base;
SomeRandomBloke 0:a29a0225f203 359 extern unsigned int Image$$RW_IRAM2$$ZI$$Limit;
SomeRandomBloke 0:a29a0225f203 360 extern unsigned int Image$$RW_IRAM3$$Base;
SomeRandomBloke 0:a29a0225f203 361 extern unsigned int Image$$RW_IRAM3$$ZI$$Limit;
SomeRandomBloke 0:a29a0225f203 362
SomeRandomBloke 0:a29a0225f203 363 // Displays the size of static allocations for each RAM bank as indicated by
SomeRandomBloke 0:a29a0225f203 364 // ARM linker to stdout.
SomeRandomBloke 0:a29a0225f203 365 static void DisplayRAMBanks(void) {
SomeRandomBloke 0:a29a0225f203 366 printf("Static RAM bank allocations\r\n");
SomeRandomBloke 0:a29a0225f203 367 printf(" Main RAM = %u\r\n", (unsigned int)&Image$$RW_IRAM1$$ZI$$Limit -
SomeRandomBloke 0:a29a0225f203 368 (unsigned int)&Image$$RW_IRAM1$$Base);
SomeRandomBloke 0:a29a0225f203 369 printf(" RAM0 = %u\r\n", (unsigned int)&Image$$RW_IRAM2$$ZI$$Limit -
SomeRandomBloke 0:a29a0225f203 370 (unsigned int)&Image$$RW_IRAM2$$Base);
SomeRandomBloke 0:a29a0225f203 371 printf(" RAM1 = %u\r\n", (unsigned int)&Image$$RW_IRAM3$$ZI$$Limit -
SomeRandomBloke 0:a29a0225f203 372 (unsigned int)&Image$$RW_IRAM3$$Base);
SomeRandomBloke 0:a29a0225f203 373 }
SomeRandomBloke 0:a29a0225f203 374
SomeRandomBloke 0:a29a0225f203 375 /** Main function, where all the magic starts
SomeRandomBloke 0:a29a0225f203 376 */
SomeRandomBloke 0:a29a0225f203 377 int main() {
SomeRandomBloke 0:a29a0225f203 378 linkLED = 1;
SomeRandomBloke 0:a29a0225f203 379 statusLED = 0;
SomeRandomBloke 0:a29a0225f203 380 pc.baud(115200);
SomeRandomBloke 0:a29a0225f203 381
SomeRandomBloke 0:a29a0225f203 382 printf(VERSION_INFO);
SomeRandomBloke 0:a29a0225f203 383 printf("\n");
SomeRandomBloke 0:a29a0225f203 384
SomeRandomBloke 0:a29a0225f203 385 DisplayRAMBanks();
SomeRandomBloke 0:a29a0225f203 386
SomeRandomBloke 0:a29a0225f203 387 printf("Setting up...\n");
SomeRandomBloke 0:a29a0225f203 388 printf("\nHEAP STATS\n");
SomeRandomBloke 0:a29a0225f203 389 __heapstats((__heapprt)fprintf,stderr);
SomeRandomBloke 0:a29a0225f203 390
SomeRandomBloke 0:a29a0225f203 391 if ( !readConfig() ) {
SomeRandomBloke 0:a29a0225f203 392 error("Setup failed");
SomeRandomBloke 0:a29a0225f203 393 }
SomeRandomBloke 0:a29a0225f203 394
SomeRandomBloke 0:a29a0225f203 395 if (useDHCP) {
SomeRandomBloke 0:a29a0225f203 396 printf("Using DHCP\n");
SomeRandomBloke 0:a29a0225f203 397 eth = new EthernetNetIf( "IoTGateway" );
SomeRandomBloke 0:a29a0225f203 398 } else {
SomeRandomBloke 0:a29a0225f203 399 // printf("Using Fixed addressing\n");
SomeRandomBloke 0:a29a0225f203 400 eth = new EthernetNetIf( ipAddress, netMask, gwAddress, dnsAddress );
SomeRandomBloke 0:a29a0225f203 401 }
SomeRandomBloke 0:a29a0225f203 402 EthernetErr ethErr = eth->setup();
SomeRandomBloke 0:a29a0225f203 403 if (ethErr) {
SomeRandomBloke 0:a29a0225f203 404 printf("Error %d in setup.\n", ethErr);
SomeRandomBloke 0:a29a0225f203 405 return -1;
SomeRandomBloke 0:a29a0225f203 406 }
SomeRandomBloke 0:a29a0225f203 407
SomeRandomBloke 0:a29a0225f203 408 linkLED = !ethernet.link();
SomeRandomBloke 0:a29a0225f203 409
SomeRandomBloke 0:a29a0225f203 410 if (useDHCP) {
SomeRandomBloke 0:a29a0225f203 411 // We are using dhcp so get IP Address
SomeRandomBloke 0:a29a0225f203 412 ipAddress = eth->getIp();
SomeRandomBloke 0:a29a0225f203 413 }
SomeRandomBloke 0:a29a0225f203 414
SomeRandomBloke 0:a29a0225f203 415 // Get Current time
SomeRandomBloke 3:f19f9c62c00b 416 Host server(IpAddr(), 123, ntpHost); // "0.uk.pool.ntp.org");
SomeRandomBloke 0:a29a0225f203 417 ntp.setTime(server);
SomeRandomBloke 0:a29a0225f203 418
SomeRandomBloke 0:a29a0225f203 419 time_t ctTime = time(NULL);
SomeRandomBloke 0:a29a0225f203 420 printf("\nTime is now (UTC): %s\n", ctime(&ctTime));
SomeRandomBloke 0:a29a0225f203 421
SomeRandomBloke 3:f19f9c62c00b 422 if ( strlen(pachubeApiKey) > 0 ) {
SomeRandomBloke 3:f19f9c62c00b 423 // Only add Pachube output if a key has been defined
SomeRandomBloke 3:f19f9c62c00b 424 outPachube = OutputPachube();
SomeRandomBloke 3:f19f9c62c00b 425 outPachube.setApiKey( pachubeApiKey );
SomeRandomBloke 3:f19f9c62c00b 426 // printf("MAIN: outPachube = %ld\n",(int)&outPachube);
SomeRandomBloke 3:f19f9c62c00b 427 rtr.addOutput( (OutputDef*)&outPachube , OUTPUT_TYPE_PACHUBE);
SomeRandomBloke 3:f19f9c62c00b 428 }
SomeRandomBloke 0:a29a0225f203 429
SomeRandomBloke 2:27714c8c9c0a 430 //mqttHostAddress = IpAddr(192,168,1,77);
SomeRandomBloke 2:27714c8c9c0a 431 OutputMqtt outMqtt = OutputMqtt();
SomeRandomBloke 2:27714c8c9c0a 432 // mqttHostAddress = resolver.resolveName("api.pachube.com");
SomeRandomBloke 2:27714c8c9c0a 433 // Only use MQTT is we have a host IP address
SomeRandomBloke 3:f19f9c62c00b 434 if ( mqttHostAddress[0] > 0 && mqttHostAddress[3] > 0 ) {
SomeRandomBloke 2:27714c8c9c0a 435 outMqtt.initConnection( &mqttHostAddress, mqttPort, mqttUsername, mqttPassword );
SomeRandomBloke 2:27714c8c9c0a 436 //( &serverIpAddr );
SomeRandomBloke 2:27714c8c9c0a 437 useMQTT = outMqtt.init();
SomeRandomBloke 0:a29a0225f203 438
SomeRandomBloke 3:f19f9c62c00b 439 if ( useMQTT )
SomeRandomBloke 2:27714c8c9c0a 440 rtr.addOutput( (OutputDef*)&outMqtt , OUTPUT_TYPE_MQTT);
SomeRandomBloke 2:27714c8c9c0a 441 }
SomeRandomBloke 3:f19f9c62c00b 442
SomeRandomBloke 0:a29a0225f203 443 rtr.initRouting();
SomeRandomBloke 0:a29a0225f203 444
SomeRandomBloke 0:a29a0225f203 445 printf("Setup OK\n");
SomeRandomBloke 0:a29a0225f203 446
SomeRandomBloke 0:a29a0225f203 447 printf( "Setting RFM12B ID %d, Band %d Group %d\n",rfm12bId, rfm12bBand, rfm12bGroup);
SomeRandomBloke 0:a29a0225f203 448 rfm12b.init(rfm12bId, rfm12bBand, rfm12bGroup ); //id = 2, band 866, group 5
SomeRandomBloke 0:a29a0225f203 449
SomeRandomBloke 0:a29a0225f203 450 printf("Listening...\n");
SomeRandomBloke 0:a29a0225f203 451
SomeRandomBloke 0:a29a0225f203 452 Timer tm;
SomeRandomBloke 0:a29a0225f203 453 tm.start();
SomeRandomBloke 0:a29a0225f203 454
SomeRandomBloke 0:a29a0225f203 455 printf("\nHEAP STATS\n");
SomeRandomBloke 0:a29a0225f203 456 __heapstats((__heapprt)fprintf,stderr);
SomeRandomBloke 0:a29a0225f203 457
SomeRandomBloke 0:a29a0225f203 458 short dataLen = 0;
SomeRandomBloke 0:a29a0225f203 459 uint8_t *rf12Buf;
SomeRandomBloke 0:a29a0225f203 460
SomeRandomBloke 0:a29a0225f203 461 // Start receiving data
SomeRandomBloke 0:a29a0225f203 462 rfm12b.rf12_recvStart();
SomeRandomBloke 0:a29a0225f203 463 while (true) {
SomeRandomBloke 0:a29a0225f203 464 Net::poll();
SomeRandomBloke 0:a29a0225f203 465
SomeRandomBloke 0:a29a0225f203 466 // This is RFM12B specific
SomeRandomBloke 0:a29a0225f203 467 if ( rfm12b.available() > 0 ) {
SomeRandomBloke 0:a29a0225f203 468 statusLED = 1;
SomeRandomBloke 0:a29a0225f203 469 rf12Buf = rfm12b.get_data();
SomeRandomBloke 0:a29a0225f203 470 dataLen = rfm12b.length();
SomeRandomBloke 0:a29a0225f203 471
SomeRandomBloke 0:a29a0225f203 472 if ( rtr.routePayload( rf12Buf, dataLen + 3 ) ) {
SomeRandomBloke 0:a29a0225f203 473 // Successfully dealt with a packet
SomeRandomBloke 0:a29a0225f203 474
SomeRandomBloke 0:a29a0225f203 475 // Do something different if routed
SomeRandomBloke 0:a29a0225f203 476
SomeRandomBloke 0:a29a0225f203 477 }
SomeRandomBloke 0:a29a0225f203 478
SomeRandomBloke 0:a29a0225f203 479 // For now, acknowledge everything
SomeRandomBloke 0:a29a0225f203 480
SomeRandomBloke 0:a29a0225f203 481 // Send an ack if required
SomeRandomBloke 0:a29a0225f203 482 if ((rf12Buf[1] & ~RF12_HDR_MASK) == RF12_HDR_ACK // &&
SomeRandomBloke 0:a29a0225f203 483 //(config.nodeId & 0x20) == 0
SomeRandomBloke 0:a29a0225f203 484 ) {
SomeRandomBloke 0:a29a0225f203 485
SomeRandomBloke 0:a29a0225f203 486 printf("RFM12B -> ack\n");
SomeRandomBloke 0:a29a0225f203 487
SomeRandomBloke 0:a29a0225f203 488 byte addr = rf12Buf[1] & RF12_HDR_MASK;
SomeRandomBloke 0:a29a0225f203 489 rfm12b.rf12_sendStart(RF12_HDR_CTL | RF12_HDR_DST | addr, 0, 1);
SomeRandomBloke 0:a29a0225f203 490 }
SomeRandomBloke 0:a29a0225f203 491
SomeRandomBloke 0:a29a0225f203 492 statusLED = 0;
SomeRandomBloke 0:a29a0225f203 493 }
SomeRandomBloke 0:a29a0225f203 494
SomeRandomBloke 0:a29a0225f203 495 if (tm.read()>.5) {
SomeRandomBloke 0:a29a0225f203 496 heartbeatLED=!heartbeatLED; //Show that we are alive
SomeRandomBloke 0:a29a0225f203 497 tm.start();
SomeRandomBloke 0:a29a0225f203 498 }
SomeRandomBloke 0:a29a0225f203 499
SomeRandomBloke 2:27714c8c9c0a 500 // If using mqtt then send heartbeat
SomeRandomBloke 3:f19f9c62c00b 501 if (useMQTT) {
SomeRandomBloke 2:27714c8c9c0a 502 outMqtt.send(); // Used for heartbeat/keepalive packet
SomeRandomBloke 2:27714c8c9c0a 503 }
SomeRandomBloke 3:f19f9c62c00b 504
SomeRandomBloke 0:a29a0225f203 505 linkLED = !ethernet.link();
SomeRandomBloke 0:a29a0225f203 506
SomeRandomBloke 0:a29a0225f203 507 }
SomeRandomBloke 0:a29a0225f203 508
SomeRandomBloke 0:a29a0225f203 509 }
SomeRandomBloke 0:a29a0225f203 510
SomeRandomBloke 0:a29a0225f203 511 // The End!