Important changes to repositories hosted on mbed.com
Mbed hosted mercurial repositories are deprecated and are due to be permanently deleted in July 2026.
To keep a copy of this software download the repository Zip archive or clone locally using Mercurial.
It is also possible to export all your personal repositories from the account settings page.
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
--- /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
--- /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
--- /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);
+}
+
--- /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
--- /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
--- 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");
- }
-}
--- /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
--- /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
