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 13 14:24:58 2015 +0000
Parent:
92:48069375dffa
Child:
94:61d44636f020
Commit message:
v2.1rc1

Changed in this revision

C027_Support.lib Show annotated file Show diff for this revision Revisions of this file
DeviceBootstrap.cpp Show annotated file Show diff for this revision Revisions of this file
DeviceBootstrap.h 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
DisplayInfo.h 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
config/ConfigurationSynchronization.cpp 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/DeviceIO.cpp Show diff for this revision Revisions of this file
io/DeviceIO.h Show diff for this revision Revisions of this file
io/GPSTracker.cpp Show annotated file Show diff for this revision Revisions of this file
io/LCDDisplay.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
mbed.bld 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/Operation.h Show annotated file Show diff for this revision Revisions of this file
operation/OperationExecutor.cpp Show annotated file Show diff for this revision Revisions of this file
operation/OperationExecutor.h Show annotated file Show diff for this revision Revisions of this file
operation/OperationStore.cpp Show diff for this revision Revisions of this file
operation/OperationStore.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
util/RtosSmartRest.cpp Show annotated file Show diff for this revision Revisions of this file
util/RtosSmartRest.h Show annotated file 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
--- a/C027_Support.lib	Fri Mar 20 14:27:10 2015 +0000
+++ b/C027_Support.lib	Mon Apr 13 14:24:58 2015 +0000
@@ -1,1 +1,1 @@
-http://developer.mbed.org/users/xinlei/code/C027_Support/#98e685503727
+http://developer.mbed.org/users/xinlei/code/C027_Support/#246587b92b3b
--- a/DeviceBootstrap.cpp	Fri Mar 20 14:27:10 2015 +0000
+++ b/DeviceBootstrap.cpp	Mon Apr 13 14:24:58 2015 +0000
@@ -1,35 +1,36 @@
-#include "DeviceBootstrap.h"
 #include <stdlib.h>
 #include <stdio.h>
 #include <string.h>
+#include "DeviceBootstrap.h"
 #include "rtos.h"
 #include "ComposedRecord.h"
 #include "CharValue.h"
 #include "IntegerValue.h"
 #include "ParsedRecord.h"
+#include "SmartRestConf.h"
 #include "logging.h"
 
-DeviceBootstrap::DeviceBootstrap(AbstractSmartRest& client, DeviceIO& io, DeviceInfo& deviceInfo, DeviceMemory& deviceMemory) :
+DeviceBootstrap::DeviceBootstrap(AbstractSmartRest& client, LCDDisplay& lcdDisplay,
+    DeviceInfo& deviceInfo, DeviceMemory& deviceMemory) :
     _client(client),
     _deviceInfo(deviceInfo),
     _deviceMemory(deviceMemory),
-    _io(io)
+    _lcdDisplay(lcdDisplay)
 {
     *_username = *_password = '\0';
 }
 
 bool DeviceBootstrap::setUpCredentials()
 {
-    if (((*_username == '\0') || (*_password == '\0')) &&
+    if ((*_username == '\0' || *_password == '\0') &&
         (!obtainFromStorage())) {
         if (!obtainFromPlatform())
             return false;
         if (!writeToStorage())
-            aWarning("Could not write credentials to file!");
+            aWarning("Can not write credentials!\n");
     }
 
-    if (_client.setAuthorization(_username, _password) != SMARTREST_SUCCESS)
-        return false;
+    setAuth(_username, _password);
     return true;
 }
 
@@ -49,24 +50,21 @@
 }
 
 bool DeviceBootstrap::obtainFromPlatform()
-{
-    uint8_t tries;
-    
+{    
     ComposedRecord record;
     ParsedRecord recvdRecord;
 
     IntegerValue msgId(61);
     CharValue identifier(_deviceInfo.imei());
-    if ((!record.add(msgId)) || (!record.add(identifier)))
+    if (!record.add(msgId) || !record.add(identifier))
         return false;
 
     // set authorization for bootstrap
-    if (_client.setAuthorization(DEVICE_BOOTSTRAP_USERNAME, DEVICE_BOOTSTRAP_PASSWORD) != SMARTREST_SUCCESS)
-        return false;
+    setAuth(DEVICE_BOOTSTRAP_USERNAME, DEVICE_BOOTSTRAP_PASSWORD);
 
-    _io.lcdPrint("Bootstrap", _deviceInfo.imei());
-    
-    tries = 255;
+    _lcdDisplay.setLines("Bootstrap", _deviceInfo.imei());
+
+    uint8_t tries = 255;
     do {
         if (_client.send(record, "") != SMARTREST_SUCCESS) {
             _client.stop();
@@ -79,11 +77,7 @@
             continue;
         }
         _client.stop();
-        
-        if (getLevel() == A_DEBUG) {
-            for (size_t q = 0; q < recvdRecord.values(); q++)
-                aDebug("Bootstrap, received: %s\r\n", recvdRecord.rawValue(q));
-        }    
+
         if ((recvdRecord.values() < 1) ||
             (recvdRecord.value(0).integerValue() == 50)) {
             Thread::wait(2000);
@@ -97,11 +91,11 @@
         setCredentials(recvdRecord.value(3).characterValue(),
                        recvdRecord.value(4).characterValue(),
                        recvdRecord.value(5).characterValue());        
-        _io.lcdPrint("Bootstrap Success", _username, _password);
+        _lcdDisplay.setLines("Bootstrap Success", _username, _password);
         return true;
     } while (--tries > 0);
 
-    _io.lcdPrint("Bootstrap Failure");
+    _lcdDisplay.setLines("Bootstrap Failure");
     return false;
 }
 
--- a/DeviceBootstrap.h	Fri Mar 20 14:27:10 2015 +0000
+++ b/DeviceBootstrap.h	Mon Apr 13 14:24:58 2015 +0000
@@ -2,7 +2,7 @@
 #define DEVICEBOOTSTRAP_H
 
 #include <stddef.h>
-#include "DeviceIO.h"
+#include "LCDDisplay.h"
 #include "DeviceMemory.h"
 #include "AbstractSmartRest.h"
 #include "DeviceInfo.h"
@@ -18,7 +18,7 @@
 class DeviceBootstrap
 {
 public:
-    DeviceBootstrap(AbstractSmartRest&, DeviceIO&, DeviceInfo&, DeviceMemory&);
+    DeviceBootstrap(AbstractSmartRest&, LCDDisplay&, DeviceInfo&, DeviceMemory&);
     
     bool setUpCredentials();
     const char * username();
@@ -36,7 +36,7 @@
     AbstractSmartRest& _client;
     DeviceInfo& _deviceInfo;
     DeviceMemory& _deviceMemory;
-    DeviceIO& _io;
+    LCDDisplay& _lcdDisplay;
     char _username[DEVICE_BOOTSTRAP_CREDENTIALS_LENGTH];
     char _password[DEVICE_BOOTSTRAP_CREDENTIALS_LENGTH];
 };
--- a/DeviceIntegration.cpp	Fri Mar 20 14:27:10 2015 +0000
+++ b/DeviceIntegration.cpp	Mon Apr 13 14:24:58 2015 +0000
@@ -1,5 +1,5 @@
+#include <stdio.h>
 #include "DeviceIntegration.h"
-#include <stdio.h>
 #include "ComposedRecord.h"
 #include "CharValue.h"
 #include "IntegerValue.h"
@@ -92,14 +92,13 @@
     }
 
     if (_client.receive(received) != SMARTREST_SUCCESS) {
-        aError("No device found.\r\n");
+        aError("No device found.\n");
         _client.stop();
         return false;
     }
     _client.stop();
 
     if (received.values() == 0) {
-        aError("Received no values.\r\n");
         return false;
     }
 
@@ -108,10 +107,9 @@
     }
     
     if (received.value(0).integerValue() != 200) {
-        aError("Bad response.\r\n");
+        aError("Unknown message ID: %d.\n", received.value(0).integerValue());
         return false;
     }
-
     _deviceId = received.value(2).integerValue();
     
     return true;
@@ -122,7 +120,7 @@
     ComposedRecord record;
     ParsedRecord received;
 
-    aInfo("Creating device...\r\n");
+    aInfo("Create device...\n");
 
     IntegerValue msgId(101);
     CharValue imei(_deviceInfo.imei());
@@ -130,25 +128,24 @@
         return false;
 
     if (_client.send(record) != SMARTREST_SUCCESS) {
-        aError("Failed to sending data when creating device.\r\n");
         _client.stop();
         return 0;
     }
 
     if (_client.receive(received) != SMARTREST_SUCCESS) {
-        aError("No device found.\r\n");
+        aError("No device found.\n");
         _client.stop();
         return false;
     }
     _client.stop();
 
     if (received.values() != 3) {
-        aError("Received incomplete data when creating device.\r\n");
+        aError("createDevice: Incomplete response.\n");
         return false;
     }
     
     if (received.value(0).integerValue() != 201) {
-        aError("Received invalid data when creating device.\r\n");
+        aError("createDevice: Unknown message ID: %d.\n", received.value(0).integerValue());
         return false;
     }
 
@@ -161,7 +158,7 @@
     ComposedRecord record;
     ParsedRecord received;
 
-    aInfo("Adding global identifier...\r\n");
+    aInfo("Add global identifier.\n");
 
     IntegerValue msgId(102);
     IntegerValue deviceId(_deviceId);
@@ -176,19 +173,19 @@
     }
 
     if (_client.receive(received) != SMARTREST_SUCCESS) {
-        aError("Received data failed when adding global identifier.\r\n");
+        aError("Receive identifier failed.\n");
         _client.stop();
         return false;
     }
     _client.stop();
 
     if (received.values() != 3) {
-        aError("Received incomplete data when adding global identifier.\r\n");
+        aError("%d (3) values received.\n", received.values());
         return false;
     }
     
     if (received.value(0).integerValue() != 200) {
-        aError("Received invalid data when adding global identifier.\r\n");
+        aError("Unknown message ID: %d\n", received.value(0).integerValue());
         return false;
     }
 
@@ -205,29 +202,30 @@
     CharValue imei(_deviceInfo.imei());
     CharValue cellId(_deviceInfo.cellId());
     CharValue iccid(_deviceInfo.iccid());
+    aInfo("Update Device.");
     if ((!record.add(msgId)) || (!record.add(deviceId)) || (!record.add(imei)) || (!record.add(cellId)) || (!record.add(iccid)))
         return false;
 
     if (_client.send(record) != SMARTREST_SUCCESS) {
-        aError("Sending data failed when updating device.\r\n");
+        aError("Send.\n");
         _client.stop();
         return false;
     }
 
     if (_client.receive(received) != SMARTREST_SUCCESS) {
-        aError("Updating device failed.\r\n");
+        aError("Receive.\n");
         _client.stop();
         return false;
     }
     _client.stop();
 
     if (received.values() != 3) {
-        aError("Received incomplete data when updating device.\r\n");
+        aError("%d (3) values received.\n", received.values());
         return false;
     }
     
     if (received.value(0).integerValue() != 201) {
-        aError("Received invalid data when updating device.\r\n");
+        aError("Unknown message ID: %d\n", received.value(0).integerValue());
         return false;
     }
 
--- a/DisplayInfo.h	Fri Mar 20 14:27:10 2015 +0000
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,29 +0,0 @@
-#ifndef DISPLAYINFO_H
-#define DISPLAYINFO_H
-#include <string.h>
-class DisplayInfo
-{
-public:
-        DisplayInfo(): firstLine(""), secondLine("") {}
-        void setFirstLine(const char* p) {
-                _setLine(firstLine, sizeof(firstLine), p);
-        }
-        const char *getFirstLine() const { return firstLine; }
-        void setSecondLine(const char* p) {
-                _setLine(secondLine, sizeof(secondLine), p);
-        }
-        const char *getSecondLine() const { return secondLine; }
-        virtual ~DisplayInfo() {}
-protected:
-        void _setLine(char *dest, size_t n, const char* src) {
-                if (src) {
-                        strncpy(dest, src, n-1);
-                        dest[n-1] = '\0';
-                }
-        }
-private:
-        char firstLine[25];
-        char secondLine[25];
-};
-
-#endif /* DISPLAYINFO_H */
--- a/MbedAgent.cpp	Fri Mar 20 14:27:10 2015 +0000
+++ b/MbedAgent.cpp	Mon Apr 13 14:24:58 2015 +0000
@@ -3,25 +3,23 @@
 #include "logging.h"
 #include "watchdog.h"
 
-bool lastSensorReadingSent=true;
-
-MbedAgent::MbedAgent(DeviceIO& io, MDMSerial& mdm, DeviceInfo& deviceInfo, DeviceMemory& deviceMemory) :
-    _io(io),
+MbedAgent::MbedAgent(GPSI2C& gps, MDMSerial& mdm, LCDDisplay& lcdDisplay,
+    DeviceInfo& deviceInfo, DeviceMemory& deviceMemory) :
     _mdm(mdm),
     _deviceInfo(deviceInfo),
     _deviceMemory(deviceMemory),
     _configurationProperties(_deviceConfiguration),
