Aeris Workshop program to read Moisture sensor and send the data to AerCloud using MQTT
main.cpp
- Committer:
- agoel
- Date:
- 2015-06-16
- Revision:
- 0:9c4dbd5b0a33
- Child:
- 1:4e6e185783c2
File content as of revision 0:9c4dbd5b0a33:
/* 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(); }