Skip to content

Climate, weather and media_player icons never reflected their state - #221

Merged
nicosandller merged 5 commits into
nicosandller:mainfrom
diegocjorge:climate-weather-media-icons
Aug 31, 2026
Merged

Climate, weather and media_player icons never reflected their state#221
nicosandller merged 5 commits into
nicosandller:mainfrom
diegocjorge:climate-weather-media-icons

Conversation

@diegocjorge

Copy link
Copy Markdown
Contributor

entityIsActive only ever recognised the literal state "on" (or a small per-domain set for lock/vacuum/camera) as active. A climate entity's state is its HVAC mode — "cool", "heat", "dry" — never "on", so a running unit always read as off: no active highlight, and a configured iconAnimation never played however it was actually running. A media player reporting "paused"/"idle"/"buffering" instead of "playing" had the same problem — still switched on, read as off.

climate and media_player each get their own active-state set now, mirroring lock/vacuum/camera: every HVAC mode but "off", and every media_player state but "off".

Separately, climate and weather had no state-aware icon at all — DOMAIN_STATE_ICONS only ever expressed a two-way on/off choice, and neither domain's meaning is binary. A climate item always drew the bare thermostat glyph regardless of mode, and a weather item — with no device class and no domain entry — drew entityDefaultIcon's plain fallback circle whatever the sky was doing.

Adds CLIMATE_MODE_ICONS (one icon per HVAC mode, HA's own climate.HVACMode enum) and WEATHER_CONDITION_ICONS (one per condition, HA's own ATTR_CONDITION_* set), and threads the entity's raw state into entityDefaultIcon so it can pick from them. A climate entity in fan_only always spins regardless of iconAnimation — its own fan is what's running, the same physical fact that makes a fan domain entity spin by default, just decided from this entity's state rather than its domain; none still wins over it.

entityIsActive only ever recognised the literal state "on" (or a
small per-domain set for lock/vacuum/camera) as active. A climate
entity's state *is* its HVAC mode — "cool", "heat", "dry" — never
"on", so a running unit always read as off: no active highlight, and
a configured iconAnimation never played however it was actually
running. A media player reporting "paused"/"idle"/"buffering" instead
of "playing" had the same problem — still switched on, read as off.

climate and media_player each get their own active-state set now,
mirroring lock/vacuum/camera: every HVAC mode but "off", and every
media_player state but "off".

Separately, climate and weather had no state-aware icon at all —
DOMAIN_STATE_ICONS only ever expressed a two-way on/off choice, and
neither domain's meaning is binary. A climate item always drew the
bare thermostat glyph regardless of mode, and a weather item — with
no device class and no domain entry — drew entityDefaultIcon's plain
fallback circle whatever the sky was doing.

