132 Commits

Author SHA1 Message Date
Xandrossian 950414c280 docs: the Elecrow's silent touch was the flex cable; what touch_probe reads either way
CI / checks (push) Failing after 7m15s
CI / firmware (add-on) (push) Has been skipped
CI / firmware (min_version) (push) Has been skipped
2026-09-21 14:38:00 -07:00
Xandrossian 6910f30d4c Add touch_probe and touch_reset actions to the Elecrow for a diagnosis over the API (0.2.97, firmware 0.2.83)
CI / checks (push) Has been cancelled
CI / firmware (add-on) (push) Has been cancelled
CI / firmware (min_version) (push) Has been cancelled
2026-09-21 14:04:25 -07:00
Xandrossian 4ec8c7a935 Reset the Elecrow's GT911 the way Elecrow's own V3.0 example does (0.2.96, firmware 0.2.82)
CI / checks (push) Waiting to run
CI / firmware (add-on) (push) Blocked by required conditions
CI / firmware (min_version) (push) Blocked by required conditions
The 2 ms reset of ESPHome's expander support (0.2.81) left the chip silent: "Calibration error" with the PCA9557
answering at 0x18. A component of smart_display's (elecrow_touch_reset.h, setup priority 700: after the I2C bus,
before the GT911 driver) writes the expander as Elecrow's V3.0 ESPHome example does: every pin an output and low,
20 ms, the reset released, 100 ms, the interrupt line back to an input. The driver's reset and interrupt pins are gone.
2026-09-21 13:30:41 -07:00
Xandrossian da28d19961 Bring the Elecrow's GT911 out of reset through the V3.0's PCA9557 (0.2.95, firmware 0.2.81)
CI / checks (push) Waiting to run
CI / firmware (add-on) (push) Blocked by required conditions
CI / firmware (min_version) (push) Blocked by required conditions
A unit's touch never answered: "touchscreen is marked FAILED: Calibration error" at setup, the GT911 still in reset
behind the PCA9557 (I2C 0x18) of the V3.0 board. The board file declares the expander as ESPHome's pca9554 (the same
register map) and hands the GT911 driver its reset (IO0) and interrupt (IO1) pins on it, so the driver runs Elecrow's
own sequence: reset low with the interrupt line low, reset high, 56 ms, address 0x5D. A V2.0 without the expander boots
its GT911 by the pull-up as before. The bus is scanned at boot for the log.
2026-09-21 12:54:18 -07:00
Xandrossian a3ef7f09a1 Keep the Elecrow's touch bus free of the USB PHY after Wi-Fi starts (0.2.94, firmware 0.2.80)
CI / checks (push) Waiting to run
CI / firmware (add-on) (push) Blocked by required conditions
CI / firmware (min_version) (push) Blocked by required conditions
The GT911 of the CrowPanel 7.0" sits on GPIO 19 and 20, the ESP32-S3's USB pins. Firmware 0.2.79 freed them once, in a
static constructor; the Wi-Fi PHY library then kept the USB PHY on (CONFIG_ESP_PHY_ENABLE_USB, on by default on an
ESP32-S3) and the touch went quiet once Wi-Fi came up. The board file turns that option off, frees the pins again in
BOOT_TOUCH after Wi-Fi started, and a one-second watchdog frees them whenever anything takes them, with a log line.
2026-09-21 12:05:28 -07:00
Xandrossian 9857cc3bda Add the Elecrow CrowPanel 7.0" as a third board, and take the packages and the add-on from Gitea (0.2.93)
CI / checks (push) Successful in 12m50s
CI / firmware (add-on) (push) Successful in 18m19s
CI / firmware (min_version) (push) Successful in 17m55s
A board file for the Elecrow CrowPanel 7.0" (DIS08070H, ESP32-S3-WROOM-1-N4R8): 800x480 through mipi_rgb, GT911 on the
ESP32-S3's USB pins (elecrow_usb_phy.h frees them, behind a flag only this board sets), the Guition's vertical sizes
across a wider page, no rotation. Its 4 MB of flash take the CYD's budget: a partition table of the component's
(smart_display: partitions: 4mb_wide_slots, 1,984 KB slots), the icon fonts at 2 bits a pixel and the TLS client only
bring the firmware to 1,865,440 bytes, 91.8 % of a slot, with camera images kept. docs/ELECROW.md has the numbers and
the trade.

