Skip to content

Add Pin Info page#5361

Open
DedeHai wants to merge 26 commits intowled:mainfrom
DedeHai:pinInfo
Open

Add Pin Info page#5361
DedeHai wants to merge 26 commits intowled:mainfrom
DedeHai:pinInfo

Conversation

@DedeHai
Copy link
Collaborator

@DedeHai DedeHai commented Feb 8, 2026

replaces #5122

I decided to replace the AI PR for proper attribution in history as only a few lines of the original AI code are left.

Features:

  • shows a table with all available and unavailable pins and their current owner
  • shows special functions and capabilities for each pin
  • for inputs (buttons) and outputs (relay) it shows the current state as a green or gray dot (live)
  • touch inuts and analog inputs show the raw reading value - useful for debugging to check "what WLED sees" (live)
  • usermod assigned pins currently only show "Usermod", the task to easily fetch names from usermod is ongoing

Screenshot for an ESP32:
image

Summary by CodeRabbit

  • New Features
    • Added a "Pin Info" settings page showing GPIO capabilities (Touch, Input Only, Analog, Flash Boot, Bootstrap), owner/usage, per‑pin notes, raw readings where available, compact layout, Back navigation, auto‑refresh, retry and error handling.
  • Developer / Integration
    • New "pins" JSON endpoint to inspect per‑pin info and live state for diagnostics and UI use.

Copilot AI and others added 21 commits February 8, 2026 02:57
Co-authored-by: DedeHai <6280424+DedeHai@users.noreply.github.com>
Co-authored-by: DedeHai <6280424+DedeHai@users.noreply.github.com>
Co-authored-by: DedeHai <6280424+DedeHai@users.noreply.github.com>
…/LOW text, rename Caps to Functions

Co-authored-by: DedeHai <6280424+DedeHai@users.noreply.github.com>
…ti Relay support

Co-authored-by: DedeHai <6280424+DedeHai@users.noreply.github.com>
…ns and platforms

Co-authored-by: DedeHai <6280424+DedeHai@users.noreply.github.com>
…t in btnPin array

Co-authored-by: DedeHai <6280424+DedeHai@users.noreply.github.com>
Co-authored-by: DedeHai <6280424+DedeHai@users.noreply.github.com>
…nfo tab

Co-authored-by: DedeHai <6280424+DedeHai@users.noreply.github.com>
…isplay

Co-authored-by: DedeHai <6280424+DedeHai@users.noreply.github.com>
Co-authored-by: DedeHai <6280424+DedeHai@users.noreply.github.com>
Co-authored-by: DedeHai <6280424+DedeHai@users.noreply.github.com>
Co-authored-by: DedeHai <6280424+DedeHai@users.noreply.github.com>
Co-authored-by: DedeHai <6280424+DedeHai@users.noreply.github.com>
Co-authored-by: DedeHai <6280424+DedeHai@users.noreply.github.com>
@coderabbitai
Copy link
Contributor

coderabbitai bot commented Feb 8, 2026

Note

Reviews paused

It looks like this branch is under active development. To avoid overwhelming you with review comments due to an influx of new commits, CodeRabbit has automatically paused this review. You can configure this behavior by changing the reviews.auto_review.auto_pause_after_reviewed_commits setting.

Use the following commands to manage reviews:

  • @coderabbitai resume to resume automatic reviews.
  • @coderabbitai review to trigger a single review.

Use the checkboxes below for quick actions:

  • ▶️ Resume reviews
  • 🔍 Trigger review

Walkthrough

Adds a new "Pin Info" settings subpage and HTML asset, exposes per-GPIO data via a new JSON "pins" target and serializePins(), defines SUBPAGE_PINS and updates subpage bounds, and wires the new page into server routing and GPIO info output.

Changes

Cohort / File(s) Summary
Build registration
tools/cdata.js, package.json
Registers settings_pininfo.htm for inclusion (gzip + html-minify) so PAGE_settings_pininfo is generated into build artifact html_settings.h.
Constants & routing
wled00/const.h, wled00/wled_server.cpp, wled00/xml.cpp
Adds SUBPAGE_PINS, sets SUBPAGE_LAST to it, replaces hard-coded subpage bound with SUBPAGE_LAST, maps "pins" URL to SUBPAGE_PINS, and serves the new page.
UI / static pages
wled00/data/settings.htm, wled00/data/settings_pininfo.htm
Adds "Pin Info" button to settings and adds settings_pininfo.htm, which loads resources, polls /json/pins, and renders a per-pin table (capabilities, owner, state/notes) with navigation and error handling.
JSON serialization & server targets
wled00/fcn_declare.h, wled00/json.cpp
Declares serializePins(JsonObject) and implements per-pin serialization; adds pins to json_target and routes /json/pins to emit per-pin JSON including capability flags, allocation, owner id/name, and conditional runtime readings.
Pin manager additions
wled00/pin_manager.h, wled00/pin_manager.cpp
Introduces PIN_CAP_* flags and public APIs: getButtonIndex(byte), isAnalogPin(byte), getPinOwnerName(uint8_t).
GPIO info output
wled00/xml.cpp (appendGPIOinfo)
Emits ESP32 touch-capable pins as d.touch and integrates pins info into settings JS when requested.

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~25 minutes

Possibly related PRs

Suggested reviewers

  • softhack007
  • netmindz
  • willmmiles
🚥 Pre-merge checks | ✅ 2 | ❌ 2

