From f0e182bd29019324c7c8fb2abd5e4ae2f1d8fb85 Mon Sep 17 00:00:00 2001 From: smitty078 Date: Thu, 7 May 2026 02:33:12 -0400 Subject: [PATCH 01/11] Fix boot preset live data override handling --- wled00/presets.cpp | 5 +++-- wled00/wled.cpp | 6 ++++++ 2 files changed, 9 insertions(+), 2 deletions(-) diff --git a/wled00/presets.cpp b/wled00/presets.cpp index 9023baf344..079b5a25ce 100644 --- a/wled00/presets.cpp +++ b/wled00/presets.cpp @@ -194,7 +194,8 @@ void handlePresets() changePreset = true; } else { if (!fdo["seg"].isNull() || !fdo["on"].isNull() || !fdo["bri"].isNull() || !fdo["nl"].isNull() || !fdo["ps"].isNull() || !fdo[F("playlist")].isNull()) changePreset = true; - if (!(tmpMode == CALL_MODE_BUTTON_PRESET && fdo["ps"].is() && strchr(fdo["ps"].as(),'~') != strrchr(fdo["ps"].as(),'~'))) + + if (!(tmpMode == CALL_MODE_INIT || (tmpMode == CALL_MODE_BUTTON_PRESET && fdo["ps"].is() && strchr(fdo["ps"].as(),'~') != strrchr(fdo["ps"].as(),'~')))) // exception for CALL_MODE_INIT and button preset fdo.remove("ps"); // remove load request for presets to prevent recursive crash (if not called by button and contains preset cycling string "1~5~") deserializeState(fdo, CALL_MODE_NO_NOTIFY, tmpPreset); // may change presetToApply by calling applyPreset() } @@ -282,4 +283,4 @@ void deletePreset(byte index) { writeObjectToFileUsingId(getPresetsFileName(), index, &empty); presetsModifiedTime = toki.second(); //unix time updateFSInfo(); -} \ No newline at end of file +} diff --git a/wled00/wled.cpp b/wled00/wled.cpp index eb6019e6bf..c1312a71ca 100644 --- a/wled00/wled.cpp +++ b/wled00/wled.cpp @@ -503,6 +503,12 @@ void WLED::setup() if (needsCfgSave) serializeConfigToFS(); // usermods required new parameters; need to wait for strip to be initialised #4752 + if (bootPreset > 0) { + handlePresets(); + yield(); + handlePresets(); // Allow a boot preset to chain to one numeric preset exactly once. + } + if (strcmp(multiWiFi[0].clientSSID, DEFAULT_CLIENT_SSID) == 0 && !configBackupExists()) showWelcomePage = true; From 83065c15aed3f535a6a14645e14667261b10713f Mon Sep 17 00:00:00 2001 From: redpandadev <304245+smitty078@users.noreply.github.com> Date: Thu, 7 May 2026 10:18:22 -0400 Subject: [PATCH 02/11] Initial implementation to apply the same improvements to boot playlist TODO: set up logic handling inside handlePresets() and anywhere else required to implement behavior that is described in comments here. --- wled00/wled.cpp | 12 ++++++++++-- 1 file changed, 10 insertions(+), 2 deletions(-) diff --git a/wled00/wled.cpp b/wled00/wled.cpp index c1312a71ca..6ff10853a8 100644 --- a/wled00/wled.cpp +++ b/wled00/wled.cpp @@ -504,9 +504,17 @@ void WLED::setup() if (needsCfgSave) serializeConfigToFS(); // usermods required new parameters; need to wait for strip to be initialised #4752 if (bootPreset > 0) { - handlePresets(); + if (!presetNeedsSaving()) { + handlePlaylist(); // handle boot playlist at setup + yield(); + } + handlePresets(); // handle boot preset (including playlist) at setup + // Allow a boot preset to chain to one numeric preset exactly once (if it sets lor) + // Allow a boot playlist is able to apply the first preset (if it sets lor) + // In both cases, pre-existing protection against recursion is preserved + // See logic inside of handlePresets() yield(); - handlePresets(); // Allow a boot preset to chain to one numeric preset exactly once. + handlePresets(); } if (strcmp(multiWiFi[0].clientSSID, DEFAULT_CLIENT_SSID) == 0 && !configBackupExists()) From c8f50e6f5aa4d9e8be44949f3136759690bbd714 Mon Sep 17 00:00:00 2001 From: redpandadev <304245+smitty078@users.noreply.github.com> Date: Thu, 7 May 2026 10:24:24 -0400 Subject: [PATCH 03/11] Add TODO for boot preset and playlist scenarios Add TODO comments for handling boot presets and playlists. --- wled00/presets.cpp | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/wled00/presets.cpp b/wled00/presets.cpp index 079b5a25ce..a9498a749b 100644 --- a/wled00/presets.cpp +++ b/wled00/presets.cpp @@ -195,6 +195,10 @@ void handlePresets() } else { if (!fdo["seg"].isNull() || !fdo["on"].isNull() || !fdo["bri"].isNull() || !fdo["nl"].isNull() || !fdo["ps"].isNull() || !fdo[F("playlist")].isNull()) changePreset = true; + // TODO: + // Scenario 1: boot preset (CALL_MODE_INIT AND sets lor>0) - do not strip ps, allowing boot preset to chain 1 single preset + // Scenario 2: boot playlist (CALL_MODE_DIRECT_CHANGE AND sets lor>0) - continue, else re-queue. is CALL_MODE_DIRECT_CHANGE correct or do I need to pass through CALL_MODE_INIT or create a new special-case call mode + if (!(tmpMode == CALL_MODE_INIT || (tmpMode == CALL_MODE_BUTTON_PRESET && fdo["ps"].is() && strchr(fdo["ps"].as(),'~') != strrchr(fdo["ps"].as(),'~')))) // exception for CALL_MODE_INIT and button preset fdo.remove("ps"); // remove load request for presets to prevent recursive crash (if not called by button and contains preset cycling string "1~5~") deserializeState(fdo, CALL_MODE_NO_NOTIFY, tmpPreset); // may change presetToApply by calling applyPreset() From 0cd709723a10c15d36ba00100c73bfa9bc987e28 Mon Sep 17 00:00:00 2001 From: smitty078 Date: Fri, 8 May 2026 23:02:16 -0400 Subject: [PATCH 04/11] Changes to implementation based on discussion. --- wled00/presets.cpp | 27 +++++++++++++++++++-------- wled00/wled.cpp | 17 ++++++----------- wled00/wled.h | 3 +++ 3 files changed, 28 insertions(+), 19 deletions(-) diff --git a/wled00/presets.cpp b/wled00/presets.cpp index a9498a749b..208b5aa56e 100644 --- a/wled00/presets.cpp +++ b/wled00/presets.cpp @@ -176,13 +176,25 @@ void handlePresets() } else #endif { - presetErrFlag = readObjectFromFileUsingId(getPresetsFileName(tmpPreset < 255), tmpPreset, pDoc) ? ERR_NONE : ERR_FS_PLOAD; + presetErrFlag = readObjectFromFileUsingId(getPresetsFileName(tmpPreset < 255), tmpPreset, pDoc) ? ERR_NONE : ERR_FS_PLOAD; } fdo = pDoc->as(); - // only reset errorflag if previous error was preset-related + // only reset error flag if previous error was preset-related if ((errorFlag == ERR_NONE) || (errorFlag == ERR_FS_PLOAD)) errorFlag = presetErrFlag; + // is this the boot preset and will the preset set lor + const bool isBootPreset = (tmpMode==CALL_MODE_INIT || tmpPreset==bootPreset); + const bool presetWillSetLor = (!fdo["lor"].isNull() && fdo["lor"].as() > REALTIME_OVERRIDE_NONE); + + // During setup, only allow the boot preset itself or safe boot-preset chains. + const bool shouldAllowPresetApply = ( + setupComplete || isBootPreset || + (currentPreset == bootPreset && realtimeOverride > REALTIME_OVERRIDE_NONE) || + (currentPreset == bootPreset && currentPlaylist > 0 && presetWillSetLor) + ); + if (!shouldAllowPresetApply) return; + //HTTP API commands const char* httpwin = fdo["win"]; if (httpwin) { @@ -194,13 +206,12 @@ void handlePresets() changePreset = true; } else { if (!fdo["seg"].isNull() || !fdo["on"].isNull() || !fdo["bri"].isNull() || !fdo["nl"].isNull() || !fdo["ps"].isNull() || !fdo[F("playlist")].isNull()) changePreset = true; - - // TODO: - // Scenario 1: boot preset (CALL_MODE_INIT AND sets lor>0) - do not strip ps, allowing boot preset to chain 1 single preset - // Scenario 2: boot playlist (CALL_MODE_DIRECT_CHANGE AND sets lor>0) - continue, else re-queue. is CALL_MODE_DIRECT_CHANGE correct or do I need to pass through CALL_MODE_INIT or create a new special-case call mode - if (!(tmpMode == CALL_MODE_INIT || (tmpMode == CALL_MODE_BUTTON_PRESET && fdo["ps"].is() && strchr(fdo["ps"].as(),'~') != strrchr(fdo["ps"].as(),'~')))) // exception for CALL_MODE_INIT and button preset - fdo.remove("ps"); // remove load request for presets to prevent recursive crash (if not called by button and contains preset cycling string "1~5~") + // only allow load requests from boot presets that set lor or button calls + const bool isButtonException = (tmpMode == CALL_MODE_BUTTON_PRESET && fdo["ps"].is() && strchr(fdo["ps"].as(),'~') != strrchr(fdo["ps"].as(),'~')) + + const bool shouldAllowLoadRequest = (isBootPreset && presetWillSetLor) || (tmpMode == CALL_MODE_BUTTON_PRESET && fdo["ps"].is() && strchr(fdo["ps"].as(),'~') != strrchr(fdo["ps"].as(),'~')) + if (!shouldAllowLoadRequest) fdo.remove("ps"); // remove load request for presets to prevent recursive crash deserializeState(fdo, CALL_MODE_NO_NOTIFY, tmpPreset); // may change presetToApply by calling applyPreset() } if (!errorFlag && tmpPreset < 255 && changePreset) currentPreset = tmpPreset; diff --git a/wled00/wled.cpp b/wled00/wled.cpp index 6ff10853a8..67cb825ae1 100644 --- a/wled00/wled.cpp +++ b/wled00/wled.cpp @@ -364,6 +364,7 @@ void WLED::disableWatchdog() { void WLED::setup() { + setupComplete = false; // flag to indicate setup is in progress #if defined(ARDUINO_ARCH_ESP32) && defined(WLED_DISABLE_BROWNOUT_DET) WRITE_PERI_REG(RTC_CNTL_BROWN_OUT_REG, 0); //disable brownout detection #endif @@ -504,17 +505,9 @@ void WLED::setup() if (needsCfgSave) serializeConfigToFS(); // usermods required new parameters; need to wait for strip to be initialised #4752 if (bootPreset > 0) { - if (!presetNeedsSaving()) { - handlePlaylist(); // handle boot playlist at setup - yield(); - } - handlePresets(); // handle boot preset (including playlist) at setup - // Allow a boot preset to chain to one numeric preset exactly once (if it sets lor) - // Allow a boot playlist is able to apply the first preset (if it sets lor) - // In both cases, pre-existing protection against recursion is preserved - // See logic inside of handlePresets() - yield(); - handlePresets(); + handlePresets(); // handle boot preset + handlePlaylist(); // handle playlist if preset queued one + handlePresets(); // handle presets again to give a chance for anything queued by the boot preset or playlist } if (strcmp(multiWiFi[0].clientSSID, DEFAULT_CLIENT_SSID) == 0 && !configBackupExists()) @@ -609,6 +602,8 @@ void WLED::setup() WRITE_PERI_REG(RTC_CNTL_BROWN_OUT_REG, 1); //enable brownout detector #endif markOTAvalid(); + + setupComplete = true; // safety check setup function has completed } void WLED::beginStrip() diff --git a/wled00/wled.h b/wled00/wled.h index 1a5f1b143e..6ea137ced0 100644 --- a/wled00/wled.h +++ b/wled00/wled.h @@ -890,6 +890,9 @@ WLED_GLOBAL byte optionType; WLED_GLOBAL bool configNeedsWrite _INIT(false); // flag to initiate saving of config WLED_GLOBAL bool doReboot _INIT(false); // flag to initiate reboot from async handlers +// setup status +WLED_GLOBAL bool setupComplete _INIT(false); // flag for preset loading safety + // status led #if defined(STATUSLED) WLED_GLOBAL unsigned long ledStatusLastMillis _INIT(0); From cfe7bad45d031a4e7356b71288eea8552aa8af4c Mon Sep 17 00:00:00 2001 From: smitty078 Date: Sat, 9 May 2026 00:01:29 -0400 Subject: [PATCH 05/11] call releaseJSONBufferLock() before returning so that the JSON buffer doesn't get accidentally locked during setup --- wled00/presets.cpp | 18 ++++++++++-------- 1 file changed, 10 insertions(+), 8 deletions(-) diff --git a/wled00/presets.cpp b/wled00/presets.cpp index 208b5aa56e..e4c43c3695 100644 --- a/wled00/presets.cpp +++ b/wled00/presets.cpp @@ -160,9 +160,6 @@ void handlePresets() JsonObject fdo; - presetToApply = 0; //clear request for preset - callModeToApply = 0; - DEBUG_PRINTF_P(PSTR("Applying preset: %u\n"), (unsigned)tmpPreset); #if defined(ARDUINO_ARCH_ESP32S2) || defined(ARDUINO_ARCH_ESP32C3) @@ -186,14 +183,20 @@ void handlePresets() // is this the boot preset and will the preset set lor const bool isBootPreset = (tmpMode==CALL_MODE_INIT || tmpPreset==bootPreset); const bool presetWillSetLor = (!fdo["lor"].isNull() && fdo["lor"].as() > REALTIME_OVERRIDE_NONE); - + // During setup, only allow the boot preset itself or safe boot-preset chains. const bool shouldAllowPresetApply = ( setupComplete || isBootPreset || (currentPreset == bootPreset && realtimeOverride > REALTIME_OVERRIDE_NONE) || (currentPreset == bootPreset && currentPlaylist > 0 && presetWillSetLor) ); - if (!shouldAllowPresetApply) return; + if (shouldAllowPresetApply) { + presetToApply = 0; //clear request for preset + callModeToApply = 0; + } else { + releaseJSONBufferLock(); + return; + } //HTTP API commands const char* httpwin = fdo["win"]; @@ -208,9 +211,8 @@ void handlePresets() if (!fdo["seg"].isNull() || !fdo["on"].isNull() || !fdo["bri"].isNull() || !fdo["nl"].isNull() || !fdo["ps"].isNull() || !fdo[F("playlist")].isNull()) changePreset = true; // only allow load requests from boot presets that set lor or button calls - const bool isButtonException = (tmpMode == CALL_MODE_BUTTON_PRESET && fdo["ps"].is() && strchr(fdo["ps"].as(),'~') != strrchr(fdo["ps"].as(),'~')) - - const bool shouldAllowLoadRequest = (isBootPreset && presetWillSetLor) || (tmpMode == CALL_MODE_BUTTON_PRESET && fdo["ps"].is() && strchr(fdo["ps"].as(),'~') != strrchr(fdo["ps"].as(),'~')) + const bool isButtonException = (tmpMode == CALL_MODE_BUTTON_PRESET && fdo["ps"].is() && strchr(fdo["ps"].as(),'~') != strrchr(fdo["ps"].as(),'~')); + const bool shouldAllowLoadRequest = (isBootPreset && presetWillSetLor) || (tmpMode == CALL_MODE_BUTTON_PRESET && fdo["ps"].is() && strchr(fdo["ps"].as(),'~') != strrchr(fdo["ps"].as(),'~')); if (!shouldAllowLoadRequest) fdo.remove("ps"); // remove load request for presets to prevent recursive crash deserializeState(fdo, CALL_MODE_NO_NOTIFY, tmpPreset); // may change presetToApply by calling applyPreset() } From 8793db356ff727abb753ae911563b678126ed622 Mon Sep 17 00:00:00 2001 From: smitty078 Date: Mon, 11 May 2026 12:56:38 -0400 Subject: [PATCH 06/11] revert whitespace correction to avoid conflicts with other PRs --- wled00/presets.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/wled00/presets.cpp b/wled00/presets.cpp index e4c43c3695..123b30abbe 100644 --- a/wled00/presets.cpp +++ b/wled00/presets.cpp @@ -173,7 +173,7 @@ void handlePresets() } else #endif { - presetErrFlag = readObjectFromFileUsingId(getPresetsFileName(tmpPreset < 255), tmpPreset, pDoc) ? ERR_NONE : ERR_FS_PLOAD; + presetErrFlag = readObjectFromFileUsingId(getPresetsFileName(tmpPreset < 255), tmpPreset, pDoc) ? ERR_NONE : ERR_FS_PLOAD; } fdo = pDoc->as(); From 722d6e8cdc1e76181d210faa19df37464f57d226 Mon Sep 17 00:00:00 2001 From: smitty078 Date: Tue, 12 May 2026 22:26:44 -0400 Subject: [PATCH 07/11] Numerous changes based on conversation --- wled00/json.cpp | 1 + wled00/presets.cpp | 25 ++++++------------------- wled00/wled.cpp | 3 --- wled00/wled.h | 3 --- 4 files changed, 7 insertions(+), 25 deletions(-) diff --git a/wled00/json.cpp b/wled00/json.cpp index 74e12b5470..0fe7703bc8 100644 --- a/wled00/json.cpp +++ b/wled00/json.cpp @@ -520,6 +520,7 @@ bool deserializeState(JsonObject root, byte callMode, byte presetId) if (root["win"].isNull() && getVal(root["ps"], presetCycCurr, 1, 250) && presetCycCurr > 0 && presetCycCurr < 251 && presetCycCurr != currentPreset) { DEBUG_PRINTF_P(PSTR("Preset select: %d\n"), presetCycCurr); // b) preset ID only or preset that does not change state (use embedded cycling limits if they exist in getVal()) + if (callMode == CALL_MODE_INIT) callMode = CALL_MODE_DIRECT_CHANGE // avoid propogating CALL_MODE_INIT, which may cause accidental recursion. applyPreset(presetCycCurr, callMode); // async load from file system (only preset ID was specified) return stateResponse; } else presetCycCurr = currentPreset; // restore presetCycCurr diff --git a/wled00/presets.cpp b/wled00/presets.cpp index 123b30abbe..00a67a26d6 100644 --- a/wled00/presets.cpp +++ b/wled00/presets.cpp @@ -180,20 +180,10 @@ void handlePresets() // only reset error flag if previous error was preset-related if ((errorFlag == ERR_NONE) || (errorFlag == ERR_FS_PLOAD)) errorFlag = presetErrFlag; - // is this the boot preset and will the preset set lor - const bool isBootPreset = (tmpMode==CALL_MODE_INIT || tmpPreset==bootPreset); - const bool presetWillSetLor = (!fdo["lor"].isNull() && fdo["lor"].as() > REALTIME_OVERRIDE_NONE); - - // During setup, only allow the boot preset itself or safe boot-preset chains. - const bool shouldAllowPresetApply = ( - setupComplete || isBootPreset || - (currentPreset == bootPreset && realtimeOverride > REALTIME_OVERRIDE_NONE) || - (currentPreset == bootPreset && currentPlaylist > 0 && presetWillSetLor) - ); - if (shouldAllowPresetApply) { - presetToApply = 0; //clear request for preset - callModeToApply = 0; - } else { + // if preset is boot preset and does not explicitly set lor, hold in queue for main loop to process + // this preserves existing behavior - new behavior where boot preset is loaded by main loop + // lor:0 can be used to load boot preset before any realtime data is received, resulting in a fast and consistent power on, but may be overridden by realtime, as soon as realtime starts. lor:1 and lor:2 can be used to prevent realtime data from taking over at boot. + if (tmpMode==CALL_MODE_INIT && fdo["lor"].isNull()) { //} && fdo["lor"].as() == REALTIME_OVERRIDE_NONE) { releaseJSONBufferLock(); return; } @@ -209,11 +199,8 @@ void handlePresets() changePreset = true; } else { if (!fdo["seg"].isNull() || !fdo["on"].isNull() || !fdo["bri"].isNull() || !fdo["nl"].isNull() || !fdo["ps"].isNull() || !fdo[F("playlist")].isNull()) changePreset = true; - - // only allow load requests from boot presets that set lor or button calls - const bool isButtonException = (tmpMode == CALL_MODE_BUTTON_PRESET && fdo["ps"].is() && strchr(fdo["ps"].as(),'~') != strrchr(fdo["ps"].as(),'~')); - const bool shouldAllowLoadRequest = (isBootPreset && presetWillSetLor) || (tmpMode == CALL_MODE_BUTTON_PRESET && fdo["ps"].is() && strchr(fdo["ps"].as(),'~') != strrchr(fdo["ps"].as(),'~')); - if (!shouldAllowLoadRequest) fdo.remove("ps"); // remove load request for presets to prevent recursive crash + if (!(tmpMode == CALL_MODE_INIT || (tmpMode == CALL_MODE_BUTTON_PRESET && fdo["ps"].is() && strchr(fdo["ps"].as(),'~') != strrchr(fdo["ps"].as(),'~')))) + fdo.remove("ps"); // remove load request for presets to prevent recursive crash (if not called by boot preset or button which contains preset cycling string "1~5~") deserializeState(fdo, CALL_MODE_NO_NOTIFY, tmpPreset); // may change presetToApply by calling applyPreset() } if (!errorFlag && tmpPreset < 255 && changePreset) currentPreset = tmpPreset; diff --git a/wled00/wled.cpp b/wled00/wled.cpp index 67cb825ae1..493c687700 100644 --- a/wled00/wled.cpp +++ b/wled00/wled.cpp @@ -364,7 +364,6 @@ void WLED::disableWatchdog() { void WLED::setup() { - setupComplete = false; // flag to indicate setup is in progress #if defined(ARDUINO_ARCH_ESP32) && defined(WLED_DISABLE_BROWNOUT_DET) WRITE_PERI_REG(RTC_CNTL_BROWN_OUT_REG, 0); //disable brownout detection #endif @@ -602,8 +601,6 @@ void WLED::setup() WRITE_PERI_REG(RTC_CNTL_BROWN_OUT_REG, 1); //enable brownout detector #endif markOTAvalid(); - - setupComplete = true; // safety check setup function has completed } void WLED::beginStrip() diff --git a/wled00/wled.h b/wled00/wled.h index 6ea137ced0..1a5f1b143e 100644 --- a/wled00/wled.h +++ b/wled00/wled.h @@ -890,9 +890,6 @@ WLED_GLOBAL byte optionType; WLED_GLOBAL bool configNeedsWrite _INIT(false); // flag to initiate saving of config WLED_GLOBAL bool doReboot _INIT(false); // flag to initiate reboot from async handlers -// setup status -WLED_GLOBAL bool setupComplete _INIT(false); // flag for preset loading safety - // status led #if defined(STATUSLED) WLED_GLOBAL unsigned long ledStatusLastMillis _INIT(0); From 6641724616111b66ae13714ba327a04e19c3c91d Mon Sep 17 00:00:00 2001 From: smitty078 Date: Tue, 12 May 2026 22:33:20 -0400 Subject: [PATCH 08/11] Consistency check to eliminate unneccesary conflicts --- wled00/presets.cpp | 13 ++++--------- 1 file changed, 4 insertions(+), 9 deletions(-) diff --git a/wled00/presets.cpp b/wled00/presets.cpp index 00a67a26d6..ae2d7c7356 100644 --- a/wled00/presets.cpp +++ b/wled00/presets.cpp @@ -160,6 +160,9 @@ void handlePresets() JsonObject fdo; + presetToApply = 0; //clear request for preset + callModeToApply = 0; + DEBUG_PRINTF_P(PSTR("Applying preset: %u\n"), (unsigned)tmpPreset); #if defined(ARDUINO_ARCH_ESP32S2) || defined(ARDUINO_ARCH_ESP32C3) @@ -177,17 +180,9 @@ void handlePresets() } fdo = pDoc->as(); - // only reset error flag if previous error was preset-related + // only reset errorflag if previous error was preset-related if ((errorFlag == ERR_NONE) || (errorFlag == ERR_FS_PLOAD)) errorFlag = presetErrFlag; - // if preset is boot preset and does not explicitly set lor, hold in queue for main loop to process - // this preserves existing behavior - new behavior where boot preset is loaded by main loop - // lor:0 can be used to load boot preset before any realtime data is received, resulting in a fast and consistent power on, but may be overridden by realtime, as soon as realtime starts. lor:1 and lor:2 can be used to prevent realtime data from taking over at boot. - if (tmpMode==CALL_MODE_INIT && fdo["lor"].isNull()) { //} && fdo["lor"].as() == REALTIME_OVERRIDE_NONE) { - releaseJSONBufferLock(); - return; - } - //HTTP API commands const char* httpwin = fdo["win"]; if (httpwin) { From f5ef3f91ce2ed3da705c865560fc5b8a8b789c57 Mon Sep 17 00:00:00 2001 From: smitty078 Date: Tue, 12 May 2026 23:05:52 -0400 Subject: [PATCH 09/11] Final conflict resolution --- wled00/presets.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/wled00/presets.cpp b/wled00/presets.cpp index ae2d7c7356..4931218812 100644 --- a/wled00/presets.cpp +++ b/wled00/presets.cpp @@ -162,7 +162,7 @@ void handlePresets() presetToApply = 0; //clear request for preset callModeToApply = 0; - + DEBUG_PRINTF_P(PSTR("Applying preset: %u\n"), (unsigned)tmpPreset); #if defined(ARDUINO_ARCH_ESP32S2) || defined(ARDUINO_ARCH_ESP32C3) @@ -282,4 +282,4 @@ void deletePreset(byte index) { writeObjectToFileUsingId(getPresetsFileName(), index, &empty); presetsModifiedTime = toki.second(); //unix time updateFSInfo(); -} +}w From 741037a242b1da16fb2df4b3273efe043f34fb5d Mon Sep 17 00:00:00 2001 From: smitty078 Date: Tue, 12 May 2026 23:21:10 -0400 Subject: [PATCH 10/11] Fix missing semi-colon and another error. Thanks coderabbit --- wled00/json.cpp | 2 +- wled00/presets.cpp | 3 ++- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/wled00/json.cpp b/wled00/json.cpp index 0fe7703bc8..ea6035922f 100644 --- a/wled00/json.cpp +++ b/wled00/json.cpp @@ -520,7 +520,7 @@ bool deserializeState(JsonObject root, byte callMode, byte presetId) if (root["win"].isNull() && getVal(root["ps"], presetCycCurr, 1, 250) && presetCycCurr > 0 && presetCycCurr < 251 && presetCycCurr != currentPreset) { DEBUG_PRINTF_P(PSTR("Preset select: %d\n"), presetCycCurr); // b) preset ID only or preset that does not change state (use embedded cycling limits if they exist in getVal()) - if (callMode == CALL_MODE_INIT) callMode = CALL_MODE_DIRECT_CHANGE // avoid propogating CALL_MODE_INIT, which may cause accidental recursion. + if (callMode == CALL_MODE_INIT) callMode = CALL_MODE_DIRECT_CHANGE; // avoid propogating CALL_MODE_INIT, which may cause accidental recursion. applyPreset(presetCycCurr, callMode); // async load from file system (only preset ID was specified) return stateResponse; } else presetCycCurr = currentPreset; // restore presetCycCurr diff --git a/wled00/presets.cpp b/wled00/presets.cpp index 4931218812..ac697eeb0c 100644 --- a/wled00/presets.cpp +++ b/wled00/presets.cpp @@ -282,4 +282,5 @@ void deletePreset(byte index) { writeObjectToFileUsingId(getPresetsFileName(), index, &empty); presetsModifiedTime = toki.second(); //unix time updateFSInfo(); -}w +} + From 8e501d9c91d558aff0109969ed1001e294ab7a26 Mon Sep 17 00:00:00 2001 From: smitty078 Date: Wed, 13 May 2026 16:20:51 -0400 Subject: [PATCH 11/11] Do not reassign callMode, revert whitespace error --- wled00/json.cpp | 5 +++-- wled00/presets.cpp | 3 +-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/wled00/json.cpp b/wled00/json.cpp index ea6035922f..b4388d27ef 100644 --- a/wled00/json.cpp +++ b/wled00/json.cpp @@ -520,8 +520,9 @@ bool deserializeState(JsonObject root, byte callMode, byte presetId) if (root["win"].isNull() && getVal(root["ps"], presetCycCurr, 1, 250) && presetCycCurr > 0 && presetCycCurr < 251 && presetCycCurr != currentPreset) { DEBUG_PRINTF_P(PSTR("Preset select: %d\n"), presetCycCurr); // b) preset ID only or preset that does not change state (use embedded cycling limits if they exist in getVal()) - if (callMode == CALL_MODE_INIT) callMode = CALL_MODE_DIRECT_CHANGE; // avoid propogating CALL_MODE_INIT, which may cause accidental recursion. - applyPreset(presetCycCurr, callMode); // async load from file system (only preset ID was specified) + // async load from file system (only preset ID was specified) + // avoid propogating CALL_MODE_INIT, which may cause accidental recursion + applyPreset(presetCycCurr, callMode == CALL_MODE_INIT ? CALL_MODE_DIRECT_CHANGE : callMode); return stateResponse; } else presetCycCurr = currentPreset; // restore presetCycCurr } diff --git a/wled00/presets.cpp b/wled00/presets.cpp index ac697eeb0c..e3ad2e9f6a 100644 --- a/wled00/presets.cpp +++ b/wled00/presets.cpp @@ -282,5 +282,4 @@ void deletePreset(byte index) { writeObjectToFileUsingId(getPresetsFileName(), index, &empty); presetsModifiedTime = toki.second(); //unix time updateFSInfo(); -} - +} \ No newline at end of file