Single JSON buffer.

This commit is contained in:
Blaž Kristan 2021-11-03 14:52:22 +01:00
parent f66fcfbe6d
commit bd521f858e
14 changed files with 158 additions and 54 deletions

View File

@ -86,8 +86,6 @@ void WS2812FX::finalizeInit(void)
busses.add(defCfg); busses.add(defCfg);
} }
} }
deserializeMap();
_length = 0; _length = 0;
for (uint8_t i=0; i<busses.getNumBusses(); i++) { for (uint8_t i=0; i<busses.getNumBusses(); i++) {
@ -1075,7 +1073,7 @@ uint32_t WS2812FX::color_from_palette(uint16_t i, bool mapping, bool wrap, uint8
} }
//load custom mapping table from JSON file //load custom mapping table from JSON file (called from finalizeInit() or deserializeState())
void WS2812FX::deserializeMap(uint8_t n) { void WS2812FX::deserializeMap(uint8_t n) {
char fileName[32]; char fileName[32];
strcpy_P(fileName, PSTR("/ledmap")); strcpy_P(fileName, PSTR("/ledmap"));
@ -1093,11 +1091,18 @@ void WS2812FX::deserializeMap(uint8_t n) {
return; return;
} }
DynamicJsonDocument doc(JSON_BUFFER_SIZE); // full sized buffer for larger maps //DynamicJsonDocument doc(JSON_BUFFER_SIZE); // full sized buffer for larger maps
while (jsonBufferLock) delay(1);
jsonBufferLock = true;
doc.clear();
DEBUG_PRINT(F("Reading LED map from ")); DEBUG_PRINT(F("Reading LED map from "));
DEBUG_PRINTLN(fileName); DEBUG_PRINTLN(fileName);
if (!readObjectFromFile(fileName, nullptr, &doc)) return; //if file does not exist just exit if (!readObjectFromFile(fileName, nullptr, &doc)) {
jsonBufferLock = false;
return; //if file does not exist just exit
}
// erase old custom ledmap // erase old custom ledmap
if (customMappingTable != nullptr) { if (customMappingTable != nullptr) {
@ -1114,6 +1119,8 @@ void WS2812FX::deserializeMap(uint8_t n) {
customMappingTable[i] = (uint16_t) map[i]; customMappingTable[i] = (uint16_t) map[i];
} }
} }
jsonBufferLock = false;
} }
//gamma 2.8 lookup table used for color correction //gamma 2.8 lookup table used for color correction

View File