Adds CLIMATE_MODE_ICONS (one icon per HVAC mode, HA's own
climate.HVACMode enum) and WEATHER_CONDITION_ICONS (one per condition,
HA's own ATTR_CONDITION_* set), and threads the entity's raw state
into entityDefaultIcon so it can pick from them. A climate entity in
fan_only always spins regardless of iconAnimation — its own fan is
what's running, the same physical fact that makes a `fan` domain
entity spin by default, just decided from this entity's state rather
than its domain; `none` still wins over it.

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

🟡 Changes recommended

The media_player “active” state logic contradicts the PR description by excluding the standby state, so behavior and tests should be aligned with the stated requirement.

Once you've addressed the issues Copilot identified, you can request another Copilot review.

Pull request overview

This PR fixes state handling for Home Assistant climate, weather, and media_player entities so the floorplan card can correctly determine “active” state (for highlight + icon animation) and choose a state-appropriate default icon for non-binary domains.

Changes:

  • Add HVAC-mode → icon mapping for climate and condition → icon mapping for weather, and pass raw entity state into entityDefaultIcon.
  • Expand entityIsActive domain-specific active-state handling for climate and media_player.
  • Add/adjust unit tests covering the new icon selection and active-state behavior.
File summaries
File Description
src/render.ts Adds climate/weather state→icon mappings, updates active-state handling, and threads state into default icon selection.
src/render.test.ts Adds test coverage for climate/weather icon selection and new active-state expectations.
Review details
  • Files reviewed: 2/2 changed files
  • Comments generated: 2
  • Review effort level: Lite

💡 Add a code-review agent skill or configure MCP servers for context-aware, tailored reviews. Learn more in the docs.

Comment thread src/render.ts
Comment thread src/render.test.ts

@nicosandller nicosandller left a comment

Copy link
Copy Markdown
Owner

Choose a reason for hiding this comment

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

Approve — clean, well-scoped fix.

Behaviour is unchanged for every domain and state outside the three this touches: each new branch in entityDefaultIcon returns early only for climate / weather, the ACTIVE_STATES additions sit beside the existing lock/vacuum/camera sets, and the resolveIconAnimation line is gated below the none and fail-closed guards. The icon and active-state maps track HA's own HVACMode and ATTR_CONDITION_* enums; unrecognised values fall back to the previous glyph rather than to nothing; card and editor stay in sync because both resolve through resolveItemIcon, which now threads st.state. Every branch has a test, tsc is clean, and the full suite is green (1202).

Rendered every state against the main and PR bundles — before/after for climate, weather and media_player here: https://claude.ai/code/artifact/d910c002-55bc-4d6f-a51e-ffe1cc5da870

Two small notes, neither blocking:

  • entityDefaultIcon for media_player still keys only on/off, so paused / idle now draw mdi:television-play. "It's on" is the right semantic and it matches the amber highlight, but a distinct pause glyph would be a nice follow-up.
  • climate counts heat / cool / … as active regardless of hvac_action, so a thermostat in heat mode but currently idle (setpoint satisfied) reads as active. That matches HA's own Tile card and is overridable with a state rule on hvac_action, so it's fine — just flagging the choice.

One request before merge

The demo plan (docker/config/floorplan-demo.yaml) has no climate.*, weather.* or media_player.* device on either floor, so none of this is visible in the dev container — only in the unit tests. The demo integration already ships climate.heatpump / climate.hvac / climate.ecobee, a weather.* entity and several media_player.*.

Could we add a few of these to the default plan — and ideally have the sample-data automation walk a climate entity through its HVAC modes the way the covers already cycle position — so the feature has a visible home, the same way the per-leaf sensors and multi-reading badges do?

@nicosandller

Copy link
Copy Markdown
Owner

@diegocjorge I approved but could you add these new feature examples on the dev container so we can keep an aye on them in the future?

nicosandller asked for these on PR nicosandller#221's review: the plan had nothing
that reflected any of the three domains this PR touches, so a future
change here has nothing to visibly break.

- climate.hvac (issue nicosandller#206's own reproduction: boots into "cool", not
  "on", and is the one demo climate entity whose hvac_modes include
  fan_only) with iconAnimation: spin, matching the original report.
- weather.demo_weather_south and weather.demo_weather_north side by
  side, the same pairing glow_warm/glow_cool already use above -- a
  demo weather entity's condition never changes, so two fixed ones is
  the only way to see more than one WEATHER_CONDITION_ICONS entry on
  the plan at once.
- media_player.walkman, which boots "playing"; media_player.media_pause
  from Developer Tools > Actions flips it to "paused" without turning
  the badge off.

All four come from the existing demo: integration already enabled in
configuration.yaml, so no other config file changes.
nicosandller flagged this on PR nicosandller#221's review: paused/idle correctly
read as active now, but both drew the same television-play glyph as
"playing" -- right about being on, but silent about not being
mid-playback.

Adds one override ahead of the generic on/off table: media_player in
"paused" draws mdi:television-pause. Every other active state (on,
idle, playing, buffering) keeps the plain play glyph, since none of
them needed their own icon before this -- only paused visibly differs
from "is something happening" now that it counts as on.

The other note on that same review -- a climate entity reading active
in heat/cool regardless of hvac_action -- is left as is per the
reviewer's own comment: it matches HA's Tile card and is already
overridable with a state rule on hvac_action.
Following up on the pause-icon fix: idle is on with nothing loaded at
all, and was still drawing the plain television-play glyph -- same
problem as paused had, one commit ago. Folded both into one small
MEDIA_PLAYER_STATE_ICONS table now that there are two exceptions
instead of a single override.

idle -> mdi:television (plain), chosen over mdi:television-stop since
nothing was actually stopped -- there may never have been anything
playing at all.
@diegocjorge

Copy link
Copy Markdown
Contributor Author

Added the pause icon (mdi:television-pause) and also gave idle its own icon (mdi:television). Everything else that counts as active (on, playing, buffering) keeps the plain play icon (mdi:television-play).

On the hvac_action point, I think that one really depends on the kind of HVAC setup. Where I live it's common to have an individual A/C unit per room, and for those, being in heat/cool mode does mean the unit is on, whether or not it's actively heating/cooling at that instant. So I'd rather leave the current behavior as the default (it also matches HA's own Tile card) and let anyone who wants idle-vs-running to show differently add a state rule on hvac_action, like you mentioned.

@nicosandller
nicosandller self-requested a review August 31, 2026 23:05
@nicosandller
nicosandller merged commit 2684eb7 into nicosandller:main Aug 31, 2026
2 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.

3 participants