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:
Thu May 07 09:57:55 2015 +0000
Parent:
98:9f2de96941c4
Child:
100:47ea098f8a47
Commit message:
prepare for v2.1rc3.

Changed in this revision

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/ConfigParser.cpp Show annotated file Show diff for this revision Revisions of this file
config/ConfigParser.h Show annotated file Show diff for this revision Revisions of this file
config/ConfigSync.cpp Show annotated file Show diff for this revision Revisions of this file
config/ConfigSync.h Show annotated file Show diff for this revision Revisions of this file
config/ConfigurationSynchronization.cpp Show diff for this revision Revisions of this file
config/ConfigurationSynchronization.h Show diff for this revision Revisions of this file
io/DeviceMemory.cpp Show annotated file Show diff for this revision Revisions of this file
io/GPSTracker.cpp Show annotated file Show diff for this revision Revisions of this file
io/GPSTracker.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.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
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/OperationSupport.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/ReportThread.cpp Show annotated file Show diff for this revision Revisions of this file
util/AbstractReporter.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
util/SmartRestSocket.cpp Show annotated file Show diff for this revision Revisions of this file
util/SmartRestSocket.h Show annotated file Show diff for this revision Revisions of this file
util/dict.h Show annotated file Show diff for this revision Revisions of this file
util/lex.cpp Show annotated file Show diff for this revision Revisions of this file
util/lex.h Show annotated file Show diff for this revision Revisions of this file
--- a/MbedAgent.cpp	Mon Apr 27 13:30:21 2015 +0000
+++ b/MbedAgent.cpp	Thu May 07 09:57:55 2015 +0000
@@ -1,20 +1,19 @@
 #include "MbedAgent.h"
-#include "rtos.h"
 #include "LCDDisplay.h"
 #include "logging.h"
 #include "watchdog.h"
 
-MbedAgent::MbedAgent(GPSI2C& gps, DeviceInfo& deviceInfo):
+MbedAgent::MbedAgent(DeviceInfo& deviceInfo):
     _deviceId(0),
     _client(),
     _bootstrap(_client, deviceInfo),
     _integration(_client, _tpl, _deviceId, deviceInfo),
-    _configurationSynchronization(_client, _tpl, _deviceId),
+    _configSync(_client, _tpl, _deviceId),
     _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),
+    _locationUpdate(_client, _tpl, _deviceId, deviceInfo),
     pool(),
     _operationSupport(_client, _tpl, _deviceId, pool)
 {
@@ -27,7 +26,7 @@
         LCDDisplay::inst().setLines("Integrate init fail");
         flag = false;
     }