-    _client(MBED_AGENT_HOST, MBED_AGENT_PORT, MBED_AGENT_DEVICE_IDENTIFIER, mdm),
-    _bootstrap(_client, _io, _deviceInfo, _deviceMemory),
+    _client(mdm),
+    _bootstrap(_client, lcdDisplay, _deviceInfo, _deviceMemory),
     _integration(_client, _tpl, _deviceId, _deviceInfo),
-    _displayInfo(),
+    _lcdDisplay(lcdDisplay),
     _configurationSynchronization(_client, _tpl, _deviceId, _deviceMemory, _deviceConfiguration, _configurationProperties),
-    _signalQualityMeasurement(_client, _tpl, _deviceId, _deviceInfo, io, _displayInfo),
-    _temperatureMeasurement(_client, _tpl, _deviceId, io, deviceInfo, _displayInfo),
-    _accelerationMeasurement(_client, _tpl, _deviceId, io, deviceInfo, _displayInfo),
-    _analogMeasurement(_client, _tpl, _deviceId, io, deviceInfo, _displayInfo),
-    _locationUpdate(_client, _tpl, _deviceId, _io.gpsTracker(), io, deviceInfo, _displayInfo),
-    _operationSupport(_client, _tpl, _deviceId, _configurationSynchronization, _io, _displayInfo),
+    _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)
 {
 }
@@ -30,103 +28,85 @@
 {
     bool flag = true;
     if (!_integration.init()) {
-        aError("Init Device Integration failed.\r\n");
+        _lcdDisplay.setLines("Integration init failure");
         flag = false;
     }
     if (!_configurationSynchronization.init()) {
-        aError("Init Configuration Synchronization failed.\r\n");
+        _lcdDisplay.setLines("Config Sync init failure");
         flag = false;
     }
     if (!_signalQualityMeasurement.init()) {
-        aError("Init Signal Quality Measurement failed.\r\n");
+        _lcdDisplay.setLines("Signal init failure");
         flag = false;
     }
     if (!_temperatureMeasurement.init()) {
-        aError("Init Temperature Measurement failed.\r\n");
+        _lcdDisplay.setLines("Temperature init failure");
         flag = false;
     }
     if (!_accelerationMeasurement.init()) {
-        aError("Init Acceleration Measurement failed.\r\n");
+        _lcdDisplay.setLines("Acceleration init failure");
         flag = false;
     }
     if (!_analogMeasurement.init()) {
-        aError("Init Analog Measurement failed.\r\n");
+        _lcdDisplay.setLines("Analog init failure");
         flag = false;
     }
     if (!_locationUpdate.init()) {
-        aError("Init Location Measurement failed.\r\n");
+        _lcdDisplay.setLines("Location init failure");
         flag = false;
     }
     if (!_operationSupport.init()) {
-        aError("Init Operation Support failed.\r\n");
+        _lcdDisplay.setLines("Operation init failure");
         flag = false;
     }
     return flag;
 }
 
