A light that offers effects gets a sparkles key at the top right of its colour
card. It opens a page with a row per thing the lamp offers, all from Home
Assistant: the light's effect and the select entities of its device (a WLED's
colour palette, preset and playlist) with what they are set to, and a slider per
number entity of the device (speed, intensity). Names are Home Assistant's own
English entity translations, icons its frontend's; nothing about a brand is
hardcoded beyond a preferred order of translation keys.
A row opens LVGL's roller with every name Home Assistant lists at that moment,
asked for when the picker opens (esphome.screen_options, answered with
op: options, one page of names per message), the effects alphabetically with
Solid on top. The check key at the top right sends the choice as one action;
the back key sends nothing. A slider sends number.set_value when let go. While
an effect runs, the tile names it instead of the brightness.
Firmware 0.2.70: effects_page.h (built when it opens, gone when it closes),
Extra.effect/option_rows/number_rows, options_request, a hidden roller widget
so ESPHome compiles LVGL's roller, five firmware-only glyphs. App 0.2.83:
light_effects.py, the effect attribute, the device rows in the state message,
card_options_loop. Checked on the host with a virtual finger (35/35 on both
boards) and compiled for both ESP32 boards; CYD 1,675,424 B (91.3 %).
Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
GitHub issue #7 asked for cover.toggle on tap. ESP Screens now asks Home
Assistant which actions each entity has instead of keeping lists: the editor
offers On / off (covers included), sliders, controls and displays only where
Home Assistant has the action, and refuses only new unsupported settings.
Perform action runs any action Home Assistant offers for the tile's entity,
under its own names and fields; the screen sends it with a call id and says
Refused when Home Assistant refuses. Sensors round by display precision, and
tiles, the top bar, timelines, vacuum chips and the inspector use Home
Assistant's words where they showed raw states. Tiles show Home Assistant's
icons, picked as its frontend does (the fonts grow to 309 glyphs).
Existing screens keep every setting and tap as before: stored layouts load
leniently, legacy taps route the same (1020 combinations), and messages are
byte-identical without Home Assistant's words and icons. Firmware 0.2.58.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
A binary sensor's tile and card now say what Home Assistant says for its
device class, such as Open or Closed for a door and Wet or Dry for a leak
sensor. The screen maps the class it already receives, with the same words
as the top bar and the history card; a test keeps both tables equal. A
history card still waiting for its answer no longer shows the previous
card's word.
Lights and binary sensors that are off turn grey, as in Home Assistant, and
a light without an icon of its own shows a crossed-out bulb while it is off,
on the tile and in the top bar. A chosen icon stays and turns grey.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Holding the top bar for about a second and a half opens a settings page on the
screen, with a blue line filling along the top edge while you hold. A built-in
screen.settings tile and the esphome.<screen>_open_settings action open it too.
The page is one constexpr table of rows in settings_screen.h: Brightness,
Night, Screen (clock, back to page 1, swiping, rotation) and This screen (name,
address, firmware, Home Assistant, Restart). Toggles flip on a tap, numbers and
times step with -/+ (a held time walks whole hours), a choice cycles in a chip,
and a row that depends on a switch above it is greyed out. The LVGL objects exist
only while the page is open: +608 bytes of RAM and +10.7 KB of flash on the CYD.
A change is saved, applied and reported through the existing screen_setting
event, so ESP Screens shows the same value within a second.
New setting auto_home (default on, 2 minutes): an open card, the settings page
or a later page goes back to page 1 after that long without a touch, not only on
standby. It travels beside the frozen eleven-key settings block with its own
preference, so older firmware and older apps keep working.
docs/SETTINGS.md is the recipe for adding a setting; the Claude skill explains
the page. Firmware 0.2.44.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
App 0.2.47 / firmware 0.2.40:
- guition-4848s040.yaml gets the CYD's climate card: the setpoint between large -/+ keys
(debounced, hold to repeat) and one row of mode keys in HA's order and colours; the arc,
scrim, mode pill and climate_number font are gone.
- Fan and swing modes sit right on the card as segmented rows behind their icons, drawn by the
new climate_card.h (async rebuild, taps through the touch guard and a profile hook). The card
is laid out per case from one table: no, one or two settings rows, with or without mode keys.
- Both boards hide a mode key row that would hold a single mode and centre the setpoint instead.
- Glyph arrow-oscillating (Home Assistant's swing icon) joins the icon set.
Verified on the Guition over OTA with the owner's air conditioner and with host renders of both
boards; see docs/TEST_RESULTS_0247.md.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
App 0.2.46 / firmware 0.2.39:
- The vacuum's state message carries extras from its own device: the cleaning mode and water
selects (found by translation key, then entity id ending, so localized ids work), the suction
speeds to offer, the battery sensor (HA 2026.8 dropped battery_level), charging and the current
room. Speeds and water levels a mode covers move into the mode row; Custom only while in use.
The manager watches these entities and resends only the vacuum's message when one changes.
- Vacuum card redesign on both boards: robot with state, battery, charging bolt and room; Start
(Pause, Resume) and Dock; then segmented rows for mode, suction and water, showing only the rows
the chosen mode uses. Taps show at once and wait for Home Assistant; Locate is a round button in
the Guition hero.
- CYD climate card without the arc: big setpoint between large -/+ keys (debounced, hold to
repeat) and one row of mode keys in HA's order and colours, with a more key for fan and swing.
- Both profiles clear climate_edit_pending when the climate card is closed, instead of running
ui_refresh every second while the flag stayed set.
Tested with the owner's Roborock S8 on HA 2026.9.1 (live data, OTA-flashed bench boards) and with
host renders of both boards; see docs/TEST_RESULTS_0246.md.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Firmware 0.2.37 for both boards:
- The analog clock card gets a thin red second hand that moves every second while the
screen is awake (runtime_tiles::screen_awake, set by the profiles from display_dimmed);
in standby it hides and the clock keeps its once-a-minute redraw.
- Card sliders follow HA's control slider: 12/42 and 8/42 corners, a 4 px handle an
eighth of the height from the fill end, a stub of a third of the height at 0 or 1 %,
the track in the fill colour at 20 %. An off light or fan shows only the empty grey
track, also in the colour card's brightness row. A light's slider floors at 1 %.
- Every overlay card shares one top bar: a round back arrow at the left (60/40 px), the
name centred, and only the climate power as a right-hand action. The "done"/"ok"
buttons of the colour and vacuum cards are gone; the brightness card gets its arrow.
- The top bar reads "Connecting to Home Assistant..." / "Waiting for ESP Screens..."
until the first layout, instead of "Choose tiles in HA".
Checked with the host renderer for both boards and on the Guition over USB.
Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Every screen gets the user action esphome.<device>_show_alert with title,
subtitle, icon, color, button_text, timeout and flash. The card sits on
LVGL's top layer above every page, card and the dim overlay, wakes the
screen and keeps the backlight at its normal brightness until the button
(or the timeout; 0 waits for the button, the button always closes at
once). flash: true blinks the backlight four times on arrival. Icons are
the tile picker names (also mdi:name or the hex codepoint of a compiled
glyph, else alert-outline), colours the tile pastels. A new alert replaces
the current one; every ending fires esphome.screen_alert with action,
title and screen. dismiss_alert removes the card remotely.
The field is button_text rather than button: ESPHome reserves the names
of loaded components as ids and the CYD profile loads button:. The C++
namespace is screen_alert because the widget id alert_overlay becomes a
global lv_obj_t*.
tools/generate_icons.py now also writes tile_icon_names.h (name to
codepoint) from the one icon list. Firmware 0.2.31 for both boards.
Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>