Everything Example
Dependencies: EthernetInterface mbed-rtos mbed
Fork of TCPEthernet by
Revision 9:b08a28f659eb, committed 2017-01-24
- Comitter:
- lachu
- Date:
- Tue Jan 24 22:17:00 2017 +0000
- Parent:
- 8:475898cdb7d4
- Commit message:
- Working Program
Changed in this revision
diff -r 475898cdb7d4 -r b08a28f659eb EvrythngApi.cpp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/EvrythngApi.cpp Tue Jan 24 22:17:00 2017 +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
diff -r 475898cdb7d4 -r b08a28f659eb EvrythngApi.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/EvrythngApi.h Tue Jan 24 22:17:00 2017 +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.evrythng.com", 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
diff -r 475898cdb7d4 -r b08a28f659eb JsonParser.cpp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/JsonParser.cpp Tue Jan 24 22:17:00 2017 +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); +} +
diff -r 475898cdb7d4 -r b08a28f659eb JsonParser.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/JsonParser.h Tue Jan 24 22:17:00 2017 +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
diff -r 475898cdb7d4 -r b08a28f659eb evry_error.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/evry_error.h Tue Jan 24 22:17:00 2017 +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
diff -r 475898cdb7d4 -r b08a28f659eb main.cpp --- a/main.cpp Thu Jan 12 19:11:37 2017 +0000 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,95 +0,0 @@ -#include "mbed.h" -#include "EthernetInterface.h" -#include <string> - -#define ECHO_SERVER_PORT 7 - -DigitalOut led1(LED1); -DigitalOut led2(LED2); -DigitalOut led3(LED3); - -int main (void) { - led1 = !led1; - led2 = !led2; - led3 = !led3; - - EthernetInterface eth; - eth.init(); //Use DHCP - eth.connect(); - printf("\nServer IP Address is %s\n", eth.getIPAddress()); - - TCPSocketServer server; - server.bind(ECHO_SERVER_PORT); - server.listen(); - - while (true) { - printf("\nWait for new connection...\n"); - TCPSocketConnection client; - server.accept(client); - client.set_blocking(false, 15000); // Timeout after (1.5)s - - printf("Connection from: %s\n", client.get_address()); - char buffer[256]; - //std::string myCommand; - //myCommand = buffer; - while (true) { - printf("TEST1\n"); - int n = client.receive(buffer, sizeof(buffer)); - //if (n <= 0) break; - - printf("Received message from Client :'%s'\n",buffer); - - client.send_all(buffer, n); - buffer[n] = '\0'; - - printf("Variable n is: %d\n", n); - - if(n>0){ - if(strcmp(buffer, "red") == 0){ - printf("REDled\n"); - led1.write(0); - }else if(strcmp(buffer, "green") == 0){ - printf("GREENled\n"); - led2.write(0); - }else if(strcmp(buffer, "blue") == 0){ - printf("BLUEled\n"); - led3.write(0); - }else if(strcmp(buffer, "clear") == 0){ - printf("CLEAR\n"); - led1.write(1); - led2.write(1); - led3.write(1); - }else if(strcmp(buffer, "white") == 0){ - printf("WHITE\n"); - led1.write(0); - led2.write(0); - led3.write(0); - }else if(strcmp(buffer, "tred") == 0){ - printf("REDtoggleled\n"); - led1 = !led1; - }else if(strcmp(buffer, "tgreen") == 0){ - printf("GREENtoggleled\n"); - led2 = !led2; - }else if(strcmp(buffer, "tblue") == 0){ - printf("BLUEtoggleled\n"); - led3 = !led3; - }else if(strcmp(buffer, "CLOSE") == 0){ - printf("CLOSE\n"); - break; - } - } - //led3.write(1); - - printf("Received message from Client :'%s'\n",buffer); - - n=0; - //if (n <= 0) break; - } - printf("TEST2"); - client.close(); - led1.write(1); - led2.write(1); - led3.write(1); - printf(" TEST3\n"); - } -}
diff -r 475898cdb7d4 -r b08a28f659eb util.cpp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/util.cpp Tue Jan 24 22:17:00 2017 +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
diff -r 475898cdb7d4 -r b08a28f659eb util.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/util.h Tue Jan 24 22:17:00 2017 +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