json-streaming-parser
json-streaming-parser copied to clipboard
HTTP Calls stop after a while
Hi
Thanks a lot for this library. Am a complete noob, but I was trying to get your planespotter demo working. After I started on it I realized I have a different LED panel than yours and I couldn't get ahead. I then somehow got the LED panel working and designed some simple screens to display the data and all works. Except that after about twenty minutes, it stops working.
Is there some memory heap I need to take care of? Any help would be greatly appreicated.
I have the AdbsExchangeClient.cpp and AdbsExchangeClient.h files in the same sketch folder which I have not done any major modification to.
My main code is:
#include <Arduino.h>
#include <ESP8266WiFi.h>
#include <JsonListener.h>
#include <ESP8266mDNS.h>
#include <DNSServer.h>
#include <ESP8266WebServer.h>
#include <WiFiManager.h>
// ST7735
#include <Adafruit_GFX.h> // Core graphics library
#include <Adafruit_ST7735.h> // Hardware-specific library
#include <SPI.h>
#define TFT_CS 16
#define TFT_RST 4
#define TFT_DC 5
Adafruit_ST7735 tft = Adafruit_ST7735(TFT_CS, TFT_DC, TFT_RST);
#include "TimeClient.h"
#include "AdsbExchangeClient.h"
/**************
Required Libraries:
- Weather Station by Daniel Eichhorn
- WifiManager by tzapu
- ESP8266 OLED Driver by Daniel Eichhorn, Fabrice Weinberg
- Json Streaming Parser by Daniel Eichhorn
*/
/***************************
Begin Settings
**************************/
// Please read http://blog.squix.org/weatherstation-getting-code-adapting-it
// for setup instructions
// Setup
const int UPDATE_INTERVAL_SECS_LONG = 15; // Update every 15 seconds if no airplanes around
const int UPDATE_INTERVAL_SECS_SHORT = 10; // Update every 3 seconds if there are airplanes
int currentUpdateInterval = UPDATE_INTERVAL_SECS_LONG;
long lastUpdate = 0;
// Check http://www.virtualradarserver.co.uk/Documentation/Formats/AircraftList.aspx
// to craft this query to your needs
const String QUERY_STRING = "lat=1.3012244&lng=103.8603969&fDstL=0&fDstU=100&fAltL=0&fAltL=1500&fAltU=20000";
const int UTC_OFFSET = 2;
const float pi = 3.141;
// save data points for display
int visibleCrafts;
int prevVisible;
String from;
String to;
String aircraft;
String altitude;
String opcode;
int highScore;
int transition = 1;
/***************************
End Settings
**************************/
TimeClient timeClient(UTC_OFFSET);
AdsbExchangeClient adsbClient;
// flag changed in the ticker function every 10 minutes
bool readyForUpdate = false;
//declaring prototypes
void configModeCallback (WiFiManager *myWiFiManager);
void setup() {
Serial.begin(115200);
//ST7735
tft.initR(INITR_144GREENTAB); // initialize a ST7735S chip, black tab
Serial.println("Initialized");
uint16_t time = millis();
tft.fillScreen(ST7735_BLACK);
time = millis() - time;
Serial.println(time, DEC);
delay(500);
// large block of text
tft.fillScreen(ST7735_RED);
testdrawtext("PLANE", ST7735_WHITE, 10, 50, 2);
testdrawtext("SPOTTER", ST7735_WHITE, 10, 70, 2);
delay(2000);
WiFiManager wifiManager;
// wifiManager.resetSettings(); // Uncomment for testing wifi manager
wifiManager.setAPCallback(configModeCallback);
//or use this for auto generated name ESP + ChipID
wifiManager.autoConnect();
int counter = 0;
while (WiFi.status() != WL_CONNECTED) {
delay(500);
Serial.print(".");
testdrawtext("WIFI CONNECTING..", ST7735_WHITE, 20, 30, 2);
delay(1000);
counter++;
}
// Serial.println("Hostname: " + hostname);
tft.fillScreen(ST7735_BLACK);
}
void loop() {
// If there are airplanes query often
if (adsbClient.getNumberOfVisibleAircrafts() == 0) {
currentUpdateInterval = UPDATE_INTERVAL_SECS_LONG;
} else {
currentUpdateInterval = UPDATE_INTERVAL_SECS_SHORT;
}
// switch between screens


if (lastUpdate < millis() - currentUpdateInterval && transition == 1) {
listAll();
} else if (transition == 2) {
visible();
}
updateData();
}
void visible() {
tft.fillScreen(ST7735_BLACK);
tft.fillRect(0, 0, tft.width(), 80, ST7735_WHITE);
if (visibleCrafts <= 9) {
tft.setCursor(tft.width() / 2 - 10, 30);
} else {
tft.setCursor(tft.width() / 2 - 25, 30);
}
if (visibleCrafts < 4) {
tft.setTextColor(ST7735_BLACK);
} else {
tft.setTextColor(ST7735_RED);
}
tft.setTextSize(5);
tft.print(visibleCrafts);
if (visibleCrafts > highScore) {
highScore = visibleCrafts;
testdrawtext("RECORD", ST7735_RED, 70, 20, 1);
}
testdrawtext("AIRCRAFTS", ST7735_WHITE, 10, 90, 2);
testdrawtext("CURRENTLY OVERHEAD", ST7735_WHITE, 10, 110, 1);
}
void listAll() {
if (adsbClient.isAircraftVisible()) {
tft.setTextWrap(true);
testdrawtext("FROM", ST7735_WHITE, 10, 5, 1);
tft.fillRect(0, 15, tft.width(), 20, ST7735_WHITE);
tft.setTextColor(ST7735_BLACK);
tft.setCursor(10, 22);
tft.print(from);
tft.fillRect(0, 35, tft.width(), 20, ST7735_BLACK);
testdrawtext("TO", ST7735_WHITE, 10, 40, 1);
tft.fillRect(0, 50, tft.width(), 20, ST7735_WHITE);
tft.setCursor(10, 56);
tft.setTextColor(ST7735_BLACK);
tft.print(to);
tft.setTextColor(ST7735_WHITE);
tft.setCursor(10, 80);
tft.fillRect(0, 70, tft.width(), 26, ST7735_BLACK);
tft.print(aircraft);
tft.fillRect(60, 96, tft.width(), 108, ST7735_YELLOW);
testdrawtext("ALTITUDE", ST7735_BLACK, 70, 99, 1);
tft.fillRect(0, 96, 60, 108, ST7735_RED);
tft.setCursor(10, 105);
tft.setTextSize(2);
tft.setTextColor(ST7735_WHITE);
tft.print(opcode);
tft.setTextSize(2);
tft.setCursor(70, 110);
tft.setTextColor(ST7735_BLACK);
tft.print(altitude);
}
}
//ST7735
void testdrawtext(char *text, uint16_t color, uint16_t x, uint16_t y, uint16_t s) {
tft.setCursor(x, y);
tft.setTextColor(color);
tft.setTextSize(s);
tft.setTextWrap(true);
tft.print(text);
}
void updateData() {
readyForUpdate = false;
adsbClient.updateVisibleAircraft(QUERY_STRING);
lastUpdate = millis();
visibleCrafts = adsbClient.getNumberOfVisibleAircrafts();
if (visibleCrafts != prevVisible) {
transition = 2;
prevVisible = visibleCrafts;
} else {
transition = 1;
}
from = String(adsbClient.getFrom());
to = String(adsbClient.getTo());
opcode = String(adsbClient.getOperatorCode());
altitude = String(adsbClient.getAltitude());
aircraft = String(adsbClient.getAircraftType());
delay(5000);
}
void configModeCallback (WiFiManager *myWiFiManager) {
Serial.println("Entered config mode");
Serial.println(WiFi.softAPIP());
//if you used auto generated SSID, print it
Serial.println(myWiFiManager->getConfigPortalSSID());
}
void checkReadyForUpdate() {
// Only do light work in ticker callback
if (lastUpdate < millis() - currentUpdateInterval * 1000) {
readyForUpdate = true;
}
}
I am running into the same problem as you, it seems to be related to the amount of data to be parsed. Somewhere between the 25 and 30 elements and it stops working (Freezes) or wdt kicks in.
You need to cast parser.reset(); otherwise it will crash the heap.
Ex:
void loop() {
parser.setListener(&listener);
char json[] = "{\"macro\": [{\"codeRaw\": [\"3450\",\"1700\",\" 450\",\"450\",\" 450\",\"1250\",\" 450\",\"400\",\" 450\",\"400\"],\"codeValue\": null,\"kind\": \"IR\",\"bits\": 32,\"repeatValue\": false,\"codeType\": -1},{\"kind\": \"DELAY\",\"time\": 1},{\"codeRaw\": [\"350\",\"600\",\" 350\",\"600\",\"300\"],\"codeValue\": null,\"kind\": \"IR\",\"bits\": 32,\"repeatValue\": false,\"codeType\": -1}";
for (int i = 0; i < sizeof(json); i++) {
parser.parse(json[i]);
}
parser.reset();
Serial.print(json[0]);
delay(1000);
}
-- Edit -- Solved: To whom it may help:
- For reading data from an external HTTP source, use HTTPClient, not WebClient.
- make Json parser and HTTPclient part of your class.
- parser.reset() before each usage as suggested above.
- Do not use HTTPclient .reuse(true);
- make loop() as short as possible : e.g. separate retrieving data from displaying it in different loop()- runthroughs .
Then no problems with heap, no problems with WIFI disconnect().
Same problem here. startDocument() is called, endDocument() fails after some time.
I did not observe heap problems. I logged ESP.getHeap() ... and it is not decreasing. The src of the parser only used the stack.
In the above example, the parser is defined local on stack and IMHO a reset() is not needed. Only if the parser object would be somehow permanent and reused between usage.
I made such a test with the parser being a member of a class and using reset() between each parsings and it did not help. Sooner or later the endDocument() is not called and the ESP is stalled.
I'm running out of ideas.