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