Api wrapper to communicate with EVRYTHNG's Engine.
Dependencies: EthernetInterface mbed-rtos
Dependents: EvrythngApiExample
Diff: EvrythngApi.cpp
- Revision:
- 0:d38d192c2f5f
--- /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