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 27 10:50:21 2015 +0000
Parent:
95:010b0f7a0a1a
Child:
97:ea056f6be2e8
Commit message:
LCDDisplay now is singleton

Changed in this revision

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
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/ConfigurationProperties.cpp Show annotated file Show diff for this revision Revisions of this file
config/ConfigurationProperties.h 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
config/ConfigurationSynchronization.h Show annotated file Show diff for this revision Revisions of this file
config/DeviceConfiguration.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
measurement/AccelerationMeasurement.cpp Show annotated file Show diff for this revision Revisions of this file
measurement/AccelerationMeasurement.h Show annotated file Show diff for this revision Revisions of this file
measurement/AnalogMeasurement.cpp Show annotated file Show diff for this revision Revisions of this file
measurement/AnalogMeasurement.h Show annotated file Show diff for this revision Revisions of this file
measurement/LocationUpdate.cpp Show annotated file Show diff for this revision Revisions of this file
measurement/LocationUpdate.h Show annotated file Show diff for this revision Revisions of this file
measurement/SignalQualityMeasurement.cpp Show annotated file Show diff for this revision Revisions of this file
measurement/SignalQualityMeasurement.h Show annotated file Show diff for this revision Revisions of this file
measurement/TemperatureMeasurement.cpp Show annotated file Show diff for this revision Revisions of this file
measurement/TemperatureMeasurement.h Show annotated file Show diff for this revision Revisions of this file
operation/ControlParser.cpp Show annotated file Show diff for this revision Revisions of this file
operation/ControlParser.h Show annotated file Show diff for this revision Revisions of this file
operation/PollThread.cpp Show annotated file Show diff for this revision Revisions of this file
operation/PollThread.h Show annotated file Show diff for this revision Revisions of this file
operation/PollingThread.cpp Show diff for this revision Revisions of this file
operation/PollingThread.h Show diff for this revision Revisions of this file
util/dict.h Show annotated file Show diff for this revision Revisions of this file
--- a/DeviceBootstrap.cpp	Wed Apr 22 11:22:25 2015 +0000
+++ b/DeviceBootstrap.cpp	Mon Apr 27 10:50:21 2015 +0000
@@ -3,6 +3,7 @@
 #include <string.h>
 #include "DeviceBootstrap.h"
 #include "rtos.h"
+#include "LCDDisplay.h"
 #include "ComposedRecord.h"
 #include "CharValue.h"
 #include "IntegerValue.h"
@@ -10,12 +11,11 @@
 #include "SmartRestConf.h"
 #include "logging.h"
 
-DeviceBootstrap::DeviceBootstrap(AbstractSmartRest& client, LCDDisplay& lcdDisplay,
+DeviceBootstrap::DeviceBootstrap(AbstractSmartRest& client,
     DeviceInfo& deviceInfo, DeviceMemory& deviceMemory) :
     _client(client),
     _deviceInfo(deviceInfo),
-    _deviceMemory(deviceMemory),
-    _lcdDisplay(lcdDisplay)
+    _deviceMemory(deviceMemory)
 {
     *_username = *_password = '\0';
 }
@@ -60,7 +60,7 @@
     // set authorization for bootstrap
     setAuth(DEVICE_BOOTSTRAP_USERNAME, DEVICE_BOOTSTRAP_PASSWORD);
 
-    _lcdDisplay.setLines("Bootstrap", _deviceInfo.imei());
+    LCDDisplay::inst().setLines("Bootstrap", _deviceInfo.imei());
 
     uint8_t tries = 255;
     do {
@@ -89,11 +89,11 @@
         setCredentials(recvdRecord.value(3).characterValue(),
                        recvdRecord.value(4).characterValue(),
                        recvdRecord.value(5).characterValue());        
-        _lcdDisplay.setLines("Bootstrap Success", _username, _password);
+        LCDDisplay::inst().setLines("Bootstrap Success", _username, _password);
         return true;
     } while (--tries > 0);
 
-    _lcdDisplay.setLines("Bootstrap Failure");
+    LCDDisplay::inst().setLines("Bootstrap Failure");
     return false;
 }
 
--- a/DeviceBootstrap.h	Wed Apr 22 11:22:25 2015 +0000
+++ b/DeviceBootstrap.h	Mon Apr 27 10:50:21 2015 +0000
@@ -2,7 +2,6 @@
 #define DEVICEBOOTSTRAP_H
 
 #include <stddef.h>
-#include "LCDDisplay.h"
 #include "DeviceMemory.h"
 #include "AbstractSmartRest.h"
 #include "DeviceInfo.h"
@@ -18,7 +17,7 @@
 class DeviceBootstrap
 {
 public:
-    DeviceBootstrap(AbstractSmartRest&, LCDDisplay&, DeviceInfo&, DeviceMemory&);
+    DeviceBootstrap(AbstractSmartRest&, DeviceInfo&, DeviceMemory&);
     
     bool setUpCredentials();
     const char * username();
@@ -36,7 +35,6 @@
     AbstractSmartRest& _client;
     DeviceInfo& _deviceInfo;
     DeviceMemory& _deviceMemory;
-    LCDDisplay& _lcdDisplay;
     char _username[DEVICE_BOOTSTRAP_CREDENTIALS_LENGTH];
     char _password[DEVICE_BOOTSTRAP_CREDENTIALS_LENGTH];
 };
--- a/MbedAgent.cpp	Wed Apr 22 11:22:25 2015 +0000
+++ b/MbedAgent.cpp	Mon Apr 27 10:50:21 2015 +0000
@@ -1,25 +1,22 @@
 #include "MbedAgent.h"
 #include "rtos.h"
+#include "LCDDisplay.h"
 #include "logging.h"
 #include "watchdog.h"
 
