Home Alert System

Dependencies:   PWM_Tone_Library DHT

Committer:
aziz111
Date:
Fri Mar 08 17:15:02 2019 +0000
Revision:
5:569a4894abc1
Parent:
3:78f223d34f36
Final

Who changed what in which revision?

UserRevisionLine numberNew contents of line
ethaderu 3:78f223d34f36 1 #include "M2XStreamClient.h"
ethaderu 3:78f223d34f36 2
ethaderu 3:78f223d34f36 3 #include <jsonlite.h>
ethaderu 3:78f223d34f36 4
ethaderu 3:78f223d34f36 5 #include "StreamParseFunctions.h"
ethaderu 3:78f223d34f36 6 #include "LocationParseFunctions.h"
ethaderu 3:78f223d34f36 7
ethaderu 3:78f223d34f36 8 const char* M2XStreamClient::kDefaultM2XHost = "api-m2x.att.com";
ethaderu 3:78f223d34f36 9
ethaderu 3:78f223d34f36 10 static int write_delete_values(Print* print, const char* from, const char* end);
ethaderu 3:78f223d34f36 11 int print_encoded_string(Print* print, const char* str);
ethaderu 3:78f223d34f36 12 int tolower(int ch);
ethaderu 3:78f223d34f36 13
ethaderu 3:78f223d34f36 14 #if defined(ARDUINO_PLATFORM) || defined(MBED_PLATFORM)
ethaderu 3:78f223d34f36 15 int tolower(int ch)
ethaderu 3:78f223d34f36 16 {
ethaderu 3:78f223d34f36 17 // Arduino and mbed use ASCII table, so we can simplify the implementation
ethaderu 3:78f223d34f36 18 if ((ch >= 'A') && (ch <= 'Z')) {
ethaderu 3:78f223d34f36 19 return (ch + 32);
ethaderu 3:78f223d34f36 20 }
ethaderu 3:78f223d34f36 21 return ch;
ethaderu 3:78f223d34f36 22 }
ethaderu 3:78f223d34f36 23 #else
ethaderu 3:78f223d34f36 24 // For other platform, we use libc's tolower by default
ethaderu 3:78f223d34f36 25 #include <ctype.h>
ethaderu 3:78f223d34f36 26 #endif
ethaderu 3:78f223d34f36 27
ethaderu 3:78f223d34f36 28 M2XStreamClient::M2XStreamClient(Client* client,
ethaderu 3:78f223d34f36 29 const char* key,
ethaderu 3:78f223d34f36 30 int case_insensitive,
ethaderu 3:78f223d34f36 31 const char* host,
ethaderu 3:78f223d34f36 32 int port,
ethaderu 3:78f223d34f36 33 const char* path_prefix) : _client(client),
ethaderu 3:78f223d34f36 34 _key(key),
ethaderu 3:78f223d34f36 35 _case_insensitive(case_insensitive),
ethaderu 3:78f223d34f36 36 _host(host),
ethaderu 3:78f223d34f36 37 _port(port),
ethaderu 3:78f223d34f36 38 _path_prefix(path_prefix),
ethaderu 3:78f223d34f36 39 _null_print() {
ethaderu 3:78f223d34f36 40 }
ethaderu 3:78f223d34f36 41
ethaderu 3:78f223d34f36 42 int M2XStreamClient::listStreamValues(const char* deviceId, const char* streamName,
ethaderu 3:78f223d34f36 43 stream_value_read_callback callback, void* context,
ethaderu 3:78f223d34f36 44 const char* query) {
ethaderu 3:78f223d34f36 45 if (_client->connect(_host, _port)) {
ethaderu 3:78f223d34f36 46 DBGLN("%s", "Connected to M2X server!");
ethaderu 3:78f223d34f36 47 _client->print("GET ");
ethaderu 3:78f223d34f36 48 if (_path_prefix)
ethaderu 3:78f223d34f36 49 _client->print(_path_prefix);
ethaderu 3:78f223d34f36 50 _client->print("/v2/devices/");
ethaderu 3:78f223d34f36 51 print_encoded_string(_client, deviceId);
ethaderu 3:78f223d34f36 52 _client->print("/streams/");
ethaderu 3:78f223d34f36 53 print_encoded_string(_client, streamName);
ethaderu 3:78f223d34f36 54 _client->print("/values.json");
ethaderu 3:78f223d34f36 55
ethaderu 3:78f223d34f36 56 if (query) {
ethaderu 3:78f223d34f36 57 if (query[0] != '?') {
ethaderu 3:78f223d34f36 58 _client->print('?');
ethaderu 3:78f223d34f36 59 }
ethaderu 3:78f223d34f36 60 _client->print(query);
ethaderu 3:78f223d34f36 61 }
ethaderu 3:78f223d34f36 62
ethaderu 3:78f223d34f36 63 _client->println(" HTTP/1.0");
ethaderu 3:78f223d34f36 64 writeHttpHeader(-1);
ethaderu 3:78f223d34f36 65 } else {
ethaderu 3:78f223d34f36 66 DBGLN("%s", "ERROR: Cannot connect to M2X server!");
ethaderu 3:78f223d34f36 67 return E_NOCONNECTION;
ethaderu 3:78f223d34f36 68 }
ethaderu 3:78f223d34f36 69 int status = readStatusCode(false);
ethaderu 3:78f223d34f36 70 if (status == 200) {
ethaderu 3:78f223d34f36 71 readStreamValue(callback, context);
ethaderu 3:78f223d34f36 72 }
ethaderu 3:78f223d34f36 73
ethaderu 3:78f223d34f36 74 close();
ethaderu 3:78f223d34f36 75 return status;
ethaderu 3:78f223d34f36 76 }
ethaderu 3:78f223d34f36 77
ethaderu 3:78f223d34f36 78 int M2XStreamClient::readLocation(const char* deviceId,
ethaderu 3:78f223d34f36 79 location_read_callback callback,
ethaderu 3:78f223d34f36 80 void* context) {
ethaderu 3:78f223d34f36 81 if (_client->connect(_host, _port)) {
ethaderu 3:78f223d34f36 82 DBGLN("%s", "Connected to M2X server!");
ethaderu 3:78f223d34f36 83 _client->print("GET ");
ethaderu 3:78f223d34f36 84 if (_path_prefix)
ethaderu 3:78f223d34f36 85 _client->print(_path_prefix);
ethaderu 3:78f223d34f36 86 _client->print("/v2/devices/");
ethaderu 3:78f223d34f36 87 print_encoded_string(_client, deviceId);
ethaderu 3:78f223d34f36 88 _client->println("/location HTTP/1.0");
ethaderu 3:78f223d34f36 89
ethaderu 3:78f223d34f36 90 writeHttpHeader(-1);
ethaderu 3:78f223d34f36 91 } else {
ethaderu 3:78f223d34f36 92 DBGLN("%s", "ERROR: Cannot connect to M2X server!");
ethaderu 3:78f223d34f36 93 return E_NOCONNECTION;
ethaderu 3:78f223d34f36 94 }
ethaderu 3:78f223d34f36 95 int status = readStatusCode(false);
ethaderu 3:78f223d34f36 96 if (status == 200) {
ethaderu 3:78f223d34f36 97 readLocation(callback, context);
ethaderu 3:78f223d34f36 98 }
ethaderu 3:78f223d34f36 99
ethaderu 3:78f223d34f36 100 close();
ethaderu 3:78f223d34f36 101 return status;
ethaderu 3:78f223d34f36 102 }
ethaderu 3:78f223d34f36 103
ethaderu 3:78f223d34f36 104 int M2XStreamClient::deleteValues(const char* deviceId, const char* streamName,
ethaderu 3:78f223d34f36 105 const char* from, const char* end) {
ethaderu 3:78f223d34f36 106 if (_client->connect(_host, _port)) {
ethaderu 3:78f223d34f36 107 DBGLN("%s", "Connected to M2X server!");
ethaderu 3:78f223d34f36 108 int length = write_delete_values(&_null_print, from, end);
ethaderu 3:78f223d34f36 109 writeDeleteHeader(deviceId, streamName, length);
ethaderu 3:78f223d34f36 110 write_delete_values(_client, from, end);
ethaderu 3:78f223d34f36 111 } else {
ethaderu 3:78f223d34f36 112 DBGLN("%s", "ERROR: Cannot connect to M2X server!");
ethaderu 3:78f223d34f36 113 return E_NOCONNECTION;
ethaderu 3:78f223d34f36 114 }
ethaderu 3:78f223d34f36 115
ethaderu 3:78f223d34f36 116 return readStatusCode(true);
ethaderu 3:78f223d34f36 117 }
ethaderu 3:78f223d34f36 118
ethaderu 3:78f223d34f36 119 static int write_delete_values(Print* print, const char* from,
ethaderu 3:78f223d34f36 120 const char* end) {
ethaderu 3:78f223d34f36 121 int bytes = 0;
ethaderu 3:78f223d34f36 122 bytes += print->print("{\"from\":\"");
ethaderu 3:78f223d34f36 123 bytes += print->print(from);
ethaderu 3:78f223d34f36 124 bytes += print->print("\",\"end\":\"");
ethaderu 3:78f223d34f36 125 bytes += print->print(end);
ethaderu 3:78f223d34f36 126 bytes += print->print("\"}");
ethaderu 3:78f223d34f36 127 return bytes;
ethaderu 3:78f223d34f36 128 }
ethaderu 3:78f223d34f36 129
ethaderu 3:78f223d34f36 130 // Encodes and prints string using Percent-encoding specified
ethaderu 3:78f223d34f36 131 // in RFC 1738, Section 2.2
ethaderu 3:78f223d34f36 132 int print_encoded_string(Print* print, const char* str) {
ethaderu 3:78f223d34f36 133 int bytes = 0;
ethaderu 3:78f223d34f36 134 for (int i = 0; str[i] != 0; i++) {
ethaderu 3:78f223d34f36 135 if (((str[i] >= 'A') && (str[i] <= 'Z')) ||
ethaderu 3:78f223d34f36 136 ((str[i] >= 'a') && (str[i] <= 'z')) ||
ethaderu 3:78f223d34f36 137 ((str[i] >= '0') && (str[i] <= '9')) ||
ethaderu 3:78f223d34f36 138 (str[i] == '-') || (str[i] == '_') ||
ethaderu 3:78f223d34f36 139 (str[i] == '.') || (str[i] == '~')) {
ethaderu 3:78f223d34f36 140 bytes += print->print(str[i]);
ethaderu 3:78f223d34f36 141 } else {
ethaderu 3:78f223d34f36 142 // Encode all other characters
ethaderu 3:78f223d34f36 143 bytes += print->print('%');
ethaderu 3:78f223d34f36 144 bytes += print->print(HEX(str[i] / 16));
ethaderu 3:78f223d34f36 145 bytes += print->print(HEX(str[i] % 16));
ethaderu 3:78f223d34f36 146 }
ethaderu 3:78f223d34f36 147 }
ethaderu 3:78f223d34f36 148 return bytes;
ethaderu 3:78f223d34f36 149 }
ethaderu 3:78f223d34f36 150
ethaderu 3:78f223d34f36 151 void M2XStreamClient::writePutHeader(const char* deviceId,
ethaderu 3:78f223d34f36 152 const char* streamName,
ethaderu 3:78f223d34f36 153 int contentLength) {
ethaderu 3:78f223d34f36 154 _client->print("PUT ");
ethaderu 3:78f223d34f36 155 if (_path_prefix)
ethaderu 3:78f223d34f36 156 _client->print(_path_prefix);
ethaderu 3:78f223d34f36 157 _client->print("/v2/devices/");
ethaderu 3:78f223d34f36 158 print_encoded_string(_client, deviceId);
ethaderu 3:78f223d34f36 159 _client->print("/streams/");
ethaderu 3:78f223d34f36 160 print_encoded_string(_client, streamName);
ethaderu 3:78f223d34f36 161 _client->println("/value HTTP/1.0");
ethaderu 3:78f223d34f36 162
ethaderu 3:78f223d34f36 163 writeHttpHeader(contentLength);
ethaderu 3:78f223d34f36 164 }
ethaderu 3:78f223d34f36 165
ethaderu 3:78f223d34f36 166 void M2XStreamClient::writeDeleteHeader(const char* deviceId,
ethaderu 3:78f223d34f36 167 const char* streamName,
ethaderu 3:78f223d34f36 168 int contentLength) {
ethaderu 3:78f223d34f36 169 _client->print("DELETE ");
ethaderu 3:78f223d34f36 170 if (_path_prefix)
ethaderu 3:78f223d34f36 171 _client->print(_path_prefix);
ethaderu 3:78f223d34f36 172 _client->print("/v2/devices/");
ethaderu 3:78f223d34f36 173 print_encoded_string(_client, deviceId);
ethaderu 3:78f223d34f36 174 _client->print("/streams/");
ethaderu 3:78f223d34f36 175 print_encoded_string(_client, streamName);
ethaderu 3:78f223d34f36 176 _client->print("/values");
ethaderu 3:78f223d34f36 177 _client->println(" HTTP/1.0");
ethaderu 3:78f223d34f36 178
ethaderu 3:78f223d34f36 179 writeHttpHeader(contentLength);
ethaderu 3:78f223d34f36 180 }
ethaderu 3:78f223d34f36 181
ethaderu 3:78f223d34f36 182 void M2XStreamClient::writeHttpHeader(int contentLength) {
ethaderu 3:78f223d34f36 183 _client->println(USER_AGENT);
ethaderu 3:78f223d34f36 184 _client->print("X-M2X-KEY: ");
ethaderu 3:78f223d34f36 185 _client->println(_key);
ethaderu 3:78f223d34f36 186
ethaderu 3:78f223d34f36 187 _client->print("Host: ");
ethaderu 3:78f223d34f36 188 print_encoded_string(_client, _host);
ethaderu 3:78f223d34f36 189 if (_port != kDefaultM2XPort) {
ethaderu 3:78f223d34f36 190 _client->print(":");
ethaderu 3:78f223d34f36 191 // port is an integer, does not need encoding
ethaderu 3:78f223d34f36 192 _client->print(_port);
ethaderu 3:78f223d34f36 193 }
ethaderu 3:78f223d34f36 194 _client->println();
ethaderu 3:78f223d34f36 195
ethaderu 3:78f223d34f36 196 if (contentLength > 0) {
ethaderu 3:78f223d34f36 197 _client->println("Content-Type: application/json");
ethaderu 3:78f223d34f36 198 DBG("%s", "Content Length: ");
ethaderu 3:78f223d34f36 199 DBGLN("%d", contentLength);
ethaderu 3:78f223d34f36 200
ethaderu 3:78f223d34f36 201 _client->print("Content-Length: ");
ethaderu 3:78f223d34f36 202 _client->println(contentLength);
ethaderu 3:78f223d34f36 203 }
ethaderu 3:78f223d34f36 204 _client->println();
ethaderu 3:78f223d34f36 205 }
ethaderu 3:78f223d34f36 206
ethaderu 3:78f223d34f36 207 int M2XStreamClient::waitForString(const char* str) {
ethaderu 3:78f223d34f36 208 int currentIndex = 0;
ethaderu 3:78f223d34f36 209 if (str[currentIndex] == '\0') return E_OK;
ethaderu 3:78f223d34f36 210
ethaderu 3:78f223d34f36 211 while (true) {
ethaderu 3:78f223d34f36 212 while (_client->available()) {
ethaderu 3:78f223d34f36 213 char c = _client->read();
ethaderu 3:78f223d34f36 214 DBG("%c", c);
ethaderu 3:78f223d34f36 215
ethaderu 3:78f223d34f36 216 int cmp;
ethaderu 3:78f223d34f36 217 if (_case_insensitive) {
ethaderu 3:78f223d34f36 218 cmp = tolower(c) - tolower(str[currentIndex]);
ethaderu 3:78f223d34f36 219 } else {
ethaderu 3:78f223d34f36 220 cmp = c - str[currentIndex];
ethaderu 3:78f223d34f36 221 }
ethaderu 3:78f223d34f36 222
ethaderu 3:78f223d34f36 223 if ((str[currentIndex] == '*') || (cmp == 0)) {
ethaderu 3:78f223d34f36 224 currentIndex++;
ethaderu 3:78f223d34f36 225 if (str[currentIndex] == '\0') {
ethaderu 3:78f223d34f36 226 return E_OK;
ethaderu 3:78f223d34f36 227 }
ethaderu 3:78f223d34f36 228 } else {
ethaderu 3:78f223d34f36 229 // start from the beginning
ethaderu 3:78f223d34f36 230 currentIndex = 0;
ethaderu 3:78f223d34f36 231 }
ethaderu 3:78f223d34f36 232 }
ethaderu 3:78f223d34f36 233
ethaderu 3:78f223d34f36 234 if (!_client->connected()) {
ethaderu 3:78f223d34f36 235 DBGLN("%s", "ERROR: The client is disconnected from the server!");
ethaderu 3:78f223d34f36 236
ethaderu 3:78f223d34f36 237 close();
ethaderu 3:78f223d34f36 238 return E_DISCONNECTED;
ethaderu 3:78f223d34f36 239 }
ethaderu 3:78f223d34f36 240
ethaderu 3:78f223d34f36 241 delay(1000);
ethaderu 3:78f223d34f36 242 }
ethaderu 3:78f223d34f36 243 // never reached here
ethaderu 3:78f223d34f36 244 return E_NOTREACHABLE;
ethaderu 3:78f223d34f36 245 }
ethaderu 3:78f223d34f36 246
ethaderu 3:78f223d34f36 247 int M2XStreamClient::readStatusCode(bool closeClient) {
ethaderu 3:78f223d34f36 248 int responseCode = 0;
ethaderu 3:78f223d34f36 249 int ret = waitForString("HTTP/*.* ");
ethaderu 3:78f223d34f36 250 if (ret != E_OK) {
ethaderu 3:78f223d34f36 251 if (closeClient) close();
ethaderu 3:78f223d34f36 252 return ret;
ethaderu 3:78f223d34f36 253 }
ethaderu 3:78f223d34f36 254
ethaderu 3:78f223d34f36 255 // ret is not needed from here(since it must be E_OK), so we can use it
ethaderu 3:78f223d34f36 256 // as a regular variable now.
ethaderu 3:78f223d34f36 257 ret = 0;
ethaderu 3:78f223d34f36 258 while (true) {
ethaderu 3:78f223d34f36 259 while (_client->available()) {
ethaderu 3:78f223d34f36 260 char c = _client->read();
ethaderu 3:78f223d34f36 261 DBG("%c", c);
ethaderu 3:78f223d34f36 262
ethaderu 3:78f223d34f36 263 responseCode = responseCode * 10 + (c - '0');
ethaderu 3:78f223d34f36 264 ret++;
ethaderu 3:78f223d34f36 265 if (ret == 3) {
ethaderu 3:78f223d34f36 266 if (closeClient) close();
ethaderu 3:78f223d34f36 267 return responseCode;
ethaderu 3:78f223d34f36 268 }
ethaderu 3:78f223d34f36 269 }
ethaderu 3:78f223d34f36 270
ethaderu 3:78f223d34f36 271 if (!_client->connected()) {
ethaderu 3:78f223d34f36 272 DBGLN("%s", "ERROR: The client is disconnected from the server!");
ethaderu 3:78f223d34f36 273
ethaderu 3:78f223d34f36 274 if (closeClient) close();
ethaderu 3:78f223d34f36 275 return E_DISCONNECTED;
ethaderu 3:78f223d34f36 276 }
ethaderu 3:78f223d34f36 277
ethaderu 3:78f223d34f36 278 delay(1000);
ethaderu 3:78f223d34f36 279 }
ethaderu 3:78f223d34f36 280
ethaderu 3:78f223d34f36 281 // never reached here
ethaderu 3:78f223d34f36 282 return E_NOTREACHABLE;
ethaderu 3:78f223d34f36 283 }
ethaderu 3:78f223d34f36 284
ethaderu 3:78f223d34f36 285 int M2XStreamClient::readContentLength() {
ethaderu 3:78f223d34f36 286 int ret = waitForString("Content-Length: ");
ethaderu 3:78f223d34f36 287 if (ret != E_OK) {
ethaderu 3:78f223d34f36 288 return ret;
ethaderu 3:78f223d34f36 289 }
ethaderu 3:78f223d34f36 290
ethaderu 3:78f223d34f36 291 // From now on, ret is not needed, we can use it
ethaderu 3:78f223d34f36 292 // to keep the final result
ethaderu 3:78f223d34f36 293 ret = 0;
ethaderu 3:78f223d34f36 294 while (true) {
ethaderu 3:78f223d34f36 295 while (_client->available()) {
ethaderu 3:78f223d34f36 296 char c = _client->read();
ethaderu 3:78f223d34f36 297 DBG("%c", c);
ethaderu 3:78f223d34f36 298
ethaderu 3:78f223d34f36 299 if ((c == '\r') || (c == '\n')) {
ethaderu 3:78f223d34f36 300 return (ret == 0) ? (E_INVALID) : (ret);
ethaderu 3:78f223d34f36 301 } else {
ethaderu 3:78f223d34f36 302 ret = ret * 10 + (c - '0');
ethaderu 3:78f223d34f36 303 }
ethaderu 3:78f223d34f36 304 }
ethaderu 3:78f223d34f36 305
ethaderu 3:78f223d34f36 306 if (!_client->connected()) {
ethaderu 3:78f223d34f36 307 DBGLN("%s", "ERROR: The client is disconnected from the server!");
ethaderu 3:78f223d34f36 308
ethaderu 3:78f223d34f36 309 return E_DISCONNECTED;
ethaderu 3:78f223d34f36 310 }
ethaderu 3:78f223d34f36 311
ethaderu 3:78f223d34f36 312 delay(1000);
ethaderu 3:78f223d34f36 313 }
ethaderu 3:78f223d34f36 314
ethaderu 3:78f223d34f36 315 // never reached here
ethaderu 3:78f223d34f36 316 return E_NOTREACHABLE;
ethaderu 3:78f223d34f36 317 }
ethaderu 3:78f223d34f36 318
ethaderu 3:78f223d34f36 319 int M2XStreamClient::skipHttpHeader() {
ethaderu 3:78f223d34f36 320 return waitForString("\r\n\r\n");
ethaderu 3:78f223d34f36 321 }
ethaderu 3:78f223d34f36 322
ethaderu 3:78f223d34f36 323 void M2XStreamClient::close() {
ethaderu 3:78f223d34f36 324 // Eats up buffered data before closing
ethaderu 3:78f223d34f36 325 _client->flush();
ethaderu 3:78f223d34f36 326 _client->stop();
ethaderu 3:78f223d34f36 327 }
ethaderu 3:78f223d34f36 328
ethaderu 3:78f223d34f36 329 int M2XStreamClient::readStreamValue(stream_value_read_callback callback,
ethaderu 3:78f223d34f36 330 void* context) {
ethaderu 3:78f223d34f36 331 const int BUF_LEN = 64;
ethaderu 3:78f223d34f36 332 char buf[BUF_LEN];
ethaderu 3:78f223d34f36 333
ethaderu 3:78f223d34f36 334 int length = readContentLength();
ethaderu 3:78f223d34f36 335 if (length < 0) {
ethaderu 3:78f223d34f36 336 close();
ethaderu 3:78f223d34f36 337 return length;
ethaderu 3:78f223d34f36 338 }
ethaderu 3:78f223d34f36 339
ethaderu 3:78f223d34f36 340 int index = skipHttpHeader();
ethaderu 3:78f223d34f36 341 if (index != E_OK) {
ethaderu 3:78f223d34f36 342 close();
ethaderu 3:78f223d34f36 343 return index;
ethaderu 3:78f223d34f36 344 }
ethaderu 3:78f223d34f36 345 index = 0;
ethaderu 3:78f223d34f36 346
ethaderu 3:78f223d34f36 347 stream_parsing_context_state state;
ethaderu 3:78f223d34f36 348 state.state = state.index = 0;
ethaderu 3:78f223d34f36 349 state.callback = callback;
ethaderu 3:78f223d34f36 350 state.context = context;
ethaderu 3:78f223d34f36 351
ethaderu 3:78f223d34f36 352 jsonlite_parser_callbacks cbs = jsonlite_default_callbacks;
ethaderu 3:78f223d34f36 353 cbs.key_found = on_stream_key_found;
ethaderu 3:78f223d34f36 354 cbs.number_found = on_stream_number_found;
ethaderu 3:78f223d34f36 355 cbs.string_found = on_stream_string_found;
ethaderu 3:78f223d34f36 356 cbs.context.client_state = &state;
ethaderu 3:78f223d34f36 357
ethaderu 3:78f223d34f36 358 jsonlite_parser p = jsonlite_parser_init(jsonlite_parser_estimate_size(5));
ethaderu 3:78f223d34f36 359 jsonlite_parser_set_callback(p, &cbs);
ethaderu 3:78f223d34f36 360
ethaderu 3:78f223d34f36 361 jsonlite_result result = jsonlite_result_unknown;
ethaderu 3:78f223d34f36 362 while (index < length) {
ethaderu 3:78f223d34f36 363 int i = 0;
ethaderu 3:78f223d34f36 364
ethaderu 3:78f223d34f36 365 DBG("%s", "Received Data: ");
ethaderu 3:78f223d34f36 366 while ((i < BUF_LEN) && _client->available()) {
ethaderu 3:78f223d34f36 367 buf[i++] = _client->read();
ethaderu 3:78f223d34f36 368 DBG("%c", buf[i - 1]);
ethaderu 3:78f223d34f36 369 }
ethaderu 3:78f223d34f36 370 DBGLNEND;
ethaderu 3:78f223d34f36 371
ethaderu 3:78f223d34f36 372 if ((!_client->connected()) &&
ethaderu 3:78f223d34f36 373 (!_client->available()) &&
ethaderu 3:78f223d34f36 374 ((index + i) < length)) {
ethaderu 3:78f223d34f36 375 jsonlite_parser_release(p);
ethaderu 3:78f223d34f36 376 close();
ethaderu 3:78f223d34f36 377 return E_NOCONNECTION;
ethaderu 3:78f223d34f36 378 }
ethaderu 3:78f223d34f36 379
ethaderu 3:78f223d34f36 380 result = jsonlite_parser_tokenize(p, buf, i);
ethaderu 3:78f223d34f36 381 if ((result != jsonlite_result_ok) &&
ethaderu 3:78f223d34f36 382 (result != jsonlite_result_end_of_stream)) {
ethaderu 3:78f223d34f36 383 jsonlite_parser_release(p);
ethaderu 3:78f223d34f36 384 close();
ethaderu 3:78f223d34f36 385 return E_JSON_INVALID;
ethaderu 3:78f223d34f36 386 }
ethaderu 3:78f223d34f36 387
ethaderu 3:78f223d34f36 388 index += i;
ethaderu 3:78f223d34f36 389 }
ethaderu 3:78f223d34f36 390
ethaderu 3:78f223d34f36 391 jsonlite_parser_release(p);
ethaderu 3:78f223d34f36 392 close();
ethaderu 3:78f223d34f36 393 return (result == jsonlite_result_ok) ? (E_OK) : (E_JSON_INVALID);
ethaderu 3:78f223d34f36 394 }
ethaderu 3:78f223d34f36 395
ethaderu 3:78f223d34f36 396 int M2XStreamClient::readLocation(location_read_callback callback,
ethaderu 3:78f223d34f36 397 void* context) {
ethaderu 3:78f223d34f36 398 const int BUF_LEN = 40;
ethaderu 3:78f223d34f36 399 char buf[BUF_LEN];
ethaderu 3:78f223d34f36 400
ethaderu 3:78f223d34f36 401 int length = readContentLength();
ethaderu 3:78f223d34f36 402 if (length < 0) {
ethaderu 3:78f223d34f36 403 close();
ethaderu 3:78f223d34f36 404 return length;
ethaderu 3:78f223d34f36 405 }
ethaderu 3:78f223d34f36 406
ethaderu 3:78f223d34f36 407 int index = skipHttpHeader();
ethaderu 3:78f223d34f36 408 if (index != E_OK) {
ethaderu 3:78f223d34f36 409 close();
ethaderu 3:78f223d34f36 410 return index;
ethaderu 3:78f223d34f36 411 }
ethaderu 3:78f223d34f36 412 index = 0;
ethaderu 3:78f223d34f36 413
ethaderu 3:78f223d34f36 414 location_parsing_context_state state;
ethaderu 3:78f223d34f36 415 state.state = state.index = 0;
ethaderu 3:78f223d34f36 416 state.callback = callback;
ethaderu 3:78f223d34f36 417 state.context = context;
ethaderu 3:78f223d34f36 418
ethaderu 3:78f223d34f36 419 jsonlite_parser_callbacks cbs = jsonlite_default_callbacks;
ethaderu 3:78f223d34f36 420 cbs.key_found = on_location_key_found;
ethaderu 3:78f223d34f36 421 cbs.string_found = on_location_string_found;
ethaderu 3:78f223d34f36 422 cbs.context.client_state = &state;
ethaderu 3:78f223d34f36 423
ethaderu 3:78f223d34f36 424 jsonlite_parser p = jsonlite_parser_init(jsonlite_parser_estimate_size(5));
ethaderu 3:78f223d34f36 425 jsonlite_parser_set_callback(p, &cbs);
ethaderu 3:78f223d34f36 426
ethaderu 3:78f223d34f36 427 jsonlite_result result = jsonlite_result_unknown;
ethaderu 3:78f223d34f36 428 while (index < length) {
ethaderu 3:78f223d34f36 429 int i = 0;
ethaderu 3:78f223d34f36 430
ethaderu 3:78f223d34f36 431 DBG("%s", "Received Data: ");
ethaderu 3:78f223d34f36 432 while ((i < BUF_LEN) && _client->available()) {
ethaderu 3:78f223d34f36 433 buf[i++] = _client->read();
ethaderu 3:78f223d34f36 434 DBG("%c", buf[i - 1]);
ethaderu 3:78f223d34f36 435 }
ethaderu 3:78f223d34f36 436 DBGLNEND;
ethaderu 3:78f223d34f36 437
ethaderu 3:78f223d34f36 438 if ((!_client->connected()) &&
ethaderu 3:78f223d34f36 439 (!_client->available()) &&
ethaderu 3:78f223d34f36 440 ((index + i) < length)) {
ethaderu 3:78f223d34f36 441 jsonlite_parser_release(p);
ethaderu 3:78f223d34f36 442 close();
ethaderu 3:78f223d34f36 443 return E_NOCONNECTION;
ethaderu 3:78f223d34f36 444 }
ethaderu 3:78f223d34f36 445
ethaderu 3:78f223d34f36 446 result = jsonlite_parser_tokenize(p, buf, i);
ethaderu 3:78f223d34f36 447 if ((result != jsonlite_result_ok) &&
ethaderu 3:78f223d34f36 448 (result != jsonlite_result_end_of_stream)) {
ethaderu 3:78f223d34f36 449 jsonlite_parser_release(p);
ethaderu 3:78f223d34f36 450 close();
ethaderu 3:78f223d34f36 451 return E_JSON_INVALID;
ethaderu 3:78f223d34f36 452 }
ethaderu 3:78f223d34f36 453
ethaderu 3:78f223d34f36 454 index += i;
ethaderu 3:78f223d34f36 455 }
ethaderu 3:78f223d34f36 456
ethaderu 3:78f223d34f36 457 jsonlite_parser_release(p);
ethaderu 3:78f223d34f36 458 close();
ethaderu 3:78f223d34f36 459 return (result == jsonlite_result_ok) ? (E_OK) : (E_JSON_INVALID);
ethaderu 3:78f223d34f36 460 }