i want to get my thingSpeak channel data into arduino by performing GET request every things works fine.Further i used Arduinojson lib to parse the JSON but i am getting failed every time when i try to parse it.I used arduinojson assistant to calculate the parsing program but still i am getting error. Below is my JSON and Failure message that i got every time in serial monitor.
{"channel":{"id":421932,"name":"remote_car","description":"Nothing up to this point !","latitude":"0.0","longitude":"0.0","field1":"MOTOR ONE","field2":"MOTOR TWO","field3":"MOTOR THREE","field4":"MOTOR FOUR","created_at":"2018-02-07T17:32:09Z","updated_at":"2018-03-17T07:08:49Z","last_entry_id":7},"feeds":[{"created_at":"2018-03-17T06:53:48Z","entry_id":4,"field1":"0"},{"created_at":"2018-03-17T06:59:22Z","entry_id":5,"field1":"0"},{"created_at":"2018-03-17T07:03:59Z","entry_id":6,"field1":"2"},{"created_at":"2018-03-17T07:08:49Z","entry_id":7,"field1":"1"}]}
Parse Failed...
this is my arduino code(i used arduino plus esp8266 to get my thinkSpeak channel data).
#include "WiFiEsp.h"
#include <ArduinoJson.h>
// Emulate Serial1 on pins 6/7 if not present
#ifndef HAVE_HWSERIAL1
#include "SoftwareSerial.h"
SoftwareSerial Serial1(2,3); // RX, TX
#endif
char ssid[] = "M T G"; // your network SSID (name)
char pass[] = "androidGUII"; // your network password
int status = WL_IDLE_STATUS; // the Wifi radio's status
// Initialize the Ethernet client object
WiFiEspClient client;
static const char* host = "api.thingspeak.com";
static const char* apiKey = "H359MYV0P0KFG2VS";
const unsigned long HTTP_TIMEOUT = 10000;
void setup()
{
// initialize serial for debugging
Serial.begin(115200);
// initialize serial for ESP module
Serial1.begin(9600);
// initialize ESP module
WiFi.init(&Serial1);
// check for the presence of the shield
if (WiFi.status() == WL_NO_SHIELD) {
Serial.println("WiFi shield not present");
// don't continue
while (true);
}
// attempt to connect to WiFi network
while ( status != WL_CONNECTED) {
Serial.print("Attempting to connect to WPA SSID: ");
Serial.println(ssid);
// Connect to WPA/WPA2 network
status = WiFi.begin(ssid, pass);
}
// you're connected now, so print out the data
Serial.println("You're connected to the network");
// printWifiStatus();
Serial.println();
}
void loop()
{
const int httpPort = 80;
if (!client.connect(host, httpPort)) {
Serial.println("connection failed");
return;
}
client.print("GET /channels/421932/fields/1.json?api_key=");
client.print(apiKey);
client.println("&results=4 HTTP/1.1");
client.print("Host:");
client.println(host);
client.println();
while (client.available() == 0);
while (!skipResponseHeaders()); // wait till something comes in; you may want to add a timeout here
while (client.available()) { // Now receive the data
String line = client.readStringUntil('\n');
if ( line.indexOf('{',0) >= 0 ) { // Ignore data that is not likely to be JSON formatted, so must contain a '{'
Serial.println(line); // Show the text received
parseData(line);
}
}
client.stop();
delay(10000);
}
void parseData(String data){
const size_t bufferSize = JSON_ARRAY_SIZE(4) + JSON_OBJECT_SIZE(2) + 4*JSON_OBJECT_SIZE(3) + JSON_OBJECT_SIZE(12) + 520;
DynamicJsonBuffer jsonBuffer(bufferSize);
const char* json = data.c_str();
JsonObject& root = jsonBuffer.parseObject(json);
if(!root.success()){
Serial.println("Parse Failed...");
}
JsonObject& channel = root["channel"];
long channel_id = channel["id"]; // 421932
const char* channel_name = channel["name"]; // "remote_car"
const char* channel_description = channel["description"]; // "Nothing up to this point !"
Serial.println(channel_name);
Serial.println(channel_description);
}
bool skipResponseHeaders() {
char endOfHeaders[] = "\r\n\r\n"; // HTTP headers end with an empty line
client.setTimeout(HTTP_TIMEOUT);
bool ok = client.find(endOfHeaders);
if (!ok) { Serial.println("No response or invalid response!"); }
return ok;
}
Any one have any idea how i am getting parsing failed message. Any help would be appreciated.
1 Answer 1
It is a memory allocation failure. Your Arduino Uno has 2KB ob RAM and I found out, via a binary search on the size of the StaticJsonBuffer<size>
object, that for this specific 566 byte long JSON string you need a JSON buffer of at least 785 bytes to parse it.
Use this minimal sketch to test the size:
#include <Arduino.h>
#include <avr/pgmspace.h>
#include <ArduinoJson.h>
#define stringToParse \
"{\"channel\":{\"id\":421932,\"name\":\"remote_car\",\"description\":\"Nothing up to this point !\",\"latitude\":\"0.0\",\"longitude\":\"0.0\",\"field1\":\"MOTOR ONE\",\"field2\":\"MOTOR TWO\",\"field3\":\"MOTOR THREE\",\"field4\":\"MOTOR FOUR\",\"created_at\":\"2018-02-07T17:32:09Z\",\"updated_at\":\"2018-03-17T07:08:49Z\",\"last_entry_id\":7},\"feeds\":[{\"created_at\":\"2018-03-17T06:53:48Z\",\"entry_id\":4,\"field1\":\"0\"},{\"created_at\":\"2018-03-17T06:59:22Z\",\"entry_id\":5,\"field1\":\"0\"},{\"created_at\":\"2018-03-17T07:03:59Z\",\"entry_id\":6,\"field1\":\"2\"},{\"created_at\":\"2018-03-17T07:08:49Z\",\"entry_id\":7,\"field1\":\"1\"}]}"
StaticJsonBuffer<785> jsonBuffer;
void parseData(const __FlashStringHelper* json){
//const size_t bufferSize = JSON_ARRAY_SIZE(4) + JSON_OBJECT_SIZE(2) + 4*JSON_OBJECT_SIZE(3) + JSON_OBJECT_SIZE(12) + 520;
//DynamicJsonBuffer jsonBuffer(bufferSize);
//const char* json = data.c_str();
JsonObject& root = jsonBuffer.parseObject(json);
if(!root.success()){
Serial.println("Parse Failed...");
return;
}
JsonObject& channel = root["channel"];
long channel_id = channel["id"]; // 421932
const char* channel_name = channel["name"]; // "remote_car"
const char* channel_description = channel["description"]; // "Nothing up to this point !"
Serial.print("Channel name: "); Serial.println(channel_name);
Serial.print("Channel description: "); Serial.println(channel_description);
Serial.print("Channel id: ");
Serial.println(channel_id);
}
void setup() {
Serial.begin(9600);
//We use the F() macro to create a flash string helper
//this way, that huge JSON string is held in FLASH and not in precious RAM..
parseData(F(stringToParse));
}
void loop() { }
If you decrease the buffer size by even 1 byte, parsing will fail.
Since you are using a DynamicJsonBuffer
initially, your memory allocation will surely fail, since the heap can be really fragmented due to your other libraries (WiFiEspClient
) and you are not able to find a continous 785 byte fragment on the heap. If the libraries tries to allocate memory object-wise (that is, not a continious segment), you might still get an out-of-memory error because
- the heap induces overhead per allocated object because of house-keeping information
- you fragment your heap over time, essentially leaving holes in it; this causes big allocations to fail because no continous segment could be found, although maybe in sum there is enough memory free
- other libraries / part of your program is also using the heap and you are actually out-of-memory no matter what your allocation strategy is
You have various options:
- decrease the length of JSON string received by the Uno for it to be able to parse it.
- For example, instead of huge JSON string have it receive a binary-formatted message with the information being as compactly packet in there as possible. You don't need to send
"id\":421932
, instead just make a field "id" in your packet format for a 32-bit integer. That decreases it from 11 bytes to 4 bytes.
- For example, instead of huge JSON string have it receive a binary-formatted message with the information being as compactly packet in there as possible. You don't need to send
- use
StaticJsonBuffer
with fixed maximum size instead ofDynamicJsonBuffer
to make sure you can always parse the longest message (that is, if you have enough RAM free) - program the ESP8266 directly.
Really, your ESP8266 has about ~40KByte of user-usable RAM at startup and is at least an order of magnitude more powerful than your Uno. I wouldn't bother strapping a Arduino Uno to a mighty ESP8266 just for it to do JSON parsing.
Depending on what ESP8266 you have (ESP8266-01, ESP12F, NodeMCU board, ..) you should start looking for tutorials for programming it using the Arduino-ESP8266 framework.
-
Hi sir thank you for your precious time...i modified the code according to your instruction but but now i am getting this..strange info...Wisal Muhammad– Wisal Muhammad2018年03月18日 12:21:59 +00:00Commented Mar 18, 2018 at 12:21
-
Con¬B Parse Failed.Wisal Muhammad– Wisal Muhammad2018年03月18日 12:22:45 +00:00Commented Mar 18, 2018 at 12:22
-
Does the above sketch work on its own? Edit your question to include the full code and runtime error.Maximilian Gerhardt– Maximilian Gerhardt2018年03月18日 12:24:21 +00:00Commented Mar 18, 2018 at 12:24
-
the above code works fine when use stand alone but when i modified it for my own purpose then it throws the above error...my main goal is to received the json from thingspeak and then parse it...Wisal Muhammad– Wisal Muhammad2018年03月18日 12:39:03 +00:00Commented Mar 18, 2018 at 12:39
-
you can look up into my main arduino code sir.Wisal Muhammad– Wisal Muhammad2018年03月18日 12:44:30 +00:00Commented Mar 18, 2018 at 12:44
Explore related questions
See similar questions with these tags.