I'm running this on a Particle Photon, but I think the issue is just me failing at C++. I'm trying to retrieve some JSON data from a HTTP API, convert it to JSON, and then extract a few values for display on the screen. I convert the String to a char array for the JSON parser, but it seems to only grab the first 10 characters of the String (unless I manually set length to a number shorter than 10), and then of course, the JSON parser fails.
Here's the relevant bit of code:
int str_len = response.body.length() + 1;
tft.print("Length: "); tft.println(str_len);
char char_array[str_len];
response.body.toCharArray(char_array, str_len);
response.body
is a big JSON string, but char_array
is always just the first 10 characters of it: {"metadata
Another thing I noticed just now that might be related, str_len
is usually reported to be ~500 characters, but when I hit the same URL in a browser it ends up more like ~1500 characters. Neither are pretty-printed, so I'm not sure what the discrepancy is.
Here's my complete code, except I removed the base64'd username and password from the Authorization header:
#include "HttpClient/HttpClient.h"
#include "SparkJson/SparkJson.h"
#include "Adafruit_mfGFX/Adafruit_mfGFX.h"
#include "Adafruit_SSD1351_Photon/Adafruit_SSD1351_Photon.h"
// OLED - You can use any (4 or) 5 pins
#define sclk A3
#define mosi A5
#define dc D7
#define cs A2
#define rst D5
// Color definitions
#define BLACK 0x0000
#define BLUE 0x001F
#define RED 0xF800
#define GREEN 0x07E0
#define CYAN 0x07FF
#define MAGENTA 0xF81F
#define YELLOW 0xFFE0
#define WHITE 0xFFFF
// Option 1: Hardware SPI - uses some analog pins, but much faster
Adafruit_SSD1351 tft = Adafruit_SSD1351(cs, dc, rst);
// Option 2: Software SPI - use any pins but a little slower
//Adafruit_SSD1351 tft = Adafruit_SSD1351(cs, dc, mosi, sclk, rst);
HttpClient http;
// Headers currently need to be set at init, useful for API keys etc.
http_header_t headers[] = {
// { "Content-Type", "application/json" },
{ "Authorization", "Basic <snip>" }, // base64encode(username:password)
{ "Accept" , "application/json" },
{ NULL, NULL } // NOTE: Always terminate headers will NULL
};
http_request_t request;
http_response_t response;
void setup(void) {
tft.begin();
tft.fillScreen(BLACK);
tft.setCursor(0,0);
tft.setTextSize(0);
tft.setTextColor(WHITE);
// http://twcservice.mybluemix.net/api/weather/v2/observations/current?units=e&geocode=40.0388067%2C-84.3428471&language=en-US
request.hostname = "twcservice.mybluemix.net";
request.port = 80;
request.path = "/api/weather/v2/observations/current?units=e&geocode=40.0388067%2C-84.3428471&language=en-US";
//request.body = "{\"key\":\"value\"}";
http.get(request, response, headers);
tft.print("Status: ");
tft.println(response.status);
//tft.println("Response Body: ");
//tft.println(response.body);
int str_len = response.body.length() + 1;
tft.print("Length: "); tft.println(str_len);
char char_array[str_len];
response.body.toCharArray(char_array, str_len);
DynamicJsonBuffer jsonBuffer;
JsonObject& root = jsonBuffer.parseObject(char_array);
if (root.success()) {
tft.print("Current Temperature: ");
const char* temp = root["observation"]["imperial"]["temp"];
tft.println(temp);
} else {
tft.setTextColor(RED);
tft.println("parseObject() failed");
tft.setTextColor(GREEN);
uint32_t freemem = System.freeMemory();
tft.print("Free memory: ");
tft.print(freemem/1024);
tft.println("k");
tft.setTextColor(WHITE);
tft.println(char_array);
tft.setTextColor(CYAN);
tft.println(response.body);
}
}
void loop() {
}
The actual printout on the screen is smething like
Status: 200
Length: 501
parseObject() failed
Free memory: 59k
{"metadata
{"metadata":{"language":"en-US","transaction_id":"1460309558940:-660053703","version":"1","latitude":40.04,"longitude":-84.34,"units":"e","expire_time_gmt":1460310025,"status_code":200},"observation":{"class":"observation","expire_
Finally, here's an example of the JSON response I'm trying to parse:
{"metadata":{"language":"en-US","transaction_id":"1460309558940:-660053703","version":"1","latitude":40.04,"longitude":-84.34,"units":"e","expire_time_gmt":1460310025,"status_code":200},"observation":{"class":"observation","expire_time_gmt":1460310025,"obs_time":1460307900,"obs_time_local":"2016-04-10T13:05:00-0400","wdir":160,"icon_code":26,"icon_extd":2690,"sunrise":"2016-04-10T07:06:23-0400","sunset":"2016-04-10T20:11:13-0400","day_ind":"D","uv_index":3,"uv_warning":0,"wxman":"wx4400","obs_qualifier_code":null,"ptend_code":2,"dow":"Sunday","wdir_cardinal":"SSE","uv_desc":"Moderate","phrase_12char":"Cloudy/Wind","phrase_22char":"Cloudy/Wind","phrase_32char":"Cloudy/Wind","ptend_desc":"Falling","sky_cover":"Cloudy","clds":"OVC","obs_qualifier_severity":null,"vocal_key":"OT48:OX2690","imperial":{"wspd":20,"gust":24,"vis":10.000,"mslp":1018.7,"altimeter":30.09,"temp":48,"dewpt":27,"rh":43,"wc":41,"hi":48,"temp_change_24hour":11,"temp_max_24hour":44,"temp_min_24hour":27,"pchange":-0.10,"feels_like":41,"snow_1hour":0.0,"snow_6hour":0.0,"snow_24hour":0.0,"snow_mtd":1.2,"snow_season":21.3,"snow_ytd":21.3,"snow_2day":0.7,"snow_3day":0.8,"snow_7day":0.9,"ceiling":7400,"precip_1hour":0.00,"precip_6hour":0.00,"precip_24hour":0.00,"precip_mtd":1.10,"precip_ytd":11.76,"precip_2day":0.29,"precip_3day":0.30,"precip_7day":0.96,"obs_qualifier_100char":null,"obs_qualifier_50char":null,"obs_qualifier_32char":null}}}
Any idea what's going on?