ARM mbed M2X API Client: The ARM mbed client library is used to send/receive data to/from AT&T's M2X service from mbed LPC1768 microcontrollers.

Dependents:   m2x-demo-all M2X_MTS_ACCEL_DEMO M2X_MTS_Accel M2X_K64F_ACCEL ... more

Committer:
NetArc
Date:
Sun Jan 04 05:26:33 2015 +0000
Revision:
14:205076b587fe
Parent:
13:0d574742208f
Child:
16:7903152de19f
Added support for path prefix for app-flow

Who changed what in which revision?

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