The add-on reads a large board's name from the type sensor's value, the editor offers the board under New screen and
draws the wide preview, tools/check.sh builds it with the budget, render_topbar and capture_ui take the panel's size.
Firmware 0.2.79; the CYD image is unchanged (1,633,760 bytes).

This fork builds from gittea.trippedonmy.name/Xandrossian/homeassistant_espscreen: the packages, the fonts, the
component and the add-on repository point there instead of GitHub.
2026-09-20 23:18:01 -07:00
Max Gramser efbab04b39 Show the album cover on a media tile, in the same strip as the live camera pictures (0.2.92)
A single or double-width media player tile takes Display -> Album cover
on a Guition: the cover of what plays in the icon's place, like Home
Assistant's own tile. It rides in the page's strip of 0.2.91: the request
and the answer are the same, a media player is simply among the tiles.
The app fetches a player's picture only when its address changes; a page
with a camera loads at the camera's pace with the cover reused, a page of
media tiles alone loads once, and a new track (the picture's mark in the
state, part of the page's wish) asks again at once. A player without a
picture keeps its icon and is not asked for; the double-width tile keeps
its controls; the tile over the whole page keeps the card's big cover.
Firmware 0.2.78.

Host harness 31 checks (docs/TEST_RESULTS_0292.md). CYD firmware
1,633,760 B, 89.0 %.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
2026-09-20 13:46:46 +02:00
Max Gramser 306636434b Show a live picture on a camera tile, run an action from the alert button, roll long media titles, and keep full-page tiles in their own colour (0.2.91)
Live picture (issue #4): a camera or image tile on a Guition takes
Display -> Live picture with a pace of 15 or 30 s. The camera tiles of a
page share one download: the screen asks ESP Screens for them together
(esphome.screen_camera with tiles, size and bg) and the app serves one
BMP, a strip of squares with the corners rounded over each tile's own
colour; every tile draws its square out of it with LVGL's image offset
(LV_IMAGE_ALIGN_TOP_LEFT: the default centres a taller source). A third
online_image on the Guition holds the strip; it loads after the alert's
picture, a cover and the camera full screen, never under a card, in
standby or under a finger. The strip is served whole every time: ESPHome's
http_request logs a 304 as a failed request. Firmware 0.2.77.

Alert button: esp_screens_show_alert takes action and data; the app
performs the action once when the button's report (esphome.screen_alert,
ok) comes from any screen. show_alert keeps its seven fields, so every
firmware from 0.2.31 has it.

Media card and full-page media tile: a title or artist line that is too
wide rolls by (LV_LABEL_LONG_SCROLL_CIRCULAR) instead of ending in dots.

Full-page tiles are white or their own pastel like every other tile; the
tint in the state colour of firmware 0.2.62 to 0.2.76 is gone.

Host harness (27 checks) and bench Guition + local add-on on the Yellow:
docs/TEST_RESULTS_0291.md. CYD firmware 1,633,728 B, 89.0 %.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
2026-09-20 12:47:44 +02:00
Max Gramser 8a81ff4d93 Show the languages in the README, with what the firmware costs
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-09-20 11:46:55 +02:00
Max Gramser 2743fdcdf7 Say in the translation guide what the tile's short "yesterday" is for
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-09-19 23:41:50 +02:00
Max Gramser a8070a0379 Say in the translation guide how to find a word, and that Home Assistant's own words are fixed in Home Assistant
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-09-19 22:26:23 +02:00
Max Gramser f02f429188 Weekdays that fit the weather columns, the top bar's own abbreviation, tile texts that fit, and a check that measures them
- The CYD's weather columns hold two letters beside the icon: every language has its own two-letter days (the CLDR's
  short width, Polish nd pn wt); French mar became nar there. check fails on a longer one.
- The top bar takes the language's abbreviation (sam. 19 sept., Sa., 19. Sept.), English keeps Sa 19 Sep.
- The editor's clock and date follow the screens: 7:05 PM in the top bar, 7:05 on the clock card.
- A long weather word ends in an ellipsis before the days.
- Tile lines that were cut on a screen are shorter (Zum Öffnen, Ouvrir, Otwórz, Sin imagen, ...); check measures
  them with the screens' font against the tile width of both boards.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-09-19 17:13:59 +02:00
