Grey out what Home Assistant calls off and colour the rest like Home Assistant, so an airco that is off no longer looks on (0.2.85)

The airco tile stayed orange while the airco was off. The firmware kept its own
short list of what turns grey and gave an off climate Home Assistant's orange,
but Home Assistant has no colour for a climate that is off: its cards fall back
to the inactive grey. Other tiles had the same fault: an off fan, a closed
blind, a docked robot, a player in standby, an idle script, a paused timer and
a camera that isn't streaming all kept their colour.

Tile::active() is now a port of the frontend's stateActive() for the domains a
tile can show, and every tile that is not active is grey. An airco that is off
reads Off, with the room's temperature when the device reports one, as Home
Assistant's tile does. tile_controls::accent() follows stateColorCss(): alarm
binary sensors red, a battery green, orange or red by its charge, a running
script or timer and a streaming camera amber, the weather per condition, the
sun amber and indigo, someone in a zone blue. Scenes, selects, numbers and
sensors keep their own colour per kind. A full-page tile lights up only for
tiles that can be off (Tile::lights_up), and a closed blind's slider keeps its
colour. The top bar's alarm classes are Home Assistant's eleven.

Checked with tools/check.sh (471 Python tests, 19/19 C++ with 58 state cases
and every colour rule) and compiled for both boards: CYD 1,677,488 B (91.4 %,
+576 B), Guition 2,054,640 B (25.3 %).

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
Max Gramser
2026-09-18 23:31:10 +02:00
parent d76461d774
commit 9391d1b0ac
16 changed files with 369 additions and 69 deletions
+32 -10
View File
@@ -290,20 +290,42 @@ struct Tile {
auto d = domain();
return state != "unknown" || d == "scene" || d == "button" || d == "input_button";
}
// Home Assistant's stateActive() (frontend src/common/entity/state_active.ts), the rule its cards colour by: an
// entity it calls inactive is grey, such as an airco that is off, a closed blind, a docked robot, a player in
// standby or a paused timer (firmware 0.2.71+). Only the cases of the domains a tile can show are here. A scene,
// button or image states the moment it last ran (TIMESTAMP_STATE_DOMAINS), so only "unavailable" makes it
// inactive. A built-in card has no state and is always active.
bool active() const {
return state == "on" || state == "cleaning" || state == "active" || (domain() == "person" && state == "home") ||
(domain() == "sun" && state == "above_horizon") || (domain() == "climate" && available() && state != "off");
if (builtin()) return true;
if (!received || state.empty() || state == "unavailable") return false;
auto d = domain();
if (d == "scene" || d == "button" || d == "input_button" || d == "image") return true;
if (state == "unknown" || state == "off") return false;
if (d == "cover") return state != "closed";
if (d == "person") return state != "not_home";
if (d == "media_player") return state != "standby";
if (d == "vacuum") return state != "idle" && state != "docked" && state != "paused";
if (d == "timer") return state == "active";
if (d == "camera") return state == "streaming" || state == "recording";
return true;
}
// A slider shows the card's colour like Home Assistant's tile sliders: grey only while stateActive()
// (frontend src/common/entity/state_active.ts) calls the entity inactive, such as an off light or fan and a
// media player that is off or in standby. A number with a value is active there, and a closed cover's
// position slider keeps the cover's colour so it never looks disabled (hui-cover-position-card-feature.ts).
// A card over the whole page lights up in its state colour while it is on (firmware 0.2.62+): only a tile that can
// be off, closed, docked or away, and only while active() calls it active (firmware 0.2.71+). Sensors, numbers,
// selects, scenes, buttons, images, the weather and the sun are always active in Home Assistant and stay plain.
bool lights_up() const {
const auto d = domain();
for (const char *on_off : {"light", "switch", "input_boolean", "climate", "fan", "cover", "media_player", "vacuum",
"script", "timer", "camera", "person", "binary_sensor"})
if (d == on_off) return active();
return false;
}
// A slider shows the card's colour like Home Assistant's tile sliders: grey only while the entity is inactive
// (active() above), such as an off light or fan and a media player that is off or in standby. A number with a
// value is active there, and a closed cover's position slider keeps the cover's colour so it never looks
// disabled (hui-cover-position-card-feature.ts).
bool slider_active() const {
if (!available()) return false;
auto d = domain();
if (d == "media_player") return state != "off" && state != "standby";
if (d == "cover" || d == "number" || d == "input_number") return true;
return active();
return domain() == "cover" || active();
}
};
// Slot position of a tile within the fixed two-column, three-row pages.