-    if (!_configurationSynchronization.init()) {
+    if (!_configSync.init()) {
         LCDDisplay::inst().setLines("ConfigSync init fail");
         flag = false;
     }
@@ -64,18 +63,18 @@
     if (!_bootstrap.setUpCredentials())
         return -1;
     setAuth(_bootstrap.username(), _bootstrap.password());
-    aInfo("Set auth: %s:%s (%s)\n", getUsername(), getPassword(), getAuthStr());
+    aInfo("Set auth: %s:%s (%s)\n", srUsername, srPassword, srAuthStr);
 
-    Thread::wait(5000);
+    Thread::wait(2000);
 
-    LCDDisplay::inst().setLines("Connect to Cloud", getHost());
+    LCDDisplay::inst().setLines("Connect to Cloud", srHost);
     if (!_integration.integrate()) {
         return -2;
     }
-    setIdentifier(_client.getIdentifier());
-    aInfo("Set id: %s\n", getIdentifier());
+    setX_ID(_client.getIdentifier());
+    aInfo("Set id: %s\n", srX_ID);
 
-    if (!_configurationSynchronization.integrate()) {
+    if (!_configSync.integrate()) {
         return -3;
     }
     return 0;
@@ -83,20 +82,20 @@
 
 void MbedAgent::loop()
 {
-    ReportThread reportThread(pool);
+//    ReportThread reportThread(pool);
     _operationSupport.run();
-    PollThread pollThread(pool, _configurationSynchronization);
-    pollThread.setChannel(_deviceId);
+//    PollThread pollThread(pool, _configSync);
+//    pollThread.setChannel(_deviceId);
 
     Watchdog wdt;
     wdt.kick(60.0);    // set a 60.0 seconds timeout on watchdog hardware timer
     while (true) {
-        _configurationSynchronization.run();
-        _analogMeasurement.run();
-        _signalQualityMeasurement.run();
-        _temperatureMeasurement.run();
-        _accelerationMeasurement.run();
-        _locationUpdate.run();
+        _configSync.run();
+//        _analogMeasurement.run();
+//        _signalQualityMeasurement.run();
+//        _temperatureMeasurement.run();
+//        _accelerationMeasurement.run();
+//        _locationUpdate.run();
 //        Thread::wait(30000);
         wdt.kick();    // reset watchdog timer
     }
--- a/MbedAgent.h	Mon Apr 27 13:30:21 2015 +0000
+++ b/MbedAgent.h	Thu May 07 09:57:55 2015 +0000
@@ -7,7 +7,7 @@
 #include "DeviceInfo.h"
 #include "DeviceBootstrap.h"
 #include "DeviceIntegration.h"
-#include "ConfigurationSynchronization.h"
+#include "ConfigSync.h"
 #include "SignalQualityMeasurement.h"
 #include "TemperatureMeasurement.h"
 #include "AccelerationMeasurement.h"
@@ -21,21 +21,19 @@
 class MbedAgent
 {
 public:
-    MbedAgent(GPSI2C&, DeviceInfo&);
+    MbedAgent(DeviceInfo&);
 
     bool init();
     int run();
     void loop();
 
-protected:
-    
 private:
     long _deviceId;
     SmartRest _client;
     SmartRestTemplate _tpl;
     DeviceBootstrap _bootstrap;
     DeviceIntegration _integration;
-    ConfigurationSynchronization _configurationSynchronization;
+    ConfigSync _configSync;
     SignalQualityMeasurement _signalQualityMeasurement;
     TemperatureMeasurement _temperatureMeasurement;
     AccelerationMeasurement _accelerationMeasurement;
--- a/MbedSmartRest.lib	Mon Apr 27 13:30:21 2015 +0000
+++ b/MbedSmartRest.lib	Thu May 07 09:57:55 2015 +0000
@@ -1,1 +1,1 @@
-http://developer.mbed.org/users/xinlei/code/MbedSmartRest/#0529d6779ab1
+http://developer.mbed.org/users/xinlei/code/MbedSmartRest/#11fd6fd14c28
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/config/ConfigParser.cpp	Thu May 07 09:57:55 2015 +0000
@@ -0,0 +1,80 @@
+#include <string.h>
+#include "ConfigParser.h"
+#include "logging.h"
+
+bool ConfigParser::parse(const char *buf)
+{
+        if (buf == NULL) return false;
+        Token tok;
+        ptrPF = &ConfigParser::parseKey;
+        parseOK = true;
+        for (const char*p = buf; *p;) {
+                p = lexConfig(p, tok);
+                (this->*ptrPF)(tok);
+        }
+        return parseOK;
+}
+
+void ConfigParser::parseKey(Token& tok)
+{
+        if (tok.type == Token::STRING) {
+                memset(key, 0, MAX_KEY_LEN);
+                size_t num = tok.len<MAX_VALUE_LEN ? tok.len : MAX_VALUE_LEN;
+                strncpy(key, tok.p, num);
+                ptrPF = &ConfigParser::parseAssignOp;
+        } else {
+                parseError(tok);
+        }
+}
+
+void ConfigParser::parseAssignOp(Token& tok)
+{
+        if (tok.type == Token::ASSIGN) {
+                ptrPF = &ConfigParser::parseValue;
+        } else {
+                parseError(tok);
+        }
+}
+
+void ConfigParser::parseValue(Token& tok)
+{
+        if (tok.type != Token::NONE) {
+                if (strncmp(key, "interval", MAX_KEY_LEN) == 0 &&
+                    tok.type != Token::INT) {
+                        parseError(tok);
+                } else {
+                        memset(value, 0, MAX_VALUE_LEN);
+                        size_t num = tok.len<MAX_VALUE_LEN ? tok.len : MAX_VALUE_LEN;
+                        strncpy(value, tok.p, num);
+                        dict.set(key, value);
+                        ptrPF = &ConfigParser::parseSemiColon;
+                }
+        } else {
+                parseError(tok);
+        }
+}
+
+void ConfigParser::parseSemiColon(Token& tok)
+{
+        if (tok.type == Token::SEMICOLON) {
+                ptrPF = &ConfigParser::parseKey;
+        } else {
+                parseError(tok);
+        }
+}
+
+void ConfigParser::parseError(Token& tok)
+{
+        parseOK = false;
+        aError("(%d) %.*s\n", tok.type, (int)tok.len, tok.p);
+        parseRecover(tok);
+}
+
+void ConfigParser::parseRecover(Token& tok)
+{
+        if (tok.type == Token::SEMICOLON) {
+                ptrPF = &ConfigParser::parseKey;
+        } else {
+                ptrPF = &ConfigParser::parseRecover;
+        }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/config/ConfigParser.h	Thu May 07 09:57:55 2015 +0000
@@ -0,0 +1,28 @@
+#ifndef CONFIGPARSER_H
+#define CONFIGPARSER_H
+#include "lex.h"
+#include "dict.h"
+
+class ConfigParser
+{
+public:
+        ConfigParser(Dict& d) : dict(d), parseOK(true) {}
+        virtual ~ConfigParser() {}
+        bool parse(const char*);
+protected:
+        void parseKey(Token&);
+        void parseAssignOp(Token&);
+        void parseValue(Token&);
+        void parseSemiColon(Token&);
+        void parseError(Token&);
+        void parseRecover(Token&);
+private:
+        typedef void (ConfigParser::*PtrParseFunc) (Token&);
+        Dict& dict;
+        bool parseOK;
+        PtrParseFunc ptrPF;
+        char key[MAX_KEY_LEN];
+        char value[MAX_VALUE_LEN];
+};
+
+#endif /* CONFIGPARSER_H */
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/config/ConfigSync.cpp	Thu May 07 09:57:55 2015 +0000
@@ -0,0 +1,145 @@
+#include <stdio.h>
+#include "ConfigSync.h"
+#include "DeviceMemory.h"
+#include "ComposedRecord.h"
+#include "CharValue.h"
+#include "IntegerValue.h"
+#include "logging.h"
+
+ConfigSync::ConfigSync(
+    AbstractSmartRest& client, SmartRestTemplate& tpl,
+    long& deviceId) :
+    _init (false),
+    _changed (false),
+    _tpl(tpl),
+    _client(client),
+    _deviceId(deviceId),
+    _deviceConfiguration(),
+    _configurationProperties(_deviceConfiguration)
+{
+}
+
+bool ConfigSync::init()
+{
+    if (_init)
+        return false;
+    
+    // Update Configuration
+    // Usage: 130,<DEVICE/ID>,<CONFIG/STRING>,<RESPONSIBILITY>
+    if (!_tpl.add("10,130,PUT,/inventory/managedObjects/%%,application/vnd.com.nsn.cumulocity.managedObject+json,application/vnd.com.nsn.cumulocity.managedObject+json,%%,UNSIGNED STRING NUMBER,\"{\"\"c8y_Configuration\"\":{\"\"config\"\":\"\"%%\"\"},\"\"c8y_RequiredAvailability\"\":{ \"\"responseInterval\"\":%%}}\"\r\n"))
+        return false;
+
+    _init = true;
+    return true;
+}
+
+bool ConfigSync::integrate()
+{
+    if ((!loadConfiguration()) || (!_configurationProperties.validateProperties())) {
+        if ((!_configurationProperties.resetConfiguration()) || (!updateDeviceObject()) || (!saveConfiguration()))
+            return false;
+    } else {
+        if (!updateDeviceObject())
+            return false;
+    }
+    return true;
+}
+
+bool ConfigSync::run()
+{
+    if (!_changed)
+        return true;
+
+    if ((!updateDeviceObject()) || (!saveConfiguration()))
+        return false;
+    
+    _changed = false;
+    return true;
+}
+
+bool ConfigSync::updateConfiguration(const char *cfg)
+{
+    if (!_deviceConfiguration.read(cfg)) {
+        aError("Read device config.\n");
+        return false;
+    }
+    
+    if (!_configurationProperties.validateProperties()) {
+        loadConfiguration();
+        return false;
+    }
+    
+    _changed = true;
+    return true;
+}
+
+bool ConfigSync::updateDeviceObject()
+{
+    char buf[256];
+    
+    if (!_deviceConfiguration.write(buf, sizeof(buf))) {
+        aError("Unable to write config.\n");
+        return false;
+    }
+
+    ComposedRecord record;
+    ParsedRecord received;
+
+    IntegerValue msgId(130);
+    IntegerValue deviceId(_deviceId);
+    CharValue config(buf);
+    IntegerValue responsibility(_configurationProperties.readInterval());
+    if (!record.add(msgId) || !record.add(deviceId) || !record.add(config) || !record.add(responsibility)) {
+        return false;
+    }
+    
+    if (_client.send(record) != SMARTREST_SUCCESS) {
+        _client.stop();
+        return false;
+    }
+    
+    if (_client.receive(received) != SMARTREST_SUCCESS) {
+        _client.stop();
+        return false;
+    }
+    _client.stop();
+
+    if (received.values() != 3) {
+        aError("Invalid config, %d (3) values received.\n", received.values());
+        return false;
+    } else if (received.value(0).integerValue() != 201) {
+        aError("updateDeviceObject: Message ID %ld .\n", received.value(0).integerValue());
+        return false;
+    }
+    return true;
+}
+
+bool ConfigSync::loadConfiguration()
+{
+    char buf[256];
+    
+    if (!::loadConfiguration(buf, sizeof(buf))) {
+        aError("Load device config.\n");
+        return false;
+    }
+    if (!_deviceConfiguration.read(buf)) {
+        aError("Read device config.\n");
+        return false;
+    }
+    return true;
+}
+
+bool ConfigSync::saveConfiguration()
+{
+    char buf[256];
+    
+    if (!_deviceConfiguration.write(buf, sizeof(buf))) {
+        aError("Write device config.\n");
+        return false;
+    }
+    if (!::saveConfiguration(buf)) {
+        aError("Save device config.\n");
+        return false;
+    }
+    return true;
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/config/ConfigSync.h	Thu May 07 09:57:55 2015 +0000
@@ -0,0 +1,34 @@
+#ifndef CONFIGURATIONSYNCHRONIZATION_H
+#define CONFIGURATIONSYNCHRONIZATION_H
+
+#include "AbstractSmartRest.h"
+#include "SmartRestTemplate.h"
+#include "ConfigurationProperties.h"
+
+class ConfigSync
+{
+public:
+    ConfigSync(AbstractSmartRest&, SmartRestTemplate&, long&);
+    
+    bool init();
+    bool integrate();
+    bool run();
+    
+    bool updateConfiguration(const char*);
+
+protected:
+    bool updateDeviceObject();
+    bool loadConfiguration();
+    bool saveConfiguration();
+
+private:
+    bool _init;
+    bool _changed;
+    SmartRestTemplate& _tpl;
+    AbstractSmartRest& _client;
+    long& _deviceId;
+    DeviceConfiguration _deviceConfiguration;
+    ConfigurationProperties _configurationProperties;
+};
+
+#endif
\ No newline at end of file
--- a/config/ConfigurationSynchronization.cpp	Mon Apr 27 13:30:21 2015 +0000
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,146 +0,0 @@
-#include <stdio.h>
-#include "ConfigurationSynchronization.h"
-#include "DeviceMemory.h"
-#include "ComposedRecord.h"
-#include "CharValue.h"
-#include "IntegerValue.h"
-#include "logging.h"
-
-ConfigurationSynchronization::ConfigurationSynchronization(
-    AbstractSmartRest& client, SmartRestTemplate& tpl,
-    long& deviceId) :
-    _init (false),
-    _changed (false),
-    _tpl(tpl),
-    _client(client),
-    _deviceId(deviceId),
-    _deviceConfiguration(),
-    _configurationProperties(_deviceConfiguration)
-{
-}
-
-bool ConfigurationSynchronization::init()
-{
-    if (_init)
-        return false;
-    
-    // Update Configuration
-    // Usage: 130,<DEVICE/ID>,<CONFIG/STRING>,<RESPONSIBILITY>
-    if (!_tpl.add("10,130,PUT,/inventory/managedObjects/%%,application/vnd.com.nsn.cumulocity.managedObject+json,application/vnd.com.nsn.cumulocity.managedObject+json,%%,UNSIGNED STRING NUMBER,\"{\"\"c8y_Configuration\"\":{\"\"config\"\":\"\"%%\"\"},\"\"c8y_RequiredAvailability\"\":{ \"\"responseInterval\"\":%%}}\"\r\n"))
-        return false;
-
-    _init = true;
-    return true;
-}
-
-bool ConfigurationSynchronization::integrate()
-{
-    if ((!loadConfiguration()) || (!_configurationProperties.validateProperties())) {
-        if ((!_configurationProperties.resetConfiguration()) || (!updateDeviceObject()) || (!saveConfiguration()))
-            return false;
-    } else {
-        if (!updateDeviceObject())
-            return false;
-    }
-
-    return true;
-}
-
-bool ConfigurationSynchronization::run()
-{
-    if (!_changed)
-        return true;
-
-    if ((!updateDeviceObject()) || (!saveConfiguration()))
-        return false;
-    
-    _changed = false;
-    return true;
-}
-
-bool ConfigurationSynchronization::updateConfiguration(const char *cfg)
-{
-    if (!_deviceConfiguration.read(cfg)) {
-        aError("Read device config.\n");
-        return false;
-    }
-    
-    if (!_configurationProperties.validateProperties()) {
-        loadConfiguration();
-        return false;
-    }
-    
-    _changed = true;
-    return true;
-}
-
-bool ConfigurationSynchronization::updateDeviceObject()
-{
-    char buf[256];
-    
-    if (!_deviceConfiguration.write(buf, sizeof(buf))) {
-        aError("Unable to write config.\n");
-        return false;
-    }
-
-    ComposedRecord record;
-    ParsedRecord received;
-
-    IntegerValue msgId(130);
-    IntegerValue deviceId(_deviceId);
-    CharValue config(buf);
-    IntegerValue responsibility(_configurationProperties.readInterval());
-    if (!record.add(msgId) || !record.add(deviceId) || !record.add(config) || !record.add(responsibility)) {
-        return false;
-    }
-    
-    if (_client.send(record) != SMARTREST_SUCCESS) {
-        _client.stop();
-        return false;
-    }
-    
-    if (_client.receive(received) != SMARTREST_SUCCESS) {
-        _client.stop();
-        return false;
-    }
-    _client.stop();
-
-    if (received.values() != 3) {
-        aError("Invalid config, %d (3) values received.\n", received.values());
-        return false;
-    } else if (received.value(0).integerValue() != 201) {
-        aError("updateDeviceObject: Message ID %ld .\n", received.value(0).integerValue());
-        return false;
-    }
-    return true;
-}
-
-bool ConfigurationSynchronization::loadConfiguration()
-{
-    char buf[256];
-    
-    if (!::loadConfiguration(buf, sizeof(buf))) {
-        aError("Load device config.\n");
-        return false;
-    }
-    if (!_deviceConfiguration.read(buf)) {
-        aError("Read device config.\n");
-        return false;
-    }
-    return true;
-}
-
-bool ConfigurationSynchronization::saveConfiguration()
-{
-    char buf[256];
-    
-    if (!_deviceConfiguration.write(buf, sizeof(buf))) {
-        aError("Write device config.\n");
-        return false;
-    }
-    if (!::saveConfiguration(buf)) {
-        aError("Save device config.\n");
-        return false;
-    }
-    return true;
-}
--- a/config/ConfigurationSynchronization.h	Mon Apr 27 13:30:21 2015 +0000
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,34 +0,0 @@
-#ifndef CONFIGURATIONSYNCHRONIZATION_H
-#define CONFIGURATIONSYNCHRONIZATION_H
-
-#include "AbstractSmartRest.h"
-#include "SmartRestTemplate.h"
-#include "ConfigurationProperties.h"
-
-class ConfigurationSynchronization
-{
-public:
-    ConfigurationSynchronization(AbstractSmartRest&, SmartRestTemplate&, long&);
-    
-    bool init();
-    bool integrate();
-    bool run();
-    
-    bool updateConfiguration(const char*);
-
-protected:
-    bool updateDeviceObject();
-    bool loadConfiguration();
-    bool saveConfiguration();
-
-private:
-    bool _init;
-    bool _changed;
-    SmartRestTemplate& _tpl;
-    AbstractSmartRest& _client;
-    long& _deviceId;
-    DeviceConfiguration _deviceConfiguration;
-    ConfigurationProperties _configurationProperties;
-};
-
-#endif
\ No newline at end of file
--- a/io/DeviceMemory.cpp	Mon Apr 27 13:30:21 2015 +0000
+++ b/io/DeviceMemory.cpp	Thu May 07 09:57:55 2015 +0000
@@ -6,54 +6,50 @@
 #define CONFIGURATION_FILE "002_CONFIGURATION"
 extern MDMSerial *pMdm;
 
-bool loadPlatformCredentials(char *username, char *password, size_t len)
+bool loadCredentials(char *username, char *password, size_t len)
 {
-    char buffer[len*2+3]; 
+    char buffer[len*2+3];
     int res = pMdm->readFile(PLATFORM_CREDENTIALS_FILE, buffer, sizeof(buffer));
     if (res < 0)
         return false;
-
-    buffer[(size_t)res] = '\0';
-    int len2=0;
-    sscanf(buffer, "%s\n%s\n%n", username, password, &len2);
-    return res == len2;
+    else {
+        buffer[res] = 0;
+        int len2 = sscanf(buffer, "%s\n%s\n", username, password);
+        return res==len2;
+    }
 }
 
-bool resetPlatformCredentials()
+bool delCredentials()
 {
     return pMdm->delFile(PLATFORM_CREDENTIALS_FILE);
 }
 
-bool savePlatformCredentials(char *username, char *password, size_t len)
+bool saveCredentials(char *username, char *password, size_t len)
 {
     char buffer[len*2+3]; 
     int res = snprintf(buffer, sizeof(buffer), "%s\n%s\n", username, password);
-    if (res<0 || res>=sizeof(buffer))
-        return false;
-
-    return (resetPlatformCredentials() && res==pMdm->writeFile(PLATFORM_CREDENTIALS_FILE, buffer, res));
+    delCredentials();
+    return pMdm->writeFile(PLATFORM_CREDENTIALS_FILE, buffer, res)==res;
 }
 
-
-
-bool loadConfiguration(char *cfg, size_t len)
+bool loadConfigFile(char *cfg, size_t len)
 {
     int res = pMdm->readFile(CONFIGURATION_FILE, cfg, len);
     if (res < 0)
         return false;
-    
-    cfg[(size_t)res] = '\0';
-    return true;
+    else {
+        cfg[res] = 0;
+        return true;
+    }
 }
 
-bool resetConfiguration()
+bool delConfigFile()
 {
     return pMdm->delFile(CONFIGURATION_FILE);
 }
 
-bool saveConfiguration(char *cfg)
+bool saveConfigFile(char *cfg, size_t len)
 {
-    size_t len = strlen(cfg);
-    return (resetConfiguration() && pMdm->writeFile(CONFIGURATION_FILE, cfg, len)==len);
+    delConfigFile();
+    return pMdm->writeFile(CONFIGURATION_FILE, cfg, len)==len;
 }
-
--- a/io/GPSTracker.cpp	Mon Apr 27 13:30:21 2015 +0000
+++ b/io/GPSTracker.cpp	Thu May 07 09:57:55 2015 +0000
@@ -3,11 +3,12 @@
 #include "GPSTracker.h"
 #include "logging.h"
 
-GPSTracker::GPSTracker(GPSI2C& gps) :
-    _gps(gps),
+GPSTracker::GPSTracker() :
+    _gps(),
     _thread(GPSTracker::thread_func, this),
     _positionSet(false)
 {
+    _gps.init();
 }
 
 bool GPSTracker::position(GPSTracker::Position *position)
--- a/io/GPSTracker.h	Mon Apr 27 13:30:21 2015 +0000
+++ b/io/GPSTracker.h	Thu May 07 09:57:55 2015 +0000
@@ -15,7 +15,7 @@
      * Initialize a new GPSTracker object.
      * @param gps a previously initialized instance of the GPSI2C class
      */
-    GPSTracker(GPSI2C&);
+    GPSTracker();
     
     typedef struct {
         double altitude;  // altitude  meters
--- a/main.cpp	Mon Apr 27 13:30:21 2015 +0000
+++ b/main.cpp	Thu May 07 09:57:55 2015 +0000
@@ -57,18 +57,12 @@
     InterruptIn joystickUp(A2);
     InterruptIn joystickDown(A3);
     MDMParser::DevStatus devStatus;
-    GPSI2C gps;
-    LCDDisplay::inst().setLines("Mbed Agent V2.1rc2", getHost());
+    LCDDisplay::inst().setLines("Mbed Agent V2.1rc2", srHost);
     if (!mdm.init(SIM_PIN, &devStatus)) {
         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::inst().setLines("GPS Init Failure");
-        mdm.disconnect();
-        mdm.powerOff();
-        return 2;
     }
     joystickUp.rise(&enableDebug);
     joystickDown.rise(&disableDebug);
@@ -115,7 +109,7 @@
 
     {
         DeviceInfo deviceInfo(devStatus);
-        MbedAgent agent(gps, deviceInfo);
+        MbedAgent agent(deviceInfo);
 
         LCDDisplay::inst().setLines("Agent Init");
         if (!agent.init()) {
@@ -129,7 +123,7 @@
             ret = agent.run();
             if (ret == 0) {
                 char status[27];
-                const char* user= getUsername();
+                const char* user= srUsername;
                 int len = strchr(user, '/')-user+sizeof("Tenant: ");
                 len = len <= 27 ? len : 27;
                 snprintf(status, len, "Tenant: %s", user);
--- a/measurement/AccelerationMeasurement.h	Mon Apr 27 13:30:21 2015 +0000
+++ b/measurement/AccelerationMeasurement.h	Thu May 07 09:57:55 2015 +0000
@@ -16,7 +16,6 @@
 
 private:
     bool _init, _test;
-    long& _deviceId;
     SmartRestTemplate& _tpl;
     AbstractSmartRest& _client;
     MMA7660 _sensor;
--- a/measurement/LocationUpdate.cpp	Mon Apr 27 13:30:21 2015 +0000
+++ b/measurement/LocationUpdate.cpp	Thu May 07 09:57:55 2015 +0000
@@ -12,11 +12,11 @@
 #define TIME_LIMIT_LOC 900               
 
 LocationUpdate::LocationUpdate(AbstractSmartRest& client, SmartRestTemplate& tpl,
-    long& deviceId, GPSI2C& gps, DeviceInfo& deviceInfo) :
+    long& deviceId, DeviceInfo& deviceInfo) :
     _deviceId(deviceId),
     _tpl(tpl),
     _client(client),
-    _gpsTracker(gps),
+    _gpsTracker(),
     _deviceInfo(deviceInfo)
 {
     _init = false;
--- a/measurement/LocationUpdate.h	Mon Apr 27 13:30:21 2015 +0000
+++ b/measurement/LocationUpdate.h	Thu May 07 09:57:55 2015 +0000
@@ -9,7 +9,7 @@
 class LocationUpdate
 {
 public:
-    LocationUpdate(AbstractSmartRest&, SmartRestTemplate&, long&, GPSI2C&, DeviceInfo&);
+    LocationUpdate(AbstractSmartRest&, SmartRestTemplate&, long&, DeviceInfo&);
     
     bool init();
     bool run();
--- a/operation/ControlParser.cpp	Mon Apr 27 13:30:21 2015 +0000
+++ b/operation/ControlParser.cpp	Thu May 07 09:57:55 2015 +0000
@@ -5,10 +5,11 @@
 #include "LCDDisplay.h"
 #include "logging.h"
 
-void ControlParser::handleControlMessage(const char *buf)
+void ControlParser::parse(const char *buf)
 {
         if (buf == NULL) return;
         const char *p = skipHTTPHeader(buf);
+        if (p == NULL) return;
         Token tok;
         ptrPF = &ControlParser::parseGetOp;
         do {
@@ -57,9 +58,11 @@
         if (tok.type == Token::STRING) {
                 if (strncmp(strPending, tok.p, tok.len)==0) {
                         Operation *p = opool.alloc();
-                        p->identifier = op.identifier;
-                        p->state = OPERATION_EXECUTING;
-                        opool.put(p);
+                        if (p) {
+                                p->identifier = op.identifier;
+                                p->state = OPERATION_EXECUTING;
+                                opool.put(p);
+                        }
                         ptrPF = &ControlParser::parseOpType;
                 } else {
                         parseError(tok);
@@ -135,6 +138,15 @@
 void ControlParser::parseBayeuxAdvice(Token& tok)
 {
         if (strncmp("86", tok.p, tok.len) == 0) {
+                ptrPF = &ControlParser::parseRowNumber;
+        } else {
+                parseError(tok);
+        }
+}
+
+void ControlParser::parseRowNumber(Token& tok)
+{
+        if (tok.type == Token::INT || tok.type == Token::NONE) {
                 ptrPF = &ControlParser::parseAdviceTimeout;
         } else {
                 parseError(tok);
@@ -157,19 +169,10 @@
 void ControlParser::parseAdviceInterval(Token& tok)
 {
         if (tok.type == Token::NONE) {
-                bayeuxInterval = -1;
-                ptrPF = &ControlParser::parseUnknownInt;
+                bayeuxInterval = 0;
+                ptrPF = &ControlParser::parseAdvicePolicy;
         } else if (tok.type == Token::INT) {
                 sscanf(tok.p, "%d", &bayeuxInterval);
-                ptrPF = &ControlParser::parseUnknownInt;
-        } else {
-                parseError(tok);
-        }
-}
-
-void ControlParser::parseUnknownInt(Token& tok)
-{
-        if (tok.type == Token::INT) {
                 ptrPF = &ControlParser::parseAdvicePolicy;
         } else {
                 parseError(tok);
@@ -196,7 +199,7 @@
 void ControlParser::parseError(Token& tok)
 {
         aError("(%d) %.*s\n", tok.type, (int)tok.len, tok.p);
-        ptrPF = &ControlParser::parseRecover;
+        parseRecover(tok);
 }
 
 void ControlParser::parseRecover(Token& tok)
--- a/operation/ControlParser.h	Mon Apr 27 13:30:21 2015 +0000
+++ b/operation/ControlParser.h	Thu May 07 09:57:55 2015 +0000
@@ -3,24 +3,22 @@
 #include "Operation.h"
 #include "lex.h"
 #include "DeviceFeedback.h"
-#include "ConfigurationSynchronization.h"
+#include "ConfigSync.h"
 
 enum BayeuxAdvice{ BA_RETRY, BA_HANDSHAKE, BA_NONE };
-class ControlParser;
-typedef void (ControlParser::*PtrParseFunc)(Token&);
 
 class ControlParser
 {
 public:
         ControlParser(OperationPool& pool, 
-                ConfigurationSynchronization& configSync): opType(0),
+                ConfigSync& configSync): opType(0),
                 bayeuxAdvice(BA_RETRY), bayeuxTimeout(-1), bayeuxInterval(0),
                 opool(pool), _configSync(configSync) {}
         virtual ~ControlParser() {}
         BayeuxAdvice getBayeuxAdvice() const { return bayeuxAdvice; }
         int getBayeuxInterval() const { return bayeuxInterval; }
         int getBayeuxTimeout() const { return bayeuxTimeout; }
-        void handleControlMessage(const char*);
+        void parse(const char*);
 protected:
         void parseAdviceInterval(Token& tok);
         void parseAdvicePolicy(Token& tok);
@@ -37,6 +35,7 @@
         void parseRecover(Token& tok);
         void parseUnknownInt(Token& tok);
 private:
+        typedef void (ControlParser::*PtrParseFunc)(Token&);
         unsigned short opType;
         Operation op;
         BayeuxAdvice bayeuxAdvice;
@@ -44,7 +43,7 @@
         int bayeuxInterval;
         PtrParseFunc ptrPF;
         OperationPool& opool;
-        ConfigurationSynchronization& _configSync;
+        ConfigSync& _configSync;
 };
 
 #endif /* CONTROLPARSER_H */
--- a/operation/OperationSupport.h	Mon Apr 27 13:30:21 2015 +0000
+++ b/operation/OperationSupport.h	Thu May 07 09:57:55 2015 +0000
@@ -8,9 +8,8 @@
 class OperationSupport
 {
 public:
-    OperationSupport(SmartRest& client, SmartRestTemplate& tpl,
-    long& deviceId, OperationPool& pool):
-    _init(false), _firstRun(true), _deviceId(deviceId), _tpl(tpl),
+    OperationSupport(SmartRest& client, SmartRestTemplate& tpl, OperationPool& pool):
+    _init(false), _firstRun(true), _tpl(tpl),
     _client(client), opool(pool) {}
     bool init();
     bool run();
@@ -23,7 +22,6 @@
 private:
     bool _init;
     bool _firstRun;
-    long& _deviceId;
     SmartRestTemplate& _tpl;
     SmartRest& _client;
     OperationPool& opool;
--- a/operation/PollThread.cpp	Mon Apr 27 13:30:21 2015 +0000
+++ b/operation/PollThread.cpp	Thu May 07 09:57:55 2015 +0000
@@ -7,7 +7,8 @@
 bool PollThread::handshake()
 {
         int l = snprintf(buf2, SMARRESTBODY_SIZE, "%s", "80\r\n");
-        l = snprintf(buf, SMARTREST_SIZE, getSmartRestFmt(), uri, l, buf2);
+        l = snprintf(buf, SMARTREST_SIZE, fmtSmartRest, uri, l, buf2);
+        sock.set_blocking(false);
         l = sock.sendAndReceive(buf, l, SMARTREST_SIZE);
         if (l < 0)
                 return false;
@@ -22,22 +23,24 @@
 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);
+        l = snprintf(buf, SMARTREST_SIZE, fmtSmartRest, uri, l, buf2);
+        sock.set_blocking(false);
+        l = sock.sendOnly(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 = snprintf(buf, SMARTREST_SIZE, fmtSmartRest, uri, l, buf2);
+        sock.set_blocking(true);
         l = sock.sendAndReceive(buf, l, SMARTREST_SIZE);
         return l>=0;
 }
 
 void PollThread::threadFunc()
 {
-        uint8_t state = 1;
+        unsigned short state = 1;
         aInfo("Poll thread: %p\n", Thread::gettid());
         while (true) {
                 switch (state) {
@@ -55,7 +58,7 @@
                                 state = 1;
                                 break;
                         }
-                default: parser.handleControlMessage(buf);
+                default: parser.parse(buf);
                         if (parser.getBayeuxAdvice() == BA_HANDSHAKE)
                                 state = 1;
                         else
--- a/operation/PollThread.h	Mon Apr 27 13:30:21 2015 +0000
+++ b/operation/PollThread.h	Thu May 07 09:57:55 2015 +0000
@@ -9,7 +9,7 @@
 {
 public:
         PollThread(OperationPool& pool,
-                ConfigurationSynchronization& configSync):
+                ConfigSync& configSync):
                 sock(), parser(pool, configSync),
                 thread(PollThread::threadWrapper, this) {
                 strncpy(uri, "/devicecontrol/notifications", sizeof(uri));
--- a/operation/ReportThread.cpp	Mon Apr 27 13:30:21 2015 +0000
+++ b/operation/ReportThread.cpp	Thu May 07 09:57:55 2015 +0000
@@ -5,6 +5,7 @@
 
 void ReportThread::threadFunc()
 {
+    sock.set_blocking(false);
     while (true) {
         osEvent e = ipool.get();
         if (e.status == osEventMail) {
@@ -25,7 +26,7 @@
                     break;
                 }
             }
-            l = snprintf(buf, sizeof(buf), getSmartRestFmt(), uri, l, buf2);
+            l = snprintf(buf, sizeof(buf), fmtSmartRest, uri, l, buf2);
             l = sock.sendOnly(buf, l);
             if (l < 0) {
                 aError("Report: <%ld, %s>\n", id, strOperationState(state));
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/util/AbstractReporter.h	Thu May 07 09:57:55 2015 +0000
@@ -0,0 +1,11 @@
+#ifndef ABSTRACTREPORTER_H
+#define ABSTRACTREPORTER_H
+
+class AbstractReporter
+{
+public:
+        virtual ~AbstractReporter() = 0;
+        virtual size_t read(const char*) = 0;
+};
+
+#endif /* ABSTRACTREPORTER_H */
\ No newline at end of file
--- a/util/SmartRestConf.cpp	Mon Apr 27 13:30:21 2015 +0000
+++ b/util/SmartRestConf.cpp	Thu May 07 09:57:55 2015 +0000
@@ -1,24 +1,21 @@
 #include <string.h>
 #include <stdio.h>
 #include "b64.h"
+#include "SmartRestConf.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 *srUsername = NULL;
+const char *srPassword = NULL;
+char srAuthStr[100] = {0};
+const char *srX_ID = "com_cumulocity_MbedAgent_1.5.2";
+const char *srHost = "developer.cumulocity.com";
 // const char *_host = "management.m2m-devicecloud.com"
-const int _port = 80;
+const int srPort = 80;
+long deviceID = 0;
 char fmtSmartRest[200] = {0};
 
-const char* getAuthStr()
-{
-        return _authStr;
-}
-
 void setAuthStr(const char* p1, const char* p2)
 {
-        memset(_authStr, 0, sizeof(_authStr));
+        memset(srAuthStr, 0, sizeof(srAuthStr));
         size_t ul = strlen(p1);
         size_t pl = strlen(p2);
         unsigned char input[3], output[5];
@@ -35,66 +32,41 @@
                 if ((inputOffset == 3) || (i == ul+pl)) {
                         b64_encode(input, inputOffset, output, 4);
                         output[4] = '\0';
-                        strcat(_authStr, (char*)output);
+                        strcat(srAuthStr, (char*)output);
                         inputOffset = 0;
                 }
         }
 }
 
-const char* getUsername()
-{
-        return _username;
-}
-
 void setUsername(const char* username)
 {
-        _username = username;
-}
-
-const char* getPassword()
-{
-        return _password;
+        srUsername = username;
 }
 
 void setPassword(const char* password)
 {
-        _password = password;
-}
-
-const char* getHost()
-{
-        return _host;
-}
-
-int getPort()
-{
-        return _port;
-}
-
-const char* getSmartRestFmt()
-{
-        return fmtSmartRest;
-}
-
-const char* getIdentifier()
-{
-        return _identifier;
+        srPassword = password;
 }
 
 void setSmartRestFmt()
 {
         const char fmt[] = "POST %%s HTTP/1.0\r\nHost: %s\r\nAuthorization: Basic %s\r\nX-Id: %s\r\nContent-Length: %%d\r\n\r\n%%s";
-        snprintf(fmtSmartRest, sizeof(fmtSmartRest), fmt, getHost(), getAuthStr(), getIdentifier());
+        snprintf(fmtSmartRest, sizeof(fmtSmartRest), fmt, srHost, srAuthStr, srX_ID);
 }
 
-void setIdentifier(const char* id)
+void setX_ID(const char* id)
 {
         if (id) {
-            _identifier = id;
+            srX_ID = id;
             setSmartRestFmt();
         }
 }
 
+void setDeviceID(long id)
+{
+        deviceID = id;
+}
+
 void setAuth(const char* username, const char* password)
 {
         if (username)
--- a/util/SmartRestConf.h	Mon Apr 27 13:30:21 2015 +0000
+++ b/util/SmartRestConf.h	Thu May 07 09:57:55 2015 +0000
@@ -3,16 +3,17 @@
 #define SMARTREST_SIZE 600
 #define SMARRESTBODY_SIZE 300
 
-const char* getHost();
-int getPort();
+extern const char *srUsername;
+extern const char *srPassword;
+extern char srAuthStr[];
+extern const char *srX_ID;
+extern const char *srHost;
+extern const int srPort;
+extern long deviceID;
+extern char fmtSmartRest[];
 
+void setDeviceID(long id);
 void setAuth(const char* username, const char* password);
-const char* getUsername();
-const char* getPassword();
-const char* getAuthStr();
-const char* getSmartRestFmt();
-
 void setIdentifier(const char* id);
-const char* getIdentifier();
 
 #endif /* SMARTRESTCONF_H */
--- a/util/SmartRestSocket.cpp	Mon Apr 27 13:30:21 2015 +0000
+++ b/util/SmartRestSocket.cpp	Thu May 07 09:57:55 2015 +0000
@@ -12,13 +12,13 @@
         ipLock.lock();
         for (size_t i = 0; i < 3; ++i) {
                 if (cachedIP[0] == '\0') {
-                        MDMParser::IP ip = pMdm->gethostbyname(getHost());
+                        MDMParser::IP ip = pMdm->gethostbyname(srHost);
                         if (ip == NOIP)
                                 continue;
                         const unsigned char *c = (const unsigned char*)&ip;
                         snprintf(cachedIP, sizeof(cachedIP), "%u.%u.%u.%u", c[3], c[2], c[1], c[0]);
                 }
-                n = TCPSocketConnection::connect(cachedIP, getPort());
+                n = TCPSocketConnection::connect(cachedIP, srPort);
                 if (n >= 0) {
                         break;
                 } else {
@@ -54,6 +54,8 @@
                 return -2;
         } else {
                 l = receive(buf, maxSize);
+                if (l >= 0 && l < maxSize)
+                        buf[l] = 0;
                 close();
                 return l;
         }
--- a/util/SmartRestSocket.h	Mon Apr 27 13:30:21 2015 +0000
+++ b/util/SmartRestSocket.h	Thu May 07 09:57:55 2015 +0000
@@ -3,15 +3,18 @@
 #include "TCPSocketConnection.h"
 #include "rtos.h"
 
-class SmartRestSocket : public TCPSocketConnection
+class SmartRestSocket : private TCPSocketConnection
 {
 public:
         SmartRestSocket(): TCPSocketConnection() {}
         virtual ~SmartRestSocket() {}
-        int connect();
         int sendOnly(char *buf, int size);
         int sendAndReceive(char *buf, int size, int maxSize);
+        void set_blocking(bool blocking, unsigned int timeout = 3000) { // timeout in milliseconds
+                Socket::set_blocking(blocking, timeout);
+        }
 private:
+        int connect();
         static char cachedIP[16];
         Mutex ipLock;
 };
--- a/util/dict.h	Mon Apr 27 13:30:21 2015 +0000
+++ b/util/dict.h	Thu May 07 09:57:55 2015 +0000
@@ -3,7 +3,7 @@
 #include <string.h>
 #define MAX_KEY_LEN 50
 #define MAX_VALUE_LEN 50
-#define MAX_ITEM_SIZE 5
+#define MAX_ITEM_SIZE 3
 
 class Dict
 {
@@ -43,11 +43,18 @@
         }
 
         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; }
+        void clear() { count = 0; }
+        size_t dump(char* buf) {
+                size_t l = 0;
+                for (size_t i = 0; i < count; ++i) {
+                        l + sprintf(buf+l, "%s=%s;", items[i].key, items[i].value);
+                }
+                buf[l] = 0;
+                return l;
+        }
         virtual ~Dict() {}
 protected:
         size_t find(const char* k) const {
--- a/util/lex.cpp	Mon Apr 27 13:30:21 2015 +0000
+++ b/util/lex.cpp	Thu May 07 09:57:55 2015 +0000
@@ -1,6 +1,7 @@
 #include <ctype.h>
 #include <string.h>
 #include "lex.h"
+#include "logging.h"
 
 const char* skipHTTPHeader(const char* p)
 {
@@ -100,6 +101,44 @@
         return p+j;
 }
 
+const char* lexConfig(const char* p, Token& tok)
+{
+        size_t j = 0;
+        for (; p[j] && !isgraph(p[j]); ++j);
+        size_t i = j;
+        tok.p = p+j;
+        if (p[i] == 0) {
+                tok.type = Token::NONE;
+        } else if (p[i] == '=') {
+                ++i;
+                tok.type = Token::ASSIGN;
+        } else if (p[i] == ';') {
+                ++i;
+                tok.type = Token::SEMICOLON;
+        } else if (isalpha(p[i])) {
+                for (++i; isalnum(p[i]); ++i);
+                tok.type = Token::STRING;
+        } else if (isdigit(p[i])) {
+                for (++i; isdigit(p[i]); ++i);
+                if (p[i] == '.') {
+                        for (++i; isdigit(p[i]); ++i);
+                        tok.type = Token::FLOAT;
+                } else if (isalnum(p[i])) {
+                        for (++i; isalnum(p[i]); ++i);
+                        tok.type = Token::STRING;
+                } else {
+                        tok.type = Token::INT;
+                }
+        } else {
+                aError("lexConfig: %c\n", p[i]);
+                for (++i; isgraph(p[i]); ++i);
+                tok.type = Token::ERROR;
+        }
+        tok.len = i - j;
+        for (; p[i] && !isgraph(p[i]); ++i);
+        return p+i;
+}
+
 size_t strncpyEscape(char* dest, const char *source, size_t num)
 {
         if (source == NULL) return 0;
--- a/util/lex.h	Mon Apr 27 13:30:21 2015 +0000
+++ b/util/lex.h	Thu May 07 09:57:55 2015 +0000
@@ -4,12 +4,10 @@
 
 struct Token
 {
-        enum TokType {
-                INT,
-                FLOAT,
-                STRING,
-                NONE,
-                ERROR
+        enum TokType { 
+                INT, FLOAT, STRING,
+                ASSIGN, SEMICOLON,
+                NONE, ERROR
         } type;
         const char *p;
         size_t len;
@@ -17,6 +15,7 @@
 
 const char* skipHTTPHeader(const char* p);
 const char* lex(const char*, Token&);
+const char* lexConfig(const char* p, Token& tok);
 size_t strncpyEscape(char*, const char*, size_t);
 
 #endif /* LEX_H */