SmartREST client reference implementation for the u-blox C027 mbed compatible device.

Dependencies:   C027 C027_Support mbed mbed-rtos MbedSmartRest LM75B MMA7660 C12832

Fork of MbedSmartRestTest by Vincent Wochnik

Embed: (wiki syntax)

« Back to documentation index

Show/hide line numbers program.cpp Source File

program.cpp

00001 #include "common.h"
00002 #include "io.h"
00003 #include "StaticData.h"
00004 #include "ComposedRecord.h"
00005 #include "CharValue.h"
00006 #include "IntegerValue.h"
00007 #include "FloatValue.h"
00008 #include "Aggregator.h"
00009 
00010 /************* CONFIGURATION *************/
00011 
00012 /* Credentials for device bootstrap authentification.
00013  * Contact cumulocity to get credentials. */
00014 #define DEVICEBOOTSTRAP_USERNAME ""
00015 #define DEVICEBOOTSTRAP_PASSWORD ""
00016 
00017 /* Uncomment and fill in credentials to turn off device bootstrapping. */
00018 //#define CREDENTIALS_USERNAME ""
00019 //#define CREDENTIALS_PASSWORD ""
00020 
00021 /* Template device identifier */
00022 #define TEMPLATE_DEVICE_IDENTIFIER "com_u-blox_C027_REV-A_0.10_Test1233123"
00023 
00024 /*****************************************/
00025 
00026 bool deviceBootstrap();
00027 long existing();
00028 long create();
00029 bool identify(long deviceId);
00030 bool update(long deviceId);
00031 void loop(long deviceId);
00032 void signalMeasurement(long deviceId, Aggregator& aggr);
00033 void temperatureMeasurement(long deviceId, Aggregator& aggr);
00034 void analogMeasurement(long deviceId, Aggregator& aggr);
00035 void motionMeasurement(long deviceId, Aggregator& aggr);
00036 
00037 credentials_t credentials = {};
00038 char cDeviceIdentifier[48];
00039 
00040 StaticData srtpl(
00041 // get device by identity
00042 // Usage: 100,<SERIAL/NR>
00043 "10,100,GET,/identity/externalIds/c8y_Serial/%%,,application/vnd.com.nsn.cumulocity.externalId+json,%%,STRING,\r\n"
00044 // get device id from identity
00045 // Response: 200,<DEVICE/ID>
00046 "11,200,\"$.managedObject\",,\"$.id\"\r\n"
00047 // Create device
00048 // Usage: 101,<SERIAL/NR>
00049 "10,101,POST,/inventory/managedObjects,application/vnd.com.nsn.cumulocity.managedObject+json,application/vnd.com.nsn.cumulocity.managedObject+json,%%,STRING,\"{\"\"name\"\":\"\"Mbed Test Device\"\",\"\"type\"\":\"\"com_ublox_C027_REV-A\"\",\"\"c8y_Hardware\"\":{\"\"revision\"\":\"\"1\"\",\"\"model\"\":\"\"Ublox C027\"\",\"\"serialNumber\"\":\"\"%%\"\"},\"\"c8y_SupportedMeasurements\"\":[\"\"c8y_SignalStrength\"\",\"\"c8y_TemperatureMeasurement\"\",\"\"c8y_AnalogMeasurement\"\",\"\"c8y_MotionMeasurement\"\"],\"\"c8y_RequiredAvailability\"\":{ \"\"responseInterval\"\":15},\"\"c8y_IsDevice\"\":{}}\"\r\n"
00050 // Get device id
00051 // Response: 201,<DEVICE/ID>
00052 "11,201,,\"$.c8y_IsDevice\",\"$.id\"\r\n"
00053 // Insert global ID
00054 // Usage: 102,<DEVICE/ID>,<SERIAL/NR>
00055 "10,102,POST,/identity/globalIds/%%/externalIds,application/vnd.com.nsn.cumulocity.externalId+json,application/vnd.com.nsn.cumulocity.externalId+json,%%,UNSIGNED STRING,\"{\"\"type\"\":\"\"c8y_Serial\"\",\"\"externalId\"\":\"\"%%\"\"}\"\r\n"
00056 // Update IMEI, CellId and iccid
00057 // Usage: 103,<DEVICE/ID>,<IMEI>,<CELL/ID>,<ICCID>
00058 "10,103,PUT,/inventory/managedObjects/%%,application/vnd.com.nsn.cumulocity.managedObject+json,application/vnd.com.nsn.cumulocity.managedObject+json,%%,UNSIGNED STRING STRING STRING,\"{\"\"c8y_Mobile\"\":{\"\"imei\"\":\"\"%%\"\",\"\"cellId\"\":\"\"%%\"\",\"\"iccid\"\":\"\"%%\"\"}}\"\r\n"
00059 // Insert measurement
00060 // USAGE: 104,<DEVICE/ID>,<RSSI>,<BER>
00061 "10,104,POST,/measurement/measurements,application/vnd.com.nsn.cumulocity.measurement+json,application/vnd.com.nsn.cumulocity.measurement+json,%%,NOW UNSIGNED NUMBER UNSIGNED,\"{\"\"time\"\":\"\"%%\"\",\"\"source\"\":{\"\"id\"\":\"\"%%\"\"},\"\"type\"\":\"\"c8y_SignalStrength\"\",\"\"c8y_SignalStrength\"\":{\"\"rssi\"\":{\"\"value\"\":%%,\"\"unit\"\":\"\"dBm\"\"},\"\"ber\"\":{\"\"value\"\":%%,\"\"unit\"\":\"\"%\"\"}}}\"\r\n"
00062 // Insert measurement
00063 // USAGE: 105,<DEVICE/ID>,<TEMPERATURE>
00064 "10,105,POST,/measurement/measurements,application/vnd.com.nsn.cumulocity.measurement+json,application/vnd.com.nsn.cumulocity.measurement+json,%%,NOW UNSIGNED NUMBER,\"{\"\"time\"\":\"\"%%\"\",\"\"source\"\":{\"\"id\"\":\"\"%%\"\"},\"\"type\"\":\"\"c8y_TemperatureMeasurement\"\",\"\"c8y_TemperatureMeasurement\"\":{\"\"T\"\":{\"\"value\"\":%%,\"\"unit\"\":\"\"C\"\"}}}\"\r\n"
00065 // Insert measurement
00066 // USAGE: 105,<DEVICE/ID>,<ANALOG0>,<ANALOG1>
00067 "10,106,POST,/measurement/measurements,application/vnd.com.nsn.cumulocity.measurement+json,application/vnd.com.nsn.cumulocity.measurement+json,%%,NOW UNSIGNED UNSIGNED UNSIGNED,\"{\"\"time\"\":\"\"%%\"\",\"\"source\"\":{\"\"id\"\":\"\"%%\"\"},\"\"type\"\":\"\"c8y_AnalogMeasurement\"\",\"\"c8y_AnalogMeasurement\"\":{\"\"analog0\"\":{\"\"value\"\":%%,\"\"unit\"\":\"\"%\"\"},\"\"analog1\"\":{\"\"value\"\":%%,\"\"unit\"\":\"\"%\"\"}}}\"\r\n"
00068 // Insert measurement
00069 // USAGE: 105,<DEVICE/ID>,<X>,<Y>,<Z>
00070 "10,107,POST,/measurement/measurements,application/vnd.com.nsn.cumulocity.measurement+json,application/vnd.com.nsn.cumulocity.measurement+json,%%,NOW UNSIGNED NUMBER NUMBER NUMBER,\"{\"\"time\"\":\"\"%%\"\",\"\"source\"\":{\"\"id\"\":\"\"%%\"\"},\"\"type\"\":\"\"c8y_MotionMeasurement\"\",\"\"c8y_MotionMeasurement\"\":{\"\"x\"\":{\"\"value\"\":%%,\"\"unit\"\":\"\"m^2/s\"\"},\"\"y\"\":{\"\"value\"\":%%,\"\"unit\"\":\"\"m^2/s\"\"},\"\"z\"\":{\"\"value\"\":%%,\"\"unit\"\":\"\"m^2/s\"\"}}}\"\r\n"
00071 );
00072 
00073 float interval = 120.0; // send measurements every two minutes
00074 
00075 MbedSmartRest client("developer.cumulocity.com", 80, credentials.username, credentials.password, cDeviceIdentifier);
00076 
00077 int program(void)
00078 {
00079     long deviceId = 0; Timer timer;
00080 
00081 #ifndef CREDENTIALS_USERNAME
00082     // read credentials from modem or make a device bootstrapping
00083     if (!credentials_read(&credentials)) {
00084         puts("Could not read credentials. Starting bootstrapping process.");
00085         if (!deviceBootstrap()) {
00086             puts("Device bootstrap failed.");
00087             return 1;
00088         }
00089     }
00090 #else
00091     // copy hardcoded credentials
00092     strcpy(credentials.username, CREDENTIALS_USERNAME);
00093     strcpy(credentials.password, CREDENTIALS_PASSWORD);
00094 #endif
00095     
00096     // copy identifier into variable
00097     strcpy(cDeviceIdentifier, TEMPLATE_DEVICE_IDENTIFIER);
00098 
00099     lcd_tenant(credentials.username);
00100     puts("Hello!");
00101     
00102     puts("Bootstrapping");
00103     lcd_status("Bootstrapping");
00104     if (client.bootstrap(srtpl) != SMARTREST_SUCCESS) {
00105         puts("Bootstrapping failed.");
00106         lcd_status("Bootstrapping failed.");
00107         return 2;
00108     }
00109    
00110     puts("Starting action...");
00111     
00112     if ((deviceId = existing()) == 0) {
00113         if (((deviceId = create()) == 0) || (!identify(deviceId))) {
00114             lcd_status("Device creation failed.");
00115             return 1;
00116         }
00117     }
00118     update(deviceId);
00119     printf("Device ID: %ld\r\n", deviceId);
00120 
00121     timer.start();
00122     while (true) {
00123         timer.reset();
00124         loop(deviceId);
00125 
00126         lcd_status("Sleeping...");
00127         // block remaining number of seconds
00128         while (timer.read() < interval) {
00129             Thread::yield();
00130         }
00131     }
00132 }
00133 
00134 bool deviceBootstrap()
00135 {
00136     uint8_t ret;
00137     
00138     ComposedRecord record(false);
00139     ParsedRecord received;
00140     CharValue deviceId(imei());
00141     IntegerValue connectMsgId(60);
00142     IntegerValue pollMsgId(61);
00143 
00144     // copy credentials
00145     strcpy(credentials.username, DEVICEBOOTSTRAP_USERNAME);
00146     strcpy(credentials.password, DEVICEBOOTSTRAP_PASSWORD);
00147     
00148     record.add(connectMsgId);
00149     record.add(deviceId);
00150     
00151     if (client.send(record) != SMARTREST_SUCCESS) {
00152         puts("Could not connect to platform.");
00153         client.stop();
00154         return false;
00155     }
00156     client.stop();
00157     
00158     ret = client.receive(received);
00159     if (ret == SMARTREST_SUCCESS) {
00160         if ((received.values() > 0) && (received.value(0).integerValue() == 50))
00161             puts("Server error. Make sure to register the device before attempting a device bootstrap.");
00162         else
00163             puts("Unknown error.");
00164         return false;
00165     }
00166     record.clear();
00167     
00168     record.add(pollMsgId);
00169     record.add(deviceId);
00170     
00171     while (true) {
00172         if (client.send(record) != SMARTREST_SUCCESS) {
00173             puts("Connection unsuccessful. Retrying.");
00174             client.stop();
00175             Thread::wait(2000);
00176             continue;
00177         }
00178         
00179         if (client.receive(received) != SMARTREST_SUCCESS) {
00180             puts("Not received anything. Retrying.");
00181             client.stop();
00182             Thread::wait(2000);
00183             continue;
00184         }
00185         client.stop();
00186         
00187         if (received.values() < 1) {
00188             puts("Bad received values. Retrying.");
00189             Thread::wait(2000);
00190             continue;
00191         }
00192         
00193         if (received.value(0).integerValue() == 50) {
00194             puts("No values. Retrying.");
00195             Thread::wait(2000);
00196             continue;
00197         }
00198         
00199         if (received.value(0).integerValue() != 70) {
00200             puts("Unknown received message identifier.");
00201             return false;
00202         }
00203         
00204         if (received.values() != 6) {
00205             puts("Bad credentials received.");
00206             return false;
00207         }
00208         
00209         credentials_set(&credentials, received.value(3).characterValue(), received.value(4).characterValue(), received.value(5).characterValue());
00210         
00211         printf("Username: %s\nPassword: %s\n", credentials.username, credentials.password);
00212         
00213         credentials_write(&credentials);
00214         
00215         return true;
00216     }
00217 }
00218 
00219 long existing()
00220 {
00221     ComposedRecord newMoRec(true); // set copy=true b/c tmp objects
00222     ParsedRecord received;
00223 
00224     lcd_status("Checking device existance...");
00225     puts("Checking for device existance...");
00226 
00227     if ((!newMoRec.add(IntegerValue(100))) || (!newMoRec.add(CharValue(imei()))))
00228         return 0;
00229 
00230     if (client.send(newMoRec) != SMARTREST_SUCCESS) {
00231         puts("Send failed.");
00232         client.stop();
00233         return 0;
00234     }
00235 
00236     if (client.receive(received) != SMARTREST_SUCCESS) {
00237         puts("No device found.");
00238         client.stop();
00239         return 0;
00240     }
00241 
00242     if (received.values() == 0) {
00243         puts("Received no values.");
00244         client.stop();
00245         return 0;
00246     }
00247 
00248     if (received.value(0).integerValue() == 50) {
00249         client.stop();
00250         return 0;
00251     }
00252     
00253     if (received.value(0).integerValue() != 200) {
00254         puts("Bad response.");
00255         client.stop();
00256         return 0;
00257     }
00258 
00259     client.stop();
00260     return received.value(2).integerValue();
00261 }
00262 
00263 long create()
00264 {
00265     ComposedRecord newMoRec(true); // set copy=true b/c tmp objects
00266     ParsedRecord received;
00267 
00268     lcd_status("Creating device...");
00269     puts("Creating device...");
00270 
00271     if ((!newMoRec.add(IntegerValue(101))) || (!newMoRec.add(CharValue(imei()))))
00272         return 0;
00273 
00274     if (client.send(newMoRec) != SMARTREST_SUCCESS) {
00275         puts("Send failed.");
00276         client.stop();
00277         return 0;
00278     }
00279 
00280     if (client.receive(received) != SMARTREST_SUCCESS) {
00281         puts("No device found.");
00282         client.stop();
00283         return 0;
00284     }
00285 
00286     if (received.values() != 3) {
00287         puts("Bad received data.");
00288         client.stop();
00289         return 0;
00290     }
00291     
00292     if (received.value(0).integerValue() != 201) {
00293         puts("Bad received data.");
00294         client.stop();
00295         return 0;
00296     }
00297 
00298     client.stop();
00299     return received.value(2).integerValue();
00300 }
00301 
00302 bool identify(long deviceId)
00303 {
00304     ComposedRecord newMoRec(true); // set copy=true b/c tmp objects
00305     ParsedRecord received;
00306 
00307     puts("Adding global identifier...");
00308 
00309     if ((!newMoRec.add(IntegerValue(102))) || (!newMoRec.add(IntegerValue(deviceId))) || (!newMoRec.add(CharValue(imei()))))
00310         return 0;
00311 
00312     if (client.send(newMoRec) != SMARTREST_SUCCESS) {
00313         puts("Sending failed.");
00314         client.stop();
00315         return false;
00316     }
00317 
00318     if (client.receive(received) != SMARTREST_SUCCESS) {
00319         puts("Failed.");
00320         client.stop();
00321         return false;
00322     }
00323 
00324     if (received.values() != 3) {
00325         puts("Received bad data.");
00326         client.stop();
00327         return false;
00328     }
00329     
00330     if (received.value(0).integerValue() != 200) {
00331         puts("Received bad data.");
00332         client.stop();
00333         return false;
00334     }
00335 
00336     client.stop();
00337     return true;
00338 }
00339 
00340 bool update(long deviceId)
00341 {
00342     ComposedRecord newMoRec(true); // set copy=true b/c tmp objects
00343     ParsedRecord received;
00344 
00345     lcd_status("Updating device object...");
00346     puts("Updating device data...");
00347 
00348     if ((!newMoRec.add(IntegerValue(103))) || (!newMoRec.add(IntegerValue(deviceId))) || (!newMoRec.add(CharValue(imei()))) || (!newMoRec.add(CharValue(cellId()))) || (!newMoRec.add(CharValue(iccid()))))
00349         return false;
00350 
00351     if (client.send(newMoRec) != SMARTREST_SUCCESS) {
00352         puts("Send failed.");
00353         client.stop();
00354         return false;
00355     }
00356 
00357     if (client.receive(received) != SMARTREST_SUCCESS) {
00358         puts("Update failed.");
00359         client.stop();
00360         return false;
00361     }
00362 
00363     if (received.values() != 3) {
00364         puts("Bad received data.");
00365         client.stop();
00366         return false;
00367     }
00368     
00369     if (received.value(0).integerValue() != 201) {
00370         puts("Bad received data.");
00371         client.stop();
00372         return false;
00373     }
00374 
00375     client.stop();
00376     
00377     return true;
00378 }
00379 
00380 void loop(long deviceId)
00381 {
00382     Aggregator aggr(true);
00383 
00384     lcd_status("Sending measurements...");
00385     temperatureMeasurement(deviceId, aggr);
00386     signalMeasurement(deviceId, aggr);
00387     analogMeasurement(deviceId, aggr);
00388     motionMeasurement(deviceId, aggr);
00389 
00390     if (client.send(aggr) != SMARTREST_SUCCESS) {
00391         puts("Loop send failed.");
00392     }
00393     client.stop();
00394 }
00395 
00396 void signalMeasurement(long deviceId, Aggregator& aggr)
00397 {
00398     sigq_t *sq = signalQuality();
00399     
00400     if ((sq->rssi == 0) || (sq->ber == 0))
00401         return;
00402     
00403     ComposedRecord measurement;
00404     IntegerValue msgId(104);
00405     IntegerValue devId(deviceId);
00406     FloatValue rssi(sq->rssi, 0);
00407     IntegerValue ber(sq->ber);
00408     if ((!measurement.add(msgId)) || (!measurement.add(devId)) || (!measurement.add(rssi)) || (!measurement.add(ber)))
00409         return;
00410     aggr.add(measurement);
00411 }
00412 
00413 void temperatureMeasurement(long deviceId, Aggregator& aggr)
00414 {
00415     ComposedRecord measurement;
00416     IntegerValue msgId(105);
00417     IntegerValue devId(deviceId);
00418     FloatValue temp(temperature(), 1);
00419     if ((!measurement.add(msgId)) || (!measurement.add(devId)) || (!measurement.add(temp)))
00420         return;
00421     aggr.add(measurement);
00422 }
00423 
00424 void analogMeasurement(long deviceId, Aggregator& aggr)
00425 {
00426     long analog0 = (long)(potentiometer(0) * 100.0);
00427     long analog1 = (long)(potentiometer(1) * 100.0);
00428     ComposedRecord measurement;
00429     IntegerValue msgId(106);
00430     IntegerValue devId(deviceId);
00431     IntegerValue an0(analog0);
00432     IntegerValue an1(analog1);
00433     if ((!measurement.add(msgId)) || (!measurement.add(devId)) || (!measurement.add(an0)) || (!measurement.add(an1)))
00434         return;
00435     aggr.add(measurement);
00436 }
00437 
00438 void motionMeasurement(long deviceId, Aggregator& aggr)
00439 {
00440     acceleration_t acc = acceleration();
00441     ComposedRecord measurement;
00442     IntegerValue msgId(107);
00443     IntegerValue devId(deviceId);
00444     FloatValue x(acc.x, 2);
00445     FloatValue y(acc.y, 2);
00446     FloatValue z(acc.z, 2);
00447     if ((!measurement.add(msgId)) || (!measurement.add(devId)) || (!measurement.add(x)) || (!measurement.add(y)) || (!measurement.add(z)))
00448         return;
00449     aggr.add(measurement);
00450 }