Initial commit
Dependencies: ConfigFile FXOS8700CQ M2XStreamClient-JMF MODSERIAL SDFileSystem WNCInterface jsonlite mbed-rtos mbed
Fork of StarterKit_M2X_DevLab by
main.cpp
00001 // 00002 // This file contains an example implementation of M2X using the HTTP interface as the underlying 00003 // transport. 00004 // 00005 00006 #include "mbed.h" 00007 #include "WNCInterface.h" 00008 #include "WncUDPSocket.h" 00009 #include "IOTSMS.h" 00010 00011 #define MBED_PLATFORM 00012 #define M2X_ENABLE_READER 00013 00014 #include <jsonlite.h> 00015 #include "M2XStreamClient.h" 00016 00017 #include "sensors.h" 00018 00019 #define CRLF "\n\r" 00020 00021 #include "SDFileSystem.h" 00022 #include "ConfigFile.h" 00023 #include "config_me.h" 00024 00025 //startup SMS, disabled by default 00026 //#define STARTUP_SMS 00027 00028 //command processing enabled by default 00029 //#define COMMANDS_ENABLED 00030 00031 //update all streams in one command, disabled by default 00032 #define SINGLE_UPDATE 00033 00034 //send data to AMOC 00035 #define AMOC_ENABLED 00036 00037 // SD card access (MOSI, MISO, SCK, CS) 00038 SDFileSystem sd(PTE3, PTE1, PTE2, PTE4, "sd"); 00039 Configuration conf; 00040 00041 WNCInterface eth; 00042 WNCSms sms; 00043 Client client; 00044 M2XStreamClient m2xClient(&client, conf.m2xKey); 00045 TimeService timeService(&m2xClient); 00046 00047 I2C i2c(PTC11, PTC10); //SDA, SCL -- define the I2C pins being used 00048 Serial pc(USBTX, USBRX); // tx, rx 00049 DigitalOut led_green(LED_GREEN); 00050 DigitalOut led_red(LED_RED); 00051 DigitalOut led_blue(LED_BLUE); 00052 00053 K64F_Sensors_t SENSOR_DATA = {}; 00054 K64F_Sensors_t OLD_SENSOR_DATA = {}; 00055 bool bStop = false; 00056 bool bSendDataNow = false; 00057 bool bSendSMS = false; 00058 00059 Ticker WatchdogTicker; 00060 int watchdogTicks = 0; 00061 bool bWatchdogOn = false; 00062 unsigned char lastLedColor = 0; 00063 00064 InterruptIn btn3(SW3); 00065 InterruptIn btn2(SW2); 00066 00067 00068 00069 #ifdef SINGLE_UPDATE 00070 const char* allStreamNames[] = { hStreamName, tStreamName, accelStreamNames[0], accelStreamNames[1], accelStreamNames[2] }; 00071 #endif 00072 00073 //******************************************************************************************************************************************** 00074 //* Set the RGB LED's Color 00075 //* LED Color 0=Off to 7=White. 3 bits represent BGR (bit0=Red, bit1=Green, bit2=Blue) 00076 //******************************************************************************************************************************************** 00077 void SetLedColor(unsigned char ucColor) 00078 { 00079 //Note that when an LED is on, you write a 0 to it: 00080 led_red = !(ucColor & 0x1); //bit 0 00081 led_green = !(ucColor & 0x2); //bit 1 00082 led_blue = !(ucColor & 0x4); //bit 2 00083 00084 lastLedColor = ucColor; 00085 } //SetLedColor() 00086 00087 struct Watchdog { 00088 Watchdog() { 00089 bWatchdogOn = true; 00090 }; 00091 00092 ~Watchdog() { 00093 bWatchdogOn = false; 00094 }; 00095 }; 00096 00097 #define WATCHDOG struct Watchdog aWatchdog; 00098 00099 void watchdog_check() 00100 { 00101 // watchdog function is run every 1/4th of a second 00102 if(bWatchdogOn) { 00103 watchdogTicks++; 00104 00105 // blink LED while watchdog is running 00106 if (watchdogTicks % 2 == 1) { 00107 led_red = led_green = led_blue = 1; 00108 } else { 00109 SetLedColor(lastLedColor); 00110 }; 00111 } else { 00112 watchdogTicks = 0; 00113 SetLedColor(lastLedColor); 00114 } 00115 00116 // reset if the watchod is on for more than 10 seconds 00117 if(watchdogTicks > 30 * 4) NVIC_SystemReset(); 00118 } 00119 00120 00121 bool power_on() { 00122 return (RCM->SRS0 & RCM_SRS0_POR_MASK); 00123 } 00124 00125 00126 bool ExecuteCommand(const char* Command) 00127 { 00128 char cLedColor = *Command; 00129 switch(cLedColor) 00130 { 00131 case 'O': 00132 { //Off 00133 SetLedColor(0); 00134 break; 00135 } 00136 case 'R': 00137 { //Red 00138 SetLedColor(1); 00139 break; 00140 } 00141 case 'G': 00142 { //Green 00143 SetLedColor(2); 00144 break; 00145 } 00146 case 'Y': 00147 { //Yellow 00148 SetLedColor(3); 00149 break; 00150 } 00151 case 'B': 00152 { //Blue 00153 SetLedColor(4); 00154 break; 00155 } 00156 case 'M': 00157 { //Magenta or M2X 00158 char Key[33], Device[33]; 00159 00160 int count = sscanf(Command, "M2X:%32s:%32s", Key, Device); 00161 if (count == 2) { 00162 pc.printf("Got key %s and device %s" CRLF, Key, Device); 00163 strncpy(conf.deviceId, Device, 32); 00164 strncpy(conf.m2xKey, Key, 32); 00165 conf.m2xConfigured = true; 00166 } else 00167 SetLedColor(5); 00168 break; 00169 } 00170 case 'T': 00171 { //Turquoise 00172 SetLedColor(6); 00173 break; 00174 } 00175 case 'W': 00176 { //White 00177 int Delay = 0, Polls = 0; 00178 00179 pc.printf("Processing WAIT command" CRLF); 00180 int count = sscanf(Command, "WAIT:%d:%d", Delay, Polls); 00181 if (count == 2) { 00182 pc.printf("Reconfiguring wait loop to %d delay and %d polls ...", Delay, Polls); 00183 if ((Delay > 5) && (Delay < 300) 00184 && (Polls > 0) && (Polls < 100)) { 00185 bSendDataNow = true; 00186 conf.commandDelay = Delay; 00187 conf.commandPolls = Polls; 00188 pc.printf("done" CRLF); 00189 } else 00190 pc.printf("discarding invalid parameters!" CRLF); 00191 } else 00192 SetLedColor(7); 00193 break; 00194 } 00195 case 'S': 00196 { //Stop 00197 bStop = true; 00198 break; 00199 } 00200 default: 00201 { 00202 return false; 00203 } 00204 } //switch(cLedColor) 00205 return true; 00206 } 00207 00208 00209 void on_data_point_found(const char* at, const char* value, int index, void* context, int type) { 00210 pc.printf(">>Found a data point, index: %d type: %d" CRLF, index, type); 00211 pc.printf(">>At: %s" CRLF " Value: %s" CRLF, at, value); 00212 } 00213 00214 void on_fill_data(Print *print, void *context) { 00215 // no data to fill 00216 } 00217 00218 00219 void on_command_found(const char* id, const char* name, int index, void *context) { 00220 pc.printf("\t|Found a command, index: %d" CRLF, index); 00221 pc.printf("\t|ID: %s" CRLF "\t|Name: %s" CRLF, id, name); 00222 ExecuteCommand(name); 00223 m2xClient.markCommandProcessed(conf.deviceId, id, on_fill_data, NULL); 00224 pc.printf("\t|Command confirmed" CRLF, id, name); 00225 } 00226 00227 00228 void on_msg_rcvd( WNCSmsMsg& msg ) { 00229 pc.printf(YEL "SMS received from %s" CRLF, msg.number.c_str()); 00230 pc.printf("|Timestamp: %s %s" CRLF, msg.date.c_str(), msg.time.c_str()); 00231 pc.printf("|Text: '%s'" CRLF, msg.msg.c_str()); 00232 pc.printf(WHT); 00233 ExecuteCommand(msg.msg.c_str()); 00234 } 00235 00236 00237 void button_2_pressed() { 00238 bSendSMS = true; 00239 } 00240 00241 00242 void button_3_pressed() { 00243 bSendDataNow = true; 00244 } 00245 00246 00247 void process_buttons() { 00248 char smsText[100]; 00249 00250 if (bSendSMS) { 00251 bSendSMS = false; 00252 00253 snprintf(smsText, 100, "Last temperature was %.2f", SENSOR_DATA.Temperature); 00254 int response = sms.send("5277", smsText); 00255 pc.printf(YEL "Button SMS %s sent." CRLF, response ? "was" : "NOT"); 00256 pc.printf(WHT); 00257 }; 00258 } 00259 00260 bool check_accelerometer_change() { 00261 read_sensors(); 00262 00263 float diffX, diffY, diffZ; 00264 diffX = abs(SENSOR_DATA.AccelX - OLD_SENSOR_DATA.AccelX); 00265 diffY = abs(SENSOR_DATA.AccelY - OLD_SENSOR_DATA.AccelY); 00266 diffZ = abs(SENSOR_DATA.AccelZ - OLD_SENSOR_DATA.AccelZ); 00267 00268 bool changed = (diffX > 0.5) || (diffY > 0.5) || (diffZ > 0.5); 00269 if (changed) { 00270 bSendDataNow = true; 00271 pc.printf("Accelerometer changed, sending data immediately." CRLF); 00272 }; 00273 00274 return changed; 00275 } 00276 00277 00278 #define MAX_AMOC 16+(7*5)+11+12 00279 void run_amoc() { 00280 pc.printf("Sending data over UDP to %s:%d ... ", conf.udpHost, conf.udpPort); 00281 WncEndpoint AmocEndpoint; 00282 WncUDPSocket AmocSocket; 00283 char buff[MAX_AMOC]; 00284 00285 if (!AmocEndpoint.set_address(conf.udpHost, conf.udpPort)) { 00286 pc.printf("Cannot resolve UDP endpoint." CRLF); 00287 return; 00288 }; 00289 00290 snprintf(buff, MAX_AMOC, "'%s',%.2f,%.2f,%.2f,%.2f,%.2f,%2.6f,%3.6f", conf.devIMEI, SENSOR_DATA.Temperature, SENSOR_DATA.Humidity, SENSOR_DATA.AccelX, SENSOR_DATA.AccelY, SENSOR_DATA.AccelZ, conf.locLat, conf.locLong); 00291 00292 int resp = AmocSocket.sendTo(AmocEndpoint, buff, strlen(buff)); 00293 pc.printf("%d bytes sent." CRLF , resp); 00294 if (resp < 0) { 00295 unsigned char aux = lastLedColor; 00296 SetLedColor(3); //Yellow 00297 lastLedColor = aux; 00298 } else 00299 SetLedColor(lastLedColor); 00300 } 00301 00302 00303 int main() { 00304 char timestamp[25]; 00305 int length = 25; 00306 int response; 00307 00308 ExecuteCommand("Red"); 00309 00310 pc.baud(115200); 00311 pc.printf("M2X StarterKit demo (compiled " __DATE__ ", " __TIME__ "): initializing the network" CRLF); 00312 response = eth.init("m2m.com.attz"); 00313 pc.printf("WNC Module %s initialized (%02X)." CRLF, response?"IS":"IS NOT", response); 00314 if( !response ) { 00315 pc.printf(" - - - - - - - SYSTEM RESET - - - - - - - " CRLF CRLF); 00316 NVIC_SystemReset(); 00317 } 00318 00319 response = sms.init(1, on_msg_rcvd); 00320 pc.printf("SMS interface %s initialized (%02X)." CRLF, response?"IS NOT":"IS", response); 00321 if (!response) { 00322 pc.printf("SMS number is %s" CRLF , sms.getSMSNbr()); 00323 }; 00324 00325 response = eth.connect(); 00326 pc.printf("IP Address: %s " CRLF CRLF, eth.getIPAddress()); 00327 pc.printf("MAC Address: %s " CRLF CRLF, eth.getMACAddress()); 00328 00329 ExecuteCommand("Yellow"); 00330 00331 pc.printf("Initialize the sensors" CRLF); 00332 sensors_init(); 00333 read_sensors(); 00334 00335 pc.printf(CYN); 00336 conf.dumpConfig(pc); 00337 pc.printf(WHT); 00338 00339 if (!conf.m2xConfigured) { 00340 pc.printf(RED "Waiting for SMS configuration" CRLF); 00341 00342 while (!conf.m2xConfigured) { 00343 ExecuteCommand("Red"); 00344 delay(1000); 00345 ExecuteCommand("Yellow"); 00346 delay(1000); 00347 } 00348 }; 00349 00350 // set up watchdog ticker running every quarter of a second 00351 WatchdogTicker.attach(watchdog_check, 0.25); 00352 00353 if (conf.enableM2X) 00354 { WATCHDOG 00355 pc.printf(WHT "initialize the M2X time service" CRLF); 00356 if (!m2x_status_is_success(timeService.init())) 00357 pc.printf("Cannot initialize time service!" CRLF); 00358 else { 00359 timeService.getTimestamp(timestamp, &length); 00360 pc.printf("Current timestamp: %s" CRLF, timestamp); 00361 }; 00362 }; 00363 00364 btn2.fall(&button_2_pressed); 00365 btn3.fall(&button_3_pressed); 00366 00367 ExecuteCommand("Green"); 00368 00369 #ifdef STARTUP_SMS 00370 response = sms.send("5277", "IoT StarterKit is now running!"); 00371 pc.printf("Startup SMS %s sent." CRLF, response ? "was" : "NOT"); 00372 #endif 00373 00374 if (conf.enableCommands) 00375 { WATCHDOG 00376 pc.printf("Query for pending commands ..." CRLF); 00377 response = m2xClient.listCommands(conf.deviceId, on_command_found, NULL, "status=pending"); 00378 pc.printf("listCommands response code: %d" CRLF, response); 00379 }; 00380 00381 00382 while (!bStop) { 00383 // read sensor values 00384 read_sensors(); 00385 00386 if (conf.enableUDP) 00387 run_amoc(); 00388 00389 if (conf.enableM2X) 00390 { WATCHDOG 00391 #ifndef SINGLE_UPDATE 00392 // post the humidity value 00393 pc.printf("Post updateStreamValue (humidity = %.2f)..." CRLF, SENSOR_DATA.Humidity); 00394 response = m2xClient.updateStreamValue(deviceId, hStreamName, SENSOR_DATA.Humidity); 00395 pc.printf("Post response code: %d" CRLF, response); 00396 00397 // post the temp value 00398 pc.printf("Post updateStreamValue (temp = %.2f)..." CRLF, SENSOR_DATA.Temperature); 00399 response = m2xClient.updateStreamValue(deviceId, tStreamName, SENSOR_DATA.Temperature); 00400 pc.printf("Post response code: %d" CRLF, response); 00401 00402 // post accelerometer values 00403 pc.printf("Post postDeviceUpdate (accelerometer [%.2f,%.2f,%.2f])..." CRLF, SENSOR_DATA.AccelX, SENSOR_DATA.AccelY, SENSOR_DATA.AccelZ); 00404 float values[3] = {SENSOR_DATA.AccelX, SENSOR_DATA.AccelY, SENSOR_DATA.AccelZ} 00405 response = m2xClient.postDeviceUpdate(deviceId, 3, accelStreamNames, values); 00406 pc.printf("Post response code: %d" CRLF, response); 00407 #else 00408 // post all values at one 00409 pc.printf("Post all stream values [%.2f,%.2f,%.2f,%.2f,%.2f])..." CRLF, SENSOR_DATA.Humidity, SENSOR_DATA.Temperature, SENSOR_DATA.AccelX, SENSOR_DATA.AccelY, SENSOR_DATA.AccelZ); 00410 float values[5] = {SENSOR_DATA.Humidity, SENSOR_DATA.Temperature, SENSOR_DATA.AccelX, SENSOR_DATA.AccelY, SENSOR_DATA.AccelZ}; 00411 response = m2xClient.postDeviceUpdate(conf.deviceId, 5, allStreamNames, values); 00412 pc.printf("Post response code: %d" CRLF, response); 00413 #endif 00414 timeService.getTimestamp(timestamp, &length); 00415 pc.printf("%s waiting for %d seconds... " CRLF , timestamp, conf.commandDelay * conf.commandPolls); 00416 } else 00417 pc.printf("Sensor values [%.2f,%.2f,%.2f,%.2f,%.2f]. Sleeping for %d seconds." CRLF, SENSOR_DATA.Humidity, SENSOR_DATA.Temperature, SENSOR_DATA.AccelX, SENSOR_DATA.AccelY, SENSOR_DATA.AccelZ, conf.commandDelay * conf.commandPolls); 00418 00419 // save old sensor data, we will use them to check for accelerometer change 00420 OLD_SENSOR_DATA = SENSOR_DATA; 00421 // sleep loop, check for accelerometer changes and pending commands 00422 for (short idx=0; idx < conf.commandPolls; idx++) { 00423 // wait commandDelay seconds 00424 for (short delays=0; delays < conf.commandDelay; delays++) { 00425 delay(1000); 00426 // if the buttons were pressed process them immediately 00427 process_buttons(); 00428 check_accelerometer_change(); 00429 // button 3 skips wait and sends data right away 00430 if (bSendDataNow || bStop) 00431 break; 00432 }; 00433 00434 // and then query for commands 00435 if (conf.enableCommands) 00436 { WATCHDOG 00437 pc.printf("\tQuery for pending commands ..." CRLF); 00438 response = m2xClient.listCommands(conf.deviceId, on_command_found, NULL, "status=pending"); 00439 pc.printf("\tlistCommands response code: %d" CRLF, response); 00440 }; 00441 00442 //if button 3 was pressed skip the wait and send data right away 00443 if (bSendDataNow || bStop) { 00444 bSendDataNow = false; 00445 break; 00446 }; 00447 } 00448 }; 00449 00450 pc.printf("Done sending data. Still accepting SMS commands." CRLF); 00451 bStop = false; 00452 while (!bStop) { 00453 delay(1000); 00454 }; 00455 00456 pc.printf("- - - - - - - THE END - - - - - - - " CRLF); 00457 NVIC_SystemReset(); 00458 }
Generated on Fri Jul 15 2022 01:40:15 by 1.7.2