From 9066a34ca5f72d0517a692626f1dd47475245a36 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Thu, 1 Jan 2026 19:44:19 +0000 Subject: [PATCH 1/4] Initial plan From ff5602840da2453307a525fdb524544814aa0ec9 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Thu, 1 Jan 2026 19:49:17 +0000 Subject: [PATCH 2/4] Fix GPIO0 button pin conflict detection in settings_leds.htm Modified pin conflict detection to check if buttons are enabled before considering their GPIO pins as "in use". Disabled buttons (type = 0) no longer block GPIO reassignment to LED outputs. Co-authored-by: DedeHai <6280424+DedeHai@users.noreply.github.com> --- wled00/data/settings_leds.htm | 34 ++++++++++++++++++++++++++++++++-- 1 file changed, 32 insertions(+), 2 deletions(-) diff --git a/wled00/data/settings_leds.htm b/wled00/data/settings_leds.htm index 2cd5e28393..7bbcbf3f87 100644 --- a/wled00/data/settings_leds.htm +++ b/wled00/data/settings_leds.htm @@ -85,7 +85,22 @@ //check for pin conflicts if (LC.value!="" && LC.value!="-1") { let p = d.rsvd.concat(d.um_p); // used pin array - d.Sf.querySelectorAll("select.pin").forEach((e)=>{if(e.value>-1)p.push(parseInt(e.value));}) // buttons, IR & relay + d.Sf.querySelectorAll("select.pin").forEach((e)=>{ + if(e.value>-1) { + // Check if this is a button pin (name starts with "BT") + if (e.name.startsWith("BT")) { + // Get button type field (BEx where BTx is the pin field) + let btnTypeField = d.Sf["BE" + e.name.substring(2)]; + // Only add to used pins if button is not disabled (type != 0) + if (btnTypeField && btnTypeField.value != "0") { + p.push(parseInt(e.value)); + } + } else { + // For IR and Relay pins, add normally + p.push(parseInt(e.value)); + } + } + }) // buttons, IR & relay if (p.some((e)=>e==parseInt(LC.value))) { alert(`Sorry, pins ${JSON.stringify(p)} can't be used.`); LC.value=""; @@ -387,7 +402,22 @@ if (nm.search(/^L[0-4]/) == 0) // pin fields if (LC.value!="" && LC.value!="-1") { let p = d.rsvd.concat(d.um_p); // used pin array - d.Sf.querySelectorAll("select.pin").forEach((e)=>{if(e.value>-1)p.push(parseInt(e.value));}) // buttons, IR & relay + d.Sf.querySelectorAll("select.pin").forEach((e)=>{ + if(e.value>-1) { + // Check if this is a button pin (name starts with "BT") + if (e.name.startsWith("BT")) { + // Get button type field (BEx where BTx is the pin field) + let btnTypeField = d.Sf["BE" + e.name.substring(2)]; + // Only add to used pins if button is not disabled (type != 0) + if (btnTypeField && btnTypeField.value != "0") { + p.push(parseInt(e.value)); + } + } else { + // For IR and Relay pins, add normally + p.push(parseInt(e.value)); + } + } + }) // buttons, IR & relay for (j=0; j Date: Fri, 2 Jan 2026 10:10:54 +0000 Subject: [PATCH 3/4] Fix button auto-creation when saving empty button list When user removes all buttons and saves, the form handler was processing all WLED_MAX_BUTTONS iterations without checking if parameters exist. Empty request->arg().toInt() returns 0, causing GPIO0 to be auto-assigned. Also fixed cleanup loop to include button index 0. Co-authored-by: DedeHai <6280424+DedeHai@users.noreply.github.com> --- wled00/set.cpp | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/wled00/set.cpp b/wled00/set.cpp index 2a633bf07d..b7f6000e49 100644 --- a/wled00/set.cpp +++ b/wled00/set.cpp @@ -279,6 +279,7 @@ void handleSettingsSet(AsyncWebServerRequest *request, byte subPage) int offset = i < 10 ? '0' : 'A' - 10; char bt[4] = "BT"; bt[2] = offset+i; bt[3] = 0; // button pin (use A,B,C,... if WLED_MAX_BUTTONS>10) char be[4] = "BE"; be[2] = offset+i; be[3] = 0; // button type (use A,B,C,... if WLED_MAX_BUTTONS>10) + if (!request->hasArg(bt)) break; // no more buttons configured int hw_btn_pin = request->arg(bt).toInt(); if (i >= buttons.size()) buttons.emplace_back(hw_btn_pin, request->arg(be).toInt()); // add button to vector else { @@ -327,7 +328,7 @@ void handleSettingsSet(AsyncWebServerRequest *request, byte subPage) } } // we should remove all unused buttons from the vector - for (int i = buttons.size()-1; i > 0; i--) { + for (int i = buttons.size()-1; i >= 0; i--) { if (buttons[i].pin < 0 && buttons[i].type == BTN_TYPE_NONE) { buttons.erase(buttons.begin() + i); // remove button from vector } From b6cea79cc0fdff3915c5a8178e4ad814e9123a22 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Fri, 2 Jan 2026 11:34:35 +0000 Subject: [PATCH 4/4] Use ternary operator for button pin assignment as suggested by @DedeHai Simplified fix by using `request->hasArg(bt) ? request->arg(bt).toInt() : -1` instead of break statement. This ensures non-existent button parameters default to -1 instead of 0. Co-authored-by: DedeHai <6280424+DedeHai@users.noreply.github.com> --- wled00/set.cpp | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/wled00/set.cpp b/wled00/set.cpp index b7f6000e49..02e26adf9f 100644 --- a/wled00/set.cpp +++ b/wled00/set.cpp @@ -279,8 +279,7 @@ void handleSettingsSet(AsyncWebServerRequest *request, byte subPage) int offset = i < 10 ? '0' : 'A' - 10; char bt[4] = "BT"; bt[2] = offset+i; bt[3] = 0; // button pin (use A,B,C,... if WLED_MAX_BUTTONS>10) char be[4] = "BE"; be[2] = offset+i; be[3] = 0; // button type (use A,B,C,... if WLED_MAX_BUTTONS>10) - if (!request->hasArg(bt)) break; // no more buttons configured - int hw_btn_pin = request->arg(bt).toInt(); + int hw_btn_pin = request->hasArg(bt) ? request->arg(bt).toInt() : -1; if (i >= buttons.size()) buttons.emplace_back(hw_btn_pin, request->arg(be).toInt()); // add button to vector else { buttons[i].pin = hw_btn_pin;