Initial commit

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

Fork of StarterKit_M2X_DevLab by Jan Korycan

Embed: (wiki syntax)

« Back to documentation index

Show/hide line numbers main.cpp Source File

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 }