-MbedAgent::MbedAgent(GPSI2C& gps, MDMSerial& mdm, LCDDisplay& lcdDisplay,
+MbedAgent::MbedAgent(GPSI2C& gps, MDMSerial& mdm,
     DeviceInfo& deviceInfo, DeviceMemory& deviceMemory) :
     _deviceId(0),
     _mdm(mdm),
-    _deviceInfo(deviceInfo),
-    _deviceMemory(deviceMemory),
-    _lcdDisplay(lcdDisplay),
-    _configurationProperties(_deviceConfiguration),
     _client(mdm),
-    _bootstrap(_client, lcdDisplay, _deviceInfo, _deviceMemory),
-    _integration(_client, _tpl, _deviceId, _deviceInfo),
-    _configurationSynchronization(_client, _tpl, _deviceId, _deviceMemory, _deviceConfiguration, _configurationProperties),
-    _signalQualityMeasurement(_client, _tpl, _deviceId, _deviceInfo, _lcdDisplay),
-    _temperatureMeasurement(_client, _tpl, _deviceId, deviceInfo, _lcdDisplay),
-    _accelerationMeasurement(_client, _tpl, _deviceId, deviceInfo, _lcdDisplay),
-    _analogMeasurement(_client, _tpl, _deviceId, deviceInfo, _lcdDisplay),
-    _locationUpdate(_client, _tpl, _deviceId, gps, deviceInfo, _lcdDisplay),
+    _bootstrap(_client, deviceInfo, deviceMemory),
+    _integration(_client, _tpl, _deviceId, deviceInfo),
+    _configurationSynchronization(_client, _tpl, _deviceId, deviceMemory),
+    _signalQualityMeasurement(_client, _tpl, _deviceId, deviceInfo),
+    _temperatureMeasurement(_client, _tpl, _deviceId, deviceInfo),
+    _accelerationMeasurement(_client, _tpl, _deviceId, deviceInfo),
+    _analogMeasurement(_client, _tpl, _deviceId, deviceInfo),
+    _locationUpdate(_client, _tpl, _deviceId, gps, deviceInfo),
     pool(),
     _operationSupport(_client, _tpl, _deviceId, pool)
 {
@@ -29,35 +26,35 @@
 {
     bool flag = true;
     if (!_integration.init()) {
-        _lcdDisplay.setLines("Integration init failure");
+        LCDDisplay::inst().setLines("Integrate init fail");
         flag = false;
     }
     if (!_configurationSynchronization.init()) {
-        _lcdDisplay.setLines("Config Sync init failure");
+        LCDDisplay::inst().setLines("ConfigSync init fail");
         flag = false;
     }
     if (!_signalQualityMeasurement.init()) {
-        _lcdDisplay.setLines("Signal init failure");
+        LCDDisplay::inst().setLines("Signal init fail");
         flag = false;
     }
     if (!_temperatureMeasurement.init()) {
-        _lcdDisplay.setLines("Temperature init failure");
+        LCDDisplay::inst().setLines("Temp init fail");
         flag = false;
     }
     if (!_accelerationMeasurement.init()) {
-        _lcdDisplay.setLines("Acceleration init failure");
+        LCDDisplay::inst().setLines("Acc init fail");
         flag = false;
     }
     if (!_analogMeasurement.init()) {
-        _lcdDisplay.setLines("Analog init failure");
+        LCDDisplay::inst().setLines("Analog init fail");
         flag = false;
     }
     if (!_locationUpdate.init()) {
-        _lcdDisplay.setLines("Location init failure");
+        LCDDisplay::inst().setLines("Location init fail");
         flag = false;
     }
     if (!_operationSupport.init()) {
-        _lcdDisplay.setLines("Operation init failure");
+        LCDDisplay::inst().setLines("Operation init fail");
         flag = false;
     }
     return flag;
@@ -73,7 +70,7 @@
 
     Thread::wait(5000);
 
-    _lcdDisplay.setLines("Connect to Cloud", getHost());
+    LCDDisplay::inst().setLines("Connect to Cloud", getHost());
     if (!_integration.integrate()) {
         return -2;
     }
@@ -83,16 +80,6 @@
     if (!_configurationSynchronization.integrate()) {
         return -3;
     }
-    
-    char status[27];
-    snprintf(status, sizeof(status), "ID: %ld", _deviceId);
-    _lcdDisplay.setLines("Connected", status);
-
-    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;
 }
 
@@ -100,8 +87,8 @@
 {
     ReportThread reportThread(pool, _mdm);
     _operationSupport.run();
-    PollingThread pollingThread(pool, _mdm, _lcdDisplay, _configurationSynchronization);
-    pollingThread.setChannel(_deviceId);
+    PollThread pollThread(pool, _mdm, _configurationSynchronization);
+    pollThread.setChannel(_deviceId);
 
     Watchdog wdt;
     wdt.kick(60.0);    // set a 60.0 seconds timeout on watchdog hardware timer
@@ -113,11 +100,6 @@
         _accelerationMeasurement.run();
         _locationUpdate.run();
 //        Thread::wait(30000);
-//        if ((interval = _configurationProperties.readInterval()) < 0)
-//            break;
-//        while (timer.read() < interval) {
-//            Thread::yield();
-//        }
         wdt.kick();    // reset watchdog timer
     }
 }
\ No newline at end of file
--- a/MbedAgent.h	Wed Apr 22 11:22:25 2015 +0000
+++ b/MbedAgent.h	Mon Apr 27 10:50:21 2015 +0000
@@ -9,8 +9,6 @@
 #include "DeviceMemory.h"
 #include "DeviceBootstrap.h"
 #include "DeviceIntegration.h"
-#include "DeviceConfiguration.h"
-#include "ConfigurationProperties.h"
 #include "ConfigurationSynchronization.h"
 #include "SignalQualityMeasurement.h"
 #include "TemperatureMeasurement.h"
@@ -18,15 +16,14 @@
 #include "AnalogMeasurement.h"
 #include "LocationUpdate.h"
 #include "OperationSupport.h"
-#include "LCDDisplay.h"
 #include "SmartRestConf.h"
-#include "PollingThread.h"
+#include "PollThread.h"
 #include "ReportThread.h"
 
 class MbedAgent
 {
 public:
-    MbedAgent(GPSI2C&, MDMSerial&, LCDDisplay&, DeviceInfo&, DeviceMemory&);
+    MbedAgent(GPSI2C&, MDMSerial&, DeviceInfo&, DeviceMemory&);
 
     bool init();
     int run();
@@ -37,11 +34,6 @@
 private:
     long _deviceId;
     MDMSerial& _mdm;
-    DeviceInfo& _deviceInfo;
-    DeviceMemory& _deviceMemory;
-    LCDDisplay& _lcdDisplay;
-    DeviceConfiguration _deviceConfiguration;
-    ConfigurationProperties _configurationProperties;
     SmartRest _client;
     SmartRestTemplate _tpl;
     DeviceBootstrap _bootstrap;
--- a/MbedSmartRest.lib	Wed Apr 22 11:22:25 2015 +0000
+++ b/MbedSmartRest.lib	Mon Apr 27 10:50:21 2015 +0000
@@ -1,1 +1,1 @@
-http://developer.mbed.org/users/xinlei/code/MbedSmartRest/#207549b3711e
+http://developer.mbed.org/users/xinlei/code/MbedSmartRest/#832cb27c28f9
--- a/config/ConfigurationProperties.cpp	Wed Apr 22 11:22:25 2015 +0000
+++ b/config/ConfigurationProperties.cpp	Mon Apr 27 10:50:21 2015 +0000
@@ -1,12 +1,7 @@
-#include "ConfigurationProperties.h"
 #include <stdlib.h>
 #include <stdio.h>
 #include <string.h>
-
-ConfigurationProperties::ConfigurationProperties(DeviceConfiguration& deviceConfiguration) :
-    _deviceConfiguration(deviceConfiguration)
-{
-}
+#include "ConfigurationProperties.h"
 
 bool ConfigurationProperties::resetConfiguration()
 {
@@ -15,17 +10,17 @@
 
 bool ConfigurationProperties::validateProperties()
 {
-    return (readInterval() > 0);
+    return (readInterval() >= 0);
 }
 
 int ConfigurationProperties::readInterval()
 {
-    const char *prop; int res, ln;
-    
-    if ((prop = _deviceConfiguration.get("interval")) == NULL)
+    const char *prop = _deviceConfiguration.get("interval");    
+    if (prop == NULL)
         prop = CONFIGURATION_PROPERTY_INTERVAL;
-    
-    ln = -1;
+
+    int res;
+    int ln = -1;
     if ((sscanf(prop, "%d%n", &res, &ln) != 1) || (ln != strlen(prop)))
         return 0;
 
--- a/config/ConfigurationProperties.h	Wed Apr 22 11:22:25 2015 +0000
+++ b/config/ConfigurationProperties.h	Mon Apr 27 10:50:21 2015 +0000
@@ -9,11 +9,11 @@
 class ConfigurationProperties
 {
 public:
-    ConfigurationProperties(DeviceConfiguration&);
-    
+    ConfigurationProperties(DeviceConfiguration& deviceConfiguration):
+        _deviceConfiguration(deviceConfiguration) {
+    }
     bool resetConfiguration();
     bool validateProperties();
-    
     int readInterval();
 
 private:
--- a/config/ConfigurationSynchronization.cpp	Wed Apr 22 11:22:25 2015 +0000
+++ b/config/ConfigurationSynchronization.cpp	Mon Apr 27 10:50:21 2015 +0000
@@ -5,16 +5,18 @@
 #include "IntegerValue.h"
 #include "logging.h"
 
-ConfigurationSynchronization::ConfigurationSynchronization(AbstractSmartRest& client, SmartRestTemplate& tpl, long& deviceId, DeviceMemory& deviceMemory, DeviceConfiguration& deviceConfiguration, ConfigurationProperties& configurationProperties) :
-    _deviceId(deviceId),
+ConfigurationSynchronization::ConfigurationSynchronization(
+    AbstractSmartRest& client, SmartRestTemplate& tpl,
+    long& deviceId, DeviceMemory& deviceMemory) :
+    _init (false),
+    _changed (false),
     _tpl(tpl),
     _client(client),
     _deviceMemory(deviceMemory),
-    _deviceConfiguration(deviceConfiguration),
-    _configurationProperties(configurationProperties)
+    _deviceId(deviceId),
+    _deviceConfiguration(),
+    _configurationProperties(_deviceConfiguration)
 {
-    _init = false;
-    _changed = false;
 }
 
 bool ConfigurationSynchronization::init()
@@ -59,7 +61,7 @@
 bool ConfigurationSynchronization::updateConfiguration(const char *cfg)
 {
     if (!_deviceConfiguration.read(cfg)) {
-        aError("updateConfiguration: Unable to read device configuration!\r\n");
+        aError("Read device config.\n");
         return false;
     }
     
@@ -77,7 +79,7 @@
     char buf[256];
     
     if (!_deviceConfiguration.write(buf, sizeof(buf))) {
-        aError("updateDeviceObject: Unable to write device configuration!\r\n");
+        aError("Unable to write config.\n");
         return false;
     }
 
@@ -89,28 +91,25 @@
     CharValue config(buf);
     IntegerValue responsibility(_configurationProperties.readInterval());
     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) {
-        aWarning("Sending configuration failed.\r\n");
         _client.stop();
         return false;
     }
     
     if (_client.receive(received) != SMARTREST_SUCCESS) {
-        aWarning("Receiving configuration failed.\r\n");
         _client.stop();
         return false;
     }
     _client.stop();
 
     if (received.values() != 3) {
-        aError("Invalid configuration received, expected 3 values, but %d received.\r\n", received.values());
+        aError("Invalid config, %d (3) values received.\n", received.values());
         return false;
     } else if (received.value(0).integerValue() != 201) {
-        aError("updateDeviceObject: Unexpected message ID %ld received.\r\n", received.value(0).integerValue());
+        aError("updateDeviceObject: Message ID %ld .\n", received.value(0).integerValue());
         return false;
     }
     return true;
@@ -121,11 +120,11 @@
     char buf[256];
     
     if (!_deviceMemory.loadConfiguration(buf, sizeof(buf))) {
-        aError("loadConfiguration: Unable to load device configuration!\r\n");
+        aError("Load device config.\n");
         return false;
     }
     if (!_deviceConfiguration.read(buf)) {
-        aError("loadConfiguration: Unable to read device configuration!\r\n");
+        aError("Read device config.\n");
         return false;
     }
     return true;
@@ -136,11 +135,11 @@
     char buf[256];
     
     if (!_deviceConfiguration.write(buf, sizeof(buf))) {
-        aError("saveConfiguration: Unable to write device configuration!\r\n");
+        aError("Write device config.\n");
         return false;
     }
     if (!_deviceMemory.saveConfiguration(buf)) {
-        aError("saveConfiguration: Unable to save device configuration!\r\n");
+        aError("Save device config.\n");
         return false;
     }
     return true;
--- a/config/ConfigurationSynchronization.h	Wed Apr 22 11:22:25 2015 +0000
+++ b/config/ConfigurationSynchronization.h	Mon Apr 27 10:50:21 2015 +0000
@@ -3,14 +3,13 @@
 
 #include "AbstractSmartRest.h"
 #include "SmartRestTemplate.h"
-#include "DeviceConfiguration.h"
+#include "DeviceMemory.h"
 #include "ConfigurationProperties.h"
-#include "DeviceMemory.h"
 
 class ConfigurationSynchronization
 {
 public:
-    ConfigurationSynchronization(AbstractSmartRest&, SmartRestTemplate&, long&, DeviceMemory&, DeviceConfiguration&, ConfigurationProperties&);
+    ConfigurationSynchronization(AbstractSmartRest&, SmartRestTemplate&, long&, DeviceMemory&);
     
     bool init();
     bool integrate();
@@ -25,13 +24,13 @@
 
 private:
     bool _init;
-    long& _deviceId;
     bool _changed;
     SmartRestTemplate& _tpl;
     AbstractSmartRest& _client;
     DeviceMemory& _deviceMemory;
-    DeviceConfiguration& _deviceConfiguration;
-    ConfigurationProperties& _configurationProperties;
+    long& _deviceId;
+    DeviceConfiguration _deviceConfiguration;
+    ConfigurationProperties _configurationProperties;
 };
 
 #endif
\ No newline at end of file
--- a/config/DeviceConfiguration.cpp	Wed Apr 22 11:22:25 2015 +0000
+++ b/config/DeviceConfiguration.cpp	Mon Apr 27 10:50:21 2015 +0000
@@ -1,13 +1,11 @@
-#include "DeviceConfiguration.h"
 #include <stdlib.h>
 #include <stdio.h>
 #include <string.h>
+#include "DeviceConfiguration.h"
 
 DeviceConfiguration::DeviceConfiguration()
 {
-    size_t i;
-    
-    for (i = 0; i < DEVICE_CONFIGURATION_SIZE; i++) {
+    for (size_t i = 0; i < DEVICE_CONFIGURATION_SIZE; ++i) {
         _items[i].key = NULL;
         _items[i].value = NULL;
     }
@@ -20,17 +18,18 @@
 
 bool DeviceConfiguration::read(const char *str)
 {
-    const char *ptr, *ptr2, *ptr3; size_t i, j, len1, len2;
-    DeviceConfiguration::KeyValue items[DEVICE_CONFIGURATION_SIZE];
-    
+    DeviceConfiguration::KeyValue items[DEVICE_CONFIGURATION_SIZE];    
+    size_t i;
     for (i = 0; i < DEVICE_CONFIGURATION_SIZE; i++) {
         items[i].key = NULL;
         items[i].value = NULL;
     }
 
-    ptr = str;
+    const char *ptr = str;
+    const char *ptr2, *ptr3;
+    int len1, len2;
     i = 0;
-    while ((*ptr != '\0') && (i < DEVICE_CONFIGURATION_SIZE)) {
+    while (*ptr && i<DEVICE_CONFIGURATION_SIZE) {
         if (((ptr2 = strchr(ptr, '=')) == NULL) ||
             ((ptr3 = strchr(ptr2+1, ';')) == NULL))
             goto failure;
@@ -42,7 +41,7 @@
             (memchr(ptr2+1, '=', len2) != NULL))
             goto failure;
         
-        for (j = 0; j < DEVICE_CONFIGURATION_SIZE; j++) {
+        for (size_t j = 0; j < DEVICE_CONFIGURATION_SIZE; j++) {
             if ((items[j].key != NULL) && (strlen(items[j].key) == len1) && (strncmp(items[j].key, ptr, len1) == 0))
                 goto failure;
         }
@@ -78,36 +77,30 @@
             free(items[i].value);
         }
     }
-    
     return false;
 }
 
 bool DeviceConfiguration::write(char *buf, size_t len)
 {
-    char *ptr; size_t i; int ret, ln;
-    
-    ptr = buf;
-    for (i = 0; i < DEVICE_CONFIGURATION_SIZE; i++) {
-        if (_items[i].key == NULL)
-            continue;
+    char *ptr= buf;
+    int ln;
 
-        ret = snprintf(ptr, len, "%s=%s;%n", _items[i].key, _items[i].value, &ln);
-        if ((ret < 0) || (ret >= len))
-            return false;
-
-        ptr += ln;
-        len -= ln;
+    for (size_t i = 0; i < DEVICE_CONFIGURATION_SIZE; i++) {
+        if (_items[i].key) {
+            snprintf(ptr, len, "%s=%s;%n", _items[i].key, _items[i].value, &ln);
+            ptr += ln;
+            len -= ln;
+        }
     }
-    
     return true;
 }
 
 bool DeviceConfiguration::set(const char *key, const char *value)
 {
-    KeyValue *item; size_t i;
+    KeyValue *item = search(key);
     
-    if ((item = search(key)) == NULL) {
-        for (i = 0; (i < DEVICE_CONFIGURATION_SIZE) && (item == NULL); i++) {
+    if (item == NULL) {
+        for (size_t i = 0; (i < DEVICE_CONFIGURATION_SIZE) && (item == NULL); i++) {
             if (_items[i].key == NULL)
                 item = &_items[i];
         }
@@ -131,26 +124,26 @@
 
 const char * DeviceConfiguration::get(const char *key)
 {
-    KeyValue *item;
+    KeyValue *item = search(key);
     
-    if ((item = search(key)) == NULL)
+    if (item)
+        return item->value;
+    else
         return NULL;
-    
-    return item->value;
 }
 
 bool DeviceConfiguration::unset(const char *key)
 {
-    KeyValue *item;
-    
-    if ((item = search(key)) == NULL)
-        return false;
+    KeyValue *item = search(key);
     
-    free(item->key);
-    free(item->value);
-    item->key = NULL;
-    item->value = NULL;
-    return true;
+    if (item) {
+        free(item->key);
+        free(item->value);
+        item->key = NULL;
+        item->value = NULL;
+        return true;
+    } else
+        return false;
 }
 
 bool DeviceConfiguration::has(const char *key)
@@ -160,10 +153,8 @@
 
 void DeviceConfiguration::clear()
 {
-    size_t i;
-    
-    for (i = 0; i < DEVICE_CONFIGURATION_SIZE; i++) {
-        if (_items[i].key != NULL) {
+    for (size_t i = 0; i < DEVICE_CONFIGURATION_SIZE; i++) {
+        if (_items[i].key) {
             free(_items[i].key);
             free(_items[i].value);
         }
@@ -172,12 +163,9 @@
 
 DeviceConfiguration::KeyValue * DeviceConfiguration::search(const char *key)
 {
-    size_t i;
-    
-    for (i = 0; i < DEVICE_CONFIGURATION_SIZE; i++) {
+    for (size_t i = 0; i < DEVICE_CONFIGURATION_SIZE; i++) {
         if (strcmp(key, _items[i].key) == 0)
             return &_items[i];
-    }
-    
+    }    
     return NULL;
 }
--- a/io/LCDDisplay.cpp	Wed Apr 22 11:22:25 2015 +0000
+++ b/io/LCDDisplay.cpp	Mon Apr 27 10:50:21 2015 +0000
@@ -1,3 +1,4 @@
+#include <ctype.h>
 #include "LCDDisplay.h"
 #include "logging.h"
 
@@ -10,8 +11,14 @@
         if (n == 0) {
                 return ;
         } else if (src && src!=dest) {
-                strncpy(dest, src, n-1);
+                size_t j = 0;
+                for (size_t i = 0; src[i] && j<n; ++i) {
+                        if (isprint(src[i]))
+                                dest[j++] = src[i];
+                }
                 dest[n-1] = '\0';
+                if (j < n)
+                    dest[j] = '\0';
         }
 }
 
@@ -58,21 +65,16 @@
 
 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) {
+    if (l2) {
         _lcd.printf("%s\n", l2);
-        aDebug(GRE "> " CYA "%s\r\n" DEF, l2);
 
-        if (l3 != NULL) {
+        if (l3) {
             _lcd.printf("%s\n", l3);
-            aDebug(GRE "> " CYA "%s\r\n" DEF, l3);
         }
     }
     lcdLock.unlock();
--- a/io/LCDDisplay.h	Wed Apr 22 11:22:25 2015 +0000
+++ b/io/LCDDisplay.h	Mon Apr 27 10:50:21 2015 +0000
@@ -7,9 +7,16 @@
 
 class LCDDisplay
 {
-public:
+private:
         LCDDisplay(): firstLine(""), secondLine(""), thirdLine(""),
                       _lcd(D11, D13, D12, D7, D10) {}
+        LCDDisplay(LCDDisplay const&);
+        void operator=(LCDDisplay const&);
+public:
+        static LCDDisplay& inst() {
+                static LCDDisplay _ref;
+                return _ref;
+        }
         void setFirstLine(const char* p);
         const char *getFirstLine() const { return firstLine; }
         void setSecondLine(const char* p);
--- a/main.cpp	Wed Apr 22 11:22:25 2015 +0000
+++ b/main.cpp	Mon Apr 27 10:50:21 2015 +0000
@@ -9,6 +9,7 @@
 #include "MbedAgent.h"
 #include "GPSTracker.h"
 #include "DeviceConfiguration.h"
+#include "LCDDisplay.h"
 #include "logging.h"
 
 /**
@@ -54,17 +55,16 @@
     pMdm = &mdm;
     InterruptIn joystickUp(A2);
     InterruptIn joystickDown(A3);
-    LCDDisplay lcdDisplay;
     MDMParser::DevStatus devStatus;
     GPSI2C gps;
-    lcdDisplay.setLines("Mbed Agent V2.1rc2", getHost());
+    LCDDisplay::inst().setLines("Mbed Agent V2.1rc2", getHost());
     if (!mdm.init(SIM_PIN, &devStatus)) {
-        lcdDisplay.setLines("Modem Init Failure", "No SIM card found", "Or SIM has PIN");
+        LCDDisplay::inst().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");
+        LCDDisplay::inst().setLines("GPS Init Failure");
         mdm.disconnect();
         mdm.powerOff();
         return 2;
@@ -76,11 +76,11 @@
     DigitalIn fireButton(D4);
 
     if (fireButton) {
-        lcdDisplay.setLines("Factory Reset");
+        LCDDisplay::inst().setLines("Factory Reset");
         if (deviceMemory.resetPlatformCredentials()) {
-            lcdDisplay.setLines("Reset Success");
+            LCDDisplay::inst().setLines("Reset Success");
         } else {
-            lcdDisplay.setLines("Reset Failure");
+            LCDDisplay::inst().setLines("Reset Failure");
         }
         mdm.disconnect();
         mdm.powerOff();
@@ -88,15 +88,15 @@
         return 0;
     }
     aInfo("Main Thread: %p\r\n", Thread::gettid());    
-    lcdDisplay.setLines("Register Network...", "IMEI", devStatus.imei);
+    LCDDisplay::inst().setLines("Register Network...", "IMEI", devStatus.imei);
     if (!mdm.registerNet()) {
-        lcdDisplay.setLines("No Network Coverage");
+        LCDDisplay::inst().setLines("No Network Coverage");
         mdm.disconnect();
         mdm.powerOff();
         return 3;
     }
 
-    lcdDisplay.setLines("Join Network");
+    LCDDisplay::inst().setLines("Join Network");
 #ifdef SIM_APN
     if (mdm.join(SIM_APN, SIM_USER, SIM_PASS) == NOIP) {
 #else
@@ -107,7 +107,7 @@
         if (p) {
             snprintf(s, sizeof(s), "%.*s-%.*s", 3, p, getMNCLen(p), p+3);
         }
-        lcdDisplay.setLines("Wrong APN Settting", "MCC-MNC:", s);
+        LCDDisplay::inst().setLines("Wrong APN Settting", "MCC-MNC:", s);
         mdm.disconnect();
         mdm.powerOff();
         return 4;
@@ -115,26 +115,33 @@
 
     {
         DeviceInfo deviceInfo(mdm, devStatus);
-        MbedAgent agent(gps, mdm, lcdDisplay, deviceInfo, deviceMemory);
+        MbedAgent agent(gps, mdm, deviceInfo, deviceMemory);
 
-        lcdDisplay.setLines("Agent Init");
+        LCDDisplay::inst().setLines("Agent Init");
         if (!agent.init()) {
             mdm.disconnect();
             mdm.powerOff();
             return 5;
         }
-        lcdDisplay.setLines("Agent Run");
+        LCDDisplay::inst().setLines("Agent Run");
         int ret = 0;
         for (uint8_t tries = 3; tries; --tries) {
             ret = agent.run();
-            if (ret == 0)
+            if (ret == 0) {
+                char status[27];
+                const char* user= getUsername();
+                int len = strchr(user, '/')-user+sizeof("Tenant: ");
+                len = len <= 27 ? len : 27;
+                snprintf(status, len, "Tenant: %s", user);
+                LCDDisplay::inst().setFirstLine(status);
                 break;
+            }
         }
 
         switch (ret) {
-            case -1: lcdDisplay.setLines("Bootstrap error"); break;
-            case -2: lcdDisplay.setLines("Integrate failure"); break;
-            case -3: lcdDisplay.setLines("Config sync failure"); break;
+            case -1: LCDDisplay::inst().setLines("Bootstrap error"); break;
+            case -2: LCDDisplay::inst().setLines("Integrate failure"); break;
+            case -3: LCDDisplay::inst().setLines("Config sync failure"); break;
             default: agent.loop();
         }
         mdm.disconnect();
--- a/measurement/AccelerationMeasurement.cpp	Wed Apr 22 11:22:25 2015 +0000
+++ b/measurement/AccelerationMeasurement.cpp	Mon Apr 27 10:50:21 2015 +0000
@@ -4,20 +4,20 @@
 #include "IntegerValue.h"
 #include "FloatValue.h"
 #include "MbedClient.h"
+#include "LCDDisplay.h"
 #include "logging.h"
 
 #define THRESHOLD_PERCENT_ACCE 0.1       // Percentage cut-off for avoiding sending similar acceleration sensor data.
 // 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, DeviceInfo& deviceInfo, LCDDisplay& lcdDisplay) :
+AccelerationMeasurement::AccelerationMeasurement(AbstractSmartRest& client,
+    SmartRestTemplate& tpl, long& deviceId, DeviceInfo& deviceInfo) :
     _deviceId(deviceId),
     _tpl(tpl),
     _client(client),
     _sensor(SDA,SCL),
-    _deviceInfo(deviceInfo),
-    _lcdDisplay(lcdDisplay)
+    _deviceInfo(deviceInfo)
 {
     _init = false;
     oldValues[0] = 0;
@@ -57,8 +57,8 @@
         time_t t_interval = time(NULL) - t_start;
         if (t_interval < TIME_LIMIT_ACCE) {
 //            printf("[N] Acc %f, %f, %f\r\n", data[0], data[1], data[2]);
-            if (strcmp(_lcdDisplay.getThirdLine(), "")) {
-                _lcdDisplay.setThirdLine("");
+            if (strcmp(LCDDisplay::inst().getThirdLine(), "")) {
+                LCDDisplay::inst().setThirdLine("");
             }
             return true;
         } else {
@@ -68,7 +68,7 @@
 //    printf("[Y] Acc %f, %f, %f\r\n", data[0], data[1], data[2]);
     char status[27] = {0};
     snprintf(status, 27, "Send Acc %.1f,%.1f,%.1f", data[0], data[1], data[2]);
-    _lcdDisplay.setThirdLine(status);
+    LCDDisplay::inst().setThirdLine(status);
 
     ComposedRecord record;
     IntegerValue msgId(106);
--- a/measurement/AccelerationMeasurement.h	Wed Apr 22 11:22:25 2015 +0000
+++ b/measurement/AccelerationMeasurement.h	Mon Apr 27 10:50:21 2015 +0000
@@ -5,12 +5,11 @@
 #include "SmartRestTemplate.h"
 #include "MMA7660.h"
 #include "DeviceInfo.h"
-#include "LCDDisplay.h"
 
 class AccelerationMeasurement
 {
 public:
-    AccelerationMeasurement(AbstractSmartRest&, SmartRestTemplate&, long&, DeviceInfo&, LCDDisplay&);
+    AccelerationMeasurement(AbstractSmartRest&, SmartRestTemplate&, long&, DeviceInfo&);
     
     bool init();
     bool run();
@@ -24,7 +23,6 @@
     float oldValues[3];
     time_t t_start;
     DeviceInfo& _deviceInfo;
-    LCDDisplay& _lcdDisplay;
 };
 
 #endif
\ No newline at end of file
--- a/measurement/AnalogMeasurement.cpp	Wed Apr 22 11:22:25 2015 +0000
+++ b/measurement/AnalogMeasurement.cpp	Mon Apr 27 10:50:21 2015 +0000
@@ -3,6 +3,7 @@
 #include "CharValue.h"
 #include "IntegerValue.h"
 #include "FloatValue.h"
+#include "LCDDisplay.h"
 #include "logging.h"
 
 #define THRESHOLD_PERCENT_ANA 0.02       // Percentage cut-off for avoiding sending similar analog sensor data.
@@ -13,15 +14,11 @@
 AnalogIn _analog2(A1);
 
 AnalogMeasurement::AnalogMeasurement(AbstractSmartRest& client,
-                                     SmartRestTemplate& tpl,
-                                     long& deviceId,
-                                     DeviceInfo& deviceInfo,
-                                     LCDDisplay& lcdDisplay) :
+    SmartRestTemplate& tpl, long& deviceId, DeviceInfo& deviceInfo) :
     _deviceId(deviceId),
     _tpl(tpl),
     _client(client),
-    _deviceInfo(deviceInfo),
-    _lcdDisplay(lcdDisplay)
+    _deviceInfo(deviceInfo)
 {
     _init = false;
     oldValues[0] = 0;
@@ -51,8 +48,8 @@
         abs(oldValues[1]-data[1]) <= abs(oldValues[1])*THRESHOLD_PERCENT_ANA) {
         time_t t_interval = time(NULL) - t_start;
         if (t_interval < TIME_LIMIT_ANA) {
-            if (strcmp(_lcdDisplay.getThirdLine(), "")) {
-                _lcdDisplay.setThirdLine("");
+            if (strcmp(LCDDisplay::inst().getThirdLine(), "")) {
+                LCDDisplay::inst().setThirdLine("");
             }
 //            printf("[N] %f, %f\r\n", data[0], data[1]);
             return true;
@@ -64,7 +61,7 @@
 //    printf("[Y] %f, %f (%f, %f)\r\n", data[0], data[1], oldValues[0], oldValues[1]);
     char status[27] = {0};
     snprintf(status, sizeof(status), "Send Poti %.1f,%.1f", data[0], data[1]);
-    _lcdDisplay.setThirdLine(status);
+    LCDDisplay::inst().setThirdLine(status);
     ComposedRecord record;
     IntegerValue msgId(107);
     IntegerValue devId(_deviceId);
--- a/measurement/AnalogMeasurement.h	Wed Apr 22 11:22:25 2015 +0000
+++ b/measurement/AnalogMeasurement.h	Mon Apr 27 10:50:21 2015 +0000
@@ -5,12 +5,11 @@
 #include "SmartRestTemplate.h"
 #include "mbed.h"
 #include "DeviceInfo.h"
-#include "LCDDisplay.h"
 
 class AnalogMeasurement
 {
 public:
-    AnalogMeasurement(AbstractSmartRest&, SmartRestTemplate&, long&, DeviceInfo&, LCDDisplay&);
+    AnalogMeasurement(AbstractSmartRest&, SmartRestTemplate&, long&, DeviceInfo&);
     
     bool init();
     bool run();
@@ -23,7 +22,6 @@
     float oldValues[2];
     time_t t_start;
     DeviceInfo& _deviceInfo;
-    LCDDisplay& _lcdDisplay;
 };
 
 #endif
\ No newline at end of file
--- a/measurement/LocationUpdate.cpp	Wed Apr 22 11:22:25 2015 +0000
+++ b/measurement/LocationUpdate.cpp	Mon Apr 27 10:50:21 2015 +0000
@@ -4,6 +4,7 @@
 #include "CharValue.h"
 #include "IntegerValue.h"
 #include "FloatValue.h"
+#include "LCDDisplay.h"
 #include "logging.h"
 
 #define THRESHOLD_PERCENT_LOC 0.05       // Percentage cut-off for avoiding sending similar acceleration sensor data.
@@ -11,13 +12,12 @@
 #define TIME_LIMIT_LOC 900               
 
 LocationUpdate::LocationUpdate(AbstractSmartRest& client, SmartRestTemplate& tpl,
-    long& deviceId, GPSI2C& gps, DeviceInfo& deviceInfo, LCDDisplay& lcdDisplay) :
+    long& deviceId, GPSI2C& gps, DeviceInfo& deviceInfo) :
     _deviceId(deviceId),
     _tpl(tpl),
     _client(client),
     _gpsTracker(gps),
-    _deviceInfo(deviceInfo),
-    _lcdDisplay(lcdDisplay)
+    _deviceInfo(deviceInfo)
 {
     _init = false;
     oldValues[0] = 0;
@@ -58,8 +58,8 @@
         abs(oldValues[2]-data[2]) <= abs(oldValues[2])*THRESHOLD_PERCENT_LOC) {
         time_t t_interval = time(NULL) - t_start;
         if (t_interval < TIME_LIMIT_LOC) {
-            if (strcmp(_lcdDisplay.getThirdLine(), "")) {
-                _lcdDisplay.setThirdLine("");
+            if (strcmp(LCDDisplay::inst().getThirdLine(), "")) {
+                LCDDisplay::inst().setThirdLine("");
             }
             return true;
         } else {
@@ -68,7 +68,7 @@
     }
     char status[27] = {0};
     snprintf(status, 27, "Send GPS %.1f,%.1f,%.1f", data[0], data[1], data[2]);
-    _lcdDisplay.setThirdLine(status);
+    LCDDisplay::inst().setThirdLine(status);
         
     Aggregator aggregator;
     ComposedRecord record1, record2;
--- a/measurement/LocationUpdate.h	Wed Apr 22 11:22:25 2015 +0000
+++ b/measurement/LocationUpdate.h	Mon Apr 27 10:50:21 2015 +0000
@@ -5,12 +5,11 @@
 #include "SmartRestTemplate.h"
 #include "GPSTracker.h"
 #include "DeviceInfo.h"
-#include "LCDDisplay.h"
 
 class LocationUpdate
 {
 public:
-    LocationUpdate(AbstractSmartRest&, SmartRestTemplate&, long&, GPSI2C&, DeviceInfo&, LCDDisplay&);
+    LocationUpdate(AbstractSmartRest&, SmartRestTemplate&, long&, GPSI2C&, DeviceInfo&);
     
     bool init();
     bool run();
@@ -24,7 +23,6 @@
     float oldValues[3];
     time_t t_start;
     DeviceInfo& _deviceInfo;
-    LCDDisplay& _lcdDisplay;
 };
 
 #endif
\ No newline at end of file
--- a/measurement/SignalQualityMeasurement.cpp	Wed Apr 22 11:22:25 2015 +0000
+++ b/measurement/SignalQualityMeasurement.cpp	Mon Apr 27 10:50:21 2015 +0000
@@ -3,6 +3,7 @@
 #include "CharValue.h"
 #include "IntegerValue.h"
 #include "FloatValue.h"
+#include "LCDDisplay.h"
 #include "logging.h"
 
 #define THRESHOLD_PERCENT_SIG 0.06       // Percentage cut-off for avoiding sending similar signal sensor data.
@@ -10,13 +11,11 @@
 #define TIME_LIMIT_SIG 900               
 
 SignalQualityMeasurement::SignalQualityMeasurement(AbstractSmartRest& client, 
-    SmartRestTemplate& tpl, long& deviceId, DeviceInfo& deviceInfo,
-    LCDDisplay& lcdDisplay) :
+    SmartRestTemplate& tpl, long& deviceId, DeviceInfo& deviceInfo) :
     _deviceId(deviceId),
     _tpl(tpl),
     _client(client),
-    _deviceInfo(deviceInfo),
-    _lcdDisplay(lcdDisplay)
+    _deviceInfo(deviceInfo)
 {
     _init = false;
     oldValues[0] = 0;
@@ -48,8 +47,8 @@
         snprintf(signal, sizeof(signal), "Network: %d dBm", signalQuality->rssi);
     else
         strncpy(signal, "Network: no coverage", sizeof(signal));
-    if (strcmp(_lcdDisplay.getSecondLine(), signal)) {
-        _lcdDisplay.setSecondLine(signal);
+    if (strcmp(LCDDisplay::inst().getSecondLine(), signal)) {
+        LCDDisplay::inst().setSecondLine(signal);
     }
 
     int data[2] = {signalQuality->rssi, signalQuality->ber};
@@ -57,8 +56,8 @@
         abs(oldValues[1]-data[1]) <= abs(oldValues[1])*THRESHOLD_PERCENT_SIG) {
         time_t t_interval = time(NULL) - t_start;
         if (t_interval < TIME_LIMIT_SIG) {
-            if (strcmp(_lcdDisplay.getThirdLine(), "")) {
-                _lcdDisplay.setThirdLine("");
+            if (strcmp(LCDDisplay::inst().getThirdLine(), "")) {
+                LCDDisplay::inst().setThirdLine("");
             }
             return true;
         } else {
@@ -68,7 +67,7 @@
 
     char status[25] = {0};
     snprintf(status, 25, "Send dBm %d,%d", data[0], data[1]);
-    _lcdDisplay.setThirdLine(status);
+    LCDDisplay::inst().setThirdLine(status);
     ComposedRecord record;
     IntegerValue msgId(104);
     IntegerValue devId(_deviceId);
--- a/measurement/SignalQualityMeasurement.h	Wed Apr 22 11:22:25 2015 +0000
+++ b/measurement/SignalQualityMeasurement.h	Mon Apr 27 10:50:21 2015 +0000
@@ -4,12 +4,11 @@
 #include "AbstractSmartRest.h"
 #include "SmartRestTemplate.h"
 #include "DeviceInfo.h"
-#include "LCDDisplay.h"
 
 class SignalQualityMeasurement
 {
 public:
-    SignalQualityMeasurement(AbstractSmartRest&, SmartRestTemplate&, long&, DeviceInfo&, LCDDisplay&);
+    SignalQualityMeasurement(AbstractSmartRest&, SmartRestTemplate&, long&, DeviceInfo&);
     
     bool init();
     bool run();
@@ -22,7 +21,6 @@
     DeviceInfo& _deviceInfo;
     int oldValues[2];
     time_t t_start;
-    LCDDisplay& _lcdDisplay;
 };
 
 #endif
\ No newline at end of file
--- a/measurement/TemperatureMeasurement.cpp	Wed Apr 22 11:22:25 2015 +0000
+++ b/measurement/TemperatureMeasurement.cpp	Mon Apr 27 10:50:21 2015 +0000
@@ -3,21 +3,21 @@
 #include "CharValue.h"
 #include "IntegerValue.h"
 #include "FloatValue.h"
+#include "LCDDisplay.h"
 #include "logging.h"
 
 #define THRESHOLD_PERCENT_TEMP 0.02       // Percentage cut-off for avoiding sending similar temperature sensor data.
 // Time interval for forcing a sending even if analog sensor readings are constantly similar (in seconds).
 #define TIME_LIMIT_TEMP 900               
 
-TemperatureMeasurement::TemperatureMeasurement(AbstractSmartRest& client, SmartRestTemplate& tpl,
-    long& deviceId, DeviceInfo& deviceInfo, LCDDisplay& lcdDisplay) :
+TemperatureMeasurement::TemperatureMeasurement(AbstractSmartRest& client,
+    SmartRestTemplate& tpl, long& deviceId, DeviceInfo& deviceInfo) :
     _deviceId(deviceId),
     _tpl(tpl),
     _client(client),
     _sensor(D14,D15),
     oldValue(0),
-    _deviceInfo(deviceInfo),
-    _lcdDisplay(lcdDisplay)
+    _deviceInfo(deviceInfo)
 {
     _init = false;
     t_start = time(NULL);
@@ -48,8 +48,8 @@
     if (abs(oldValue-data) <= abs(oldValue)*THRESHOLD_PERCENT_TEMP) {
         time_t t_interval = time(NULL) - t_start;
         if (t_interval < TIME_LIMIT_TEMP) {
-            if (strcmp(_lcdDisplay.getThirdLine(), "")) {
-                _lcdDisplay.setThirdLine("");
+            if (strcmp(LCDDisplay::inst().getThirdLine(), "")) {
+                LCDDisplay::inst().setThirdLine("");
             }
             return true;
         } else {
@@ -59,7 +59,7 @@
 
     char status[25] = {0};
     snprintf(status, 25, "Send Temp %.2f", data);
-    _lcdDisplay.setThirdLine(status);
+    LCDDisplay::inst().setThirdLine(status);
     ComposedRecord record;
     IntegerValue msgId(105);
     IntegerValue devId(_deviceId);
--- a/measurement/TemperatureMeasurement.h	Wed Apr 22 11:22:25 2015 +0000
+++ b/measurement/TemperatureMeasurement.h	Mon Apr 27 10:50:21 2015 +0000
@@ -5,12 +5,11 @@
 #include "SmartRestTemplate.h"
 #include "LM75B.h"
 #include "DeviceInfo.h"
-#include "LCDDisplay.h"
 
 class TemperatureMeasurement
 {
 public:
-    TemperatureMeasurement(AbstractSmartRest&, SmartRestTemplate&, long&, DeviceInfo&, LCDDisplay&);
+    TemperatureMeasurement(AbstractSmartRest&, SmartRestTemplate&, long&, DeviceInfo&);
 
     bool init();
     bool run();
@@ -24,7 +23,6 @@
     float oldValue;
     time_t t_start;
     DeviceInfo& _deviceInfo;
-    LCDDisplay& _lcdDisplay;
 };
 
 #endif
\ No newline at end of file
--- a/operation/ControlParser.cpp	Wed Apr 22 11:22:25 2015 +0000
+++ b/operation/ControlParser.cpp	Mon Apr 27 10:50:21 2015 +0000
@@ -2,6 +2,7 @@
 #include <string.h>
 #include "ControlParser.h"
 #include "DeviceFeedback.h"
+#include "LCDDisplay.h"
 #include "logging.h"
 
 void ControlParser::handleControlMessage(const char *buf)
@@ -96,15 +97,15 @@
                 }
         } else if (opType == 221) {
                 char line[30] = {0};
-                size_t num = tok.len<30 ? tok.len : 30;
+                size_t num = tok.len < 30 ? tok.len : 30;
                 if (tok.type == Token::STRING)
                         strncpyEscape(line, tok.p, num);
                 else
                         strncpy(line, tok.p, num);
-                _lcdDisplay.setFirstLine(line);
+                LCDDisplay::inst().setFirstLine(line);
         } else if (opType == 222) {
                 char config[128] = {0};
-                size_t num = tok.len<128 ? tok.len : 128;
+                size_t num = tok.len < 127 ? tok.len : 127;
                 strncpy(config, tok.p, num);
                 ret = _configSync.updateConfiguration(config);
         } else {
--- a/operation/ControlParser.h	Wed Apr 22 11:22:25 2015 +0000
+++ b/operation/ControlParser.h	Mon Apr 27 10:50:21 2015 +0000
@@ -3,7 +3,6 @@
 #include "Operation.h"
 #include "lex.h"
 #include "DeviceFeedback.h"
-#include "LCDDisplay.h"
 #include "ConfigurationSynchronization.h"
 
 enum BayeuxAdvice{ BA_RETRY, BA_HANDSHAKE, BA_NONE };
@@ -13,10 +12,10 @@
 class ControlParser
 {
 public:
-        ControlParser(OperationPool& pool, LCDDisplay& lcdDisplay, 
+        ControlParser(OperationPool& pool, 
                 ConfigurationSynchronization& configSync): opType(0),
                 bayeuxAdvice(BA_RETRY), bayeuxTimeout(-1), bayeuxInterval(0),
-                opool(pool), _lcdDisplay(lcdDisplay), _configSync(configSync) {}
+                opool(pool), _configSync(configSync) {}
         virtual ~ControlParser() {}
         BayeuxAdvice getBayeuxAdvice() const { return bayeuxAdvice; }
         int getBayeuxInterval() const { return bayeuxInterval; }
@@ -45,7 +44,6 @@
         int bayeuxInterval;
         PtrParseFunc ptrPF;
         OperationPool& opool;
-        LCDDisplay& _lcdDisplay;
         ConfigurationSynchronization& _configSync;
 };
 
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/operation/PollThread.cpp	Mon Apr 27 10:50:21 2015 +0000
@@ -0,0 +1,65 @@
+#include <stdio.h>
+#include <ctype.h>
+#include "PollThread.h"
+#include "lex.h"
+#include "logging.h"
+
+bool PollThread::handshake()
+{
+        int l = snprintf(buf2, SMARRESTBODY_SIZE, "%s", "80\r\n");
+        l = snprintf(buf, SMARTREST_SIZE, getSmartRestFmt(), uri, l, buf2);
+        l = sock.sendAndReceive(buf, l, SMARTREST_SIZE);
+        if (l < 0)
+                return false;
+        size_t i = 0;
+        for (const char* p = skipHTTPHeader(buf); isalnum(*p); ++p, ++i) {
+                bayeuxId[i] = *p;
+        }
+        bayeuxId[i] = '\0';
+        return bayeuxId[0];
+}
+
+bool PollThread::subscribe()
+{
+        int l = snprintf(buf2, SMARRESTBODY_SIZE, "81,%s,/%s\r\n", bayeuxId, chn);
+        l = snprintf(buf, SMARTREST_SIZE, getSmartRestFmt(), uri, l, buf2);
+        l = sock.sendAndReceive(buf, l, SMARTREST_SIZE);
+        return l>=0;
+}
+
+bool PollThread::connect()
+{
+        int l = snprintf(buf2, SMARRESTBODY_SIZE, "83,%s\r\n", bayeuxId);
+        l = snprintf(buf, SMARTREST_SIZE, getSmartRestFmt(), uri, l, buf2);
+        l = sock.sendAndReceive(buf, l, SMARTREST_SIZE);
+        return l>=0;
+}
+
+void PollThread::threadFunc()
+{
+        uint8_t state = 1;
+        aInfo("Poll thread: %p\n", Thread::gettid());
+        while (true) {
+                switch (state) {
+                case 1: if (!handshake()) {
+                                aCritical("Poll: handshake fail!\n");
+                                break;
+                        }
+                case 2: if(!subscribe()) {
+                                aCritical("Poll: subscribe fail!\n");
+                                state = 1;
+                                break;
+                        }
+                case 3: if(!connect()) {
+                                aCritical("Poll: connect fail!\n");
+                                state = 1;
+                                break;
+                        }
+                default: parser.handleControlMessage(buf);
+                        if (parser.getBayeuxAdvice() == BA_HANDSHAKE)
+                                state = 1;
+                        else
+                                state = 3;
+                }
+        }
+}
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/operation/PollThread.h	Mon Apr 27 10:50:21 2015 +0000
@@ -0,0 +1,36 @@
+#ifndef POLLTHREAD_H
+#define POLLTHREAD_H
+#include "SmartRestSocket.h"
+#include "Operation.h"
+#include "SmartRestConf.h"
+#include "ControlParser.h"
+
+class PollThread
+{
+public:
+        PollThread(OperationPool& pool, MDMSerial& m,
+                ConfigurationSynchronization& configSync):
+                sock(m), parser(pool, configSync),
+                thread(PollThread::threadWrapper, this) {
+                strncpy(uri, "/devicecontrol/notifications", sizeof(uri));
+                sock.set_blocking(true);
+        }
+        virtual ~PollThread() { sock.close(); }
+        bool handshake();
+        bool subscribe();
+        bool connect();
+        void setChannel(long channel) { snprintf(chn, sizeof(chn), "/%ld", channel); }
+        void threadFunc();
+        static void threadWrapper(const void *p) { ((PollThread*)p)->threadFunc(); }
+private:
+        char chn[16];
+        char uri[30];
+        char bayeuxId[50];
+        char buf[SMARTREST_SIZE];
+        char buf2[SMARRESTBODY_SIZE];
+        SmartRestSocket sock;
+        ControlParser parser;
+        Thread thread;
+};
+
+#endif /* POLLTHREAD_H */
--- a/operation/PollingThread.cpp	Wed Apr 22 11:22:25 2015 +0000
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,65 +0,0 @@
-#include <stdio.h>
-#include <ctype.h>
-#include "PollingThread.h"
-#include "lex.h"
-#include "logging.h"
-
-bool PollingThread::handshake()
-{
-        int l = snprintf(buf2, SMARRESTBODY_SIZE, "%s", "80\r\n");
-        l = snprintf(buf, SMARTREST_SIZE, getSmartRestFmt(), uri, l, buf2);
-        l = sock.sendAndReceive(buf, l, SMARTREST_SIZE);
-        if (l < 0)
-                return false;
-        size_t i = 0;
-        for (const char* p = skipHTTPHeader(buf); isalnum(*p); ++p, ++i) {
-                bayeuxId[i] = *p;
-        }
-        bayeuxId[i] = '\0';
-        return bayeuxId[0];
-}
-
-bool PollingThread::subscribe()
-{
-        int l = snprintf(buf2, SMARRESTBODY_SIZE, "81,%s,/%s\r\n", bayeuxId, chn);
-        l = snprintf(buf, SMARTREST_SIZE, getSmartRestFmt(), uri, l, buf2);
-        l = sock.sendAndReceive(buf, l, SMARTREST_SIZE);
-        return l>=0;
-}
-
-bool PollingThread::connect()
-{
-        int l = snprintf(buf2, SMARRESTBODY_SIZE, "83,%s\r\n", bayeuxId);
-        l = snprintf(buf, SMARTREST_SIZE, getSmartRestFmt(), uri, l, buf2);
-        l = sock.sendAndReceive(buf, l, SMARTREST_SIZE);
-        return l>=0;
-}
-
-void PollingThread::threadFunc()
-{
-        uint8_t state = 1;
-        aInfo("Polling thread: %p\n", Thread::gettid());
-        while (true) {
-                switch (state) {
-                case 1: if (!handshake()) {
-                                aCritical("Poll: handshake fail!\n");
-                                break;
-                        }
-                case 2: if(!subscribe()) {
-                                aCritical("Poll: subscribe fail!\n");
-                                state = 1;
-                                break;
-                        }
-                case 3: if(!connect()) {
-                                aCritical("Poll: connect fail!\n");
-                                state = 1;
-                                break;
-                        }
-                default: parser.handleControlMessage(buf);
-                        if (parser.getBayeuxAdvice() == BA_HANDSHAKE)
-                                state = 1;
-                        else
-                                state = 3;
-                }
-        }
-}
\ No newline at end of file
--- a/operation/PollingThread.h	Wed Apr 22 11:22:25 2015 +0000
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,36 +0,0 @@
-#ifndef POLLINGTHREAD_H
-#define POLLINGTHREAD_H
-#include "SmartRestSocket.h"
-#include "Operation.h"
-#include "SmartRestConf.h"
-#include "ControlParser.h"
-
-class PollingThread
-{
-public:
-        PollingThread(OperationPool& pool, MDMSerial& m,
-                LCDDisplay& lcdDisplay, ConfigurationSynchronization& configSync):
-                sock(m), parser(pool, lcdDisplay, configSync),
-                thread(PollingThread::threadWrapper, this) {
-                strncpy(uri, "/devicecontrol/notifications", sizeof(uri));
-                sock.set_blocking(true);
-        }
-        virtual ~PollingThread() { sock.close(); }
-        bool handshake();
-        bool subscribe();
-        bool connect();
-        void setChannel(long channel) { snprintf(chn, sizeof(chn), "/%ld", channel); }
-        void threadFunc();
-        static void threadWrapper(const void *p) { ((PollingThread*)p)->threadFunc(); }
-private:
-        char chn[16];
-        char uri[30];
-        char bayeuxId[50];
-        char buf[SMARTREST_SIZE];
-        char buf2[SMARRESTBODY_SIZE];
-        SmartRestSocket sock;
-        ControlParser parser;
-        Thread thread;
-};
-
-#endif /* POLLINGTHREAD_H */
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/util/dict.h	Mon Apr 27 10:50:21 2015 +0000
@@ -0,0 +1,65 @@
+#ifndef DICH_H
+#define DICH_H
+#include <string.h>
+#define MAX_KEY_LEN 50
+#define MAX_VALUE_LEN 50
+#define MAX_ITEM_SIZE 5
+
+class Dict
+{
+public:
+        struct Item {
+                char key[MAX_KEY_LEN];
+                char value[MAX_VALUE_LEN];
+        };
+
+        Dict(): count(0) {}
+
+        const Item* at(const size_t i) const {
+                if (i < count) return &items[i];
+                else return NULL;
+        }
+
+        const Item* get(const char *k) const {
+                size_t i = find(k);
+                if (i < count)
+                        return &items[i];
+                else
+                        return NULL;
+        }
+
+        const Item* set(const char *k, const char *v) {
+                size_t i = find(k);
+                if (i < count) {
+                        strncpy(items[i].value, v, MAX_VALUE_LEN);
+                        return &items[i];
+                } else if (count < MAX_ITEM_SIZE){
+                        ++count;
+                        strncpy(items[i].key, k, MAX_KEY_LEN);
+                        strncpy(items[i].value, v, MAX_VALUE_LEN);
+                        return &items[i];
+                } else
+                        return NULL;
+        }
+
+        size_t maxSize() const { return MAX_ITEM_SIZE; }
+        size_t maxKeyLen() const { return MAX_KEY_LEN; }
+        size_t maxValueLen() const { return MAX_VALUE_LEN; }
+        size_t size() const { return count; }
+        bool empty() const { return count==0; }
+        bool full() const { return count == MAX_ITEM_SIZE; }
+        virtual ~Dict() {}
+protected:
+        size_t find(const char* k) const {
+                for (size_t i = 0; i < count; ++i) {
+                        if (strncmp(items[i].key, k, MAX_KEY_LEN) == 0)
+                                return i;
+                }
+                return count;
+        }
+private:
+        Item items[MAX_ITEM_SIZE];
+        size_t count;
+};
+
+#endif /* DICH_H */