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:
citrusbyte
Date:
Tue Dec 09 14:36:16 2014 +0000
Revision:
13:0d574742208f
Parent:
11:a11af0c81cfa
Child:
14:205076b587fe
Update client library to latest version

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