❌ Failed checks (2 warnings)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 30.77% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
Merge Conflict Detection ⚠️ Warning ❌ Merge conflicts detected (50 files):

⚔️ .github/ISSUE_TEMPLATE/bug.yml (content)
⚔️ .gitignore (content)
⚔️ package-lock.json (content)
⚔️ package.json (content)
⚔️ tools/cdata.js (content)
⚔️ usermods/Analog_Clock/Analog_Clock.cpp (content)
⚔️ usermods/Temperature/Temperature.cpp (content)
⚔️ usermods/TetrisAI_v2/TetrisAI_v2.cpp (content)
⚔️ usermods/pixels_dice_tray/led_effects.h (content)
⚔️ usermods/pov_display/pov_display.cpp (content)
⚔️ usermods/rgb-rotary-encoder/rgb-rotary-encoder.cpp (content)
⚔️ usermods/user_fx/README.md (content)
⚔️ usermods/user_fx/user_fx.cpp (content)
⚔️ usermods/usermod_v2_animartrix/usermod_v2_animartrix.cpp (content)
⚔️ wled00/FX.cpp (content)
⚔️ wled00/FX.h (content)
⚔️ wled00/FX_2Dfcn.cpp (content)
⚔️ wled00/FX_fcn.cpp (content)
⚔️ wled00/FXparticleSystem.cpp (content)
⚔️ wled00/FXparticleSystem.h (content)
⚔️ wled00/bus_manager.cpp (content)
⚔️ wled00/bus_manager.h (content)
⚔️ wled00/bus_wrapper.h (content)
⚔️ wled00/cfg.cpp (content)
⚔️ wled00/const.h (content)
⚔️ wled00/data/index.js (content)
⚔️ wled00/data/settings.htm (content)
⚔️ wled00/data/settings_leds.htm (content)
⚔️ wled00/data/settings_wifi.htm (content)
⚔️ wled00/e131.cpp (content)
⚔️ wled00/fcn_declare.h (content)
⚔️ wled00/file.cpp (content)
⚔️ wled00/improv.cpp (content)
⚔️ wled00/ir.cpp (content)
⚔️ wled00/json.cpp (content)
⚔️ wled00/network.cpp (content)
⚔️ wled00/ntp.cpp (content)
⚔️ wled00/overlay.cpp (content)
⚔️ wled00/pin_manager.cpp (content)
⚔️ wled00/pin_manager.h (content)
⚔️ wled00/remote.cpp (content)
⚔️ wled00/set.cpp (content)
⚔️ wled00/udp.cpp (content)
⚔️ wled00/util.cpp (content)
⚔️ wled00/wled.cpp (content)
⚔️ wled00/wled.h (content)
⚔️ wled00/wled_serial.cpp (content)
⚔️ wled00/wled_server.cpp (content)
⚔️ wled00/ws.cpp (content)
⚔️ wled00/xml.cpp (content)

