Sample code for connecting u-blox c027 to AerCloud
Dependencies: C027_Support_AerCloud HTTPClient_AerCloud mbed
Fork of HTTPClient_Cellular_HelloWorld by
main.cpp@14:fcdfdd37affe, 2014-11-14 (annotated)
- Committer:
- mchowla
- Date:
- Fri Nov 14 01:29:08 2014 +0000
- Revision:
- 14:fcdfdd37affe
- Parent:
- 12:955439e7166f
Fix issue where SIM always looked unprovisioned; Add line feeds to console messages so they print cleanly on the console
Who changed what in which revision?
User | Revision | Line number | New contents of line |
---|---|---|---|
ycaer | 12:955439e7166f | 1 | // Copyright 2014 Aeris Communications Inc |
ycaer | 12:955439e7166f | 2 | // |
ycaer | 12:955439e7166f | 3 | // Licensed under the Apache License, Version 2.0 (the "License"); |
ycaer | 12:955439e7166f | 4 | // you may not use this file except in compliance with the License. |
ycaer | 12:955439e7166f | 5 | // You may obtain a copy of the License at |
ycaer | 12:955439e7166f | 6 | // |
ycaer | 12:955439e7166f | 7 | // http://www.apache.org/licenses/LICENSE-2.0 |
ycaer | 12:955439e7166f | 8 | // |
ycaer | 12:955439e7166f | 9 | // Unless required by applicable law or agreed to in writing, software |
ycaer | 12:955439e7166f | 10 | // distributed under the License is distributed on an "AS IS" BASIS, |
ycaer | 12:955439e7166f | 11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
ycaer | 12:955439e7166f | 12 | // See the License for the specific language governing permissions and |
ycaer | 12:955439e7166f | 13 | // limitations under the License. |
ycaer | 12:955439e7166f | 14 | |
ycaer | 12:955439e7166f | 15 | // |
ycaer | 12:955439e7166f | 16 | // AerCloud sample code for the u-blox C027 board |
ycaer | 12:955439e7166f | 17 | // Details on the C027: http://developer.mbed.org/platforms/u-blox-C027/ |
ycaer | 12:955439e7166f | 18 | // Details on AerCloud: http://www.aeris.com/technology/aercloud/ |
ycaer | 12:955439e7166f | 19 | // AerCloud Developer Forum: https://developer.aeris.com/ |
ycaer | 12:955439e7166f | 20 | // |
ycaer | 12:955439e7166f | 21 | // Sample writes latitude, longitude, altitude, speed & GPS time to an AerCloud container |
ycaer | 12:955439e7166f | 22 | // |
ycaer | 12:955439e7166f | 23 | // Dependencies: |
ycaer | 12:955439e7166f | 24 | // mbed HTTP Client Libary |
ycaer | 12:955439e7166f | 25 | // C027_Support Library |
ycaer | 12:955439e7166f | 26 | // mbed Library |
ycaer | 12:955439e7166f | 27 | // |
ycaer | 12:955439e7166f | 28 | // To get the sample running, you'll need to fill in the following parameters below |
ycaer | 12:955439e7166f | 29 | // Your cellular provider's APN: APN |
ycaer | 12:955439e7166f | 30 | // AerCloud API Key: AC_APIKEY |
ycaer | 12:955439e7166f | 31 | // AerCloud Account ID: acId |
ycaer | 12:955439e7166f | 32 | // AerCloud Container: AC_CONTAINER |
ycaer | 12:955439e7166f | 33 | // |
ycaer | 12:955439e7166f | 34 | // and you'll also need to create an AerCloud contianer with the schema |
ycaer | 12:955439e7166f | 35 | // described below |
ycaer | 12:955439e7166f | 36 | // |
ycaer | 12:955439e7166f | 37 | |
donatien | 0:0e0debc29569 | 38 | #include "mbed.h" |
donatien | 0:0e0debc29569 | 39 | #include "HTTPClient.h" |
ycaer | 12:955439e7166f | 40 | #include "GPS.h" |
ycaer | 12:955439e7166f | 41 | |
ycaer | 12:955439e7166f | 42 | #include "MDM.h" |
mazgch | 6:6ff6061a0f76 | 43 | |
mazgch | 6:6ff6061a0f76 | 44 | //------------------------------------------------------------------------------------ |
ycaer | 12:955439e7166f | 45 | // Connectivity Parameters |
mazgch | 6:6ff6061a0f76 | 46 | //------------------------------------------------------------------------------------ |
ycaer | 12:955439e7166f | 47 | |
ycaer | 12:955439e7166f | 48 | //! Aeris SIM does not use PIN |
mazgch | 3:412a526d7054 | 49 | #define SIMPIN NULL |
ycaer | 12:955439e7166f | 50 | |
ycaer | 12:955439e7166f | 51 | //! The APN of your Aeris SIM |
ycaer | 12:955439e7166f | 52 | // You can find the APN for your SIM at https://aerport.aeris.com |
mchowla | 14:fcdfdd37affe | 53 | #define APN "_INSERT_YOUR_APN_HERE_" |
ycaer | 12:955439e7166f | 54 | |
ycaer | 12:955439e7166f | 55 | //! User name and password are not required to use Aeris APN |
mazgch | 3:412a526d7054 | 56 | #define USERNAME NULL |
ycaer | 12:955439e7166f | 57 | |
ycaer | 12:955439e7166f | 58 | //! User name and password are not required to use Aeris APN |
mazgch | 3:412a526d7054 | 59 | #define PASSWORD NULL |
ycaer | 12:955439e7166f | 60 | |
ycaer | 12:955439e7166f | 61 | |
ycaer | 12:955439e7166f | 62 | // ------------------------------------------------------------------------------------ |
ycaer | 12:955439e7166f | 63 | // AerCloud Paramers |
ycaer | 12:955439e7166f | 64 | // ------------------------------------------------------------------------------------ |
ycaer | 12:955439e7166f | 65 | |
ycaer | 12:955439e7166f | 66 | // AerCloud BASE URL |
ycaer | 12:955439e7166f | 67 | #define AC_BASE "http://api.aercloud.aeris.com/v1" |
ycaer | 12:955439e7166f | 68 | |
ycaer | 12:955439e7166f | 69 | //! AerCloud API Key |
mchowla | 14:fcdfdd37affe | 70 | // You can find your api key at https://aerport.aeris.com" |
mchowla | 14:fcdfdd37affe | 71 | #define AC_APIKEY "_INSERT_YOUR_AERCLOUD_API_KEY_HERE_" |
ycaer | 12:955439e7166f | 72 | |
ycaer | 12:955439e7166f | 73 | //! Aercloud Account Id |
ycaer | 12:955439e7166f | 74 | // You can find your account id at https://aerport.aeris.com |
ycaer | 12:955439e7166f | 75 | int acId = 1; |
ycaer | 12:955439e7166f | 76 | |
ycaer | 12:955439e7166f | 77 | // AerCloud Container |
ycaer | 12:955439e7166f | 78 | // The name of the AerCloud Container to write data into |
mchowla | 14:fcdfdd37affe | 79 | #define AC_CONTAINER "C027_Sample" // Example Container |
ycaer | 12:955439e7166f | 80 | |
ycaer | 12:955439e7166f | 81 | //------------------------------------------------------------------------------------ |
ycaer | 12:955439e7166f | 82 | // AerCloud SCL (Device) Data Model |
ycaer | 12:955439e7166f | 83 | // ------------------------------------------------------------------------------------ |
ycaer | 12:955439e7166f | 84 | // |
ycaer | 12:955439e7166f | 85 | // Code assumes an AerCloud Data Model with the following fields |
ycaer | 12:955439e7166f | 86 | // |
ycaer | 12:955439e7166f | 87 | // Altitude DOUBLE GPS altitude |
ycaer | 12:955439e7166f | 88 | // Speed DOUBLE GPS speed |
ycaer | 12:955439e7166f | 89 | // VSLat STRING GPS latitude |
ycaer | 12:955439e7166f | 90 | // VSLong STRING GPS longitude |
ycaer | 12:955439e7166f | 91 | // GPSTime DOUBLE Raw GPS time |
ycaer | 12:955439e7166f | 92 | // GPSDate DOUBLE Raw GPS Date |
ycaer | 12:955439e7166f | 93 | // SCLID INT AerCloud Device Identifier (i.e. IMEI) |
ycaer | 12:955439e7166f | 94 | // |
ycaer | 12:955439e7166f | 95 | |
mazgch | 6:6ff6061a0f76 | 96 | //------------------------------------------------------------------------------------ |
mazgch | 3:412a526d7054 | 97 | |
donatien | 1:d263603373ac | 98 | char str[512]; |
ycaer | 12:955439e7166f | 99 | char simImei[16]; |
ycaer | 12:955439e7166f | 100 | |
mchowla | 14:fcdfdd37affe | 101 | const char* HttpResultToString(HTTPResult r) { |
mchowla | 14:fcdfdd37affe | 102 | switch(r) { |
mchowla | 14:fcdfdd37affe | 103 | case HTTP_PROCESSING: |
mchowla | 14:fcdfdd37affe | 104 | return "HTTP_PROCESSING"; |
mchowla | 14:fcdfdd37affe | 105 | case HTTP_PARSE: |
mchowla | 14:fcdfdd37affe | 106 | return "HTTP_PARSE"; |
mchowla | 14:fcdfdd37affe | 107 | case HTTP_DNS: |
mchowla | 14:fcdfdd37affe | 108 | return "HTTP_DNS"; |
mchowla | 14:fcdfdd37affe | 109 | case HTTP_PRTCL: |
mchowla | 14:fcdfdd37affe | 110 | return "HTTP_PRTCL"; |
mchowla | 14:fcdfdd37affe | 111 | case HTTP_NOTFOUND: |
mchowla | 14:fcdfdd37affe | 112 | return "HTTP_NOTFOUND - 404"; |
mchowla | 14:fcdfdd37affe | 113 | case HTTP_REFUSED: |
mchowla | 14:fcdfdd37affe | 114 | return "HTTP_REFUSED - 403"; |
mchowla | 14:fcdfdd37affe | 115 | case HTTP_ERROR: |
mchowla | 14:fcdfdd37affe | 116 | return "HTTP_ERROR"; |
mchowla | 14:fcdfdd37affe | 117 | case HTTP_TIMEOUT: |
mchowla | 14:fcdfdd37affe | 118 | return "HTTP_TIMEOUT"; |
mchowla | 14:fcdfdd37affe | 119 | case HTTP_CONN: |
mchowla | 14:fcdfdd37affe | 120 | return "HTTP_CONN"; |
mchowla | 14:fcdfdd37affe | 121 | case HTTP_CLOSED: |
mchowla | 14:fcdfdd37affe | 122 | return "HTTP_CLOSED"; |
mchowla | 14:fcdfdd37affe | 123 | // case HTTP_OK: |
mchowla | 14:fcdfdd37affe | 124 | // return "HTTP_OK"; |
mchowla | 14:fcdfdd37affe | 125 | } |
mchowla | 14:fcdfdd37affe | 126 | |
mchowla | 14:fcdfdd37affe | 127 | return "UNKNOWN ERROR CODE"; |
mchowla | 14:fcdfdd37affe | 128 | } |
donatien | 1:d263603373ac | 129 | |
donatien | 0:0e0debc29569 | 130 | int main() |
donatien | 0:0e0debc29569 | 131 | { |
ycaer | 12:955439e7166f | 132 | bool simProvisioned = false; |
ycaer | 12:955439e7166f | 133 | int ret; |
ycaer | 12:955439e7166f | 134 | char buf[512] = ""; |
ycaer | 12:955439e7166f | 135 | int itn = 580; |
ycaer | 12:955439e7166f | 136 | const int wait = 100; |
ycaer | 12:955439e7166f | 137 | double lastLat = 0, lastLong = 0, lastAlt = 0, lastSpeed = 0, lastTime = 0, lastDate = 0; |
ycaer | 12:955439e7166f | 138 | bool abort = false; |
ycaer | 12:955439e7166f | 139 | |
ycaer | 12:955439e7166f | 140 | GPSI2C gps; |
ycaer | 12:955439e7166f | 141 | |
mchowla | 14:fcdfdd37affe | 142 | printf("GPS object created\r\n"); |
mazgch | 5:a18ddbfd70c9 | 143 | // turn on the supplies of the Modem |
mazgch | 3:412a526d7054 | 144 | MDMSerial mdm; |
mchowla | 14:fcdfdd37affe | 145 | printf("Modem object created\r\n"); |
sam_grove | 11:101705d43c92 | 146 | //mdm.setDebug(4); // enable this for debugging issues |
ycaer | 12:955439e7166f | 147 | if (!mdm.connect(SIMPIN, APN,USERNAME,PASSWORD)) { |
mchowla | 14:fcdfdd37affe | 148 | printf("Unabled to connect to the network.\r\n"); |
mazgch | 4:7fd97087e573 | 149 | return -1; |
ycaer | 12:955439e7166f | 150 | } |
mazgch | 4:7fd97087e573 | 151 | HTTPClient http; |
mazgch | 8:eea979594a37 | 152 | |
ycaer | 12:955439e7166f | 153 | //get SIM IMEI |
ycaer | 12:955439e7166f | 154 | mdm.getIMEI(simImei); |
mchowla | 14:fcdfdd37affe | 155 | printf("Requesting provision info for IMEI %s\r\n",simImei); |
ycaer | 12:955439e7166f | 156 | |
ycaer | 12:955439e7166f | 157 | // Check if SIM is provisioned in AerCloud |
mchowla | 14:fcdfdd37affe | 158 | printf("\r\nIs the SIM provisioned? "); |
ycaer | 12:955439e7166f | 159 | char url[512]; |
ycaer | 12:955439e7166f | 160 | snprintf(url, sizeof(url), "%s/%d/scls/%s?apiKey=%s", AC_BASE, acId, simImei, AC_APIKEY); |
ycaer | 12:955439e7166f | 161 | ret = http.get(url, str, 128); |
mchowla | 14:fcdfdd37affe | 162 | if (ret == HTTP_OK) |
donatien | 0:0e0debc29569 | 163 | { |
ycaer | 12:955439e7166f | 164 | // We're already provisioned |
mchowla | 14:fcdfdd37affe | 165 | printf("Yes\r\n"); |
mchowla | 14:fcdfdd37affe | 166 | printf("Page fetched successfully - read %d characters\r\n", strlen(str)); |
mchowla | 14:fcdfdd37affe | 167 | printf("Result: %s\r\n", str); |
ycaer | 12:955439e7166f | 168 | simProvisioned = true; |
mazgch | 4:7fd97087e573 | 169 | } |
mazgch | 4:7fd97087e573 | 170 | else |
mazgch | 4:7fd97087e573 | 171 | { |
mchowla | 14:fcdfdd37affe | 172 | printf("No\r\n"); |
mchowla | 14:fcdfdd37affe | 173 | printf("Error - ret = %d - HTTP return code = %d\r\n", ret, http.getHTTPResponseCode()); |
ycaer | 12:955439e7166f | 174 | //SIM is not provisioned. trying to provision it... |
ycaer | 12:955439e7166f | 175 | char url[512]; |
ycaer | 12:955439e7166f | 176 | snprintf(url, sizeof(url), "%s/%d/scls?apiKey=%s", AC_BASE, acId, AC_APIKEY); |
ycaer | 12:955439e7166f | 177 | |
ycaer | 12:955439e7166f | 178 | snprintf(str, sizeof(str), "{\"sclId\":\"%s\"}\0",simImei); |
ycaer | 12:955439e7166f | 179 | HTTPText outText(str); |
ycaer | 12:955439e7166f | 180 | HTTPText inText(str, 512); |
ycaer | 12:955439e7166f | 181 | ret = http.post(url, outText, &inText); |
ycaer | 12:955439e7166f | 182 | if (!ret) |
ycaer | 12:955439e7166f | 183 | { |
mchowla | 14:fcdfdd37affe | 184 | printf("Executed POST successfully - read %d characters\r\n", strlen(str)); |
mchowla | 14:fcdfdd37affe | 185 | printf("Result: %s\r\n", str); |
ycaer | 12:955439e7166f | 186 | simProvisioned = true; |
ycaer | 12:955439e7166f | 187 | } |
ycaer | 12:955439e7166f | 188 | else |
ycaer | 12:955439e7166f | 189 | { |
ycaer | 12:955439e7166f | 190 | if(http.getHTTPResponseCode() == 200) |
ycaer | 12:955439e7166f | 191 | simProvisioned = true; |
mchowla | 14:fcdfdd37affe | 192 | printf("Error - ret = %d - HTTP return code = %d\r\n", ret, http.getHTTPResponseCode()); |
ycaer | 12:955439e7166f | 193 | } |
mazgch | 4:7fd97087e573 | 194 | } |
donatien | 2:270e2d0bb85a | 195 | |
ycaer | 12:955439e7166f | 196 | //POST data to containers if SIM has been successfully provisioned |
ycaer | 12:955439e7166f | 197 | if(simProvisioned) |
mazgch | 4:7fd97087e573 | 198 | { |
ycaer | 12:955439e7166f | 199 | //Read GPS |
ycaer | 12:955439e7166f | 200 | while (!abort) |
ycaer | 12:955439e7166f | 201 | { |
ycaer | 12:955439e7166f | 202 | while ((ret = gps.getMessage(buf, sizeof(buf))) > 0) |
ycaer | 12:955439e7166f | 203 | { |
ycaer | 12:955439e7166f | 204 | int len = LENGTH(ret); |
ycaer | 12:955439e7166f | 205 | if ((PROTOCOL(ret) == GPSParser::NMEA) && (len > 6)) |
ycaer | 12:955439e7166f | 206 | { |
ycaer | 12:955439e7166f | 207 | if (!strncmp("$GPGLL", buf, 6)) |
ycaer | 12:955439e7166f | 208 | { |
ycaer | 12:955439e7166f | 209 | //Get Lat/Long |
ycaer | 12:955439e7166f | 210 | double la = 0, lo = 0; |
ycaer | 12:955439e7166f | 211 | char ch; |
ycaer | 12:955439e7166f | 212 | if (gps.getNmeaAngle(1,buf,len,la) && |
ycaer | 12:955439e7166f | 213 | gps.getNmeaAngle(3,buf,len,lo) && |
ycaer | 12:955439e7166f | 214 | gps.getNmeaItem(6,buf,len,ch) && ch == 'A') |
ycaer | 12:955439e7166f | 215 | { |
ycaer | 12:955439e7166f | 216 | lastLat = la; |
ycaer | 12:955439e7166f | 217 | lastLong = lo; |
ycaer | 12:955439e7166f | 218 | } |
ycaer | 12:955439e7166f | 219 | } |
ycaer | 12:955439e7166f | 220 | else if (!strncmp("$GPGGA", buf, 6)) |
ycaer | 12:955439e7166f | 221 | { |
ycaer | 12:955439e7166f | 222 | //Get Altitude |
ycaer | 12:955439e7166f | 223 | double a = 0; |
ycaer | 12:955439e7166f | 224 | if (gps.getNmeaItem(9,buf,len,a)) // altitude msl [m] |
ycaer | 12:955439e7166f | 225 | { |
ycaer | 12:955439e7166f | 226 | lastAlt = a; |
ycaer | 12:955439e7166f | 227 | } |
ycaer | 12:955439e7166f | 228 | } |
ycaer | 12:955439e7166f | 229 | else if (!strncmp("$GPVTG", buf, 6)) |
ycaer | 12:955439e7166f | 230 | { |
ycaer | 12:955439e7166f | 231 | //Get Speed |
ycaer | 12:955439e7166f | 232 | double s = 0; |
ycaer | 12:955439e7166f | 233 | if (gps.getNmeaItem(7,buf,len,s)) // speed [km/h] |
ycaer | 12:955439e7166f | 234 | { |
ycaer | 12:955439e7166f | 235 | lastSpeed = s; |
ycaer | 12:955439e7166f | 236 | } |
ycaer | 12:955439e7166f | 237 | } |
ycaer | 12:955439e7166f | 238 | else if (!strncmp("$GPRMC", buf, 6)) |
ycaer | 12:955439e7166f | 239 | { |
ycaer | 12:955439e7166f | 240 | //Get Timestamp |
ycaer | 12:955439e7166f | 241 | double fixTime = 0; |
ycaer | 12:955439e7166f | 242 | double fixDate = 0; |
ycaer | 12:955439e7166f | 243 | |
ycaer | 12:955439e7166f | 244 | if (gps.getNmeaItem(1,buf,len,fixTime)) // speed [km/h] |
ycaer | 12:955439e7166f | 245 | { |
ycaer | 12:955439e7166f | 246 | lastTime = fixTime; |
ycaer | 12:955439e7166f | 247 | } |
ycaer | 12:955439e7166f | 248 | if (gps.getNmeaItem(9,buf,len,fixDate)) // speed [km/h] |
ycaer | 12:955439e7166f | 249 | { |
ycaer | 12:955439e7166f | 250 | lastDate = fixDate; |
ycaer | 12:955439e7166f | 251 | } |
ycaer | 12:955439e7166f | 252 | // printf("time: %f\n Date:%f\n", lastTime, lastDate); |
ycaer | 12:955439e7166f | 253 | } |
ycaer | 12:955439e7166f | 254 | } |
ycaer | 12:955439e7166f | 255 | } |
ycaer | 12:955439e7166f | 256 | wait_ms(wait); |
ycaer | 12:955439e7166f | 257 | itn++; |
ycaer | 12:955439e7166f | 258 | //post every 60 seconds |
ycaer | 12:955439e7166f | 259 | if(itn == 590) |
ycaer | 12:955439e7166f | 260 | { |
ycaer | 12:955439e7166f | 261 | // POST data to AerCLoud |
ycaer | 12:955439e7166f | 262 | char url[512]; |
ycaer | 12:955439e7166f | 263 | snprintf(url, sizeof(url), "%s/%d/scls/%s/containers/%s/contentInstances?apiKey=%s", AC_BASE, acId, simImei, AC_CONTAINER, AC_APIKEY); |
ycaer | 12:955439e7166f | 264 | |
ycaer | 12:955439e7166f | 265 | sprintf(str,"{\"VSLat\": %.5f, \"VSLong\": %.5f, \"Altitude\": %.5f, \"Speed\":%.5f, \"GPSTime\":%.5f, \"GPSDate\":%.5f, \"SCLID\":\"%s\"}", lastLat, lastLong, lastAlt, lastSpeed, lastTime, lastDate, simImei); |
ycaer | 12:955439e7166f | 266 | HTTPText outText(str); |
ycaer | 12:955439e7166f | 267 | HTTPText inText(str, 512); |
mchowla | 14:fcdfdd37affe | 268 | printf("\r\nPost acquired data...\r\n"); |
ycaer | 12:955439e7166f | 269 | ret = http.post(url, outText, &inText); |
mchowla | 14:fcdfdd37affe | 270 | if (ret == HTTP_OK) |
ycaer | 12:955439e7166f | 271 | { |
mchowla | 14:fcdfdd37affe | 272 | printf("Executed POST successfully - read %d characters\r\n", strlen(str)); |
mchowla | 14:fcdfdd37affe | 273 | printf("Result: %s\r\n", str); |
ycaer | 12:955439e7166f | 274 | } |
ycaer | 12:955439e7166f | 275 | else |
ycaer | 12:955439e7166f | 276 | { |
mchowla | 14:fcdfdd37affe | 277 | printf("Error - ret = %d (%s), - HTTP return code = %d\r\n", ret, HttpResultToString((HTTPResult)ret), http.getHTTPResponseCode()); |
ycaer | 12:955439e7166f | 278 | } |
ycaer | 12:955439e7166f | 279 | itn = 0; |
ycaer | 12:955439e7166f | 280 | } |
ycaer | 12:955439e7166f | 281 | } |
ycaer | 12:955439e7166f | 282 | gps.powerOff(); |
ycaer | 12:955439e7166f | 283 | } else { |
mchowla | 14:fcdfdd37affe | 284 | printf("SIM is not provisioned.\r\n"); |
donatien | 2:270e2d0bb85a | 285 | } |
mazgch | 4:7fd97087e573 | 286 | |
mazgch | 4:7fd97087e573 | 287 | |
mazgch | 4:7fd97087e573 | 288 | mdm.disconnect(); |
mazgch | 3:412a526d7054 | 289 | mdm.powerOff(); |
mazgch | 6:6ff6061a0f76 | 290 | |
ycaer | 12:955439e7166f | 291 | return 0; |
donatien | 0:0e0debc29569 | 292 | } |
ycaer | 12:955439e7166f | 293 |