Skip to content

fix(uartex): wire fan preset modes into FanTraits so Home Assistant sees them - #278

Merged
eigger merged 1 commit into
eigger:masterfrom
mrbigcho:fix/uartex-fan-preset-modes
Jul 25, 2026
Merged

fix(uartex): wire fan preset modes into FanTraits so Home Assistant sees them#278
eigger merged 1 commit into
eigger:masterfrom
mrbigcho:fix/uartex-fan-preset-modes

Conversation

@mrbigcho

Copy link
Copy Markdown
Contributor

What follows is described here.

Problem

A uartex fan configured with preset_modes never exposes preset-mode support to Home Assistant. The fan entity reports supported_features without the PRESET_MODE flag and preset_modes: [], so fan.set_preset_mode is unavailable — even after a clean build. Speed control works; only presets are missing.

Root cause

Since ESPHome 2026.4 the fan preset-mode vectors moved onto the Fan entity base class, and Fan::get_traits() is virtual with no base-class hook to inject them. Each get_traits() override must call this->wire_preset_modes_(traits) explicitly (unlike Climate, whose base class wires custom modes automatically) — see the migration note.

UARTExFan::set_preset_modes() already registers the modes on the entity via set_supported_preset_modes(), but UARTExFan::get_traits() returns a fresh FanTraits populated only with speed info and never wires the preset modes in. The modes are stored on the entity but never reach the traits sent to HA.

This is a regression from #226, which removed the trait-side mode registration from uartex_fan.cpp without adding the wire_preset_modes_() call the new API requires.

Fix

Call this->wire_preset_modes_(traits) in get_traits(). It copies the registered preset modes into the returned FanTraits, and no-ops when none are configured (speed-only fans unchanged). No header change needed.

Testing

Tested on a real Kocom ventilator (device 0x48) with preset_modes: ["자동", "수동"]:

  • Before: HA shows supported_features: 49, preset_modes: []; fan.set_preset_mode fails.
  • After: supported_features: 57 (PRESET_MODE bit set), preset_modes populated, and fan.set_preset_mode sends command_preset and reflects state_preset. Switching between the two presets works.

…ees them

UARTExFan::set_preset_modes() registers modes on the entity, but get_traits()
returned a fresh FanTraits with speed only and never wired the presets in, so
Home Assistant never saw PRESET_MODE support (preset_modes stayed empty).

Since ESPHome 2026.4, Fan::get_traits() overrides must call wire_preset_modes_()
explicitly (the base class no longer auto-injects them, unlike Climate). This is
a regression from eigger#226, which removed trait-side registration without adding the
required call. Add this->wire_preset_modes_(traits); it no-ops when no presets
are configured, so speed-only fans are unaffected.
@eigger

eigger commented Jul 25, 2026

Copy link
Copy Markdown
Owner

감사합니다!

@eigger
eigger merged commit 379d8c1 into eigger:master Jul 25, 2026
10 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants