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 94:61d44636f020, committed 2015-04-20
- Comitter:
- xinlei
- Date:
- Mon Apr 20 15:04:23 2015 +0000
- Parent:
- 93:0acd11870c6a
- Child:
- 95:010b0f7a0a1a
- Commit message:
- Integration of new device push code base.
Changed in this revision
--- a/DeviceBootstrap.cpp Mon Apr 13 14:24:58 2015 +0000 +++ b/DeviceBootstrap.cpp Mon Apr 20 15:04:23 2015 +0000 @@ -29,8 +29,6 @@ if (!writeToStorage()) aWarning("Can not write credentials!\n"); } - - setAuth(_username, _password); return true; }
--- a/DeviceIntegration.cpp Mon Apr 13 14:24:58 2015 +0000 +++ b/DeviceIntegration.cpp Mon Apr 20 15:04:23 2015 +0000 @@ -202,7 +202,7 @@ CharValue imei(_deviceInfo.imei()); CharValue cellId(_deviceInfo.cellId()); CharValue iccid(_deviceInfo.iccid()); - aInfo("Update Device."); + aInfo("Update Device.\n"); if ((!record.add(msgId)) || (!record.add(deviceId)) || (!record.add(imei)) || (!record.add(cellId)) || (!record.add(iccid))) return false;
--- a/MbedAgent.cpp Mon Apr 13 14:24:58 2015 +0000 +++ b/MbedAgent.cpp Mon Apr 20 15:04:23 2015 +0000 @@ -5,22 +5,23 @@ MbedAgent::MbedAgent(GPSI2C& gps, MDMSerial& mdm, LCDDisplay& lcdDisplay, DeviceInfo& deviceInfo, DeviceMemory& deviceMemory) : + _deviceId(0), _mdm(mdm), _deviceInfo(deviceInfo), _deviceMemory(deviceMemory), + _lcdDisplay(lcdDisplay), _configurationProperties(_deviceConfiguration), _client(mdm), _bootstrap(_client, lcdDisplay, _deviceInfo, _deviceMemory), _integration(_client, _tpl, _deviceId, _deviceInfo), - _lcdDisplay(lcdDisplay), _configurationSynchronization(_client, _tpl, _deviceId, _deviceMemory, _deviceConfiguration, _configurationProperties), _signalQualityMeasurement(_client, _tpl, _deviceId, _deviceInfo, _lcdDisplay), _temperatureMeasurement(_client, _tpl, _deviceId, deviceInfo, _lcdDisplay), _accelerationMeasurement(_client, _tpl, _deviceId, deviceInfo, _lcdDisplay), _analogMeasurement(_client, _tpl, _deviceId, deviceInfo, _lcdDisplay), _locationUpdate(_client, _tpl, _deviceId, gps, deviceInfo, _lcdDisplay), - _operationSupport(_client, _tpl, _deviceId, _configurationSynchronization, _lcdDisplay), - _deviceId(0) + pool(), + _operationSupport(_client, _tpl, _deviceId, pool) { } @@ -67,6 +68,8 @@ // device bootstrapping process if (!_bootstrap.setUpCredentials()) return -1; + setAuth(_bootstrap.username(), _bootstrap.password()); + aInfo("Set auth: %s:%s (%s)\n", getUsername(), getPassword(), getAuthStr()); Thread::wait(5000); @@ -74,7 +77,9 @@ if (!_integration.integrate()) { return -2; } - + setIdentifier(_client.getIdentifier()); + aInfo("Set id: %s\n", getIdentifier()); + if (!_configurationSynchronization.integrate()) { return -3; } @@ -93,18 +98,21 @@ void MbedAgent::loop() { + ReportThread reportThread(pool, _mdm); + _operationSupport.run(); + PollingThread pollingThread(pool, _mdm, _lcdDisplay, _configurationSynchronization); + pollingThread.setChannel(_deviceId); + Watchdog wdt; wdt.kick(60.0); // set a 60.0 seconds timeout on watchdog hardware timer - while (true) { - _operationSupport.run(); - _configurationSynchronization.run(); - _signalQualityMeasurement.run(); - _temperatureMeasurement.run(); - _accelerationMeasurement.run(); - _analogMeasurement.run(); - _locationUpdate.run(); - +// _configurationSynchronization.run(); +// _analogMeasurement.run(); +// _signalQualityMeasurement.run(); +// _temperatureMeasurement.run(); +// _accelerationMeasurement.run(); +// _locationUpdate.run(); + Thread::wait(30000); // if ((interval = _configurationProperties.readInterval()) < 0) // break; // while (timer.read() < interval) {
--- a/MbedAgent.h Mon Apr 13 14:24:58 2015 +0000 +++ b/MbedAgent.h Mon Apr 20 15:04:23 2015 +0000 @@ -3,7 +3,7 @@ #include <stddef.h> #include "MDM.h" -#include "RtosSmartRest.h" +#include "SmartRest.h" #include "SmartRestTemplate.h" #include "DeviceInfo.h" #include "DeviceMemory.h" @@ -20,6 +20,8 @@ #include "OperationSupport.h" #include "LCDDisplay.h" #include "SmartRestConf.h" +#include "PollingThread.h" +#include "ReportThread.h" class MbedAgent { @@ -33,24 +35,25 @@ protected: private: + long _deviceId; MDMSerial& _mdm; DeviceInfo& _deviceInfo; DeviceMemory& _deviceMemory; + LCDDisplay& _lcdDisplay; DeviceConfiguration _deviceConfiguration; ConfigurationProperties _configurationProperties; - RtosSmartRest _client; + SmartRest _client; SmartRestTemplate _tpl; DeviceBootstrap _bootstrap; DeviceIntegration _integration; - LCDDisplay& _lcdDisplay; ConfigurationSynchronization _configurationSynchronization; SignalQualityMeasurement _signalQualityMeasurement; TemperatureMeasurement _temperatureMeasurement; AccelerationMeasurement _accelerationMeasurement; AnalogMeasurement _analogMeasurement; LocationUpdate _locationUpdate; + OperationPool pool; OperationSupport _operationSupport; - long _deviceId; }; #endif \ No newline at end of file
--- a/MbedSmartRest.lib Mon Apr 13 14:24:58 2015 +0000 +++ b/MbedSmartRest.lib Mon Apr 20 15:04:23 2015 +0000 @@ -1,1 +1,1 @@ -http://developer.mbed.org/users/xinlei/code/MbedSmartRest/#505d29d5bdfc +http://developer.mbed.org/users/xinlei/code/MbedSmartRest/#207549b3711e
--- a/io/DeviceFeedback.cpp Mon Apr 13 14:24:58 2015 +0000 +++ b/io/DeviceFeedback.cpp Mon Apr 20 15:04:23 2015 +0000 @@ -1,114 +1,19 @@ -#include <stdlib.h> -#include <string.h> -#include "DeviceFeedback.h" - -#define MSG_BEEP_SUCCESS 1 -#define MSG_BEEP_FAILURE 2 -#define MSG_CLOSE_RELAY 3 -#define MSG_OPEN_RELAY 4 +#include "mbed.h" -DeviceFeedback::DeviceFeedback() : -// _speaker(D6), -// _thread(DeviceFeedback::thread_func, this), - shieldLEDRed(D5), - shieldLEDBlue(D8), - shieldLEDGreen(D9) -{ - shieldLEDRed = 255; - shieldLEDBlue = 255; - shieldLEDGreen = 255; -} +DigitalOut shieldLEDRed(D5, 255); +DigitalOut shieldLEDBlue(D8, 255); +DigitalOut shieldLEDGreen(D9, 255); -//void DeviceFeedback::beepSuccess() -//{ -// sendMessage(MSG_BEEP_SUCCESS); -//} -// -//void DeviceFeedback::beepFailure() -//{ -// sendMessage(MSG_BEEP_FAILURE); -//} - -void DeviceFeedback::closeRelay() +void closeRelay() { shieldLEDRed = 255; shieldLEDBlue = 255; shieldLEDGreen = 0; -// sendMessage(MSG_CLOSE_RELAY); } -void DeviceFeedback::openRelay() +void openRelay() { shieldLEDRed = 255; shieldLEDBlue = 255; shieldLEDGreen = 255; -// sendMessage(MSG_OPEN_RELAY); -} - -//void DeviceFeedback::sendMessage(uint8_t msg) -//{ -// uint8_t *msgPtr = _mail.alloc(); -// *msgPtr = msg; -// _mail.put(msgPtr); -//} - -//void DeviceFeedback::thread() -//{ -// osEvent evt; -// while (true) { -// evt = _mail.get(); -// if (evt.status == osEventMail) { -// uint8_t *msg = (uint8_t*)evt.value.p; -// uint8_t u = *msg; -// _mail.free(msg); -// switch (u) { -// case MSG_BEEP_SUCCESS: -// for (float i=2000.0; i<10000.0; i+=2000.0) { -// _speaker.period(1.0/i); -// _speaker = 0.5; -// Thread::wait(200); -// _speaker = 0.0; -// Thread::wait(50); -// } -// break; -// case MSG_BEEP_FAILURE: -// for (float i=10000.0; i>2000.0; i-=2000.0) { -// _speaker.period(1.0/i); -// _speaker = 0.5; -// Thread::wait(200); -// _speaker = 0.0; -// Thread::wait(50); -// } -// break; -// case MSG_CLOSE_RELAY: -// if (!relayState) { -// for (float i=2000.0; i<10000.0; i+=100) { -// _speaker.period(1.0/i); -// _speaker = 0.5; -// Thread::wait(20); -// } -// _speaker = 0.0; -// } -// break; -// case MSG_OPEN_RELAY: -// if (relayState) { -// for (float i=10000.0; i>2000.0; i-=100) { -// _speaker.period(1.0/i); -// _speaker = 0.5; -// Thread::wait(20); -// } -// _speaker = 0.0; -// } -// break; -// } -// } -// -// } -//} - -//void DeviceFeedback::thread_func(void const *arg) -//{ -// DeviceFeedback *that; -// that = (DeviceFeedback*)arg; -// that->thread(); -//} +} \ No newline at end of file
--- a/io/DeviceFeedback.h Mon Apr 13 14:24:58 2015 +0000 +++ b/io/DeviceFeedback.h Mon Apr 20 15:04:23 2015 +0000 @@ -1,36 +1,7 @@ #ifndef DEVICEFEEDBACK_H #define DEVICEFEEDBACK_H -#include <stddef.h> -#include "mbed.h" -#include "rtos.h" - -class DeviceFeedback -{ -public: - DeviceFeedback(); - -// void beepSuccess(); -// void beepFailure(); - void closeRelay(); - void openRelay(); - -protected: -// void sendMessage(uint8_t); -// void thread(); -// static void thread_func(void const*); - -private: -// PwmOut _speaker; -// Thread _thread; - - /* LED lights on the application shield, consists of three colors: Red, Blue, Green. - * Note: value 0 means fully on for a color, 255 means off. - */ - DigitalOut shieldLEDRed; - DigitalOut shieldLEDBlue; - DigitalOut shieldLEDGreen; -// Mail<uint8_t, 16> _mail; -}; +void closeRelay(); +void openRelay(); #endif \ No newline at end of file
--- a/io/DeviceMemory.cpp Mon Apr 13 14:24:58 2015 +0000 +++ b/io/DeviceMemory.cpp Mon Apr 20 15:04:23 2015 +0000 @@ -13,22 +13,22 @@ bool DeviceMemory::loadPlatformCredentials(char *username, char *password, size_t len) { - char buffer[len*2+3]; int res, len2; - - if ((res = _mdm.readFile(PLATFORM_CREDENTIALS_FILE, buffer, sizeof(buffer))) < 0) + char buffer[len*2+3]; + int res = _mdm.readFile(PLATFORM_CREDENTIALS_FILE, buffer, sizeof(buffer)); + if (res < 0) return false; buffer[(size_t)res] = '\0'; + int len2=0; sscanf(buffer, "%s\n%s\n%n", username, password, &len2); return res == len2; } bool DeviceMemory::savePlatformCredentials(char *username, char *password, size_t len) { - char buffer[len*2+3]; int res; - - res = snprintf(buffer, sizeof(buffer), "%s\n%s\n", username, password); - if ((res < 0) || (res >= sizeof(buffer))) + char buffer[len*2+3]; + int res = snprintf(buffer, sizeof(buffer), "%s\n%s\n", username, password); + if (res<0 || res>=sizeof(buffer)) return false; return ((resetPlatformCredentials()) && (res == _mdm.writeFile(PLATFORM_CREDENTIALS_FILE, buffer, res))); @@ -42,9 +42,8 @@ bool DeviceMemory::loadConfiguration(char *cfg, size_t len) { - int res; - - if ((res = _mdm.readFile(CONFIGURATION_FILE, cfg, len)) < 0) + int res = _mdm.readFile(CONFIGURATION_FILE, cfg, len); + if (res < 0) return false; cfg[(size_t)res] = '\0'; @@ -53,10 +52,7 @@ bool DeviceMemory::saveConfiguration(char *cfg) { - size_t len; - - len = strlen(cfg); - + size_t len = strlen(cfg); return ((resetConfiguration()) && (_mdm.writeFile(CONFIGURATION_FILE, cfg, len) == len)); }
--- a/io/LCDDisplay.h Mon Apr 13 14:24:58 2015 +0000 +++ b/io/LCDDisplay.h Mon Apr 20 15:04:23 2015 +0000 @@ -3,7 +3,7 @@ #include <string.h> #include "C12832.h" #include "rtos.h" -#define DISPLAY_LEN 28 +#define DISPLAY_LEN 27 class LCDDisplay {
--- a/main.cpp Mon Apr 13 14:24:58 2015 +0000 +++ b/main.cpp Mon Apr 20 15:04:23 2015 +0000 @@ -48,6 +48,8 @@ int main() { + set_time(1256729737); + openRelay(); MDMRtos<MDMSerial> mdm; pMdm = &mdm; InterruptIn joystickUp(A2); @@ -55,7 +57,7 @@ LCDDisplay lcdDisplay; MDMParser::DevStatus devStatus; GPSI2C gps; - lcdDisplay.setLines("Mbed Agent V2.1rc1", getHost()); + lcdDisplay.setLines("Mbed Agent V2.1rc2", getHost()); if (!mdm.init(SIM_PIN, &devStatus)) { lcdDisplay.setLines("Modem Init Failure", "No SIM card found", "Or SIM has PIN"); mdm.disconnect();
--- a/measurement/AccelerationMeasurement.cpp Mon Apr 13 14:24:58 2015 +0000 +++ b/measurement/AccelerationMeasurement.cpp Mon Apr 20 15:04:23 2015 +0000 @@ -23,7 +23,7 @@ oldValues[0] = 0; oldValues[1] = 0; oldValues[2] = 0; - sendingTimer.start(); + t_start = time(NULL); } bool AccelerationMeasurement::init() @@ -54,14 +54,15 @@ // abs(oldValues[2]-data[2]) <= abs(oldValues[2])*THRESHOLD_PERCENT_ACCE) { if (((0.15>abs(data[0])) || (abs(oldValues[0]-data[0]) <= abs(oldValues[0])*THRESHOLD_PERCENT_ACCE)) && ((0.1> abs(data[1])) || (abs(oldValues[1]-data[1]) <= abs(oldValues[1])*THRESHOLD_PERCENT_ACCE))) { - if (sendingTimer.read() < TIME_LIMIT_ACCE) { + time_t t_interval = time(NULL) - t_start; + if (t_interval < TIME_LIMIT_ACCE) { // printf("[N] Acc %f, %f, %f\r\n", data[0], data[1], data[2]); if (strcmp(_lcdDisplay.getThirdLine(), "")) { _lcdDisplay.setThirdLine(""); } return true; } else { - aDebug("Acc: Timeout at %f s.\n", sendingTimer.read()); + aDebug("Acc: Timeout at %d s.\n", t_interval); } } // printf("[Y] Acc %f, %f, %f\r\n", data[0], data[1], data[2]); @@ -78,18 +79,18 @@ if ((!record.add(msgId)) || (!record.add(devId)) || (!record.add(xValue)) || (!record.add(yValue)) || (!record.add(zValue))) return false; - float t_start = sendingTimer.read(); + time_t t0 = time(NULL); if (_client.send(record) != SMARTREST_SUCCESS) { aWarning("Acc: Send failed.\n"); _client.stop(); return false; } - float t_end = sendingTimer.read(); + time_t t1 = time(NULL); _client.stop(); - aDebug("Acc: Sent in %.1f.\n", t_end-t_start); + aDebug("Acc: Sent in %d s.\n", t1-t0); oldValues[0] = data[0]; oldValues[1] = data[1]; oldValues[2] = data[2]; - sendingTimer.reset(); + t_start = time(NULL); return true; }
--- a/measurement/AccelerationMeasurement.h Mon Apr 13 14:24:58 2015 +0000 +++ b/measurement/AccelerationMeasurement.h Mon Apr 20 15:04:23 2015 +0000 @@ -22,7 +22,7 @@ AbstractSmartRest& _client; MMA7660 _sensor; float oldValues[3]; - Timer sendingTimer; + time_t t_start; DeviceInfo& _deviceInfo; LCDDisplay& _lcdDisplay; };
--- a/measurement/AnalogMeasurement.cpp Mon Apr 13 14:24:58 2015 +0000 +++ b/measurement/AnalogMeasurement.cpp Mon Apr 20 15:04:23 2015 +0000 @@ -26,7 +26,7 @@ _init = false; oldValues[0] = 0; oldValues[1] = 0; - sendingTimer.start(); + t_start = time(NULL); } bool AnalogMeasurement::init() @@ -49,14 +49,15 @@ if (abs(oldValues[0]-data[0]) <= abs(oldValues[0])*THRESHOLD_PERCENT_ANA && abs(oldValues[1]-data[1]) <= abs(oldValues[1])*THRESHOLD_PERCENT_ANA) { - if (sendingTimer.read() < TIME_LIMIT_ANA) { + time_t t_interval = time(NULL) - t_start; + if (t_interval < TIME_LIMIT_ANA) { if (strcmp(_lcdDisplay.getThirdLine(), "")) { _lcdDisplay.setThirdLine(""); } // printf("[N] %f, %f\r\n", data[0], data[1]); return true; } else { - aDebug("Poti: Timeout at %f s.\n", sendingTimer.read()); + aDebug("Poti: Timeout at %d s.\n", t_interval); } } @@ -72,17 +73,17 @@ if ((!record.add(msgId)) || (!record.add(devId)) || (!record.add(analog1)) || (!record.add(analog2))) return false; - float t_start = sendingTimer.read(); + time_t t0 = time(NULL); if (_client.send(record) != SMARTREST_SUCCESS) { aWarning("Poti: Send failed.\n"); _client.stop(); return false; } - float t_end = sendingTimer.read(); + time_t t1 = time(NULL); _client.stop(); - aDebug("Poti: Sent in %.1f.\n", t_end-t_start); + aDebug("Poti: Sent in %d s.\n", t1-t0); oldValues[0] = data[0]; oldValues[1] = data[1]; - sendingTimer.reset(); + t_start = time(NULL); return true; }
--- a/measurement/AnalogMeasurement.h Mon Apr 13 14:24:58 2015 +0000 +++ b/measurement/AnalogMeasurement.h Mon Apr 20 15:04:23 2015 +0000 @@ -21,7 +21,7 @@ SmartRestTemplate& _tpl; AbstractSmartRest& _client; float oldValues[2]; - Timer sendingTimer; + time_t t_start; DeviceInfo& _deviceInfo; LCDDisplay& _lcdDisplay; };
--- a/measurement/LocationUpdate.cpp Mon Apr 13 14:24:58 2015 +0000 +++ b/measurement/LocationUpdate.cpp Mon Apr 20 15:04:23 2015 +0000 @@ -23,7 +23,7 @@ oldValues[0] = 0; oldValues[1] = 0; oldValues[2] = 0; - sendingTimer.start(); + t_start = time(NULL); } bool LocationUpdate::init() @@ -56,13 +56,14 @@ if (abs(oldValues[0]-data[0]) <= abs(oldValues[0])*THRESHOLD_PERCENT_LOC && abs(oldValues[1]-data[1]) <= abs(oldValues[1])*THRESHOLD_PERCENT_LOC && abs(oldValues[2]-data[2]) <= abs(oldValues[2])*THRESHOLD_PERCENT_LOC) { - if (sendingTimer.read() < TIME_LIMIT_LOC) { + time_t t_interval = time(NULL) - t_start; + if (t_interval < TIME_LIMIT_LOC) { if (strcmp(_lcdDisplay.getThirdLine(), "")) { _lcdDisplay.setThirdLine(""); } return true; } else { - aDebug("GPS: Timeout at %f s.\n", sendingTimer.read()); + aDebug("GPS: Timeout at %d s.\n", t_interval); } } char status[27] = {0}; @@ -84,18 +85,18 @@ if ((!aggregator.add(record1)) || (!aggregator.add(record2))) return false; - float t_start = sendingTimer.read(); + time_t t0 = time(NULL); if (_client.send(aggregator) != SMARTREST_SUCCESS) { aWarning("GPS: Send failed.\n"); _client.stop(); return false; } - float t_end = sendingTimer.read(); + time_t t1 = time(NULL); _client.stop(); - aDebug("GPS: Sent in %.1f.\n", t_end-t_start); + aDebug("GPS: Sent in %d s.\n", t1-t0); oldValues[0] = data[0]; oldValues[1] = data[1]; oldValues[2] = data[2]; - sendingTimer.reset(); + t_start = time(NULL); return true; }
--- a/measurement/LocationUpdate.h Mon Apr 13 14:24:58 2015 +0000 +++ b/measurement/LocationUpdate.h Mon Apr 20 15:04:23 2015 +0000 @@ -22,7 +22,7 @@ AbstractSmartRest& _client; GPSTracker _gpsTracker; float oldValues[3]; - Timer sendingTimer; + time_t t_start; DeviceInfo& _deviceInfo; LCDDisplay& _lcdDisplay; };
--- a/measurement/SignalQualityMeasurement.cpp Mon Apr 13 14:24:58 2015 +0000 +++ b/measurement/SignalQualityMeasurement.cpp Mon Apr 20 15:04:23 2015 +0000 @@ -21,7 +21,7 @@ _init = false; oldValues[0] = 0; oldValues[1] = 0; - sendingTimer.start(); + t_start = time(NULL); } bool SignalQualityMeasurement::init() @@ -55,13 +55,14 @@ int data[2] = {signalQuality->rssi, signalQuality->ber}; if (abs(oldValues[0]-data[0]) <= abs(oldValues[0])*THRESHOLD_PERCENT_SIG && abs(oldValues[1]-data[1]) <= abs(oldValues[1])*THRESHOLD_PERCENT_SIG) { - if (sendingTimer.read() < TIME_LIMIT_SIG) { + time_t t_interval = time(NULL) - t_start; + if (t_interval < TIME_LIMIT_SIG) { if (strcmp(_lcdDisplay.getThirdLine(), "")) { _lcdDisplay.setThirdLine(""); } return true; } else { - aDebug("Signal: Timeout at %f s.\n", sendingTimer.read()); + aDebug("Signal: Timeout at %d s.\n", t_interval); } } @@ -76,17 +77,17 @@ if ((!record.add(msgId)) || (!record.add(devId)) || (!record.add(rssi)) || (!record.add(ber))) return false; - float t_start = sendingTimer.read(); + time_t t0 = time(NULL); if (_client.send(record) != SMARTREST_SUCCESS) { aWarning("Signal: Send failed.\n"); _client.stop(); return false; } - float t_end = sendingTimer.read(); + time_t t1 = time(NULL); _client.stop(); - aDebug("Signal: Sent in %.1f.\n", t_end-t_start); + aDebug("Signal: Sent in %d s.\n", t1-t0); oldValues[0] = data[0]; oldValues[1] = data[1]; - sendingTimer.reset(); + t_start = time(NULL); return true; }
--- a/measurement/SignalQualityMeasurement.h Mon Apr 13 14:24:58 2015 +0000 +++ b/measurement/SignalQualityMeasurement.h Mon Apr 20 15:04:23 2015 +0000 @@ -21,7 +21,7 @@ AbstractSmartRest& _client; DeviceInfo& _deviceInfo; int oldValues[2]; - Timer sendingTimer; + time_t t_start; LCDDisplay& _lcdDisplay; };
--- a/measurement/TemperatureMeasurement.cpp Mon Apr 13 14:24:58 2015 +0000 +++ b/measurement/TemperatureMeasurement.cpp Mon Apr 20 15:04:23 2015 +0000 @@ -20,7 +20,7 @@ _lcdDisplay(lcdDisplay) { _init = false; - sendingTimer.start(); + t_start = time(NULL); } bool TemperatureMeasurement::init() @@ -46,13 +46,14 @@ float data = _sensor.temp(); if (abs(oldValue-data) <= abs(oldValue)*THRESHOLD_PERCENT_TEMP) { - if (sendingTimer.read() < TIME_LIMIT_TEMP) { + time_t t_interval = time(NULL) - t_start; + if (t_interval < TIME_LIMIT_TEMP) { if (strcmp(_lcdDisplay.getThirdLine(), "")) { _lcdDisplay.setThirdLine(""); } return true; } else { - aDebug("Temp: Timeout at %f s.\n", sendingTimer.read()); + aDebug("Temp: Timeout at %d s.\n", t_interval); } } @@ -66,16 +67,16 @@ if ((!record.add(msgId)) || (!record.add(devId)) || (!record.add(temperature))) return false; - float t_start = sendingTimer.read(); + time_t t0 = time(NULL); if (_client.send(record) != SMARTREST_SUCCESS) { aWarning("Temp: Send failed.\n"); _client.stop(); return false; } - float t_end = sendingTimer.read(); + time_t t1 = time(NULL); _client.stop(); - aDebug("Temp: Sent in %.1f.\n", t_end-t_start); + aDebug("Temp: Sent in %d s.\n", t1-t0); oldValue = data; - sendingTimer.reset(); + t_start = time(NULL); return true; }
--- a/measurement/TemperatureMeasurement.h Mon Apr 13 14:24:58 2015 +0000 +++ b/measurement/TemperatureMeasurement.h Mon Apr 20 15:04:23 2015 +0000 @@ -22,7 +22,7 @@ AbstractSmartRest& _client; LM75B _sensor; float oldValue; - Timer sendingTimer; + time_t t_start; DeviceInfo& _deviceInfo; LCDDisplay& _lcdDisplay; };
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/operation/ControlParser.cpp Mon Apr 20 15:04:23 2015 +0000 @@ -0,0 +1,216 @@ +#include <stdio.h> +#include <string.h> +#include "ControlParser.h" +#include "DeviceFeedback.h" +#include "logging.h" + +void ControlParser::handleControlMessage(const char *buf) +{ + if (buf == NULL) return; + const char *p = skipHTTPHeader(buf); + Token tok; + ptrPF = &ControlParser::parseGetOp; + do { + p = lex(p, tok); + (this->*ptrPF)(tok); + } while (*p); +} + +void ControlParser::parseGetOp(Token& tok) +{ + if (tok.type == Token::INT && strncmp("211", tok.p, tok.len)==0) { + opType = 211; + ptrPF = &ControlParser::parseDeviceId; + } else { + parseError(tok); + } +} + +void ControlParser::parseDeviceId(Token& tok) +{ + if (tok.type == Token::INT) { + ptrPF = &ControlParser::parseOpId; + } else { + parseError(tok); + } +} + +void ControlParser::parseOpId(Token& tok) +{ + if (tok.type == Token::INT) { + if (opType == 211) { + sscanf(tok.p, "%ld", &op.identifier); + ptrPF = &ControlParser::parseOpState; + } else if (opType >= 220 && opType <= 222){ + ptrPF = &ControlParser::parseOpData; + } else { + parseError(tok); + } + } else { + parseError(tok); + } +} + +void ControlParser::parseOpState(Token& tok) +{ + if (tok.type == Token::STRING) { + if (strncmp(strPending, tok.p, tok.len)==0) { + Operation *p = opool.alloc(); + p->identifier = op.identifier; + p->state = OPERATION_EXECUTING; + opool.put(p); + ptrPF = &ControlParser::parseOpType; + } else { + parseError(tok); + } + } else { + parseError(tok); + } +} + +void ControlParser::parseOpType(Token& tok) +{ + if (tok.type == Token::INT) { + sscanf(tok.p, "%u", &opType); + if (opType >= 220 && opType <= 222) { + ptrPF = &ControlParser::parseDeviceId; + } else { + parseError(tok); + } + } else { + parseError(tok); + } +} + +void ControlParser::parseOpData(Token& tok) +{ + bool ret = true; + if (opType == 220) { + if (strncmp("CLOSED", tok.p, tok.len) == 0) { + closeRelay(); + } else if (strncmp("OPEN", tok.p, tok.len) == 0) { + openRelay(); + } else { + aError("Relay op (%.*s)\n", (int)tok.len, tok.p); + ret = false; + } + } else if (opType == 221) { + char line[30] = {0}; + size_t num = tok.len<30 ? tok.len : 30; + if (tok.type == Token::STRING) + strncpyEscape(line, tok.p, num); + else + strncpy(line, tok.p, num); + _lcdDisplay.setFirstLine(line); + } else if (opType == 222) { + char config[128]; + size_t num = tok.len<128 ? tok.len : 128; + strncpy(config, tok.p, num); + ret = _configSync.updateConfiguration(config); + } else { + parseError(tok); + return; + } + Operation *p = opool.alloc(); + p->identifier = op.identifier; + p->state = ret ? OPERATION_SUCCESSFUL : OPERATION_FAILED; + opool.put(p); + ptrPF = &ControlParser::parseGetOpOrBayeuxAdvice; +} + +void ControlParser::parseGetOpOrBayeuxAdvice(Token& tok) +{ + if (strncmp("211", tok.p, tok.len) == 0) { + parseGetOp(tok); + } else if (strncmp("86", tok.p, tok.len) == 0) { + parseBayeuxAdvice(tok); + } else { + parseError(tok); + } +} + +void ControlParser::parseBayeuxAdvice(Token& tok) +{ + if (strncmp("86", tok.p, tok.len) == 0) { + ptrPF = &ControlParser::parseAdviceTimeout; + } else { + parseError(tok); + } +} + +void ControlParser::parseAdviceTimeout(Token& tok) +{ + if (tok.type == Token::NONE) { + bayeuxTimeout = -1; + ptrPF = &ControlParser::parseAdviceInterval; + } else if (tok.type == Token::INT) { + sscanf(tok.p, "%d", &bayeuxTimeout); + ptrPF = &ControlParser::parseAdviceInterval; + } else { + parseError(tok); + } +} + +void ControlParser::parseAdviceInterval(Token& tok) +{ + if (tok.type == Token::NONE) { + bayeuxInterval = -1; + ptrPF = &ControlParser::parseUnknownInt; + } else if (tok.type == Token::INT) { + sscanf(tok.p, "%d", &bayeuxInterval); + ptrPF = &ControlParser::parseUnknownInt; + } else { + parseError(tok); + } +} + +void ControlParser::parseUnknownInt(Token& tok) +{ + if (tok.type == Token::INT) { + ptrPF = &ControlParser::parseAdvicePolicy; + } else { + parseError(tok); + } +} + +void ControlParser::parseAdvicePolicy(Token& tok) +{ + if (tok.type == Token::STRING) { + if (strncmp("retry", tok.p, tok.len) == 0) { + bayeuxAdvice = BA_RETRY; + } else if (strncmp("handshake", tok.p, tok.len) == 0) { + bayeuxAdvice = BA_HANDSHAKE; + } else if (strncmp("none", tok.p, tok.len) == 0) { + bayeuxAdvice = BA_NONE; + } else { + parseError(tok); + } + } else { + parseError(tok); + } +} + +void ControlParser::parseError(Token& tok) +{ + aError("(%d) %.*s\n", tok.type, (int)tok.len, tok.p); + ptrPF = &ControlParser::parseRecover; +} + +void ControlParser::parseRecover(Token& tok) +{ + if (tok.type == Token::INT) { + int i = 0; + sscanf(tok.p, "%d", &i); + if (i == 211) { + parseGetOp(tok); + } else if (i >= 220 && i <= 222) { + parseOpType(tok); + } else if (i == 86) { + parseBayeuxAdvice(tok); + } else { + ptrPF = &ControlParser::parseRecover; + } + } else { + ptrPF = &ControlParser::parseRecover; + } +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/operation/ControlParser.h Mon Apr 20 15:04:23 2015 +0000 @@ -0,0 +1,52 @@ +#ifndef CONTROLPARSER_H +#define CONTROLPARSER_H +#include "Operation.h" +#include "lex.h" +#include "DeviceFeedback.h" +#include "LCDDisplay.h" +#include "ConfigurationSynchronization.h" + +enum BayeuxAdvice{ BA_RETRY, BA_HANDSHAKE, BA_NONE }; +class ControlParser; +typedef void (ControlParser::*PtrParseFunc)(Token&); + +class ControlParser +{ +public: + ControlParser(OperationPool& pool, LCDDisplay& lcdDisplay, + ConfigurationSynchronization& configSync): opType(0), + bayeuxAdvice(BA_RETRY), bayeuxTimeout(-1), bayeuxInterval(0), + opool(pool), _lcdDisplay(lcdDisplay), _configSync(configSync) {} + virtual ~ControlParser() {} + BayeuxAdvice getBayeuxAdvice() const { return bayeuxAdvice; } + int getBayeuxInterval() const { return bayeuxInterval; } + int getBayeuxTimeout() const { return bayeuxTimeout; } + void handleControlMessage(const char*); +protected: + void parseAdviceInterval(Token& tok); + void parseAdvicePolicy(Token& tok); + void parseAdviceTimeout(Token& tok); + void parseBayeuxAdvice(Token& tok); + void parseDeviceId(Token& tok); + void parseError(Token& tok); + void parseGetOp(Token& tok); + void parseGetOpOrBayeuxAdvice(Token& tok); + void parseOpData(Token& tok); + void parseOpId(Token& tok); + void parseOpState(Token& tok); + void parseOpType(Token& tok); + void parseRecover(Token& tok); + void parseUnknownInt(Token& tok); +private: + uint8_t opType; + Operation op; + BayeuxAdvice bayeuxAdvice; + int bayeuxTimeout; + int bayeuxInterval; + PtrParseFunc ptrPF; + OperationPool& opool; + LCDDisplay& _lcdDisplay; + ConfigurationSynchronization& _configSync; +}; + +#endif /* CONTROLPARSER_H */
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/operation/Opeartion.cpp Mon Apr 20 15:04:23 2015 +0000 @@ -0,0 +1,16 @@ +#include "Operation.h" + +const char strPending[] = "PENDING"; +const char strExecuting[] = "EXECUTING"; +const char strSuccessful[] = "SUCCESSFUL"; +const char strFailed[] = "FAILED"; + +const char* strOperationState(OperationState state) +{ + switch (state) { + case OPERATION_EXECUTING: return strExecuting; + case OPERATION_SUCCESSFUL: return strSuccessful; + case OPERATION_FAILED: return strFailed; + case OPERATION_PENDING: return strPending; + } +}
--- a/operation/Operation.h Mon Apr 13 14:24:58 2015 +0000 +++ b/operation/Operation.h Mon Apr 20 15:04:23 2015 +0000 @@ -1,12 +1,26 @@ #ifndef OPERATIONSTORE_H #define OPERATIONSTORE_H +#include "rtos.h" +#define POOL_SIZE 32 -enum OperationState { OPERATION_PENDING, OPERATION_EXECUTING, OPERATION_SUCCESSFUL, OPERATION_FAILED }; +enum OperationState { + OPERATION_PENDING, + OPERATION_EXECUTING, + OPERATION_SUCCESSFUL, + OPERATION_FAILED +}; struct Operation { - Operation() : identifier(0), state(OPERATION_PENDING) {} long identifier; OperationState state; }; +typedef Mail<Operation, POOL_SIZE> OperationPool; + +const char* strOperationState(OperationState state); +extern const char strPending[]; +extern const char strExecuting[]; +extern const char strSuccessful[]; +extern const char strFailed[]; + #endif
--- a/operation/OperationExecutor.cpp Mon Apr 13 14:24:58 2015 +0000 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,101 +0,0 @@ -#include <string.h> -#include "OperationExecutor.h" -#include "ComposedRecord.h" -#include "CharValue.h" -#include "IntegerValue.h" -#include "logging.h" - -#define FOUND_RELAY 1 -#define FOUND_MESSAGE 2 -#define FOUND_CONFIGURATION 3 - -OperationExecutor::OperationExecutor(AbstractSmartRest& client, SmartRestTemplate& tpl, - long& deviceId, ConfigurationSynchronization& configurationSynchronization, - LCDDisplay& lcdDisplay) : - _init(false), - _deviceId(deviceId), - _tpl(tpl), - _client(client), - _configurationSynchronization(configurationSynchronization), - _deviceFeedback(), - _lcdDisplay(lcdDisplay) -{ -} - -bool OperationExecutor::init() -{ - if (_init) - return false; - - // Get operation by id - // USAGE: 112,<OPERATION/ID> - if (!_tpl.add("10,112,GET,/devicecontrol/operations/%%,,application/vnd.com.nsn.cumulocity.operation+json,%%,UNSIGNED,\r\n")) - return false; - - // Relay operation response - // Response: 220,<OPERATION/ID>,<STATUS> - if (!_tpl.add("11,220,,\"$.c8y_Relay\",\"$.id\",\"$.c8y_Relay.relayState\"\r\n")) - return false; - - // Message operation response - // Response: 221,<OPERATION/ID>,<MESSAGE> - if (!_tpl.add("11,221,,\"$.c8y_Message\",\"$.id\",\"$.c8y_Message.text\"\r\n")) - return false; - - // Configuration operation response - // Response: 222,<OPERATION/ID>,<CONFIGURATION/STRING> - if (!_tpl.add("11,222,,\"$.c8y_Configuration\",\"$.id\",\"$.c8y_Configuration.config\"\r\n")) - return false; - - _init = true; - return true; -} - -bool OperationExecutor::executeOperation(ParsedRecord& received) -{ - uint8_t found = 0; - bool relayState=false; - char message[128]; - if (received.values() != 4) { - aError("executeOperation: %u of 4 values received.\n", received.values()); - } else if (received.value(0).integerValue() == 220) { - relayState = strcmp("CLOSED", received.value(3).characterValue()) == 0; - found = FOUND_RELAY; - } else if (received.value(0).integerValue() == 221) { - const char *p = received.rawValue(3); - strncpy(message, p, sizeof(message)); - message[sizeof(message)-1] = '\0'; - found = FOUND_MESSAGE; - } else if (received.value(0).integerValue() == 222) { - strncpy(message, received.value(3).characterValue(), sizeof(message)); - message[sizeof(message)-1] = '\0'; - found = FOUND_CONFIGURATION; - } - - switch (found) { - case FOUND_RELAY: return executeRelayStateUpdate(relayState); - case FOUND_MESSAGE: return executeMessageDisplay(message); - case FOUND_CONFIGURATION: return executeUpdateConfiguration(message); - default: return false; - } -} - -bool OperationExecutor::executeRelayStateUpdate(bool relayState) -{ - if (relayState) - _deviceFeedback.closeRelay(); - else - _deviceFeedback.openRelay(); - return true; -} - -bool OperationExecutor::executeMessageDisplay(const char *message) -{ - _lcdDisplay.setFirstLine(message); - return true; -} - -bool OperationExecutor::executeUpdateConfiguration(const char *config) -{ - return _configurationSynchronization.updateConfiguration(config); -}
--- a/operation/OperationExecutor.h Mon Apr 13 14:24:58 2015 +0000 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,34 +0,0 @@ -#ifndef OPERATIONEXECUTOR_H -#define OPERATIONEXECUTOR_H - -#include "AbstractSmartRest.h" -#include "SmartRestTemplate.h" -#include "Operation.h" -#include "ConfigurationSynchronization.h" -#include "DeviceFeedback.h" -#include "LCDDisplay.h" - -class OperationExecutor -{ -public: - OperationExecutor(AbstractSmartRest&, SmartRestTemplate&, long&, ConfigurationSynchronization&, LCDDisplay&); - - bool init(); - bool executeOperation(ParsedRecord&); - -protected: - bool executeRelayStateUpdate(bool relayState); - bool executeMessageDisplay(const char *message); - bool executeUpdateConfiguration(const char *config); - -private: - bool _init; - long& _deviceId; - SmartRestTemplate& _tpl; - AbstractSmartRest& _client; - ConfigurationSynchronization& _configurationSynchronization; - DeviceFeedback _deviceFeedback; - LCDDisplay& _lcdDisplay; -}; - -#endif \ No newline at end of file
--- a/operation/OperationSupport.cpp Mon Apr 13 14:24:58 2015 +0000 +++ b/operation/OperationSupport.cpp Mon Apr 20 15:04:23 2015 +0000 @@ -1,34 +1,10 @@ #include <string.h> #include "OperationSupport.h" -//#include "Aggregator.h" -#include "SmartRestConf.h" +#include "ComposedRecord.h" +#include "ParsedRecord.h" +#include "IntegerValue.h" #include "logging.h" -//CharValue aOperationStatePending("PENDING"); -//CharValue aOperationStateExecuting("EXECUTING"); -//CharValue aOperationStateSuccessful("SUCCESSFUL"); -//CharValue aOperationStateFailed("FAILED"); - -const char strPending[] = "PENDING"; -const char strExecuting[] = "EXECUTING"; -const char strSuccessful[] = "SUCCESSFUL"; -const char strFailed[] = "FAILED"; - -OperationSupport::OperationSupport(RtosSmartRest& client, SmartRestTemplate& tpl, long& deviceId, - ConfigurationSynchronization& configurationSynchronization, - LCDDisplay& lcdDisplay) : - _deviceId(deviceId), - _tpl(tpl), - _client(client), - _executor(client, tpl, deviceId, configurationSynchronization, lcdDisplay), - sock(), - _thread2(OperationSupport::thread2_func, this), - _thread3(OperationSupport::thread3_func, this) -{ - _init = false; - _firstRun = true; -} - bool OperationSupport::init() { if (_init) @@ -54,7 +30,24 @@ if (!_tpl.add("11,211,,\"$.deviceId\",\"$.id\",\"$.status\"\r\n")) return false; - if (!_executor.init()) + // Get operation by id + // USAGE: 112,<OPERATION/ID> + if (!_tpl.add("10,112,GET,/devicecontrol/operations/%%,,application/vnd.com.nsn.cumulocity.operation+json,%%,UNSIGNED,\r\n")) + return false; + + // Relay operation response + // Response: 220,<OPERATION/ID>,<STATUS> + if (!_tpl.add("11,220,,\"$.c8y_Relay\",\"$.id\",\"$.c8y_Relay.relayState\"\r\n")) + return false; + + // Message operation response + // Response: 221,<OPERATION/ID>,<MESSAGE> + if (!_tpl.add("11,221,,\"$.c8y_Message\",\"$.id\",\"$.c8y_Message.text\"\r\n")) + return false; + + // Configuration operation response + // Response: 222,<OPERATION/ID>,<CONFIGURATION/STRING> + if (!_tpl.add("11,222,,\"$.c8y_Configuration\",\"$.id\",\"$.c8y_Configuration.config\"\r\n")) return false; _init = true; @@ -90,7 +83,8 @@ p.value(2).valueType() == VALUE_INTEGER) { Operation* op1 = opool.alloc(); op1->identifier = p.value(2).integerValue(); - bool ret = _executor.executeOperation(p); +// bool ret = _executor.executeOperation(p); + bool ret = true; op1->state = ret ? OPERATION_SUCCESSFUL : OPERATION_FAILED; opool.put(op1); } @@ -158,218 +152,4 @@ else return false; return true; -} - -//CharValue& OperationSupport::operationStateValue(OperationState state) const -//{ -// switch (state) { -// case OPERATION_EXECUTING: return aOperationStateExecuting; -// case OPERATION_SUCCESSFUL: return aOperationStateSuccessful; -// case OPERATION_FAILED: return aOperationStateFailed; -// default: return aOperationStatePending; -// } -//} - -const char * OperationSupport::getOperationStateChar(OperationState state) const -{ - switch (state) { - case OPERATION_EXECUTING: return strExecuting; - case OPERATION_SUCCESSFUL: return strSuccessful; - case OPERATION_FAILED: return strFailed; - case OPERATION_PENDING: return strPending; - } -} - -//void OperationSupport::thread2() -//{ -// IntegerValue msgId(111); -// Aggregator aggr(true); -// aInfo("Report thread: %p\n", Thread::gettid()); -// while (true) { -// while (!aggr.full()) { -// osEvent e = opool.get(200); -// if (e.status == osEventTimeout) { -// break; -// } else if (e.status == osEventMail) { -// Operation *op = (Operation*)e.value.p; -// ComposedRecord record; -// IntegerValue operationId(op->identifier); -// if (record.add(msgId) && record.add(operationId) && -// record.add(operationStateValue(op->state)) && aggr.add(record)) { -// printf("Reporting: <%ld, %u>.\n", op->identifier, op->state); -// opool.free(op); -// } else { -// opool.put(op); -// } -// } else { -// break; -// } -// } -// if (aggr.length()) { -// _client.sendAndClose(aggr); -// _client.stop(); -// aggr.clear(); -// } -// } -//} - -const char fmt[] = "POST /s HTTP/1.0\r\nHost: %s\r\nAuthorization: Basic %s\r\nX-Id: %s\r\nContent-Length: %d\r\n\r\n%s"; -const char fmt2[] = "111,%ld,%s\r\n"; -void OperationSupport::thread2() -{ - aInfo("Report thread: %p\n", Thread::gettid()); - while (true) { - osEvent e = opool.get(); - if (e.status == osEventMail) { - Operation *op = (Operation*)e.value.p; - aDebug("Report: <%ld, %u>.\n", op->identifier, op->state); - int len = snprintf(buf2, sizeof(buf2), fmt2, op->identifier, getOperationStateChar(op->state)); - opool.free(op); - int ret = sock.connect(getHost(), getPort()); - for (uint8_t i = 1; ret < 0 && i < 3; ++i) { - ret = sock.connect(getHost(), getPort()); - } - if (ret >= 0) { - int l = snprintf(buf, sizeof(buf), fmt, getHost(), getAuthStr(), getIdentifier(), len, buf2); - ret = sock.send(buf, l); - if (ret < 0) { - aError("Report: Send!\n"); - } - sock.close(); - } else { - aError("Report: Connect!\n"); - } - } - } -} - -void OperationSupport::thread3() -{ - char bayeuxId[33]; - ComposedRecord record; - ParsedRecord received; - - while (!_init || _firstRun) - Thread::yield(); - - // request Bayeux ID - aInfo("Polling thread: %p\n", Thread::gettid()); - { - const char *str; - IntegerValue msgId(80); - if (!record.add(msgId)) - return; - - if ((_client.stream("/devicecontrol/notifications", record) != SMARTREST_SUCCESS) || - (_client.receive(received) != SMARTREST_SUCCESS)) { - _client.stop(); - return; - } - _client.stop(); - - str = received.value(0).characterValue(); - if (str == NULL || strlen(str) > sizeof(bayeuxId)) - return; - - strcpy(bayeuxId, str); - record.clear(); - aInfo("Polling: bayeux ID %s\n", str); - } - - // set channel - { - char chn[16]; - int len = 0; - snprintf(chn, sizeof(chn), "/%ld%n", _deviceId, &len); - if (len == 0 || len == sizeof(chn)) { - aError("Polling: Invalid id %ld.\n", _deviceId); - return; - } - - IntegerValue msgId(81); - CharValue bid(bayeuxId); - CharValue channel(chn); - if (!record.add(msgId) || !record.add(bid) || !record.add(channel)) { - return; - } - - if ((_client.stream("/devicecontrol/notifications", record) != SMARTREST_SUCCESS) || - (_client.receive(received) != SMARTREST_END_OF_RESPONSE)) { - aError("Polling: Subscribe channel %s.\n", chn); - _client.stop(); - return; - } - _client.stop(); - record.clear(); - aInfo("Polling: Subscribed channel %s!\n", chn); - } - - if (!record.add(IntegerValue(83)) || !record.add(CharValue(bayeuxId))) { - return; - } - - while (true) { - if (_client.stream("/devicecontrol/notifications", record) != SMARTREST_SUCCESS) { - aError("Polling: Connect.\n"); - _client.stop(); - continue; - } - while (_client.receive(received) == SMARTREST_SUCCESS) { - for (size_t i = 0; i < received.values(); ++i) { - printf("%s ", received.rawValue(i)); - } - puts(""); - if (received.values() == 0) { - continue; - } else if (received.value(0).integerValue() == 86) { // advice responses - if (received.values() < 5) { - aWarning("Incomplete advice, %u of 5 values received.\n", received.values()); - continue; - } else if (strcmp(received.value(4).characterValue(), "retry") == 0) { - aDebug("Carry out 'retry' policy.\n"); - break; - } else if (strcmp(received.value(4).characterValue(), "handshake") == 0) { - } - } else if (received.value(0).integerValue() == 211) { // Operation State Message - Operation* op = opool.alloc(); - if (op == NULL) { - aCritical("opool full!\n"); - } else if (operationFromRecord(received, *op)) { - op->state = OPERATION_EXECUTING; - opool.put(op); - } else { - opool.free(op); - } - } else if (received.value(0).integerValue() >= 220 && - received.value(0).integerValue() <= 222) { // Real Operation - if (received.values() >= 3 && - received.value(2).valueType() == VALUE_INTEGER) { - Operation* op = opool.alloc(); - op->identifier = received.value(2).integerValue(); - bool ret = _executor.executeOperation(received); - op->state = ret ? OPERATION_SUCCESSFUL : OPERATION_FAILED; - opool.put(op); - } else { - aWarning("Incomplete operation, %u of 4 values received.\n", received.values()); - } - } else { - aError("Unknown operation ID: %d\n", received.value(0).integerValue()); - } - } - _client.stop(); - } -} - -void OperationSupport::thread2_func(void const *arg) -{ - OperationSupport *that; - that = (OperationSupport*)arg; - that->thread2(); -} - -void OperationSupport::thread3_func(void const *arg) -{ - OperationSupport *that; - that = (OperationSupport*)arg; - that->thread3(); -} +} \ No newline at end of file
--- a/operation/OperationSupport.h Mon Apr 13 14:24:58 2015 +0000 +++ b/operation/OperationSupport.h Mon Apr 20 15:04:23 2015 +0000 @@ -1,53 +1,32 @@ #ifndef OPERATIONSUPPORT_H #define OPERATIONSUPPORT_H -#include "rtos.h" -#include "ConfigurationSynchronization.h" -#include "OperationExecutor.h" -//#include "AbstractSmartRest.h" -#include "RtosSmartRest.h" +#include "Operation.h" +#include "SmartRest.h" #include "SmartRestTemplate.h" -#include "ComposedRecord.h" -#include "CharValue.h" -#include "Operation.h" -#include "ParsedRecord.h" -#include "IntegerValue.h" - -#define POOL_SIZE 64 class OperationSupport { public: - OperationSupport(RtosSmartRest&, SmartRestTemplate&, long&, ConfigurationSynchronization&, LCDDisplay&); - + OperationSupport(SmartRest& client, SmartRestTemplate& tpl, + long& deviceId, OperationPool& pool): + _init(false), _firstRun(true), _deviceId(deviceId), _tpl(tpl), + _client(client), opool(pool) {} bool init(); bool run(); protected: bool requestPendingOperations(); - bool operationFromRecord(ParsedRecord&, Operation&); bool executePendingOperation(Operation&); -// CharValue& operationStateValue(OperationState state) const; - const char * getOperationStateChar(OperationState) const; - - void thread2(); - void thread3(); - - static void thread2_func(void const*); - static void thread3_func(void const*); + bool operationFromRecord(ParsedRecord& record, Operation& op); private: - bool _init, _firstRun; + bool _init; + bool _firstRun; long& _deviceId; SmartRestTemplate& _tpl; - RtosSmartRest& _client; - Mail<Operation, POOL_SIZE> opool; - OperationExecutor _executor; - TCPSocketConnection sock; - char buf[300]; - char buf2[50]; - Thread _thread2; - Thread _thread3; + SmartRest& _client; + OperationPool& opool; }; #endif \ No newline at end of file
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/operation/PollingThread.cpp Mon Apr 20 15:04:23 2015 +0000 @@ -0,0 +1,65 @@ +#include <stdio.h> +#include <ctype.h> +#include "PollingThread.h" +#include "lex.h" +#include "logging.h" + +bool PollingThread::handshake() +{ + int l = snprintf(buf2, SMARRESTBODY_SIZE, "%s", "80\r\n"); + l = snprintf(buf, SMARTREST_SIZE, getSmartRestFmt(), uri, l, buf2); + l = sock.sendAndReceive(buf, l, SMARTREST_SIZE); + if (l < 0) + return false; + size_t i = 0; + for (const char* p = skipHTTPHeader(buf); isalnum(*p); ++p, ++i) { + bayeuxId[i] = *p; + } + bayeuxId[i] = '\0'; + return bayeuxId[0]; +} + +bool PollingThread::subscribe() +{ + int l = snprintf(buf2, SMARRESTBODY_SIZE, "81,%s,/%s\r\n", bayeuxId, chn); + l = snprintf(buf, SMARTREST_SIZE, getSmartRestFmt(), uri, l, buf2); + l = sock.sendAndReceive(buf, l, SMARTREST_SIZE); + return l>=0; +} + +bool PollingThread::connect() +{ + int l = snprintf(buf2, SMARRESTBODY_SIZE, "83,%s\r\n", bayeuxId); + l = snprintf(buf, SMARTREST_SIZE, getSmartRestFmt(), uri, l, buf2); + l = sock.sendAndReceive(buf, l, SMARTREST_SIZE); + return l>=0; +} + +void PollingThread::threadFunc() +{ + uint8_t state = 1; + aInfo("Polling thread: %p\n", Thread::gettid()); + while (true) { + switch (state) { + case 1: if (!handshake()) { + aCritical("Poll: handshake fail!\n"); + break; + } + case 2: if(!subscribe()) { + aCritical("Poll: subscribe fail!\n"); + state = 1; + break; + } + case 3: if(!connect()) { + aCritical("Poll: connect fail!\n"); + state = 1; + break; + } + default: parser.handleControlMessage(buf); + if (parser.getBayeuxAdvice() == BA_HANDSHAKE) + state = 1; + else + state = 3; + } + } +} \ No newline at end of file
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/operation/PollingThread.h Mon Apr 20 15:04:23 2015 +0000 @@ -0,0 +1,36 @@ +#ifndef POLLINGTHREAD_H +#define POLLINGTHREAD_H +#include "SmartRestSocket.h" +#include "Operation.h" +#include "SmartRestConf.h" +#include "ControlParser.h" + +class PollingThread +{ +public: + PollingThread(OperationPool& pool, MDMSerial& m, + LCDDisplay& lcdDisplay, ConfigurationSynchronization& configSync): + sock(m), parser(pool, lcdDisplay, configSync), + thread(PollingThread::threadWrapper, this) { + strncpy(uri, "/devicecontrol/notifications", sizeof(uri)); + sock.set_blocking(true); + } + virtual ~PollingThread() { sock.close(); } + bool handshake(); + bool subscribe(); + bool connect(); + void setChannel(long channel) { snprintf(chn, sizeof(chn), "/%ld", channel); } + void threadFunc(); + static void threadWrapper(const void *p) { ((PollingThread*)p)->threadFunc(); } +private: + char chn[16]; + char uri[30]; + char bayeuxId[50]; + char buf[SMARTREST_SIZE]; + char buf2[SMARRESTBODY_SIZE]; + SmartRestSocket sock; + ControlParser parser; + Thread thread; +}; + +#endif /* POLLINGTHREAD_H */
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/operation/ReportThread.cpp Mon Apr 20 15:04:23 2015 +0000 @@ -0,0 +1,23 @@ +#include "ReportThread.h" +#include "logging.h" + +const char fmt2[] = "111,%ld,%s\r\n"; + +void ReportThread::threadFunc() +{ + while (true) { + osEvent e = ipool.get(); + if (e.status == osEventMail) { + Operation *op = (Operation*)e.value.p; + long id = op->identifier; + OperationState state = op->state; + ipool.free(op); + int l = snprintf(buf2, sizeof(buf2), fmt2, id, strOperationState(state)); + l = snprintf(buf, sizeof(buf), getSmartRestFmt(), uri, l, buf2); + l = sock.sendOnly(buf, l); + if (l < 0) { + aError("Report: <%ld, %s>\n", id, strOperationState(state)); + } + } + } +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/operation/ReportThread.h Mon Apr 20 15:04:23 2015 +0000 @@ -0,0 +1,26 @@ +#ifndef REPORTTHREAD_H +#define REPORTTHREAD_H +#include "SmartRestSocket.h" +#include "Operation.h" +#include "SmartRestConf.h" + +class ReportThread +{ +public: + ReportThread(OperationPool& pool, MDMSerial& m) : ipool(pool), sock(m), + thread(ReportThread::threadWrapper, this) { + strncpy(uri, "/s", sizeof(uri)); + } + virtual ~ReportThread() { sock.close(); } + void threadFunc(); + static void threadWrapper(const void *p) { ((ReportThread*)p)->threadFunc(); } +private: + char uri[4]; + OperationPool& ipool; + char buf[SMARTREST_SIZE]; + char buf2[SMARRESTBODY_SIZE]; + SmartRestSocket sock; + Thread thread; +}; + +#endif /* REPORTTHREAD_H */ \ No newline at end of file
--- a/util/RtosSmartRest.cpp Mon Apr 13 14:24:58 2015 +0000 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,96 +0,0 @@ -#include "RtosSmartRest.h" -#include "SmartRestConf.h" -#include "logging.h" - -RtosSmartRest::RtosSmartRest(MDMSerial& mdm, uint8_t tries) : - _tries(tries), - _count(0), - slotsLock(), - _mdm(mdm) -{ -} - -RtosSmartRest::~RtosSmartRest() -{ - for (size_t i = 0; i < _count; i++) - delete _slots[i].inst; -} - -uint8_t RtosSmartRest::bootstrap(const DataGenerator& generator) -{ - MbedSmartRest *inst = instance(); - if (inst == NULL) - return SMARTREST_INTERNAL_ERROR; - - uint8_t ret = inst->bootstrap(generator); - if (ret == SMARTREST_SUCCESS) - setIdentifier(inst->getIdentifier()); - return ret; -} - -uint8_t RtosSmartRest::send(const DataGenerator& generator, const char *overrideIdentifier) -{ - MbedSmartRest *inst = instance(); - if (inst) - return inst->send(generator, overrideIdentifier); - else - return SMARTREST_INTERNAL_ERROR; -} - -uint8_t RtosSmartRest::sendAndClose(const DataGenerator& generator, const char *overrideIdentifier) -{ - MbedSmartRest *inst = instance(); - if (inst) - return inst->sendAndClose(generator, overrideIdentifier); - else - return SMARTREST_INTERNAL_ERROR; -} - -uint8_t RtosSmartRest::stream(const char *uri, const Record& record, const char *overrideIdentifier) -{ - MbedSmartRest *inst = instance(); - if (inst) - return inst->stream(uri, record, overrideIdentifier); - else - return SMARTREST_INTERNAL_ERROR; - -} - -uint8_t RtosSmartRest::receive(ParsedRecord& record) -{ - MbedSmartRest *inst = instance(); - if (inst) - return inst->receive(record); - else - return SMARTREST_INTERNAL_ERROR; -} - -void RtosSmartRest::stop() -{ - MbedSmartRest *inst = instance(); - if (inst) - inst->stop(); -} - -MbedSmartRest * RtosSmartRest::instance() -{ - osThreadId tid = Thread::gettid(); - for (size_t i = 0; i < _count; ++i) { - if (tid == _slots[i].tid) { - return _slots[i].inst; - } - } - - if (_count == RTOS_SMARTREST_SLOTS) - return NULL; - else { - MbedSmartRest *inst = new MbedSmartRest(_mdm, _tries); - slotsLock.lock(); - _slots[_count].tid = tid; - _slots[_count].inst = inst; - ++_count; - slotsLock.unlock(); - - return inst; - } -}
--- a/util/RtosSmartRest.h Mon Apr 13 14:24:58 2015 +0000 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,40 +0,0 @@ -#ifndef RTOSSMARTREST_H -#define RTOSSMARTREST_H - -#include "AbstractSmartRest.h" -#include "MbedSmartRest.h" -#include "rtos.h" - -#define RTOS_SMARTREST_SLOTS 8 - -class RtosSmartRest : public AbstractSmartRest -{ -public: - RtosSmartRest(MDMSerial&, uint8_t = MBEDSMARTREST_TRIES); - virtual ~RtosSmartRest(); - - struct Slot { - osThreadId tid; - MbedSmartRest *inst; - }; - - virtual uint8_t bootstrap(const DataGenerator&); - virtual uint8_t send(const DataGenerator&, const char* = NULL); - virtual uint8_t sendAndClose(const DataGenerator&, const char* = NULL); - virtual uint8_t stream(const char*, const Record&, const char* = NULL); - virtual uint8_t receive(ParsedRecord&); - virtual void stop(); - -protected: - MbedSmartRest * instance(); - -private: - uint8_t _tries; - - Slot _slots[RTOS_SMARTREST_SLOTS]; - size_t _count; - Mutex slotsLock; - MDMSerial& _mdm; -}; - -#endif \ No newline at end of file
--- a/util/SmartRestConf.cpp Mon Apr 13 14:24:58 2015 +0000 +++ b/util/SmartRestConf.cpp Mon Apr 20 15:04:23 2015 +0000 @@ -1,4 +1,5 @@ #include <string.h> +#include <stdio.h> #include "b64.h" const char* _username = NULL; @@ -8,6 +9,7 @@ const char _host[] = "developer.cumulocity.com"; // const char _host[] = "management.m2m-devicecloud.com" const int _port = 80; +char fmtSmartRest[200] = {0}; const char* getAuthStr() { @@ -39,18 +41,6 @@ } } - -const char* getIdentifier() -{ - return _identifier; -} - -void setIdentifier(const char* id) -{ - if (id) - _identifier = id; -} - const char* getUsername() { return _username; @@ -71,13 +61,6 @@ _password = password; } -void setAuth(const char* username, const char* password) -{ - setUsername(username); - setPassword(password); - setAuthStr(username, password); -} - const char* getHost() { return _host; @@ -87,3 +70,39 @@ { return _port; } + +const char* getSmartRestFmt() +{ + return fmtSmartRest; +} + +const char* getIdentifier() +{ + return _identifier; +} + +void setSmartRestFmt() +{ + const char fmt[] = "POST %%s HTTP/1.0\r\nHost: %s\r\nAuthorization: Basic %s\r\nX-Id: %s\r\nContent-Length: %%d\r\n\r\n%%s"; + snprintf(fmtSmartRest, sizeof(fmtSmartRest), fmt, getHost(), getAuthStr(), getIdentifier()); +} + +void setIdentifier(const char* id) +{ + if (id) { + _identifier = id; + setSmartRestFmt(); + } +} + +void setAuth(const char* username, const char* password) +{ + if (username) + setUsername(username); + if (password) + setPassword(password); + if (username || password) { + setAuthStr(username, password); + setSmartRestFmt(); + } +} \ No newline at end of file
--- a/util/SmartRestConf.h Mon Apr 13 14:24:58 2015 +0000 +++ b/util/SmartRestConf.h Mon Apr 20 15:04:23 2015 +0000 @@ -1,21 +1,18 @@ #ifndef SMARTRESTCONF_H #define SMARTRESTCONF_H +#define SMARTREST_SIZE 600 +#define SMARRESTBODY_SIZE 300 const char* getHost(); int getPort(); void setAuth(const char* username, const char* password); - -void setAuthStr(const char* p1, const char* p2); +const char* getUsername(); +const char* getPassword(); const char* getAuthStr(); +const char* getSmartRestFmt(); void setIdentifier(const char* id); const char* getIdentifier(); -void setUsername(const char* username); -const char* getUsername(); - -void setPassword(const char* password); -const char* getPassword(); - #endif /* SMARTRESTCONF_H */
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/util/SmartRestSocket.cpp Mon Apr 20 15:04:23 2015 +0000 @@ -0,0 +1,59 @@ +#include <string.h> +#include "SmartRestSocket.h" +#include "SmartRestConf.h" + +//memset((void*)SmartRestSocket::cachedIP, 0, sizeof(SmartRestSocket::cachedIP)); +char SmartRestSocket::cachedIP[16] = {0}; + +int SmartRestSocket::connect() +{ + int n = -1; + ipLock.lock(); + for (size_t i = 0; i < 3; ++i) { + if (cachedIP[0] == '\0') { + MDMParser::IP ip = mdm.gethostbyname(getHost()); + if (ip == NOIP) + continue; + const unsigned char *c = (const unsigned char*)&ip; + snprintf(cachedIP, sizeof(cachedIP), "%u.%u.%u.%u", c[3], c[2], c[1], c[0]); + } + n = TCPSocketConnection::connect(cachedIP, getPort()); + if (n >= 0) { + break; + } else { + cachedIP[0] = '\0'; + } + } + ipLock.unlock(); + return n; +} + +int SmartRestSocket::sendOnly(char *buf, int size) +{ + int l = connect(); + if (l < 0) + return -3; + l = send(buf, size); + close(); + if (l < 0) { + return -2; + } else { + return l; + } +} + +int SmartRestSocket::sendAndReceive(char *buf, int size, int maxSize) +{ + int l = connect(); + if (l < 0) + return -3; + l = send(buf, size); + if (l < 0) { + close(); + return -2; + } else { + l = receive(buf, maxSize); + close(); + return l; + } +} \ No newline at end of file
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/util/SmartRestSocket.h Mon Apr 20 15:04:23 2015 +0000 @@ -0,0 +1,21 @@ +#ifndef SMARTRESTSOCKET_H +#define SMARTRESTSOCKET_H +#include "MDM.h" +#include "TCPSocketConnection.h" +#include "rtos.h" + +class SmartRestSocket : public TCPSocketConnection +{ +public: + SmartRestSocket(MDMSerial& m): TCPSocketConnection(), mdm(m) {} + virtual ~SmartRestSocket() {} + int connect(); + int sendOnly(char *buf, int size); + int sendAndReceive(char *buf, int size, int maxSize); +private: + static char cachedIP[16]; + MDMSerial& mdm; + Mutex ipLock; +}; + +#endif /* SMARTRESTSOCKET_H */ \ No newline at end of file
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/util/lex.cpp Mon Apr 20 15:04:23 2015 +0000 @@ -0,0 +1,120 @@ +#include <ctype.h> +#include <string.h> +#include "lex.h" + +const char* skipHTTPHeader(const char* p) +{ + const char* ptr = p; + if (p) + ptr = strstr(p, "\r\n\r\n"); + + if (ptr) { + return ptr+4; + } else { + return NULL; + } +} + +const char* lex(const char *p, Token& t) +{ + if (p == NULL) { + t.type = Token::NONE; + t.p = NULL; + t.len = 0; + return NULL; + } + t.type = Token::NONE; + size_t i = 0; + while (p[i] && isspace(p[i])) ++i; + bool opening = false; + if (p[i] == '"') { + opening = true; + ++i; + } + size_t j = i; + size_t dots = 0; + bool hasChar = false; + bool escaping = false; + bool hasDigit = false; + for (;p[j]; ++j) { + if (p[j] == '"') { + if (!opening) { // inline quote + t.type = Token::ERROR; + } else if (!escaping) { // escaping quote + escaping = true; + } else { + hasChar = true; + escaping = false; + } + } else { + if (escaping && opening) { + break; + } else if (p[j] == '.') { + hasChar = true; + dots++; + } else if (p[j] == ',' || iscntrl(p[j])) { + if (opening) + hasChar = true; + else + break; + } else if (isdigit(p[j])) { + hasDigit = true; + } else { + hasChar = true; + } + } + } + t.p = p+i; + size_t k = j; + while (k > i && (p[k]==',' || isspace(p[k]))) --k; + t.len = k-i+1; + if (escaping && opening) { + opening = false; + t.len -= 1; + } + if (t.type != Token::ERROR) { + if (opening) { + t.type = Token::ERROR; + } else if (hasChar) { + t.type = Token::STRING; + } else if (hasDigit) { + switch (dots) { + case 0: t.type = Token::INT; break; + case 1: t.type = Token::FLOAT; break; + default: t.type = Token::STRING; break; + } + } else { + t.type = Token::NONE; + } + } + while (p[j]) { + if (isspace(p[j])) { + ++j; + } else if (p[j]==',') { + ++j; + break; + } else { + break; + } + } + return p+j; +} + +size_t strncpyEscape(char* dest, const char *source, size_t num) +{ + if (source == NULL) return 0; + size_t i = 0, j = 0; + for (bool escaping = false; i < num; ++i) { + if (source[i] != '"') { + dest[j++] = source[i]; + } else { + if (escaping) { + dest[j++] = source[i]; + escaping = false; + } else { + escaping = true; + } + } + } + return j; +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/util/lex.h Mon Apr 20 15:04:23 2015 +0000 @@ -0,0 +1,22 @@ +#ifndef LEX_H +#define LEX_H +#include <stddef.h> + +struct Token +{ + enum TokType{ + INT, + FLOAT, + STRING, + NONE, + ERROR + } type; + const char *p; + size_t len; +}; + +const char* skipHTTPHeader(const char* p); +const char* lex(const char*, Token&); +size_t strncpyEscape(char*, const char*, size_t); + +#endif /* LEX_H */
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/util/watchdog.h Mon Apr 20 15:04:23 2015 +0000 @@ -0,0 +1,22 @@ +#ifndef WATCHDOG_H +#define WATCHDOG_H +#include "mbed.h" + +class Watchdog { +public: +// Load timeout value in watchdog timer and enable + void kick(float s) { + LPC_WDT->WDCLKSEL = 0x1; // Set CLK src to PCLK + uint32_t clk = SystemCoreClock / 16; // WD has a fixed /4 prescaler, PCLK default is /4 + LPC_WDT->WDTC = s * (float)clk; + LPC_WDT->WDMOD = 0x3; // Enabled and Reset + kick(); + } +// "kick" or "feed" the dog - reset the watchdog timer +// by writing this required bit pattern + void kick() { + LPC_WDT->WDFEED = 0xAA; + LPC_WDT->WDFEED = 0x55; + } +}; +#endif /* WATCHDOG_H */ \ No newline at end of file
--- a/watchdog.h Mon Apr 13 14:24:58 2015 +0000 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,22 +0,0 @@ -#ifndef WATCHDOG_H -#define WATCHDOG_H -#include "mbed.h" - -class Watchdog { -public: -// Load timeout value in watchdog timer and enable - void kick(float s) { - LPC_WDT->WDCLKSEL = 0x1; // Set CLK src to PCLK - uint32_t clk = SystemCoreClock / 16; // WD has a fixed /4 prescaler, PCLK default is /4 - LPC_WDT->WDTC = s * (float)clk; - LPC_WDT->WDMOD = 0x3; // Enabled and Reset - kick(); - } -// "kick" or "feed" the dog - reset the watchdog timer -// by writing this required bit pattern - void kick() { - LPC_WDT->WDFEED = 0xAA; - LPC_WDT->WDFEED = 0x55; - } -}; -#endif /* WATCHDOG_H */ \ No newline at end of file