@ -14,6 +14,7 @@ void getStringFromJson(char* dest, const char* src, size_t len) {
} }
bool deserializeConfig(JsonObject doc, bool fromFS) { bool deserializeConfig(JsonObject doc, bool fromFS) {
bool needsSave = false;
//int rev_major = doc["rev"][0]; // 1 //int rev_major = doc["rev"][0]; // 1
//int rev_minor = doc["rev"][1]; // 0 //int rev_minor = doc["rev"][1]; // 0
@ -419,13 +420,12 @@ bool deserializeConfig(JsonObject doc, bool fromFS) {
DEBUG_PRINTLN(F("Starting usermod config.")); DEBUG_PRINTLN(F("Starting usermod config."));
JsonObject usermods_settings = doc["um"]; JsonObject usermods_settings = doc["um"];
if (!usermods_settings.isNull()) { if (!usermods_settings.isNull()) {
bool allComplete = usermods.readFromConfig(usermods_settings); needsSave = usermods.readFromConfig(usermods_settings);
if (!allComplete && fromFS) serializeConfig();
} }
if (fromFS) return false; if (fromFS) return needsSave;
doReboot = doc[F("rb")] | doReboot; doReboot = doc[F("rb")] | doReboot;
return (doc["sv"] | true); return (doc["sv"] | needsSave);
} }
void deserializeConfigFromFS() { void deserializeConfigFromFS() {
@ -435,19 +435,26 @@ void deserializeConfigFromFS() {
return; return;
} }
DynamicJsonDocument doc(JSON_BUFFER_SIZE); //DynamicJsonDocument doc(JSON_BUFFER_SIZE);
while (jsonBufferLock) delay(1);
jsonBufferLock = true;
doc.clear();
DEBUG_PRINTLN(F("Reading settings from /cfg.json...")); DEBUG_PRINTLN(F("Reading settings from /cfg.json..."));
success = readObjectFromFile("/cfg.json", nullptr, &doc); success = readObjectFromFile("/cfg.json", nullptr, &doc);
if (!success) { //if file does not exist, try reading from EEPROM if (!success) { //if file does not exist, try reading from EEPROM
deEEPSettings(); deEEPSettings();
jsonBufferLock = false;
return; return;
} }
// NOTE: This routine deserializes *and* applies the configuration // NOTE: This routine deserializes *and* applies the configuration
// Therefore, must also initialize ethernet from this function // Therefore, must also initialize ethernet from this function
deserializeConfig(doc.as<JsonObject>(), true); bool needsSave = deserializeConfig(doc.as<JsonObject>(), true);
jsonBufferLock = false;
if (needsSave) serializeConfig(); // usermods required new prameters
} }
void serializeConfig() { void serializeConfig() {
@ -455,7 +462,10 @@ void serializeConfig() {
DEBUG_PRINTLN(F("Writing settings to /cfg.json...")); DEBUG_PRINTLN(F("Writing settings to /cfg.json..."));
DynamicJsonDocument doc(JSON_BUFFER_SIZE); //DynamicJsonDocument doc(JSON_BUFFER_SIZE);
while (jsonBufferLock) delay(1);
jsonBufferLock = true;
doc.clear();
JsonArray rev = doc.createNestedArray("rev"); JsonArray rev = doc.createNestedArray("rev");
rev.add(1); //major settings revision rev.add(1); //major settings revision
@ -762,16 +772,23 @@ void serializeConfig() {
File f = WLED_FS.open("/cfg.json", "w"); File f = WLED_FS.open("/cfg.json", "w");
if (f) serializeJson(doc, f); if (f) serializeJson(doc, f);
f.close(); f.close();
jsonBufferLock = false;
} }
//settings in /wsec.json, not accessible via webserver, for passwords and tokens //settings in /wsec.json, not accessible via webserver, for passwords and tokens
bool deserializeConfigSec() { bool deserializeConfigSec() {
DEBUG_PRINTLN(F("Reading settings from /wsec.json...")); DEBUG_PRINTLN(F("Reading settings from /wsec.json..."));
DynamicJsonDocument doc(JSON_BUFFER_SIZE); //DynamicJsonDocument doc(JSON_BUFFER_SIZE);
while (jsonBufferLock) delay(1);
jsonBufferLock = true;
doc.clear();
bool success = readObjectFromFile("/wsec.json", nullptr, &doc); bool success = readObjectFromFile("/wsec.json", nullptr, &doc);
if (!success) return false; if (!success) {
jsonBufferLock = false;
return false;
}
JsonObject nw_ins_0 = doc["nw"]["ins"][0]; JsonObject nw_ins_0 = doc["nw"]["ins"][0];
getStringFromJson(clientPass, nw_ins_0["psk"], 65); getStringFromJson(clientPass, nw_ins_0["psk"], 65);
@ -803,13 +820,17 @@ bool deserializeConfigSec() {
CJSON(wifiLock, ota[F("lock-wifi")]); CJSON(wifiLock, ota[F("lock-wifi")]);
CJSON(aOtaEnabled, ota[F("aota")]); CJSON(aOtaEnabled, ota[F("aota")]);
jsonBufferLock = false;
return true; return true;
} }
void serializeConfigSec() { void serializeConfigSec() {
DEBUG_PRINTLN(F("Writing settings to /wsec.json...")); DEBUG_PRINTLN(F("Writing settings to /wsec.json..."));
DynamicJsonDocument doc(JSON_BUFFER_SIZE); //DynamicJsonDocument doc(JSON_BUFFER_SIZE);
while (jsonBufferLock) delay(1);
jsonBufferLock = true;
doc.clear();
JsonObject nw = doc.createNestedObject("nw"); JsonObject nw = doc.createNestedObject("nw");
@ -844,4 +865,5 @@ void serializeConfigSec() {
File f = WLED_FS.open("/wsec.json", "w"); File f = WLED_FS.open("/wsec.json", "w");
if (f) serializeJson(doc, f); if (f) serializeJson(doc, f);
f.close(); f.close();
jsonBufferLock = false;
} }

View File

@ -572,18 +572,22 @@ void decodeIRJson(uint32_t code)
{ {
char objKey[10]; char objKey[10];
String cmdStr; String cmdStr;
DynamicJsonDocument irDoc(JSON_BUFFER_SIZE);
JsonObject fdo; JsonObject fdo;
JsonObject jsonCmdObj; JsonObject jsonCmdObj;
//DynamicJsonDocument doc(JSON_BUFFER_SIZE);
while (jsonBufferLock) delay(1);
jsonBufferLock = true;
doc.clear();
sprintf_P(objKey, PSTR("\"0x%lX\":"), (unsigned long)code); sprintf_P(objKey, PSTR("\"0x%lX\":"), (unsigned long)code);
// attempt to read command from ir.json // attempt to read command from ir.json
// this may fail for two reasons: ir.json does not exist or IR code not found // this may fail for two reasons: ir.json does not exist or IR code not found
// if the IR code is not found readObjectFromFile() will clean() irDoc JSON document // if the IR code is not found readObjectFromFile() will clean() doc JSON document
// so we can differentiate between the two // so we can differentiate between the two
readObjectFromFile("/ir.json", objKey, &irDoc); readObjectFromFile("/ir.json", objKey, &doc);
fdo = irDoc.as<JsonObject>(); fdo = doc.as<JsonObject>();
lastValidCode = 0; lastValidCode = 0;
if (fdo.isNull()) { if (fdo.isNull()) {
//the received code does not exist //the received code does not exist
@ -630,10 +634,11 @@ void decodeIRJson(uint32_t code)
} else if (!jsonCmdObj.isNull()) { } else if (!jsonCmdObj.isNull()) {
// command is JSON object // command is JSON object
//allow applyPreset() to reuse JSON buffer, or it would alloc. a second buffer and run out of mem. //allow applyPreset() to reuse JSON buffer, or it would alloc. a second buffer and run out of mem.
fileDoc = &irDoc; fileDoc = &doc;
deserializeState(jsonCmdObj, CALL_MODE_BUTTON); deserializeState(jsonCmdObj, CALL_MODE_BUTTON);
fileDoc = nullptr; fileDoc = nullptr;
} }
jsonBufferLock = false;
} }
void initIR() void initIR()

View File

@ -204,13 +204,13 @@ void deserializeSegment(JsonObject elem, byte it, byte presetId)
} }
strip.setPixelSegment(255); strip.setPixelSegment(255);
strip.trigger(); strip.trigger();
// this is now handled using the "frz" toggle.
} else if (!elem["frz"] && iarr.isNull()) { //return to regular effect } else if (!elem["frz"] && iarr.isNull()) { //return to regular effect
seg.setOption(SEG_OPTION_FREEZE, false); seg.setOption(SEG_OPTION_FREEZE, false);
} }
return; // seg.differs(prev); return; // seg.differs(prev);
} }
// deserializes WLED state (fileDoc points to doc object if called from web server)
bool deserializeState(JsonObject root, byte callMode, byte presetId) bool deserializeState(JsonObject root, byte callMode, byte presetId)
{ {
DEBUG_PRINTLN(F("Deserializing state")); DEBUG_PRINTLN(F("Deserializing state"));
@ -324,7 +324,8 @@ bool deserializeState(JsonObject root, byte callMode, byte presetId)
int8_t ledmap = root[F("ledmap")] | -1; int8_t ledmap = root[F("ledmap")] | -1;
if (ledmap >= 0) { if (ledmap >= 0) {
strip.deserializeMap(ledmap); //strip.deserializeMap(ledmap); // requires separate JSON buffer
loadLedmap = ledmap;
} }
int ps = root[F("psave")] | -1; int ps = root[F("psave")] | -1;

View File

@ -91,11 +91,15 @@ void onMqttMessage(char* topic, char* payload, AsyncMqttClientMessageProperties
colorUpdated(CALL_MODE_DIRECT_CHANGE); colorUpdated(CALL_MODE_DIRECT_CHANGE);
} else if (strcmp_P(topic, PSTR("/api")) == 0) { } else if (strcmp_P(topic, PSTR("/api")) == 0) {
if (payload[0] == '{') { //JSON API if (payload[0] == '{') { //JSON API
DynamicJsonDocument doc(JSON_BUFFER_SIZE); //DynamicJsonDocument doc(JSON_BUFFER_SIZE);
while (jsonBufferLock) delay(1);
jsonBufferLock = true;
doc.clear();
deserializeJson(doc, payloadStr); deserializeJson(doc, payloadStr);
fileDoc = &doc; fileDoc = &doc;
deserializeState(doc.as<JsonObject>()); deserializeState(doc.as<JsonObject>());
fileDoc = nullptr; fileDoc = nullptr;
jsonBufferLock = false;
} else { //HTTP API } else { //HTTP API
String apireq = "win&"; String apireq = "win&";
apireq += (char*)payloadStr; apireq += (char*)payloadStr;

View File

@ -20,14 +20,18 @@ bool applyPreset(byte index, byte callMode)
deserializeState(fdo, callMode, index); deserializeState(fdo, callMode, index);
} else { } else {
DEBUGFS_PRINTLN(F("Make read buf")); DEBUGFS_PRINTLN(F("Make read buf"));
DynamicJsonDocument fDoc(JSON_BUFFER_SIZE); //DynamicJsonDocument fDoc(JSON_BUFFER_SIZE);
errorFlag = readObjectFromFileUsingId(filename, index, &fDoc) ? ERR_NONE : ERR_FS_PLOAD; while (jsonBufferLock) delay(1);
JsonObject fdo = fDoc.as<JsonObject>(); jsonBufferLock = true;
doc.clear();
errorFlag = readObjectFromFileUsingId(filename, index, &doc) ? ERR_NONE : ERR_FS_PLOAD;
JsonObject fdo = doc.as<JsonObject>();
if (fdo["ps"] == index) fdo.remove("ps"); if (fdo["ps"] == index) fdo.remove("ps");
#ifdef WLED_DEBUG_FS #ifdef WLED_DEBUG_FS
serializeJson(fDoc, Serial); serializeJson(doc, Serial);
#endif #endif
deserializeState(fdo, callMode, index); deserializeState(fdo, callMode, index);
jsonBufferLock = false;
} }
if (!errorFlag) { if (!errorFlag) {
@ -40,22 +44,27 @@ bool applyPreset(byte index, byte callMode)
void savePreset(byte index, bool persist, const char* pname, JsonObject saveobj) void savePreset(byte index, bool persist, const char* pname, JsonObject saveobj)
{ {
if (index == 0 || (index > 250 && persist) || (index<255 && !persist)) return; if (index == 0 || (index > 250 && persist) || (index<255 && !persist)) return;
bool docAlloc = (fileDoc != nullptr);
JsonObject sObj = saveobj; JsonObject sObj = saveobj;
const char *filename = persist ? "/presets.json" : "/tmp.json"; const char *filename = persist ? "/presets.json" : "/tmp.json";
if (!docAlloc) { if (!fileDoc) {
DEBUGFS_PRINTLN(F("Allocating saving buffer")); DEBUGFS_PRINTLN(F("Allocating saving buffer"));
DynamicJsonDocument lDoc(JSON_BUFFER_SIZE); //DynamicJsonDocument lDoc(JSON_BUFFER_SIZE);
sObj = lDoc.to<JsonObject>(); while (jsonBufferLock) delay(1);
jsonBufferLock = true;
doc.clear();
sObj = doc.to<JsonObject>();
if (pname) sObj["n"] = pname; if (pname) sObj["n"] = pname;
DEBUGFS_PRINTLN(F("Save current state")); DEBUGFS_PRINTLN(F("Save current state"));
serializeState(sObj, true); serializeState(sObj, true);
if (persist) currentPreset = index; if (persist) currentPreset = index;
writeObjectToFileUsingId(filename, index, &lDoc); writeObjectToFileUsingId(filename, index, &doc);
} else { //from JSON API
jsonBufferLock = false;
} else { //from JSON API (fileDoc != nullptr)
DEBUGFS_PRINTLN(F("Reuse recv buffer")); DEBUGFS_PRINTLN(F("Reuse recv buffer"));
sObj.remove(F("psave")); sObj.remove(F("psave"));
sObj.remove(F("v")); sObj.remove(F("v"));

View File

@ -415,7 +415,11 @@ void handleSettingsSet(AsyncWebServerRequest *request, byte subPage)
//USERMODS //USERMODS
if (subPage == 8) if (subPage == 8)
{ {
DynamicJsonDocument doc(JSON_BUFFER_SIZE); //DynamicJsonDocument doc(JSON_BUFFER_SIZE);
while (jsonBufferLock) delay(1);
jsonBufferLock = true;
doc.clear();
JsonObject um = doc.createNestedObject("um"); JsonObject um = doc.createNestedObject("um");
size_t args = request->args(); size_t args = request->args();
@ -490,6 +494,8 @@ void handleSettingsSet(AsyncWebServerRequest *request, byte subPage)
usermods.readFromConfig(um); // force change of usermod parameters usermods.readFromConfig(um); // force change of usermod parameters
} }
jsonBufferLock = false;
if (subPage != 2 && (subPage != 6 || !doReboot)) serializeConfig(); //do not save if factory reset or LED settings (which are saved after LED re-init) if (subPage != 2 && (subPage != 6 || !doReboot)) serializeConfig(); //do not save if factory reset or LED settings (which are saved after LED re-init)
if (subPage == 4) alexaInit(); if (subPage == 4) alexaInit();
} }

View File

@ -150,11 +150,16 @@ void WLED::loop()
delete busConfigs[i]; busConfigs[i] = nullptr; delete busConfigs[i]; busConfigs[i] = nullptr;
} }
strip.finalizeInit(); strip.finalizeInit();
loadLedmap = 0;
if (aligned) strip.makeAutoSegments(); if (aligned) strip.makeAutoSegments();
else strip.fixInvalidSegments(); else strip.fixInvalidSegments();
yield(); yield();
serializeConfig(); serializeConfig();
} }
if (loadLedmap >= 0) {
strip.deserializeMap(loadLedmap);
loadLedmap = -1;
}
yield(); yield();
handleWs(); handleWs();
@ -339,6 +344,7 @@ void WLED::beginStrip()
{ {
// Initialize NeoPixel Strip and button // Initialize NeoPixel Strip and button
strip.finalizeInit(); // busses created during deserializeConfig() strip.finalizeInit(); // busses created during deserializeConfig()
strip.deserializeMap();
strip.makeAutoSegments(); strip.makeAutoSegments();
strip.setBrightness(0); strip.setBrightness(0);
strip.setShowCallback(handleOverlayDraw); strip.setShowCallback(handleOverlayDraw);

View File

@ -598,10 +598,15 @@ WLED_GLOBAL BusManager busses _INIT(BusManager());
WLED_GLOBAL WS2812FX strip _INIT(WS2812FX()); WLED_GLOBAL WS2812FX strip _INIT(WS2812FX());
WLED_GLOBAL BusConfig* busConfigs[WLED_MAX_BUSSES] _INIT({nullptr}); //temporary, to remember values from network callback until after WLED_GLOBAL BusConfig* busConfigs[WLED_MAX_BUSSES] _INIT({nullptr}); //temporary, to remember values from network callback until after
WLED_GLOBAL bool doInitBusses _INIT(false); WLED_GLOBAL bool doInitBusses _INIT(false);
WLED_GLOBAL int8_t loadLedmap _INIT(-1);
// Usermod manager // Usermod manager
WLED_GLOBAL UsermodManager usermods _INIT(UsermodManager()); WLED_GLOBAL UsermodManager usermods _INIT(UsermodManager());
// global ArduinoJson buffer
WLED_GLOBAL StaticJsonDocument<JSON_BUFFER_SIZE> doc;
WLED_GLOBAL volatile bool jsonBufferLock _INIT(false);
// enable additional debug output // enable additional debug output
#ifdef WLED_DEBUG #ifdef WLED_DEBUG
#ifndef ESP8266 #ifndef ESP8266

View File

@ -373,8 +373,12 @@ void deEEP() {
DEBUG_PRINTLN(F("Preset file not found, attempting to load from EEPROM")); DEBUG_PRINTLN(F("Preset file not found, attempting to load from EEPROM"));
DEBUGFS_PRINTLN(F("Allocating saving buffer for dEEP")); DEBUGFS_PRINTLN(F("Allocating saving buffer for dEEP"));
DynamicJsonDocument dDoc(JSON_BUFFER_SIZE *2); //DynamicJsonDocument doc(JSON_BUFFER_SIZE *2);
JsonObject sObj = dDoc.to<JsonObject>(); while (jsonBufferLock) delay(1);
jsonBufferLock = true;
doc.clear();
JsonObject sObj = doc.to<JsonObject>();
sObj.createNestedObject("0"); sObj.createNestedObject("0");
EEPROM.begin(EEPSIZE); EEPROM.begin(EEPSIZE);
@ -433,8 +437,6 @@ void deEEP() {
} }
} }
for (uint16_t index = 1; index <= 16; index++) { //copy macros to presets.json for (uint16_t index = 1; index <= 16; index++) { //copy macros to presets.json
char m[65]; char m[65];
readStringFromEEPROM(1024+64*(index-1), m, 64); readStringFromEEPROM(1024+64*(index-1), m, 64);
@ -456,8 +458,11 @@ void deEEP() {
errorFlag = ERR_FS_GENERAL; errorFlag = ERR_FS_GENERAL;
return; return;
} }
serializeJson(dDoc, f); serializeJson(doc, f);
f.close(); f.close();
jsonBufferLock = false;
DEBUG_PRINTLN(F("deEEP complete!")); DEBUG_PRINTLN(F("deEEP complete!"));
} }

