Advanced locking with time-out.

Bugfixes.
This commit is contained in:
Blaz Kristan 2021-11-12 23:33:10 +01:00
parent ce5a81d83c
commit 85ded6e500
15 changed files with 145 additions and 95 deletions

View File

@ -1092,16 +1092,17 @@ void WS2812FX::deserializeMap(uint8_t n) {
#ifdef WLED_USE_DYNAMIC_JSON #ifdef WLED_USE_DYNAMIC_JSON
DynamicJsonDocument doc(JSON_BUFFER_SIZE); DynamicJsonDocument doc(JSON_BUFFER_SIZE);
#else #else
while (jsonBufferLock) delay(1); if (!requestJSONBufferLock()) {
jsonBufferLock = true; DEBUG_PRINTLN(F("ERROR: Locking JSON buffer failed!"));
doc.clear(); return;
}
#endif #endif
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)) { if (!readObjectFromFile(fileName, nullptr, &doc)) {
jsonBufferLock = false; releaseJSONBufferLock();
return; //if file does not exist just exit return; //if file does not exist just exit
} }
@ -1121,7 +1122,7 @@ void WS2812FX::deserializeMap(uint8_t n) {
} }
} }
jsonBufferLock = false; releaseJSONBufferLock();
} }
//gamma 2.8 lookup table used for color correction //gamma 2.8 lookup table used for color correction

View File

@ -410,12 +410,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()) {
needsSave = usermods.readFromConfig(usermods_settings); needsSave = !usermods.readFromConfig(usermods_settings);
} }
if (fromFS) return needsSave; if (fromFS) return needsSave;
doReboot = doc[F("rb")] | doReboot; doReboot = doc[F("rb")] | doReboot;
return (doc["sv"] | needsSave); return (doc["sv"] | true);
} }
void deserializeConfigFromFS() { void deserializeConfigFromFS() {
@ -428,9 +428,10 @@ void deserializeConfigFromFS() {
#ifdef WLED_USE_DYNAMIC_JSON #ifdef WLED_USE_DYNAMIC_JSON
DynamicJsonDocument doc(JSON_BUFFER_SIZE); DynamicJsonDocument doc(JSON_BUFFER_SIZE);
#else #else
while (jsonBufferLock) delay(1); if (!requestJSONBufferLock()) {
jsonBufferLock = true; DEBUG_PRINTLN(F("ERROR: Locking JSON buffer failed!"));
doc.clear(); return;
}
#endif #endif
DEBUG_PRINTLN(F("Reading settings from /cfg.json...")); DEBUG_PRINTLN(F("Reading settings from /cfg.json..."));
@ -438,14 +439,14 @@ void deserializeConfigFromFS() {
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; releaseJSONBufferLock();
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
bool needsSave = deserializeConfig(doc.as<JsonObject>(), true); bool needsSave = deserializeConfig(doc.as<JsonObject>(), true);
jsonBufferLock = false; releaseJSONBufferLock();
if (needsSave) serializeConfig(); // usermods required new prameters if (needsSave) serializeConfig(); // usermods required new prameters
} }
@ -458,9 +459,10 @@ void serializeConfig() {
#ifdef WLED_USE_DYNAMIC_JSON #ifdef WLED_USE_DYNAMIC_JSON
DynamicJsonDocument doc(JSON_BUFFER_SIZE); DynamicJsonDocument doc(JSON_BUFFER_SIZE);
#else #else
while (jsonBufferLock) delay(1); if (!requestJSONBufferLock()) {
jsonBufferLock = true; DEBUG_PRINTLN(F("ERROR: Locking JSON buffer failed!"));
doc.clear(); return;
}
#endif #endif
JsonArray rev = doc.createNestedArray("rev"); JsonArray rev = doc.createNestedArray("rev");
@ -768,7 +770,7 @@ 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; releaseJSONBufferLock();
} }
//settings in /wsec.json, not accessible via webserver, for passwords and tokens //settings in /wsec.json, not accessible via webserver, for passwords and tokens
@ -778,14 +780,15 @@ bool deserializeConfigSec() {
#ifdef WLED_USE_DYNAMIC_JSON #ifdef WLED_USE_DYNAMIC_JSON
DynamicJsonDocument doc(JSON_BUFFER_SIZE); DynamicJsonDocument doc(JSON_BUFFER_SIZE);
#else #else
while (jsonBufferLock) delay(1); if (!requestJSONBufferLock()) {
jsonBufferLock = true; DEBUG_PRINTLN(F("ERROR: Locking JSON buffer failed!"));
doc.clear(); return false;
}
#endif #endif
bool success = readObjectFromFile("/wsec.json", nullptr, &doc); bool success = readObjectFromFile("/wsec.json", nullptr, &doc);
if (!success) { if (!success) {
jsonBufferLock = false; releaseJSONBufferLock();
return false; return false;
} }
@ -819,7 +822,7 @@ 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; releaseJSONBufferLock();
return true; return true;
} }
@ -829,9 +832,10 @@ void serializeConfigSec() {
#ifdef WLED_USE_DYNAMIC_JSON #ifdef WLED_USE_DYNAMIC_JSON
DynamicJsonDocument doc(JSON_BUFFER_SIZE); DynamicJsonDocument doc(JSON_BUFFER_SIZE);
#else #else
while (jsonBufferLock) delay(1); if (!requestJSONBufferLock()) {
jsonBufferLock = true; DEBUG_PRINTLN(F("ERROR: Locking JSON buffer failed!"));
doc.clear(); return;
}
#endif #endif
JsonObject nw = doc.createNestedObject("nw"); JsonObject nw = doc.createNestedObject("nw");
@ -867,5 +871,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; releaseJSONBufferLock();
} }

View File

@ -272,6 +272,8 @@ void sappends(char stype, const char* key, char* val);
void prepareHostname(char* hostname); void prepareHostname(char* hostname);
void _setRandomColor(bool _sec, bool fromButton); void _setRandomColor(bool _sec, bool fromButton);
bool isAsterisksOnly(const char* str, byte maxLen); bool isAsterisksOnly(const char* str, byte maxLen);
bool requestJSONBufferLock();
void releaseJSONBufferLock();
//wled_eeprom.cpp //wled_eeprom.cpp
void applyMacro(byte index); void applyMacro(byte index);

View File

@ -575,12 +575,14 @@ void decodeIRJson(uint32_t code)
JsonObject fdo; JsonObject fdo;
JsonObject jsonCmdObj; JsonObject jsonCmdObj;
DEBUG_PRINTLN(F("IR JSON buffer requested."));
#ifdef WLED_USE_DYNAMIC_JSON #ifdef WLED_USE_DYNAMIC_JSON
DynamicJsonDocument doc(JSON_BUFFER_SIZE); DynamicJsonDocument doc(JSON_BUFFER_SIZE);
#else #else
while (jsonBufferLock) delay(1); if (!requestJSONBufferLock()) {
jsonBufferLock = true; DEBUG_PRINTLN(F("ERROR: Locking JSON buffer failed!"));
doc.clear(); return;
}
#endif #endif
sprintf_P(objKey, PSTR("\"0x%lX\":"), (unsigned long)code); sprintf_P(objKey, PSTR("\"0x%lX\":"), (unsigned long)code);
@ -601,6 +603,9 @@ void decodeIRJson(uint32_t code)
cmdStr = fdo["cmd"].as<String>();; cmdStr = fdo["cmd"].as<String>();;
jsonCmdObj = fdo["cmd"]; //object jsonCmdObj = fdo["cmd"]; //object
// command is JSON object
//allow applyPreset() to reuse JSON buffer, or it would alloc. a second buffer and run out of mem.
//fileDoc = &doc; // used for applying presets (presets.cpp)
if (!cmdStr.isEmpty()) if (!cmdStr.isEmpty())
{ {
if (cmdStr.startsWith("!")) { if (cmdStr.startsWith("!")) {
@ -635,13 +640,10 @@ void decodeIRJson(uint32_t code)
} }
colorUpdated(CALL_MODE_BUTTON); colorUpdated(CALL_MODE_BUTTON);
} else if (!jsonCmdObj.isNull()) { } else if (!jsonCmdObj.isNull()) {
// command is JSON object
//allow applyPreset() to reuse JSON buffer, or it would alloc. a second buffer and run out of mem.
fileDoc = &doc;
deserializeState(jsonCmdObj, CALL_MODE_BUTTON); deserializeState(jsonCmdObj, CALL_MODE_BUTTON);
fileDoc = nullptr;
} }
jsonBufferLock = false; //fileDoc = nullptr;
releaseJSONBufferLock();
} }
void initIR() void initIR()