These conflicts must be resolved before merging into main.
Resolve conflicts locally and push changes to this branch.
✅ Passed checks (2 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title 'Add Pin Info page' is clear, concise, and directly matches the main objective of the PR—adding a new Pin Info feature page to the UI.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing touches
  • 📝 Generate docstrings
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Post copyable unit tests in a comment
⚔️ Resolve merge conflicts (beta)
  • Auto-commit resolved conflicts to branch pinInfo
  • Post resolved changes as copyable diffs in a comment

Tip

Issue Planner is now in beta. Read the docs and try it out! Share your feedback on Discord.


Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

@DedeHai DedeHai added enhancement hardware (Likely) Setup-specific issue, e.g. flickering LEDs configuration Incorrect configuration or configuration related issue. labels Feb 8, 2026
Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 3

🤖 Fix all issues with AI agents
In `@wled00/data/settings_pininfo.htm`:
- Around line 28-31: The page references d.Sf.action which will throw because
there is no form named "Sf"; remove or guard that line (check that d && d.Sf &&
d.Sf.action exist before assigning) and keep behavior consistent with this being
a read-only info page; also reduce the polling frequency by changing the
setInterval call that assigns pinsTimer (currently setInterval(loadPins, 250))
to a much less aggressive interval (e.g., setInterval(loadPins, 2000)) to lower
embedded HTTP server load; locate these changes around the pinsTimer/setInterval
and the d.Sf.action reference in this block and update accordingly.

In `@wled00/json.cpp`:
- Around line 1092-1097: The loop that enumerates pins on ESP8266 skips A0
(GPIO17) because ENUM_PINS is 17 and the for-loop uses gpio < ENUM_PINS; change
the ESP8266 constant so the loop includes gpio==17 (e.g., set constexpr int
ENUM_PINS = 18) so the for (int gpio = 0; gpio < ENUM_PINS; gpio++) iteration
will reach GPIO17 and make the existing special-case code checking if (gpio ==
17) effective; update any related comment to reflect the new upper bound.
- Around line 1080-1085: The comment in getPinOwnerName is wrong: change the
comment that currently reads "low bit not set" to "high bit not set" (or "bit 7
not set") to reflect the check !(static_cast<uint8_t>(owner) & 0x80), and since
getPinOwnerName is only used from serializePins within this translation unit,
give getPinOwnerName internal linkage by marking it static; update the function
declaration/definition accordingly (refer to getPinOwnerName and serializePins).
🧹 Nitpick comments (7)
wled00/xml.cpp (1)

193-193: subPage < 0 is always false since byte is unsigned.

subPage is declared as byte (i.e., uint8_t), so the < 0 check is dead code. Not a functional issue, but worth noting for clarity.

Proposed fix
-  if (subPage <0 || subPage >SUBPAGE_LAST) return;
+  if (subPage > SUBPAGE_LAST) return;
wled00/data/settings_pininfo.htm (4)

16-16: gpioInfo is declared but never used.

The global variable gpioInfo is initialized as an empty object but never referenced anywhere in the file.

Proposed cleanup
-	var pinsTimer=null, gpioInfo={};
+	var pinsTimer=null;

58-83: Missing cleanup of the polling timer.

When navigating away from this page (e.g., via the Back button), the setInterval timer is never cleared. While navigation typically unloads the page, explicitly clearing the timer in B() would be cleaner and prevent any edge-case where requests continue after the user navigates away.

Proposed fix
-	function B(){window.open(getURL('/settings'),'_self');} // back button
+	function B(){if(pinsTimer)clearInterval(pinsTimer);window.open(getURL('/settings'),'_self');} // back button

62-82: Consider reducing DOM churn from full innerHTML replacement every poll cycle.

Every 250ms (or whatever the interval), the entire table HTML is rebuilt and assigned via innerHTML. On embedded devices with limited resources, this creates unnecessary GC pressure and visual flicker. A lighter approach would be to only update the dynamic parts (state dots, touch values) after the initial table is built, or at minimum check if the pin list structure has changed before rebuilding.


85-94: Styles duplicate style.css base theme — consider relying on the loaded stylesheet.

The page already loads style.css (line 12), but then re-declares body background, colors, etc. in the inline <style> block. The table-specific styles (.bs, .tv) are fine, but the body/general styles may conflict with or duplicate the shared theme. Consider keeping only the page-specific additions inline. As per coding guidelines, use tabs for indentation in web files. The inline styles appear to use tabs correctly.

wled00/json.cpp (2)

1111-1129: Inconsistent indentation inside #elif blocks.

Lines 1118–1128 use 8-space indentation while the rest of the function and the coding guideline require 2-space indentation. The #if CONFIG_IDF_TARGET_ESP32 block at lines 1114–1116 uses 4-space indentation which is also inconsistent.

As per coding guidelines: "Use 2-space indentation for C++ source files (.cpp)".

Proposed fix (showing ESP32-S2 block as example; apply same to S3 and C3)
     `#elif` CONFIG_IDF_TARGET_ESP32S2
-        // ESP32-S2: ADC1 channels 0-9 (GPIO 1-10)
-        int adc_channel = digitalPinToAnalogChannel(gpio);
-        if (adc_channel >= 0 && adc_channel <= 9) caps |= PIN_CAP_ADC;
+    // ESP32-S2: ADC1 channels 0-9 (GPIO 1-10)
+    int adc_channel = digitalPinToAnalogChannel(gpio);
+    if (adc_channel >= 0 && adc_channel <= 9) caps |= PIN_CAP_ADC;

1184-1188: Use gpio instead of rlyPin for consistency and correctness.

rlyPin is a global for the primary relay, but the loop iterates all GPIOs. If WLED ever supports multiple relay-owner pins, this would read the wrong pin's state. Since gpio is already known to be the relay pin at this point, use it directly.

Proposed fix
       if (owner == PinOwner::Relay) {
         pinObj["m"] = 1;  // mode: output
-        pinObj["s"] = digitalRead(rlyPin); // read state from hardware (digitalRead returns output state for output pins)
+        pinObj["s"] = digitalRead(gpio); // read state from hardware
       }

Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 2

🤖 Fix all issues with AI agents
In `@wled00/json.cpp`:
- Around line 1111-1129: Fix the indentation and add a fallback ADC branch:
reformat the `#elif` blocks that call digitalPinToAnalogChannel(gpio) so they use
2-space indentation to match .cpp coding guidelines, and add a final `#else`
branch after the CONFIG_IDF_TARGET checks that calls
digitalPinToAnalogChannel(gpio) and sets caps |= PIN_CAP_ADC when adc_channel >=
0 (so newer ESP32 variants get ADC capability detected); ensure you reference
the same symbols (digitalPinToAnalogChannel, gpio, adc_channel, caps,
PIN_CAP_ADC) and keep the per-variant explicit checks for
ESP32/ESP32S2/ESP32S3/ESP32C3 intact.
- Around line 1137-1150: Add an explicit CONFIG_IDF_TARGET_ESP32C6 branch so
ESP32-C6 doesn't fall through to the legacy "classic" defaults: under an `#elif
defined(CONFIG_IDF_TARGET_ESP32C6)` check, mark the boot pin with `if (gpio ==
9) caps |= PIN_CAP_BOOT;` and set the bootstrap pins with `if (gpio == 2 || gpio
== 8) caps |= PIN_CAP_BOOTSTRAP;` (same pattern as the other target-specific
branches using the gpio variable and PIN_CAP_BOOT / PIN_CAP_BOOTSTRAP symbols).
🧹 Nitpick comments (2)
wled00/json.cpp (2)

1052-1057: PIN_CAP_PWM is defined but never used.

The macro is defined at line 1054 but the only usage site is commented out (line 1132). Remove it to avoid dead code, or add a comment that it's reserved for future use.


1184-1188: Consider using gpio instead of rlyPin for the relay digitalRead.

Line 1187 reads digitalRead(rlyPin) using the global variable, but at this point gpio is the pin being serialized and its owner is confirmed to be PinOwner::Relay. Using digitalRead(gpio) would be more self-consistent and wouldn't break if the relay pin ownership model ever changes.

Proposed fix
       if (owner == PinOwner::Relay) {
         pinObj["m"] = 1;  // mode: output
-        pinObj["s"] = digitalRead(rlyPin); // read state from hardware (digitalRead returns output state for output pins)
+        pinObj["s"] = digitalRead(gpio); // read state from hardware
       }

@DedeHai
Copy link
Collaborator Author

DedeHai commented Feb 8, 2026

@coderabbitai ESP8266 has the analog input pin A0, it is not selectable as an analog button in WLED dropdowns. Was this ever available as an analo pin or where can it be used through the UI?

@coderabbitai
Copy link
Contributor

coderabbitai bot commented Feb 8, 2026

Tip

For best results, initiate chat on the files or code changes.

🧩 Analysis chain

🏁 Script executed:

#!/bin/bash
# Search for A0 pin references in the codebase
rg -n "A0" --type cpp --type h -C 3

# Search for analog pin and analog button related code
rg -n "analog.*button" -i --type cpp --type h -C 2

# Search for ESP8266 pin definitions and GPIO info
rg -n "ESP8266.*analog|analog.*ESP8266" -i --type cpp --type h -C 3

# Look for pin capability definitions and ADC-related code
rg -n "PIN_CAP.*ADC|ADC.*CAP" --type cpp --type h -C 2

Length of output: 52203


🏁 Script executed:

#!/bin/bash
# Search for analog button configuration and pin selection in settings/UI
rg -n "BTN_TYPE_ANALOG" --type cpp --type h -C 3

# Search for pin dropdown/selection UI code in settings pages
rg -n "analog.*pin|pin.*analog" -i wled00/data/ -C 2

# Look for ESP8266 specific pin handling in settings
rg -n "ESP8266.*pin.*select|pin.*dropdown" -i --type cpp --type h -C 2

# Check how pins are enumerated for UI dropdowns
rg -n "WLED_NUM_PINS|appendGPIOinfo" --type cpp --type h -C 3

Length of output: 17063


@DedeHai, great question! Based on my analysis of the codebase, here's the situation with A0 on ESP8266:

A0 was never selectable in WLED UI dropdowns for ESP8266. This is by design.

On ESP8266, the hardware only has one analog input pin, and the code handles this specially:

  1. For analog buttons on ESP8266: The code always reads from the hardcoded A0 pin regardless of what pin you configure in the UI. The pin parameter is essentially ignored.

  2. Pin manager exclusion: GPIO17 (which is A0) is marked as "analog input only and not available through pinmanager".

  3. Special handling: ESP8266 allows analog button types even when the pin is set to -1, because it knows it will always use A0 anyway.

How to use analog buttons on ESP8266:

  • Set the button type to "Analog" or "Analog (Inverted)"
  • The pin value doesn't matter (can be -1 or any value) - the code will always read from A0
  • The A0 pin is automatically used

About the commit message "remove A0 for ESP8266": This refers to not displaying A0/GPIO17 in the new Pin Info page you added in this PR, since it's marked as input-only with a TODO to "display as A0 pin" - meaning there's still work to improve how it's shown in the UI.

So A0 is available for analog buttons through the button type setting, but it's not a selectable pin in dropdowns because it's automatically used when needed.


🧠 Learnings used
Learnt from: DedeHai
Repo: wled/WLED PR: 4456
File: usermods/deep_sleep/deep_sleep.cpp:224-230
Timestamp: 2025-11-30T15:29:00.726Z
Learning: In WLED, `touchThreshold` is a global variable defined in wled00/wled.h and is accessible to all usermods. It stores the touch sensitivity threshold for touch-capable GPIO pins on ESP32 variants and should not be flagged as undefined when used in usermods.

@softhack007
Copy link
Member

softhack007 commented Feb 8, 2026

Good idea, reminds me of something similar that I did for wled-mm some time ago - but never found time to go from "summary on serial" to "page in the UI".

WLED-MM has extended pinmanager to ask for pin capabilities, maybe this would be a good for your PR, too.

https://github.com/MoonModules/WLED-MM/blob/7e9f3c428e500e15ba240acfc27f778bd104621f/wled00/pin_manager.h#L138-L150

https://github.com/MoonModules/WLED-MM/blob/7e9f3c428e500e15ba240acfc27f778bd104621f/wled00/pin_manager.cpp#L636-L680

https://github.com/MoonModules/WLED-MM/blob/7e9f3c428e500e15ba240acfc27f778bd104621f/wled00/wled.cpp#L885-L914

At that time my pin-info code was unwanted in upstream, due to "abuse of pinmanager" 😝. But times have changed :-)


just for comparison: even on serial, the info below seems to help many users. So i think your PR is "on the right track" 👍

image

@softhack007
Copy link
Member

Small improvement: instead of "System" you could display pins as "reserved", I think this is the usual wording in espressif docs.

@netmindz
Copy link
Member

netmindz commented Feb 8, 2026

How easily can we extend this to create a reusable component to replace anywhere were we just have a text box for the user entering a pin to a drop-down incorporating this pin info?

@softhack007
Copy link
Member

softhack007 commented Feb 8, 2026

How easily can we extend this to create a reusable component to replace anywhere were we just have a text box for the user entering a pin to a drop-down incorporating this pin info?

We (upstream WLED) have an annotated drop-down for LEDs settings already. You're right it should be possible to make a generic PIN drop-down and put it into common.js. The new json endpoint for pin info is very good. I would suggest to add something like getPinCapabilities(pinNr) to pinmanager, so that hardware-specific code stays together in one place.

@DedeHai
Copy link
Collaborator Author

DedeHai commented Feb 8, 2026

How easily can we extend this to create a reusable component to replace anywhere were we just have a text box for the user entering a pin to a drop-down incorporating this pin info?

the addition of "touch" to void appendGPIOinfo() was made with exactly this follow-up goal in mind.

@DedeHai
Copy link
Collaborator Author

DedeHai commented Feb 8, 2026

We (upstream WLED) have an annotated drop-down for LEDs settings already. You're right it should be possible to make a generic PIN drop-down and put it into common.js. The new json endpoint for pin info is very good. I would suggest to add something like getPinCapabilities(pinNr) to pinmanager, so that hardware-specific code stays together in one place.

yes, from what I recall most of the code is already there, after all many pins already use dropdowns. good idea to move some of the json.cpp code into pinmanager.

@DedeHai
Copy link
Collaborator Author

DedeHai commented Feb 8, 2026

Small improvement: instead of "System" you could display pins as "reserved", I think this is the usual wording in espressif docs.

I had that initially but it felt a bit too "generic" as in "why is that pin reserved? and how to unreserve it?" stating it is used by the system and not available "no matter what" felt more appropriate and informative.

@DedeHai
Copy link
Collaborator Author

DedeHai commented Feb 8, 2026

Good idea, reminds me of something similar that I did for wled-mm some time ago - but never found time to go from "summary on serial" to "page in the UI".

WLED-MM has extended pinmanager to ask for pin capabilities, maybe this would be a good for your PR, too.

https://github.com/MoonModules/WLED-MM/blob/7e9f3c428e500e15ba240acfc27f778bd104621f/wled00/pin_manager.h#L138-L150

https://github.com/MoonModules/WLED-MM/blob/7e9f3c428e500e15ba240acfc27f778bd104621f/wled00/pin_manager.cpp#L636-L680

https://github.com/MoonModules/WLED-MM/blob/7e9f3c428e500e15ba240acfc27f778bd104621f/wled00/wled.cpp#L885-L914

At that time my pin-info code was unwanted in upstream, due to "abuse of pinmanager" 😝. But times have changed :-)

just for comparison: even on serial, the info below seems to help many users. So i think your PR is "on the right track" 👍

yes, the serial output in MM is very helpful but inaccessible to most AC users - I do have that code for "extended error log" ready in a branch that adds a console of sorts to the info panel, maybe that can be extended as well as a general log (see #4959).
I remember seeing something similar to this a while back but can't recall where exactly, maybe in a demo video of moonligh? I remember @ewoudwijma recognizing it immediately so good chance I saw it there :)

@ewoudwijma
Copy link
Contributor

@DedeHai , indeed, it was here : https://discord.com/channels/473448917040758787/795233398314237972/1444802942149591090

@ewoudwijma
Copy link
Contributor

... this was pin manager related, or you refer to logging?

WLED-MM has netdebug, sending serial logging over the network.
I also worked on sending logging over websocket to UI, that's the best solution if you talk about logging I think 🙂

@DedeHai
Copy link
Collaborator Author

DedeHai commented Feb 8, 2026

only pin manager / pin info related - the logging I referred to is currently not in PR, I wanted to give that a checkup before I do but once it is up you are welcome to comment or share your inputs

@softhack007
Copy link
Member

softhack007 commented Feb 9, 2026

@DedeHai

btw, in case that "pin conflicts" are still interesting. To get the conflicts,

  • the main idea is to have a second list of failed_pin_owner[] next to pin owner[].
  • Every time a pin allocation attempt fails due to "already allocated to another owner", update failed_pin_owner[].
  • Clear the failed_pin_owner entry only when an allocation succeeds (kind of garbage collection).
  • add pinManager.getFailedPinOwner(int pin) function

This gives you the last conflict on each pin. Very helpful in case of "wtf I'm lost in pin probelms" ;-)

@DedeHai
Copy link
Collaborator Author

DedeHai commented Feb 10, 2026

double allocations can only happen if you force pins at compile time, the UI knows available pins and won't allow double allocations (if it does, that needs fixing).
debugging things in the UI that were f'd up at compile time is not something we want to take on, there is the debug build for that.

@netmindz
Copy link
Member

double allocations can only happen if you force pins at compile time, the UI knows available pins and won't allow double allocations (if it does, that needs fixing). debugging things in the UI that were f'd up at compile time is not something we want to take on, there is the debug build for that.

The UI does allow duplicates, dmx input is one place, but don't think the only place that doesn't use a drop-down for the pin selection

@DedeHai
Copy link
Collaborator Author

DedeHai commented Feb 10, 2026

LED pins also do not use dropdowns, they still do not allow conflicting pins. Anyway, moving towards dropdowns for all pins is definitely something we need and it should be pretty straight forward to implement.

@DedeHai
Copy link
Collaborator Author

DedeHai commented Feb 16, 2026

@coderabbitai please review latest changes and check if there are any newly introduced issues.

Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

🤖 Fix all issues with AI agents
In `@wled00/pin_manager.cpp`:
- Around line 351-372: PinManager::isAnalogPin currently handles only specific
ESP32 targets and will return false for newer variants (C6, H2, etc.); add an
`#else` fallback under the ARDUINO_ARCH_ESP32 block that calls
digitalPinToAnalogChannel(gpio) and returns true if the result is >= 0 so
ADC-capable pins on unlisted ESP32 variants are detected; update only the
conditional branches in isAnalogPin to include this generic check referencing
digitalPinToAnalogChannel and keep existing per-target checks intact.
🧹 Nitpick comments (2)
wled00/json.cpp (2)

1120-1161: Consider the latency impact of touchRead() during JSON serialization.

touchRead() can take several milliseconds per call on ESP32 (especially Touch V2 on S2/S3). Since serializePins() runs while holding the JSON buffer lock, multiple touch-enabled buttons could add noticeable latency to the /json/pins response. This is acceptable for a debug/info page but worth documenting if there's concern about the lock hold time.


1221-1238: URL matching for "pins" could collide with future endpoints.

The indexOf(F("pins")) check would match any URL containing "pins" (e.g., a hypothetical /json/mappins). Currently there's no conflict, but this is fragile compared to exact segment matching. The same pattern exists for other endpoints here, so this is consistent with the codebase style.

@coderabbitai
Copy link
Contributor

coderabbitai bot commented Feb 16, 2026

Tip

For best results, initiate chat on the files or code changes.

🧩 Analysis chain

🏁 Script executed:

#!/bin/bash
# Fetch the PR branch and examine the latest changes
cd /tmp
git clone --depth 1 --branch pinInfo https://github.com/DedeHai/WLED.git wled-pr-5361 2>&1 || echo "Clone failed, trying to use existing repo"

cd wled-pr-5361 || exit 1

# Get the latest commit info
echo "=== Latest commit ==="
git log -1 --oneline

# Show the files changed in recent commits
echo -e "\n=== Files changed in latest commits ==="
git diff --name-only HEAD~3..HEAD 2>/dev/null || git diff --name-only HEAD~1..HEAD 2>/dev/null || echo "Could not get diff"

# Check the key files for the latest changes
echo -e "\n=== Checking json.cpp ==="
cat wled00/json.cpp | head -50

Length of output: 1642


🏁 Script executed:

#!/bin/bash
cd /tmp/wled-pr-5361

# Review the serializePins function for potential issues
echo "=== serializePins function ==="
ast-grep --pattern $'void serializePins($$$) {
  $$$
}'

# Check for the getPinOwnerName function
echo -e "\n=== getPinOwnerName function ==="
ast-grep --pattern $'const char* getPinOwnerName($$$) {
  $$$
}'