Max Gramser 125346d94e Notation like Home Assistant, each screen in its own language, and the language in every build
From the end-to-end test on the bench boards and an independent review:
- Units spaced as Home Assistant does (54% / 54 % in German and French, 18°, 21.5 °C), in the firmware and the app.
- Grouping from five digits where the language does (1234 but 12.345 in Spanish, Polish, Portuguese): the layout
  message carries group_min and percent_space; an unknown number style no longer refuses a layout.
- Automatic follows Home Assistant's own language for the clock and numbers, also without a translation (Swedish:
  24 hours, 1 234,5; pt-BR: 1.234,5): regions.json from the CLDR for all 63 languages Home Assistant offers.
- 12-hour clock: the top bar says 3:48 PM, the clock card 3:48 (not 03:48), Last runs follow the clock.
- The climate setpoint font has the decimal comma; the value fonts have ², ³ and µ (m³ was a box).
- Weather days: at most three letters without the dot (mié, sáb, czw); the screen took three bytes.
- Texts fall back per key through the base language (pt-BR -> pt -> en) in the firmware and the app.
- Each screen gets the app's words in the language its firmware speaks; firmware from before the languages gets
  English and its own letters, not boxes.
- set_language re-reads what it writes (indentation, comments, quoted keys, CRLF, !include) and every build writes
  the language first; the 24-hour pin no longer hits a fresh install and waits for the old clock switches.
- Tests: region and notation, plural parity with the C++ rules, set_language edge cases, the pin, PUT /api/language.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-09-19 16:52:34 +02:00
Max Gramser e2284de7f3 The editor in Spanish and Portuguese, and Portugal's plural rule for Portuguese
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-09-19 15:28:54 +02:00
Max Gramser 42ed793aee Write the sun's and the forecast's times, and the top bar's, for the screens' 12 or 24-hour clock
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-09-19 15:11:14 +02:00
Max Gramser c2cf3391d6 Say in the guides that the clock is set for every screen under Language & region
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-09-19 14:45:19 +02:00
Max Gramser 286a431adf Explain how to check or add a language, and run the translation checks with the others
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-09-19 14:36:40 +02:00
Max Gramser 9362a5f1db Start the translations: one file per language, English as the source, and how to translate
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-09-19 13:52:29 +02:00
Max Gramser 3b15e7f7a3 Build the screens with ESPHome 2026.9 and keep its build memory in the app's own storage, give the CYD 94 KB more room, and stop a timer from counting one second too many (0.2.89)
The add-on ships ESPHome 2026.9.0: it builds an ESP32 with ESP-IDF itself
and keeps a compiler cache. firmware.py gives the CLI its own storage in
/data (ESPHOME_DATA_DIR /data/esphome, which the ESPHome Device Builder no
longer wipes on start; ESP-IDF and ccache in /data/idf, at most 1 GB;
compilers limited to the core count as PlatformIO ran them), removes the
unused PlatformIO once before the first ESP-IDF build, and leaves the new
folders out of backups.