View File

@ -920,9 +920,10 @@ void serveJson(AsyncWebServerRequest* request)
#ifdef WLED_USE_DYNAMIC_JSON #ifdef WLED_USE_DYNAMIC_JSON
AsyncJsonResponse* response = new AsyncJsonResponse(JSON_BUFFER_SIZE); AsyncJsonResponse* response = new AsyncJsonResponse(JSON_BUFFER_SIZE);
#else #else
while (jsonBufferLock) delay(1); if (!requestJSONBufferLock()) {
jsonBufferLock = true; DEBUG_PRINTLN(F("ERROR: Locking JSON buffer failed!"));
doc.clear(); return;
}
AsyncJsonResponse *response = new AsyncJsonResponse(&doc); AsyncJsonResponse *response = new AsyncJsonResponse(&doc);
#endif #endif
@ -956,7 +957,7 @@ void serveJson(AsyncWebServerRequest* request)
response->setLength(); response->setLength();
request->send(response); request->send(response);
jsonBufferLock = false; releaseJSONBufferLock();
} }
#define MAX_LIVE_LEDS 180 #define MAX_LIVE_LEDS 180

View File

@ -90,26 +90,26 @@ void onMqttMessage(char* topic, char* payload, AsyncMqttClientMessageProperties
colorFromDecOrHexString(col, (char*)payloadStr); colorFromDecOrHexString(col, (char*)payloadStr);
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 DEBUG_PRINTLN(F("MQTT JSON buffer requested."));
#ifdef WLED_USE_DYNAMIC_JSON #ifdef WLED_USE_DYNAMIC_JSON
DynamicJsonDocument doc(JSON_BUFFER_SIZE); DynamicJsonDocument doc(JSON_BUFFER_SIZE);
#else #else
while (jsonBufferLock) delay(1); if (!requestJSONBufferLock()) {
jsonBufferLock = true; DEBUG_PRINTLN(F("ERROR: Locking JSON buffer failed!"));
doc.clear(); return;
}
#endif #endif
if (payload[0] == '{') { //JSON API
deserializeJson(doc, payloadStr); deserializeJson(doc, payloadStr);
fileDoc = &doc; //fileDoc = &doc; // used for applying presets (presets.cpp)
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;
handleSet(nullptr, apireq); handleSet(nullptr, apireq);
} }
releaseJSONBufferLock();
} else if (strlen(topic) != 0) { } else if (strlen(topic) != 0) {
// non standard topic, check with usermods // non standard topic, check with usermods
usermods.onMqttMessage(topic, payloadStr); usermods.onMqttMessage(topic, payloadStr);

View File

@ -4,6 +4,8 @@
* Methods to handle saving and loading presets to/from the filesystem * Methods to handle saving and loading presets to/from the filesystem
*/ */
// called from: handleSet(), deserializeState(), applyMacro(), handlePlaylist(), checkCountdown(), checkTimers(), handleNightlight(), presetFallback()
// shortPressAction(), longPressAction(), doublePressAction(), handleSwitch(), onAlexaChange()
bool applyPreset(byte index, byte callMode) bool applyPreset(byte index, byte callMode)
{ {
if (index == 0) return false; if (index == 0) return false;
@ -19,13 +21,14 @@ bool applyPreset(byte index, byte callMode)
#endif #endif
deserializeState(fdo, callMode, index); deserializeState(fdo, callMode, index);
} else { } else {
DEBUGFS_PRINTLN(F("Make read buf")); DEBUG_PRINTLN(F("Apply preset JSON buffer requested."));
#ifdef WLED_USE_DYNAMIC_JSON #ifdef WLED_USE_DYNAMIC_JSON
DynamicJsonDocument doc(JSON_BUFFER_SIZE); DynamicJsonDocument doc(JSON_BUFFER_SIZE);
#else #else
while (jsonBufferLock) delay(1); if (!requestJSONBufferLock()) {
jsonBufferLock = true; DEBUG_PRINTLN(F("ERROR: Locking JSON buffer failed!"));
doc.clear(); return false;
}
#endif #endif
errorFlag = readObjectFromFileUsingId(filename, index, &doc) ? ERR_NONE : ERR_FS_PLOAD; errorFlag = readObjectFromFileUsingId(filename, index, &doc) ? ERR_NONE : ERR_FS_PLOAD;
@ -35,7 +38,7 @@ bool applyPreset(byte index, byte callMode)
serializeJson(doc, Serial); serializeJson(doc, Serial);
#endif #endif
deserializeState(fdo, callMode, index); deserializeState(fdo, callMode, index);
jsonBufferLock = false; releaseJSONBufferLock();
} }
if (!errorFlag) { if (!errorFlag) {
@ -53,13 +56,14 @@ void savePreset(byte index, bool persist, const char* pname, JsonObject saveobj)
const char *filename = persist ? "/presets.json" : "/tmp.json"; const char *filename = persist ? "/presets.json" : "/tmp.json";
if (!fileDoc) { if (!fileDoc) {
DEBUGFS_PRINTLN(F("Allocating saving buffer")); DEBUG_PRINTLN(F("Save preset JSON buffer requested."));
#ifdef WLED_USE_DYNAMIC_JSON #ifdef WLED_USE_DYNAMIC_JSON
DynamicJsonDocument doc(JSON_BUFFER_SIZE); DynamicJsonDocument doc(JSON_BUFFER_SIZE);
#else #else
while (jsonBufferLock) delay(1); if (!requestJSONBufferLock()) {
jsonBufferLock = true; DEBUG_PRINTLN(F("ERROR: Locking JSON buffer failed!"));
doc.clear(); return;
}
#endif #endif
sObj = doc.to<JsonObject>(); sObj = doc.to<JsonObject>();
@ -71,7 +75,7 @@ void savePreset(byte index, bool persist, const char* pname, JsonObject saveobj)
writeObjectToFileUsingId(filename, index, &doc); writeObjectToFileUsingId(filename, index, &doc);
jsonBufferLock = false; releaseJSONBufferLock();
} else { //from JSON API (fileDoc != nullptr) } 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"));

View File

@ -418,9 +418,10 @@ void handleSettingsSet(AsyncWebServerRequest *request, byte subPage)
#ifdef WLED_USE_DYNAMIC_JSON #ifdef WLED_USE_DYNAMIC_JSON
DynamicJsonDocument doc(JSON_BUFFER_SIZE); DynamicJsonDocument doc(JSON_BUFFER_SIZE);
#else #else
while (jsonBufferLock) delay(1); if (!requestJSONBufferLock()) {
jsonBufferLock = true; DEBUG_PRINTLN(F("ERROR: Locking JSON buffer failed!"));
doc.clear(); return;
}
#endif #endif
JsonObject um = doc.createNestedObject("um"); JsonObject um = doc.createNestedObject("um");
@ -497,7 +498,7 @@ void handleSettingsSet(AsyncWebServerRequest *request, byte subPage)
usermods.readFromConfig(um); // force change of usermod parameters usermods.readFromConfig(um); // force change of usermod parameters
} }
jsonBufferLock = false; releaseJSONBufferLock();
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

@ -129,3 +129,27 @@ bool isAsterisksOnly(const char* str, byte maxLen)
//at this point the password contains asterisks only //at this point the password contains asterisks only
return (str[0] != 0); //false on empty string return (str[0] != 0); //false on empty string
} }
bool requestJSONBufferLock()
{
unsigned long now = millis();
while (jsonBufferLock && millis()-now < 1000) delay(1); // wait for a second for buffer lock
if (millis()-now >= 1000) return false; // waiting time-outed
jsonBufferLock = true;
fileDoc = &doc; // used for applying presets (presets.cpp)
doc.clear();
return true;
}
void releaseJSONBufferLock()
{
#ifndef WLED_USE_DYNAMIC_JSON
fileDoc = nullptr;
jsonBufferLock = false;
#endif
}

View File

@ -8,7 +8,7 @@
*/ */
// version code in format yymmddb (b = daily build) // version code in format yymmddb (b = daily build)
#define VERSION 2111091 #define VERSION 2111121
//uncomment this if you have a "my_config.h" file you'd like to use //uncomment this if you have a "my_config.h" file you'd like to use
//#define WLED_USE_MY_CONFIG //#define WLED_USE_MY_CONFIG

View File

@ -385,9 +385,10 @@ void deEEP() {
#ifdef WLED_USE_DYNAMIC_JSON #ifdef WLED_USE_DYNAMIC_JSON
DynamicJsonDocument doc(JSON_BUFFER_SIZE); DynamicJsonDocument doc(JSON_BUFFER_SIZE);
#else #else
while (jsonBufferLock) delay(1); if (!requestJSONBufferLock()) {
jsonBufferLock = true; DEBUG_PRINTLN(F("ERROR: Locking JSON buffer failed!"));
doc.clear(); return;
}
#endif #endif
JsonObject sObj = doc.to<JsonObject>(); JsonObject sObj = doc.to<JsonObject>();
@ -473,7 +474,7 @@ void deEEP() {
serializeJson(doc, f); serializeJson(doc, f);
f.close(); f.close();
jsonBufferLock = false; releaseJSONBufferLock();
DEBUG_PRINTLN(F("deEEP complete!")); DEBUG_PRINTLN(F("deEEP complete!"));
} }

View File

@ -43,22 +43,24 @@ void handleSerial()
} }
else if (next == '{') { //JSON API else if (next == '{') { //JSON API
bool verboseResponse = false; bool verboseResponse = false;
DEBUG_PRINTLN(F("Serial JSON buffer requested."));
#ifdef WLED_USE_DYNAMIC_JSON #ifdef WLED_USE_DYNAMIC_JSON
DynamicJsonDocument doc(JSON_BUFFER_SIZE); DynamicJsonDocument doc(JSON_BUFFER_SIZE);
#else #else
while (jsonBufferLock) delay(1); if (!requestJSONBufferLock()) {
jsonBufferLock = true; DEBUG_PRINTLN(F("ERROR: Locking JSON buffer failed!"));
doc.clear(); return;
}
#endif #endif
Serial.setTimeout(100); Serial.setTimeout(100);
DeserializationError error = deserializeJson(doc, Serial); DeserializationError error = deserializeJson(doc, Serial);
if (error) { if (error) {
jsonBufferLock = false; releaseJSONBufferLock();
return; return;
} }
fileDoc = &doc; //fileDoc = &doc; // used for applying presets (presets.cpp)
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)) {
@ -70,7 +72,7 @@ void handleSerial()
serializeJson(doc, Serial); serializeJson(doc, Serial);
} }
jsonBufferLock = false; releaseJSONBufferLock();
} }
break; break;
case AdaState::Header_d: case AdaState::Header_d:

