Aeris Workshop program to read Moisture sensor and send the data to AerCloud using MQTT
Revision 0:9c4dbd5b0a33, committed 2015-06-16
- 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
--- /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