View File

@ -43,18 +43,25 @@ void handleSerial()
} }
else if (next == '{') { //JSON API else if (next == '{') { //JSON API
bool verboseResponse = false; bool verboseResponse = false;
while (jsonBufferLock) delay(1);
jsonBufferLock = true;
doc.clear();
{ {
DynamicJsonDocument doc(JSON_BUFFER_SIZE); //DynamicJsonDocument doc(JSON_BUFFER_SIZE);
Serial.setTimeout(100); Serial.setTimeout(100);
DeserializationError error = deserializeJson(doc, Serial); DeserializationError error = deserializeJson(doc, Serial);
if (error) return; if (error) {
jsonBufferLock = false;
return;
}
fileDoc = &doc; fileDoc = &doc;
verboseResponse = deserializeState(doc.as<JsonObject>()); verboseResponse = deserializeState(doc.as<JsonObject>());
fileDoc = nullptr; fileDoc = nullptr;
} }
//only send response if TX pin is unused for other purposes //only send response if TX pin is unused for other purposes
if (verboseResponse && !pinManager.isPinAllocated(1)) { if (verboseResponse && !pinManager.isPinAllocated(1)) {
DynamicJsonDocument doc(JSON_BUFFER_SIZE); //DynamicJsonDocument doc(JSON_BUFFER_SIZE);
doc.clear();
JsonObject state = doc.createNestedObject("state"); JsonObject state = doc.createNestedObject("state");
serializeState(state); serializeState(state);
JsonObject info = doc.createNestedObject("info"); JsonObject info = doc.createNestedObject("info");
@ -62,6 +69,7 @@ void handleSerial()
serializeJson(doc, Serial); serializeJson(doc, Serial);
} }
jsonBufferLock = false;
} }
break; break;
case AdaState::Header_d: case AdaState::Header_d:

View File

@ -110,9 +110,13 @@ void initServer()
bool verboseResponse = false; bool verboseResponse = false;
bool isConfig = false; bool isConfig = false;
{ //scope JsonDocument so it releases its buffer { //scope JsonDocument so it releases its buffer
DynamicJsonDocument jsonBuffer(JSON_BUFFER_SIZE); //DynamicJsonDocument jsonBuffer(JSON_BUFFER_SIZE);
DeserializationError error = deserializeJson(jsonBuffer, (uint8_t*)(request->_tempObject)); while (jsonBufferLock) delay(1);
JsonObject root = jsonBuffer.as<JsonObject>(); jsonBufferLock = true;
doc.clear();
DeserializationError error = deserializeJson(doc, (uint8_t*)(request->_tempObject));
JsonObject root = doc.as<JsonObject>();
if (error || root.isNull()) { if (error || root.isNull()) {
request->send(400, "application/json", F("{\"error\":9}")); return; request->send(400, "application/json", F("{\"error\":9}")); return;
} }
@ -124,12 +128,13 @@ void initServer()
serializeJson(root,Serial); serializeJson(root,Serial);
DEBUG_PRINTLN(); DEBUG_PRINTLN();
#endif #endif
fileDoc = &jsonBuffer; // used for applying presets (presets.cpp) fileDoc = &doc; // used for applying presets (presets.cpp)
verboseResponse = deserializeState(root); verboseResponse = deserializeState(root);
fileDoc = nullptr; fileDoc = nullptr;
} else { } else {
verboseResponse = deserializeConfig(root); //use verboseResponse to determine whether cfg change should be saved immediately verboseResponse = deserializeConfig(root); //use verboseResponse to determine whether cfg change should be saved immediately
} }
jsonBufferLock = false;
} }
if (verboseResponse) { if (verboseResponse) {
if (!isConfig) { if (!isConfig) {

View File

@ -36,16 +36,24 @@ void wsEvent(AsyncWebSocket * server, AsyncWebSocketClient * client, AwsEventTyp
} }
bool verboseResponse = false; bool verboseResponse = false;
{ //scope JsonDocument so it releases its buffer { //scope JsonDocument so it releases its buffer
DynamicJsonDocument jsonBuffer(JSON_BUFFER_SIZE); //DynamicJsonDocument doc(JSON_BUFFER_SIZE);
DeserializationError error = deserializeJson(jsonBuffer, data, len); while (jsonBufferLock) delay(1);
JsonObject root = jsonBuffer.as<JsonObject>(); jsonBufferLock = true;
if (error || root.isNull()) return; doc.clear();
DeserializationError error = deserializeJson(doc, data, len);
JsonObject root = doc.as<JsonObject>();
if (error || root.isNull()) {
jsonBufferLock = false;
return;
}
/*
#ifdef WLED_DEBUG #ifdef WLED_DEBUG
DEBUG_PRINT(F("Incoming WS: ")); DEBUG_PRINT(F("Incoming WS: "));
serializeJson(root,Serial); serializeJson(root,Serial);
DEBUG_PRINTLN(); DEBUG_PRINTLN();
#endif #endif
*/
if (root["v"] && root.size() == 1) { if (root["v"] && root.size() == 1) {
//if the received value is just "{"v":true}", send only to this client //if the received value is just "{"v":true}", send only to this client
verboseResponse = true; verboseResponse = true;
@ -53,7 +61,7 @@ void wsEvent(AsyncWebSocket * server, AsyncWebSocketClient * client, AwsEventTyp
{ {
wsLiveClientId = root["lv"] ? client->id() : 0; wsLiveClientId = root["lv"] ? client->id() : 0;
} else { } else {
fileDoc = &jsonBuffer; fileDoc = &doc;
verboseResponse = deserializeState(root); verboseResponse = deserializeState(root);
fileDoc = nullptr; fileDoc = nullptr;
if (!interfaceUpdateCallMode) { if (!interfaceUpdateCallMode) {
@ -61,6 +69,7 @@ void wsEvent(AsyncWebSocket * server, AsyncWebSocketClient * client, AwsEventTyp
if (millis() - lastInterfaceUpdate > 1700) verboseResponse = false; if (millis() - lastInterfaceUpdate > 1700) verboseResponse = false;
} }
} }
jsonBufferLock = false;
} }
//update if it takes longer than 300ms until next "broadcast" //update if it takes longer than 300ms until next "broadcast"
if (verboseResponse && (millis() - lastInterfaceUpdate < 1700 || !interfaceUpdateCallMode)) sendDataWs(client); if (verboseResponse && (millis() - lastInterfaceUpdate < 1700 || !interfaceUpdateCallMode)) sendDataWs(client);
@ -102,14 +111,20 @@ void sendDataWs(AsyncWebSocketClient * client)
AsyncWebSocketMessageBuffer * buffer; AsyncWebSocketMessageBuffer * buffer;
{ //scope JsonDocument so it releases its buffer { //scope JsonDocument so it releases its buffer
DynamicJsonDocument doc(JSON_BUFFER_SIZE); //DynamicJsonDocument doc(JSON_BUFFER_SIZE);
while (jsonBufferLock) delay(1);
jsonBufferLock = true;
doc.clear();
JsonObject state = doc.createNestedObject("state"); JsonObject state = doc.createNestedObject("state");
serializeState(state); serializeState(state);
JsonObject info = doc.createNestedObject("info"); JsonObject info = doc.createNestedObject("info");
serializeInfo(info); serializeInfo(info);
size_t len = measureJson(doc); size_t len = measureJson(doc);
buffer = ws.makeBuffer(len); buffer = ws.makeBuffer(len);
if (!buffer) return; //out of memory if (!buffer) {
jsonBufferLock = false;
return; //out of memory
}
/* /*
#ifdef WLED_DEBUG #ifdef WLED_DEBUG
DEBUG_PRINT(F("Outgoing WS: ")); DEBUG_PRINT(F("Outgoing WS: "));
@ -118,6 +133,7 @@ void sendDataWs(AsyncWebSocketClient * client)
#endif #endif
*/ */
serializeJson(doc, (char *)buffer->get(), len +1); serializeJson(doc, (char *)buffer->get(), len +1);
jsonBufferLock = false;
} }
DEBUG_PRINT(F("Sending WS data ")); DEBUG_PRINT(F("Sending WS data "));
if (client) { if (client) {

View File

@ -249,13 +249,18 @@ void getSettingsJS(byte subPage, char* dest)
{ {
char nS[8]; char nS[8];
// Pin reservations will become unnecessary when settings pages will read cfg.json directly
// add reserved and usermod pins as d.um_p array // add reserved and usermod pins as d.um_p array
oappend(SET_F("d.um_p=[6,7,8,9,10,11")); oappend(SET_F("d.um_p=[6,7,8,9,10,11"));
DynamicJsonDocument doc(JSON_BUFFER_SIZE/2); //DynamicJsonDocument doc(JSON_BUFFER_SIZE/2);
while (jsonBufferLock) delay(1);
jsonBufferLock = true;
doc.clear();
JsonObject mods = doc.createNestedObject(F("um")); JsonObject mods = doc.createNestedObject(F("um"));
usermods.addToConfig(mods); usermods.addToConfig(mods);
if (!mods.isNull()) fillUMPins(mods); if (!mods.isNull()) fillUMPins(mods);
jsonBufferLock = false;
#ifdef WLED_ENABLE_DMX #ifdef WLED_ENABLE_DMX
oappend(SET_F(",2")); // DMX hardcoded pin oappend(SET_F(",2")); // DMX hardcoded pin