Last active
January 26, 2016 13:05
-
-
Save sticilface/ceef9a0b031afc0ce2a2 to your computer and use it in GitHub Desktop.
demonstrates crash with large JSONs
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/* | |
* | |
* Demonstrates crash using chuncked print and large Json | |
* Requires | |
* https://github.com/me-no-dev/ESPAsyncWebServer | |
* https://github.com/me-no-dev/ESPAsyncTCP | |
* https://github.com/bblanchon/ArduinoJson | |
* | |
* use curl to make request... | |
* http://ip/json -> Will make request and send results async... causes crash. Works if lines are removed from json.. see addJson function | |
* http://ip/jsonprint -> sets flag in loop, then prints same json, async to serial. does not crash. | |
* http://ip/jsonsync -> uses an async method to print json back to client. Called from loop. Not working, not sure why | |
*/ | |
#include <ESP8266WiFi.h> | |
#include <ESP8266mDNS.h> | |
#include <ArduinoOTA.h> | |
#include <ESPAsyncTCP.h> | |
#include <ESPAsyncWebServer.h> | |
#include <ArduinoJson.h> | |
static const char rubbish[] = "abcdefgeabcdefgeabcdefgeabcdefgeabcdefgeabcdefgeabcdefgeabcdefgeabcdefgeabcdefgeabcdefgeabcdefgeabcdefgeabcdefgeabcdefgeabcdefgeabcdefgeabcdefgeabcdefgeabcdefgeabcdefgeabcdefgeabcdefgeabcdefgeabcdefgeabcdefgeabcdefgeabcdefgeabcdefgeabcdefgeabcdefgeabcdefgeabcdefgeabcdefgeabcdefgeabcdefgeabcdefgeabcdefgeabcdefgeabcdefgeabcdefgeabcdefgeabcdefgeabcdefgeabcdefgeabcdefgeabcdefgeabcdefgeabcdefgeabcdefgeabcdefgeabcdefgeabcdefgeabcdefgeabcdefgeabcdefgeabcdefgeabcdefgeabcdefgeabcdefgeabcdefgeabcdefgeabcdefgeabcdefgeabcdefgeabcdefgeabcdefgeabcdefgeabcdefgeabcdefgeabcdefgeabcdefgeabcdefgeabcdefgeabcdefgeabcdefgeabcdefgeabcdefgeabcdefgeabcdefgeabcdefgeabcdefgeabcdefgeabcdefgeabcdefgeabcdefgeabcdefgeabcdefgeabcdefgeabcdefgeabcdefgeabcdefgeabcdefgeabcdefgeabcdefge"; | |
//static const char rubbish[] = "abcdefgeabcdefgeabcde"; | |
const char* ssid = "xx"; | |
const char* password = "xx"; | |
AsyncWebServerRequest *client = nullptr; | |
/* | |
* Json Response | |
* */ | |
class AsyncJsonResponse: public AsyncAbstractResponse | |
{ | |
private: | |
DynamicJsonBuffer _jsonBuffer; | |
JsonVariant _root; | |
bool _isValid; | |
class ChunkPrint : public Print | |
{ | |
public: | |
ChunkPrint(uint8_t* destination, size_t from, size_t to) | |
: _destination(destination), _to_skip(from), _to_write(to - from), _pos{0} {} | |
size_t write(uint8_t c) | |
{ | |
if (_to_skip > 0) { | |
_to_skip--; | |
} else if (_to_write > 0) { | |
_to_write--; | |
_destination[_pos++] = c; | |
return 1; | |
} | |
return 0; | |
} | |
private: | |
uint8_t* _destination; | |
size_t _to_skip; | |
size_t _to_write; | |
size_t _pos; | |
}; | |
public: | |
AsyncJsonResponse() : _isValid{false} | |
{ | |
_code = 200; | |
_contentType = "text/json"; | |
} | |
~AsyncJsonResponse() {}; | |
DynamicJsonBuffer & getBuffer() { return _jsonBuffer; } | |
bool _sourceValid() { return _isValid; } | |
void SetTarget( JsonVariant root) | |
{ | |
_root = root; | |
_contentLength = _root.measureLength(); | |
os_printf("[SetTarget] buffer size = %u\n", _root.size()); | |
if (_contentLength) { _isValid = true; } | |
} | |
size_t _fillBuffer(uint8_t *data, size_t len) | |
{ | |
os_printf("[_fillBuffer] heap = %u\n",ESP.getFreeHeap()); | |
ChunkPrint dest(data, _sentLength, _sentLength + len ); | |
return _root.printTo( dest ) ; | |
} | |
}; | |
void addjson(JsonObject& root) { | |
JsonObject& sub1 = root.createNestedObject("nested1"); | |
JsonObject& test = sub1.createNestedObject("nested2"); | |
JsonArray& array = root.createNestedArray("array"); | |
root["key1"] = rubbish; | |
sub1["key2"] = rubbish; | |
sub1["key3"] = rubbish; | |
sub1["key4"] = rubbish; | |
sub1["key5"] = rubbish; | |
sub1["key6"] = rubbish; | |
sub1["key7"] = rubbish; | |
sub1["key8"] = rubbish; | |
sub1["key9"] = rubbish; | |
sub1["key10"] = rubbish; | |
sub1["key11"] = rubbish; | |
sub1["key12"] = rubbish; | |
sub1["key13"] = rubbish; | |
sub1["key14"] = rubbish; | |
sub1["key15"] = rubbish; | |
sub1["key16"] = rubbish; | |
sub1["key17"] = rubbish; | |
sub1["key18"] = rubbish; | |
sub1["key19"] = rubbish; | |
sub1["key20"] = rubbish; | |
sub1["key21"] = rubbish; | |
sub1["key22"] = rubbish; | |
sub1["key23"] = rubbish; | |
sub1["key24"] = rubbish; | |
sub1["key25"] = rubbish; | |
sub1["key26"] = rubbish; | |
sub1["key27"] = rubbish; | |
sub1["key28"] = rubbish; | |
sub1["key29"] = rubbish; | |
test["akey1"] = rubbish; | |
test["akey2"] = rubbish; | |
test["akey3"] = rubbish; | |
test["akey4"] = rubbish; | |
test["akey5"] = rubbish; | |
test["akey6"] = rubbish; | |
test["akey7"] = rubbish; | |
test["akey8"] = rubbish; | |
test["akey9"] = rubbish; | |
test["akey10"] = rubbish; | |
test["akey11"] = rubbish; | |
test["akey12"] = rubbish; | |
// | |
// test["akey13"] = "straw that broke the camels back"; | |
// test["akey14"] = "straw that broke the camels back"; | |
// test["akey15"] = "straw that broke the camels back"; | |
// test["akey16"] = "straw that broke the camels back"; | |
} | |
void send_data() { | |
os_printf("[send_data]\n"); | |
DynamicJsonBuffer buffer; | |
JsonObject& root = buffer.createObject(); | |
addjson(root); | |
while (client != NULL) { | |
Serial.println("[send_data] Send Json"); | |
AsyncResponseStream *stream = client->beginResponseStream("text/json", root.measureLength()); | |
os_printf("[send_Data] root.length() = %u\n", root.measureLength()); | |
root.printTo(*stream); | |
client = client->next; | |
} | |
} | |
// SKETCH BEGIN | |
AsyncWebServer HTTP(80); | |
bool flag = false; | |
// need these to debug during an inturrupt.. | |
extern "C" void system_set_os_print(uint8 onoff); | |
extern "C" void ets_install_putc1(void* routine); | |
//Use the internal hardware buffer | |
static void _u0_putc(char c){ | |
while(((U0S >> USTXC) & 0x7F) == 0x7F); | |
U0F = c; | |
} | |
void initSerial(){ | |
Serial.begin(115200); | |
ets_install_putc1((void *) &_u0_putc); | |
system_set_os_print(1); | |
} | |
void setup(){ | |
initSerial(); | |
os_printf("\n\nJSON TEST"); | |
WiFi.mode(WIFI_STA); | |
WiFi.begin(ssid, password); | |
if (WiFi.waitForConnectResult() != WL_CONNECTED) { | |
Serial.printf("STA: Failed!\n"); | |
WiFi.disconnect(false); | |
delay(1000); | |
WiFi.begin(ssid, password); | |
} | |
ArduinoOTA.begin(); | |
ArduinoOTA.setHostname("json"); | |
HTTP.on("/json", HTTP_ANY, [](AsyncWebServerRequest * request) { | |
Serial.println(); | |
Serial.printf("New Json request: heap = %u\n", ESP.getFreeHeap()); | |
AsyncJsonResponse * response = new AsyncJsonResponse(); | |
DynamicJsonBuffer buffer = response->getBuffer(); | |
JsonObject& root = buffer.createObject(); | |
addjson(root); | |
response->SetTarget(root); | |
request->send(response); | |
}); | |
HTTP.on("/jsonprint", HTTP_ANY, [](AsyncWebServerRequest * request) { | |
flag = true; | |
request->send(200); | |
}); | |
HTTP.on("/jsonsync", HTTP_ANY, [](AsyncWebServerRequest * request) { | |
if (client == NULL) { | |
os_printf("[HTTP] client = request\n"); | |
client = request; | |
} else { | |
os_printf("[HTTP] client already.... chaining...."); | |
AsyncWebServerRequest *c = client; | |
while (c->next != NULL) c = c->next; | |
c->next = request; | |
} | |
}); | |
HTTP.begin(); | |
} | |
void loop(){ | |
ArduinoOTA.handle(); | |
if (flag) { | |
DynamicJsonBuffer buffer; | |
JsonObject& root = buffer.createObject(); | |
addjson(root); | |
root.printTo(Serial); | |
flag = false; | |
} | |
if (client) { | |
send_data(); | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment