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

Dependencies:   MQTT mbed-src

Committer:
agoel
Date:
Wed Jun 17 22:55:16 2015 +0000
Revision:
3:db681a5cf46f
Parent:
2:08cbf9d1754f
TimeZone correction in setting time for RTC of the dragon fly board

Who changed what in which revision?

UserRevisionLine numberNew contents of line
agoel 0:9c4dbd5b0a33 1 /*
agoel 0:9c4dbd5b0a33 2 Dragon Fly Sample Program for MultiTech Connected Cooler Workshop - reading value from Alcohol and Moisture sesnor
agoel 0:9c4dbd5b0a33 3 */
agoel 0:9c4dbd5b0a33 4
agoel 0:9c4dbd5b0a33 5 // AerCloud sample code for Dragon Fly Sample Program for MultiTech Connected Cooler - created for following hardware:
agoel 0:9c4dbd5b0a33 6 // ST Nucleo F411RE http://developer.mbed.org/platforms/ST-Nucleo-F411RE/
agoel 0:9c4dbd5b0a33 7 // ST Sensor Board http://developer.mbed.org/teams/ST-Americas-mbed-Team/wiki/Getting-Started-with-Nucleo-Sensors
agoel 0:9c4dbd5b0a33 8 // MultiTech Socket Modem Shield: http://developer.mbed.org/components/Multi-Tech-SocketModem-Arduino-Shield-MT/
agoel 0:9c4dbd5b0a33 9 // MultiTech http://developer.mbed.org/teams/Multi-Hackers/code/MTSAS_Cellular_HTTP_Example/
agoel 0:9c4dbd5b0a33 10 // Details on AerCloud: http://www.aeris.com/technology/aercloud/
agoel 0:9c4dbd5b0a33 11 // AerCloud Developer Forum: https://developer.aeris.com/
agoel 0:9c4dbd5b0a33 12 //
agoel 0:9c4dbd5b0a33 13 // Sample writes moistureValue & alcoholValue to an AerCloud container
agoel 0:9c4dbd5b0a33 14 //
agoel 0:9c4dbd5b0a33 15 // Dependencies:
agoel 0:9c4dbd5b0a33 16 // mbed HTTP Client Libary
agoel 0:9c4dbd5b0a33 17 // mbed MQTT Client Libary
agoel 0:9c4dbd5b0a33 18 // DragonFly Support Library
agoel 0:9c4dbd5b0a33 19 // mtsas Modem Library
agoel 0:9c4dbd5b0a33 20 // mbed Library
agoel 0:9c4dbd5b0a33 21 //
agoel 0:9c4dbd5b0a33 22 // To get the sample running, you'll need to fill in the following parameters below
agoel 0:9c4dbd5b0a33 23 // Your cellular provider's APN: APN
agoel 0:9c4dbd5b0a33 24 // AerCloud API Key: AC_APIKEY
agoel 0:9c4dbd5b0a33 25 // AerCloud Account ID: acId
agoel 0:9c4dbd5b0a33 26 // AerCloud Container: AC_CONTAINER
agoel 0:9c4dbd5b0a33 27 //
agoel 0:9c4dbd5b0a33 28 // and you'll also need to create an AerCloud contianer with the schema
agoel 0:9c4dbd5b0a33 29 // described below
agoel 0:9c4dbd5b0a33 30 //
agoel 0:9c4dbd5b0a33 31
agoel 0:9c4dbd5b0a33 32 #include "mbed.h"
agoel 0:9c4dbd5b0a33 33 #include "mtsas.h"
agoel 0:9c4dbd5b0a33 34 #include "HTTPClient.h"
agoel 0:9c4dbd5b0a33 35 #include "PubSubClient.h"
agoel 0:9c4dbd5b0a33 36
agoel 0:9c4dbd5b0a33 37 //------------------------------------------------------------------------------------
agoel 0:9c4dbd5b0a33 38 // Connectivity Parameters
agoel 0:9c4dbd5b0a33 39 //------------------------------------------------------------------------------------
agoel 0:9c4dbd5b0a33 40
agoel 0:9c4dbd5b0a33 41 //! Aeris SIM does not use PIN
agoel 0:9c4dbd5b0a33 42 #define SIMPIN NULL
agoel 0:9c4dbd5b0a33 43
agoel 0:9c4dbd5b0a33 44 //! The APN of your Aeris SIM
agoel 0:9c4dbd5b0a33 45 // You can find the APN for your SIM at https://aerport.aeris.com
agoel 0:9c4dbd5b0a33 46 char _APN[] = "aer.aerisapn.net";
agoel 0:9c4dbd5b0a33 47
agoel 0:9c4dbd5b0a33 48 //! User name and password are not required to use Aeris APN
agoel 0:9c4dbd5b0a33 49 #define USERNAME NULL
agoel 0:9c4dbd5b0a33 50
agoel 0:9c4dbd5b0a33 51 //! User name and password are not required to use Aeris APN
agoel 0:9c4dbd5b0a33 52 #define PASSWORD NULL
agoel 0:9c4dbd5b0a33 53
agoel 0:9c4dbd5b0a33 54 // ------------------------------------------------------------------------------------
agoel 0:9c4dbd5b0a33 55 // AerCloud Paramers
agoel 0:9c4dbd5b0a33 56 // ------------------------------------------------------------------------------------
agoel 0:9c4dbd5b0a33 57
agoel 0:9c4dbd5b0a33 58 // AerCloud BASE URL
agoel 0:9c4dbd5b0a33 59 #define AC_BASE "http://api.aercloud.aeris.com/v1"
agoel 0:9c4dbd5b0a33 60
agoel 0:9c4dbd5b0a33 61 //! AerCloud API Key
agoel 0:9c4dbd5b0a33 62 // You can find your api key at https://aerport.aeris.com"
agoel 2:08cbf9d1754f 63 char _AERCLOUD_API_KEY[] = "<Set Your AerCloud Account API KEY>"; // ff767bee-f5bf-403b-badb-fde13bc2b756
agoel 0:9c4dbd5b0a33 64
agoel 0:9c4dbd5b0a33 65 //! Aercloud Account Id
agoel 0:9c4dbd5b0a33 66 // You can find your account id at https://aerport.aeris.com
agoel 2:08cbf9d1754f 67 char _AERCLOUD_ACCOUNT_ID[] = "<Set Your AerCloud Account Id>"; // 10975
agoel 0:9c4dbd5b0a33 68
agoel 0:9c4dbd5b0a33 69 // AerCloud Container
agoel 0:9c4dbd5b0a33 70 // The name of the AerCloud Container to write data into
agoel 0:9c4dbd5b0a33 71 char _AERCLOUD_CONTAINER[] = "AERIS_WORKSHOP_MAIN";
agoel 0:9c4dbd5b0a33 72 char _AERCLOUD_CONTAINER_ALARM[] = "AERIS_WORKSHOP_ALARM";
agoel 0:9c4dbd5b0a33 73
agoel 0:9c4dbd5b0a33 74 // AerCloud Device Id
agoel 0:9c4dbd5b0a33 75 // The Device Id that is registered and provisioned at AerCloud
agoel 0:9c4dbd5b0a33 76 // (random value here program automatically detects and provision it)
agoel 0:9c4dbd5b0a33 77 char _AERCLOUD_DEVICE_ID[] = "*****-nucleo-0001-***********";
agoel 0:9c4dbd5b0a33 78
agoel 0:9c4dbd5b0a33 79 char _host[] = "mqtt.aercloud.aeris.com";
agoel 0:9c4dbd5b0a33 80 int _port = 1883;
agoel 0:9c4dbd5b0a33 81
agoel 0:9c4dbd5b0a33 82 //------------------------------------------------------------------------------------
agoel 0:9c4dbd5b0a33 83 // AerCloud SCL (Device) Data Model
agoel 0:9c4dbd5b0a33 84 // ------------------------------------------------------------------------------------
agoel 0:9c4dbd5b0a33 85 //
agoel 0:9c4dbd5b0a33 86 // Code assumes an AerCloud Data Model (AERIS_WORKSHOP_MAIN) with following fields
agoel 0:9c4dbd5b0a33 87 //
agoel 0:9c4dbd5b0a33 88 // moistureSensorValue FLOAT Value read frrom moisture sensor
agoel 0:9c4dbd5b0a33 89 // moistureProcessedValue FLOAT Processed value of moisture sensor (LOW / MEDIUM / HIGH)
agoel 0:9c4dbd5b0a33 90 // alcoholSensorValue FLOAT Value read frrom alcohol sensor
agoel 0:9c4dbd5b0a33 91 // alcoholProcessedValue FLOAT Processed value of alcohol sensor (LOW / MEDIUM / HIGH)
agoel 0:9c4dbd5b0a33 92 // sclid INT Device-id
agoel 0:9c4dbd5b0a33 93 // timeStamp LONG timestamp when event occurred
agoel 0:9c4dbd5b0a33 94 //
agoel 0:9c4dbd5b0a33 95 // Code assumes an AerCloud Data Model (AERIS_WORKSHOP_ALARM) with following fields
agoel 0:9c4dbd5b0a33 96 //
agoel 0:9c4dbd5b0a33 97 // alarmText STRING alarm string
agoel 0:9c4dbd5b0a33 98 // timeStamp LONG time at which alarn has been generated
agoel 0:9c4dbd5b0a33 99 // sclid INT Device-id
agoel 0:9c4dbd5b0a33 100 //
agoel 0:9c4dbd5b0a33 101 //------------------------------------------------------------------------------------
agoel 0:9c4dbd5b0a33 102
agoel 0:9c4dbd5b0a33 103
agoel 0:9c4dbd5b0a33 104 // 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
agoel 3:db681a5cf46f 105 AnalogIn moistureSensor(PC_2); // A0 - PA_0
agoel 3:db681a5cf46f 106 AnalogIn alcoholSensor(PB_0); // A3
agoel 0:9c4dbd5b0a33 107
agoel 0:9c4dbd5b0a33 108 float moistureValue = 0.0f;
agoel 0:9c4dbd5b0a33 109 float alcoholValue = 0.0f;
agoel 0:9c4dbd5b0a33 110 float moistureProcessedValue = 0.0f;
agoel 0:9c4dbd5b0a33 111 float alcoholProcessedValue = 0.0f;
agoel 0:9c4dbd5b0a33 112
agoel 0:9c4dbd5b0a33 113 float moistureLastPeakValue = 0.0f;
agoel 0:9c4dbd5b0a33 114 float alcoholLastPeakValue = 0.0f;
agoel 0:9c4dbd5b0a33 115
agoel 0:9c4dbd5b0a33 116 // Enumeration for Range
agoel 0:9c4dbd5b0a33 117 #define LOW 1
agoel 0:9c4dbd5b0a33 118 #define MEDIUM 2
agoel 0:9c4dbd5b0a33 119 #define HIGH 3
agoel 0:9c4dbd5b0a33 120
agoel 0:9c4dbd5b0a33 121 char str[512];
agoel 0:9c4dbd5b0a33 122 char *simImei;
agoel 0:9c4dbd5b0a33 123
agoel 0:9c4dbd5b0a33 124 const char* HttpResultToString(HTTPResult r)
agoel 0:9c4dbd5b0a33 125 {
agoel 0:9c4dbd5b0a33 126 switch(r) {
agoel 0:9c4dbd5b0a33 127 case HTTP_PROCESSING:
agoel 0:9c4dbd5b0a33 128 return "HTTP_PROCESSING";
agoel 0:9c4dbd5b0a33 129 case HTTP_PARSE:
agoel 0:9c4dbd5b0a33 130 return "HTTP_PARSE";
agoel 0:9c4dbd5b0a33 131 case HTTP_DNS:
agoel 0:9c4dbd5b0a33 132 return "HTTP_DNS";
agoel 0:9c4dbd5b0a33 133 case HTTP_PRTCL:
agoel 0:9c4dbd5b0a33 134 return "HTTP_PRTCL";
agoel 0:9c4dbd5b0a33 135 case HTTP_NOTFOUND:
agoel 0:9c4dbd5b0a33 136 return "HTTP_NOTFOUND - 404";
agoel 0:9c4dbd5b0a33 137 case HTTP_REFUSED:
agoel 0:9c4dbd5b0a33 138 return "HTTP_REFUSED - 403";
agoel 0:9c4dbd5b0a33 139 case HTTP_ERROR:
agoel 0:9c4dbd5b0a33 140 return "HTTP_ERROR";
agoel 0:9c4dbd5b0a33 141 case HTTP_TIMEOUT:
agoel 0:9c4dbd5b0a33 142 return "HTTP_TIMEOUT";
agoel 0:9c4dbd5b0a33 143 case HTTP_CONN:
agoel 0:9c4dbd5b0a33 144 return "HTTP_CONN";
agoel 0:9c4dbd5b0a33 145 case HTTP_CLOSED:
agoel 0:9c4dbd5b0a33 146 return "HTTP_CLOSED";
agoel 0:9c4dbd5b0a33 147 case HTTP_OK:
agoel 0:9c4dbd5b0a33 148 return "HTTP_OK";
agoel 0:9c4dbd5b0a33 149 }
agoel 0:9c4dbd5b0a33 150 return "UNKNOWN ERROR CODE";
agoel 0:9c4dbd5b0a33 151 }
agoel 0:9c4dbd5b0a33 152
agoel 0:9c4dbd5b0a33 153 void callback(char* topic, char* payload, unsigned int len) {
agoel 0:9c4dbd5b0a33 154 logInfo("topic: [%s]\r\npayload: [%s]", topic, payload);
agoel 0:9c4dbd5b0a33 155 }
agoel 0:9c4dbd5b0a33 156
agoel 2:08cbf9d1754f 157 // Function to set RTC clock using the time received from Radio
agoel 2:08cbf9d1754f 158 // This is required as the board does not have a clock so every time board gets reset the RTC clock gets reset too.
agoel 2:08cbf9d1754f 159 void set_current_time (Cellular* radio)
agoel 2:08cbf9d1754f 160 {
agoel 2:08cbf9d1754f 161 string response = radio->sendCommand("AT+CCLK?", 1000);
agoel 2:08cbf9d1754f 162 if (response.find("+CCLK: ") == string::npos) {
agoel 2:08cbf9d1754f 163 printf("Error : Could not retrieve time \n\n\n");
agoel 2:08cbf9d1754f 164 }
agoel 2:08cbf9d1754f 165 // printf("Output from AT Command\n%s", response.c_str());
agoel 2:08cbf9d1754f 166
agoel 2:08cbf9d1754f 167 char dateString [256];
agoel 2:08cbf9d1754f 168 char timeString [256];
agoel 2:08cbf9d1754f 169 int start = response.find(':');
agoel 2:08cbf9d1754f 170 int stop = response.find(',', start);
agoel 2:08cbf9d1754f 171 string signal = response.substr(start + 2, stop - start - 2);
agoel 2:08cbf9d1754f 172 strcpy (dateString, signal.c_str());
agoel 2:08cbf9d1754f 173 string signal2 = response.substr(stop+1);
agoel 2:08cbf9d1754f 174 strcpy (timeString, signal2.c_str());
agoel 2:08cbf9d1754f 175 // printf("***** Date String ****** %s \n\n", dateString);
agoel 2:08cbf9d1754f 176 // printf("***** Time String ****** %s \n\n", timeString);
agoel 2:08cbf9d1754f 177
agoel 2:08cbf9d1754f 178 char dayStr[2+1];
agoel 2:08cbf9d1754f 179 char monthStr[2+1];
agoel 2:08cbf9d1754f 180 char yearStr[2+1];
agoel 2:08cbf9d1754f 181
agoel 2:08cbf9d1754f 182 uint32_t dayInt;
agoel 2:08cbf9d1754f 183 uint32_t monthInt;
agoel 2:08cbf9d1754f 184 uint32_t yearInt;
agoel 2:08cbf9d1754f 185
agoel 2:08cbf9d1754f 186 char hourStr[2+1];
agoel 2:08cbf9d1754f 187 char minuteStr[2+1];
agoel 2:08cbf9d1754f 188 char secStr[2+1];
agoel 3:db681a5cf46f 189 char timeZoneStr[3+1];
agoel 2:08cbf9d1754f 190
agoel 2:08cbf9d1754f 191 uint32_t hourInt;
agoel 2:08cbf9d1754f 192 uint32_t minuteInt;
agoel 2:08cbf9d1754f 193 uint32_t secInt;
agoel 3:db681a5cf46f 194 int32_t tzInt;
agoel 2:08cbf9d1754f 195
agoel 2:08cbf9d1754f 196 //Step 1 - Seperate the day, month and year into their own NULL terminated string buffers...
agoel 2:08cbf9d1754f 197 yearStr[0] = dateString[1];
agoel 2:08cbf9d1754f 198 yearStr[1] = dateString[2];
agoel 2:08cbf9d1754f 199 yearStr[2] = '\0';
agoel 2:08cbf9d1754f 200
agoel 2:08cbf9d1754f 201 monthStr[0] = dateString[4];
agoel 2:08cbf9d1754f 202 monthStr[1] = dateString[5];
agoel 2:08cbf9d1754f 203 monthStr[2] = '\0';
agoel 2:08cbf9d1754f 204
agoel 2:08cbf9d1754f 205 dayStr[0] = dateString[7];
agoel 2:08cbf9d1754f 206 dayStr[1] = dateString[8];
agoel 2:08cbf9d1754f 207 dayStr[2] = '\0';
agoel 2:08cbf9d1754f 208
agoel 2:08cbf9d1754f 209 //Step 2 - Run atoi() to parse the strings into integer values...
agoel 2:08cbf9d1754f 210 dayInt = atoi(dayStr);
agoel 2:08cbf9d1754f 211 monthInt = atoi(monthStr);
agoel 2:08cbf9d1754f 212 yearInt = atoi(yearStr) + 2000;
agoel 2:08cbf9d1754f 213
agoel 2:08cbf9d1754f 214 //Step 3 - Seperate the hour, minute and sec into their own NULL terminated string buffers...
agoel 2:08cbf9d1754f 215 hourStr[0] = timeString[0];
agoel 2:08cbf9d1754f 216 hourStr[1] = timeString[1];
agoel 2:08cbf9d1754f 217 hourStr[2] = '\0';
agoel 2:08cbf9d1754f 218
agoel 2:08cbf9d1754f 219 minuteStr[0] = timeString[3];
agoel 2:08cbf9d1754f 220 minuteStr[1] = timeString[4];
agoel 2:08cbf9d1754f 221 minuteStr[2] = '\0';
agoel 2:08cbf9d1754f 222
agoel 2:08cbf9d1754f 223 secStr[0] = timeString[6];
agoel 2:08cbf9d1754f 224 secStr[1] = timeString[7];
agoel 2:08cbf9d1754f 225 secStr[2] = '\0';
agoel 2:08cbf9d1754f 226
agoel 3:db681a5cf46f 227 timeZoneStr[0] = timeString[8];
agoel 3:db681a5cf46f 228 timeZoneStr[1] = timeString[9];
agoel 3:db681a5cf46f 229 if (timeString[10] != '\"') {
agoel 3:db681a5cf46f 230 timeZoneStr[2] = timeString[10];
agoel 3:db681a5cf46f 231 } else {
agoel 3:db681a5cf46f 232 timeZoneStr[2] = '\0';
agoel 3:db681a5cf46f 233 }
agoel 3:db681a5cf46f 234 timeZoneStr[3] = '\0';
agoel 3:db681a5cf46f 235
agoel 2:08cbf9d1754f 236 //Step 4 - Run atoi() to parse the strings into integer values...
agoel 2:08cbf9d1754f 237 hourInt = atoi(hourStr);
agoel 2:08cbf9d1754f 238 minuteInt = atoi(minuteStr);
agoel 2:08cbf9d1754f 239 secInt = atoi(secStr);
agoel 3:db681a5cf46f 240 tzInt = atoi(timeZoneStr);
agoel 2:08cbf9d1754f 241
agoel 2:08cbf9d1754f 242 time_t rawtime;
agoel 2:08cbf9d1754f 243 struct tm * timeinfo;
agoel 2:08cbf9d1754f 244
agoel 2:08cbf9d1754f 245 // get current timeinfo and modify it to the user's choice
agoel 2:08cbf9d1754f 246 time_t ctTime;
agoel 2:08cbf9d1754f 247 ctTime = time ( &rawtime );
agoel 2:08cbf9d1754f 248 timeinfo = localtime (&rawtime);
agoel 2:08cbf9d1754f 249
agoel 2:08cbf9d1754f 250 // printf("Time before setting is (UTC): %s\r\n", ctime(&ctTime));
agoel 2:08cbf9d1754f 251
agoel 2:08cbf9d1754f 252 //Step 5 - Build up our date data structure...this will be used by the next step...
agoel 2:08cbf9d1754f 253 timeinfo->tm_mday = dayInt;
agoel 2:08cbf9d1754f 254 timeinfo->tm_mon = monthInt - 1; //num months since January - so Jan=0, Feb=1, Mar=2, etc
agoel 2:08cbf9d1754f 255 timeinfo->tm_year = yearInt - 1900; //num years since 1900
agoel 2:08cbf9d1754f 256 timeinfo->tm_hour = hourInt;
agoel 2:08cbf9d1754f 257 timeinfo->tm_min = minuteInt;
agoel 2:08cbf9d1754f 258 timeinfo->tm_sec = secInt;
agoel 2:08cbf9d1754f 259
agoel 2:08cbf9d1754f 260 // printf("***** Year: %s, Month: %s, Day: %s ****** \n\n\n", yearStr, monthStr, dayStr);
agoel 2:08cbf9d1754f 261 // printf("***** Year: %d, Month: %d, Day: %d ****** \n\n\n", yearInt, monthInt, dayInt);
agoel 3:db681a5cf46f 262 // printf("***** hour: %s, minute: %s, sec: %s, TZ: %s ****** \n\n\n", hourStr, minuteStr, secStr, timeZoneStr);
agoel 3:db681a5cf46f 263 // printf("***** hour: %d, minute: %d, sec: %d, TZ: %d ****** \n\n\n", hourInt, minuteInt, secInt, tzInt);
agoel 2:08cbf9d1754f 264
agoel 2:08cbf9d1754f 265 time_t t1=0;
agoel 2:08cbf9d1754f 266 t1 = mktime(timeinfo);
agoel 3:db681a5cf46f 267 set_time (t1 - tzInt*15*60); // offseting the TimeZone Index (received value from string is in quarter of the hour)
agoel 2:08cbf9d1754f 268 ctTime = time (NULL);
agoel 2:08cbf9d1754f 269 printf("Time set to (UTC): %s\r\n", ctime(&ctTime));
agoel 2:08cbf9d1754f 270 }
agoel 2:08cbf9d1754f 271
agoel 3:db681a5cf46f 272
agoel 0:9c4dbd5b0a33 273 int main()
agoel 0:9c4dbd5b0a33 274 {
agoel 0:9c4dbd5b0a33 275 bool simProvisioned = false;
agoel 0:9c4dbd5b0a33 276 int ret;
agoel 0:9c4dbd5b0a33 277
agoel 0:9c4dbd5b0a33 278 printf("Dragon Fly Sample Program for MultiTech Board - Sample Workshop Program ...\n\r");
agoel 0:9c4dbd5b0a33 279
agoel 0:9c4dbd5b0a33 280 //Sets the log level to INFO, higher log levels produce more log output.
agoel 0:9c4dbd5b0a33 281 //Possible levels: NONE, FATAL, ERROR, WARNING, INFO, DEBUG, TRACE
agoel 0:9c4dbd5b0a33 282 MTSLog::setLogLevel(MTSLog::TRACE_LEVEL);
agoel 0:9c4dbd5b0a33 283
agoel 0:9c4dbd5b0a33 284 /** STMicro Nucelo F411RE
agoel 0:9c4dbd5b0a33 285 * The supported jumper configurations of the MTSAS do not line up with
agoel 0:9c4dbd5b0a33 286 * the pin mapping of the Nucleo F411RE. Therefore, the MTSAS serial TX
agoel 0:9c4dbd5b0a33 287 * pin (JP8 Pin 2) must be manually jumped to Serial1 RX (Shield pin D2)
agoel 0:9c4dbd5b0a33 288 * and the MTSAS serial RX pin (JP9 Pin 2) pin must be manually jumped to
agoel 0:9c4dbd5b0a33 289 * Serial1 TX (Shield pin D8).
agoel 0:9c4dbd5b0a33 290 */
agoel 0:9c4dbd5b0a33 291 MTSSerialFlowControl* io = new MTSSerialFlowControl(RADIO_TX, RADIO_RX, RADIO_RTS, RADIO_CTS);
agoel 0:9c4dbd5b0a33 292
agoel 0:9c4dbd5b0a33 293 //Sets the baud rate for communicating with the radio
agoel 0:9c4dbd5b0a33 294 io->baud(115200);
agoel 0:9c4dbd5b0a33 295
agoel 0:9c4dbd5b0a33 296 //Creates a radio object
agoel 0:9c4dbd5b0a33 297 Cellular* radio = CellularFactory::create(io);
agoel 0:9c4dbd5b0a33 298
agoel 0:9c4dbd5b0a33 299 if (! radio) {
agoel 0:9c4dbd5b0a33 300 logFatal("failed to create Cellular object - exiting");
agoel 0:9c4dbd5b0a33 301 printf("failed to create Cellular object - exiting.\n\r");
agoel 0:9c4dbd5b0a33 302 return 1;
agoel 0:9c4dbd5b0a33 303 }
agoel 0:9c4dbd5b0a33 304
agoel 0:9c4dbd5b0a33 305 // radio->configureSignals(D11,D7,RESET); // Modified Flow Control for ST Sensor Board D11
agoel 0:9c4dbd5b0a33 306 Transport::setTransport(radio); // Required to control Cell Radio vs WiFi solution
agoel 0:9c4dbd5b0a33 307
agoel 0:9c4dbd5b0a33 308 while (radio->setApn(_APN) != MTS_SUCCESS) {
agoel 0:9c4dbd5b0a33 309 logError("failed to set APN [%s]", _APN);
agoel 0:9c4dbd5b0a33 310 printf("failed to set APN.\n\r");
agoel 0:9c4dbd5b0a33 311 wait(2);
agoel 0:9c4dbd5b0a33 312 }
agoel 0:9c4dbd5b0a33 313
agoel 0:9c4dbd5b0a33 314 while (! radio->connect()) {
agoel 0:9c4dbd5b0a33 315 logError("failed to bring up PPP link");
agoel 0:9c4dbd5b0a33 316 printf("failed to bring up PPP link.\n\r");
agoel 0:9c4dbd5b0a33 317 wait(2);
agoel 0:9c4dbd5b0a33 318 }
agoel 0:9c4dbd5b0a33 319
agoel 0:9c4dbd5b0a33 320 printf("Signal Strength: %d\n\r", radio->getSignalStrength()); //Check the signal strength should be above 8
agoel 0:9c4dbd5b0a33 321
agoel 0:9c4dbd5b0a33 322 // If you suspect a connectivity issue, uncomment the code below and if ping works. If you are not getting a
agoel 0:9c4dbd5b0a33 323 // valid ping, there's a connectivity problem. First step is to verify you've got the right APN set
agoel 0:9c4dbd5b0a33 324 //
agoel 0:9c4dbd5b0a33 325 // Try pinging default server "8.8.8.8" (Google's DNS)
agoel 0:9c4dbd5b0a33 326 int ping_valid = 0;
agoel 0:9c4dbd5b0a33 327 while (ping_valid == 0) {
agoel 0:9c4dbd5b0a33 328 ping_valid = radio->ping();
agoel 0:9c4dbd5b0a33 329 // or can use ping_valid = radio->ping("www.google.com");
agoel 0:9c4dbd5b0a33 330 printf("Ping Valid: %s\n\r", ping_valid ? "true" : "false");
agoel 0:9c4dbd5b0a33 331 if (ping_valid == 0) {
agoel 0:9c4dbd5b0a33 332 wait(3);
agoel 0:9c4dbd5b0a33 333 printf("wait 3");
agoel 0:9c4dbd5b0a33 334 }
agoel 0:9c4dbd5b0a33 335 }
agoel 0:9c4dbd5b0a33 336
agoel 0:9c4dbd5b0a33 337 // Get the IMEI of the SIM, this will act as SCL-id on AerCloud
agoel 0:9c4dbd5b0a33 338 string sImei;
agoel 0:9c4dbd5b0a33 339 sImei = radio->getEquipmentIdentifier();
agoel 0:9c4dbd5b0a33 340 simImei = (char*) sImei.c_str();
agoel 0:9c4dbd5b0a33 341 strcpy (_AERCLOUD_DEVICE_ID, simImei);
agoel 0:9c4dbd5b0a33 342
agoel 2:08cbf9d1754f 343 // set RTC clock to current time using radio time
agoel 2:08cbf9d1754f 344 set_current_time (radio);
agoel 2:08cbf9d1754f 345
agoel 0:9c4dbd5b0a33 346 // Create http client
agoel 0:9c4dbd5b0a33 347 HTTPClient http;
agoel 0:9c4dbd5b0a33 348
agoel 0:9c4dbd5b0a33 349 // Check if SIM is provisioned in AerCloud
agoel 0:9c4dbd5b0a33 350 printf("\r\nIs the SIM provisioned? ");
agoel 0:9c4dbd5b0a33 351 char url[512];
agoel 0:9c4dbd5b0a33 352 snprintf(url, sizeof(url), "%s/%s/scls/%s?apiKey=%s", AC_BASE, _AERCLOUD_ACCOUNT_ID, simImei, _AERCLOUD_API_KEY);
agoel 0:9c4dbd5b0a33 353 ret = http.get(url, str, 128);
agoel 1:4e6e185783c2 354 // printf("URL : %s", url);
agoel 1:4e6e185783c2 355 // printf("STR : %s", str);
agoel 0:9c4dbd5b0a33 356
agoel 0:9c4dbd5b0a33 357 if (ret == HTTP_OK) {
agoel 0:9c4dbd5b0a33 358 // We're already provisioned
agoel 0:9c4dbd5b0a33 359 printf("Yes\r\n");
agoel 1:4e6e185783c2 360 // printf("Page fetched successfully - read %d characters\r\n", strlen(str));
agoel 1:4e6e185783c2 361 // printf("Result: %s\r\n", str);
agoel 0:9c4dbd5b0a33 362 simProvisioned = true;
agoel 0:9c4dbd5b0a33 363 } else {
agoel 0:9c4dbd5b0a33 364 printf("No\r\n");
agoel 1:4e6e185783c2 365 // printf("Error - ret = %d - HTTP return code = %d\r\n", ret, http.getHTTPResponseCode());
agoel 0:9c4dbd5b0a33 366
agoel 0:9c4dbd5b0a33 367 //SIM is not provisioned. trying to provision it...
agoel 0:9c4dbd5b0a33 368 char url[512];
agoel 0:9c4dbd5b0a33 369 snprintf(url, sizeof(url), "%s/%s/scls?apiKey=%s", AC_BASE, _AERCLOUD_ACCOUNT_ID, _AERCLOUD_API_KEY);
agoel 0:9c4dbd5b0a33 370 snprintf(str, sizeof(str), "{\"sclId\":\"%s\"}\0",simImei);
agoel 0:9c4dbd5b0a33 371 HTTPJson outText(str);
agoel 0:9c4dbd5b0a33 372 HTTPJson inText(str, 512);
agoel 0:9c4dbd5b0a33 373 ret = http.post(url, outText, &inText);
agoel 0:9c4dbd5b0a33 374
agoel 0:9c4dbd5b0a33 375 if (!ret) {
agoel 0:9c4dbd5b0a33 376 printf("Executed POST successfully - read %d characters\r\n", strlen(str));
agoel 1:4e6e185783c2 377 // printf("Result: %s\r\n", str);
agoel 0:9c4dbd5b0a33 378 simProvisioned = true;
agoel 0:9c4dbd5b0a33 379 } else {
agoel 0:9c4dbd5b0a33 380 if(http.getHTTPResponseCode() == 200)
agoel 0:9c4dbd5b0a33 381 simProvisioned = true;
agoel 0:9c4dbd5b0a33 382 printf("Error - ret = %d - HTTP return code = %d\r\n", ret, http.getHTTPResponseCode());
agoel 0:9c4dbd5b0a33 383 }
agoel 0:9c4dbd5b0a33 384 }
agoel 0:9c4dbd5b0a33 385
agoel 0:9c4dbd5b0a33 386 PubSubClient mqtt(_host, _port, callback);
agoel 0:9c4dbd5b0a33 387 unsigned int connectRetry = 0;
agoel 0:9c4dbd5b0a33 388 while(! mqtt.connect(_AERCLOUD_DEVICE_ID, _AERCLOUD_ACCOUNT_ID, _AERCLOUD_API_KEY)) {
agoel 0:9c4dbd5b0a33 389 logError("failed to connect to AerCloud Server");
agoel 0:9c4dbd5b0a33 390 wait(5);
agoel 0:9c4dbd5b0a33 391 connectRetry++;
agoel 0:9c4dbd5b0a33 392 if (connectRetry > 5) break;
agoel 0:9c4dbd5b0a33 393 }
agoel 0:9c4dbd5b0a33 394
agoel 0:9c4dbd5b0a33 395 //POST data to containers if SIM has been successfully provisioned
agoel 0:9c4dbd5b0a33 396 if (simProvisioned) {
agoel 0:9c4dbd5b0a33 397 while(1) {
agoel 0:9c4dbd5b0a33 398
agoel 0:9c4dbd5b0a33 399 // Read data from sensor
agoel 0:9c4dbd5b0a33 400 char alarmStringM[512] = "";
agoel 0:9c4dbd5b0a33 401 bool generateAlertM = false;
agoel 0:9c4dbd5b0a33 402
agoel 0:9c4dbd5b0a33 403 moistureValue = moistureSensor;
agoel 0:9c4dbd5b0a33 404 printf("Moisture value read : %f \n\n",moistureValue);
agoel 0:9c4dbd5b0a33 405 if (moistureValue > .5f) {
agoel 0:9c4dbd5b0a33 406 moistureProcessedValue = HIGH;
agoel 0:9c4dbd5b0a33 407 } else if (moistureValue > .25f) {
agoel 0:9c4dbd5b0a33 408 moistureProcessedValue = MEDIUM;
agoel 0:9c4dbd5b0a33 409 } else {
agoel 0:9c4dbd5b0a33 410 moistureProcessedValue = LOW;
agoel 0:9c4dbd5b0a33 411 }
agoel 0:9c4dbd5b0a33 412
agoel 0:9c4dbd5b0a33 413 if (moistureLastPeakValue != moistureProcessedValue) { //condition to trigger alarm
agoel 0:9c4dbd5b0a33 414 if (moistureLastPeakValue == 0) { // first time
agoel 0:9c4dbd5b0a33 415 moistureLastPeakValue = moistureProcessedValue;
agoel 0:9c4dbd5b0a33 416 generateAlertM = false;
agoel 0:9c4dbd5b0a33 417 } else {
agoel 0:9c4dbd5b0a33 418 if (moistureLastPeakValue == LOW) {
agoel 0:9c4dbd5b0a33 419 if (moistureProcessedValue == MEDIUM) {
agoel 0:9c4dbd5b0a33 420 strcpy (alarmStringM, "Moisture level going up from LOW to MEDIUM");
agoel 0:9c4dbd5b0a33 421 } else if (moistureProcessedValue == HIGH) {
agoel 0:9c4dbd5b0a33 422 strcpy (alarmStringM, "Moisture level going up from LOW to HIGH");
agoel 0:9c4dbd5b0a33 423 }
agoel 0:9c4dbd5b0a33 424 } else if (moistureLastPeakValue == MEDIUM) {
agoel 0:9c4dbd5b0a33 425 if (moistureProcessedValue == LOW) {
agoel 0:9c4dbd5b0a33 426 strcpy (alarmStringM, "Moisture level going down from MEDIUM to LOW");
agoel 0:9c4dbd5b0a33 427 } else if (moistureProcessedValue == HIGH) {
agoel 0:9c4dbd5b0a33 428 strcpy (alarmStringM, "Moisture level going up from MEDIUM to HIGH");
agoel 0:9c4dbd5b0a33 429 }
agoel 0:9c4dbd5b0a33 430 } else if (moistureLastPeakValue == HIGH) {
agoel 0:9c4dbd5b0a33 431 if (moistureProcessedValue == LOW) {
agoel 0:9c4dbd5b0a33 432 strcpy (alarmStringM, "Moisture level going down from HIGH to LOW");
agoel 0:9c4dbd5b0a33 433 } else if (moistureProcessedValue == MEDIUM) {
agoel 0:9c4dbd5b0a33 434 strcpy (alarmStringM, "Moisture level going down from HIGH to MEDIUM");
agoel 0:9c4dbd5b0a33 435 }
agoel 0:9c4dbd5b0a33 436 }
agoel 0:9c4dbd5b0a33 437 moistureLastPeakValue = moistureProcessedValue;
agoel 0:9c4dbd5b0a33 438 generateAlertM = true;
agoel 0:9c4dbd5b0a33 439 }
agoel 0:9c4dbd5b0a33 440 }
agoel 0:9c4dbd5b0a33 441
agoel 0:9c4dbd5b0a33 442 char alarmStringA[512] = "";
agoel 0:9c4dbd5b0a33 443 bool generateAlertA = false;
agoel 0:9c4dbd5b0a33 444
agoel 0:9c4dbd5b0a33 445 alcoholValue = 1 - alcoholSensor; // as per example logic value needs to be subtracted from 1 (inverse value)
agoel 0:9c4dbd5b0a33 446 printf("Alcohol value read : %f \n\n",alcoholValue);
agoel 0:9c4dbd5b0a33 447 if (alcoholValue > .5f) {
agoel 0:9c4dbd5b0a33 448 alcoholProcessedValue = HIGH;
agoel 0:9c4dbd5b0a33 449 } else if (alcoholValue > .25f) {
agoel 0:9c4dbd5b0a33 450 alcoholProcessedValue = MEDIUM;
agoel 0:9c4dbd5b0a33 451 } else {
agoel 0:9c4dbd5b0a33 452 alcoholProcessedValue = LOW;
agoel 0:9c4dbd5b0a33 453 }
agoel 0:9c4dbd5b0a33 454
agoel 0:9c4dbd5b0a33 455 if (alcoholLastPeakValue != alcoholProcessedValue) { //condition to trigger alarm
agoel 0:9c4dbd5b0a33 456 if (alcoholLastPeakValue == 0) { // first time
agoel 0:9c4dbd5b0a33 457 alcoholLastPeakValue = alcoholProcessedValue;
agoel 0:9c4dbd5b0a33 458 generateAlertA = false;
agoel 0:9c4dbd5b0a33 459 } else {
agoel 0:9c4dbd5b0a33 460 if (alcoholLastPeakValue == LOW) {
agoel 0:9c4dbd5b0a33 461 if (alcoholProcessedValue == MEDIUM) {
agoel 0:9c4dbd5b0a33 462 strcpy (alarmStringA, "Alcohol level going up from LOW to MEDIUM");
agoel 0:9c4dbd5b0a33 463 } else if (alcoholProcessedValue == HIGH) {
agoel 0:9c4dbd5b0a33 464 strcpy (alarmStringA, "Alcohol level going up from LOW to HIGH");
agoel 0:9c4dbd5b0a33 465 }
agoel 0:9c4dbd5b0a33 466 } else if (alcoholLastPeakValue == MEDIUM) {
agoel 0:9c4dbd5b0a33 467 if (alcoholProcessedValue == LOW) {
agoel 0:9c4dbd5b0a33 468 strcpy (alarmStringA, "Alcohol level going down from MEDIUM to LOW");
agoel 0:9c4dbd5b0a33 469 } else if (alcoholProcessedValue == HIGH) {
agoel 0:9c4dbd5b0a33 470 strcpy (alarmStringA, "Alcohol level going up from MEDIUM to HIGH");
agoel 0:9c4dbd5b0a33 471 }
agoel 0:9c4dbd5b0a33 472 } else if (alcoholLastPeakValue == HIGH) {
agoel 0:9c4dbd5b0a33 473 if (alcoholProcessedValue == LOW) {
agoel 0:9c4dbd5b0a33 474 strcpy (alarmStringA, "Alcohol level going down from HIGH to LOW");
agoel 0:9c4dbd5b0a33 475 } else if (alcoholProcessedValue == MEDIUM) {
agoel 0:9c4dbd5b0a33 476 strcpy (alarmStringA, "Alcohol level going down from HIGH to MEDIUM");
agoel 0:9c4dbd5b0a33 477 }
agoel 0:9c4dbd5b0a33 478 }
agoel 0:9c4dbd5b0a33 479 alcoholLastPeakValue = alcoholProcessedValue;
agoel 0:9c4dbd5b0a33 480 generateAlertA = true;
agoel 0:9c4dbd5b0a33 481 }
agoel 0:9c4dbd5b0a33 482 }
agoel 0:9c4dbd5b0a33 483
agoel 0:9c4dbd5b0a33 484 // POST data to AerCloud using MQTT
agoel 0:9c4dbd5b0a33 485 time_t seconds = time(NULL);
agoel 0:9c4dbd5b0a33 486 sprintf(str,"{\"moistureSensorValue\": %.5f, \"moistureProcessedValue\": %.2f, \"alcoholSensorValue\": %.5f, \"alcoholProcessedValue\": %.2f, \"sclId\":\"%s\", \"timeStamp\": %u}", moistureValue, moistureProcessedValue, alcoholValue, alcoholProcessedValue, simImei, seconds);
agoel 0:9c4dbd5b0a33 487
agoel 0:9c4dbd5b0a33 488 printf("str = %s \r\n",str);
agoel 0:9c4dbd5b0a33 489 time_t beforeTime = time(NULL);
agoel 0:9c4dbd5b0a33 490 printf("\r\nAcquired data going to post now... %u \r\n", beforeTime);
agoel 0:9c4dbd5b0a33 491 if (! mqtt.publish(_AERCLOUD_CONTAINER, str)) {
agoel 0:9c4dbd5b0a33 492 printf("failed to publish: [%s]", str);
agoel 0:9c4dbd5b0a33 493 }
agoel 0:9c4dbd5b0a33 494 wait_ms (100); // wait for 100 ms to get the data published
agoel 0:9c4dbd5b0a33 495 printf("\r\nPosted data took ... %u seconds \r\n", time(NULL)-beforeTime );
agoel 0:9c4dbd5b0a33 496
agoel 0:9c4dbd5b0a33 497 // post alert for Moisture
agoel 0:9c4dbd5b0a33 498 if (generateAlertM) {
agoel 0:9c4dbd5b0a33 499 sprintf(str,"{\"alarmText\": \"%s\", \"sclId\":\"%s\", \"timeStamp\": %u}", alarmStringM, simImei, seconds);
agoel 0:9c4dbd5b0a33 500 printf("str = %s \r\n",str);
agoel 0:9c4dbd5b0a33 501 time_t beforeTime = time(NULL);
agoel 0:9c4dbd5b0a33 502 printf("\r\nAcquired data going to post now... %u \r\n", beforeTime);
agoel 0:9c4dbd5b0a33 503 if (! mqtt.publish(_AERCLOUD_CONTAINER_ALARM, str)) {
agoel 0:9c4dbd5b0a33 504 printf("failed to publish: [%s]", str);
agoel 0:9c4dbd5b0a33 505 }
agoel 0:9c4dbd5b0a33 506 wait_ms (100); // wait for 100 ms to get the data published
agoel 0:9c4dbd5b0a33 507 printf("\r\nPosted data took ... %u seconds \r\n", time(NULL)-beforeTime );
agoel 0:9c4dbd5b0a33 508 }
agoel 0:9c4dbd5b0a33 509
agoel 0:9c4dbd5b0a33 510 // post alert for Alcohol
agoel 0:9c4dbd5b0a33 511 if (generateAlertA) {
agoel 0:9c4dbd5b0a33 512 sprintf(str,"{\"alarmText\": \"%s\", \"sclId\":\"%s\", \"timeStamp\": %u}", alarmStringA, simImei, seconds);
agoel 0:9c4dbd5b0a33 513 printf("str = %s \r\n",str);
agoel 0:9c4dbd5b0a33 514 time_t beforeTime = time(NULL);
agoel 0:9c4dbd5b0a33 515 printf("\r\nAcquired data going to post now... %u \r\n", beforeTime);
agoel 0:9c4dbd5b0a33 516 if (! mqtt.publish(_AERCLOUD_CONTAINER_ALARM, str)) {
agoel 0:9c4dbd5b0a33 517 printf("failed to publish: [%s]", str);
agoel 0:9c4dbd5b0a33 518 }
agoel 0:9c4dbd5b0a33 519 wait_ms (100); // wait for 100 ms to get the data published
agoel 0:9c4dbd5b0a33 520 printf("\r\nPosted data took ... %u seconds \r\n", time(NULL)-beforeTime );
agoel 0:9c4dbd5b0a33 521 }
agoel 0:9c4dbd5b0a33 522
agoel 1:4e6e185783c2 523 // URL to print
agoel 1:4e6e185783c2 524 printf("URL for Main Container: %s/%s/scls/%s/containers/%s/contentInstances?apiKey=%s&dataFormat=jsonRaw\n\n", AC_BASE, _AERCLOUD_ACCOUNT_ID, simImei, _AERCLOUD_CONTAINER, _AERCLOUD_API_KEY);
agoel 1:4e6e185783c2 525 printf("URL for Alam Container: %s/%s/scls/%s/containers/%s/contentInstances?apiKey=%s&dataFormat=jsonRaw\n\n", AC_BASE, _AERCLOUD_ACCOUNT_ID, simImei, _AERCLOUD_CONTAINER_ALARM, _AERCLOUD_API_KEY);
agoel 1:4e6e185783c2 526
agoel 0:9c4dbd5b0a33 527 printf("Will be measuring again after 1 seconds !!!! \r\n\n");
agoel 0:9c4dbd5b0a33 528 wait (1);
agoel 0:9c4dbd5b0a33 529 }
agoel 0:9c4dbd5b0a33 530 }
agoel 0:9c4dbd5b0a33 531
agoel 0:9c4dbd5b0a33 532 //Disconnect ppp link of radio
agoel 0:9c4dbd5b0a33 533 mqtt.disconnect();
agoel 0:9c4dbd5b0a33 534 //Disconnect ppp link of radio
agoel 0:9c4dbd5b0a33 535 radio->disconnect();
agoel 0:9c4dbd5b0a33 536 }