Api wrapper to communicate with EVRYTHNG's Engine.
Dependencies: EthernetInterface mbed-rtos
Dependents: EvrythngApiExample
EvrythngApi.cpp@1:7162d0e030f5, 2012-08-30 (annotated)
- Committer:
- vladounet
- Date:
- Thu Aug 30 13:25:41 2012 +0000
- Revision:
- 1:7162d0e030f5
- Parent:
- 0:d38d192c2f5f
Initial commit
Who changed what in which revision?
User | Revision | Line number | New contents of line |
---|---|---|---|
vladounet | 0:d38d192c2f5f | 1 | /* |
vladounet | 0:d38d192c2f5f | 2 | * (c) Copyright 2012 EVRYTHNG Ltd London / Zurich |
vladounet | 0:d38d192c2f5f | 3 | * www.evrythng.com |
vladounet | 0:d38d192c2f5f | 4 | * |
vladounet | 0:d38d192c2f5f | 5 | * --- DISCLAIMER --- |
vladounet | 0:d38d192c2f5f | 6 | * |
vladounet | 0:d38d192c2f5f | 7 | * EVRYTHNG provides this source code "as is" and without warranty of any kind, |
vladounet | 0:d38d192c2f5f | 8 | * and hereby disclaims all express or implied warranties, including without |
vladounet | 0:d38d192c2f5f | 9 | * limitation warranties of merchantability, fitness for a particular purpose, |
vladounet | 0:d38d192c2f5f | 10 | * performance, accuracy, reliability, and non-infringement. |
vladounet | 0:d38d192c2f5f | 11 | * |
vladounet | 0:d38d192c2f5f | 12 | * Author: Michel Yerly |
vladounet | 0:d38d192c2f5f | 13 | * |
vladounet | 0:d38d192c2f5f | 14 | */ |
vladounet | 0:d38d192c2f5f | 15 | #include "EvrythngApi.h" |
vladounet | 0:d38d192c2f5f | 16 | |
vladounet | 0:d38d192c2f5f | 17 | #include <string> |
vladounet | 0:d38d192c2f5f | 18 | |
vladounet | 0:d38d192c2f5f | 19 | #include "util.h" |
vladounet | 0:d38d192c2f5f | 20 | #include "evry_error.h" |
vladounet | 0:d38d192c2f5f | 21 | #include "JsonParser.h" |
vladounet | 0:d38d192c2f5f | 22 | |
vladounet | 0:d38d192c2f5f | 23 | //#define DEBUG_EVRYTHNG_API |
vladounet | 0:d38d192c2f5f | 24 | |
vladounet | 0:d38d192c2f5f | 25 | using namespace std; |
vladounet | 0:d38d192c2f5f | 26 | |
vladounet | 0:d38d192c2f5f | 27 | const int HTTP_OK = 200; |
vladounet | 0:d38d192c2f5f | 28 | |
vladounet | 0:d38d192c2f5f | 29 | const char* THNG_PATH = "/thngs/"; |
vladounet | 0:d38d192c2f5f | 30 | const char* THNG_PROP_PATH = "/properties/"; |
vladounet | 0:d38d192c2f5f | 31 | |
vladounet | 0:d38d192c2f5f | 32 | EvrythngApi::EvrythngApi(const string& token, const string& host, int port) |
vladounet | 0:d38d192c2f5f | 33 | { |
vladounet | 0:d38d192c2f5f | 34 | this->token = token; |
vladounet | 0:d38d192c2f5f | 35 | this->host = host; |
vladounet | 0:d38d192c2f5f | 36 | this->port = port; |
vladounet | 0:d38d192c2f5f | 37 | } |
vladounet | 0:d38d192c2f5f | 38 | |
vladounet | 0:d38d192c2f5f | 39 | EvrythngApi::~EvrythngApi() |
vladounet | 0:d38d192c2f5f | 40 | { |
vladounet | 0:d38d192c2f5f | 41 | } |
vladounet | 0:d38d192c2f5f | 42 | |
vladounet | 0:d38d192c2f5f | 43 | int EvrythngApi::getThngPropertyValue(const string& thngId, const string& key, string& value) |
vladounet | 0:d38d192c2f5f | 44 | { |
vladounet | 0:d38d192c2f5f | 45 | string path = THNG_PATH; |
vladounet | 0:d38d192c2f5f | 46 | path += thngId; |
vladounet | 0:d38d192c2f5f | 47 | path += THNG_PROP_PATH; |
vladounet | 0:d38d192c2f5f | 48 | path += key; |
vladounet | 0:d38d192c2f5f | 49 | path += "?from=latest"; |
vladounet | 0:d38d192c2f5f | 50 | string res; |
vladounet | 0:d38d192c2f5f | 51 | int err; |
vladounet | 0:d38d192c2f5f | 52 | int code; |
vladounet | 0:d38d192c2f5f | 53 | if ((err = httpGet(path, res, code)) != 0) return err; |
vladounet | 0:d38d192c2f5f | 54 | if (code != HTTP_OK) return EVRY_ERR_UNEXPECTEDHTTPSTATUS; |
vladounet | 0:d38d192c2f5f | 55 | JsonParser json; |
vladounet | 0:d38d192c2f5f | 56 | json.parse(res.c_str()); |
vladounet | 0:d38d192c2f5f | 57 | JsonValue* doc = json.getDocument(); |
vladounet | 0:d38d192c2f5f | 58 | const char* v = doc->getString("0/value"); |
vladounet | 0:d38d192c2f5f | 59 | if (v) { |
vladounet | 0:d38d192c2f5f | 60 | value.assign(v); |
vladounet | 0:d38d192c2f5f | 61 | return 0; |
vladounet | 0:d38d192c2f5f | 62 | } else { |
vladounet | 0:d38d192c2f5f | 63 | return -1; |
vladounet | 0:d38d192c2f5f | 64 | } |
vladounet | 0:d38d192c2f5f | 65 | } |
vladounet | 0:d38d192c2f5f | 66 | |
vladounet | 0:d38d192c2f5f | 67 | int EvrythngApi::setThngPropertyValue(const std::string& thngId, const std::string& key, const std::string& value, int64_t timestamp) |
vladounet | 0:d38d192c2f5f | 68 | { |
vladounet | 0:d38d192c2f5f | 69 | char strTimestamp[21]; |
vladounet | 0:d38d192c2f5f | 70 | char* end; |
vladounet | 0:d38d192c2f5f | 71 | sprinti64(strTimestamp, timestamp, &end); |
vladounet | 0:d38d192c2f5f | 72 | *end = '\0'; |
vladounet | 0:d38d192c2f5f | 73 | |
vladounet | 0:d38d192c2f5f | 74 | string path = THNG_PATH; |
vladounet | 0:d38d192c2f5f | 75 | path += thngId; |
vladounet | 0:d38d192c2f5f | 76 | path += THNG_PROP_PATH; |
vladounet | 0:d38d192c2f5f | 77 | path += key; |
vladounet | 0:d38d192c2f5f | 78 | |
vladounet | 0:d38d192c2f5f | 79 | string json = "[{\"timestamp\":"; |
vladounet | 0:d38d192c2f5f | 80 | json += strTimestamp; |
vladounet | 0:d38d192c2f5f | 81 | json += ",\"value\":\""; |
vladounet | 0:d38d192c2f5f | 82 | json += value; |
vladounet | 0:d38d192c2f5f | 83 | json += "\"}]"; |
vladounet | 0:d38d192c2f5f | 84 | |
vladounet | 0:d38d192c2f5f | 85 | string res; |
vladounet | 0:d38d192c2f5f | 86 | int err; |
vladounet | 0:d38d192c2f5f | 87 | int code; |
vladounet | 0:d38d192c2f5f | 88 | if ((err = httpPut(path, json, res, code)) != 0) return err; |
vladounet | 0:d38d192c2f5f | 89 | if (code != HTTP_OK) return EVRY_ERR_UNEXPECTEDHTTPSTATUS; |
vladounet | 0:d38d192c2f5f | 90 | |
vladounet | 0:d38d192c2f5f | 91 | return 0; |
vladounet | 0:d38d192c2f5f | 92 | } |
vladounet | 0:d38d192c2f5f | 93 | |
vladounet | 0:d38d192c2f5f | 94 | |
vladounet | 0:d38d192c2f5f | 95 | int EvrythngApi::httpRequest(HttpMethod method, const string& path, const string& content, string& out, int& codeOut) |
vladounet | 0:d38d192c2f5f | 96 | { |
vladounet | 0:d38d192c2f5f | 97 | int ret; |
vladounet | 0:d38d192c2f5f | 98 | |
vladounet | 0:d38d192c2f5f | 99 | const char* strMethod; |
vladounet | 0:d38d192c2f5f | 100 | switch (method) { |
vladounet | 0:d38d192c2f5f | 101 | case GET: |
vladounet | 0:d38d192c2f5f | 102 | strMethod = "GET"; |
vladounet | 0:d38d192c2f5f | 103 | break; |
vladounet | 0:d38d192c2f5f | 104 | case PUT: |
vladounet | 0:d38d192c2f5f | 105 | strMethod = "PUT"; |
vladounet | 0:d38d192c2f5f | 106 | break; |
vladounet | 0:d38d192c2f5f | 107 | case POST: |
vladounet | 0:d38d192c2f5f | 108 | strMethod = "POST"; |
vladounet | 0:d38d192c2f5f | 109 | break; |
vladounet | 0:d38d192c2f5f | 110 | case DELETE: |
vladounet | 0:d38d192c2f5f | 111 | strMethod = "DELETE"; |
vladounet | 0:d38d192c2f5f | 112 | break; |
vladounet | 0:d38d192c2f5f | 113 | default: |
vladounet | 0:d38d192c2f5f | 114 | return EVRY_ERR_UNSUPPORTED; |
vladounet | 0:d38d192c2f5f | 115 | } |
vladounet | 0:d38d192c2f5f | 116 | |
vladounet | 0:d38d192c2f5f | 117 | char contentLength[16]; |
vladounet | 0:d38d192c2f5f | 118 | snprintf(contentLength, sizeof(contentLength), "%d", content.size()); |
vladounet | 0:d38d192c2f5f | 119 | |
vladounet | 0:d38d192c2f5f | 120 | string req = strMethod; |
vladounet | 0:d38d192c2f5f | 121 | req += " "; |
vladounet | 0:d38d192c2f5f | 122 | req += path; |
vladounet | 0:d38d192c2f5f | 123 | req += " HTTP/1.0\r\n" |
vladounet | 0:d38d192c2f5f | 124 | "Host: "; |
vladounet | 0:d38d192c2f5f | 125 | req += host; |
vladounet | 0:d38d192c2f5f | 126 | req += "\r\n" |
vladounet | 0:d38d192c2f5f | 127 | "Accept: application/json\r\n" |
vladounet | 0:d38d192c2f5f | 128 | "Content-Length: "; |
vladounet | 0:d38d192c2f5f | 129 | req += contentLength; |
vladounet | 0:d38d192c2f5f | 130 | req += "\r\n" |
vladounet | 0:d38d192c2f5f | 131 | "Content-Type: application/json\r\n" |
vladounet | 0:d38d192c2f5f | 132 | "Connection: close\r\n" |
vladounet | 0:d38d192c2f5f | 133 | "Authorization: "; |
vladounet | 0:d38d192c2f5f | 134 | req += token; |
vladounet | 0:d38d192c2f5f | 135 | req += "\r\n\r\n"; |
vladounet | 0:d38d192c2f5f | 136 | |
vladounet | 0:d38d192c2f5f | 137 | req += content; |
vladounet | 0:d38d192c2f5f | 138 | |
vladounet | 0:d38d192c2f5f | 139 | #ifdef DEBUG_EVRYTHNG_API |
vladounet | 0:d38d192c2f5f | 140 | dbg.printf("%s\r\n\r\n", req.c_str()); |
vladounet | 0:d38d192c2f5f | 141 | #endif |
vladounet | 0:d38d192c2f5f | 142 | |
vladounet | 0:d38d192c2f5f | 143 | TCPSocketConnection socket; |
vladounet | 0:d38d192c2f5f | 144 | |
vladounet | 0:d38d192c2f5f | 145 | out.clear(); |
vladounet | 0:d38d192c2f5f | 146 | |
vladounet | 0:d38d192c2f5f | 147 | string res; |
vladounet | 0:d38d192c2f5f | 148 | |
vladounet | 0:d38d192c2f5f | 149 | if (socket.connect(host.c_str(), port) == 0) { |
vladounet | 0:d38d192c2f5f | 150 | |
vladounet | 0:d38d192c2f5f | 151 | char* snd = new char[req.size()+1]; |
vladounet | 0:d38d192c2f5f | 152 | req.copy(snd, req.size()); |
vladounet | 0:d38d192c2f5f | 153 | snd[req.size()]='\0'; |
vladounet | 0:d38d192c2f5f | 154 | bool sent = socket.send_all(snd, req.size()) >= 0; |
vladounet | 0:d38d192c2f5f | 155 | delete[] snd; |
vladounet | 0:d38d192c2f5f | 156 | |
vladounet | 0:d38d192c2f5f | 157 | if (sent) { |
vladounet | 0:d38d192c2f5f | 158 | |
vladounet | 0:d38d192c2f5f | 159 | char rcv[256]; |
vladounet | 0:d38d192c2f5f | 160 | |
vladounet | 0:d38d192c2f5f | 161 | int r; |
vladounet | 0:d38d192c2f5f | 162 | while (true) { |
vladounet | 0:d38d192c2f5f | 163 | r = socket.receive(rcv, sizeof(rcv)); |
vladounet | 0:d38d192c2f5f | 164 | if (r <= 0) |
vladounet | 0:d38d192c2f5f | 165 | break; |
vladounet | 0:d38d192c2f5f | 166 | res.append(rcv, r); |
vladounet | 0:d38d192c2f5f | 167 | } |
vladounet | 0:d38d192c2f5f | 168 | |
vladounet | 0:d38d192c2f5f | 169 | ret = EVRY_ERR_OK; |
vladounet | 0:d38d192c2f5f | 170 | |
vladounet | 0:d38d192c2f5f | 171 | } else { |
vladounet | 0:d38d192c2f5f | 172 | ret = EVRY_ERR_CANTSEND; |
vladounet | 0:d38d192c2f5f | 173 | } |
vladounet | 0:d38d192c2f5f | 174 | |
vladounet | 0:d38d192c2f5f | 175 | socket.close(); |
vladounet | 0:d38d192c2f5f | 176 | |
vladounet | 0:d38d192c2f5f | 177 | } else { |
vladounet | 0:d38d192c2f5f | 178 | ret = EVRY_ERR_CANTCONNECT; |
vladounet | 0:d38d192c2f5f | 179 | } |
vladounet | 0:d38d192c2f5f | 180 | |
vladounet | 0:d38d192c2f5f | 181 | #ifdef DEBUG_EVRYTHNG_API |
vladounet | 0:d38d192c2f5f | 182 | dbg.printf("%s", res.c_str()); |
vladounet | 0:d38d192c2f5f | 183 | #endif |
vladounet | 0:d38d192c2f5f | 184 | |
vladounet | 0:d38d192c2f5f | 185 | if (res.compare(0,5,"HTTP/") != 0) { |
vladounet | 0:d38d192c2f5f | 186 | return EVRY_ERR_UNKNOWN; |
vladounet | 0:d38d192c2f5f | 187 | } |
vladounet | 0:d38d192c2f5f | 188 | |
vladounet | 0:d38d192c2f5f | 189 | int spPos = res.find(' ', 5); |
vladounet | 0:d38d192c2f5f | 190 | if (spPos == string::npos) { |
vladounet | 0:d38d192c2f5f | 191 | return EVRY_ERR_UNKNOWN; |
vladounet | 0:d38d192c2f5f | 192 | } |
vladounet | 0:d38d192c2f5f | 193 | |
vladounet | 0:d38d192c2f5f | 194 | // TODO: check str length |
vladounet | 0:d38d192c2f5f | 195 | int code = atoi(res.c_str()+spPos+1); |
vladounet | 0:d38d192c2f5f | 196 | if (code < 100 || code > 999) { |
vladounet | 0:d38d192c2f5f | 197 | return EVRY_ERR_UNKNOWN; |
vladounet | 0:d38d192c2f5f | 198 | } |
vladounet | 0:d38d192c2f5f | 199 | codeOut = code; |
vladounet | 0:d38d192c2f5f | 200 | |
vladounet | 0:d38d192c2f5f | 201 | int startContent = res.find("\r\n\r\n"); |
vladounet | 0:d38d192c2f5f | 202 | if (startContent != string::npos) { |
vladounet | 0:d38d192c2f5f | 203 | out.append(res.substr(startContent+4,res.size()-startContent-4)); |
vladounet | 0:d38d192c2f5f | 204 | } |
vladounet | 0:d38d192c2f5f | 205 | |
vladounet | 0:d38d192c2f5f | 206 | return ret; |
vladounet | 0:d38d192c2f5f | 207 | } |
vladounet | 0:d38d192c2f5f | 208 | |
vladounet | 0:d38d192c2f5f | 209 | int EvrythngApi::httpPut(const string& path, const string& json, string& out, int& codeOut) |
vladounet | 0:d38d192c2f5f | 210 | { |
vladounet | 0:d38d192c2f5f | 211 | return httpRequest(PUT, path, json, out, codeOut); |
vladounet | 0:d38d192c2f5f | 212 | } |
vladounet | 0:d38d192c2f5f | 213 | |
vladounet | 0:d38d192c2f5f | 214 | int EvrythngApi::httpGet(const string& path, string& out, int& codeOut) |
vladounet | 0:d38d192c2f5f | 215 | { |
vladounet | 0:d38d192c2f5f | 216 | return httpRequest(GET, path, "", out, codeOut); |
vladounet | 0:d38d192c2f5f | 217 | } |
vladounet | 0:d38d192c2f5f | 218 | |
vladounet | 0:d38d192c2f5f | 219 | int EvrythngApi::httpPost(const string& path, const string& json, string& out, int& codeOut) |
vladounet | 0:d38d192c2f5f | 220 | { |
vladounet | 0:d38d192c2f5f | 221 | return httpRequest(POST, path, json, out, codeOut); |
vladounet | 0:d38d192c2f5f | 222 | } |
vladounet | 0:d38d192c2f5f | 223 | |
vladounet | 0:d38d192c2f5f | 224 | int EvrythngApi::httpDelete(const string& path, string& out, int& codeOut) |
vladounet | 0:d38d192c2f5f | 225 | { |
vladounet | 0:d38d192c2f5f | 226 | return httpRequest(DELETE, path, "", out, codeOut); |
vladounet | 0:d38d192c2f5f | 227 | } |