You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
While reviewing PR #1011 (mashumaro from_dict refactor), we noticed that two pieces of ConfigEntry metadata are wired up end-to-end but never carry any actual data, so the corresponding UX gates are no-ops today across all 317 PIN-type fields in the catalog:
Field
What it would drive
Actual content today
entry.pin_features: list[PinFeature]
Filter the pin dropdown to board pins whose features list includes every required capability (required.every(f => pin.features.includes(f)) at config-entry-pin-renderer.ts:125-128)
Empty list for every component
`entry.pin_mode: PinMode
None`
Disable input-only pins for fields needing output (line 64-68 of the same file)
Background trail: PR #1011 surfaced this when filtering _resolve_pin_features in script/sync_components.py against the PinFeature enum dropped 100% of catalog pin_features entries (the schema was emitting GPIO mode strings like input / output / pullup that don't belong on a hardware-capability enum; the runtime was already silently dropping them via _safe_enum before they reached the wire). The data shape is now honest, but the metadata pipe runs dry.
The frontend filter wiring, the model shape, and the board manifests are all already in place — board manifests list real hardware features (adc, dac, i2c_sda, spi_clk, uart_tx, pwm, touch, strapping, input_only, …). The missing piece is just the per-field requirement.
What this issue covers
Hand-curated _PIN_FEATURE_OVERRIDES table in script/sync_components.py. Map (component_id, field_key) → list[PinFeature] for high-value entries. ~20-30 rows covers most of the user-visible benefit:
Most can probably be inferred from the schema's pin-block default mode: setting — the sync script already walks the inner schema and could lift that to a field-level pin_mode.
Soften the frontend filter. The current required.every(f => pin.features.includes(f))hides non-matching pins. That's harsh for unusual boards and "I know what I'm doing" workflows. Render-time options:
Show matching pins normally; flag non-matching pins with a warning icon + tooltip (e.g., "This pin doesn't expose ADC; the component may not work as expected.")
Group: matching pins on top, "Other pins" collapsed below
Keep selection always allowed; only the visual affordance changes
Why not push it upstream into the ESPHome schema bundle?
Cleaner long-term, but it requires an upstream PR + schema version coordination + waiting for a bundle release. The hand-curated table gives us the user-visible benefit immediately while leaving the door open to a schema-driven source of truth later — same way INTERNAL_COMPONENT_IDS was hand-maintained even though the auto-load chain notionally lives in ESPHome's component metadata.
Acceptance
_PIN_FEATURE_OVERRIDES populated for the components listed above (and any others the maintainers want covered).
pin_mode populated for OUTPUT-driving fields where the schema's default mode makes it unambiguous.
Frontend renders non-matching pins with a soft affordance (warning icon / grouped section) rather than hiding them; pin selection stays unrestricted.
A test pinning at least one mapping per category (sensor.adc.pin requires ADC, etc.) so a regen-without-the-table regression is caught in CI.
Out of scope
Adding new PinFeature enum values — the current set covers everything board manifests carry.
Background
While reviewing PR #1011 (mashumaro from_dict refactor), we noticed that two pieces of
ConfigEntrymetadata are wired up end-to-end but never carry any actual data, so the corresponding UX gates are no-ops today across all 317 PIN-type fields in the catalog:entry.pin_features: list[PinFeature]featureslist includes every required capability (required.every(f => pin.features.includes(f))atconfig-entry-pin-renderer.ts:125-128)Background trail: PR #1011 surfaced this when filtering
_resolve_pin_featuresinscript/sync_components.pyagainst thePinFeatureenum dropped 100% of catalogpin_featuresentries (the schema was emitting GPIO mode strings likeinput/output/pullupthat don't belong on a hardware-capability enum; the runtime was already silently dropping them via_safe_enumbefore they reached the wire). The data shape is now honest, but the metadata pipe runs dry.The frontend filter wiring, the model shape, and the board manifests are all already in place — board manifests list real hardware features (
adc,dac,i2c_sda,spi_clk,uart_tx,pwm,touch,strapping,input_only, …). The missing piece is just the per-field requirement.What this issue covers
Hand-curated
_PIN_FEATURE_OVERRIDEStable inscript/sync_components.py. Map(component_id, field_key) → list[PinFeature]for high-value entries. ~20-30 rows covers most of the user-visible benefit:sensor.adc.pinADCdac.gpio.pinDACi2c.sda/i2c.sclI2C_SDA/I2C_SCLspi.clk_pin/mosi_pin/miso_pin/cs_pinSPI_CLK/SPI_MOSI/SPI_MISO/SPI_CSuart.tx_pin/rx_pinUART_TX/UART_RXesp32_touch.pinTOUCHoutput.ledc.pin, light-PWM outputsPWMMirrors the existing
_FIELD_OVERRIDESandINTERNAL_COMPONENT_IDShand-curation pattern. Applied during emission so the build-time roundtrip guard (components: replace hand-rolled body loader with mashumaro from_dict, tighten sync-script roundtrip #1006 /_emit_split_catalog) catches typos at sync time.Same exercise for
pin_mode. Whether each PIN field expects input or output:output.gpio.pin, stepperdir_pin/step_pin/sleep_pin,switch.gpio.pin(when driving a load) →OUTPUTbinary_sensor.gpio.pin, button GPIO inputs →INPUTmode:setting — the sync script already walks the inner schema and could lift that to a field-levelpin_mode.Soften the frontend filter. The current
required.every(f => pin.features.includes(f))hides non-matching pins. That's harsh for unusual boards and "I know what I'm doing" workflows. Render-time options:Companion frontend change in
config-entry-pin-renderer.ts.Why not push it upstream into the ESPHome schema bundle?
Cleaner long-term, but it requires an upstream PR + schema version coordination + waiting for a bundle release. The hand-curated table gives us the user-visible benefit immediately while leaving the door open to a schema-driven source of truth later — same way
INTERNAL_COMPONENT_IDSwas hand-maintained even though the auto-load chain notionally lives in ESPHome's component metadata.Acceptance
_PIN_FEATURE_OVERRIDESpopulated for the components listed above (and any others the maintainers want covered).pin_modepopulated for OUTPUT-driving fields where the schema's default mode makes it unambiguous.sensor.adc.pinrequiresADC, etc.) so a regen-without-the-table regression is caught in CI.Out of scope
PinFeatureenum values — the current set covers everything board manifests carry.