Firmware 0.2.75: assertion_level SILENT in every board's esp32 block, the
core logs from INFO, and clock_parts() in runtime_model.h replaces sscanf.
timer_left() caps a running timer at its duration (the screen's clock runs
up to a second behind Home Assistant's). The packages keep min_version
2026.6.2, the top-level online_image and OTA passwords for new screens, so
an add-on or Device Builder that isn't updated yet keeps building every
screen; CI now builds both boards with the add-on's ESPHome and with
min_version. ESP-IDF's error names stay on, and build_flags stay under
platformio_options, because ESPHome 2026.9's LVGL reads only those.

tools/check.sh: 478 Python tests, 19/19 C++, editor; --firmware PASS with
ESPHome 2026.6.2 (CYD 87.7 %), 2026.8.1 (88.3 %) and 2026.9.0 (86.4 %,
was 91.5 %). Both bench screens OTA'd and watched for half an hour;
ESP Screens as a local add-on on the Yellow built both profiles
(CYD 1,037 s first build, 41 s unchanged). Details:
docs/TEST_RESULTS_0289.md.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-09-19 12:35:49 +02:00
Max Gramser a8b4fabd75 Add real photos and a video of a Guition in use to the README (docs only)
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-09-19 09:32:10 +02:00
Max Gramser fcdea12c44 Keep every screen's Wi-Fi awake from the shared core, so Home Assistant's messages no longer wait for the router's next beacon (0.2.88)
packages/core.yaml sets wifi: power_save_mode: none. ESPHome merges it
under the screen's own wifi: block, which keeps the network, the password
and the hotspot, and the screen's own YAML still wins on the mode. The
YAML ESP Screens writes has had the line since app 0.2.24; screens with
an older or hand-written YAML ran ESPHome's ESP32 default light, and
their messages from Home Assistant waited 76-117 ms on the bench.

esphome config on the bench screens' Device Builder YAMLs: NONE for both
without a line of their own, LIGHT when the YAML says light. The bench
Guition, flashed from its Device Builder YAML: ping 15 ms average instead
of 117 ms. tools/check.sh: 474 Python tests (a new one keeps the core's
wifi: block to this one key), 19/19 C++, editor; firmware unchanged in
size (CYD 1,678,816 B, 91.5 %; Guition 2,055,280 B), since the checkout
profiles already had the line.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-09-19 09:06:53 +02:00
Max Gramser ff9d3af9f8 Show a spinner while a screen starts and while a camera loads, bring a camera's first picture sooner, and round the alert's camera picture (0.2.87)
Starting screen: until the first layout, render() keeps the status text
("Connecting to Home Assistant", "Waiting for ESP Screens") and a spinner
as one block in the middle of the page; the first layout deletes both.
The room label stays empty meanwhile, and ROOM_NAME defaults to "".

Camera: the full screen shows a spinner instead of "Loading image". The
screen asks when the camera opens and loads a link as soon as it comes
(camera_load, never under a finger) instead of waiting for the 250 ms
tick twice, and online_image reads 16 KB per loop instead of 4 KB. On the
bench Guition with the EZVIZ camera: cold 5.8 -> 4.55 s, warm 3.4 -> 2.06 s.

Alert picture: the image takes the frame's radius (18, the alert card's);
LVGL's software renderer clips it row by row, without a layer.

One spinner_create() makes the busy sheet's, the starting screen's and the
camera's spinner; theme role CAMERA_TRACK colours the camera's ring. The
README gets a row of camera pictures; docs/CAMERA.md, RELEASING.md and
TEST_RESULTS_0287.md describe the measurements.

Checked with tools/check.sh (473 Python tests, 19/19 C++, editor) and
--firmware: CYD 1,678,816 B (91.5 %, +1,312 B), Guition 2,055,280 B
(25.3 %). Host renders of both boards in both looks; four OTA builds on
the bench Guition Wallbox, which runs this firmware.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-09-19 08:50:08 +02:00
Max Gramser 2d343a450f Let the on/off switch on a wide tile switch, instead of sending the opposite of what it shows (0.2.86)
A tap on the On/off switch of a wide or full-page tile moved the knob to on
and back, and the light stayed off. Since firmware 0.2.59 control_event drew
the new position first (Tile::optimistic writes it into state) and then asked
key_action for the action, which read that new position: an off light got
light.turn_off, an on light light.turn_on. A tap on the tile itself was never
affected.

tile_controls::press_key chooses the action first and then shows the new
position; control_event uses it. Unit tests cover a light, a fan, a sensor
and a cover key.

Checked with tools/check.sh (471 Python tests, 19/19 C++) and compiled for
both boards: CYD 1,677,504 B (91.4 %, +16 B), Guition 2,054,640 B (25.3 %).
On Max's Guition Wallbox (OTA from this branch) every tap on the switch sent
the right action and Home Assistant's logbook followed.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-09-19 08:15:50 +02:00
Max Gramser 311fa2a7fd Show the screens and ESP Screens as they are now in the README pictures (docs only)
Rendered again from firmware 0.2.71 and the editor of 0.2.85 on the demo homes, with the render tooling
brought over to the core and board files of 0.2.84: the tile pages with 0.2.85's colours (a running timer
amber, a docked robot and idle scripts grey, the full-page speaker lit while it plays), the cards with the
icon edges of 0.2.75, and the editor with 48 tiles, the icon-left tiles of 0.2.76, Size and Page in the
tile drawer, Perform action on the curtains as the caption says, and every Screen settings row. The camera
pictures show a free Unsplash photo by Virginia Marinova, credited in the README. The two photos at the top
carry the current firmware on their screen: the page with scenes, scripts, the robot and the table lamp,
and the vacuum card with its cleaning mode.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-09-19 00:54:10 +02:00
Max Gramser 6fb60b34d2 Bring the guides up to date with the code of the last releases (docs only)
README_EXTENDED rendered everything from "Direct control" to "Override YAML" as raw text on
GitHub since 0.2.74: the full-page pictures ended without a blank line. It also gains the
media card, Page buttons, the ··· menu's Identify/Copy/Export/Import, Try it, and where
SCREEN_FIRMWARE_VERSION lives now. EASY_SETUP's settings table drops Show clock and gets
Back to page 1; SETTINGS.md points at web/src/store.ts and packages/core.yaml; GUITION.md
had the GT911 mirrored and cache settings that left the profile on 2026-09-12;
TROUBLESHOOTING still named TILE_COUNT and files deleted in 0.2.50; CALIBRATING put
Calibrate touch in ESP Screens instead of Home Assistant. RELEASING gets the compatibility
notes of 0.2.73 to 0.2.85 and the GitHub release step.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-09-19 00:11:40 +02:00
Max Gramser 9391d1b0ac 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>
2026-09-18 23:31:10 +02:00
Max Gramser d76461d774 Build every screen from one shared core plus a small file per board, the same firmware as before (0.2.84)
The two board profiles (5,000 lines each, 87 % the same text) become packages/core.yaml and one file per
board under packages/boards/: the hardware, a table of 84 sizes and font sizes, 18 hooks with the lines of C++
only that board adds inside a shared lambda, and the board's own sections. packages/cyd.yaml and
packages/guition.yaml keep their names and places (a screen installed from ESP Screens builds as before);
home-like-2432s028.yaml and guition-4848s040.yaml become the same entries for a checkout.

The firmware stays 0.2.70: the C++ ESPHome generates for each board, through the checkout profile and
through the GitHub package route, was compared line by line with the old profiles' (docs/TEST_RESULTS_0284.md).
tools/check_packages.py replaces tools/generate_packages.py; tools/profiles.py gives the tests and tools the
three files as one; docs/PROFILES.md says how the files fit together and how a board is added.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
2026-09-18 22:57:14 +02:00
Max Gramser e7e173d3b7 Give a lamp's modes a page: the effects, palettes, presets, speed and intensity of a WLED behind its colour card, with a drum picker and the effect's name on the tile (0.2.83)
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>
2026-09-18 21:38:20 +02:00
Max Gramser 86e6ce79fe Show the new page buttons in the README pictures: chevrons and page dots under the tiles
The pictures of tile pages still had the Previous and Next words and the "1 / 4" counter from
before 0.2.82. The 26 pictures that show the bar are rendered again from firmware 0.2.69 with the
chevrons and page dots, and pick up the smoother icons of 0.2.75 on the way. The Screen group of
the settings page gained a Page buttons row and now has a second page, so its picture shows the
first page with the pager, and its description says where the page buttons and the rotation went.

Rendered from the host firmware and the real add-on on the same demo homes as the earlier pictures.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-09-18 21:05:20 +02:00
Max Gramser ffe639e23c Let the page buttons make way: a Page buttons setting that gives their room to the tiles, chevrons and dots instead of words, and a warning in the editor for pages nothing leads to (0.2.82)
GitHub issue #9 asked to drop the Previous/Next bar when Go to page tiles do the navigation and to give the tiles the whole screen. Page buttons is a setting the screen owns (on by default): a row in the Screen group of the settings page, switch.<screen>_page_buttons in Home Assistant, and a row in the editor's Screen settings. Without the bar, and on a screen with one page, place_page moves and sizes the three rows so they reach the bottom margin (Guition 108 -> 122 px, CYD 52 -> 61 px); a card keeps its circle, name and state in its middle and the single analog clock keeps its dial. With page buttons and swiping both off, the editor says where the Go to page tiles lead and which pages that leaves out of reach.

The bar itself: each half of the band under the tiles is one key with an MDI chevron and lights up under a finger, and a dot per page sits between them; the screen's settings page uses the same pager. App 0.2.82, firmware 0.2.69.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-09-18 20:43:43 +02:00
Max Gramser 788f42da65 Fill a blind's slider with its closed part, like its card and Home Assistant's cover dialog (0.2.79)
On the tile (and the strip of a full-page blind) the small slider filled with the open part, while the blind's card
draws the blind hanging from the top: a closed blind looked open on one and closed on the other. Now both fill with
the closed part and dragging right closes; the text still gives the position (open %). The editor's mockup follows.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-09-18 17:30:52 +02:00
Max Gramser 1a6308aba7 Fix what a full test round of today's releases found: a ticking single clock, a switch that works in standby, no taps from a swipe (0.2.78)
A test and code-analysis round of 0.2.72 to 0.2.76 (suites at every tag, sanitizers, ESP32 and GitHub builds, host
harnesses on both boards, the editor in a browser, best practice checked against ESPHome, LVGL, Home Assistant and
Vue) found these, fixed here with Max's choices for the product questions:

