Official reference client implementation for Cumulocity SmartREST on u-blox C027.
Dependencies: C027_Support C12832 LM75B MMA7660 MbedSmartRest mbed-rtos mbed
Fork of MbedSmartRestMain by
Revision 41:804f6a0bda26, committed 2014-07-15
- Comitter:
- Cumulocity
- Date:
- Tue Jul 15 12:44:34 2014 +0000
- Parent:
- 40:13c24225f189
- Child:
- 42:104746744af8
- Commit message:
- refactoring of mbed agent
Changed in this revision
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/AccelerationMeasurement.cpp Tue Jul 15 12:44:34 2014 +0000 @@ -0,0 +1,56 @@ +#include "AccelerationMeasurement.h" +#include "ComposedRecord.h" +#include "CharValue.h" +#include "IntegerValue.h" +#include "FloatValue.h" + +AccelerationMeasurement::AccelerationMeasurement(SmartRest& client, SmartRestTemplate& tpl, long& deviceId, MMA7660& sensor) : + _client(client), + _tpl(tpl), + _deviceId(deviceId), + _sensor(sensor) +{ + _init = false; +} + +bool AccelerationMeasurement::init() +{ + if (_init) + return false; + + // Insert measurement + // USAGE: 105,<DEVICE/ID>,<X>,<Y>,<Z> + if (!_tpl.add("10,106,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")) + return false; + + _test = _sensor.testConnection(); + _init = true; + return true; +} + +bool AccelerationMeasurement::run() +{ + float data[3] = { 0.0, 0.0, 0.0 }; + + if (!_test) + return false; + + _sensor.readData(data); + + ComposedRecord record; + IntegerValue msgId(106); + IntegerValue devId(_deviceId); + FloatValue xValue(data[0], 2); + FloatValue yValue(data[1], 2); + FloatValue zValue(data[2], 2); + if ((!record.add(msgId)) || (!record.add(devId)) || (!record.add(xValue)) || (!record.add(yValue)) || (!record.add(zValue))) + return false; + + if (_client.send(record) != SMARTREST_SUCCESS) { + puts("Signal measurement failed."); + _client.stop(); + return false; + } + _client.stop(); + return true; +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/AccelerationMeasurement.h Tue Jul 15 12:44:34 2014 +0000 @@ -0,0 +1,24 @@ +#ifndef ACCELERATIONMEASUREMENT_H +#define ACCELERATIONMEASUREMENT_H + +#include "SmartRest.h" +#include "SmartRestTemplate.h" +#include "MMA7660.h" + +class AccelerationMeasurement +{ +public: + AccelerationMeasurement(SmartRest&, SmartRestTemplate&, long&, MMA7660&); + + bool init(); + bool run(); + +private: + bool _init, _test; + long& _deviceId; + SmartRestTemplate& _tpl; + SmartRest& _client; + MMA7660& _sensor; +}; + +#endif \ No newline at end of file
--- a/C027.lib Thu Jul 10 14:22:11 2014 +0000 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,1 +0,0 @@ -http://mbed.org/teams/ublox/code/C027/#89c45165ee87
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/DeviceBootstrap.cpp Tue Jul 15 12:44:34 2014 +0000 @@ -0,0 +1,146 @@ +#include "DeviceBootstrap.h" +#include <stdlib.h> +#include <stdio.h> +#include <string.h> +#include "rtos.h" +#include "ComposedRecord.h" +#include "CharValue.h" +#include "IntegerValue.h" +#include "ParsedRecord.h" + +DeviceBootstrap::DeviceBootstrap(SmartRest& client, MDMSerial& mdm, DeviceInfo& deviceInfo) : + _client(client), + _mdm(mdm), + _deviceInfo(deviceInfo) +{ + *_username = *_password = '\0'; +} + +bool DeviceBootstrap::setUpCredentials() +{ + if (((*_username == '\0') || (*_password == '\0')) && + (!obtainFromStorage())) { + if (!obtainFromPlatform()) + return false; + if (!writeToStorage()) + puts("Warning: Could not write credentials to file!"); + } + + printf("Credentials: %s : %s\n", _username, _password); + if (_client.setAuthorization(_username, _password) != SMARTREST_SUCCESS) + return false; + return true; +} + +bool DeviceBootstrap::obtainFromStorage() +{ + char buf[DEVICE_BOOTSTRAP_CREDENTIALS_LENGTH*2+2], *ptr; + + int res = _mdm.readFile(CREDENTIALS_FILE, buf, sizeof(buf)); + + if (res < 0) + return false; + + buf[res] = '\0'; + if ((ptr = strchr(buf, '\n')) == NULL) + return false; + *ptr = '\0'; + + ptr = buf; + strcpy(_username, ptr); + ptr += strlen(ptr)+1; + strcpy(_password, ptr); + return true; +} + +bool DeviceBootstrap::obtainFromPlatform() +{ + uint8_t ret; + + printf("Starting device bootstrap with '%s'\n", _deviceInfo.imei()); + + ComposedRecord record; + ParsedRecord recvdRecord; + + IntegerValue msgId(61); + CharValue identifier(_deviceInfo.imei()); + if ((!record.add(msgId)) || (!record.add(identifier))) + return false; + + // set authorization for bootstrap + if (_client.setAuthorization(DEVICE_BOOTSTRAP_USERNAME, DEVICE_BOOTSTRAP_PASSWORD) != SMARTREST_SUCCESS) + return false; + + while (true) { + if (_client.send(record, "") != SMARTREST_SUCCESS) { + puts("Connection unsuccessful. Retrying."); + _client.stop(); + Thread::wait(2000); + continue; + } + + if (_client.receive(recvdRecord) != SMARTREST_SUCCESS) { + puts("Receiving failure."); + _client.stop(); + Thread::wait(2000); + continue; + } + + if ((recvdRecord.values() < 1) || + (recvdRecord.value(0).integerValue() == 50)) { + puts("No credentials available yet. Retrying."); + Thread::wait(2000); + continue; + } + + if ((recvdRecord.value(0).integerValue() != 70) || + (recvdRecord.values() != 6)) { + puts("Bad credentials received."); + return false; + } + + setCredentials(recvdRecord.value(3).characterValue(), + recvdRecord.value(4).characterValue(), + recvdRecord.value(5).characterValue()); + + return true; + } + return false; +} + +bool DeviceBootstrap::writeToStorage() +{ + char buf[DEVICE_BOOTSTRAP_CREDENTIALS_LENGTH*2+2], *ptr; + size_t len; + + ptr = buf; + len = strlen(_username); + strcpy(ptr, _username); + ptr += len; + + *ptr++ = '\n'; + len++; + + len += strlen(_password); + strcpy(ptr, _password); + + _mdm.delFile(CREDENTIALS_FILE); + _mdm.writeFile(CREDENTIALS_FILE, buf, len); + return true; +} + +void DeviceBootstrap::setCredentials(const char *tenant, const char *username, const char *password) +{ + *_username = '\0'; + if (tenant != NULL) { + strncpy(_username, tenant, DEVICE_BOOTSTRAP_CREDENTIALS_LENGTH); + _username[DEVICE_BOOTSTRAP_CREDENTIALS_LENGTH-1] = '\0'; + if (strlen(_username)+1 < DEVICE_BOOTSTRAP_CREDENTIALS_LENGTH) + strcat(_username, "/"); + } + strncat(_username, username, DEVICE_BOOTSTRAP_CREDENTIALS_LENGTH-strlen(_username)); + _username[DEVICE_BOOTSTRAP_CREDENTIALS_LENGTH-1] = '\0'; + + strncpy(_password, password, DEVICE_BOOTSTRAP_CREDENTIALS_LENGTH); + _password[DEVICE_BOOTSTRAP_CREDENTIALS_LENGTH-1] = '\0'; +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/DeviceBootstrap.h Tue Jul 15 12:44:34 2014 +0000 @@ -0,0 +1,42 @@ +#ifndef DEVICEBOOTSTRAP_H +#define DEVICEBOOTSTRAP_H + +#include <stddef.h> +#include "MDM.h" +#include "SmartRest.h" +#include "DeviceInfo.h" + +/** The username used for device bootstrapping. */ +#define DEVICE_BOOTSTRAP_USERNAME "management/devicebootstrap" + +/** The password used for device bootstrapping. */ +#define DEVICE_BOOTSTRAP_PASSWORD "Fhdt1bb1f" + +#define DEVICE_BOOTSTRAP_CREDENTIALS_LENGTH 256 + +#define CREDENTIALS_FILE "001_CREDENTIALS" + +class DeviceBootstrap +{ +public: + DeviceBootstrap(SmartRest&, MDMSerial&, DeviceInfo&); + + bool setUpCredentials(); + +protected: + bool obtainFromStorage(); + bool obtainFromPlatform(); + +private: + bool writeToStorage(); + void setCredentials(const char *, const char*, const char*); + +private: + SmartRest& _client; + MDMSerial& _mdm; + DeviceInfo& _deviceInfo; + char _username[DEVICE_BOOTSTRAP_CREDENTIALS_LENGTH], + _password[DEVICE_BOOTSTRAP_CREDENTIALS_LENGTH]; +}; + +#endif \ No newline at end of file
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/DeviceIO.cpp Tue Jul 15 12:44:34 2014 +0000 @@ -0,0 +1,30 @@ +#include "DeviceIO.h" + +DeviceIO::DeviceIO() : + _temperatureSensor(SDA,SCL), + _accelerometer(SDA,SCL), + _lcd(D11, D13, D12, D7, D10) +{ +} + +LM75B& DeviceIO::temperatureSensor() +{ + return _temperatureSensor; +} + +MMA7660& DeviceIO::accelerometer() +{ + return _accelerometer; +} + +void DeviceIO::lcdPrint(const char *line1, const char *line2, const char *line3) +{ + _lcd.cls(); + _lcd.locate(0, 0); + _lcd.printf("%s\n", line1); + if (line2 != NULL) { + _lcd.printf("%s\n", line2); + if (line3 != NULL) + _lcd.printf("%s\n", line3); + } +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/DeviceIO.h Tue Jul 15 12:44:34 2014 +0000 @@ -0,0 +1,50 @@ +#ifndef DEVICEIO_H +#define DEVICEIO_H + +#include "mbed.h" +#include "LM75B.h" +#include "MMA7660.h" +#include "C12832.h" + +#define A0 P0_23 +#define A1 P0_24 +#define A2 P0_25 +#define A3 P0_26 +#define A4 P0_30 +#define A5 P1_31 + +#define D0 P4_29 +#define D1 P4_28 +#define D2 P2_13 +#define D3 P2_0 +#define D4 P2_12 +#define D5 P2_1 +#define D6 P2_2 +#define D7 P2_11 + +#define D8 P2_4 +#define D9 P2_3 +#define D10 P1_21 +#define D11 P1_24 +#define D12 P1_23 +#define D13 P1_20 + +#define SDA P0_0 +#define SCL P0_1 + +class DeviceIO +{ +public: + DeviceIO(); + + LM75B& temperatureSensor(); + MMA7660& accelerometer(); + void lcdPrint(const char*, const char* = NULL, const char* = NULL); + +private: + LM75B _temperatureSensor; + MMA7660 _accelerometer; + C12832 _lcd; +}; + +#endif \ No newline at end of file
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/DeviceInfo.cpp Tue Jul 15 12:44:34 2014 +0000 @@ -0,0 +1,56 @@ +#include "DeviceInfo.h" +#include <stdlib.h> +#include <string.h> + +DeviceInfo::DeviceInfo(MDMSerial& mdm, MDMParser::DevStatus& devStatus) : + _mdm(mdm) +{ + *_cellId = '\0'; + memcpy(&_devStatus, &devStatus, sizeof(MDMParser::DevStatus)); + memset(&_netStatus, 0, sizeof(MDMParser::NetStatus)); + memset(&_signalQuality, 0, sizeof(DeviceInfo::SignalQuality)); +} + +const char * DeviceInfo::imsi() +{ + return _devStatus.imsi; +} + +const char * DeviceInfo::imei() +{ + return _devStatus.imei; +} + +const char * DeviceInfo::cellId() +{ + if (!refreshNetStatus()) + return NULL; + + if (snprintf(_cellId, sizeof(_cellId), "%X", _netStatus.ci) < 1) + return NULL; + return _cellId; +} + +const char * DeviceInfo::iccid() +{ + return _devStatus.ccid; +} + +DeviceInfo::SignalQuality * DeviceInfo::signalQuality() +{ + memset(&_signalQuality, 0, sizeof(DeviceInfo::SignalQuality)); + if (!refreshNetStatus()) + return NULL; + + if ((_netStatus.rssi == 0) || (_netStatus.ber == 0)) + return NULL; + + _signalQuality.rssi = _netStatus.rssi; + _signalQuality.ber = _netStatus.ber; + return &_signalQuality; +} + +bool DeviceInfo::refreshNetStatus() +{ + return _mdm.checkNetStatus(&_netStatus); +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/DeviceInfo.h Tue Jul 15 12:44:34 2014 +0000 @@ -0,0 +1,35 @@ +#ifndef DEVICEINFO_H +#define DEVICEINFO_H + +#include <stddef.h> +#include <stdint.h> +#include "MDM.h" + +class DeviceInfo +{ +public: + DeviceInfo(MDMSerial& mdm, MDMParser::DevStatus& devStatus); + + typedef struct { + int rssi; // RSSI in dBm + int ber; // BER in % + } SignalQuality; + + const char * imsi(); + const char * imei(); + const char * cellId(); + const char * iccid(); + SignalQuality * signalQuality(); + +protected: + bool refreshNetStatus(); + +private: + MDMSerial& _mdm; + MDMParser::DevStatus _devStatus; + MDMParser::NetStatus _netStatus; + char _cellId[9]; + SignalQuality _signalQuality; +}; + +#endif \ No newline at end of file
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/DeviceIntegration.cpp Tue Jul 15 12:44:34 2014 +0000 @@ -0,0 +1,247 @@ +#include "DeviceIntegration.h" +#include <stdio.h> +#include "ComposedRecord.h" +#include "CharValue.h" +#include "IntegerValue.h" + +DeviceIntegration::DeviceIntegration(SmartRest& client, SmartRestTemplate& tpl, long& deviceId, DeviceInfo& deviceInfo) : + _client(client), + _tpl(tpl), + _deviceId(deviceId), + _deviceInfo(deviceInfo) +{ + _init = false; +} + +bool DeviceIntegration::init() +{ + if (_init) + return false; + + // get device by identity + // Usage: 100,<SERIAL/NR> + if (!_tpl.add("10,100,GET,/identity/externalIds/c8y_Serial/%%,,application/vnd.com.nsn.cumulocity.externalId+json,%%,STRING,\r\n")) + return false; + + // get device id from identity + // Response: 200,<DEVICE/ID> + if (!_tpl.add("11,200,\"$.managedObject\",,\"$.id\"\r\n")) + return false; + + // Create device + // Usage: 101,<SERIAL/NR> + if (!_tpl.add("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")) + return false; + + // Get device id + // Response: 201,<DEVICE/ID> + if (!_tpl.add("11,201,,\"$.c8y_IsDevice\",\"$.id\"\r\n")) + return false; + + // Insert global ID + // Usage: 102,<DEVICE/ID>,<SERIAL/NR> + if (!_tpl.add("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")) + return false; + + // Update IMEI, CellId and iccid + // Usage: 103,<DEVICE/ID>,<IMEI>,<CELL/ID>,<ICCID> + if (!_tpl.add("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")) + return false; + + _init = true; + _deviceId = 0; + return true; +} + +bool DeviceIntegration::integrate() +{ + if (_deviceId != 0) + return false; + + // template bootstrapping process + if (_client.bootstrap(_tpl) != SMARTREST_SUCCESS) { + puts("Template bootstrap failed."); + return 1; + } + + puts("Hello."); + if (!deviceExisting()) { + puts("Creating device."); + if (!createDevice()) { + puts("Failed."); + return false; + } + puts("Adding global identifier."); + if (!addGlobalIdentifier()) { + puts("Failed."); + return false; + } + } + + puts("Updating device data."); + if (!updateDevice()) { + puts("Failed."); + return false; + } + + return true; +} + +bool DeviceIntegration::deviceExisting() +{ + ComposedRecord record; + ParsedRecord received; + + IntegerValue msgId(100); + CharValue imei(_deviceInfo.imei()); + if ((!record.add(msgId)) || (!record.add(imei))) + return false; + + if (_client.send(record) != SMARTREST_SUCCESS) { + puts("Send failed."); + _client.stop(); + return false; + } + + if (_client.receive(received) != SMARTREST_SUCCESS) { + puts("No device found."); + _client.stop(); + return false; + } + _client.stop(); + + if (received.values() == 0) { + puts("Received no values."); + return false; + } + + if (received.value(0).integerValue() == 50) { + return false; + } + + if (received.value(0).integerValue() != 200) { + puts("Bad response."); + return false; + } + + _deviceId = received.value(2).integerValue(); + + return true; +} + +bool DeviceIntegration::createDevice() +{ + ComposedRecord record; + ParsedRecord received; + + puts("Creating device..."); + + IntegerValue msgId(101); + CharValue imei(_deviceInfo.imei()); + if ((!record.add(msgId)) || (!record.add(imei))) + return false; + + if (_client.send(record) != SMARTREST_SUCCESS) { + puts("Send failed."); + _client.stop(); + return 0; + } + + if (_client.receive(received) != SMARTREST_SUCCESS) { + puts("No device found."); + _client.stop(); + return false; + } + _client.stop(); + + if (received.values() != 3) { + puts("Bad received data."); + return false; + } + + if (received.value(0).integerValue() != 201) { + puts("Bad received data."); + return false; + } + + _deviceId = received.value(2).integerValue(); + return true; +} + +bool DeviceIntegration::addGlobalIdentifier() +{ + ComposedRecord record; + ParsedRecord received; + + puts("Adding global identifier..."); + + IntegerValue msgId(102); + IntegerValue deviceId(_deviceId); + CharValue imei(_deviceInfo.imei()); + if ((!record.add(msgId)) || (!record.add(deviceId)) || (!record.add(imei))) + return false; + + if (_client.send(record) != SMARTREST_SUCCESS) { + puts("Sending failed."); + _client.stop(); + return false; + } + + if (_client.receive(received) != SMARTREST_SUCCESS) { + puts("Failed."); + _client.stop(); + return false; + } + _client.stop(); + + if (received.values() != 3) { + puts("Received bad data."); + return false; + } + + if (received.value(0).integerValue() != 200) { + puts("Received bad data."); + return false; + } + + return true; +} + +bool DeviceIntegration::updateDevice() +{ + ComposedRecord record; + ParsedRecord received; + + IntegerValue msgId(103); + IntegerValue deviceId(_deviceId); + CharValue imei(_deviceInfo.imei()); + CharValue cellId(_deviceInfo.cellId()); + CharValue iccid(_deviceInfo.iccid()); + if ((!record.add(msgId)) || (!record.add(deviceId)) || (!record.add(imei)) || (!record.add(cellId)) || (!record.add(iccid))) + return false; + + if (_client.send(record) != SMARTREST_SUCCESS) { + puts("Send failed."); + _client.stop(); + return false; + } + + if (_client.receive(received) != SMARTREST_SUCCESS) { + puts("Update failed."); + _client.stop(); + return false; + } + _client.stop(); + + if (received.values() != 3) { + puts("Bad received data."); + return false; + } + + if (received.value(0).integerValue() != 201) { + puts("Bad received data."); + return false; + } + + return true; +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/DeviceIntegration.h Tue Jul 15 12:44:34 2014 +0000 @@ -0,0 +1,30 @@ +#ifndef DEVICEINTEGRATION_H +#define DEVICEINTEGRATION_H + +#include "SmartRest.h" +#include "SmartRestTemplate.h" +#include "DeviceInfo.h" + +class DeviceIntegration +{ +public: + DeviceIntegration(SmartRest&, SmartRestTemplate&, long&, DeviceInfo&); + + bool init(); + bool integrate(); + +protected: + bool deviceExisting(); + bool createDevice(); + bool addGlobalIdentifier(); + bool updateDevice(); + +private: + bool _init; + long& _deviceId; + SmartRestTemplate& _tpl; + SmartRest& _client; + DeviceInfo& _deviceInfo; +}; + +#endif \ No newline at end of file
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/MbedAgent.cpp Tue Jul 15 12:44:34 2014 +0000 @@ -0,0 +1,69 @@ +#include "MbedAgent.h" +#include "rtos.h" + +MbedAgent::MbedAgent(MDMSerial& mdm, DeviceInfo& deviceInfo) : + _mdm(mdm), + _deviceInfo(deviceInfo), + _client(MBED_AGENT_HOST, MBED_AGENT_PORT, MBED_AGENT_DEVICE_IDENTIFIER), + _bootstrap(_client, _mdm, _deviceInfo), + _integration(_client, _tpl, _deviceId, _deviceInfo), + _signalQualityMeasurement(_client, _tpl, _deviceId, _deviceInfo), + _temperatureMeasurement(_client, _tpl, _deviceId, _io.temperatureSensor()), + _accelerationMeasurement(_client, _tpl, _deviceId, _io.accelerometer()), + _deviceId(0) +{ +} + +bool MbedAgent::init() +{ + if ((!_integration.init()) || + (!_signalQualityMeasurement.init()) || + (!_temperatureMeasurement.init()) || + (!_accelerationMeasurement.init())) { + puts("Initialization failed."); + return false; + } + return true; +} + +bool MbedAgent::run() +{ + // device bootstrapping process + _io.lcdPrint("BOOTSTRAP", _deviceInfo.imei()); + if (!_bootstrap.setUpCredentials()) { + puts("Could not obtain credentials."); + return false; + } + + _io.lcdPrint("INTEGRATION"); + if (!_integration.integrate()) { + puts("Device integration process failed."); + return false; + } + + char status[60]; + snprintf(status, sizeof(status), "ID: %ld", _deviceId); + _io.lcdPrint("INTEGRATED", status); + puts(status); + + loop(); + return true; +} + +void MbedAgent::loop() +{ + Timer timer; + + timer.start(); + while (true) { + timer.reset(); + + _signalQualityMeasurement.run(); + _temperatureMeasurement.run(); + _accelerationMeasurement.run(); + + while (timer.read() < MBED_AGENT_INTERVAL) { + Thread::yield(); + } + } +} \ No newline at end of file
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/MbedAgent.h Tue Jul 15 12:44:34 2014 +0000 @@ -0,0 +1,46 @@ +#ifndef MBEDAGENT_H +#define MBEDAGENT_H + +#include <stddef.h> +#include "MDM.h" +#include "DeviceIO.h" +#include "MbedSmartRest.h" +#include "SmartRestTemplate.h" +#include "DeviceInfo.h" +#include "DeviceBootstrap.h" +#include "DeviceIntegration.h" +#include "SignalQualityMeasurement.h" +#include "TemperatureMeasurement.h" +#include "AccelerationMeasurement.h" + +#define MBED_AGENT_HOST "developer.cumulocity.com" +#define MBED_AGENT_PORT 80 +#define MBED_AGENT_DEVICE_IDENTIFIER "com_cumulocity_MbedAgent_1.0.0" +#define MBED_AGENT_INTERVAL 60.0 + +class MbedAgent +{ +public: + MbedAgent(MDMSerial&, DeviceInfo&); + + bool init(); + bool run(); + +protected: + void loop(); + +private: + DeviceIO _io; + MDMSerial& _mdm; + DeviceInfo& _deviceInfo; + MbedSmartRest _client; + SmartRestTemplate _tpl; + DeviceBootstrap _bootstrap; + DeviceIntegration _integration; + SignalQualityMeasurement _signalQualityMeasurement; + TemperatureMeasurement _temperatureMeasurement; + AccelerationMeasurement _accelerationMeasurement; + long _deviceId; +}; + +#endif \ No newline at end of file
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/SignalQualityMeasurement.cpp Tue Jul 15 12:44:34 2014 +0000 @@ -0,0 +1,52 @@ +#include "SignalQualityMeasurement.h" +#include "ComposedRecord.h" +#include "CharValue.h" +#include "IntegerValue.h" +#include "FloatValue.h" + +SignalQualityMeasurement::SignalQualityMeasurement(SmartRest& client, SmartRestTemplate& tpl, long& deviceId, DeviceInfo& deviceInfo) : + _client(client), + _tpl(tpl), + _deviceId(deviceId), + _deviceInfo(deviceInfo) +{ + _init = false; +} + +bool SignalQualityMeasurement::init() +{ + if (_init) + return false; + + // Insert measurement + // USAGE: 104,<DEVICE/ID>,<RSSI>,<BER> + if (!_tpl.add("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")) + return false; + + _init = true; + return true; +} + +bool SignalQualityMeasurement::run() +{ + DeviceInfo::SignalQuality *signalQuality; + + if ((signalQuality = _deviceInfo.signalQuality()) == NULL) + return false; + + ComposedRecord record; + IntegerValue msgId(104); + IntegerValue devId(_deviceId); + IntegerValue rssi(signalQuality->rssi); + IntegerValue ber(signalQuality->ber); + if ((!record.add(msgId)) || (!record.add(devId)) || (!record.add(rssi)) || (!record.add(ber))) + return false; + + if (_client.send(record) != SMARTREST_SUCCESS) { + puts("Signal measurement failed."); + _client.stop(); + return false; + } + _client.stop(); + return true; +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/SignalQualityMeasurement.h Tue Jul 15 12:44:34 2014 +0000 @@ -0,0 +1,24 @@ +#ifndef SIGNALQUALITYMEASUREMENT_H +#define SIGNALQUALITYMEASUREMENT_H + +#include "SmartRest.h" +#include "SmartRestTemplate.h" +#include "DeviceInfo.h" + +class SignalQualityMeasurement +{ +public: + SignalQualityMeasurement(SmartRest&, SmartRestTemplate&, long&, DeviceInfo&); + + bool init(); + bool run(); + +private: + bool _init; + long& _deviceId; + SmartRestTemplate& _tpl; + SmartRest& _client; + DeviceInfo& _deviceInfo; +}; + +#endif \ No newline at end of file
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/TemperatureMeasurement.cpp Tue Jul 15 12:44:34 2014 +0000 @@ -0,0 +1,50 @@ +#include "TemperatureMeasurement.h" +#include "ComposedRecord.h" +#include "CharValue.h" +#include "IntegerValue.h" +#include "FloatValue.h" + +TemperatureMeasurement::TemperatureMeasurement(SmartRest& client, SmartRestTemplate& tpl, long& deviceId, LM75B& sensor) : + _client(client), + _tpl(tpl), + _deviceId(deviceId), + _sensor(sensor) +{ + _init = false; +} + +bool TemperatureMeasurement::init() +{ + if (_init) + return false; + + // Insert measurement + // USAGE: 105,<DEVICE/ID>,<TEMPERATURE> + if (!_tpl.add("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")) + return false; + + _open = _sensor.open(); + _init = true; + return true; +} + +bool TemperatureMeasurement::run() +{ + if (!_open) + return false; + + ComposedRecord record; + IntegerValue msgId(105); + IntegerValue devId(_deviceId); + FloatValue temperature(_sensor.temp(), 1); + if ((!record.add(msgId)) || (!record.add(devId)) || (!record.add(temperature))) + return false; + + if (_client.send(record) != SMARTREST_SUCCESS) { + puts("Signal measurement failed."); + _client.stop(); + return false; + } + _client.stop(); + return true; +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/TemperatureMeasurement.h Tue Jul 15 12:44:34 2014 +0000 @@ -0,0 +1,24 @@ +#ifndef TEMPERATUREMEASUREMENT_H +#define TEMPERATUREMEASUREMENT_H + +#include "SmartRest.h" +#include "SmartRestTemplate.h" +#include "LM75B.h" + +class TemperatureMeasurement +{ +public: + TemperatureMeasurement(SmartRest&, SmartRestTemplate&, long&, LM75B&); + + bool init(); + bool run(); + +private: + bool _init, _open; + long& _deviceId; + SmartRestTemplate& _tpl; + SmartRest& _client; + LM75B& _sensor; +}; + +#endif \ No newline at end of file
--- a/common.h Thu Jul 10 14:22:11 2014 +0000 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,69 +0,0 @@ -#ifndef COMMON_H -#define COMMON_H - -#include <stdint.h> -#include <stddef.h> -#include "mbed.h" -#include "C027.h" -#include "MbedSmartRest.h" -#include "rtos.h" - -#define CREDENTIALS_FILE "001_CREDENTIALS" -#define CREDENTIALS_BUFFER 256 - -#define A0 P0_23 -#define A1 P0_24 -#define A2 P0_25 -#define A3 P0_26 -#define A4 P0_30 -#define A5 P1_31 - -#define D0 P4_29 -#define D1 P4_28 -#define D2 P2_13 -#define D3 P2_0 -#define D4 P2_12 -#define D5 P2_1 -#define D6 P2_2 -#define D7 P2_11 - -#define D8 P2_4 -#define D9 P2_3 -#define D10 P1_21 -#define D11 P1_24 -#define D12 P1_23 -#define D13 P1_20 - -#define SDA P0_0 -#define SCL P0_1 - - -/** signal quality type */ -typedef struct -{ - int8_t rssi; // RSSI in dBm - uint8_t ber; // BER in % -} sigq_t; - -typedef struct -{ - char username[128]; - char password[128]; -} credentials_t; - -extern C027 c027; -//extern UbloxUSBGSMModem modem; -extern MbedSmartRest client; - -const char * imei(); -const char * imsi(); -const char * cellId(); -const char * iccid(); -sigq_t * signalQuality(); -void credentials_set(credentials_t *dst, const char *tenant, const char *username, const char *password); -bool credentials_read(credentials_t *dst); -void credentials_write(credentials_t *src); -void credentials_reset(); -int program(void); - -#endif \ No newline at end of file
--- a/io.cpp Thu Jul 10 14:22:11 2014 +0000 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,109 +0,0 @@ -#include "io.h" -#include "rtos.h" -#include "mbed.h" - -void timer_callback(void const*); -void lcd_update(void); - -// Using Arduino pin notation -C12832 lcdDisplay(D11, D13, D12, D7, D10); -MMA7660 accSensor(SDA,SCL); -LM75B tempSensor(SDA,SCL); -DigitalOut button(D4); -AnalogIn meter0(A0); -AnalogIn meter1(A1); - -RtosTimer *timer; - -bool tempFound = false, accFound = false; -uint32_t count = 0; -bool btnPressed = false; - -char cSignal[80] = "", cTenant[80] = "", cStatus[80] = ""; - -void io_init(void) -{ - timer = new RtosTimer(&timer_callback, osTimerPeriodic); - timer->start(50); - tempFound = tempSensor.open(); - accFound = accSensor.testConnection(); - - if (!tempFound) - puts("Temperature sensor not found."); - if (!accFound) - puts("Accelerometer not found."); - - lcd_update(); -} - -float temperature() -{ - if (!tempFound) - return 0.0; - - return tempSensor.temp(); -} - -acceleration_t acceleration() -{ - float data[3]; - acceleration_t ret = { 0.0, 0.0, 0.0 }; - - if (accFound) { - accSensor.readData(data); - ret.x = data[0]; - ret.y = data[1]; - ret.z = data[2]; - } - - return ret; -} - -uint32_t counter() -{ - return count; -} - -double potentiometer(uint8_t n) -{ - switch (n) { - case 0: return (double)meter0; - case 1: return (double)meter1; - default: return 0.0; - } -} - -void lcd_signal(int8_t rssi, uint8_t ber) -{ - if ((rssi == 0) && (ber == 0)) - snprintf(cSignal, 80, "%s", "No signal"); - else - snprintf(cSignal, 80, "RSSI: %d dBm BER: %d %%", rssi, ber); - lcd_update(); -} - -void lcd_tenant(const char* tenant) -{ - snprintf(cTenant, 80, "Tenant: %s", tenant); - lcd_update(); -} - -void lcd_status(const char* status) -{ - snprintf(cStatus, 80, "%s", status); - lcd_update(); -} - -void timer_callback(void const*) -{ - if ((!btnPressed) && (button)) - count++; - btnPressed = button; -} - -void lcd_update(void) -{ - lcdDisplay.cls(); - lcdDisplay.locate(0, 0); - lcdDisplay.printf("%s\n%s\n%s\n", cSignal, cTenant, cStatus); -}
--- a/io.h Thu Jul 10 14:22:11 2014 +0000 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,23 +0,0 @@ -#ifndef IO_H -#define IO_H - -#include "common.h" -#include "LM75B.h" -#include "MMA7660.h" -#include "C12832.h" - -typedef struct -{ - float x, y, z; -} acceleration_t; - -void io_init(void); -float temperature(); -acceleration_t acceleration(); -uint32_t counter(); -double potentiometer(uint8_t n); -void lcd_signal(int8_t rssi, uint8_t ber); -void lcd_tenant(const char* tenant); -void lcd_status(const char* status); - -#endif \ No newline at end of file
--- a/main.cpp Thu Jul 10 14:22:11 2014 +0000 +++ b/main.cpp Tue Jul 15 12:44:34 2014 +0000 @@ -1,26 +1,16 @@ -#include "common.h" +#include "mbed.h" +#include "rtos.h" +#include "MDM.h" +#include "DeviceInfo.h" +#include "MbedAgent.h" #include "apndb.h" -#include "io.h" - -C027 c027; -MDMSerial* pMdm; -sigq_t sigQ = {}; -char cCellId[8+1]; -MDMParser::DevStatus devStatus = {}; -MDMParser::NetStatus netStatus = {}; int main() { - int ret; size_t c; - - puts("Hello"); - - io_init(); - puts("IO initialized."); + MDMParser::DevStatus devStatus; MDMSerial mdm; //mdm.setDebug(4); - pMdm = &mdm; if (!mdm.init(NULL, &devStatus)) { puts("Modem initialization failed. Check your PIN number."); @@ -38,7 +28,7 @@ printf("IMEI: %s\n", devStatus.imei); printf("IMSI: %s\n", devStatus.imsi); - if (!mdm.registerNet(&netStatus)) { + if (!mdm.registerNet()) { puts("Network registration failed."); return 1; } @@ -50,116 +40,29 @@ return 1; } - // Shown on display - signalQuality(); + DeviceInfo deviceInfo(mdm, devStatus); + MbedAgent agent(mdm, deviceInfo); - puts("Starting program..."); + puts("Starting agent ..."); + if (!agent.init()) { + puts("Initialization failure."); + mdm.disconnect(); + return 1; + } - // restart program upon failure + size_t tries = 3; + do { - ret = program(); - if (ret) - puts("Restarting program..."); - } while (ret); + puts("Running agent ..."); + + if (!agent.run()) { + puts("Agent failure."); + continue; + } else { + break; + } + } while (--tries > 0); mdm.disconnect(); - c027.mdmPower(false); - return 0; } - -const char * imei() -{ - return devStatus.imei; -} - -const char * imsi() -{ - return devStatus.imsi; -} - -const char * cellId() -{ - if (!pMdm->checkNetStatus(&netStatus)) - return NULL; - - if (snprintf(cCellId, sizeof(cCellId), "%X", netStatus.ci) < 1) - return NULL; - - return cCellId; -} - -const char * iccid() -{ - return devStatus.ccid; -} - -sigq_t * signalQuality() -{ - sigQ.rssi = 0; sigQ.ber = 0; - if (!pMdm->checkNetStatus(&netStatus)) - return NULL; - - sigQ.rssi = netStatus.rssi; - sigQ.ber = netStatus.ber; - - lcd_signal(sigQ.rssi, sigQ.ber); - return &sigQ; -} - -void credentials_set(credentials_t *dst, const char *tenant, const char *username, const char *password) -{ - char *ptr = dst->username; - - strcpy(ptr, tenant); - ptr += strlen(tenant); - strcpy(ptr++, "/"); - strcpy(ptr, username); - strcpy(dst->password, password); -} - -bool credentials_read(credentials_t *dst) -{ - char buf[CREDENTIALS_BUFFER], *ptr; - - int res = pMdm->readFile(CREDENTIALS_FILE, buf, CREDENTIALS_BUFFER); - - if (res < 0) - return false; - - buf[res] = '\0'; - if ((ptr = strchr(buf, '\n')) == NULL) - return false; - *ptr = '\0'; - - ptr = buf; - strcpy(dst->username, ptr); - ptr += strlen(ptr)+1; - strcpy(dst->password, ptr); - return true; -} - -void credentials_write(credentials_t *src) -{ - char buf[CREDENTIALS_BUFFER], *ptr; - size_t len; - - ptr = buf; - len = strlen(src->username); - strcpy(ptr, src->username); - ptr += len; - - *ptr++ = '\n'; - len++; - - len += strlen(src->password); - strcpy(ptr, src->password); - - pMdm->delFile(CREDENTIALS_FILE); - pMdm->writeFile(CREDENTIALS_FILE, buf, len); -} - -void credentials_reset() -{ - pMdm->delFile(CREDENTIALS_FILE); -}
--- a/program.cpp Thu Jul 10 14:22:11 2014 +0000 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,422 +0,0 @@ -#include "common.h" -#include "io.h" -#include "StaticData.h" -#include "ComposedRecord.h" -#include "CharValue.h" -#include "IntegerValue.h" -#include "FloatValue.h" -#include "Aggregator.h" - -/************* CONFIGURATION *************/ - -/* Credentials for device bootstrap authentification. */ -#define DEVICEBOOTSTRAP_USERNAME "management/devicebootstrap" -#define DEVICEBOOTSTRAP_PASSWORD "Fhdt1bb1f" - -/* Uncomment and fill in credentials to turn off device bootstrapping. */ -//#define CREDENTIALS_USERNAME "" -//#define CREDENTIALS_PASSWORD "" - -/* Template device identifier */ -#define TEMPLATE_DEVICE_IDENTIFIER "com_u-blox_C027_REV-A_0.10_Test1233123" - -/*****************************************/ - -bool deviceBootstrap(); -long existing(); -long create(); -bool identify(long deviceId); -bool update(long deviceId); -void loop(long deviceId); -void signalMeasurement(long deviceId, Aggregator& aggr); -void temperatureMeasurement(long deviceId, Aggregator& aggr); -void analogMeasurement(long deviceId, Aggregator& aggr); -void motionMeasurement(long deviceId, Aggregator& aggr); - -credentials_t credentials = {}; - -StaticData srtpl( -// get device by identity -// Usage: 100,<SERIAL/NR> -"10,100,GET,/identity/externalIds/c8y_Serial/%%,,application/vnd.com.nsn.cumulocity.externalId+json,%%,STRING,\r\n" -// get device id from identity -// Response: 200,<DEVICE/ID> -"11,200,\"$.managedObject\",,\"$.id\"\r\n" -// Create device -// Usage: 101,<SERIAL/NR> -"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" -// Get device id -// Response: 201,<DEVICE/ID> -"11,201,,\"$.c8y_IsDevice\",\"$.id\"\r\n" -// Insert global ID -// Usage: 102,<DEVICE/ID>,<SERIAL/NR> -"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" -// Update IMEI, CellId and iccid -// Usage: 103,<DEVICE/ID>,<IMEI>,<CELL/ID>,<ICCID> -"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" -// Insert measurement -// USAGE: 104,<DEVICE/ID>,<RSSI>,<BER> -"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" -// Insert measurement -// USAGE: 105,<DEVICE/ID>,<TEMPERATURE> -"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" -// Insert measurement -// USAGE: 105,<DEVICE/ID>,<ANALOG0>,<ANALOG1> -"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" -// Insert measurement -// USAGE: 105,<DEVICE/ID>,<X>,<Y>,<Z> -"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" -); - -float interval = 120.0; // send measurements every two minutes - -MbedSmartRest client("developer.cumulocity.com", 80, TEMPLATE_DEVICE_IDENTIFIER); - -int program(void) -{ - long deviceId = 0; Timer timer; - -#ifndef CREDENTIALS_USERNAME - // read credentials from modem or make a device bootstrapping - if (!credentials_read(&credentials)) { - puts("Could not read credentials. Starting bootstrapping process."); - if (!deviceBootstrap()) { - puts("Device bootstrap failed."); - return 1; - } - } - client.setAuthorization(credentials.username, credentials.password); -#else - client.setAuthorization(CREDENTIALS_USERNAME, CREDENTIALS_PASSWORD); -#endif - - lcd_tenant(credentials.username); - puts("Hello!"); - - puts("Bootstrapping"); - lcd_status("Bootstrapping"); - if (client.bootstrap(srtpl) != SMARTREST_SUCCESS) { - puts("Bootstrapping failed."); - lcd_status("Bootstrapping failed."); - return 2; - } - - puts("Starting action..."); - - if ((deviceId = existing()) == 0) { - if (((deviceId = create()) == 0) || (!identify(deviceId))) { - lcd_status("Device creation failed."); - return 1; - } - } - update(deviceId); - printf("Device ID: %ld\r\n", deviceId); - - timer.start(); - while (true) { - timer.reset(); - loop(deviceId); - - lcd_status("Sleeping..."); - // block remaining number of seconds - while (timer.read() < interval) { - Thread::yield(); - } - } -} - -bool deviceBootstrap() -{ - uint8_t ret; - - ComposedRecord record; - ParsedRecord received; - - IntegerValue msgId(60); - CharValue identifier(imei()); - if ((!record.add(msgId)) || (!record.add(identifier))) - return false; - - // copy credentials - client.setAuthorization(DEVICEBOOTSTRAP_USERNAME, DEVICEBOOTSTRAP_PASSWORD); - - while (true) { - if (client.send(record, "") != SMARTREST_SUCCESS) { - puts("Connection unsuccessful. Retrying."); - client.stop(); - Thread::wait(2000); - continue; - } - - if (client.receive(received) != SMARTREST_SUCCESS) { - puts("Not received anything. Retrying."); - client.stop(); - Thread::wait(2000); - continue; - } - client.stop(); - - if (received.values() < 1) { - puts("Bad received values. Retrying."); - Thread::wait(2000); - continue; - } - - if (received.value(0).integerValue() == 50) { - puts("No credentials available yet. Retrying."); - Thread::wait(2000); - continue; - } - - if (received.value(0).integerValue() != 70) { - puts("Unknown received message identifier."); - return false; - } - - if (received.values() != 6) { - puts("Bad credentials received."); - return false; - } - - credentials_set(&credentials, received.value(3).characterValue(), received.value(4).characterValue(), received.value(5).characterValue()); - - printf("Username: %s\nPassword: %s\n", credentials.username, credentials.password); - - credentials_write(&credentials); - - return true; - } -} - -long existing() -{ - ComposedRecord newMoRec(true); // set copy=true b/c tmp objects - ParsedRecord received; - - lcd_status("Checking device existance..."); - puts("Checking for device existance..."); - - if ((!newMoRec.add(IntegerValue(100))) || (!newMoRec.add(CharValue(imei())))) - return 0; - - if (client.send(newMoRec) != SMARTREST_SUCCESS) { - puts("Send failed."); - client.stop(); - return 0; - } - - if (client.receive(received) != SMARTREST_SUCCESS) { - puts("No device found."); - client.stop(); - return 0; - } - - if (received.values() == 0) { - puts("Received no values."); - client.stop(); - return 0; - } - - if (received.value(0).integerValue() == 50) { - client.stop(); - return 0; - } - - if (received.value(0).integerValue() != 200) { - puts("Bad response."); - client.stop(); - return 0; - } - - client.stop(); - return received.value(2).integerValue(); -} - -long create() -{ - ComposedRecord newMoRec(true); // set copy=true b/c tmp objects - ParsedRecord received; - - lcd_status("Creating device..."); - puts("Creating device..."); - - if ((!newMoRec.add(IntegerValue(101))) || (!newMoRec.add(CharValue(imei())))) - return 0; - - if (client.send(newMoRec) != SMARTREST_SUCCESS) { - puts("Send failed."); - client.stop(); - return 0; - } - - if (client.receive(received) != SMARTREST_SUCCESS) { - puts("No device found."); - client.stop(); - return 0; - } - - if (received.values() != 3) { - puts("Bad received data."); - client.stop(); - return 0; - } - - if (received.value(0).integerValue() != 201) { - puts("Bad received data."); - client.stop(); - return 0; - } - - client.stop(); - return received.value(2).integerValue(); -} - -bool identify(long deviceId) -{ - ComposedRecord newMoRec(true); // set copy=true b/c tmp objects - ParsedRecord received; - - puts("Adding global identifier..."); - - if ((!newMoRec.add(IntegerValue(102))) || (!newMoRec.add(IntegerValue(deviceId))) || (!newMoRec.add(CharValue(imei())))) - return 0; - - if (client.send(newMoRec) != SMARTREST_SUCCESS) { - puts("Sending failed."); - client.stop(); - return false; - } - - if (client.receive(received) != SMARTREST_SUCCESS) { - puts("Failed."); - client.stop(); - return false; - } - - if (received.values() != 3) { - puts("Received bad data."); - client.stop(); - return false; - } - - if (received.value(0).integerValue() != 200) { - puts("Received bad data."); - client.stop(); - return false; - } - - client.stop(); - return true; -} - -bool update(long deviceId) -{ - ComposedRecord newMoRec(true); // set copy=true b/c tmp objects - ParsedRecord received; - - lcd_status("Updating device object..."); - puts("Updating device data..."); - - if ((!newMoRec.add(IntegerValue(103))) || (!newMoRec.add(IntegerValue(deviceId))) || (!newMoRec.add(CharValue(imei()))) || (!newMoRec.add(CharValue(cellId()))) || (!newMoRec.add(CharValue(iccid())))) - return false; - - if (client.send(newMoRec) != SMARTREST_SUCCESS) { - puts("Send failed."); - client.stop(); - return false; - } - - if (client.receive(received) != SMARTREST_SUCCESS) { - puts("Update failed."); - client.stop(); - return false; - } - - if (received.values() != 3) { - puts("Bad received data."); - client.stop(); - return false; - } - - if (received.value(0).integerValue() != 201) { - puts("Bad received data."); - client.stop(); - return false; - } - - client.stop(); - - return true; -} - -void loop(long deviceId) -{ - Aggregator aggr(true); - - lcd_status("Sending measurements..."); - temperatureMeasurement(deviceId, aggr); - signalMeasurement(deviceId, aggr); - analogMeasurement(deviceId, aggr); - motionMeasurement(deviceId, aggr); - - if (client.send(aggr) != SMARTREST_SUCCESS) { - puts("Loop send failed."); - } - client.stop(); -} - -void signalMeasurement(long deviceId, Aggregator& aggr) -{ - sigq_t *sq = signalQuality(); - - if ((sq->rssi == 0) || (sq->ber == 0)) - return; - - ComposedRecord measurement; - IntegerValue msgId(104); - IntegerValue devId(deviceId); - FloatValue rssi(sq->rssi, 0); - IntegerValue ber(sq->ber); - if ((!measurement.add(msgId)) || (!measurement.add(devId)) || (!measurement.add(rssi)) || (!measurement.add(ber))) - return; - aggr.add(measurement); -} - -void temperatureMeasurement(long deviceId, Aggregator& aggr) -{ - ComposedRecord measurement; - IntegerValue msgId(105); - IntegerValue devId(deviceId); - FloatValue temp(temperature(), 1); - if ((!measurement.add(msgId)) || (!measurement.add(devId)) || (!measurement.add(temp))) - return; - aggr.add(measurement); -} - -void analogMeasurement(long deviceId, Aggregator& aggr) -{ - long analog0 = (long)(potentiometer(0) * 100.0); - long analog1 = (long)(potentiometer(1) * 100.0); - ComposedRecord measurement; - IntegerValue msgId(106); - IntegerValue devId(deviceId); - IntegerValue an0(analog0); - IntegerValue an1(analog1); - if ((!measurement.add(msgId)) || (!measurement.add(devId)) || (!measurement.add(an0)) || (!measurement.add(an1))) - return; - aggr.add(measurement); -} - -void motionMeasurement(long deviceId, Aggregator& aggr) -{ - acceleration_t acc = acceleration(); - ComposedRecord measurement; - IntegerValue msgId(107); - IntegerValue devId(deviceId); - FloatValue x(acc.x, 2); - FloatValue y(acc.y, 2); - FloatValue z(acc.z, 2); - if ((!measurement.add(msgId)) || (!measurement.add(devId)) || (!measurement.add(x)) || (!measurement.add(y)) || (!measurement.add(z))) - return; - aggr.add(measurement); -}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/utils/SmartRestTemplate.cpp Tue Jul 15 12:44:34 2014 +0000 @@ -0,0 +1,39 @@ +#include "SmartRestTemplate.h" +#include <string.h> + +SmartRestTemplate::SmartRestTemplate() +{ + _len = NULL; +} + +bool SmartRestTemplate::add(const char *line) +{ + if (_len == SMARTREST_TEMPLATE_FIXED_SIZE) + return false; + _buffer[_len++] = line; +} + +size_t SmartRestTemplate::writeTo(AbstractDataSink& sink) const +{ + size_t len = 0; + + for (size_t n = 0; n < _len; n++) + len += sink.write((char*)_buffer[n], strlen(_buffer[n])); + + return len; +} + +size_t SmartRestTemplate::writtenLength() const +{ + size_t len = 0; + + for (size_t n = 0; n < _len; n++) + len += strlen(_buffer[n]); + + return len; +} + +DataGenerator * SmartRestTemplate::copy() const +{ + return NULL; +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/utils/SmartRestTemplate.h Tue Jul 15 12:44:34 2014 +0000 @@ -0,0 +1,27 @@ +#ifndef SMARTRESTTEMPLATE_H +#define SMARTRESTTEMPLATE_H + +#include "DataGenerator.h" + +#define SMARTREST_TEMPLATE_FIXED_SIZE 64 + +/** + * A data generator implementation holding an array of template lines + * to send via .bootstrap(). + */ +class SmartRestTemplate : public DataGenerator +{ +public: + SmartRestTemplate(); + bool add(const char*); + + size_t writeTo(AbstractDataSink&) const; + size_t writtenLength() const; + DataGenerator* copy() const; + +private: + const char *_buffer[SMARTREST_TEMPLATE_FIXED_SIZE]; + size_t _len; +}; + +#endif \ No newline at end of file