Aeris Workshop program to read Moisture sensor and send the data to AerCloud using MQTT

Dependencies:   MQTT mbed-src

Files at this revision

API Documentation at this revision

Comitter:
agoel
Date:
Tue Jun 16 19:04:09 2015 +0000
Child:
1:4e6e185783c2
Commit message:
First Version of Aeris Moisture Workshop to be used on 18/Jun/2015

Changed in this revision

MQTT.lib Show annotated file Show diff for this revision Revisions of this file
main.cpp Show annotated file Show diff for this revision Revisions of this file
mbed-src.lib Show annotated file Show diff for this revision Revisions of this file
mtsas.lib Show annotated file Show diff for this revision Revisions of this file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/MQTT.lib	Tue Jun 16 19:04:09 2015 +0000
@@ -0,0 +1,1 @@
+http://developer.mbed.org/users/mfiore/code/MQTT/#66fba174d875
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/main.cpp	Tue Jun 16 19:04:09 2015 +0000
@@ -0,0 +1,414 @@
+/*
+     Dragon Fly Sample Program for MultiTech Connected Cooler Workshop - reading value from Alcohol and Moisture sesnor
+*/
+
+// AerCloud sample code for Dragon Fly Sample Program for MultiTech Connected Cooler - created for following hardware:
+//   ST Nucleo F411RE   http://developer.mbed.org/platforms/ST-Nucleo-F411RE/
+//   ST Sensor Board  http://developer.mbed.org/teams/ST-Americas-mbed-Team/wiki/Getting-Started-with-Nucleo-Sensors
+//   MultiTech Socket Modem Shield: http://developer.mbed.org/components/Multi-Tech-SocketModem-Arduino-Shield-MT/
+//   MultiTech http://developer.mbed.org/teams/Multi-Hackers/code/MTSAS_Cellular_HTTP_Example/
+//  Details on AerCloud: http://www.aeris.com/technology/aercloud/
+//  AerCloud Developer Forum: https://developer.aeris.com/
+//
+// Sample writes moistureValue & alcoholValue to an AerCloud container
+//
+// Dependencies:
+//     mbed HTTP Client Libary
+//     mbed MQTT Client Libary
+//     DragonFly Support Library
+//     mtsas Modem Library
+//     mbed Library
+//
+// To get the sample running, you'll need to fill in the following parameters below
+//   Your cellular provider's APN: APN
+//   AerCloud API Key: AC_APIKEY
+//   AerCloud Account ID: acId
+//   AerCloud Container: AC_CONTAINER
+//
+// and you'll also need to create an AerCloud contianer with the schema
+// described below
+//
+
+#include "mbed.h"
+#include "mtsas.h"
+#include "HTTPClient.h"
+#include "PubSubClient.h"
+
+//------------------------------------------------------------------------------------
+// Connectivity Parameters
+//------------------------------------------------------------------------------------
+
+//! Aeris SIM does not use PIN
+#define SIMPIN      NULL
+
+//! The APN of your Aeris SIM
+//    You can find the APN for your SIM at https://aerport.aeris.com
+char _APN[] = "aer.aerisapn.net";
+
+//! User name and password are not required to use Aeris APN
+#define USERNAME    NULL
+
+//! User name and password are not required to use Aeris APN
+#define PASSWORD    NULL
+
+// ------------------------------------------------------------------------------------
+// AerCloud Paramers
+// ------------------------------------------------------------------------------------
+
+// AerCloud BASE URL
+#define AC_BASE     "http://api.aercloud.aeris.com/v1"
+
+//! AerCloud API Key
+//   You can find your api key at https://aerport.aeris.com"
+char _AERCLOUD_API_KEY[] = "ff767bee-f5bf-403b-badb-fde13bc2b756";
+
+//! Aercloud Account Id
+//   You can find your account id at https://aerport.aeris.com
+char _AERCLOUD_ACCOUNT_ID[] = "10975";
+
+// AerCloud Container
+//  The name of the AerCloud Container to write data into
+char _AERCLOUD_CONTAINER[] = "AERIS_WORKSHOP_MAIN";
+char _AERCLOUD_CONTAINER_ALARM[] = "AERIS_WORKSHOP_ALARM";
+
+// AerCloud Device Id
+//  The Device Id that is registered and provisioned at AerCloud 
+//  (random value here program automatically detects and provision it)
+char _AERCLOUD_DEVICE_ID[] = "*****-nucleo-0001-***********"; 
+ 
+char _host[] = "mqtt.aercloud.aeris.com";
+int _port = 1883;
+
+//------------------------------------------------------------------------------------
+// AerCloud SCL (Device) Data Model
+// ------------------------------------------------------------------------------------
+//
+// Code assumes an AerCloud Data Model (AERIS_WORKSHOP_MAIN) with following fields
+//
+//  moistureSensorValue     FLOAT       Value read frrom moisture sensor
+//  moistureProcessedValue  FLOAT       Processed value of moisture sensor (LOW / MEDIUM / HIGH)
+//  alcoholSensorValue      FLOAT       Value read frrom alcohol sensor
+//  alcoholProcessedValue   FLOAT       Processed value of alcohol sensor (LOW / MEDIUM / HIGH)
+//  sclid                   INT         Device-id
+//  timeStamp               LONG        timestamp when event occurred
+//
+// Code assumes an AerCloud Data Model (AERIS_WORKSHOP_ALARM) with following fields
+//
+//  alarmText           STRING  alarm string
+//  timeStamp           LONG    time at which alarn has been generated
+//  sclid               INT     Device-id
+//
+//------------------------------------------------------------------------------------
+
+
+// Define alcoholSensor and moisture input PIN (Arduino connector namings A0 - PA_0, A1 - PA_1, A2 - PC_4, A3 - PB_0, A4 - PC_1, A5 - PC_0
+AnalogIn moistureSensor(PC_2);        // A0 - PA_0
+AnalogIn alcoholSensor(PB_0);   // A3
+
+float moistureValue = 0.0f;
+float alcoholValue = 0.0f;
+float moistureProcessedValue = 0.0f;
+float alcoholProcessedValue = 0.0f;
+
+float moistureLastPeakValue = 0.0f;
+float alcoholLastPeakValue = 0.0f;
+
+// Enumeration for Range
+#define LOW     1
+#define MEDIUM  2
+#define HIGH    3
+
+char str[512];
+char *simImei;
+
+const char* HttpResultToString(HTTPResult r)
+{
+    switch(r) {
+        case HTTP_PROCESSING:
+            return "HTTP_PROCESSING";
+        case HTTP_PARSE:
+            return "HTTP_PARSE";
+        case HTTP_DNS:
+            return "HTTP_DNS";
+        case HTTP_PRTCL:
+            return "HTTP_PRTCL";
+        case HTTP_NOTFOUND:
+            return "HTTP_NOTFOUND - 404";
+        case HTTP_REFUSED:
+            return "HTTP_REFUSED - 403";
+        case HTTP_ERROR:
+            return "HTTP_ERROR";
+        case HTTP_TIMEOUT:
+            return "HTTP_TIMEOUT";
+        case HTTP_CONN:
+            return "HTTP_CONN";
+        case HTTP_CLOSED:
+            return "HTTP_CLOSED";
+        case HTTP_OK:
+            return "HTTP_OK";
+    }
+    return "UNKNOWN ERROR CODE";
+}
+
+void callback(char* topic, char* payload, unsigned int len) {
+    logInfo("topic: [%s]\r\npayload: [%s]", topic, payload);
+}
+
+int main()
+{
+    bool simProvisioned = false;
+    int ret;
+
+    printf("Dragon Fly Sample Program for MultiTech Board - Sample Workshop Program ...\n\r");
+
+    //Sets the log level to INFO, higher log levels produce more log output.
+    //Possible levels: NONE, FATAL, ERROR, WARNING, INFO, DEBUG, TRACE
+    MTSLog::setLogLevel(MTSLog::TRACE_LEVEL);
+
+    /** STMicro Nucelo F411RE
+    * The supported jumper configurations of the MTSAS do not line up with
+    * the pin mapping of the Nucleo F411RE. Therefore, the MTSAS serial TX
+    * pin (JP8 Pin 2) must be manually jumped to Serial1 RX (Shield pin D2)
+    * and the MTSAS serial RX pin (JP9 Pin 2) pin must be manually jumped to
+    * Serial1 TX (Shield pin D8).
+    */
+    MTSSerialFlowControl* io = new MTSSerialFlowControl(RADIO_TX, RADIO_RX, RADIO_RTS, RADIO_CTS);
+
+    //Sets the baud rate for communicating with the radio
+    io->baud(115200);
+
+    //Creates a radio object
+    Cellular* radio = CellularFactory::create(io);
+
+    if (! radio) {
+        logFatal("failed to create Cellular object - exiting");
+        printf("failed to create Cellular object - exiting.\n\r");
+        return 1;
+    }
+
+//    radio->configureSignals(D11,D7,RESET);          // Modified Flow Control for ST Sensor Board  D11
+    Transport::setTransport(radio);                 // Required to control Cell Radio vs WiFi solution
+
+    while (radio->setApn(_APN) != MTS_SUCCESS) {
+        logError("failed to set APN [%s]", _APN);
+        printf("failed to set APN.\n\r");
+        wait(2);
+    }
+
+    while (! radio->connect()) {
+        logError("failed to bring up PPP link");
+        printf("failed to bring up PPP link.\n\r");
+        wait(2);
+    }
+
+    printf("Signal Strength: %d\n\r", radio->getSignalStrength()); //Check the signal strength should be above 8
+
+    // If you suspect a connectivity issue, uncomment the code below and if ping works.  If you are not getting a
+    //  valid ping, there's a connectivity problem.  First step is to verify you've got the right APN set
+    //
+    // Try pinging default server "8.8.8.8" (Google's DNS)
+    int ping_valid = 0;
+    while (ping_valid == 0) {
+        ping_valid = radio->ping();
+        // or can use ping_valid = radio->ping("www.google.com");
+        printf("Ping Valid: %s\n\r", ping_valid ? "true" : "false");
+        if (ping_valid == 0) {
+            wait(3);
+            printf("wait 3");
+        }
+    }
+
+    // Get the IMEI of the SIM, this will act as SCL-id on AerCloud
+    string sImei;
+    sImei = radio->getEquipmentIdentifier();
+    simImei = (char*) sImei.c_str();
+    strcpy (_AERCLOUD_DEVICE_ID, simImei);
+
+    // Create http client
+    HTTPClient http;
+
+    // Check if SIM is provisioned in AerCloud
+    printf("\r\nIs the SIM provisioned?  ");
+    char url[512];
+    snprintf(url, sizeof(url), "%s/%s/scls/%s?apiKey=%s", AC_BASE, _AERCLOUD_ACCOUNT_ID, simImei, _AERCLOUD_API_KEY);
+    ret = http.get(url, str, 128);
+    printf("URL : %s", url);
+    printf("STR : %s", str);
+
+    if (ret == HTTP_OK) {
+        // We're already provisioned
+        printf("Yes\r\n");
+        printf("Page fetched successfully - read %d characters\r\n", strlen(str));
+        printf("Result: %s\r\n", str);
+        simProvisioned = true;
+    } else {
+        printf("No\r\n");
+        printf("Error - ret = %d - HTTP return code = %d\r\n", ret, http.getHTTPResponseCode());
+
+        //SIM is not provisioned. trying to provision it...
+        char url[512];
+        snprintf(url, sizeof(url), "%s/%s/scls?apiKey=%s", AC_BASE, _AERCLOUD_ACCOUNT_ID, _AERCLOUD_API_KEY);
+        snprintf(str, sizeof(str), "{\"sclId\":\"%s\"}\0",simImei);
+        HTTPJson outText(str);
+        HTTPJson inText(str, 512);
+        ret = http.post(url, outText, &inText);
+
+        if (!ret) {
+            printf("Executed POST successfully - read %d characters\r\n", strlen(str));
+            printf("Result: %s\r\n", str);
+            simProvisioned = true;
+        } else {
+            if(http.getHTTPResponseCode() == 200)
+                simProvisioned = true;
+            printf("Error - ret = %d - HTTP return code = %d\r\n", ret, http.getHTTPResponseCode());
+        }
+    }
+
+    PubSubClient mqtt(_host, _port, callback);
+    unsigned int connectRetry = 0;
+    while(! mqtt.connect(_AERCLOUD_DEVICE_ID, _AERCLOUD_ACCOUNT_ID, _AERCLOUD_API_KEY)) {
+        logError("failed to connect to AerCloud Server");
+        wait(5);
+        connectRetry++;
+        if (connectRetry > 5) break;
+    }
+
+    //POST data to containers if SIM has been successfully provisioned
+    if (simProvisioned) {
+        while(1) {
+
+            // Read data from sensor
+            char alarmStringM[512] = "";
+            bool generateAlertM = false;
+
+            moistureValue = moistureSensor;
+            printf("Moisture value read : %f \n\n",moistureValue);
+            if (moistureValue > .5f) {
+                moistureProcessedValue = HIGH;
+            } else if (moistureValue > .25f) {
+                moistureProcessedValue = MEDIUM;
+            } else {
+                moistureProcessedValue = LOW;
+            }
+
+            if (moistureLastPeakValue != moistureProcessedValue) {  //condition to trigger alarm
+                if (moistureLastPeakValue == 0) {                   // first time
+                    moistureLastPeakValue = moistureProcessedValue;
+                    generateAlertM = false;
+                } else {
+                    if (moistureLastPeakValue == LOW) {
+                        if (moistureProcessedValue == MEDIUM) {
+                            strcpy (alarmStringM, "Moisture level going up from LOW to MEDIUM");
+                        } else if (moistureProcessedValue == HIGH) {
+                            strcpy (alarmStringM, "Moisture level going up from LOW to HIGH");
+                        }
+                    } else if (moistureLastPeakValue == MEDIUM) {
+                        if (moistureProcessedValue == LOW) {
+                            strcpy (alarmStringM, "Moisture level going down from MEDIUM to LOW");
+                        } else if (moistureProcessedValue == HIGH) {
+                            strcpy (alarmStringM, "Moisture level going up from MEDIUM to HIGH");
+                        }
+                    } else if (moistureLastPeakValue == HIGH) {
+                        if (moistureProcessedValue == LOW) {
+                            strcpy (alarmStringM, "Moisture level going down from HIGH to LOW");
+                        } else if (moistureProcessedValue == MEDIUM) {
+                            strcpy (alarmStringM, "Moisture level going down from HIGH to MEDIUM");
+                        }
+                    }
+                    moistureLastPeakValue = moistureProcessedValue;
+                    generateAlertM = true;
+                }
+            }
+            
+            char alarmStringA[512] = "";
+            bool generateAlertA = false;
+
+            alcoholValue = 1 - alcoholSensor; // as per example logic value needs to be subtracted from 1 (inverse value)
+            printf("Alcohol value read : %f \n\n",alcoholValue);
+            if (alcoholValue > .5f) {
+                alcoholProcessedValue = HIGH;
+            } else if (alcoholValue > .25f) {
+                alcoholProcessedValue = MEDIUM;
+            } else {
+                alcoholProcessedValue = LOW;
+            }
+
+            if (alcoholLastPeakValue != alcoholProcessedValue) {  //condition to trigger alarm
+                if (alcoholLastPeakValue == 0) {                   // first time
+                    alcoholLastPeakValue = alcoholProcessedValue;
+                    generateAlertA = false;
+                } else {
+                    if (alcoholLastPeakValue == LOW) {
+                        if (alcoholProcessedValue == MEDIUM) {
+                            strcpy (alarmStringA, "Alcohol level going up from LOW to MEDIUM");
+                        } else if (alcoholProcessedValue == HIGH) {
+                            strcpy (alarmStringA, "Alcohol level going up from LOW to HIGH");
+                        }
+                    } else if (alcoholLastPeakValue == MEDIUM) {
+                        if (alcoholProcessedValue == LOW) {
+                            strcpy (alarmStringA, "Alcohol level going down from MEDIUM to LOW");
+                        } else if (alcoholProcessedValue == HIGH) {
+                            strcpy (alarmStringA, "Alcohol level going up from MEDIUM to HIGH");
+                        }
+                    } else if (alcoholLastPeakValue == HIGH) {
+                        if (alcoholProcessedValue == LOW) {
+                            strcpy (alarmStringA, "Alcohol level going down from HIGH to LOW");
+                        } else if (alcoholProcessedValue == MEDIUM) {
+                            strcpy (alarmStringA, "Alcohol level going down from HIGH to MEDIUM");
+                        }
+                    }
+                    alcoholLastPeakValue = alcoholProcessedValue;
+                    generateAlertA = true;
+                }
+            }
+ 
+            // POST data to AerCloud using MQTT 
+            time_t seconds = time(NULL);
+            sprintf(str,"{\"moistureSensorValue\": %.5f, \"moistureProcessedValue\": %.2f, \"alcoholSensorValue\": %.5f, \"alcoholProcessedValue\": %.2f, \"sclId\":\"%s\", \"timeStamp\": %u}", moistureValue, moistureProcessedValue, alcoholValue, alcoholProcessedValue, simImei, seconds);
+
+            printf("str = %s \r\n",str);
+            time_t beforeTime = time(NULL);
+            printf("\r\nAcquired data going to post now...  %u \r\n", beforeTime);
+            if (! mqtt.publish(_AERCLOUD_CONTAINER, str)) {
+                printf("failed to publish: [%s]", str);
+            }
+            wait_ms (100); // wait for 100 ms to get the data published
+            printf("\r\nPosted data took ...  %u seconds \r\n", time(NULL)-beforeTime );
+
+            // post alert for Moisture
+            if (generateAlertM) {
+                sprintf(str,"{\"alarmText\": \"%s\", \"sclId\":\"%s\", \"timeStamp\": %u}", alarmStringM, simImei, seconds);
+                printf("str = %s \r\n",str);
+                time_t beforeTime = time(NULL);
+                printf("\r\nAcquired data going to post now...  %u \r\n", beforeTime);
+                if (! mqtt.publish(_AERCLOUD_CONTAINER_ALARM, str)) {
+                    printf("failed to publish: [%s]", str);
+                }
+                wait_ms (100); // wait for 100 ms to get the data published
+                printf("\r\nPosted data took ...  %u seconds \r\n", time(NULL)-beforeTime );
+            }
+            
+            // post alert for Alcohol
+            if (generateAlertA) {
+                sprintf(str,"{\"alarmText\": \"%s\", \"sclId\":\"%s\", \"timeStamp\": %u}", alarmStringA, simImei, seconds);
+                printf("str = %s \r\n",str);
+                time_t beforeTime = time(NULL);
+                printf("\r\nAcquired data going to post now...  %u \r\n", beforeTime);
+                if (! mqtt.publish(_AERCLOUD_CONTAINER_ALARM, str)) {
+                    printf("failed to publish: [%s]", str);
+                }
+                wait_ms (100); // wait for 100 ms to get the data published
+                printf("\r\nPosted data took ...  %u seconds \r\n", time(NULL)-beforeTime );
+            }
+
+            printf("Will be measuring again after 1 seconds !!!! \r\n\n");
+            wait (1);
+            moistureValue = 0;
+        }
+    }
+
+    //Disconnect ppp link of radio
+    mqtt.disconnect();
+    //Disconnect ppp link of radio
+    radio->disconnect();
+}
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/mbed-src.lib	Tue Jun 16 19:04:09 2015 +0000
@@ -0,0 +1,1 @@
+http://mbed.org/users/mbed_official/code/mbed-src/#18c5cf67e74d
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/mtsas.lib	Tue Jun 16 19:04:09 2015 +0000
@@ -0,0 +1,1 @@
+http://developer.mbed.org/teams/Multi-Hackers/code/mtsas/#efa4a5981370