Api wrapper to communicate with EVRYTHNG's Engine.

Dependencies:   EthernetInterface mbed-rtos

Dependents:   EvrythngApiExample

Embed: (wiki syntax)

« Back to documentation index

Show/hide line numbers EvrythngApi.cpp Source File

EvrythngApi.cpp

00001 /*
00002  * (c) Copyright 2012 EVRYTHNG Ltd London / Zurich
00003  * www.evrythng.com
00004  *
00005  * --- DISCLAIMER ---
00006  *
00007  * EVRYTHNG provides this source code "as is" and without warranty of any kind,
00008  * and hereby disclaims all express or implied warranties, including without
00009  * limitation warranties of merchantability, fitness for a particular purpose,
00010  * performance, accuracy, reliability, and non-infringement.
00011  *
00012  * Author: Michel Yerly
00013  *
00014  */
00015 #include "EvrythngApi.h"
00016 
00017 #include <string>
00018 
00019 #include "util.h"
00020 #include "evry_error.h"
00021 #include "JsonParser.h"
00022 
00023 //#define DEBUG_EVRYTHNG_API
00024 
00025 using namespace std;
00026 
00027 const int HTTP_OK = 200;
00028 
00029 const char* THNG_PATH = "/thngs/";
00030 const char* THNG_PROP_PATH = "/properties/";
00031 
00032 EvrythngApi::EvrythngApi(const string& token, const string& host, int port)
00033 {
00034     this->token = token;
00035     this->host = host;
00036     this->port = port;
00037 }
00038 
00039 EvrythngApi::~EvrythngApi()
00040 {
00041 }
00042 
00043 int EvrythngApi::getThngPropertyValue(const string& thngId, const string& key, string& value)
00044 {
00045     string path = THNG_PATH;
00046     path += thngId;
00047     path += THNG_PROP_PATH;
00048     path += key;
00049     path += "?from=latest";
00050     string res;
00051     int err;
00052     int code;
00053     if ((err = httpGet(path, res, code)) != 0) return err;
00054     if (code != HTTP_OK) return EVRY_ERR_UNEXPECTEDHTTPSTATUS;
00055     JsonParser json;
00056     json.parse(res.c_str());
00057     JsonValue* doc = json.getDocument();
00058     const char* v = doc->getString("0/value");
00059     if (v) {
00060         value.assign(v);
00061         return 0;
00062     } else {
00063         return -1;
00064     }
00065 }
00066 
00067 int EvrythngApi::setThngPropertyValue(const std::string& thngId, const std::string& key, const std::string& value, int64_t timestamp)
00068 {
00069     char strTimestamp[21];
00070     char* end;
00071     sprinti64(strTimestamp, timestamp, &end);
00072     *end = '\0';
00073 
00074     string path = THNG_PATH;
00075     path += thngId;
00076     path += THNG_PROP_PATH;
00077     path += key;
00078 
00079     string json = "[{\"timestamp\":";
00080     json += strTimestamp;
00081     json += ",\"value\":\"";
00082     json += value;
00083     json += "\"}]";
00084 
00085     string res;
00086     int err;
00087     int code;
00088     if ((err = httpPut(path, json, res, code)) != 0) return err;
00089     if (code != HTTP_OK) return EVRY_ERR_UNEXPECTEDHTTPSTATUS;
00090 
00091     return 0;
00092 }
00093 
00094 
00095 int EvrythngApi::httpRequest(HttpMethod method, const string& path, const string& content, string& out, int& codeOut)
00096 {
00097     int ret;
00098 
00099     const char* strMethod;
00100     switch (method) {
00101         case GET:
00102             strMethod = "GET";
00103             break;
00104         case PUT:
00105             strMethod = "PUT";
00106             break;
00107         case POST:
00108             strMethod = "POST";
00109             break;
00110         case DELETE:
00111             strMethod = "DELETE";
00112             break;
00113         default:
00114             return EVRY_ERR_UNSUPPORTED;
00115     }
00116 
00117     char contentLength[16];
00118     snprintf(contentLength, sizeof(contentLength), "%d", content.size());
00119 
00120     string req = strMethod;
00121     req += " ";
00122     req += path;
00123     req += " HTTP/1.0\r\n"
00124            "Host: ";
00125     req += host;
00126     req += "\r\n"
00127            "Accept: application/json\r\n"
00128            "Content-Length: ";
00129     req += contentLength;
00130     req += "\r\n"
00131            "Content-Type: application/json\r\n"
00132            "Connection: close\r\n"
00133            "Authorization: ";
00134     req += token;
00135     req += "\r\n\r\n";
00136 
00137     req += content;
00138 
00139 #ifdef DEBUG_EVRYTHNG_API
00140     dbg.printf("%s\r\n\r\n", req.c_str());
00141 #endif
00142 
00143     TCPSocketConnection socket;
00144 
00145     out.clear();
00146 
00147     string res;
00148 
00149     if (socket.connect(host.c_str(), port) == 0) {
00150 
00151         char* snd = new char[req.size()+1];
00152         req.copy(snd, req.size());
00153         snd[req.size()]='\0';
00154         bool sent = socket.send_all(snd, req.size()) >= 0;
00155         delete[] snd;
00156 
00157         if (sent) {
00158 
00159             char rcv[256];
00160 
00161             int r;
00162             while (true) {
00163                 r = socket.receive(rcv, sizeof(rcv));
00164                 if (r <= 0)
00165                     break;
00166                 res.append(rcv, r);
00167             }
00168 
00169             ret = EVRY_ERR_OK;
00170 
00171         } else {
00172             ret = EVRY_ERR_CANTSEND;
00173         }
00174 
00175         socket.close();
00176 
00177     } else {
00178         ret = EVRY_ERR_CANTCONNECT;
00179     }
00180     
00181 #ifdef DEBUG_EVRYTHNG_API
00182     dbg.printf("%s", res.c_str());
00183 #endif
00184 
00185     if (res.compare(0,5,"HTTP/") != 0) {
00186         return EVRY_ERR_UNKNOWN;
00187     }
00188 
00189     int spPos = res.find(' ', 5);
00190     if (spPos == string::npos) {
00191         return EVRY_ERR_UNKNOWN;
00192     }
00193 
00194     // TODO: check str length
00195     int code = atoi(res.c_str()+spPos+1);
00196     if (code < 100 || code > 999) {
00197         return EVRY_ERR_UNKNOWN;
00198     }
00199     codeOut = code;
00200 
00201     int startContent = res.find("\r\n\r\n");
00202     if (startContent != string::npos) {
00203         out.append(res.substr(startContent+4,res.size()-startContent-4));
00204     }
00205 
00206     return ret;
00207 }
00208 
00209 int EvrythngApi::httpPut(const string& path, const string& json, string& out, int& codeOut)
00210 {
00211     return httpRequest(PUT, path, json, out, codeOut);
00212 }
00213 
00214 int EvrythngApi::httpGet(const string& path, string& out, int& codeOut)
00215 {
00216     return httpRequest(GET, path, "", out, codeOut);
00217 }
00218 
00219 int EvrythngApi::httpPost(const string& path, const string& json, string& out, int& codeOut)
00220 {
00221     return httpRequest(POST, path, json, out, codeOut);
00222 }
00223 
00224 int EvrythngApi::httpDelete(const string& path, string& out, int& codeOut)
00225 {
00226     return httpRequest(DELETE, path, "", out, codeOut);
00227 }