Length of output: 64


🏁 Script executed:

#!/bin/bash
cd /tmp/wled-pr-5361

# Check the new HTML page
echo "=== settings_pininfo.htm ==="
cat wled00/data/settings_pininfo.htm

Length of output: 3729


🏁 Script executed:

#!/bin/bash
cd /tmp/wled-pr-5361

# Check const.h for the new constants
echo "=== New constants in const.h ==="
rg -n "SUBPAGE_PINS|SUBPAGE_LAST" wled00/const.h -A 1 -B 1

# Check xml.cpp changes for touch info
echo -e "\n=== xml.cpp changes for touch ==="
rg -n "touch" wled00/xml.cpp -C 3

# Check wled_server.cpp routing changes
echo -e "\n=== wled_server.cpp routing ==="
rg -n "SUBPAGE_PINS|pins" wled00/wled_server.cpp -C 3

Length of output: 2111


🏁 Script executed:

#!/bin/bash
cd /tmp/wled-pr-5361

# Look for potential issues in json.cpp - array bounds, magic numbers, etc.
echo "=== Checking for magic numbers in serializePins ==="
rg -n "PIN_CAP_|getPinOwnerName|serializePins" wled00/json.cpp -C 5

# Check for any hardcoded array sizes or bounds
echo -e "\n=== Checking for array bounds issues ==="
rg -n "\[.*\]|sizeof" wled00/json.cpp | grep -A 2 -B 2 "serializePins\|getPinOwnerName"

Length of output: 4252


🏁 Script executed:

#!/bin/bash
cd /tmp/wled-pr-5361

# Check the full serializePins implementation
echo "=== Full serializePins and getPinOwnerName implementation ==="
sed -n '/void serializePins/,/^}/p' wled00/json.cpp | head -200

echo -e "\n=== getPinOwnerName implementation ==="
sed -n '/const char\* getPinOwnerName/,/^}/p' wled00/json.cpp

Length of output: 5877


🏁 Script executed:

#!/bin/bash
cd /tmp/wled-pr-5361

# Check pin_manager files to see the new functions added per latest commit
echo "=== pin_manager.h - looking for new functions ==="
rg -n "isAnalogPin|getPinOwnerName|getButtonIndex|PIN_CAP_" wled00/pin_manager.h -C 3

echo -e "\n=== pin_manager.cpp - looking for implementations ==="
rg -n "isAnalogPin|getPinOwnerName|getButtonIndex" wled00/pin_manager.cpp -C 5

Length of output: 2382


🏁 Script executed:

#!/bin/bash
cd /tmp/wled-pr-5361

# Get the full pin_manager.h to see the new pin capability constants
echo "=== Full pin_manager.h enum and constants section ==="
head -150 wled00/pin_manager.h | tail -100

Length of output: 6792


🏁 Script executed:

#!/bin/bash
cd /tmp/wled-pr-5361

# Check for PIN_CAP definitions - they should be in pin_manager.h now per latest commit
echo "=== Searching for PIN_CAP constants ==="
rg -n "PIN_CAP" wled00/ -C 2

# Look for any magic numbers in the serializePins function
echo -e "\n=== Magic numbers check in json.cpp serializePins ==="
rg -n "0x|255|>>|<<" wled00/json.cpp | grep -A 3 -B 3 "serializePins\|buttonIndex\|analogRead"

Length of output: 4153


🏁 Script executed:

#!/bin/bash
cd /tmp/wled-pr-5361

# Check if there are bounds checks for button array access
echo "=== Button array access safety check ==="
sed -n '1115,1160p' wled00/json.cpp

# Check the button-related pin index logic
echo -e "\n=== Looking for buttons array usage ==="
rg -n "buttons\[" wled00/json.cpp -C 2

Length of output: 3793


🏁 Script executed:

#!/bin/bash
cd /tmp/wled-pr-5361

# Check tools/cdata.js to see if PIN_CAP constants are defined properly
echo "=== Check for pininfo page registration ==="
cat tools/cdata.js | grep -A 5 -B 5 "pininfo"

# Verify fcn_declare.h for serializePins declaration
echo -e "\n=== fcn_declare.h serializePins declaration ==="
rg -n "serializePins" wled00/fcn_declare.h -C 2

