Api wrapper to communicate with EVRYTHNG's Engine.

Dependencies:   EthernetInterface mbed-rtos

Dependents:   EvrythngApiExample

Files at this revision

API Documentation at this revision

Comitter:
vladounet
Date:
Thu Aug 30 13:20:01 2012 +0000
Child:
1:7162d0e030f5
Commit message:
Initial commit

Changed in this revision

EthernetInterface.lib Show annotated file Show diff for this revision Revisions of this file
EvrythngApi.cpp Show annotated file Show diff for this revision Revisions of this file
EvrythngApi.h Show annotated file Show diff for this revision Revisions of this file
JsonParser.cpp Show annotated file Show diff for this revision Revisions of this file
JsonParser.h Show annotated file Show diff for this revision Revisions of this file
evry_error.h Show annotated file Show diff for this revision Revisions of this file
mbed-rtos.lib Show annotated file Show diff for this revision Revisions of this file
util.cpp Show annotated file Show diff for this revision Revisions of this file
util.h Show annotated file Show diff for this revision Revisions of this file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/EthernetInterface.lib	Thu Aug 30 13:20:01 2012 +0000
@@ -0,0 +1,1 @@
+http://mbed.org/users/mbed_official/code/EthernetInterface/#a0ee3ae75cfa
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/EvrythngApi.cpp	Thu Aug 30 13:20:01 2012 +0000
@@ -0,0 +1,227 @@
+/*
+ * (c) Copyright 2012 EVRYTHNG Ltd London / Zurich
+ * www.evrythng.com
+ *
+ * --- DISCLAIMER ---
+ *
+ * EVRYTHNG provides this source code "as is" and without warranty of any kind,
+ * and hereby disclaims all express or implied warranties, including without
+ * limitation warranties of merchantability, fitness for a particular purpose,
+ * performance, accuracy, reliability, and non-infringement.
+ *
+ * Author: Michel Yerly
+ *
+ */
+#include "EvrythngApi.h"
+
+#include <string>
+
+#include "util.h"
+#include "evry_error.h"
+#include "JsonParser.h"
+
+//#define DEBUG_EVRYTHNG_API
+
+using namespace std;
+
+const int HTTP_OK = 200;
+
+const char* THNG_PATH = "/thngs/";
+const char* THNG_PROP_PATH = "/properties/";
+
+EvrythngApi::EvrythngApi(const string& token, const string& host, int port)
+{
+    this->token = token;
+    this->host = host;
+    this->port = port;
+}
+
+EvrythngApi::~EvrythngApi()
+{
+}
+
+int EvrythngApi::getThngPropertyValue(const string& thngId, const string& key, string& value)
+{
+    string path = THNG_PATH;
+    path += thngId;
+    path += THNG_PROP_PATH;
+    path += key;
+    path += "?from=latest";
+    string res;
+    int err;
+    int code;
+    if ((err = httpGet(path, res, code)) != 0) return err;
+    if (code != HTTP_OK) return EVRY_ERR_UNEXPECTEDHTTPSTATUS;
+    JsonParser json;
+    json.parse(res.c_str());
+    JsonValue* doc = json.getDocument();
+    const char* v = doc->getString("0/value");
+    if (v) {
+        value.assign(v);
+        return 0;
+    } else {
+        return -1;
+    }
+}
+
+int EvrythngApi::setThngPropertyValue(const std::string& thngId, const std::string& key, const std::string& value, int64_t timestamp)
+{
+    char strTimestamp[21];
+    char* end;
+    sprinti64(strTimestamp, timestamp, &end);
+    *end = '\0';
+
+    string path = THNG_PATH;
+    path += thngId;
+    path += THNG_PROP_PATH;
+    path += key;
+
+    string json = "[{\"timestamp\":";
+    json += strTimestamp;
+    json += ",\"value\":\"";
+    json += value;
+    json += "\"}]";
+
+    string res;
+    int err;
+    int code;
+    if ((err = httpPut(path, json, res, code)) != 0) return err;
+    if (code != HTTP_OK) return EVRY_ERR_UNEXPECTEDHTTPSTATUS;
+
+    return 0;
+}
+
+
+int EvrythngApi::httpRequest(HttpMethod method, const string& path, const string& content, string& out, int& codeOut)
+{
+    int ret;
+
+    const char* strMethod;
+    switch (method) {
+        case GET:
+            strMethod = "GET";
+            break;
+        case PUT:
+            strMethod = "PUT";
+            break;
+        case POST:
+            strMethod = "POST";
+            break;
+        case DELETE:
+            strMethod = "DELETE";
+            break;
+        default:
+            return EVRY_ERR_UNSUPPORTED;
+    }
+
+    char contentLength[16];
+    snprintf(contentLength, sizeof(contentLength), "%d", content.size());
+
+    string req = strMethod;
+    req += " ";
+    req += path;
+    req += " HTTP/1.0\r\n"
+           "Host: ";
+    req += host;
+    req += "\r\n"
+           "Accept: application/json\r\n"
+           "Content-Length: ";
+    req += contentLength;
+    req += "\r\n"
+           "Content-Type: application/json\r\n"
+           "Connection: close\r\n"
+           "Authorization: ";
+    req += token;
+    req += "\r\n\r\n";
+
+    req += content;
+
+#ifdef DEBUG_EVRYTHNG_API
+    dbg.printf("%s\r\n\r\n", req.c_str());
+#endif
+
+    TCPSocketConnection socket;
+
+    out.clear();
+
+    string res;
+
+    if (socket.connect(host.c_str(), port) == 0) {
+
+        char* snd = new char[req.size()+1];
+        req.copy(snd, req.size());
+        snd[req.size()]='\0';
+        bool sent = socket.send_all(snd, req.size()) >= 0;
+        delete[] snd;
+
+        if (sent) {
+
+            char rcv[256];
+
+            int r;
+            while (true) {
+                r = socket.receive(rcv, sizeof(rcv));
+                if (r <= 0)
+                    break;
+                res.append(rcv, r);
+            }
+
+            ret = EVRY_ERR_OK;
+
+        } else {
+            ret = EVRY_ERR_CANTSEND;
+        }
+
+        socket.close();
+
+    } else {
+        ret = EVRY_ERR_CANTCONNECT;
+    }
+    
+#ifdef DEBUG_EVRYTHNG_API
+    dbg.printf("%s", res.c_str());
+#endif
+
+    if (res.compare(0,5,"HTTP/") != 0) {
+        return EVRY_ERR_UNKNOWN;
+    }
+
+    int spPos = res.find(' ', 5);
+    if (spPos == string::npos) {
+        return EVRY_ERR_UNKNOWN;
+    }
+
+    // TODO: check str length
+    int code = atoi(res.c_str()+spPos+1);
+    if (code < 100 || code > 999) {
+        return EVRY_ERR_UNKNOWN;
+    }
+    codeOut = code;
+
+    int startContent = res.find("\r\n\r\n");
+    if (startContent != string::npos) {
+        out.append(res.substr(startContent+4,res.size()-startContent-4));
+    }
+
+    return ret;
+}
+
+int EvrythngApi::httpPut(const string& path, const string& json, string& out, int& codeOut)
+{
+    return httpRequest(PUT, path, json, out, codeOut);
+}
+
+int EvrythngApi::httpGet(const string& path, string& out, int& codeOut)
+{
+    return httpRequest(GET, path, "", out, codeOut);
+}
+
+int EvrythngApi::httpPost(const string& path, const string& json, string& out, int& codeOut)
+{
+    return httpRequest(POST, path, json, out, codeOut);
+}
+
+int EvrythngApi::httpDelete(const string& path, string& out, int& codeOut)
+{
+    return httpRequest(DELETE, path, "", out, codeOut);
+}
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/EvrythngApi.h	Thu Aug 30 13:20:01 2012 +0000
@@ -0,0 +1,73 @@
+/*
+ * (c) Copyright 2012 EVRYTHNG Ltd London / Zurich
+ * www.evrythng.com
+ *
+ * --- DISCLAIMER ---
+ *
+ * EVRYTHNG provides this source code "as is" and without warranty of any kind,
+ * and hereby disclaims all express or implied warranties, including without
+ * limitation warranties of merchantability, fitness for a particular purpose,
+ * performance, accuracy, reliability, and non-infringement.
+ *
+ * Author: Michel Yerly
+ *
+ */
+#ifndef EVRYTHNGAPI_H
+#define EVRYTHNGAPI_H
+
+#include "EthernetInterface.h"
+#include <string>
+
+#include <stdint.h>
+
+enum HttpMethod {
+    GET, PUT, POST, DELETE
+};
+
+
+/*
+ * Class to communicate with EVRYTHNG engine.
+ */
+class EvrythngApi
+{
+public:
+
+    /*
+     * Constructor
+     */
+    EvrythngApi(const std::string& token, const std::string& host = "api.test.evrythng.net", int port = 80);
+
+    /*
+     * Destructor
+     */
+    virtual ~EvrythngApi();
+    
+    /*
+     * Reads the current value of a thng's property. The value read is put
+     * in the value parameter.
+     * Returns 0 on success, or an error code on error. Error codes are
+     * described in evry_error.h.
+     */
+    int getThngPropertyValue(const std::string& thngId, const std::string& key, std::string& value);
+    
+    /*
+     * Sets the value of a thng's property.
+     * Returns 0 on success, or an error code on error. Error codes are
+     * described in evry_error.h.
+     */
+    int setThngPropertyValue(const std::string& thngId, const std::string& key, const std::string& value, int64_t timestamp);
+    
+private:
+    std::string token;
+    std::string host;
+    int port;
+    
+    int httpRequest(HttpMethod method, const std::string& path, const std::string& content, std::string& out, int& codeOut);
+    
+    int httpPut(const std::string& path, const std::string& json, std::string& out, int& codeOut);
+    int httpGet(const std::string& path, std::string& out, int& codeOut);
+    int httpPost(const std::string& path, const std::string& json, std::string& out, int& codeOut);
+    int httpDelete(const std::string& path, std::string& out, int& codeOut);
+};
+
+#endif
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/JsonParser.cpp	Thu Aug 30 13:20:01 2012 +0000
@@ -0,0 +1,574 @@
+/*
+ * (c) Copyright 2012 EVRYTHNG Ltd London / Zurich
+ * www.evrythng.com
+ *
+ * --- DISCLAIMER ---
+ *
+ * EVRYTHNG provides this source code "as is" and without warranty of any kind,
+ * and hereby disclaims all express or implied warranties, including without
+ * limitation warranties of merchantability, fitness for a particular purpose,
+ * performance, accuracy, reliability, and non-infringement.
+ *
+ * Author: Michel Yerly
+ *
+ */
+#include "JsonParser.h"
+#include "string.h"
+#include "stdlib.h"
+#include "errno.h"
+#include "util.h"
+
+//#define DEBUG_JSONTOKENIZER
+//#define DEBUG_JSONPARSER
+//#define DEBUG_JSONGET
+
+using namespace std;
+
+bool isDigit(char c)
+{
+    return c >= '0' && c <= '9';
+}
+
+JsonParser::JsonParser()
+{
+    this->pDocument = NULL;
+}
+
+JsonParser::~JsonParser()
+{
+    if (this->pDocument) {
+        delete this->pDocument;
+    }
+}
+
+int JsonParser::parse(const char* json)
+{
+    this->json = json;
+    this->json_len = strlen(json);
+
+    if (this->pDocument) {
+        delete this->pDocument;
+        this->pDocument = NULL;
+    }
+
+    ctPos = 0;
+    ctLen = 0;
+    if (goToNextToken() != 0) return -1;
+    bool ok = true;
+    if (json[ctPos] == '{') {
+        if (parseObject(&pDocument) != 0) {
+            ok = false;
+        }
+    } else {
+        if (parseArray(&pDocument) != 0) ok = false;
+    }
+    if (ct != TOKEN_EOS) {
+        ok = false;
+    }
+
+    if (!ok) {
+        delete pDocument;
+        pDocument = NULL;
+        return -1;
+    }
+
+    return 0;
+}
+
+JsonValue* JsonParser::getDocument()
+{
+    return pDocument;
+}
+
+int JsonParser::goToNextToken()
+{
+
+#ifdef DEBUG_JSONTOKENIZER
+
+    dbg.printf("Token: ");
+
+#endif
+
+    ctPos += ctLen;
+
+    // Skip whitespaces
+    while (ctPos < json_len &&
+            (json[ctPos] == ' ' || json[ctPos] == '\t' ||
+             json[ctPos] == '\r' || json[ctPos] == '\n'))
+        ++ctPos;
+
+    if (ctPos < json_len) {
+        if (json[ctPos] == '"') {
+            ct = TOKEN_STRING;
+            int i = ctPos+1;
+            while (i < json_len && json[i] != '"') {
+                if (json[i] == '\\') {
+                    if (i+1 < json_len) {
+                        switch (json[i+1]) {
+                            case '\\':
+                            case '"':
+                            case '/':
+                            case 'b':
+                            case 'f':
+                            case 'n':
+                            case 'r':
+                            case 't':
+                                ++i;
+                                break;
+                            case 'u':
+                                i+= 5;
+                                break;
+                            default:
+                                return -1;
+                        }
+                    } else {
+                        return -1;
+                    }
+                }
+                ++i;
+            }
+            if (i >= json_len || json[i] != '"') return -1;
+            ctLen = i - ctPos + 1;
+        } else if (isDigit(json[ctPos]) || json[ctPos] == '-') {
+            ct = TOKEN_NUMBER;
+            char* e;
+            errno = 0;
+            ctNumberVal = strtod(json+ctPos, &e);
+            if (errno || e - json <= 0) return -1;
+            ctLen = (e - json) - ctPos;
+
+        } else if (strncmp(json+ctPos,"true",4) == 0) {
+            ct = TOKEN_TRUE;
+            ctLen = 4;
+        } else if (strncmp(json+ctPos,"false",5) == 0) {
+            ct = TOKEN_FALSE;
+            ctLen = 5;
+        } else if (strncmp(json+ctPos,"null",4) == 0) {
+            ct = TOKEN_NULL;
+            ctLen = 4;
+        } else {
+            ct = TOKEN_DELIMITER;
+            ctLen = 1;
+        }
+    } else {
+        ct = TOKEN_EOS;
+        ctLen = 0;
+    }
+
+#ifdef DEBUG_JSONTOKENIZER
+
+    switch (ct) {
+        case TOKEN_DELIMITER:
+            dbg.printf("Delimtier - ");
+            break;
+        case TOKEN_EOS:
+            dbg.printf("End of stream");
+            break;
+        case TOKEN_NUMBER:
+            dbg.printf("Number %g - ", ctNumberVal);
+            break;
+        case TOKEN_STRING:
+            dbg.printf("String - ");
+            break;
+        case TOKEN_FALSE:
+            dbg.printf("False - ");
+            break;
+        case TOKEN_TRUE:
+            dbg.printf("True - ");
+            break;
+        case TOKEN_NULL:
+            dbg.printf("Null - ");
+            break;
+    }
+    if (ct != TOKEN_EOS) {
+        for (int i = 0; i < ctLen; ++i)
+            dbg.printf("%c", json[ctPos+i]);
+    }
+    dbg.printf(" (%d,%d)\r\n", ctPos, ctLen);
+
+#endif
+
+    return 0;
+}
+
+int JsonParser::parseObject(JsonValue** object)
+{
+
+#ifdef DEBUG_JSONPARSER
+    dbg.printf("Enter parseObject\r\n");
+#endif
+
+    *object = JsonValue::createMap();
+    map<string,JsonValue*>* m = (*object)->value.map;
+
+    if (ct != TOKEN_DELIMITER || json[ctPos] != '{') return -1;
+    if (goToNextToken() != 0) return -1;
+
+    if (ct == TOKEN_STRING) {
+
+        string key;
+        key.assign(json+ctPos+1, ctLen-2);
+
+        if (goToNextToken() != 0) return -1;
+
+        if (ct != TOKEN_DELIMITER || json[ctPos] != ':') return -1;
+        if (goToNextToken() != 0) return -1;
+
+        JsonValue* pValue;
+        if (parseValue(&pValue) != 0) {
+            delete pValue;
+            return -1;
+        }
+        (*m)[key] = pValue;
+
+        while (ct == TOKEN_DELIMITER && json[ctPos] == ',') {
+            if (goToNextToken() != 0) return -1;
+
+            if (ct != TOKEN_STRING) return -1;
+            key.assign(json+ctPos+1, ctLen-2);
+            if (goToNextToken() != 0) return -1;
+
+            if (ct != TOKEN_DELIMITER || json[ctPos] != ':') return -1;
+            if (goToNextToken() != 0) return -1;
+
+            if (parseValue(&pValue) != 0) {
+                delete pValue;
+                return -1;
+            }
+            (*m)[key] = pValue;
+        }
+    }
+
+    if (ct != TOKEN_DELIMITER || json[ctPos] != '}') return -1;
+    if (goToNextToken() != 0) return -1;
+
+#ifdef DEBUG_JSONPARSER
+    dbg.printf("Exit parseObject\r\n");
+#endif
+    return 0;
+}
+
+int JsonParser::parseValue(JsonValue** value)
+{
+
+#ifdef DEBUG_JSONPARSER
+    dbg.printf("Enter parseValue\r\n");
+#endif
+
+    switch (ct) {
+        case TOKEN_STRING:
+            *value = JsonValue::createString(json+ctPos+1,ctLen-2);
+            if (goToNextToken() != 0) return -1;
+            break;
+        case TOKEN_NUMBER:
+            *value = JsonValue::createDouble(ctNumberVal);
+            if (goToNextToken() != 0) return -1;
+            break;
+        case TOKEN_NULL:
+            *value = JsonValue::createNull();
+            if (goToNextToken() != 0) return -1;
+            break;
+        case TOKEN_FALSE:
+            *value = JsonValue::createBoolean(false);
+            if (goToNextToken() != 0) return -1;
+            break;
+        case TOKEN_TRUE:
+            *value = JsonValue::createBoolean(true);
+            if (goToNextToken() != 0) return -1;
+            break;
+        case TOKEN_DELIMITER:
+            if (json[ctPos] == '{') {
+                if (parseObject(value) != 0) return -1;
+            } else if (json[ctPos] == '[') {
+                if (parseArray(value) != 0) return -1;
+            }
+            break;
+        default:
+            *value = JsonValue::createNull();
+            return -1;
+    }
+
+#ifdef DEBUG_JSONPARSER
+    dbg.printf("Exit parseValue\r\n");
+#endif
+
+    return 0;
+}
+
+int JsonParser::parseArray(JsonValue** array)
+{
+
+#ifdef DEBUG_JSONPARSER
+    dbg.printf("Enter parseArray\r\n");
+#endif
+
+    *array = JsonValue::createVector();
+    vector<JsonValue*>* vec = (*array)->value.vec;
+
+    if (ct != TOKEN_DELIMITER || json[ctPos] != '[') return -1;
+    if (goToNextToken() != 0) return -1;
+
+    if (ct != TOKEN_DELIMITER || json[ctPos] != ']') {
+
+        JsonValue* pValue;
+        if (parseValue(&pValue) != 0) {
+            delete pValue;
+            return -1;
+        };
+        vec->push_back(pValue);
+
+        while (ct == TOKEN_DELIMITER && json[ctPos] == ',') {
+            if (goToNextToken() != 0) return -1;
+
+            if (parseValue(&pValue) != 0) {
+                delete pValue;
+                return -1;
+            };
+            vec->push_back(pValue);
+        }
+    }
+
+    if (ct != TOKEN_DELIMITER || json[ctPos] != ']') return -1;
+    if (goToNextToken() != 0) return -1;
+
+#ifdef DEBUG_JSONPARSER
+    dbg.printf("Exit parseArray\r\n");
+#endif
+
+    return 0;
+}
+
+int inst = 0;
+
+JsonValue::JsonValue(const char* buffer, int len)
+{
+    type = VT_CHAR_PTR;
+    value.s = new char[len+1];
+    strncpy(value.s, buffer, len);
+    value.s[len] = '\0';
+}
+
+JsonValue::JsonValue(double d)
+{
+    type = VT_DOUBLE;
+    value.d = d;
+}
+
+JsonValue::JsonValue(bool b)
+{
+    type = b ? VT_CST_TRUE : VT_CST_FALSE;
+
+}
+
+JsonValue::JsonValue()
+{
+}
+
+JsonValue::~JsonValue()
+{
+    switch (type) {
+        case VT_CHAR_PTR:
+            delete[] value.s;
+            break;
+        case VT_MAP_PTR:
+            for (map<string,JsonValue*>::iterator itr = value.map->begin(); itr != value.map->end(); itr++)
+                delete ((*itr).second);
+            delete value.map;
+            break;
+        case VT_VEC_PTR:
+            for (vector<JsonValue*>::iterator itr = value.vec->begin(); itr != value.vec->end(); itr++)
+                delete (*itr);
+            delete value.vec;
+            break;
+        default:
+            break;
+    }
+}
+
+JsonValue* JsonValue::createString(const char* buffer, int len)
+{
+    return new JsonValue(buffer, len);
+}
+
+JsonValue* JsonValue::createDouble(double d)
+{
+    return new JsonValue(d);
+}
+
+JsonValue* JsonValue::createBoolean(bool b)
+{
+    return new JsonValue(b);
+}
+
+JsonValue* JsonValue::createMap()
+{
+    JsonValue* ret = new JsonValue();
+    ret->type = VT_MAP_PTR;
+    ret->value.map = new map<string,JsonValue*>();
+    return ret;
+}
+
+JsonValue* JsonValue::createVector()
+{
+    JsonValue* ret = new JsonValue();
+    ret->type = VT_VEC_PTR;
+    ret->value.vec = new vector<JsonValue*>();
+    return ret;
+}
+
+JsonValue* JsonValue::createNull()
+{
+    JsonValue* ret = new JsonValue();
+    ret->type = VT_CST_NULL;
+    return ret;
+}
+
+void JsonValue::print()
+{
+    bool c = false;
+    switch (type) {
+        case VT_CHAR_PTR:
+            dbg.printf("\"%s\"", value.s);
+            break;
+        case VT_MAP_PTR:
+            dbg.printf("{");
+            for (map<string,JsonValue*>::iterator itr = value.map->begin(); itr != value.map->end(); itr++) {
+                if (c) dbg.printf(",");
+                else c = true;
+                dbg.printf("\"%s\":",(*itr).first.c_str());
+                (*itr).second->print();
+            }
+            dbg.printf("}");
+            break;
+        case VT_VEC_PTR:
+            dbg.printf("[");
+            for (vector<JsonValue*>::iterator itr = value.vec->begin(); itr != value.vec->end(); itr++) {
+                if (c) dbg.printf(",");
+                else c = true;
+                (*itr)->print();
+            }
+            dbg.printf("]");
+            break;
+        case VT_DOUBLE:
+            dbg.printf("%g", value.d);
+            break;
+        case VT_CST_TRUE:
+            dbg.printf("true");
+            break;
+        case VT_CST_FALSE:
+            dbg.printf("false");
+            break;
+        case VT_CST_NULL:
+            dbg.printf("null");
+            break;
+        default:
+            break;
+    }
+}
+
+JsonValue* JsonValue::get(const char* path)
+{
+    JsonValue* pValue = this;
+    int pos = 0;
+    while (path != NULL && path[pos] != '\0') {
+
+#ifdef DEBUG_JSONGET
+        dbg.printf("::get ");
+        pValue->print();
+        dbg.printf("\r\n");
+#endif
+
+        const char* start = path+pos;
+        const char* pSl = strchr(start, '/');
+        int len = pSl == NULL ? strlen(start) : pSl - start;
+        if (len <= 0) return NULL;
+        if (pValue->type == VT_VEC_PTR) {
+            int v = atoi(start);
+            if (v == 0 && path[pos] != '0') {
+                return NULL;
+            }
+            if (v < 0 || v >= pValue->value.vec->size()) {
+                return NULL;
+            }
+            pValue = (*pValue->value.vec)[v];
+        } else if (pValue->type == VT_MAP_PTR) {
+            char* pKey = new char[len+1];
+            strncpy(pKey, start, len);
+            pKey[len] = '\0';
+            pValue = (*pValue->value.map)[pKey];
+            delete[] pKey;
+            if (pValue == NULL) {
+                return NULL;
+            }
+        } else {
+            return NULL;
+        }
+        pos += len;
+        if (pSl) ++pos;
+    }
+
+#ifdef DEBUG_JSONGET
+        dbg.printf("::get ");
+        pValue->print();
+        dbg.printf("\r\n");
+#endif
+
+    return pValue;
+}
+
+const double* JsonValue::getDouble(const char* path)
+{
+    JsonValue* pV = get(path);
+    if (pV != NULL && pV->type == VT_DOUBLE) {
+        return &(pV->value.d);
+    } else {
+        return NULL;
+    }
+}
+
+const char* JsonValue::getString(const char* path)
+{
+    JsonValue* pV = get(path);
+    if (pV != NULL && pV->type == VT_CHAR_PTR) {
+        return pV->value.s;
+    } else {
+        return NULL;
+    }
+}
+const std::vector<JsonValue*>* JsonValue::getVector(const char* path)
+{
+    JsonValue* pV = get(path);
+    if (pV != NULL && pV->type == VT_VEC_PTR) {
+        return pV->value.vec;
+    } else {
+        return NULL;
+    }
+}
+const std::map<std::string,JsonValue*>* JsonValue::getMap(const char* path)
+{
+    JsonValue* pV = get(path);
+    if (pV != NULL && pV->type == VT_MAP_PTR) {
+        return pV->value.map;
+    } else {
+        return NULL;
+    }
+}
+
+static const bool FALSE = false;
+static const bool TRUE = true;
+
+const bool* JsonValue::getBoolean(const char* path)
+{
+    JsonValue* pV = get(path);
+    if (pV != NULL && (pV->type == VT_CST_TRUE || pV->type == VT_CST_FALSE)) {
+        return (pV->type == VT_CST_TRUE) ? &TRUE : &FALSE;
+    } else {
+        return NULL;
+    }
+}
+bool JsonValue::isNull(const char* path)
+{
+    JsonValue* pV = get(path);
+    return (pV != NULL) && (pV->type == VT_CST_NULL);
+}
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/JsonParser.h	Thu Aug 30 13:20:01 2012 +0000
@@ -0,0 +1,242 @@
+/*
+ * (c) Copyright 2012 EVRYTHNG Ltd London / Zurich
+ * www.evrythng.com
+ *
+ * --- DISCLAIMER ---
+ *
+ * EVRYTHNG provides this source code "as is" and without warranty of any kind,
+ * and hereby disclaims all express or implied warranties, including without
+ * limitation warranties of merchantability, fitness for a particular purpose,
+ * performance, accuracy, reliability, and non-infringement.
+ *
+ * Author: Michel Yerly
+ *
+ */
+#ifndef JSONPARSER_H
+#define JSONPARSER_H
+
+#include <vector>
+#include <map>
+#include <string>
+
+/*
+ * Possible JSON value types
+ */
+enum ValueType {
+
+    VT_DOUBLE,   // Number
+    VT_CHAR_PTR, // String
+    VT_VEC_PTR,  // Array
+    VT_MAP_PTR,  // Object
+    VT_CST_NULL, // Null
+    VT_CST_TRUE, // True
+    VT_CST_FALSE // False
+};
+
+/*
+ * Class to hold a JSON value. A JSON value may be composed of other JSON
+ * values.
+ */
+class JsonValue
+{
+public:
+
+    /*
+     * Creates a new string JSON value. The string is copied into the object.
+     * WARNING: a new object is created. The caller is responsible of deleting
+     * it.
+     * buffer: the string to read from.
+     * len: the number of characters to read.
+     */
+    static JsonValue* createString(const char* buffer, int len);
+    
+    /* Creates a new number JSON value.
+     * WARNING: a new object is created. The caller is responsible of deleting
+     * it.
+     */
+    static JsonValue* createDouble(double d);
+
+    /* Creates a new object JSON value.
+     * WARNING: a new object is created. The caller is responsible of deleting
+     * it.
+     */
+    static JsonValue* createMap();
+
+    /* Creates a new array JSON value.
+     * WARNING: a new object is created. The caller is responsible of deleting
+     * it.
+     */
+    static JsonValue* createVector();
+    
+    /* Creates a new true or false JSON value, depending on b.
+     * WARNING: a new object is created. The caller is responsible of deleting
+     * it.
+     */
+    static JsonValue* createBoolean(bool b);
+    
+    /* Creates a new null JSON value.
+     * WARNING: a new object is created. The caller is responsible of deleting
+     * it.
+     */
+    static JsonValue* createNull();
+
+    /* 
+     * Destructor.
+     * The destructor also deletes nested JsonValues if any.
+     */
+    virtual ~JsonValue();
+
+    /*
+     * Gets a JSON value given a path.
+     * If the path is NULL or an empty string the method returns this.
+     * If there is an error, the method returns NULL.
+     * The path is composed of strings (object keys) and numbers (array 
+     * indices) separated by '/'.
+     *
+     * Example:
+     *   JSON: {"xy":34,"ab":[{"r":true},{"s":false}]}
+     *   Path: ab/1/s
+     *   Returns: a JsonValue representing false.
+     */
+    JsonValue* get(const char* path);
+    
+    /*
+     * Gets a pointer to a double given a path (see get()).
+     * If there is an error, the method returns NULL.
+     */
+    const double* getDouble(const char* path);
+    
+    /*
+     * Gets a pointer to a string given a path (see get()).
+     * If there is an error, the method returns NULL.
+     */
+    const char* getString(const char* path);
+    
+    /*
+     * Gets a pointer to an array given a path (see get()).
+     * If there is an error, the method returns NULL.
+     */
+    const std::vector<JsonValue*>* getVector(const char* path);
+
+    /*
+     * Gets a pointer to a map given a path (see get()).
+     * If there is an error, the method returns NULL.
+     */
+    const std::map<std::string,JsonValue*>* getMap(const char* path);
+
+    /*
+     * Gets a pointer to a boolean given a path (see get()).
+     * If there is an error, the method returns NULL.
+     */
+    const bool* getBoolean(const char* path);
+
+    /*
+     * Determines if the value at the path (see get()) is null.
+     * Return true if and only if the value is explicitely null.
+     */
+    bool isNull(const char* path);
+
+    /*
+     * Debug function.
+     */
+    void print();
+
+    friend class JsonParser;
+
+private:
+
+    /*
+     * Constructor that creates a string JSON value. The string is copied into
+     * the object.
+     * buffer: the string to read from.
+     * len: the number of characters to read.
+     */
+    JsonValue(const char* buffer, int len);
+    
+    /*
+     * Constructor that creates a number JSON value.
+     */
+    JsonValue(double d);
+    
+    /*
+     * Constructor that creates either a True or a False JSON value.
+     */
+    JsonValue(bool b);
+    
+    /*
+     * Constructor that creates a JSON value without specifying the type.
+     */
+    JsonValue();
+    
+    ValueType type;
+    union {
+        double d;
+        char* s;
+        std::vector<JsonValue*>* vec;
+        std::map<std::string,JsonValue*>* map;
+    } value;
+
+};
+
+enum TokenType {
+    TOKEN_EOS,
+    TOKEN_NUMBER,
+    TOKEN_STRING,
+    TOKEN_DELIMITER,
+    TOKEN_TRUE,
+    TOKEN_FALSE,
+    TOKEN_NULL
+};
+
+/*
+ * Class to parse a JSON string.
+ *
+ * NOTE: The current implementation does only support ASCII encoding.
+ */
+class JsonParser
+{
+public:
+
+    /*
+     * Constructor.
+     */
+    JsonParser();
+    
+    /*
+     * Destructor.
+     * The destructor also deletes the parsed document (the one you get with
+     * getDocument().
+     */
+    virtual ~JsonParser();
+    
+    /*
+     * Parses the json string.
+     * json: String that contains the json to parse.
+     * Returns 0 on success, or -1 on error.
+     *
+     * NOTE: This method deletes the previously parsed document.
+     */
+    int parse(const char* json);
+    
+    /*
+     * Returns the parsed document, or NULL if the json is not parsed.
+     */
+    JsonValue* getDocument();
+
+private:
+    const char* json;
+    int json_len;
+    TokenType ct;
+    int ctPos;
+    int ctLen;
+    double ctNumberVal;
+    JsonValue* pDocument;
+
+    int goToNextToken();
+
+    int parseObject(JsonValue** object);
+    int parseValue(JsonValue** value);
+    int parseArray(JsonValue** array);
+};
+
+#endif
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/evry_error.h	Thu Aug 30 13:20:01 2012 +0000
@@ -0,0 +1,25 @@
+/*
+ * (c) Copyright 2012 EVRYTHNG Ltd London / Zurich
+ * www.evrythng.com
+ *
+ * --- DISCLAIMER ---
+ *
+ * EVRYTHNG provides this source code "as is" and without warranty of any kind,
+ * and hereby disclaims all express or implied warranties, including without
+ * limitation warranties of merchantability, fitness for a particular purpose,
+ * performance, accuracy, reliability, and non-infringement.
+ *
+ * Author: Michel Yerly
+ *
+ */
+#ifndef EVRY_ERROR_H
+#define EVRY_ERROR_H
+
+#define EVRY_ERR_OK 0
+#define EVRY_ERR_UNKNOWN 1
+#define EVRY_ERR_CANTCONNECT 2
+#define EVRY_ERR_CANTSEND 3
+#define EVRY_ERR_UNSUPPORTED 4
+#define EVRY_ERR_UNEXPECTEDHTTPSTATUS 5
+
+#endif
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/mbed-rtos.lib	Thu Aug 30 13:20:01 2012 +0000
@@ -0,0 +1,1 @@
+http://mbed.org/users/mbed_official/code/mbed-rtos/#9654a71f5a90
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/util.cpp	Thu Aug 30 13:20:01 2012 +0000
@@ -0,0 +1,46 @@
+/*
+ * (c) Copyright 2012 EVRYTHNG Ltd London / Zurich
+ * www.evrythng.com
+ *
+ * --- DISCLAIMER ---
+ *
+ * EVRYTHNG provides this source code "as is" and without warranty of any kind,
+ * and hereby disclaims all express or implied warranties, including without
+ * limitation warranties of merchantability, fitness for a particular purpose,
+ * performance, accuracy, reliability, and non-infringement.
+ *
+ * Author: Michel Yerly
+ *
+ */
+#include "util.h"
+
+Serial dbg(USBTX, USBRX);
+
+
+void sprinti64(char* dest, int64_t v, char** end)
+{
+    int len;
+    if (v != 0x8000000000000000LL) {
+        char str[20];
+        int p = sizeof(str);
+        str[--p] = '\0';
+        str[p-1] = '0';
+        bool neg = false;
+        if (v < 0) {
+            v = -v;
+            neg = true;
+        }
+        while (v > 0) {
+            str[--p] = '0' + (v % 10);
+            v /= 10;
+        }
+        if (neg) {
+            str[--p] = '-';
+        }
+        len = sizeof(str) - p;
+        strncpy(dest, str + p, len);
+    } else {
+        len = 20;
+        strncpy(dest, "-9223372036854775808", len);
+    }    *end = dest + len;
+}
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/util.h	Thu Aug 30 13:20:01 2012 +0000
@@ -0,0 +1,24 @@
+/*
+ * (c) Copyright 2012 EVRYTHNG Ltd London / Zurich
+ * www.evrythng.com
+ *
+ * --- DISCLAIMER ---
+ *
+ * EVRYTHNG provides this source code "as is" and without warranty of any kind,
+ * and hereby disclaims all express or implied warranties, including without
+ * limitation warranties of merchantability, fitness for a particular purpose,
+ * performance, accuracy, reliability, and non-infringement.
+ *
+ * Author: Michel Yerly
+ *
+ */
+#ifndef UTIL_H
+#define UTIL_H
+
+#include "mbed.h"
+
+extern Serial dbg;
+
+void sprinti64(char* dest, int64_t v, char** end);
+
+#endif
\ No newline at end of file