- Firmware 0.2.65: the second hand of a single analog clock moves again; on a page that is one full on/off tile the
  waking push also switches it; on the Guition a flick is never a tap and a finger that slides off a tile doesn't tap
  it; Previous/Next react to a firm press; the same Go to page tile may sit on several pages; a layout the screen has
  no memory for is refused instead of crashing; 64-bit redraw mask for 48 tiles; Montserrat 14 no longer built.
- App: Save refuses a layout too long for one message or too big for eight pages; an offline screen keeps its
  firmware version from the device registry; HA refusals reach the editor; 128 KB requests; changelog out of the
  live stream; cached hashed assets; tini as init and a clean stop; changelog parsing without asterisks or crashes.
- Editor: clicking the open screen keeps unsaved edits, edits during a save stay unsaved, a Page row and phone
  dragging to other pages, repeated page tiles, limits from the server, HA's error messages, a type-checked build.
- tools/check.sh + GitHub Actions + a CYD flash budget; docs match 48 tiles and the new editor.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-09-18 17:25:23 +02:00
Max Gramser c09e4e333f Add the Studio 1 hardware results to the 0.2.77 test report
Docs only, no version change: the add-on update and the OTA to firmware 0.2.64,
the media card with a real Sonos cover, and an alert with a camera over it.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-09-18 17:23:38 +02:00
Max Gramser 079ffcf059 Load one picture at a time on a Guition: an alert's picture before a media tile's cover (0.2.77)
A download shares ESPHome's loop with touch and drawing. An alert already
closes every card, and the card's cover with it; a media tile over the whole
page stays under the alert. Its cover now waits while the alert's picture is
announced, loading or due for a retry, and an alert picture that arrives while
a cover is on its way (or a dropped cover's download is still being closed)
starts right after it. The host harness checks all three cases on the Guition.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-09-18 17:15:54 +02:00
Max Gramser f13d8ad0ed A media card like a phone's now playing, with the album cover on a Guition (0.2.77)
The card behind a media tile shows the album cover, the title, the artist and
the album, a progress bar that runs while the track plays with the times at its
ends, round keys for previous, play or pause and next, and a volume row with a
mute key, a wide slider and the percentage. Keys the player lacks stay faded,
an off player shows one power key, a stream without a length shows no bar, and
the CYD shows the player's icon in the cover's place. A media tile over the
whole page is the same card under the tile's head. media_card.h holds the
geometry, tests/test_media_card.cpp checks every shape.

The cover comes the way camera images do: the screen asks with the size and
the colour behind the corners, the app fetches the picture from Home Assistant,
cuts it square, rounds the corners over that colour and serves it on port 8098;
the Guition loads it once and asks again only when the picture's mark in the
state changes. Firmware 0.2.64.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
2026-09-18 17:04:44 +02:00
Max Gramser bdb1f12c55 Draw a tile on the editor's mockup the way the screen does: the CYD shows the whole tile again (0.2.76)
Both boards draw a normal tile with the icon on the left and the name and value beside it;
the Vue editor stacked icon, name and value in one column. On a CYD mockup a tile is 47 px
high and that stack needed 58 px (63 for a watch card), so the value line was cut in half and
a big value hid the name. A single tile is now a row (.head: icon + .tx), a watch card puts
the name row on top and the number under it, and the small slider runs underneath; on a CYD
a tile with a slider uses the screen's 4 px padding and 8 px slider. The Guition mockup
follows the screen the same way.

App 0.2.76, firmware stays 0.2.63. Test results in docs/TEST_RESULTS_0276.md.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-09-18 09:56:01 +02:00
Max Gramser 261fa82c7d Draw the icons with sixteen shades: the power ring on the CYD is a ring again (0.2.75)
The Material Design Icons fonts of both boards had no bpp, so ESPHome rendered them at
its default of one bit per pixel while the text fonts already had four. On the CYD, at
18 and 28 px, a thin stroke such as the ring of mdi:power came out lumpy and uneven, and
every other icon had a ragged edge. All four icon fonts of both profiles now say bpp: 4;
the icon generator and its test keep that line. Costs the CYD 95 KB of flash (90 % of
the update slot in use on top of 0.2.74), no RAM.

App 0.2.75, firmware 0.2.63. Test results in docs/TEST_RESULTS_0275.md.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
2026-09-18 08:48:31 +02:00
Max Gramser bb25353089 Forty-eight tiles, a tile over the whole page and tiles that go to a page (0.2.74)
Max asked for many more tiles, a tile that takes the whole page as a light
switch you push without looking, and tiles that go to a page. The limit is
one tile per slot of the eight pages, 48, and the firmware keeps its tile
list on the heap sized to the layout (PSRAM on a Guition). A tile's size can
be `full`: one big button that lights up in the state colour while on, or the
double-width card's head with its small slider, direct controls or graph at
the bottom and the value the double-width card had no room for in between;
the clock, the forecast (with an hours strip) and the sun path fill the page.
Navigation tiles are the built-in entities screen.page_1 to screen.page_8:
an arrow or a chosen icon, the name and "Page n", a tap opens that page.
The app sends the three only to firmware 0.2.62+, the editor (the Vue port of
this round by the editor session, 00c9a4e) offers Normal / Double-width /
Full page and "Goes to page", and Claude in Home Assistant gets size: full and
the page tiles. Built-in tiles now send a chosen icon as its codepoint.

Found and fixed by the new host harness before release: the one-second tick
moved the analog clock's second hand (part 18) on a full forecast's hour label
during a page switch and corrupted it. Firmware 0.2.62; both C++ and Python
suites, host harness 37/37 on both boards, hardware pass on both bench boards
in docs/TEST_RESULTS_0274.md.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
2026-09-18 08:44:44 +02:00
Max Gramser 1ed42dc425 Release 0.2.73: the Vue editor with live values, Identify, a test alert, layout copying and ⌘K
Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
2026-09-18 08:32:08 +02:00
Max Gramser 8d11de8a28 Test the editor with Vitest: grid and top bar rules, the store, and the components in jsdom
Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
2026-09-18 08:30:38 +02:00
Max Gramser 6148dfd211 Show live values on the mockup, blink a screen to identify it, try an alert, copy and share layouts (0.2.74)
The tiles draw what Home Assistant reports (a new /api/states answers for the tiles on the page); the ···
menu gets Identify (the screen's own show_alert with flash), Copy layout from another screen, Export and
Import as JSON; the Alerts page opens with Try it (/api/alerts/test, one screen or all); the library filters
by room and hides what is placed, with lit icons for what is on; ⌘K searches screens, entities and actions;
the Update badge lists what's new from the changelog (copied into the image) and a running update shows a
progress bar with the ESPHome stage and the last log line.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
2026-09-18 08:30:38 +02:00
Max Gramser ef8e94f6d1 Show the new editor in the README pictures
Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
2026-09-18 08:30:38 +02:00
Max Gramser 510ebdf885 Rebuild the editor as a Vue app: sidebar, pages side by side, tile settings in a drawer (0.2.74)
The page is now web/ (Vue 3 + Vite + TypeScript), built into screen_manager/app/static
with hashed file names; server.py serves index.html as built and /assets/. The Python
API, the data and the firmware are unchanged. Your screens sit in a sidebar, the pages
of a screen stand next to each other at the screen's own shape, the library sits on the
right, and a tile's settings slide in as a drawer while the mockup stays in view. New
screen, Firmware & USB, Alerts, Override YAML and Settings are pages of their own.
Fonts moved to web/src/assets; the tests read the source through tests/editor_sources.py.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
2026-09-18 08:30:38 +02:00
Max Gramser 9f5694b9eb Let the page buttons keep up with the finger: Next, Next, Next reaches page 4 (0.2.72)
The Previous and Next bars ran their tap through the tile guard, whose 600 ms
same-tile window (so one contact never fires a tile twice) dropped the second
and third tap of a quick Next, Next, Next. They now use accept_repeat, the
-/+ keys' rule since 0.2.25: every clean tap counts, only a contact within
150 ms of the last accepted tap on the same button is a bounce. The page fill
already dropped a fill under way when the next page was asked for. Firmware
0.2.61; test_cyd_ui.cpp covers the page buttons; host harness and check builds
in docs/TEST_RESULTS_0272.md.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
2026-09-18 07:29:23 +02:00
Max Gramser 2cb347964d Keep a small slider where the finger left it while the light fades towards it (0.2.71)
A light group's lamps fade, Home Assistant reports every step, and the tile's slider followed each one: after a drag it
jumped back to the old value and crept up. The Tile now holds the sent value (brightness, fan percent, volume) until
Home Assistant reports within 3 % of it, reports the entity off, refuses, or reports once and stays quiet for 1.5 s;
never longer than 8 s, and without any report the hold ends with the wait. A cover's position slider keeps following
the blind. Firmware 0.2.60; host checks 17/17 on both boards.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
2026-09-17 23:10:00 +02:00
Max Gramser 91a2445663 Let a tap look instant and keep the spinner for a command that really takes a while (0.2.70)
Home Assistant answered every command in 342-599 ms on a real installation,
yet a tile was busy for at least a second and up to six without a confirming
state. Now nothing is drawn for the first 400 ms, a tap that switches shows
the new stand at once as Home Assistant's own switch does, and the sheet
appears only for a slow command. Home Assistant's "it worked" answer ends the
wait 800 ms later, which covers a stop on a cover that already stands still,
and a wait without any answer ends after three seconds instead of six. The
cards' keys, sliders, chips and the -/+ edit now ask for an answer too, so a
refusal shows wherever a finger presses.

Firmware 0.2.59. A 200 ms LVGL timer runs only while a command is under way.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-09-17 22:26:38 +02:00
Max Gramser 42bf5811f7 Show the settings on the screen, tap actions and Override YAML in the README
The README pictures now match the released screens and ESP Screens: the light pages had the sliders
and clock from before 0.2.43, the editor showed firmware 0.2.34, and the vacuum and climate cards
carried Dutch names. New pictures show the settings page on the screen with Dark mode, the Screen
settings cards, Perform action in the tile settings and Override YAML; the full reference gets the
same and short notes on tap actions, Home Assistant's words and icons, and Override YAML.

Rendered from the host firmware and the real add-on on the demo home, like the earlier pictures.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-09-17 16:04:37 +02:00
Max Gramser 66b1590184 Download a screen's firmware and put it on from your own computer (0.2.68)
GitHub issue #8: Home Assistant on a server or virtual machine is out of
reach of the screen. New screen and Firmware & USB get a Download choice:
ESP Screens builds the profile's firmware as always and offers ESPHome's
factory image, which the owner flashes with ESPHome Web in Chrome or Edge.

- Firmware: a download job compiles without uploading; only the image of
  the profile's latest successful build in this process is served, a new
  job withdraws it, and a build without a factory image fails.
- USB on the Home Assistant machine stays first in both lists, also before
  a board is plugged in; Download and Later stay chosen once picked.
- The not-yet-in-Home-Assistant card knows a downloaded screen.
- The device name pattern is valid again under Chrome's v flag.
- Docs: README, DOCS, EASY_SETUP, DOCKER, TROUBLESHOOTING. App only;
  firmware stays 0.2.58.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-09-17 16:00:06 +02:00
Max Gramser 6809d3b941 Take what a tile can do, its tap actions, words and icons from Home Assistant (0.2.67)
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>
2026-09-17 15:41:38 +02:00
Max Gramser d60a0f122b Show who is at the door: camera images on the Guition (0.2.66)
An alert from esp_screens_show_alert takes a `camera` (a camera.* or image.* entity): a Guition with firmware
0.2.57 shows that moment's picture across the top of the card, and a tap opens the camera full screen. A camera
or image tile opens the same full-screen view, refreshed every four seconds at a steady pace.

ESP Screen Manager fetches the snapshot with its own access, sizes it for the screen and serves a 24-bit BMP
under a random, short-lived link on port 8098; the screen loads it with ESPHome's online_image and holds no
Home Assistant token. BMP because ESPHome decodes it per chunk, where a full-screen JPEG held the loop 0.6 s.
The CYD keeps its alerts without the picture and gets no camera tiles.

The Guition also builds with ESPHome 2026.8+ again: backlight_fade.h derived from ESPHome's LEDC output, which
2026.8 made final, so the backlight now dims through ESPHome's own light transition.

Tested on the bench boards and a local add-on on the Home Assistant Yellow; docs/TEST_RESULTS_0266.md.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-09-17 15:31:11 +02:00