Length of output: 564


🏁 Script executed:

#!/bin/bash
cd /tmp/wled-pr-5361

# Look more closely at the isAnalogPin implementation to verify ADC1/ADC2 handling
echo "=== Full isAnalogPin implementation ==="
sed -n '/bool PinManager::isAnalogPin/,/^}/p' wled00/pin_manager.cpp

Length of output: 1195


🏁 Script executed:

#!/bin/bash
cd /tmp/wled-pr-5361

# Check if there are any other potential issues - look for TODO, FIXME, etc.
echo "=== Looking for TODO/FIXME in changed files ==="
rg -n "TODO|FIXME|XXX|HACK" wled00/json.cpp wled00/pin_manager.cpp wled00/pin_manager.h wled00/xml.cpp wled00/wled_server.cpp wled00/data/settings_pininfo.htm -C 2

# Check for potential memory leaks or resource issues
echo -e "\n=== Checking for potential resource issues ==="
rg -n "new |malloc|calloc|free|delete" wled00/json.cpp wled00/pin_manager.cpp -C 2

Length of output: 9020


🏁 Script executed:

#!/bin/bash
cd /tmp/wled-pr-5361

# Verify the HTML page doesn't have XSS vulnerabilities or unsafe practices
echo "=== Security check - innerHTML usage ==="
rg -n "innerHTML" wled00/data/settings_pininfo.htm -C 3

# Check for proper escaping and sanitization
echo -e "\n=== Check JSON parsing safety ==="
rg -n "\.json\(\)|JSON\.parse" wled00/data/settings_pininfo.htm -C 2

Length of output: 413


@DedeHai I've reviewed the latest changes. The code looks solid overall! Here are my findings:

Good Improvements

The latest commit "moved pin capabilities to pinmanager" is an excellent architectural improvement. The PIN_CAP constants are now properly defined in pin_manager.h, which centralizes pin capability handling where it belongs.

🔍 Code Quality Observations

Memory Safety: All good here. Button array access is properly protected with buttonIndex >= 0 bounds check before accessing buttons[buttonIndex].

Platform-Specific Code: The isAnalogPin() function correctly filters for ADC1 channels only, which is important since ADC2 channels can't be used when WiFi is active on ESP32.

Magic Numbers: There are bit shift operations (>> 4, >> 2) and the value 255 for analog inversion. These are acceptable because:

  • They're well-commented (e.g., "right shift by 4 to match threshold range")
  • They represent bit depth conversions (10-bit to 8-bit ADC)
  • They're consistent with existing WLED code patterns

Security: The HTML page uses innerHTML to build the table. This is generally a potential XSS risk, but in this case the data comes entirely from your own firmware's /json/pins endpoint with controlled string outputs, so it's acceptable.

📝 TODOs Noted

ESP8266 GPIO17/A0 has TODOs to "display as A0 pin" - this is documented and can be addressed in a follow-up.

Usermod names have a TODO: "Get actual usermod name from UsermodManager" - currently shows generic "UM #X", which is fine for now.

No Newly Introduced Issues

The code is well-structured, uses proper error handling, includes appropriate platform-specific conditionals, and follows WLED coding patterns. The 250ms polling interval for live updates is reasonable and won't cause performance issues.

Great work on this feature! The Pin Info page will be very helpful for users debugging their configurations. 🐰


🧠 Learnings used
Learnt from: softhack007
Repo: wled/WLED PR: 5048
File: wled00/bus_manager.cpp:549-556
Timestamp: 2026-02-11T16:20:02.872Z
Learning: ESP-IDF V5 requires a complete rewrite of the LEDC (PWM/analog LED) subsystem in WLED. The framework now manages LEDC channels internally (unlike V4 where WLED managed them directly), and dithering functionality may not work as it did before. Direct LEDC struct access (e.g., `LEDC.channel_group[gr].channel[ch].duty.duty`) used in the current implementation will need to be replaced with proper HAL API calls. This affects `wled00/bus_manager.cpp` BusPwm class and related pin manager LEDC allocation code.

