I added functionality to get the RSSI, BER, and Cell Neighbor for reporting connection issues to M2X
Dependencies: mbed FXOS8700CQ mbed-rtos WNCInterface M2XStreamClient-JMF jsonlite
main.cpp
- Committer:
- ng977t
- Date:
- 2019-04-18
- Revision:
- 12:0dfd0129f75d
- Parent:
- 9:3f5dfac96ac1
File content as of revision 12:0dfd0129f75d:
// // This file contains an example implementation of M2X using the HTTP interface as the underlying // transport. // #include "mbed.h" #include "WNCInterface.h" #include "IOTSMS.h" #define MBED_PLATFORM #define M2X_ENABLE_READER #include <jsonlite.h> #include "M2XStreamClient.h" #include "sensors.h" #include "config_me.h" #define CRLF "\n\r" //startup SMS, disabled by default //#define STARTUP_SMS //command processing enabled by default #define COMMANDS_ENABLED //update all streams in one command, disabled by default //#define SINGLE_UPDATE WNCInterface eth; WNCSms sms; Client client; M2XStreamClient m2xClient(&client, m2xKey); TimeService timeService(&m2xClient); I2C i2c(PTC11, PTC10); //SDA, SCL -- define the I2C pins being used Serial pc(USBTX, USBRX); // tx, rx DigitalOut led_green(LED_GREEN); DigitalOut led_red(LED_RED); DigitalOut led_blue(LED_BLUE); K64F_Sensors_t SENSOR_DATA = {}; K64F_Sensors_t OLD_SENSOR_DATA = {}; bool bStop = false; bool bSendDataNow = false; bool bSendSMS = false; bool bM2XConfigured; Ticker WatchdogTicker; int watchdogTicks = 0; bool bWatchdogOn = false; unsigned char lastLedColor = 0; InterruptIn btn3(SW3); InterruptIn btn2(SW2); #ifdef SINGLE_UPDATE const char* allStreamNames[] = { hStreamName, tStreamName, accelStreamNames[0], accelStreamNames[1], accelStreamNames[2] }; #endif //******************************************************************************************************************************************** //* Set the RGB LED's Color //* LED Color 0=Off to 7=White. 3 bits represent BGR (bit0=Red, bit1=Green, bit2=Blue) //******************************************************************************************************************************************** void SetLedColor(unsigned char ucColor) { //Note that when an LED is on, you write a 0 to it: led_red = !(ucColor & 0x1); //bit 0 led_green = !(ucColor & 0x2); //bit 1 led_blue = !(ucColor & 0x4); //bit 2 lastLedColor = ucColor; } //SetLedColor() struct Watchdog { Watchdog() { bWatchdogOn = true; }; ~Watchdog() { bWatchdogOn = false; }; }; #define WATCHDOG struct Watchdog aWatchdog; void watchdog_check() { // watchdog function is run every 1/4th of a second if(bWatchdogOn) { watchdogTicks++; // blink LED while watchdog is running if (watchdogTicks % 2 == 1) { led_red = led_green = led_blue = 1; } else { SetLedColor(lastLedColor); }; } else { watchdogTicks = 0; SetLedColor(lastLedColor); } // reset if the watchod is on for more than 10 seconds if(watchdogTicks > 30 * 4) NVIC_SystemReset(); } bool power_on() { return (RCM->SRS0 & RCM_SRS0_POR_MASK); } bool ExecuteCommand(const char* Command) { char cLedColor = *Command; switch(cLedColor) { case 'O': { //Off SetLedColor(0); break; } case 'R': { //Red SetLedColor(1); break; } case 'G': { //Green SetLedColor(2); break; } case 'Y': { //Yellow SetLedColor(3); break; } case 'B': { //Blue SetLedColor(4); break; } case 'M': { //Magenta or M2X char Key[33], Device[33]; int count = sscanf(Command, "M2X:%32s:%32s", Key, Device); if (count == 2) { pc.printf("Got key %s and device %s" CRLF, Key, Device); strncpy(deviceId, Device, 32); strncpy(m2xKey, Key, 32); bM2XConfigured = true; } else SetLedColor(5); break; } case 'T': { //Turquoise SetLedColor(6); break; } case 'W': { //White int Delay = 0, Polls = 0; pc.printf("Processing WAIT command" CRLF); int count = sscanf(Command, "WAIT:%d:%d", Delay, Polls); if (count == 2) { pc.printf("Reconfiguring wait loop to %d delay and %d polls ...", Delay, Polls); if ((Delay > 5) && (Delay < 300) && (Polls > 0) && (Polls < 100)) { bSendDataNow = true; commandDelay = Delay; commandPolls = Polls; pc.printf("done" CRLF); } else pc.printf("discarding invalid parameters!" CRLF); } else SetLedColor(7); break; } case 'S': { //Stop bStop = true; break; } default: { return false; } } //switch(cLedColor) return true; } void on_data_point_found(const char* at, const char* value, int index, void* context, int type) { pc.printf(">>Found a data point, index: %d type: %d" CRLF, index, type); pc.printf(">>At: %s" CRLF " Value: %s" CRLF, at, value); } void on_fill_data(Print *print, void *context) { // no data to fill } void on_command_found(const char* id, const char* name, int index, void *context) { pc.printf("\t|Found a command, index: %d" CRLF, index); pc.printf("\t|ID: %s" CRLF "\t|Name: %s" CRLF, id, name); ExecuteCommand(name); m2xClient.markCommandProcessed(deviceId, id, on_fill_data, NULL); pc.printf("\t|Command confirmed" CRLF, id, name); } void on_msg_rcvd( WNCSmsMsg& msg ) { pc.printf(YEL "SMS received from %s" CRLF, msg.number.c_str()); pc.printf("|Timestamp: %s %s" CRLF, msg.date.c_str(), msg.time.c_str()); pc.printf("|Text: '%s'" CRLF, msg.msg.c_str()); pc.printf(WHT); ExecuteCommand(msg.msg.c_str()); } void button_2_pressed() { bSendSMS = true; } void button_3_pressed() { bSendDataNow = true; } void process_buttons() { char smsText[100]; if (bSendSMS) { bSendSMS = false; snprintf(smsText, 100, "Last temperature was %.2f", SENSOR_DATA.Temperature); int response = sms.send("5277", smsText); pc.printf(YEL "Button SMS %s sent." CRLF, response ? "was" : "NOT"); pc.printf(WHT); }; } bool check_accelerometer_change() { read_sensors(); float diffX, diffY, diffZ; diffX = abs(SENSOR_DATA.AccelX - OLD_SENSOR_DATA.AccelX); diffY = abs(SENSOR_DATA.AccelY - OLD_SENSOR_DATA.AccelY); diffZ = abs(SENSOR_DATA.AccelZ - OLD_SENSOR_DATA.AccelZ); bool changed = (diffX > 0.5) || (diffY > 0.5) || (diffZ > 0.5); if (changed) { bSendDataNow = true; pc.printf("Accelerometer changed, sending data immediately." CRLF); }; return changed; } int main() { char timestamp[25]; int length = 25; int response; ExecuteCommand("Red"); pc.baud(115200); pc.printf("M2X StarterKit demo (compiled " __DATE__ ", " __TIME__ "): initializing the network" CRLF); response = eth.init("m2m.com.attz"); pc.printf("WNC Module %s initialized (%02X)." CRLF, response?"IS":"IS NOT", response); if( !response ) { pc.printf(" - - - - - - - SYSTEM RESET - - - - - - - " CRLF CRLF); NVIC_SystemReset(); } response = sms.init(1, on_msg_rcvd); pc.printf("SMS interface %s initialized (%02X)." CRLF, response?"IS NOT":"IS", response); if (!response) { pc.printf("SMS number is %s" CRLF , sms.getSMSNbr()); }; response = eth.connect(); pc.printf("IP Address: %s " CRLF CRLF, eth.getIPAddress()); ExecuteCommand("Yellow"); pc.printf("Initialize the sensors" CRLF); sensors_init(); read_sensors(); bM2XConfigured = *deviceId && *m2xKey; if (!bM2XConfigured) { pc.printf(RED "Waiting for SMS configuration" CRLF); while (!bM2XConfigured) { ExecuteCommand("Red"); delay(1000); ExecuteCommand("Yellow"); delay(1000); } }; // set up watchdog ticker running every quarter of a second WatchdogTicker.attach(watchdog_check, 0.25); { //WATCHDOG pc.printf(WHT "initialize the M2X time service" CRLF); if (!m2x_status_is_success(timeService.init())) pc.printf("Cannot initialize time service!" CRLF); else { timeService.getTimestamp(timestamp, &length); pc.printf("Current timestamp: %s" CRLF, timestamp); }; }; btn2.fall(&button_2_pressed); btn3.fall(&button_3_pressed); ExecuteCommand("Green"); #ifdef STARTUP_SMS response = sms.send("5277", "IoT StarterKit is now running!"); pc.printf("Startup SMS %s sent." CRLF, response ? "was" : "NOT"); #endif #ifdef COMMANDS_ENABLED { WATCHDOG pc.printf("Query for pending commands ..." CRLF); response = m2xClient.listCommands(deviceId, on_command_found, NULL, "status=pending"); pc.printf("listCommands response code: %d" CRLF, response); }; #endif while (!bStop) { // read sensor values read_sensors(); { WATCHDOG #ifndef SINGLE_UPDATE // post the humidity value pc.printf("Post updateStreamValue (humidity = %.2f)..." CRLF, SENSOR_DATA.Humidity); response = m2xClient.updateStreamValue(deviceId, hStreamName, SENSOR_DATA.Humidity); pc.printf("Post response code: %d" CRLF, response); // post the temp value pc.printf("Post updateStreamValue (temp = %.2f)..." CRLF, SENSOR_DATA.Temperature); response = m2xClient.updateStreamValue(deviceId, tStreamName, SENSOR_DATA.Temperature); pc.printf("Post response code: %d" CRLF, response); // post accelerometer values pc.printf("Post postDeviceUpdate (accelerometer [%.2f,%.2f,%.2f])..." CRLF, SENSOR_DATA.AccelX, SENSOR_DATA.AccelY, SENSOR_DATA.AccelZ); response = m2xClient.postDeviceUpdate(deviceId, 3, accelStreamNames, (float []){SENSOR_DATA.AccelX, SENSOR_DATA.AccelY, SENSOR_DATA.AccelZ}); pc.printf("Post response code: %d" CRLF, response); // post the signal value pc.printf("Post updateStreamValue (signal = %.2f)..." CRLF, SENSOR_DATA.Signal_Strength); response = m2xClient.updateStreamValue(deviceId, sStreamName, SENSOR_DATA.Signal_Strength); pc.printf("Post response code: %d" CRLF, response); // post the signal error value pc.printf("Post updateStreamValue (error = %d)..." CRLF, SENSOR_DATA.Error); response = m2xClient.updateStreamValue(deviceId, eStreamName, SENSOR_DATA.Error); pc.printf("Post response code: %d" CRLF, response); // post the neighbor value pc.printf("Post updateStreamValue (neighbor = %s)..." CRLF, SENSOR_DATA.Neighbor); //response = m2xClient.updateStreamValues(deviceId, nStreamName, SENSOR_DATA.Neighbor); pc.printf("Post response code: %d" CRLF, response); #else // post all values at one 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); response = m2xClient.postDeviceUpdate(deviceId, 5, allStreamNames, (float []){SENSOR_DATA.Humidity, SENSOR_DATA.Temperature, SENSOR_DATA.AccelX, SENSOR_DATA.AccelY, SENSOR_DATA.AccelZ}); pc.printf("Post response code: %d" CRLF, response); #endif timeService.getTimestamp(timestamp, &length); pc.printf("%s waiting for %d seconds... " CRLF , timestamp, commandDelay * commandPolls); }; // save old sensor data, we will use them to check for accelerometer change OLD_SENSOR_DATA = SENSOR_DATA; // sleep loop, check for accelerometer changes and pending commands for (short idx=0; idx < commandPolls; idx++) { // wait commandDelay seconds for (short delays=0; delays < commandDelay; delays++) { delay(1000); // if the buttons were pressed process them immediately process_buttons(); check_accelerometer_change(); // button 3 skips wait and sends data right away if (bSendDataNow || bStop) break; }; #ifdef COMMANDS_ENABLED // and then query for commands { WATCHDOG pc.printf("\tQuery for pending commands ..." CRLF); response = m2xClient.listCommands(deviceId, on_command_found, NULL, "status=pending"); pc.printf("\tlistCommands response code: %d" CRLF, response); }; #endif //if button 3 was pressed skip the wait and send data right away if (bSendDataNow || bStop) { bSendDataNow = false; break; }; } }; pc.printf("Done sending data. Still accepting SMS commands." CRLF); bStop = false; while (!bStop) { delay(1000); }; pc.printf("- - - - - - - THE END - - - - - - - " CRLF); NVIC_SystemReset(); }