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 Vincent Wochnik

Files at this revision

API Documentation at this revision

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

DeviceBootstrap.cpp Show annotated file Show diff for this revision Revisions of this file
DeviceIntegration.cpp Show annotated file Show diff for this revision Revisions of this file
MbedAgent.cpp Show annotated file Show diff for this revision Revisions of this file
MbedAgent.h Show annotated file Show diff for this revision Revisions of this file
MbedSmartRest.lib Show annotated file Show diff for this revision Revisions of this file
io/DeviceFeedback.cpp Show annotated file Show diff for this revision Revisions of this file
io/DeviceFeedback.h Show annotated file Show diff for this revision Revisions of this file
io/DeviceMemory.cpp Show annotated file Show diff for this revision Revisions of this file
io/LCDDisplay.h Show annotated file Show diff for this revision Revisions of this file
main.cpp Show annotated file Show diff for this revision Revisions of this file
measurement/AccelerationMeasurement.cpp Show annotated file Show diff for this revision Revisions of this file
measurement/AccelerationMeasurement.h Show annotated file Show diff for this revision Revisions of this file
measurement/AnalogMeasurement.cpp Show annotated file Show diff for this revision Revisions of this file
measurement/AnalogMeasurement.h Show annotated file Show diff for this revision Revisions of this file
measurement/LocationUpdate.cpp Show annotated file Show diff for this revision Revisions of this file
measurement/LocationUpdate.h Show annotated file Show diff for this revision Revisions of this file
measurement/SignalQualityMeasurement.cpp Show annotated file Show diff for this revision Revisions of this file
measurement/SignalQualityMeasurement.h Show annotated file Show diff for this revision Revisions of this file
measurement/TemperatureMeasurement.cpp Show annotated file Show diff for this revision Revisions of this file
measurement/TemperatureMeasurement.h Show annotated file Show diff for this revision Revisions of this file
operation/ControlParser.cpp Show annotated file Show diff for this revision Revisions of this file
operation/ControlParser.h Show annotated file Show diff for this revision Revisions of this file
operation/Opeartion.cpp Show annotated file Show diff for this revision Revisions of this file
operation/Operation.h Show annotated file Show diff for this revision Revisions of this file
operation/OperationExecutor.cpp Show diff for this revision Revisions of this file
operation/OperationExecutor.h Show diff for this revision Revisions of this file
operation/OperationSupport.cpp Show annotated file Show diff for this revision Revisions of this file
operation/OperationSupport.h Show annotated file Show diff for this revision Revisions of this file
operation/PollingThread.cpp Show annotated file Show diff for this revision Revisions of this file
operation/PollingThread.h Show annotated file Show diff for this revision Revisions of this file
operation/ReportThread.cpp Show annotated file Show diff for this revision Revisions of this file
operation/ReportThread.h Show annotated file Show diff for this revision Revisions of this file
util/RtosSmartRest.cpp Show diff for this revision Revisions of this file
util/RtosSmartRest.h Show diff for this revision Revisions of this file
util/SmartRestConf.cpp Show annotated file Show diff for this revision Revisions of this file
util/SmartRestConf.h Show annotated file Show diff for this revision Revisions of this file
util/SmartRestSocket.cpp Show annotated file Show diff for this revision Revisions of this file
util/SmartRestSocket.h Show annotated file Show diff for this revision Revisions of this file
util/lex.cpp Show annotated file Show diff for this revision Revisions of this file
util/lex.h Show annotated file Show diff for this revision Revisions of this file
util/watchdog.h Show annotated file Show diff for this revision Revisions of this file
watchdog.h Show diff for this revision Revisions of this file
--- 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