Learnt from: DedeHai
Repo: wled/WLED PR: 4798
File: wled00/FX.cpp:7531-7533
Timestamp: 2025-08-26T11:51:21.817Z
Learning: In WLED PR `#4798`, DedeHai confirmed that certain gamma-related calls in FX.cpp/FX_fcn.cpp/particle systems are intentional for effect-level shaping (e.g., brightness curves, TV sim, Pride 2015 pre-mix), distinct from final output gamma. Do not flag or remove these in future reviews; add comments when feasible to clarify intent.

Learnt from: softhack007
Repo: wled/WLED PR: 0
File: :0-0
Timestamp: 2025-11-14T13:37:11.994Z
Learning: In WLED code reviews, when code is modified or added, look for "magic numbers" (hardcoded numeric literals) and suggest replacing them with appropriate defined constants when those constants are meaningful in the context of the PR. For example, the hardcoded value 32 should be replaced with WLED_MAX_SEGNAME_LEN when it represents a segment name length limit. This improves code maintainability and reduces the risk of inconsistencies.

Learnt from: DedeHai
Repo: wled/WLED PR: 4939
File: wled00/FX_fcn.cpp:1176-1187
Timestamp: 2025-09-16T18:08:42.848Z
Learning: In WLED finalizeInit() bus creation (wled00/FX_fcn.cpp), intentionally allowing memory overruns when bus configurations exceed MAX_LED_MEMORY is a deliberate design choice. The trade-off prioritizes creating buses with reduced LED counts over completely failing to create buses, which would cause no LED output and UI failures. This approach forces users to update configurations after migrating to version 0.16 while maintaining basic functionality.

Learnt from: mval-sg
Repo: wled/WLED PR: 4876
File: wled00/xml.cpp:0-0
Timestamp: 2025-08-28T08:09:20.630Z
Learning: The WLED codebase has opportunities for refactoring hardcoded array bounds (like the "15" used for DMX channels) to use sizeof(array)/sizeof(array[0]) for more maintainable code, but such changes should be done consistently across the entire codebase in a dedicated refactoring effort.

Learnt from: softhack007
Repo: wled/WLED PR: 0
File: :0-0
Timestamp: 2025-11-14T13:37:30.955Z
Learning: In WLED code reviews, when code is modified or added, look for "magic numbers" (hardcoded numeric literals) and suggest replacing them with defined constants when meaningful constants exist in the codebase. For example, suggest replacing hardcoded "32" with WLED_MAX_SEGNAME_LEN if the context relates to segment name length limits.

Learnt from: mval-sg
Repo: wled/WLED PR: 4876
File: wled00/wled_eeprom.cpp:0-0
Timestamp: 2025-09-01T10:26:17.959Z
Learning: In WLED PR `#4876`, the DMXStartLED EEPROM backward compatibility issue was partially addressed by keeping it at address 2550 and reading it as a 16-bit value, with DMXChannelsValue array moved to addresses 2552-2566. This maintains compatibility with pre-0.11 EEPROM layouts for DMXStartLED, though legacy "Set to 255" (code 6) configurations may still need migration logic.

Learnt from: blazoncek
Repo: wled/WLED PR: 5140
File: wled00/data/settings_time.htm:66-76
Timestamp: 2025-12-01T07:01:16.949Z
Learning: In WLED PR `#5134`, the fix for macros being initialized with the enable bit set only handles new configurations, not existing ones. If there is a bug in timer/macro handling code (e.g., in settings_time.htm), it must be fixed to work correctly for existing configurations as well.

Learnt from: DedeHai
Repo: wled/WLED PR: 4923
File: wled00/FX.cpp:4883-4901
Timestamp: 2025-09-12T17:29:43.826Z
Learning: In WLED’s web UI, only one slider value (e.g., SEGMENT.intensity or SEGMENT.custom1) changes at a time; code relying on this may use simplified change guards, though presets/JSON can still update multiple fields atomically.

Learnt from: willmmiles
Repo: wled/WLED PR: 4939
File: wled00/FX_fcn.cpp:1183-1194
Timestamp: 2025-09-18T03:17:30.107Z
Learning: In WLED bus management code, dead code branches in error handling (like unreachable else breaks) are intentionally preserved to accommodate potential future API changes, even when currently unreachable.

Learnt from: netmindz
Repo: wled/WLED PR: 5093
File: wled00/util.cpp:1159-1182
Timestamp: 2025-11-20T00:04:04.829Z
Learning: In WLED PR `#5093`, the deviceId feature is designed for opt-in usage reporting that tracks only version/upgrade information (non-behavioral data), not user activity patterns. The deterministic salt approach (MAC + "WLED" + chip model/revision) is acceptable for this limited use case, as correlating MAC addresses to version history represents minimal privacy risk compared to behavioral tracking.

@DedeHai
Copy link
Collaborator Author

DedeHai commented Feb 16, 2026

there are still things that can be improved / moved for pin dropdowns but I would like to tackle that in a seperate PR building upon this one.
I would say this is ready to merge as-is.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

configuration Incorrect configuration or configuration related issue. enhancement hardware (Likely) Setup-specific issue, e.g. flickering LEDs

Projects

None yet

Development

Successfully merging this pull request may close these issues.

5 participants