Initial commit

Dependencies:   ConfigFile FXOS8700CQ M2XStreamClient-JMF MODSERIAL SDFileSystem WNCInterface jsonlite mbed-rtos mbed

Fork of StarterKit_M2X_DevLab by Jan Korycan

Committer:
jk431j
Date:
Wed Apr 26 00:05:32 2017 +0000
Revision:
8:b82d330e10e9
Parent:
7:721eb6bb68d3
Child:
9:3f5dfac96ac1
* Added APN to WNCInterface initialization (more reliable initialization); * Added watchdog to M2X requests; * Added M2X configuration over SMS

Who changed what in which revision?

UserRevisionLine numberNew contents of line
JMF 0:62feed0f1fd9 1 //
JMF 0:62feed0f1fd9 2 // This file contains an example implementation of M2X using the HTTP interface as the underlying
JMF 0:62feed0f1fd9 3 // transport.
JMF 0:62feed0f1fd9 4 //
JMF 0:62feed0f1fd9 5
JMF 0:62feed0f1fd9 6 #include "mbed.h"
JMF 0:62feed0f1fd9 7 #include "WNCInterface.h"
jk431j 7:721eb6bb68d3 8 #include "IOTSMS.h"
JMF 0:62feed0f1fd9 9
JMF 0:62feed0f1fd9 10 #define MBED_PLATFORM
JMF 0:62feed0f1fd9 11 #define M2X_ENABLE_READER
JMF 0:62feed0f1fd9 12
JMF 0:62feed0f1fd9 13 #include <jsonlite.h>
JMF 0:62feed0f1fd9 14 #include "M2XStreamClient.h"
JMF 0:62feed0f1fd9 15
jk431j 4:08979e323c6e 16 #include "sensors.h"
jk431j 7:721eb6bb68d3 17 #include "config_me.h"
jk431j 4:08979e323c6e 18
JMF 0:62feed0f1fd9 19 #define CRLF "\n\r"
JMF 0:62feed0f1fd9 20
jk431j 7:721eb6bb68d3 21 //startup SMS, disabled by default
jk431j 7:721eb6bb68d3 22 //#define STARTUP_SMS
JMF 0:62feed0f1fd9 23
JMF 0:62feed0f1fd9 24 WNCInterface eth;
jk431j 7:721eb6bb68d3 25 WNCSms sms;
JMF 0:62feed0f1fd9 26 Client client;
JMF 0:62feed0f1fd9 27 M2XStreamClient m2xClient(&client, m2xKey);
JMF 0:62feed0f1fd9 28 TimeService timeService(&m2xClient);
jk431j 4:08979e323c6e 29
jk431j 4:08979e323c6e 30 I2C i2c(PTC11, PTC10); //SDA, SCL -- define the I2C pins being used
jk431j 4:08979e323c6e 31 Serial pc(USBTX, USBRX); // tx, rx
jk431j 4:08979e323c6e 32 DigitalOut led_green(LED_GREEN);
jk431j 4:08979e323c6e 33 DigitalOut led_red(LED_RED);
jk431j 4:08979e323c6e 34 DigitalOut led_blue(LED_BLUE);
jk431j 4:08979e323c6e 35
jk431j 6:731f412e6571 36 K64F_Sensors_t SENSOR_DATA = {};
jk431j 7:721eb6bb68d3 37 bool bStop = false;
jk431j 8:b82d330e10e9 38 bool bM2XConfigured;
jk431j 8:b82d330e10e9 39
jk431j 8:b82d330e10e9 40 Ticker WatchdogTicker;
jk431j 8:b82d330e10e9 41 int watchdogTicks = 0;
jk431j 8:b82d330e10e9 42 bool bWatchdogOn = false;
jk431j 8:b82d330e10e9 43 unsigned char lastLedColor = 0;
jk431j 4:08979e323c6e 44
jk431j 4:08979e323c6e 45 //********************************************************************************************************************************************
jk431j 4:08979e323c6e 46 //* Set the RGB LED's Color
jk431j 4:08979e323c6e 47 //* LED Color 0=Off to 7=White. 3 bits represent BGR (bit0=Red, bit1=Green, bit2=Blue)
jk431j 4:08979e323c6e 48 //********************************************************************************************************************************************
jk431j 4:08979e323c6e 49 void SetLedColor(unsigned char ucColor)
jk431j 4:08979e323c6e 50 {
jk431j 4:08979e323c6e 51 //Note that when an LED is on, you write a 0 to it:
jk431j 4:08979e323c6e 52 led_red = !(ucColor & 0x1); //bit 0
jk431j 4:08979e323c6e 53 led_green = !(ucColor & 0x2); //bit 1
jk431j 4:08979e323c6e 54 led_blue = !(ucColor & 0x4); //bit 2
jk431j 8:b82d330e10e9 55
jk431j 8:b82d330e10e9 56 lastLedColor = ucColor;
jk431j 4:08979e323c6e 57 } //SetLedColor()
jk431j 4:08979e323c6e 58
jk431j 8:b82d330e10e9 59 struct Watchdog {
jk431j 8:b82d330e10e9 60 Watchdog() {
jk431j 8:b82d330e10e9 61 bWatchdogOn = true;
jk431j 8:b82d330e10e9 62 };
jk431j 8:b82d330e10e9 63
jk431j 8:b82d330e10e9 64 ~Watchdog() {
jk431j 8:b82d330e10e9 65 bWatchdogOn = false;
jk431j 8:b82d330e10e9 66 };
jk431j 8:b82d330e10e9 67 };
jk431j 8:b82d330e10e9 68
jk431j 8:b82d330e10e9 69 #define WATCHDOG struct Watchdog aWatchdog;
jk431j 8:b82d330e10e9 70
jk431j 8:b82d330e10e9 71 void watchdog_check()
jk431j 8:b82d330e10e9 72 {
jk431j 8:b82d330e10e9 73 // watchdog function is run every 1/4th of a second
jk431j 8:b82d330e10e9 74 if(bWatchdogOn) {
jk431j 8:b82d330e10e9 75 watchdogTicks++;
jk431j 8:b82d330e10e9 76
jk431j 8:b82d330e10e9 77 // blink LED while watchdog is running
jk431j 8:b82d330e10e9 78 if (watchdogTicks % 2 == 1) {
jk431j 8:b82d330e10e9 79 led_red = led_green = led_blue = 1;
jk431j 8:b82d330e10e9 80 } else {
jk431j 8:b82d330e10e9 81 SetLedColor(lastLedColor);
jk431j 8:b82d330e10e9 82 };
jk431j 8:b82d330e10e9 83 } else {
jk431j 8:b82d330e10e9 84 watchdogTicks = 0;
jk431j 8:b82d330e10e9 85 SetLedColor(lastLedColor);
jk431j 8:b82d330e10e9 86 }
jk431j 8:b82d330e10e9 87
jk431j 8:b82d330e10e9 88 // reset if the watchod is on for more than one minute
jk431j 8:b82d330e10e9 89 if(watchdogTicks > 60 * 4) NVIC_SystemReset();
jk431j 8:b82d330e10e9 90 }
jk431j 8:b82d330e10e9 91
jk431j 8:b82d330e10e9 92
jk431j 8:b82d330e10e9 93 bool power_on() {
jk431j 8:b82d330e10e9 94 return (RCM->SRS0 & RCM_SRS0_POR_MASK);
jk431j 8:b82d330e10e9 95 }
jk431j 8:b82d330e10e9 96
JMF 0:62feed0f1fd9 97
jk431j 4:08979e323c6e 98 bool ExecuteCommand(const char* Command)
jk431j 4:08979e323c6e 99 {
jk431j 4:08979e323c6e 100 char cLedColor = *Command;
jk431j 4:08979e323c6e 101 switch(cLedColor)
jk431j 4:08979e323c6e 102 {
jk431j 4:08979e323c6e 103 case 'O':
jk431j 4:08979e323c6e 104 { //Off
jk431j 4:08979e323c6e 105 SetLedColor(0);
jk431j 4:08979e323c6e 106 break;
jk431j 4:08979e323c6e 107 }
jk431j 4:08979e323c6e 108 case 'R':
jk431j 4:08979e323c6e 109 { //Red
jk431j 4:08979e323c6e 110 SetLedColor(1);
jk431j 4:08979e323c6e 111 break;
jk431j 4:08979e323c6e 112 }
jk431j 4:08979e323c6e 113 case 'G':
jk431j 4:08979e323c6e 114 { //Green
jk431j 4:08979e323c6e 115 SetLedColor(2);
jk431j 4:08979e323c6e 116 break;
jk431j 4:08979e323c6e 117 }
jk431j 4:08979e323c6e 118 case 'Y':
jk431j 4:08979e323c6e 119 { //Yellow
jk431j 4:08979e323c6e 120 SetLedColor(3);
jk431j 4:08979e323c6e 121 break;
jk431j 4:08979e323c6e 122 }
jk431j 4:08979e323c6e 123 case 'B':
jk431j 4:08979e323c6e 124 { //Blue
jk431j 4:08979e323c6e 125 SetLedColor(4);
jk431j 4:08979e323c6e 126 break;
jk431j 4:08979e323c6e 127 }
jk431j 4:08979e323c6e 128 case 'M':
jk431j 8:b82d330e10e9 129 { //Magenta or M2X
jk431j 8:b82d330e10e9 130 char Key[33], Device[33];
jk431j 8:b82d330e10e9 131
jk431j 8:b82d330e10e9 132 int count = sscanf(Command, "M2X:%32s:%32s", Key, Device);
jk431j 8:b82d330e10e9 133 if (count == 2) {
jk431j 8:b82d330e10e9 134 pc.printf("Got key %s and device %s" CRLF, Key, Device);
jk431j 8:b82d330e10e9 135 strncpy(deviceId, Device, 32);
jk431j 8:b82d330e10e9 136 strncpy(m2xKey, Key, 32);
jk431j 8:b82d330e10e9 137 bM2XConfigured = true;
jk431j 8:b82d330e10e9 138 } else
jk431j 8:b82d330e10e9 139 SetLedColor(5);
jk431j 4:08979e323c6e 140 break;
jk431j 4:08979e323c6e 141 }
jk431j 4:08979e323c6e 142 case 'T':
jk431j 4:08979e323c6e 143 { //Turquoise
jk431j 4:08979e323c6e 144 SetLedColor(6);
jk431j 4:08979e323c6e 145 break;
jk431j 4:08979e323c6e 146 }
jk431j 4:08979e323c6e 147 case 'W':
jk431j 4:08979e323c6e 148 { //White
jk431j 4:08979e323c6e 149 SetLedColor(7);
jk431j 4:08979e323c6e 150 break;
jk431j 4:08979e323c6e 151 }
jk431j 7:721eb6bb68d3 152 case 'S':
jk431j 7:721eb6bb68d3 153 { //Stop
jk431j 7:721eb6bb68d3 154 bStop = true;
jk431j 7:721eb6bb68d3 155 break;
jk431j 7:721eb6bb68d3 156 }
jk431j 4:08979e323c6e 157 default:
jk431j 4:08979e323c6e 158 {
jk431j 4:08979e323c6e 159 return false;
jk431j 4:08979e323c6e 160 }
jk431j 4:08979e323c6e 161 } //switch(cLedColor)
jk431j 4:08979e323c6e 162 return true;
JMF 0:62feed0f1fd9 163 }
JMF 0:62feed0f1fd9 164
JMF 0:62feed0f1fd9 165
jk431j 4:08979e323c6e 166 void on_data_point_found(const char* at, const char* value, int index, void* context, int type) {
jk431j 4:08979e323c6e 167 pc.printf(">>Found a data point, index: %d type: %d" CRLF, index, type);
jk431j 4:08979e323c6e 168 pc.printf(">>At: %s" CRLF " Value: %s" CRLF, at, value);
jk431j 4:08979e323c6e 169 }
jk431j 4:08979e323c6e 170
jk431j 4:08979e323c6e 171 void on_fill_data(Print *print, void *context) {
jk431j 4:08979e323c6e 172 // no data to fill
JMF 0:62feed0f1fd9 173 }
JMF 0:62feed0f1fd9 174
jk431j 4:08979e323c6e 175 void on_command_found(const char* id, const char* name, int index, void *context) {
jk431j 7:721eb6bb68d3 176 pc.printf("\t|Found a command, index: %d" CRLF, index);
jk431j 7:721eb6bb68d3 177 pc.printf("\t|ID: %s" CRLF "\t|Name: %s" CRLF, id, name);
jk431j 4:08979e323c6e 178 ExecuteCommand(name);
jk431j 4:08979e323c6e 179 m2xClient.markCommandProcessed(deviceId, id, on_fill_data, NULL);
jk431j 7:721eb6bb68d3 180 pc.printf("\t|Command confirmed" CRLF, id, name);
JMF 0:62feed0f1fd9 181 }
JMF 0:62feed0f1fd9 182
jk431j 7:721eb6bb68d3 183 void on_msg_rcvd( WNCSmsMsg& msg ) {
jk431j 7:721eb6bb68d3 184 pc.printf(YEL "SMS received from %s" CRLF, msg.number.c_str());
jk431j 7:721eb6bb68d3 185 pc.printf("|Timestamp: %s %s" CRLF, msg.date.c_str(), msg.time.c_str());
jk431j 7:721eb6bb68d3 186 pc.printf("|Text: '%s'" CRLF, msg.msg.c_str());
jk431j 7:721eb6bb68d3 187 pc.printf(WHT);
jk431j 7:721eb6bb68d3 188 ExecuteCommand(msg.msg.c_str());
jk431j 7:721eb6bb68d3 189 }
jk431j 4:08979e323c6e 190
jk431j 8:b82d330e10e9 191
jk431j 8:b82d330e10e9 192
JMF 0:62feed0f1fd9 193 int main() {
jk431j 4:08979e323c6e 194 char timestamp[25];
jk431j 4:08979e323c6e 195 int length = 25;
jk431j 4:08979e323c6e 196 int response;
jk431j 7:721eb6bb68d3 197
jk431j 7:721eb6bb68d3 198 ExecuteCommand("Red");
jk431j 8:b82d330e10e9 199
jk431j 7:721eb6bb68d3 200 pc.baud(115200);
jk431j 7:721eb6bb68d3 201 pc.printf("M2X StarterKit demo: initializing the network" CRLF);
jk431j 8:b82d330e10e9 202 response = eth.init("m2m.com.attz");
jk431j 4:08979e323c6e 203 pc.printf("WNC Module %s initialized (%02X)." CRLF, response?"IS":"IS NOT", response);
jk431j 4:08979e323c6e 204 if( !response ) {
jk431j 8:b82d330e10e9 205 pc.printf(" - - - - - - - SYSTEM RESET - - - - - - - " CRLF CRLF);
jk431j 4:08979e323c6e 206 NVIC_SystemReset();
jk431j 4:08979e323c6e 207 }
jk431j 7:721eb6bb68d3 208
jk431j 7:721eb6bb68d3 209 response = sms.init(1, on_msg_rcvd);
jk431j 7:721eb6bb68d3 210 pc.printf("SMS interface %s initialized (%02X)." CRLF, response?"IS NOT":"IS", response);
jk431j 7:721eb6bb68d3 211 if (!response) {
jk431j 7:721eb6bb68d3 212 pc.printf("SMS number is %s" CRLF , sms.getSMSNbr());
jk431j 7:721eb6bb68d3 213 };
jk431j 7:721eb6bb68d3 214
jk431j 4:08979e323c6e 215 response = eth.connect();
jk431j 4:08979e323c6e 216 pc.printf("IP Address: %s " CRLF CRLF, eth.getIPAddress());
jk431j 7:721eb6bb68d3 217
jk431j 7:721eb6bb68d3 218 ExecuteCommand("Yellow");
jk431j 4:08979e323c6e 219
jk431j 4:08979e323c6e 220 pc.printf("Initialize the sensors" CRLF);
jk431j 4:08979e323c6e 221 sensors_init();
jk431j 4:08979e323c6e 222 read_sensors();
jk431j 8:b82d330e10e9 223
jk431j 8:b82d330e10e9 224 bM2XConfigured = *deviceId && *m2xKey;
jk431j 8:b82d330e10e9 225 if (!bM2XConfigured) {
jk431j 8:b82d330e10e9 226 pc.printf(RED "Waiting for SMS configuration" CRLF);
jk431j 8:b82d330e10e9 227
jk431j 8:b82d330e10e9 228 while (!bM2XConfigured) {
jk431j 8:b82d330e10e9 229 ExecuteCommand("Red");
jk431j 8:b82d330e10e9 230 delay(1000);
jk431j 8:b82d330e10e9 231 ExecuteCommand("Yellow");
jk431j 8:b82d330e10e9 232 delay(1000);
jk431j 8:b82d330e10e9 233 }
jk431j 8:b82d330e10e9 234 };
jk431j 8:b82d330e10e9 235
jk431j 8:b82d330e10e9 236 // set up watchdog ticker running every quarter of a second
jk431j 8:b82d330e10e9 237 WatchdogTicker.attach(watchdog_check, 0.25);
jk431j 7:721eb6bb68d3 238
jk431j 8:b82d330e10e9 239 { WATCHDOG
jk431j 8:b82d330e10e9 240 pc.printf(WHT "initialize the M2X time service" CRLF);
jk431j 8:b82d330e10e9 241 if (!m2x_status_is_success(timeService.init()))
jk431j 8:b82d330e10e9 242 pc.printf("Cannot initialize time service!" CRLF);
jk431j 8:b82d330e10e9 243 else {
jk431j 8:b82d330e10e9 244 timeService.getTimestamp(timestamp, &length);
jk431j 8:b82d330e10e9 245 pc.printf("Current timestamp: %s" CRLF, timestamp);
jk431j 8:b82d330e10e9 246 };
jk431j 8:b82d330e10e9 247 };
jk431j 8:b82d330e10e9 248
jk431j 7:721eb6bb68d3 249 ExecuteCommand("Green");
jk431j 7:721eb6bb68d3 250
jk431j 7:721eb6bb68d3 251 #ifdef STARTUP_SMS
jk431j 7:721eb6bb68d3 252 response = sms.send("5277", "IoT StarterKit is now running!");
jk431j 7:721eb6bb68d3 253 pc.printf("Startup SMS %s sent." CRLF, response ? "was" : "NOT");
jk431j 7:721eb6bb68d3 254 #endif
jk431j 7:721eb6bb68d3 255
jk431j 8:b82d330e10e9 256 { WATCHDOG
jk431j 8:b82d330e10e9 257 pc.printf("Query for pending commands ..." CRLF);
jk431j 8:b82d330e10e9 258 response = m2xClient.listCommands(deviceId, on_command_found, NULL, "status=pending");
jk431j 8:b82d330e10e9 259 pc.printf("listCommands response code: %d" CRLF, response);
jk431j 8:b82d330e10e9 260 };
jk431j 8:b82d330e10e9 261
jk431j 7:721eb6bb68d3 262 while (!bStop) {
jk431j 4:08979e323c6e 263 // read sensor values
jk431j 4:08979e323c6e 264 read_sensors();
JMF 0:62feed0f1fd9 265
jk431j 8:b82d330e10e9 266 { WATCHDOG
jk431j 8:b82d330e10e9 267 // post the humidity value
jk431j 8:b82d330e10e9 268 pc.printf("Post updateStreamValue (humidity = %.2f)..." CRLF, SENSOR_DATA.Humidity);
jk431j 8:b82d330e10e9 269 response = m2xClient.updateStreamValue(deviceId, hStreamName, SENSOR_DATA.Humidity);
jk431j 8:b82d330e10e9 270 pc.printf("Post response code: %d" CRLF, response);
jk431j 8:b82d330e10e9 271
jk431j 8:b82d330e10e9 272 // post the temp value
jk431j 8:b82d330e10e9 273 pc.printf("Post updateStreamValue (temp = %.2f)..." CRLF, SENSOR_DATA.Temperature);
jk431j 8:b82d330e10e9 274 response = m2xClient.updateStreamValue(deviceId, tStreamName, SENSOR_DATA.Temperature);
jk431j 8:b82d330e10e9 275 pc.printf("Post response code: %d" CRLF, response);
jk431j 8:b82d330e10e9 276
jk431j 8:b82d330e10e9 277 // post accelerometer values
jk431j 8:b82d330e10e9 278 pc.printf("Post postDeviceUpdate (accelerometer)..." CRLF, SENSOR_DATA.Temperature);
jk431j 8:b82d330e10e9 279 response = m2xClient.postDeviceUpdate(deviceId, 3, accelStreamNames, (float []){SENSOR_DATA.AccelX, SENSOR_DATA.AccelY, SENSOR_DATA.AccelZ});
jk431j 8:b82d330e10e9 280 pc.printf("Post response code: %d" CRLF, response);
jk431j 8:b82d330e10e9 281
jk431j 8:b82d330e10e9 282 timeService.getTimestamp(timestamp, &length);
jk431j 8:b82d330e10e9 283 pc.printf("%s waiting for %d seconds... " CRLF , timestamp, commandDelay * commandPolls);
jk431j 8:b82d330e10e9 284 };
jk431j 4:08979e323c6e 285
jk431j 7:721eb6bb68d3 286 // now poll for pending commands
jk431j 7:721eb6bb68d3 287 for (short idx=0; idx < commandPolls; idx++) {
jk431j 7:721eb6bb68d3 288 // wait commandDelay seconds
jk431j 7:721eb6bb68d3 289 delay(commandDelay * 1000);
JMF 0:62feed0f1fd9 290
jk431j 7:721eb6bb68d3 291 // and then query for commands
jk431j 8:b82d330e10e9 292 { WATCHDOG
jk431j 8:b82d330e10e9 293 pc.printf("\tQuery for pending commands ..." CRLF);
jk431j 8:b82d330e10e9 294 response = m2xClient.listCommands(deviceId, on_command_found, NULL, "status=pending");
jk431j 8:b82d330e10e9 295 pc.printf("\tlistCommands response code: %d" CRLF, response);
jk431j 8:b82d330e10e9 296 };
jk431j 4:08979e323c6e 297 }
jk431j 7:721eb6bb68d3 298 };
jk431j 7:721eb6bb68d3 299
jk431j 7:721eb6bb68d3 300 pc.printf("Done sending data. Still accepting SMS commands." CRLF);
jk431j 7:721eb6bb68d3 301 bStop = false;
jk431j 7:721eb6bb68d3 302 while (!bStop) {
jk431j 7:721eb6bb68d3 303 delay(1000);
jk431j 7:721eb6bb68d3 304 };
jk431j 7:721eb6bb68d3 305
jk431j 7:721eb6bb68d3 306 pc.printf("- - - - - - - THE END - - - - - - - " CRLF);
jk431j 7:721eb6bb68d3 307 NVIC_SystemReset();
jk431j 8:b82d330e10e9 308 }