-bool MbedAgent::run()
+int MbedAgent::run()
 {
     // device bootstrapping process
     if (!_bootstrap.setUpCredentials())
-        return false;
+        return -1;
 
     Thread::wait(5000);
 
-    _io.lcdPrint("Connect to Cloud", MBED_AGENT_HOST);
+    _lcdDisplay.setLines("Connect to Cloud", getHost());
     if (!_integration.integrate()) {
-        return false;
+        return -2;
     }
     
     if (!_configurationSynchronization.integrate()) {
-        return false;
+        return -3;
     }
     
-    char status[60];
+    char status[27];
     snprintf(status, sizeof(status), "ID: %ld", _deviceId);
-    _io.lcdPrint("Connected", status);
+    _lcdDisplay.setLines("Connected", status);
 
-    char tenant[25];
-    const char* user= _bootstrap.username();
-    int len = strchr(user, '/')-user+1+8;  // 8: length of "Tenant: "
-    len = len <= 25 ? len : 25;
-    snprintf(tenant, len, "Tenant: %s", user);
-    _displayInfo.setFirstLine(tenant);
-    loop();
-
-    return true;
+    const char* user= getUsername();
+    int len = strchr(user, '/')-user+sizeof("Tenant: ");
+    len = len <= 27 ? len : 27;
+    snprintf(status, len, "Tenant: %s", user);
+    _lcdDisplay.setFirstLine(status);
+    return 0;
 }
 
 void MbedAgent::loop()
 {
     Watchdog wdt;
-    DigitalIn joystickUp(A2);
-    DigitalIn joystickDown(A3);
-//    DigitalIn joystickLeft(A4);
-//    AnalogIn joystickRight(A5);
-    
     wdt.kick(60.0);    // set a 60.0 seconds timeout on watchdog hardware timer
+
     while (true) {
-        if (joystickDown) {
-            setLevel(A_NONE);
-            _mdm.setDebug(-1);
-            printf("***Disabled debug mode.***\r\n");
-        } else if (joystickUp) {
-            setLevel(A_DEBUG);
-            _mdm.setDebug(3);
-            printf("***Enabled debug mode.***\r\n");
-        }
-
+        _operationSupport.run();
         _configurationSynchronization.run();
         _signalQualityMeasurement.run();
         _temperatureMeasurement.run();
+        _accelerationMeasurement.run();
         _analogMeasurement.run();
-        _accelerationMeasurement.run();
         _locationUpdate.run();
-        _operationSupport.run();
 
 //        if ((interval = _configurationProperties.readInterval()) < 0)
 //            break;
-//
 //        while (timer.read() < interval) {
 //            Thread::yield();
 //        }
--- a/MbedAgent.h	Fri Mar 20 14:27:10 2015 +0000
+++ b/MbedAgent.h	Mon Apr 13 14:24:58 2015 +0000
@@ -3,7 +3,6 @@
 
 #include <stddef.h>
 #include "MDM.h"
-#include "DeviceIO.h"
 #include "RtosSmartRest.h"
 #include "SmartRestTemplate.h"
 #include "DeviceInfo.h"
@@ -19,25 +18,21 @@
 #include "AnalogMeasurement.h"
 #include "LocationUpdate.h"
 #include "OperationSupport.h"
-
-#define MBED_AGENT_HOST "management.m2m-devicecloud.com"
-//#define MBED_AGENT_HOST "developer.cumulocity.com"
-#define MBED_AGENT_PORT 80
-#define MBED_AGENT_DEVICE_IDENTIFIER "com_cumulocity_MbedAgent_1.5.2"
+#include "LCDDisplay.h"
+#include "SmartRestConf.h"
 
 class MbedAgent
 {
 public:
-    MbedAgent(DeviceIO&, MDMSerial&, DeviceInfo&, DeviceMemory&);
-    
+    MbedAgent(GPSI2C&, MDMSerial&, LCDDisplay&, DeviceInfo&, DeviceMemory&);
+
     bool init();
-    bool run();
+    int run();
+    void loop();
 
 protected:
-    void loop();
     
 private:
-    DeviceIO& _io;
     MDMSerial& _mdm;
     DeviceInfo& _deviceInfo;
     DeviceMemory& _deviceMemory;
@@ -47,7 +42,7 @@
     SmartRestTemplate _tpl;
     DeviceBootstrap _bootstrap;
     DeviceIntegration _integration;
-    DisplayInfo _displayInfo;
+    LCDDisplay& _lcdDisplay;
     ConfigurationSynchronization _configurationSynchronization;
     SignalQualityMeasurement _signalQualityMeasurement;
     TemperatureMeasurement _temperatureMeasurement;
--- a/MbedSmartRest.lib	Fri Mar 20 14:27:10 2015 +0000
+++ b/MbedSmartRest.lib	Mon Apr 13 14:24:58 2015 +0000
@@ -1,1 +1,1 @@
-http://developer.mbed.org/users/xinlei/code/MbedSmartRest/#81dfc04ce0bb
+http://developer.mbed.org/users/xinlei/code/MbedSmartRest/#505d29d5bdfc
--- a/config/ConfigurationSynchronization.cpp	Fri Mar 20 14:27:10 2015 +0000
+++ b/config/ConfigurationSynchronization.cpp	Mon Apr 13 14:24:58 2015 +0000
@@ -58,8 +58,10 @@
 
 bool ConfigurationSynchronization::updateConfiguration(const char *cfg)
 {
-    if (!_deviceConfiguration.read(cfg))
+    if (!_deviceConfiguration.read(cfg)) {
+        aError("updateConfiguration: Unable to read device configuration!\r\n");
         return false;
+    }
     
     if (!_configurationProperties.validateProperties()) {
         loadConfiguration();
@@ -74,8 +76,10 @@
 {
     char buf[256];
     
-    if (!_deviceConfiguration.write(buf, sizeof(buf)))
+    if (!_deviceConfiguration.write(buf, sizeof(buf))) {
+        aError("updateDeviceObject: Unable to write device configuration!\r\n");
         return false;
+    }
 
     ComposedRecord record;
     ParsedRecord received;
@@ -84,29 +88,29 @@
     IntegerValue deviceId(_deviceId);
     CharValue config(buf);
     IntegerValue responsibility(_configurationProperties.readInterval());
-    if ((!record.add(msgId)) || (!record.add(deviceId)) || (!record.add(config)) || (!record.add(responsibility)))
+    if (!record.add(msgId) || !record.add(deviceId) || !record.add(config) || !record.add(responsibility)) {
+        aWarning("updateDeviceObject: Adding record failed!\r\n");
         return false;
-
+    }
+    
     if (_client.send(record) != SMARTREST_SUCCESS) {
-        aError("Sending configuration failed.\r\n");
+        aWarning("Sending configuration failed.\r\n");
         _client.stop();
         return false;
     }
-
+    
     if (_client.receive(received) != SMARTREST_SUCCESS) {
-        aError("Connection failure or invalid configuration.\r\n");
+        aWarning("Receiving configuration failed.\r\n");
         _client.stop();
         return false;
     }
     _client.stop();
 
     if (received.values() != 3) {
-        aError("Unmatching configuration data received, expected 3, but %d received.\r\n", received.values());
+        aError("Invalid configuration received, expected 3 values, but %d received.\r\n", received.values());
         return false;
-    }
-    
-    if (received.value(0).integerValue() != 201) {
-        aError("Bad configuration data received.\r\n");
+    } else if (received.value(0).integerValue() != 201) {
+        aError("updateDeviceObject: Unexpected message ID %ld received.\r\n", received.value(0).integerValue());
         return false;
     }
     return true;
@@ -116,12 +120,14 @@
 {
     char buf[256];
     
-    if (!_deviceMemory.loadConfiguration(buf, sizeof(buf)))
+    if (!_deviceMemory.loadConfiguration(buf, sizeof(buf))) {
+        aError("loadConfiguration: Unable to load device configuration!\r\n");
         return false;
-    
-    if (!_deviceConfiguration.read(buf))
+    }
+    if (!_deviceConfiguration.read(buf)) {
+        aError("loadConfiguration: Unable to read device configuration!\r\n");
         return false;
-
+    }
     return true;
 }
 
@@ -129,11 +135,13 @@
 {
     char buf[256];
     
-    if (!_deviceConfiguration.write(buf, sizeof(buf)))
+    if (!_deviceConfiguration.write(buf, sizeof(buf))) {
+        aError("saveConfiguration: Unable to write device configuration!\r\n");
         return false;
-    
-    if (!_deviceMemory.saveConfiguration(buf))
+    }
+    if (!_deviceMemory.saveConfiguration(buf)) {
+        aError("saveConfiguration: Unable to save device configuration!\r\n");
         return false;
-    
+    }
     return true;
 }
--- a/io/DeviceFeedback.cpp	Fri Mar 20 14:27:10 2015 +0000
+++ b/io/DeviceFeedback.cpp	Mon Apr 13 14:24:58 2015 +0000
@@ -1,6 +1,6 @@
-#include "DeviceFeedback.h"
 #include <stdlib.h>
 #include <string.h>
+#include "DeviceFeedback.h"
 
 #define MSG_BEEP_SUCCESS 1
 #define MSG_BEEP_FAILURE 2
@@ -8,7 +8,7 @@
 #define MSG_OPEN_RELAY 4
 
 DeviceFeedback::DeviceFeedback() :
-    _speaker(D6),
+//    _speaker(D6),
 //    _thread(DeviceFeedback::thread_func, this),
     shieldLEDRed(D5),
     shieldLEDBlue(D8),
@@ -19,15 +19,15 @@
     shieldLEDGreen = 255;
 }
 
-void DeviceFeedback::beepSuccess()
-{
-    sendMessage(MSG_BEEP_SUCCESS);
-}
-
-void DeviceFeedback::beepFailure()
-{
-    sendMessage(MSG_BEEP_FAILURE);
-}
+//void DeviceFeedback::beepSuccess()
+//{
+//    sendMessage(MSG_BEEP_SUCCESS);
+//}
+//
+//void DeviceFeedback::beepFailure()
+//{
+//    sendMessage(MSG_BEEP_FAILURE);
+//}
 
 void DeviceFeedback::closeRelay()
 {
@@ -45,42 +45,42 @@
 //    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; uint8_t *msg;
-    bool relayState = false;
+//void DeviceFeedback::sendMessage(uint8_t msg)
+//{
+//    uint8_t *msgPtr = _mail.alloc();
+//    *msgPtr = msg;
+//    _mail.put(msgPtr);
+//}
 
-    while (true) {
-        if ((evt = _mail.get(1000)).status == osEventMail) {
-            msg = (uint8_t*)evt.value.p;
-            switch (*msg) {
-            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:
-                relayState = true;
+//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);
@@ -89,9 +89,8 @@
 //                    }
 //                    _speaker = 0.0;
 //                }
-                break;
-            case MSG_OPEN_RELAY:
-                relayState = false;
+//                    break;
+//                case MSG_OPEN_RELAY:
 //                if (relayState) {
 //                    for (float i=10000.0; i>2000.0; i-=100) {
 //                        _speaker.period(1.0/i);
@@ -100,23 +99,16 @@
 //                    }
 //                    _speaker = 0.0;
 //                }
-                break;
-            }
-            _mail.free(msg);
-        }
+//                    break;
+//            }
+//        }
+//
+//    }
+//}
 
-//        if (relayState) {
-//            _speaker.period(1.0/10000);
-//            _speaker = 0.5;
-//            Thread::wait(20);
-//            _speaker = 0.0;
-//        }
-    }
-}
-
-void DeviceFeedback::thread_func(void const *arg)
-{
-    DeviceFeedback *that;
-    that = (DeviceFeedback*)arg;
-    that->thread();
-}
+//void DeviceFeedback::thread_func(void const *arg)
+//{
+//    DeviceFeedback *that;
+//    that = (DeviceFeedback*)arg;
+//    that->thread();
+//}
--- a/io/DeviceFeedback.h	Fri Mar 20 14:27:10 2015 +0000
+++ b/io/DeviceFeedback.h	Mon Apr 13 14:24:58 2015 +0000
@@ -10,18 +10,18 @@
 public:
     DeviceFeedback();
 
-    void beepSuccess();
-    void beepFailure();
+//    void beepSuccess();
+//    void beepFailure();
     void closeRelay();
     void openRelay();
     
 protected:
-    void sendMessage(uint8_t);
-    void thread();
-    static void thread_func(void const*);
+//    void sendMessage(uint8_t);
+//    void thread();
+//    static void thread_func(void const*);
 
 private:
-    PwmOut _speaker;
+//    PwmOut _speaker;
 //    Thread _thread;
     
     /* LED lights on the application shield, consists of three colors: Red, Blue, Green.
@@ -30,7 +30,7 @@
     DigitalOut shieldLEDRed;
     DigitalOut shieldLEDBlue;
     DigitalOut shieldLEDGreen;
-    Mail<uint8_t, 16> _mail;
+//    Mail<uint8_t, 16> _mail;
 };
 
 #endif
\ No newline at end of file
--- a/io/DeviceIO.cpp	Fri Mar 20 14:27:10 2015 +0000
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,49 +0,0 @@
-#include "DeviceIO.h"
-#include "logging.h"
-
-#define DEF "\033[39m"
-#define GRE "\033[32m"
-#define CYA "\033[36m"
-
-DeviceIO::DeviceIO(GPSI2C& gps) :
-    _resetButton(D4), // fire button on arduino app shield
-    _lcd(D11, D13, D12, D7, D10),
-    _gpsTracker(gps),
-    _deviceFeedback()
-{
-}
-
-bool DeviceIO::resetButtonPressed()
-{
-    return _resetButton;
-}
-
-GPSTracker& DeviceIO::gpsTracker()
-{
-    return _gpsTracker;
-}
-
-DeviceFeedback& DeviceIO::deviceFeedback()
-{
-    return _deviceFeedback;
-}
-
-void DeviceIO::lcdPrint(const char *line1, const char *line2, const char *line3)
-{
-    aDebug(GRE "io::lcdPrint" DEF "\r\n");
-    _lcd.cls();
-    _lcd.locate(0, 0);
-
-    _lcd.printf("%s\n", line1);
-    aDebug(GRE "> " CYA "%s\r\n" DEF, line1);
-
-    if (line2 != NULL) {
-        _lcd.printf("%s\n", line2);
-        aDebug(GRE "> " CYA "%s\r\n" DEF, line2);
-
-        if (line3 != NULL) {
-            _lcd.printf("%s\n", line3);
-            aDebug(GRE "> " CYA "%s\r\n" DEF, line3);
-        }
-    }
-}
--- a/io/DeviceIO.h	Fri Mar 20 14:27:10 2015 +0000
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,29 +0,0 @@
-#ifndef DEVICEIO_H
-#define DEVICEIO_H
-
-#include "mbed.h"
-#include "GPS.h"
-#include "LM75B.h"
-#include "MMA7660.h"
-#include "C12832.h"
-#include "GPSTracker.h"
-#include "DeviceFeedback.h"
-
-class DeviceIO
-{
-public:
-    DeviceIO(GPSI2C&);
-
-    bool resetButtonPressed();
-    GPSTracker& gpsTracker();
-    DeviceFeedback& deviceFeedback();
-    void lcdPrint(const char*, const char* = NULL, const char* = NULL);
-
-private:
-    DigitalIn _resetButton;
-    C12832 _lcd;
-    GPSTracker _gpsTracker;
-    DeviceFeedback _deviceFeedback;
-};
-
-#endif
\ No newline at end of file
--- a/io/GPSTracker.cpp	Fri Mar 20 14:27:10 2015 +0000
+++ b/io/GPSTracker.cpp	Mon Apr 13 14:24:58 2015 +0000
@@ -32,7 +32,7 @@
     char buf[256], chr; // needs to be that big otherwise mdm isn't working
     int ret, len, n;
     double altitude, latitude, longitude;
-    
+    aInfo("GPS thread: %p\r\n", Thread::gettid());    
     while (true) {
         ret = _gps.getMessage(buf, sizeof(buf));
         if (ret <= 0) {
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/io/LCDDisplay.cpp	Mon Apr 13 14:24:58 2015 +0000
@@ -0,0 +1,79 @@
+#include "LCDDisplay.h"
+#include "logging.h"
+
+#define DEF "\033[39m"
+#define GRE "\033[32m"
+#define CYA "\033[36m"
+
+void LCDDisplay::_setLine(char *dest, const char* src, size_t n)
+{
+        if (n == 0) {
+                return ;
+        } else if (src && src!=dest) {
+                strncpy(dest, src, n-1);
+                dest[n-1] = '\0';
+        }
+}
+
+void LCDDisplay::clear()
+{
+        _setLine(firstLine, "", sizeof(firstLine));
+        _setLine(secondLine, "", sizeof(secondLine));
+        _setLine(thirdLine, "", sizeof(thirdLine));
+        _lcd.cls();
+}
+
+void LCDDisplay::setFirstLine(const char* p)
+{
+        _setLine(firstLine, p, sizeof(firstLine));
+        lcdPrint(firstLine, secondLine, thirdLine);
+}
+
+void LCDDisplay::setSecondLine(const char* p)
+{
+        _setLine(secondLine, p, sizeof(secondLine));
+        lcdPrint(firstLine, secondLine, thirdLine);
+}
+
+void LCDDisplay::setThirdLine(const char* p)
+{
+        _setLine(thirdLine, p, sizeof(thirdLine));
+        lcdPrint(firstLine, secondLine, thirdLine);
+}
+
+void LCDDisplay::setLines(const char *p1, const char *p2, const char *p3)
+{
+        _setLine(firstLine, p1, sizeof(firstLine));
+        if (p2)
+            _setLine(secondLine, p2, sizeof(secondLine));
+        else
+            _setLine(secondLine, "", sizeof(secondLine));
+
+        if (p3)
+            _setLine(thirdLine, p3, sizeof(thirdLine));
+        else
+            _setLine(thirdLine, "", sizeof(thirdLine));
+        lcdPrint(firstLine, secondLine, thirdLine);
+}
+
+void LCDDisplay::lcdPrint(const char *l1, const char *l2, const char *l3)
+{
+    aDebug(GRE "io::lcdPrint" DEF "\r\n");
+
+    lcdLock.lock();
+    _lcd.cls();
+    _lcd.locate(0, 0);
+    _lcd.printf("%s\n", l1);
+    aDebug(GRE "> " CYA "%s\r\n" DEF, l1);
+
+    if (l2 != NULL) {
+        _lcd.printf("%s\n", l2);
+        aDebug(GRE "> " CYA "%s\r\n" DEF, l2);
+
+        if (l3 != NULL) {
+            _lcd.printf("%s\n", l3);
+            aDebug(GRE "> " CYA "%s\r\n" DEF, l3);
+        }
+    }
+    lcdLock.unlock();
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/io/LCDDisplay.h	Mon Apr 13 14:24:58 2015 +0000
@@ -0,0 +1,35 @@
+#ifndef LCDDISPLAY_H
+#define LCDDISPLAY_H
+#include <string.h>
+#include "C12832.h"
+#include "rtos.h"
+#define DISPLAY_LEN 28
+
+class LCDDisplay
+{
+public:
+        LCDDisplay(): firstLine(""), secondLine(""), thirdLine(""),
+                      _lcd(D11, D13, D12, D7, D10) {}
+        void setFirstLine(const char* p);
+        const char *getFirstLine() const { return firstLine; }
+        void setSecondLine(const char* p);
+        const char *getSecondLine() const { return secondLine; }
+        void setThirdLine(const char* p);
+        const char *getThirdLine() const { return thirdLine; }
+        void setLines(const char *p1, const char *p2=NULL, const char *p3=NULL);
+        void clear();
+        virtual ~LCDDisplay() {}
+
+protected:
+        void lcdPrint(const char*, const char* = NULL, const char* = NULL);
+        void _setLine(char *dest, const char* src, size_t n);
+
+private:
+        char firstLine[DISPLAY_LEN];
+        char secondLine[DISPLAY_LEN];
+        char thirdLine[DISPLAY_LEN];
+        C12832 _lcd;
+        Mutex lcdLock;
+};
+
+#endif /* LCDDISPLAY_H */
--- a/main.cpp	Fri Mar 20 14:27:10 2015 +0000
+++ b/main.cpp	Mon Apr 13 14:24:58 2015 +0000
@@ -22,113 +22,121 @@
 //#define SIM_APN ""
 //#define SIM_USER ""
 //#define SIM_PASS ""
+MDMRtos<MDMSerial> *pMdm = NULL;
 
-unsigned short getMNCLen(const char *imsi) {
+unsigned short getMNCLen(const char *imsi)
+{
     if (strncmp(imsi, "310", 3) != 0) // Non American ISMI
         return 2;
     else
         return 3;
 }
 
+void enableDebug()
+{
+        setLevel(A_DEBUG);
+        if (pMdm)
+            pMdm->setDebug(3);
+}
+
+void disableDebug()
+{
+       setLevel(A_NONE);
+       if (pMdm)
+           pMdm->setDebug(-1);
+}
+
 int main()
 {
+    MDMRtos<MDMSerial> mdm;
+    pMdm = &mdm;
+    InterruptIn joystickUp(A2);
+    InterruptIn joystickDown(A3);
+    LCDDisplay lcdDisplay;
     MDMParser::DevStatus devStatus;
-    uint8_t status = 0;
-
-    MDMRtos<MDMSerial> mdm;
     GPSI2C gps;
-    DeviceIO io(gps); 
-    
-    DigitalIn joystickUp(A2);
-    DigitalIn joystickDown(A3);
-    if (joystickUp) {
-        setLevel(A_DEBUG);
-        mdm.setDebug(3);
-        printf("Enable debug mode.\r\n");
-    } else {
-        setLevel(A_NONE);
-        mdm.setDebug(-1);
-    }        
-    
-    io.lcdPrint("Mbed Agent V2.1rc1", MBED_AGENT_HOST);
+    lcdDisplay.setLines("Mbed Agent V2.1rc1", getHost());
     if (!mdm.init(SIM_PIN, &devStatus)) {
-        status = 1;
-        io.lcdPrint("Modem Init Failure", "No SIM card found", "Or SIM has PIN code");
-    } else if (!gps.init()) {
-        status = 2;
-        io.lcdPrint("GPS Init Failure");
-    }
-    if (status != 0) {
+        lcdDisplay.setLines("Modem Init Failure", "No SIM card found", "Or SIM has PIN");
         mdm.disconnect();
         mdm.powerOff();
         return 1;
+    } else if (!gps.init()) {
+        lcdDisplay.setLines("GPS Init Failure");
+        mdm.disconnect();
+        mdm.powerOff();
+        return 2;
     }
-    
-    DeviceInfo deviceInfo(mdm, devStatus);
+    joystickUp.rise(&enableDebug);
+    joystickDown.rise(&disableDebug);
+
     DeviceMemory deviceMemory(mdm);
+    DigitalIn fireButton(D4);
 
-    if (io.resetButtonPressed()) {
-        io.lcdPrint("Factory Reset");
+    if (fireButton) {
+        lcdDisplay.setLines("Factory Reset");
         if (deviceMemory.resetPlatformCredentials()) {
-//            io.deviceFeedback().beepSuccess();
-            io.lcdPrint("Reset Success");
+            lcdDisplay.setLines("Reset Success");
+        } else {
+            lcdDisplay.setLines("Reset Failure");
         }
-        else {
-//            io.deviceFeedback().beepFailure();
-            io.lcdPrint("Reset Failure");
-        }
+        mdm.disconnect();
+        mdm.powerOff();
         Thread::wait(1000);
         return 0;
     }
-
-    io.lcdPrint("Register Network...", "IMEI", devStatus.imei);
+    aInfo("Main Thread: %p\r\n", Thread::gettid());    
+    lcdDisplay.setLines("Register Network...", "IMEI", devStatus.imei);
     if (!mdm.registerNet()) {
-        io.lcdPrint("No Network Coverage");
-        goto error;
+        lcdDisplay.setLines("No Network Coverage");
+        mdm.disconnect();
+        mdm.powerOff();
+        return 3;
     }
 
-    io.lcdPrint("Join Network");
+    lcdDisplay.setLines("Join Network");
 #ifdef SIM_APN
     if (mdm.join(SIM_APN, SIM_USER, SIM_PASS) == NOIP) {
 #else
     if (mdm.join() == NOIP) {
 #endif
-        char s[8] = "unknown";
+        char s[8] = "Unknown";
         const char *p = devStatus.imsi;
         if (p) {
             snprintf(s, sizeof(s), "%.*s-%.*s", 3, p, getMNCLen(p), p+3);
         }
-        io.lcdPrint("Wrong APN settting", "MCC-MNC:", s);
-        goto error;
+        lcdDisplay.setLines("Wrong APN Settting", "MCC-MNC:", s);
+        mdm.disconnect();
+        mdm.powerOff();
+        return 4;
     }
-    
+
     {
-        MbedAgent agent(io, mdm, deviceInfo, deviceMemory);
-    
-        io.lcdPrint("Agent Init");
+        DeviceInfo deviceInfo(mdm, devStatus);
+        MbedAgent agent(gps, mdm, lcdDisplay, deviceInfo, deviceMemory);
+
+        lcdDisplay.setLines("Agent Init");
         if (!agent.init()) {
-            io.lcdPrint("Agent Init Failure", "Debug via serial port");
-            goto error;
+            mdm.disconnect();
+            mdm.powerOff();
+            return 5;
         }
-        uint8_t tries = 3;
-        do {
-            io.lcdPrint("Agent Run");
-            if (agent.run())
+        lcdDisplay.setLines("Agent Run");
+        int ret = 0;
+        for (uint8_t tries = 3; tries; --tries) {
+            ret = agent.run();
+            if (ret == 0)
                 break;
-        } while (--tries > 0);
+        }
 
-        if (tries == 0) {
-            io.lcdPrint("Integration/Config Failure");
-            goto error;
+        switch (ret) {
+            case -1: lcdDisplay.setLines("Bootstrap error"); break;
+            case -2: lcdDisplay.setLines("Integrate failure"); break;
+            case -3: lcdDisplay.setLines("Config sync failure"); break;
+            default: agent.loop();
         }
+        mdm.disconnect();
+        mdm.powerOff();
+        return ret;
     }
-    
-    mdm.disconnect();
-    mdm.powerOff();
-    return 0;
-
-error:
-    mdm.disconnect();
-    mdm.powerOff();
-    return 1;
 }
--- a/mbed.bld	Fri Mar 20 14:27:10 2015 +0000
+++ b/mbed.bld	Mon Apr 13 14:24:58 2015 +0000
@@ -1,1 +1,1 @@
-http://mbed.org/users/mbed_official/code/mbed/builds/7e07b6fb45cf
\ No newline at end of file
+http://mbed.org/users/mbed_official/code/mbed/builds/487b796308b0
\ No newline at end of file
--- a/measurement/AccelerationMeasurement.cpp	Fri Mar 20 14:27:10 2015 +0000
+++ b/measurement/AccelerationMeasurement.cpp	Mon Apr 13 14:24:58 2015 +0000
@@ -10,15 +10,14 @@
 // Time interval for forcing a sending even if acceleration sensor readings are constantly similar (in seconds).
 #define TIME_LIMIT_ACCE 900          
 
-AccelerationMeasurement::AccelerationMeasurement(AbstractSmartRest& client, SmartRestTemplate& tpl, long& deviceId, 
-    DeviceIO& io, DeviceInfo& deviceInfo, DisplayInfo& displayInfo) :
+AccelerationMeasurement::AccelerationMeasurement(AbstractSmartRest& client, SmartRestTemplate& tpl, 
+    long& deviceId, DeviceInfo& deviceInfo, LCDDisplay& lcdDisplay) :
     _deviceId(deviceId),
     _tpl(tpl),
     _client(client),
     _sensor(SDA,SCL),
-    _io(io),
     _deviceInfo(deviceInfo),
-    _displayInfo(displayInfo)
+    _lcdDisplay(lcdDisplay)
 {
     _init = false;
     oldValues[0] = 0;
@@ -44,7 +43,6 @@
 
 bool AccelerationMeasurement::run()
 {
-    extern bool lastSensorReadingSent;
     if (!_test)
         return false;
     
@@ -58,20 +56,18 @@
         ((0.1> abs(data[1])) || (abs(oldValues[1]-data[1]) <= abs(oldValues[1])*THRESHOLD_PERCENT_ACCE))) {
         if (sendingTimer.read() < TIME_LIMIT_ACCE) {
 //            printf("[N] Acc %f, %f, %f\r\n", data[0], data[1], data[2]);
-            if (lastSensorReadingSent) {
-                _io.lcdPrint(_displayInfo.getFirstLine(), _displayInfo.getSecondLine());
-                lastSensorReadingSent=false;
+            if (strcmp(_lcdDisplay.getThirdLine(), "")) {
+                _lcdDisplay.setThirdLine("");
             }
-            aDebug("Similar acceleration readings found, no sending!\r\n");
             return true;
         } else {
-            aDebug("Acceleration sensor timed out at %f s, a sending is forced.\r\n", sendingTimer.read());
+            aDebug("Acc: Timeout at %f s.\n", sendingTimer.read());
         }
     }
 //    printf("[Y] Acc %f, %f, %f\r\n", data[0], data[1], data[2]);
     char status[27] = {0};
-    snprintf(status, 27, "Sending Acc %.1f,%.1f,%.1f", data[0], data[1], data[2]);
-    _io.lcdPrint(_displayInfo.getFirstLine(), _displayInfo.getSecondLine(), status);
+    snprintf(status, 27, "Send Acc %.1f,%.1f,%.1f", data[0], data[1], data[2]);
+    _lcdDisplay.setThirdLine(status);
 
     ComposedRecord record;
     IntegerValue msgId(106);
@@ -84,17 +80,16 @@
 
     float t_start = sendingTimer.read();
     if (_client.send(record) != SMARTREST_SUCCESS) {
-        aWarning("Sending acceleration readings failed.");
+        aWarning("Acc: Send failed.\n");
         _client.stop();
         return false;
     }
     float t_end = sendingTimer.read();
     _client.stop();
-    aInfo("Acceleration readings sent in %.1f.\r\n", t_end-t_start);
+    aDebug("Acc: Sent in %.1f.\n", t_end-t_start);
     oldValues[0] = data[0];
     oldValues[1] = data[1];
     oldValues[2] = data[2];
     sendingTimer.reset();
-    lastSensorReadingSent=true;
     return true;
 }
--- a/measurement/AccelerationMeasurement.h	Fri Mar 20 14:27:10 2015 +0000
+++ b/measurement/AccelerationMeasurement.h	Mon Apr 13 14:24:58 2015 +0000
@@ -4,14 +4,13 @@
 #include "AbstractSmartRest.h"
 #include "SmartRestTemplate.h"
 #include "MMA7660.h"
-#include "DeviceIO.h"
 #include "DeviceInfo.h"
-#include "DisplayInfo.h"
+#include "LCDDisplay.h"
 
 class AccelerationMeasurement
 {
 public:
-    AccelerationMeasurement(AbstractSmartRest&, SmartRestTemplate&, long&, DeviceIO&, DeviceInfo&, DisplayInfo&);
+    AccelerationMeasurement(AbstractSmartRest&, SmartRestTemplate&, long&, DeviceInfo&, LCDDisplay&);
     
     bool init();
     bool run();
@@ -24,9 +23,8 @@
     MMA7660 _sensor;
     float oldValues[3];
     Timer sendingTimer;
-    DeviceIO& _io;
     DeviceInfo& _deviceInfo;
-    DisplayInfo& _displayInfo;
+    LCDDisplay& _lcdDisplay;
 };
 
 #endif
\ No newline at end of file
--- a/measurement/AnalogMeasurement.cpp	Fri Mar 20 14:27:10 2015 +0000
+++ b/measurement/AnalogMeasurement.cpp	Mon Apr 13 14:24:58 2015 +0000
@@ -15,15 +15,13 @@
 AnalogMeasurement::AnalogMeasurement(AbstractSmartRest& client,
                                      SmartRestTemplate& tpl,
                                      long& deviceId,
-                                     DeviceIO& io,
                                      DeviceInfo& deviceInfo,
-                                     DisplayInfo& displayInfo) :
+                                     LCDDisplay& lcdDisplay) :
     _deviceId(deviceId),
     _tpl(tpl),
     _client(client),
-    _io(io),
     _deviceInfo(deviceInfo),
-    _displayInfo(displayInfo)
+    _lcdDisplay(lcdDisplay)
 {
     _init = false;
     oldValues[0] = 0;
@@ -47,28 +45,25 @@
 
 bool AnalogMeasurement::run()
 {
-    extern bool lastSensorReadingSent;
     float data[2] = {(float)_analog1*100, (float)_analog2*100};
 
     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) {
-            if (lastSensorReadingSent) {
-                _io.lcdPrint(_displayInfo.getFirstLine(), _displayInfo.getSecondLine());
-                lastSensorReadingSent=false;
+            if (strcmp(_lcdDisplay.getThirdLine(), "")) {
+                _lcdDisplay.setThirdLine("");
             }
-            aDebug("Similar analog readings found, no sending!\r\n");
 //            printf("[N] %f, %f\r\n", data[0], data[1]);
             return true;
         } else {
-            aDebug("Analog sensor timed out at %f s, a sending is forced.\r\n", sendingTimer.read());
+            aDebug("Poti: Timeout at %f s.\n", sendingTimer.read());
         }
     }
 
 //    printf("[Y] %f, %f (%f, %f)\r\n", data[0], data[1], oldValues[0], oldValues[1]);
-    char status[25] = {0};
-    snprintf(status, 25, "Sending Poti %.1f,%.1f", data[0], data[1]);
-    _io.lcdPrint(_displayInfo.getFirstLine(), _displayInfo.getSecondLine(), status);
+    char status[27] = {0};
+    snprintf(status, sizeof(status), "Send Poti %.1f,%.1f", data[0], data[1]);
+    _lcdDisplay.setThirdLine(status);
     ComposedRecord record;
     IntegerValue msgId(107);
     IntegerValue devId(_deviceId);
@@ -79,16 +74,15 @@
 
     float t_start = sendingTimer.read();
     if (_client.send(record) != SMARTREST_SUCCESS) {
-        aWarning("Sending analog readings failed.");
+        aWarning("Poti: Send failed.\n");
         _client.stop();
         return false;
     }
     float t_end = sendingTimer.read();
     _client.stop();
-    aInfo("Analog readings sent in %.1f.\r\n", t_end-t_start);
+    aDebug("Poti: Sent in %.1f.\n", t_end-t_start);
     oldValues[0] = data[0];
     oldValues[1] = data[1];
     sendingTimer.reset();
-    lastSensorReadingSent=true;
     return true;
 }
--- a/measurement/AnalogMeasurement.h	Fri Mar 20 14:27:10 2015 +0000
+++ b/measurement/AnalogMeasurement.h	Mon Apr 13 14:24:58 2015 +0000
@@ -4,14 +4,13 @@
 #include "SmartRest.h"
 #include "SmartRestTemplate.h"
 #include "mbed.h"
-#include "DeviceIO.h"
 #include "DeviceInfo.h"
-#include "DisplayInfo.h"
+#include "LCDDisplay.h"
 
 class AnalogMeasurement
 {
 public:
-    AnalogMeasurement(AbstractSmartRest&, SmartRestTemplate&, long&, DeviceIO&, DeviceInfo&, DisplayInfo&);
+    AnalogMeasurement(AbstractSmartRest&, SmartRestTemplate&, long&, DeviceInfo&, LCDDisplay&);
     
     bool init();
     bool run();
@@ -23,9 +22,8 @@
     AbstractSmartRest& _client;
     float oldValues[2];
     Timer sendingTimer;
-    DeviceIO& _io;
     DeviceInfo& _deviceInfo;
-    DisplayInfo& _displayInfo;
+    LCDDisplay& _lcdDisplay;
 };
 
 #endif
\ No newline at end of file
--- a/measurement/LocationUpdate.cpp	Fri Mar 20 14:27:10 2015 +0000
+++ b/measurement/LocationUpdate.cpp	Mon Apr 13 14:24:58 2015 +0000
@@ -10,15 +10,14 @@
 // Time interval for forcing a sending even if analog sensor readings are constantly similar (in seconds).
 #define TIME_LIMIT_LOC 900               
 
-LocationUpdate::LocationUpdate(AbstractSmartRest& client, SmartRestTemplate& tpl, long& deviceId, GPSTracker& gpsTracker, 
-    DeviceIO& io, DeviceInfo& deviceInfo, DisplayInfo& displayInfo) :
+LocationUpdate::LocationUpdate(AbstractSmartRest& client, SmartRestTemplate& tpl,
+    long& deviceId, GPSI2C& gps, DeviceInfo& deviceInfo, LCDDisplay& lcdDisplay) :
     _deviceId(deviceId),
     _tpl(tpl),
     _client(client),
-    _gpsTracker(gpsTracker),
-    _io(io),
+    _gpsTracker(gps),
     _deviceInfo(deviceInfo),
-    _displayInfo(displayInfo)
+    _lcdDisplay(lcdDisplay)
 {
     _init = false;
     oldValues[0] = 0;
@@ -48,10 +47,8 @@
 
 bool LocationUpdate::run()
 {
-    extern bool lastSensorReadingSent;
     GPSTracker::Position position;    
     if (!_gpsTracker.position(&position)) {
-        aError("No GPS data available.\r\n");
         return false;
     }
     float data[3] = { position.altitude, position.latitude, position.longitude };
@@ -60,19 +57,17 @@
         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) {
-            if (lastSensorReadingSent) {
-                _io.lcdPrint(_displayInfo.getFirstLine(), _displayInfo.getSecondLine());
-                lastSensorReadingSent=false;
+            if (strcmp(_lcdDisplay.getThirdLine(), "")) {
+                _lcdDisplay.setThirdLine("");
             }
-            aDebug("Similar location readings found, no sending!\r\n");
             return true;
         } else {
-            aDebug("Location sensor timed out at %f s, a sending is forced.\r\n", sendingTimer.read());
+            aDebug("GPS: Timeout at %f s.\n", sendingTimer.read());
         }
     }
     char status[27] = {0};
-    snprintf(status, 27, "Sending GPS %.1f,%.1f,%.1f", data[0], data[1], data[2]);
-    _io.lcdPrint(_displayInfo.getFirstLine(), _displayInfo.getSecondLine(), status);
+    snprintf(status, 27, "Send GPS %.1f,%.1f,%.1f", data[0], data[1], data[2]);
+    _lcdDisplay.setThirdLine(status);
         
     Aggregator aggregator;
     ComposedRecord record1, record2;
@@ -91,17 +86,16 @@
 
     float t_start = sendingTimer.read();
     if (_client.send(aggregator) != SMARTREST_SUCCESS) {
-        aWarning("Sending GPS readings failed.\r\n");
+        aWarning("GPS: Send failed.\n");
         _client.stop();
         return false;
     }
     float t_end = sendingTimer.read();
     _client.stop();
-    aInfo("GPS readings sent in %.1f.\r\n", t_end-t_start);
+    aDebug("GPS: Sent in %.1f.\n", t_end-t_start);
     oldValues[0] = data[0];
     oldValues[1] = data[1];
     oldValues[2] = data[2];
     sendingTimer.reset();
-    lastSensorReadingSent=true;
     return true;
 }
--- a/measurement/LocationUpdate.h	Fri Mar 20 14:27:10 2015 +0000
+++ b/measurement/LocationUpdate.h	Mon Apr 13 14:24:58 2015 +0000
@@ -4,14 +4,13 @@
 #include "AbstractSmartRest.h"
 #include "SmartRestTemplate.h"
 #include "GPSTracker.h"
-#include "DeviceIO.h"
 #include "DeviceInfo.h"
-#include "DisplayInfo.h"
+#include "LCDDisplay.h"
 
 class LocationUpdate
 {
 public:
-    LocationUpdate(AbstractSmartRest&, SmartRestTemplate&, long&, GPSTracker&, DeviceIO&, DeviceInfo&, DisplayInfo&);
+    LocationUpdate(AbstractSmartRest&, SmartRestTemplate&, long&, GPSI2C&, DeviceInfo&, LCDDisplay&);
     
     bool init();
     bool run();
@@ -21,12 +20,11 @@
     long& _deviceId;
     SmartRestTemplate& _tpl;
     AbstractSmartRest& _client;
-    GPSTracker& _gpsTracker;
+    GPSTracker _gpsTracker;
     float oldValues[3];
     Timer sendingTimer;
-    DeviceIO& _io;
     DeviceInfo& _deviceInfo;
-    DisplayInfo& _displayInfo;
+    LCDDisplay& _lcdDisplay;
 };
 
 #endif
\ No newline at end of file
--- a/measurement/SignalQualityMeasurement.cpp	Fri Mar 20 14:27:10 2015 +0000
+++ b/measurement/SignalQualityMeasurement.cpp	Mon Apr 13 14:24:58 2015 +0000
@@ -9,14 +9,14 @@
 // Time interval for forcing a sending even if analog sensor readings are constantly similar (in seconds).
 #define TIME_LIMIT_SIG 900               
 
-SignalQualityMeasurement::SignalQualityMeasurement(AbstractSmartRest& client, SmartRestTemplate& tpl, long& deviceId, 
-    DeviceInfo& deviceInfo, DeviceIO& io, DisplayInfo& displayInfo) :
+SignalQualityMeasurement::SignalQualityMeasurement(AbstractSmartRest& client, 
+    SmartRestTemplate& tpl, long& deviceId, DeviceInfo& deviceInfo,
+    LCDDisplay& lcdDisplay) :
     _deviceId(deviceId),
     _tpl(tpl),
     _client(client),
     _deviceInfo(deviceInfo),
-    _io(io),
-    _displayInfo(displayInfo)
+    _lcdDisplay(lcdDisplay)
 {
     _init = false;
     oldValues[0] = 0;
@@ -40,35 +40,34 @@
 
 bool SignalQualityMeasurement::run()
 {
-    extern bool lastSensorReadingSent;
     static char signal[25] = {0};
-    DeviceInfo::SignalQuality *signalQuality;   
+    DeviceInfo::SignalQuality *signalQuality;
     if ((signalQuality = _deviceInfo.signalQuality()) == NULL)
         return false;
     if (signalQuality && signalQuality->rssi)
         snprintf(signal, sizeof(signal), "Network: %d dBm", signalQuality->rssi);
     else
         strncpy(signal, "Network: no coverage", sizeof(signal));
-    _displayInfo.setSecondLine(signal);
+    if (strcmp(_lcdDisplay.getSecondLine(), signal)) {
+        _lcdDisplay.setSecondLine(signal);
+    }
 
     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) {
-            if (lastSensorReadingSent) {
-                _io.lcdPrint(_displayInfo.getFirstLine(), _displayInfo.getSecondLine());
-                lastSensorReadingSent=false;
+            if (strcmp(_lcdDisplay.getThirdLine(), "")) {
+                _lcdDisplay.setThirdLine("");
             }
-            aDebug("Similar signal readings found, no sending!\r\n");
             return true;
         } else {
-            aDebug("Signal sensor timed out at %f s, a sending is forced.\r\n", sendingTimer.read());
+            aDebug("Signal: Timeout at %f s.\n", sendingTimer.read());
         }
     }
 
     char status[25] = {0};
-    snprintf(status, 25, "Sending dBm %d,%d", data[0], data[1]);
-    _io.lcdPrint(_displayInfo.getFirstLine(), _displayInfo.getSecondLine(), status);
+    snprintf(status, 25, "Send dBm %d,%d", data[0], data[1]);
+    _lcdDisplay.setThirdLine(status);
     ComposedRecord record;
     IntegerValue msgId(104);
     IntegerValue devId(_deviceId);
@@ -79,16 +78,15 @@
 
     float t_start = sendingTimer.read();
     if (_client.send(record) != SMARTREST_SUCCESS) {
-        aWarning("Sending signal readings failed.\r\n");
+        aWarning("Signal: Send failed.\n");
         _client.stop();
         return false;
     }
     float t_end = sendingTimer.read();    
     _client.stop();
-    aInfo("Signal readings sent in %.1f.\r\n", t_end-t_start);
+    aDebug("Signal: Sent in %.1f.\n", t_end-t_start);
     oldValues[0] = data[0];
     oldValues[1] = data[1];
     sendingTimer.reset();
-    lastSensorReadingSent=true;
     return true;
 }
--- a/measurement/SignalQualityMeasurement.h	Fri Mar 20 14:27:10 2015 +0000
+++ b/measurement/SignalQualityMeasurement.h	Mon Apr 13 14:24:58 2015 +0000
@@ -4,13 +4,12 @@
 #include "AbstractSmartRest.h"
 #include "SmartRestTemplate.h"
 #include "DeviceInfo.h"
-#include "DeviceIO.h"
-#include "DisplayInfo.h"
+#include "LCDDisplay.h"
 
 class SignalQualityMeasurement
 {
 public:
-    SignalQualityMeasurement(AbstractSmartRest&, SmartRestTemplate&, long&, DeviceInfo&, DeviceIO&, DisplayInfo&);
+    SignalQualityMeasurement(AbstractSmartRest&, SmartRestTemplate&, long&, DeviceInfo&, LCDDisplay&);
     
     bool init();
     bool run();
@@ -23,8 +22,7 @@
     DeviceInfo& _deviceInfo;
     int oldValues[2];
     Timer sendingTimer;
-    DeviceIO& _io;
-    DisplayInfo& _displayInfo;
+    LCDDisplay& _lcdDisplay;
 };
 
 #endif
\ No newline at end of file
--- a/measurement/TemperatureMeasurement.cpp	Fri Mar 20 14:27:10 2015 +0000
+++ b/measurement/TemperatureMeasurement.cpp	Mon Apr 13 14:24:58 2015 +0000
@@ -10,15 +10,14 @@
 #define TIME_LIMIT_TEMP 900               
 
 TemperatureMeasurement::TemperatureMeasurement(AbstractSmartRest& client, SmartRestTemplate& tpl,
-    long& deviceId, DeviceIO& io, DeviceInfo& deviceInfo, DisplayInfo& displayInfo) :
+    long& deviceId, DeviceInfo& deviceInfo, LCDDisplay& lcdDisplay) :
     _deviceId(deviceId),
     _tpl(tpl),
     _client(client),
     _sensor(D14,D15),
     oldValue(0),
-    _io(io),
     _deviceInfo(deviceInfo),
-    _displayInfo(displayInfo)
+    _lcdDisplay(lcdDisplay)
 {
     _init = false;
     sendingTimer.start();
@@ -44,25 +43,22 @@
     if (!_open)
         return false;
 
-    extern bool lastSensorReadingSent;
     float data = _sensor.temp();
 
     if (abs(oldValue-data) <= abs(oldValue)*THRESHOLD_PERCENT_TEMP) {
         if (sendingTimer.read() < TIME_LIMIT_TEMP) {
-            if (lastSensorReadingSent) {
-                _io.lcdPrint(_displayInfo.getFirstLine(), _displayInfo.getSecondLine());
-                lastSensorReadingSent=false;
+            if (strcmp(_lcdDisplay.getThirdLine(), "")) {
+                _lcdDisplay.setThirdLine("");
             }
-            aDebug("Similar temperature readings found, no sending!\r\n");
             return true;
         } else {
-            aDebug("Temperature sensor timed out at %f s, a sending is forced.\r\n", sendingTimer.read());
+            aDebug("Temp: Timeout at %f s.\n", sendingTimer.read());
         } 
     }
 
     char status[25] = {0};
-    snprintf(status, 25, "Sending Temp %.2f", data);
-    _io.lcdPrint(_displayInfo.getFirstLine(), _displayInfo.getSecondLine(), status);
+    snprintf(status, 25, "Send Temp %.2f", data);
+    _lcdDisplay.setThirdLine(status);
     ComposedRecord record;
     IntegerValue msgId(105);
     IntegerValue devId(_deviceId);
@@ -72,15 +68,14 @@
 
     float t_start = sendingTimer.read();
     if (_client.send(record) != SMARTREST_SUCCESS) {
-        aWarning("Sending temperature readings failed.\r\n");
+        aWarning("Temp: Send failed.\n");
         _client.stop();
         return false;
     }
     float t_end = sendingTimer.read();
     _client.stop();
-    aInfo("Temperature readings sent in %.1f.\r\n", t_end-t_start);
+    aDebug("Temp: Sent in %.1f.\n", t_end-t_start);
     oldValue = data;
     sendingTimer.reset();
-    lastSensorReadingSent=true;
     return true;
 }
--- a/measurement/TemperatureMeasurement.h	Fri Mar 20 14:27:10 2015 +0000
+++ b/measurement/TemperatureMeasurement.h	Mon Apr 13 14:24:58 2015 +0000
@@ -4,14 +4,13 @@
 #include "AbstractSmartRest.h"
 #include "SmartRestTemplate.h"
 #include "LM75B.h"
-#include "DeviceIO.h"
 #include "DeviceInfo.h"
-#include "DisplayInfo.h"
+#include "LCDDisplay.h"
 
 class TemperatureMeasurement
 {
 public:
-    TemperatureMeasurement(AbstractSmartRest&, SmartRestTemplate&, long&, DeviceIO&, DeviceInfo&, DisplayInfo&);
+    TemperatureMeasurement(AbstractSmartRest&, SmartRestTemplate&, long&, DeviceInfo&, LCDDisplay&);
 
     bool init();
     bool run();
@@ -24,9 +23,8 @@
     LM75B _sensor;
     float oldValue;
     Timer sendingTimer;
-    DeviceIO& _io;
     DeviceInfo& _deviceInfo;
-    DisplayInfo& _displayInfo;
+    LCDDisplay& _lcdDisplay;
 };
 
 #endif
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/operation/Operation.h	Mon Apr 13 14:24:58 2015 +0000
@@ -0,0 +1,12 @@
+#ifndef OPERATIONSTORE_H
+#define OPERATIONSTORE_H
+
+enum OperationState { OPERATION_PENDING, OPERATION_EXECUTING, OPERATION_SUCCESSFUL, OPERATION_FAILED };
+
+struct Operation {
+    Operation() : identifier(0), state(OPERATION_PENDING) {}
+    long identifier;
+    OperationState state;
+};
+
+#endif
--- a/operation/OperationExecutor.cpp	Fri Mar 20 14:27:10 2015 +0000
+++ b/operation/OperationExecutor.cpp	Mon Apr 13 14:24:58 2015 +0000
@@ -1,5 +1,4 @@
 #include <string.h>
-#include <stdio.h>
 #include "OperationExecutor.h"
 #include "ComposedRecord.h"
 #include "CharValue.h"
@@ -10,16 +9,16 @@
 #define FOUND_MESSAGE 2
 #define FOUND_CONFIGURATION 3
 
-OperationExecutor::OperationExecutor(AbstractSmartRest& client, SmartRestTemplate& tpl, long& deviceId, 
-                                     ConfigurationSynchronization& configurationSynchronization, DeviceIO& io,
-                                     DisplayInfo& displayInfo) :
+OperationExecutor::OperationExecutor(AbstractSmartRest& client, SmartRestTemplate& tpl,
+    long& deviceId, ConfigurationSynchronization& configurationSynchronization, 
+    LCDDisplay& lcdDisplay) :
     _init(false),
     _deviceId(deviceId),
     _tpl(tpl),
     _client(client),
     _configurationSynchronization(configurationSynchronization),
-    _io(io),
-    _displayInfo(displayInfo)
+    _deviceFeedback(),
+    _lcdDisplay(lcdDisplay)
 {
 }
 
@@ -52,95 +51,47 @@
     return true;
 }
 
-bool OperationExecutor::executeOperation(OperationStore::Operation& op)
+bool OperationExecutor::executeOperation(ParsedRecord& received)
 {
-    ComposedRecord record;
-    ParsedRecord received;
-    
-    IntegerValue msgId(112);
-    IntegerValue operationId(op.identifier);
-    if ((!record.add(msgId)) || (!record.add(operationId)))
-        return false;
-    
-    if (_client.send(record) != SMARTREST_SUCCESS) {
-        _client.stop();
-        return false;
-    }
-    
     uint8_t found = 0;
-    bool relayState;
-    char message[256];
-    while (_client.receive(received) == SMARTREST_SUCCESS) {
-        if ((received.values() == 4) &&
-            (received.value(0).valueType() == VALUE_INTEGER) &&
-            (received.value(0).integerValue() == 220) &&
-            (received.value(2).valueType() == VALUE_INTEGER) &&
-            (received.value(2).integerValue() == op.identifier) &&
-            (received.value(3).valueType() == VALUE_CHARACTER)) {
-            relayState = strcmp("CLOSED", received.value(3).characterValue()) == 0;
-            found = FOUND_RELAY;
-            break;
-        }       
-        if ((received.values() == 4) &&
-            (received.value(0).valueType() == VALUE_INTEGER) &&
-            (received.value(0).integerValue() == 221) &&
-            (received.value(2).valueType() == VALUE_INTEGER) &&
-            (received.value(2).integerValue() == op.identifier) &&
-            (received.value(3).valueType() == VALUE_CHARACTER)) {
-            strncpy(message, received.value(3).characterValue(), 128);
-            message[127] = '\0';
-            found = FOUND_MESSAGE;
-            break;
-        }
-        if ((received.values() == 4) &&
-            (received.value(0).valueType() == VALUE_INTEGER) &&
-            (received.value(0).integerValue() == 222) &&
-            (received.value(2).valueType() == VALUE_INTEGER) &&
-            (received.value(2).integerValue() == op.identifier) &&
-            (received.value(3).valueType() == VALUE_CHARACTER)) {
-            strncpy(message, received.value(3).characterValue(), 256);
-            message[255] = '\0';
-            found = FOUND_CONFIGURATION;
-            break;
-        }
+    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;
     }
-    _client.stop();
 
     switch (found) {
     case FOUND_RELAY:         return executeRelayStateUpdate(relayState);
     case FOUND_MESSAGE:       return executeMessageDisplay(message);
     case FOUND_CONFIGURATION: return executeUpdateConfiguration(message);
-    default:
-        aWarning("Unsupported configuration received.\r\n");
-        if (getLevel() == A_DEBUG) {
-            aDebug("Configuration received: \r\n");
-            for (size_t q = 0; q < received.values(); q++)
-                aDebug("\t%s", received.rawValue(q));
-        }
-        return false;
+    default:                  return false;
     }
 }
 
 bool OperationExecutor::executeRelayStateUpdate(bool relayState)
 {
     if (relayState)
-        _io.deviceFeedback().closeRelay();
+        _deviceFeedback.closeRelay();
     else
-        _io.deviceFeedback().openRelay();
+        _deviceFeedback.openRelay();
     return true;
 }
 
 bool OperationExecutor::executeMessageDisplay(const char *message)
 {
-//    char msg[78];   // Length of text that the LCD display can hold
-//    strncpy(msg, message, sizeof(msg));
-//    _io.lcdPrint(msg);
-    extern bool lastSensorReadingSent;
-    _displayInfo.setFirstLine(message);
-    puts("setted first line");
-    _io.lcdPrint(message);
-    puts("printed io message");
-    lastSensorReadingSent=true;
+    _lcdDisplay.setFirstLine(message);
     return true;
 }
 
--- a/operation/OperationExecutor.h	Fri Mar 20 14:27:10 2015 +0000
+++ b/operation/OperationExecutor.h	Mon Apr 13 14:24:58 2015 +0000
@@ -3,18 +3,18 @@
 
 #include "AbstractSmartRest.h"
 #include "SmartRestTemplate.h"
-#include "OperationStore.h"
-#include "DeviceIO.h"
+#include "Operation.h"
 #include "ConfigurationSynchronization.h"
-#include "DisplayInfo.h"
+#include "DeviceFeedback.h"
+#include "LCDDisplay.h"
 
 class OperationExecutor
 {
 public:
-    OperationExecutor(AbstractSmartRest&, SmartRestTemplate&, long&, ConfigurationSynchronization&, DeviceIO&, DisplayInfo&);
+    OperationExecutor(AbstractSmartRest&, SmartRestTemplate&, long&, ConfigurationSynchronization&, LCDDisplay&);
     
     bool init();
-    bool executeOperation(OperationStore::Operation&);
+    bool executeOperation(ParsedRecord&);
     
 protected:
     bool executeRelayStateUpdate(bool relayState);
@@ -27,8 +27,8 @@
     SmartRestTemplate& _tpl;
     AbstractSmartRest& _client;
     ConfigurationSynchronization& _configurationSynchronization;
-    DeviceIO& _io;
-    DisplayInfo& _displayInfo;
+    DeviceFeedback _deviceFeedback;
+    LCDDisplay& _lcdDisplay;
 };
 
 #endif
\ No newline at end of file
--- a/operation/OperationStore.cpp	Fri Mar 20 14:27:10 2015 +0000
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,156 +0,0 @@
-#include "OperationStore.h"
-#include <stdlib.h>
-#include <string.h>
-
-/*#define OPERATION_PENDING    0
-#define OPERATION_EXECUTING  1
-#define OPERATION_SUCCESS    2
-#define OPERATION_FAILURE    3
-#define OPERATION_STORE_SIZE 128*/
-
-OperationStore::OperationStore() :
-    _count(0),
-    _offset(0)
-{
-}
-
-bool OperationStore::enqueue(Operation& operation)
-{
-    _mutex.lock();
-    if ((full()) || (getByIdentifier(operation.identifier) != NULL) ||
-            (operation.state != OPERATION_PENDING)) {
-        _mutex.unlock();
-        return false;
-    }
-    
-    memcpy(get(_count++), &operation, sizeof(OperationStore::Operation));
-    _mutex.unlock();
-    return true;
-}
-
-bool OperationStore::takePending(Operation& operation)
-{
-    size_t n;
-    Operation *tmp;
-
-    _mutex.lock();
-    for (n = 0; n < _count; n++) {
-        tmp = get(n);
-        if (tmp->state != OPERATION_PENDING)
-            continue;
-        
-        tmp->state = OPERATION_EXECUTING;
-        memcpy(&operation, tmp, sizeof(OperationStore::Operation));
-
-        _mutex.unlock();
-        return true;
-    }
-
-    _mutex.unlock();    
-    return false;
-}
-
-bool OperationStore::hasPending()
-{
-    size_t n;
-    Operation *tmp;
-
-    _mutex.lock();
-    for (n = 0; n < _count; n++) {
-        tmp = get(n);
-        if (tmp->state != OPERATION_PENDING)
-            continue;
-        
-        _mutex.unlock();
-        return true;
-    }
-
-    _mutex.unlock();    
-    return false;
-}
-    
-bool OperationStore::markAsDone(Operation& operation, bool successful)
-{
-    Operation *tmp;
-
-    _mutex.lock();    
-    tmp = getByIdentifier(operation.identifier);
-    if ((tmp == NULL) || (tmp->state != OPERATION_EXECUTING)) {
-        _mutex.unlock();
-        return false;
-    }
-    
-    tmp->state = (successful) ? OPERATION_SUCCESSFUL : OPERATION_FAILED;
-    _mutex.unlock();
-    return true;
-}
-    
-bool OperationStore::takeDone(Operation& operation)
-{
-    Operation *tmp;
-    
-    _mutex.lock();
-    tmp = get(0);
-    if ((tmp == NULL) || ((tmp->state != OPERATION_SUCCESSFUL) &&
-            (tmp->state != OPERATION_FAILED))) {
-        _mutex.unlock();
-        return false;
-    }
-    
-    if (++_offset == OPERATION_STORE_SIZE)
-        _offset = 0;
-    _count--;
-    
-    memcpy(&operation, tmp, sizeof(OperationStore::Operation));
-
-    _mutex.unlock();
-    return true;
-}
-    
-bool OperationStore::full()
-{
-    bool ret;
-    
-    _mutex.lock();
-    ret = (_count == OPERATION_STORE_SIZE);
-    _mutex.unlock();
-
-    return ret;
-}
-
-bool OperationStore::empty()
-{
-    bool ret;
-    
-    _mutex.lock();
-    ret = (_count == 0);
-    _mutex.unlock();
-    
-    return ret;
-}
-
-OperationStore::Operation * OperationStore::get(size_t index)
-{
-    size_t i;
-    
-    if (_offset + index < OPERATION_STORE_SIZE)
-        i = _offset + index;
-    else
-        i = index - (OPERATION_STORE_SIZE - _offset);
-    
-    return &_store[i];
-}
-
-OperationStore::Operation * OperationStore::getByIdentifier(long identifier)
-{
-    size_t n;
-    Operation *tmp;
-    
-    for (n = 0; n < _count; n++) {
-        tmp = get(n);
-        if (tmp->identifier == identifier)
-            return tmp;
-    }
-
-    return NULL;
-}
--- a/operation/OperationStore.h	Fri Mar 20 14:27:10 2015 +0000
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,91 +0,0 @@
-#ifndef OPERATIONSTORE_H
-#define OPERATIONSTORE_H
-
-#include <stddef.h>
-#include <stdint.h>
-#include "rtos.h"
-
-#define OPERATION_PENDING    0
-#define OPERATION_EXECUTING  1
-#define OPERATION_SUCCESSFUL 2
-#define OPERATION_FAILED     3
-
-/**
- * Number of operations which can be stored in the OperationStore
- */
-#define OPERATION_STORE_SIZE 128
-
-/**
- * OperationStore utilizing a circular buffer for storage.
- */
-class OperationStore
-{
-public:
-    OperationStore();
-    
-    struct Operation {
-        Operation() : identifier(0), descriptor(""), state(0) {}
-        long identifier;
-        const char *descriptor;
-        uint8_t state;
-    };
-
-    /**
-     * Enqueues a pending-state operation.
-     * A defensive copy of the operation is madw.
-     * @param operation the operation to enqueue
-     * @return true on success, false otherwise
-     */
-    bool enqueue(Operation&);
-    
-    /**
-     * Dequeues a pending-state operation and sets its state to executing.
-     * @param operation a reference to write the operation to
-     * @return true on success, false otherwise
-     */
-    bool takePending(Operation&);
-    
-    /**
-     * Checks whether there are pending operations available.
-     * @return true if pending operations are available, false otherwise
-     */
-    bool hasPending();
-    
-    /**
-     * Marks a previously dequeued operation as done.
-     * @param operation the operation to mark as done
-     * @param successful set whether the operation was successful
-     * @return true on success, false otherwise
-     */
-    bool markAsDone(Operation&, bool);
-    
-    /**
-     * Dequeues a done-state operation and removes it from the store.
-     * @param operation a reference to write the operation to
-     * @return true on success, false otherwise
-     */
-    bool takeDone(Operation&);
-    
-    /**
-     * Retrieves whether the operation store is full.
-     * @return true when full, false otherwise
-     */
-    bool full();
-
-    /**
-     * Retrieves whether the operation store is empty.
-     * @return true when empty, false otherwise
-     */
-    bool empty();
-
-protected:
-    Operation * get(size_t);
-    Operation * getByIdentifier(long);
-
-private:
-    Operation _store[OPERATION_STORE_SIZE];
-    size_t _offset, _count;
-    Mutex _mutex;
-};
-
-#endif
--- a/operation/OperationSupport.cpp	Fri Mar 20 14:27:10 2015 +0000
+++ b/operation/OperationSupport.cpp	Mon Apr 13 14:24:58 2015 +0000
@@ -1,23 +1,27 @@
 #include <string.h>
 #include "OperationSupport.h"
-#include "Aggregator.h"
-#include "ComposedRecord.h"
-#include "CharValue.h"
-#include "IntegerValue.h"
+//#include "Aggregator.h"
+#include "SmartRestConf.h"
+#include "logging.h"
+
+//CharValue aOperationStatePending("PENDING");
+//CharValue aOperationStateExecuting("EXECUTING");
+//CharValue aOperationStateSuccessful("SUCCESSFUL");
+//CharValue aOperationStateFailed("FAILED");
 
-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(AbstractSmartRest& client, SmartRestTemplate& tpl, long& deviceId, 
-                                   ConfigurationSynchronization& configurationSynchronization, DeviceIO& io,
-                                   DisplayInfo& displayInfo) :
+OperationSupport::OperationSupport(RtosSmartRest& client, SmartRestTemplate& tpl, long& deviceId, 
+                                   ConfigurationSynchronization& configurationSynchronization,
+                                   LCDDisplay& lcdDisplay) :
     _deviceId(deviceId),
     _tpl(tpl),
     _client(client),
-    _executor(client, tpl, deviceId, configurationSynchronization, io, displayInfo),
-    _thread1(OperationSupport::thread1_func, this),
+    _executor(client, tpl, deviceId, configurationSynchronization, lcdDisplay),
+    sock(),
     _thread2(OperationSupport::thread2_func, this),
     _thread3(OperationSupport::thread3_func, this)
 {
@@ -36,7 +40,7 @@
         return false;
 
     // Set operation state
-    // USAGE: 110,<OPERATION/ID>,<STATE>
+    // USAGE: 111,<OPERATION/ID>,<STATE>
     if (!_tpl.add("10,111,PUT,/devicecontrol/operations/%%,application/vnd.com.nsn.cumulocity.operation+json,application/vnd.com.nsn.cumulocity.operation+json,%%,UNSIGNED STRING,\"{\"\"status\"\":\"\"%%\"\"}\"\r\n"))
         return false;
 
@@ -61,176 +65,181 @@
 {
     if (_firstRun) {
         _firstRun = false;
-        if (!requestPendingOperations())
-            return false;
+        bool b = requestPendingOperations();
+        return b;
+    } else {
+        return true;
+    }
+}
+
+bool OperationSupport::executePendingOperation(Operation& op)
+{
+    ComposedRecord r;
+    if (!r.add(IntegerValue(112)) || !r.add(IntegerValue(op.identifier))) {
+        return false;
+    } else if (_client.send(r) != SMARTREST_SUCCESS) {
+        _client.stop();
+        return false;
     }
-    return true;
+    ParsedRecord p;
+    bool b = true;
+    while (_client.receive(p) == SMARTREST_SUCCESS) {
+        if (p.values() >= 3 &&
+            p.value(0).integerValue() >= 220 &&
+            p.value(0).integerValue() <= 222 &&
+            p.value(2).valueType() == VALUE_INTEGER) {
+            Operation* op1 = opool.alloc();
+            op1->identifier = p.value(2).integerValue();
+            bool ret = _executor.executeOperation(p);
+            op1->state = ret ? OPERATION_SUCCESSFUL : OPERATION_FAILED;
+            opool.put(op1);
+        }
+    }
+    _client.stop();
+    return b;
 }
 
 bool OperationSupport::requestPendingOperations()
 {
-    uint8_t ret;
-    OperationStore::Operation op;
-
-    ComposedRecord record;
-    ParsedRecord received;
-    
     IntegerValue msgId(110);
     IntegerValue deviceId(_deviceId);
+    ComposedRecord record;
+
     if ((!record.add(msgId)) || (!record.add(deviceId)))
         return false;
-
-    if (_client.send(record) != SMARTREST_SUCCESS) {
-        _client.stop();
-        return false;
-    }
-    
-    while ((ret = _client.receive(received)) == SMARTREST_SUCCESS) {
-        if (!operationFromRecord(received, op))
-            continue;
-        _store.enqueue(op);
-//        _store.takePending(op);
-//        updateOperation(op);
-//        bool b = _executor.executeOperation(op);
-//        _store.markAsDone(op, b);
-    }
-    _client.stop();
-
-    if ((ret != SMARTREST_END_OF_RESPONSE) &&
-        (ret != SMARTREST_CONNECTION_CLOSED)) {
-        return false;
-    }   
-    return true;
-}
-
-bool OperationSupport::operationFromRecord(ParsedRecord& received, OperationStore::Operation& op)
-{
-    const char *tmp;
-
-    if ((received.values() < 4) ||
-        (received.value(0).valueType() != VALUE_INTEGER) ||
-//TODO: error here since streaming op does not have 210 msg id
-//        (received.value(0).integerValue() != 210) ||
-        (received.value(2).valueType() != VALUE_INTEGER) ||
-        (received.value(3).valueType() != VALUE_CHARACTER))
-        return false;
-    
-    op.identifier = received.value(2).integerValue();
-    tmp = received.value(3).characterValue();
-    if (strcmp(tmp, "EXECUTING") == 0)
-        op.state = OPERATION_EXECUTING;
-    else if (strcmp(tmp, "SUCCESSFUL") == 0)
-        op.state = OPERATION_SUCCESSFUL;
-    else if (strcmp(tmp, "FAILED") == 0)
-        op.state = OPERATION_FAILED;
-    else if (strcmp(tmp, "PENDING") == 0)
-        op.state = OPERATION_PENDING;
-    else
-        return false;
-
-    return true;
-}
-
-bool OperationSupport::updateOperation(OperationStore::Operation& op)
-{
-    ComposedRecord record;
-    ParsedRecord received;
-    IntegerValue msgId(111);
-    IntegerValue operationId(op.identifier);
-    if ((!record.add(msgId)) || (!record.add(operationId)) ||
-        (!record.add(operationStateValue(op))))
-        return false;
-    
-    if (_client.send(record) != SMARTREST_SUCCESS) {
+    else if (_client.send(record) != SMARTREST_SUCCESS) {
         _client.stop();
         return false;
     }
-    puts("UP: sent record!");
-    bool found = false;
-    while (_client.receive(received) == SMARTREST_SUCCESS) {
-        if ((received.values() == 4) &&
-            (received.value(0).valueType() == VALUE_INTEGER) &&
-            (received.value(0).integerValue() == 211) &&
-            (received.value(2).valueType() == VALUE_INTEGER) &&
-            (received.value(2).integerValue() == op.identifier)) {
-            found = true;
+
+    uint8_t ret;
+    ParsedRecord received;
+    Operation opl[10];
+    size_t c = 0;
+    while ((ret=_client.receive(received)) == SMARTREST_SUCCESS) {
+        if (c < 10 && operationFromRecord(received, opl[c])) {
+            ++c;
+        } else {
+            aWarning("Ignored pending operation after 10.\n");
             break;
         }
     }
-    puts("UP: received record!");
     _client.stop();
-    return found;
+
+    for (size_t i = 0; i < c; ++i) {
+        Operation* op = opool.alloc();
+        op->identifier = opl[i].identifier;
+        op->state = OPERATION_EXECUTING;
+        opool.put(op);
+        executePendingOperation(opl[i]);
+    }
+    return (ret == SMARTREST_END_OF_RESPONSE || ret == SMARTREST_CONNECTION_CLOSED);
 }
 
-CharValue& OperationSupport::operationStateValue(OperationStore::Operation& op)
+bool OperationSupport::operationFromRecord(ParsedRecord& received, Operation& op)
 {
-    switch (op.state) {
-    case OPERATION_EXECUTING:
-        return aOperationStateExecuting;
-    case OPERATION_SUCCESSFUL:
-        return aOperationStateSuccessful;
-    case OPERATION_FAILED:
-        return aOperationStateFailed;
-    default:
-        return aOperationStatePending;
+    if ((received.values() < 4) ||
+        (received.value(0).valueType() != VALUE_INTEGER) ||
+//        (received.value(0).integerValue() != 211) ||
+        (received.value(2).valueType() != VALUE_INTEGER) ||
+        (received.value(3).valueType() != VALUE_CHARACTER))
+        return false;
+
+    op.identifier = received.value(2).integerValue();
+    const char *tmp = received.value(3).characterValue();
+    if (strcmp(tmp, strExecuting) == 0)
+        op.state = OPERATION_EXECUTING;
+    else if (strcmp(tmp, strSuccessful) == 0)
+        op.state = OPERATION_SUCCESSFUL;
+    else if (strcmp(tmp, strFailed) == 0)
+        op.state = OPERATION_FAILED;
+    else if (strcmp(tmp, strPending) == 0)
+        op.state = OPERATION_PENDING;
+    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::thread1()
-{
-    OperationStore::Operation op;
-    bool ret;
+//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();
+//        }
+//    }
+//}
 
-    while (!_init)
-        Thread::yield();
-    
-    while (true) {
-        if (!_store.takePending(op)) {
-            Thread::yield();
-            continue;
-        }        
-//        printf("Thread 1: %l, %s, %u\r\n", op.identifier, op.descriptor, op.state);
-        puts("Updating op");
-        updateOperation(op);
-        puts("Updated op");
-        ret = _executor.executeOperation(op);
-        puts("Executed op");
-        _store.markAsDone(op, ret);
-    }
-}
-
+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()
 {
-    OperationStore::Operation op;
-    Aggregator aggr(true);
-
-    while (!_init)
-        Thread::yield();
-    
+    aInfo("Report thread: %p\n", Thread::gettid());
     while (true) {
-        while ((!aggr.full()) && (_store.takeDone(op))) {
-            ComposedRecord record;
-    
-//            printf("Thread 2: %l, %s, %u\r\n", op.identifier, op.descriptor, op.state);
-            IntegerValue msgId(111);
-            IntegerValue operationId(op.identifier);
-            if ((!record.add(msgId)) || (!record.add(operationId)) ||
-                (!record.add(operationStateValue(op))))
-                break;
-            
-            if (!aggr.add(record))
-                break;
+        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");
+            }
         }
-        
-        if (aggr.length() == 0) {
-            Thread::yield();
-            continue;
-        }
-        
-        puts("Sending aggr");
-        if (_client.send(aggr) != SMARTREST_SUCCESS) { }
-        _client.stop();
-        aggr.clear();        
     }
 }
 
@@ -239,12 +248,12 @@
     char bayeuxId[33];
     ComposedRecord record;
     ParsedRecord received;
-    OperationStore::Operation op;
-    
-    while ((!_init) || (_firstRun))
+
+    while (!_init || _firstRun)
         Thread::yield();
-    
+
     // request Bayeux ID
+    aInfo("Polling thread: %p\n", Thread::gettid());
     {
         const char *str;
         IntegerValue msgId(80);
@@ -259,80 +268,98 @@
         _client.stop();
 
         str = received.value(0).characterValue();
-        if ((str == NULL) || (strlen(str) > sizeof(bayeuxId)))
+        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)))
+        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)))
+        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);
     }
     
-    {
-        IntegerValue msgId(83);
-        CharValue bid(bayeuxId);
-        if ((!record.add(msgId)) || (!record.add(bid)))
-            return;
+    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;
         }
-
-        puts("Receiving op");
         while (_client.receive(received) == SMARTREST_SUCCESS) {
-            if (!operationFromRecord(received, op))
+            for (size_t i = 0; i < received.values(); ++i) {
+                printf("%s ", received.rawValue(i));
+            }
+            puts("");
+            if (received.values() == 0) {
                 continue;
-            puts("Parsed record");
-//            printf("Thread 3: %l, %s, %u\r\n", op.identifier, op.descriptor, op.state);
-            _store.enqueue(op);
-            puts("Enqueued op");
-//            _store.takePending(op);
-//            puts("Updating op");
-//            updateOperation(op);
-//            puts("Updated op");
-//            bool ret = _executor.executeOperation(op);
-//            puts("Executed op");
-//            _store.markAsDone(op, ret);
-//            puts("Marked");
+            } 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());
+            }
         }
-
-        //TODO: error checking
         _client.stop();
     }
 }
 
-void OperationSupport::thread1_func(void const *arg)
-{
-    OperationSupport *that;
-    that = (OperationSupport*)arg;
-    that->thread1();
-}
-
 void OperationSupport::thread2_func(void const *arg)
 {
     OperationSupport *that;
--- a/operation/OperationSupport.h	Fri Mar 20 14:27:10 2015 +0000
+++ b/operation/OperationSupport.h	Mon Apr 13 14:24:58 2015 +0000
@@ -3,34 +3,36 @@
 
 #include "rtos.h"
 #include "ConfigurationSynchronization.h"
-#include "DeviceIO.h"
 #include "OperationExecutor.h"
-#include "AbstractSmartRest.h"
+//#include "AbstractSmartRest.h"
+#include "RtosSmartRest.h"
 #include "SmartRestTemplate.h"
 #include "ComposedRecord.h"
 #include "CharValue.h"
-#include "OperationStore.h"
+#include "Operation.h"
 #include "ParsedRecord.h"
+#include "IntegerValue.h"
+
+#define POOL_SIZE 64
 
 class OperationSupport
 {
 public:
-    OperationSupport(AbstractSmartRest&, SmartRestTemplate&, long&, ConfigurationSynchronization&, DeviceIO&, DisplayInfo&);
-    
+    OperationSupport(RtosSmartRest&, SmartRestTemplate&, long&, ConfigurationSynchronization&, LCDDisplay&);
+
     bool init();
     bool run();
 
 protected:
     bool requestPendingOperations();
-    bool operationFromRecord(ParsedRecord&, OperationStore::Operation&);
-    bool updateOperation(OperationStore::Operation&);
-    CharValue& operationStateValue(OperationStore::Operation&);
+    bool operationFromRecord(ParsedRecord&, Operation&);
+    bool executePendingOperation(Operation&);
+//    CharValue& operationStateValue(OperationState state) const;
+    const char * getOperationStateChar(OperationState) const;
 
-    void thread1();
     void thread2();
     void thread3();
 
-    static void thread1_func(void const*);
     static void thread2_func(void const*);
     static void thread3_func(void const*);
 
@@ -38,17 +40,14 @@
     bool _init, _firstRun;
     long& _deviceId;
     SmartRestTemplate& _tpl;
-    AbstractSmartRest& _client;
-    OperationStore _store;
+    RtosSmartRest& _client;
+    Mail<Operation, POOL_SIZE> opool;
     OperationExecutor _executor;
-    Thread _thread1;
+    TCPSocketConnection sock;
+    char buf[300];
+    char buf2[50];
     Thread _thread2;
     Thread _thread3;
 };
 
-extern CharValue aOperationStatePending;
-extern CharValue aOperationStateExecuting;
-extern CharValue aOperationStateSuccessful;
-extern CharValue aOperationStateFailed;
-
 #endif
\ No newline at end of file
--- a/util/RtosSmartRest.cpp	Fri Mar 20 14:27:10 2015 +0000
+++ b/util/RtosSmartRest.cpp	Mon Apr 13 14:24:58 2015 +0000
@@ -1,13 +1,11 @@
 #include "RtosSmartRest.h"
+#include "SmartRestConf.h"
+#include "logging.h"
 
-RtosSmartRest::RtosSmartRest(const char *host, uint16_t port, const char *identifier, MDMSerial& mdm, uint8_t tries) :
-    _host(host),
-    _identifier(identifier),
-    _port(port),
+RtosSmartRest::RtosSmartRest(MDMSerial& mdm, uint8_t tries) :
     _tries(tries),
-    _username(NULL),
-    _password(NULL),
     _count(0),
+    slotsLock(),
     _mdm(mdm)
 {
 }
@@ -18,104 +16,81 @@
         delete _slots[i].inst;
 }
 
-uint8_t RtosSmartRest::setAuthorization(const char *username, const char *password)
+uint8_t RtosSmartRest::bootstrap(const DataGenerator& generator)
 {
-    uint8_t ret;
-    MbedSmartRest *inst;
-    
-    if ((inst = instance()) == NULL)
+    MbedSmartRest *inst = instance();
+    if (inst == NULL)
         return SMARTREST_INTERNAL_ERROR;
-    
-    if ((ret = inst->setAuthorization(username, password)) == SMARTREST_SUCCESS) {
-        _username = username;
-        _password = password;
-    }
-    
+
+    uint8_t ret = inst->bootstrap(generator);
+    if (ret == SMARTREST_SUCCESS)
+        setIdentifier(inst->getIdentifier());
     return ret;
 }
 
-uint8_t RtosSmartRest::bootstrap(const DataGenerator& generator)
-{
-    uint8_t ret;
-    MbedSmartRest *inst;
-    
-    if ((inst = instance()) == NULL)
-        return SMARTREST_INTERNAL_ERROR;
-    
-    if ((ret = inst->bootstrap(generator)) == SMARTREST_SUCCESS)
-        _identifier = inst->getIdentifier();
-    
-    return ret;
-}
-    
 uint8_t RtosSmartRest::send(const DataGenerator& generator, const char *overrideIdentifier)
 {
-    MbedSmartRest *inst;
-    
-    if ((inst = instance()) == NULL)
+    MbedSmartRest *inst = instance();   
+    if (inst)
+        return inst->send(generator, overrideIdentifier);
+    else
         return SMARTREST_INTERNAL_ERROR;
+}
 
-    return inst->send(generator, overrideIdentifier);
+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;
-    
-    if ((inst = instance()) == NULL)
+    MbedSmartRest *inst = instance();
+    if (inst)
+        return inst->stream(uri, record, overrideIdentifier);
+    else
         return SMARTREST_INTERNAL_ERROR;
 
-    return inst->stream(uri, record, overrideIdentifier);
 }
 
 uint8_t RtosSmartRest::receive(ParsedRecord& record)
 {
-    MbedSmartRest *inst;
-    
-    if ((inst = instance()) == NULL)
+    MbedSmartRest *inst = instance();
+    if (inst)
+        return inst->receive(record);
+    else
         return SMARTREST_INTERNAL_ERROR;
-
-    return inst->receive(record);
 }
 
 void RtosSmartRest::stop()
 {
-    MbedSmartRest *inst;
-    
-    if ((inst = instance()) == NULL)
-        return;
-
-    inst->stop();
-}
-
-const char * RtosSmartRest::getIdentifier()
-{
-    return _identifier;
+    MbedSmartRest *inst = instance();
+    if (inst)
+        inst->stop();
 }
 
 MbedSmartRest * RtosSmartRest::instance()
 {
-    size_t i;
-    osThreadId tid;
-    MbedSmartRest *inst;
-    RtosSmartRest::Slot slot;
-    
-    tid = Thread::gettid();
-    
-    for (i = 0; i < _count; i++) {
-        if (tid == _slots[i].tid)
+    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;
-    
-    inst = new MbedSmartRest(_host, _port, _identifier, _mdm, _tries);
-    inst->setAuthorization(_username, _password);
+    else {
+        MbedSmartRest *inst = new MbedSmartRest(_mdm, _tries);
+        slotsLock.lock();
+        _slots[_count].tid = tid;
+        _slots[_count].inst = inst;
+        ++_count;
+        slotsLock.unlock();
 
-    slot.tid = tid;
-    slot.inst = inst;
-    
-    _slots[_count++] = slot;
-    return inst;
+        return inst;
+    }
 }
--- a/util/RtosSmartRest.h	Fri Mar 20 14:27:10 2015 +0000
+++ b/util/RtosSmartRest.h	Mon Apr 13 14:24:58 2015 +0000
@@ -10,7 +10,7 @@
 class RtosSmartRest : public AbstractSmartRest
 {
 public:
-    RtosSmartRest(const char*, uint16_t, const char*, MDMSerial&, uint8_t = MBEDSMARTREST_TRIES);
+    RtosSmartRest(MDMSerial&, uint8_t = MBEDSMARTREST_TRIES);
     virtual ~RtosSmartRest();
     
     struct Slot {
@@ -18,24 +18,22 @@
         MbedSmartRest *inst;
     };
 
-    virtual uint8_t setAuthorization(const char*, const char*);
     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();
-    virtual const char * getIdentifier();
     
 protected:
     MbedSmartRest * instance();
 
 private:
-    const char *_host, *_identifier;
-    uint8_t _port, _tries;
-    const char *_username, *_password;
+    uint8_t _tries;
     
     Slot _slots[RTOS_SMARTREST_SLOTS];
     size_t _count;
+    Mutex slotsLock;
     MDMSerial& _mdm;
 };
 
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/util/SmartRestConf.cpp	Mon Apr 13 14:24:58 2015 +0000
@@ -0,0 +1,89 @@
+#include <string.h>
+#include "b64.h"
+
+const char* _username = NULL;
+const char* _password = NULL;
+char _authStr[100] = {0};
+const char *_identifier = "com_cumulocity_MbedAgent_1.5.2";
+const char _host[] = "developer.cumulocity.com";
+// const char _host[] = "management.m2m-devicecloud.com"
+const int _port = 80;
+
+const char* getAuthStr()
+{
+        return _authStr;
+}
+
+void setAuthStr(const char* p1, const char* p2)
+{
+        memset(_authStr, 0, sizeof(_authStr));
+        size_t ul = strlen(p1);
+        size_t pl = strlen(p2);
+        unsigned char input[3], output[5];
+        int inputOffset = 0;
+
+        for (size_t i = 0; i < (ul+1+pl); i++) {
+                if (i < ul)
+                        input[inputOffset++] = p1[i];
+                else if (i == ul)
+                        input[inputOffset++] = ':';
+                else
+                        input[inputOffset++] = p2[i-(ul+1)];
+
+                if ((inputOffset == 3) || (i == ul+pl)) {
+                        b64_encode(input, inputOffset, output, 4);
+                        output[4] = '\0';
+                        strcat(_authStr, (char*)output);
+                        inputOffset = 0;
+                }
+        }
+}
+
+
+const char* getIdentifier()
+{
+        return _identifier;
+}
+
+void setIdentifier(const char* id)
+{
+        if (id)
+            _identifier = id;
+}
+
+const char* getUsername()
+{
+        return _username;
+}
+
+void setUsername(const char* username)
+{
+        _username = username;
+}
+
+const char* getPassword()
+{
+        return _password;
+}
+
+void setPassword(const char* password)
+{
+        _password = password;
+}
+
+void setAuth(const char* username, const char* password)
+{
+        setUsername(username);
+        setPassword(password);
+        setAuthStr(username, password);
+}
+
+const char* getHost()
+{
+        return _host;
+}
+
+int getPort()
+{
+        return _port;
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/util/SmartRestConf.h	Mon Apr 13 14:24:58 2015 +0000
@@ -0,0 +1,21 @@
+#ifndef SMARTRESTCONF_H
+#define SMARTRESTCONF_H
+
+const char* getHost();
+int getPort();
+
+void setAuth(const char* username, const char* password);
+
+void setAuthStr(const char* p1, const char* p2);
+const char* getAuthStr();
+
+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 */