View File

@ -110,12 +110,14 @@ 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
DEBUG_PRINTLN(F("HTTP JSON buffer requested."));
#ifdef WLED_USE_DYNAMIC_JSON #ifdef WLED_USE_DYNAMIC_JSON
DynamicJsonDocument doc(JSON_BUFFER_SIZE); DynamicJsonDocument doc(JSON_BUFFER_SIZE);
#else #else
while (jsonBufferLock) delay(1); if (!requestJSONBufferLock()) {
jsonBufferLock = true; DEBUG_PRINTLN(F("ERROR: Locking JSON buffer failed!"));
doc.clear(); return;
}
#endif #endif
DeserializationError error = deserializeJson(doc, (uint8_t*)(request->_tempObject)); DeserializationError error = deserializeJson(doc, (uint8_t*)(request->_tempObject));
@ -131,13 +133,13 @@ void initServer()
serializeJson(root,Serial); serializeJson(root,Serial);
DEBUG_PRINTLN(); DEBUG_PRINTLN();
#endif #endif
fileDoc = &doc; // 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; releaseJSONBufferLock();
} }
if (verboseResponse) { if (verboseResponse) {
if (!isConfig) { if (!isConfig) {

View File

@ -36,18 +36,20 @@ 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
DEBUG_PRINTLN(F("WS JSON receive buffer requested."));
#ifdef WLED_USE_DYNAMIC_JSON #ifdef WLED_USE_DYNAMIC_JSON
DynamicJsonDocument doc(JSON_BUFFER_SIZE); DynamicJsonDocument doc(JSON_BUFFER_SIZE);
#else #else
while (jsonBufferLock) delay(1); if (!requestJSONBufferLock()) {
jsonBufferLock = true; DEBUG_PRINTLN(F("ERROR: Locking JSON buffer failed!"));
doc.clear(); return;
}
#endif #endif
DeserializationError error = deserializeJson(doc, data, len); DeserializationError error = deserializeJson(doc, data, len);
JsonObject root = doc.as<JsonObject>(); JsonObject root = doc.as<JsonObject>();
if (error || root.isNull()) { if (error || root.isNull()) {
jsonBufferLock = false; releaseJSONBufferLock();
return; return;
} }
/* /*
@ -64,15 +66,15 @@ void wsEvent(AsyncWebSocket * server, AsyncWebSocketClient * client, AwsEventTyp
{ {
wsLiveClientId = root["lv"] ? client->id() : 0; wsLiveClientId = root["lv"] ? client->id() : 0;
} else { } else {
fileDoc = &doc; //fileDoc = &doc; // used for applying presets (presets.cpp)
verboseResponse = deserializeState(root); verboseResponse = deserializeState(root);
fileDoc = nullptr; //fileDoc = nullptr;
if (!interfaceUpdateCallMode) { if (!interfaceUpdateCallMode) {
//special case, only on playlist load, avoid sending twice in rapid succession //special case, only on playlist load, avoid sending twice in rapid succession
if (millis() - lastInterfaceUpdate > 1700) verboseResponse = false; if (millis() - lastInterfaceUpdate > 1700) verboseResponse = false;
} }
} }
jsonBufferLock = false; releaseJSONBufferLock();
} }
//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);
@ -114,12 +116,14 @@ void sendDataWs(AsyncWebSocketClient * client)
AsyncWebSocketMessageBuffer * buffer; AsyncWebSocketMessageBuffer * buffer;
{ //scope JsonDocument so it releases its buffer { //scope JsonDocument so it releases its buffer
DEBUG_PRINTLN(F("WS JSON send buffer requested."));
#ifdef WLED_USE_DYNAMIC_JSON #ifdef WLED_USE_DYNAMIC_JSON
DynamicJsonDocument doc(JSON_BUFFER_SIZE); DynamicJsonDocument doc(JSON_BUFFER_SIZE);
#else #else
while (jsonBufferLock) delay(1); if (!requestJSONBufferLock()) {
jsonBufferLock = true; DEBUG_PRINTLN(F("ERROR: Locking JSON buffer failed!"));
doc.clear(); return;
}
#endif #endif
JsonObject state = doc.createNestedObject("state"); JsonObject state = doc.createNestedObject("state");
@ -129,7 +133,7 @@ void sendDataWs(AsyncWebSocketClient * client)
size_t len = measureJson(doc); size_t len = measureJson(doc);
buffer = ws.makeBuffer(len); buffer = ws.makeBuffer(len);
if (!buffer) { if (!buffer) {
jsonBufferLock = false; releaseJSONBufferLock();
return; //out of memory return; //out of memory
} }
/* /*
@ -140,7 +144,7 @@ void sendDataWs(AsyncWebSocketClient * client)
#endif #endif
*/ */
serializeJson(doc, (char *)buffer->get(), len +1); serializeJson(doc, (char *)buffer->get(), len +1);
jsonBufferLock = false; releaseJSONBufferLock();
} }
DEBUG_PRINT(F("Sending WS data ")); DEBUG_PRINT(F("Sending WS data "));
if (client) { if (client) {

View File

@ -254,17 +254,19 @@ void getSettingsJS(byte subPage, char* dest)
oappend(SET_F("d.um_p=[6,7,8,9,10,11")); oappend(SET_F("d.um_p=[6,7,8,9,10,11"));
#ifdef WLED_USE_DYNAMIC_JSON #ifdef WLED_USE_DYNAMIC_JSON
DynamicJsonDocument doc(JSON_BUFFER_SIZE); DynamicJsonDocument doc(2048); // 2k is enough for usermods
#else #else
while (jsonBufferLock) delay(1); if (!requestJSONBufferLock()) {
jsonBufferLock = true; DEBUG_PRINTLN(F("ERROR: Locking JSON buffer failed!"));
doc.clear(); return;
}
#endif #endif
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;
releaseJSONBufferLock();
#ifdef WLED_ENABLE_DMX #ifdef WLED_ENABLE_DMX
oappend(SET_F(",2")); // DMX hardcoded pin oappend(SET_F(",2")); // DMX hardcoded pin