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>
This commit is contained in:
Max Gramser
2026-09-19 00:11:40 +02:00
parent 9391d1b0ac
commit 6fb60b34d2
12 changed files with 222 additions and 106 deletions
+5 -5
View File
@@ -28,8 +28,8 @@ Don't configure wallbox relays as part of display support.
# Working instructions for LLMs and developers
This project drives an ESP32-2432S028 with ILI9341 + XPT2046 (320×240,
LVGL 90°). Read README.md, README_EXTENDED.md and docs/ before installing. The owner can
This project drives two boards: the CYD ESP32-2432S028 with ILI9341 + XPT2046 (320×240,
LVGL 90°) and the Guition above. Read README.md, README_EXTENDED.md and docs/ before installing. The owner can
physically tap; an agent cannot replace that with software coordinates.
## Installing a new screen
@@ -69,7 +69,7 @@ and screens for lookups and tests. If that file is missing you are not on his ma
another header; docs/THEME.md is the recipe, tests/test_theme.py and tests/test_theme.cpp guard it.
- Screen settings live in one table: `components/smart_display/settings_screen.h` draws the
page on the screen, `SETTING_RULES` in the add-on validates the same keys. Firmware 0.2.49+
owns them: every writer (the page, the entities in both profiles) goes through
owns them: every writer (the page, the entities in `packages/core.yaml`) goes through
`settings_screen::set()`, and the add-on changes them through the entities in
`SETTING_ENTITIES`, never through the layout message. docs/SETTINGS.md is the end-to-end
recipe for adding one; never widen the eleven-key `settings` block older firmware insists on.
@@ -80,8 +80,8 @@ and screens for lookups and tests. If that file is missing you are not on his ma
filtered physical ADC values. Don't apply the affine correction twice, in both the driver and the UI.
- The calibration wizard assumes swap_xy=false, mirror_x=true, mirror_y=false,
and LVGL 90°. A changed orientation also requires a new projection/tests.
- Run `tools/check.sh` on code changes (the Python tests, every C++ test, both generators, the
editor's tests, types and build); on a firmware change also `tools/check.sh --firmware`, which
- Run `tools/check.sh` on code changes (the Python tests, every C++ test, the package check, the icon
generator's check, the editor's tests, types and build); on a firmware change also `tools/check.sh --firmware`, which
compiles both boards and applies the CYD's flash budget (docs/RELEASING.md step 2). CI runs the
same script. Firmware tests and hardware acceptance are different checks.
- `diagnostics/run_ui_test.py` renders without HA actions; don't touch the screen
+3 -2
View File
@@ -202,8 +202,9 @@ For Home Assistant OS with Apps/Add-ons on **aarch64 or amd64**:
</p>
<p align="center"><sub>New screen (step 3) and choosing your tiles (step 5).</sub></p>
You can install new firmware later from **Firmware & USB → Wi-Fi / OTA** in the sidebar.
For an existing screen, always use the existing profile; creating a new
New firmware goes on over Wi-Fi with the **Update** button of a screen in ESP Screens, or by itself
every night if you turn that on under **Settings**; **Firmware & USB → Wi-Fi / OTA** in the sidebar
installs it by hand. For an existing screen, always use the existing profile; creating a new
installation profile generates new keys.
The [complete installation guide](docs/EASY_SETUP.md) walks through every step in more detail.
+45 -23
View File
@@ -23,13 +23,15 @@ on the screen itself, and how updates work.
title; a number that's too long is truncated with an ellipsis, the unit stays visible.
- **Pastel backgrounds per tile:** choose red for an all-off script,
green for all-on, or any other color. The title and status stay dark and
readable. The color also appears in the screen preview; **Default** restores
readable; in Dark mode the colour turns deep and the text light. The color also
appears in the screen preview; **Default** restores
the normal colors. Requires firmware 0.2.10 or newer. **None** drops the card
entirely: the content then sits at the same size directly on the screen background
(firmware 0.2.16).
- **Clock:** digital or analog. The analog clock has tick marks at 12, 3, 6, and 9
and, on a single tile, shows a calendar block (weekday, day, month) next to the
dial; double-width shows the digital time with the date beside it.
- **Clock:** digital or analog. The analog clock has a mark for every hour (numerals at 12, 3, 6,
and 9 on the Guition) and a red second hand while the screen is awake. On a single tile it shows
a calendar block next to the dial (weekday, day and month; the CYD the day and month); double-width
shows the digital time with the date beside it, and a full-page clock is the dial alone.
- **Light control:** brightness, rainbow color, and white temperature according to
the light's capabilities. Open the detailed control with a long touch.
- **Effects (firmware 0.2.70+):** a light that offers effects (a WLED, a Hue with
@@ -50,8 +52,9 @@ on the screen itself, and how updates work.
sunset), a **timer** (`timer.*`, tapping starts or pauses it), and
**presence** (`person.*`). Pick them in the library like any other tile, or
drag them straight into the screen mockup; **Double-width** is an option for every tile, and so is
**Full page** (firmware 0.2.62+): the tile takes the whole page and is one big button that lights up
in its state colour while on, so a screen by the door switches the light when you push anywhere on it.
**Full page** (firmware 0.2.62+; not for a Go to page tile): the tile takes the whole page and is
one big button that lights up in its state colour while on, so a screen by the door switches the
light when you push anywhere on it.
Only something that can be off lights up: a light, switch, airco, fan, blind, speaker, robot, script,
timer, camera, person or binary sensor. Sensors, numbers, selects, scenes, the weather and the sun stay plain
(firmware 0.2.71+).
@@ -71,6 +74,7 @@ on the screen itself, and how updates work.
<img src="docs/images/cyd-full-menu.png" width="32%" alt="Navigation tiles on the CYD">
<img src="docs/images/cyd-full-climate.png" width="32%" alt="A full-page heating tile on the CYD with the mode keys at the bottom">
</p>
- **Direct control on double-width tiles** (firmware 0.2.19+), like the rows in
Home Assistant: temperature − / + or mode buttons (climate), a toggle (switch,
light, fan), start/stop/dock (vacuum), open/stop/close or a
@@ -101,12 +105,18 @@ on the screen itself, and how updates work.
cleans: **vacuum, vacuum and mop, or mop only** for robots that offer a cleaning mode in
Home Assistant (such as Roborock), then suction and water. Only the rows the chosen mode
uses are shown (app 0.2.46 / firmware 0.2.39).
Scenes, scripts, and buttons show when they last ran. A tile that's waiting on
Home Assistant shows a small spinner on a light overlay.
Scenes, scripts, and buttons show when they last ran. A tile that waits longer than
a moment on Home Assistant shows a small spinner over the tile (see below).
- **Cover card** for blinds, curtains, shutters, and garage doors, like Home Assistant's own:
a tall position slider on which the blind hangs from the top, a tilt slider over slats for
venetian blinds, open, stop, and close, and the battery of a battery-powered blind
(such as Motionblinds). A cover shows only what it supports (app 0.2.58 / firmware 0.2.50).
- **Media card** like a phone's "now playing" (app 0.2.77 / firmware 0.2.64): the album cover, the
title, artist and album, a progress bar with the elapsed and total time, previous, play or pause
and next, and a volume row with mute. Keys the player doesn't offer are faded, and a player that is
off shows a power key. A Guition fetches the cover through ESP Screens, like a camera picture
([docs/CAMERA.md](docs/CAMERA.md)); the CYD shows the player's icon in its place. A media tile of
size **Full page** is the same card on the page, with the keys and the volume working on the tile.
- **History card** for sensors, numbers, binary sensors, people, and switches, the way Home
Assistant shows history: a line with an axis in round steps and clock times for numbers,
with the highest and lowest moment, and a timeline with the time in each state for on/off,
@@ -118,9 +128,10 @@ on the screen itself, and how updates work.
(open/closed), the alarm, who's home, or when something or someone last
changed ("5 min ago", "Yesterday"). See [Top bar](#top-bar).
- **Screen settings:** standby time, normal and dimmed brightness,
night hours, **Dark mode** (firmware 0.2.54+), 24- or 12-hour clock, return to the home page,
and optional swiping between pages. Change them in ESP Screens, where they apply at once, or on the screen
itself. With firmware 0.2.49+ the screen keeps them, and every one of them is also an
night hours, **Dark mode** (firmware 0.2.54+), 24- or 12-hour clock, back to page 1 by itself
and on standby, optional swiping between pages, and **Page buttons** (firmware 0.2.69+): switched
off, the bar under the tiles goes and the tiles take its room. Change them in ESP Screens, where
they apply at once, or on the screen itself. With firmware 0.2.49+ the screen keeps them, and every one of them is also an
entity in Home Assistant, so an automation can switch **Night mode** or **Auto standby**
(firmware 0.2.41+), for example to keep a screen on while someone is home, turn **Dark mode**
on at bedtime (firmware 0.2.54+), and
@@ -128,14 +139,16 @@ on the screen itself, and how updates work.
See [Wake and sleep](#wake-and-sleep-from-an-automation).
- **Settings on the screen itself** (firmware 0.2.44+): hold the top bar for about a
second and a half and the screen opens its own settings page — brightness, night,
the clock, swiping, rotation, and what this screen is (name, IP address, firmware,
whether Home Assistant is connected, and Restart). Changes show up in ESP Screens
the clock, back to page 1, swiping, the page buttons, rotation, and what this screen is
(name, IP address, firmware, whether Home Assistant is connected, and Restart). Changes show up in ESP Screens
within a second. See [Settings on the screen](#settings-on-the-screen).
- **Guition rotation:** 0°, 90°, 180°, or 270°, directly from the management page.
Native LVGL rotation turns the display and touch together. The CYD keeps its fixed
orientation and its own calibration.
- **Read current data** (the ··· menu of a screen): what Home Assistant reports for every tile right now,
and how each tile is set.
and how each tile is set. The same menu has **Identify**, which blinks the screen so you know which one
it is (firmware 0.2.31+), **Copy layout from…** another screen, and **Export** and **Import** of a
layout as JSON (app 0.2.73); nothing reaches the screen before **Save & send**.
- **Override YAML per screen** (app 0.2.61): your own ESPHome YAML for one screen, such as another
display controller, kept through updates. See
[Updates and keeping your settings](#updates-and-keeping-your-settings).
@@ -230,7 +243,9 @@ data:
- **`flash`**: `true` makes the backlight blink four times when the alert arrives.
In ESP Screens, **Alerts** in the sidebar opens a cheatsheet with the exact action name for each screen,
a ready-to-paste example, and all fields, icons, and colors. Home Assistant asks for all seven fields; leave a field empty (`""`, `0`, `false`) if you
a ready-to-paste example, and all fields, icons, and colors. It starts with **Try it** (app 0.2.73): fill in
the same seven fields, choose one screen or all of them, and send a test alert.
Home Assistant asks for all seven fields; leave a field empty (`""`, `0`, `false`) if you
don't use it. A new alert replaces the current one. Every end is reported as the event
**`esphome.screen_alert`** with `action` (`ok`, `timeout`, `replaced`, or `remote`), `title`,
`screen`, and the `device_id` that Home Assistant adds, so an automation can wait for OK.
@@ -334,9 +349,10 @@ the Wake and Sleep of the same screen included.
## Customizing tiles and colors
Click a tile in the screen preview. Under **Pastel background**, choose a color,
such as red or green. Optionally adjust the name, click action, mini-slider, or large
value. Click **Save & send** to apply the changes.
Click a tile in the screen preview and its settings open in a drawer beside it. Under
**Pastel background**, choose a color, such as red or green. Optionally adjust the name, the
size, what a tap does (**On tap**), the small slider, or a large value. Click **Save & send**
to apply the changes.
After the first supporting firmware update, this requires no new flash.
<p align="center">
@@ -351,8 +367,9 @@ stay separately visible.
## Top bar
At the top of the editor, each screen has its **Top bar**: the name on the left, up to
six items on the right. **+ Add** offers the time, an analog clock, and the date (which
Tap the top bar of any page in the editor's preview and the drawer shows the screen's **Top bar**:
the name on the left, up to six items on the right. **+ Add** offers the time, an analog clock,
and the date (which
keep ticking on the screen itself, even without Home Assistant), suggestions from your own
home (temperature and power usage from the screen's room, the weather, how many people are home,
sunrise and sunset), and a search field for any entity, including a phone
@@ -396,7 +413,7 @@ Home Assistant, `esphome.<screen>_open_settings` opens it too (`page` 0 menu, 1
|---|---|
| Brightness | Brightness, Dark mode, Auto standby, Standby after, Standby brightness |
| Night | Night mode, Starts, Ends, Night brightness |
| Screen | 12/24-hour clock, back to page 1 by itself and after how long, also on standby, swiping between pages, rotation (boards that turn) |
| Screen | 12/24-hour clock, back to page 1 by itself and after how long, also on standby, swiping between pages, page buttons, rotation (boards that turn) |
| This screen | Name, IP address, firmware version, Home Assistant connected, Restart |
<p align="center">
@@ -474,14 +491,19 @@ See the [release history](screen_manager/CHANGELOG.md) and
**If you publish your own fork:** every push to GitHub is a release. Always also
bump the add-on version in `screen_manager/config.yaml` and log the change in
the CHANGELOG, otherwise the HA App store won't offer an update. A change to the
screen also gets a new `SCREEN_FIRMWARE_VERSION` in both board profiles.
screen also gets a new `SCREEN_FIRMWARE_VERSION` in `packages/core.yaml`, the one place both boards
take it from, and the same `FIRMWARE_VERSION` in `screen_manager/app/core.py`.
## Guides and installation help
- [Complete installation from ESP Screens](docs/EASY_SETUP.md)
- [ESP Screens with Home Assistant Container (Docker)](docs/DOCKER.md)
- [Guition hardware, mounting, and rotation](docs/GUITION.md)
- [CYD calibration and USB diagnostics](docs/CALIBRATING.md)
- [Instructions for developers and LLMs](AGENTS.md)
- [Camera images and album covers](docs/CAMERA.md)
- [Troubleshooting](docs/TROUBLESHOOTING.md)
- [Instructions for developers and LLMs](AGENTS.md), with [how a screen's YAML is put together](docs/PROFILES.md),
[settings](docs/SETTINGS.md), [colours and Dark mode](docs/THEME.md) and [releases](docs/RELEASING.md)
Give a developer or LLM a clean copy of this repository and, for example:
+5 -3
View File
@@ -17,7 +17,8 @@ panel, a loose connection, unstable power, or random outliers.
```yaml
packages:
display: ... # what ESP Screens put there
display: ... # what ESP Screens put there
local_overrides: !include kitchen.local.yaml # idem
calibration: !include calibration.yaml
```
2. Check the data cable and the USB port with `python -m serial.tools.list_ports`.
@@ -122,8 +123,9 @@ No `-s CALIBRATION_ON_BOOT true` is given here; the profile keeps it `false`.
Then check the real thing: the tiles, the navigation and a few taps in the corners.
Most screens never need this. A CYD shows its calibration on the screen itself when
it first starts, and ESP Screens has **Calibrate touch** for a repeat. This USB route
is for a panel that stays off after that, or for a measurement report.
it first starts, and its **Calibrate touch** button in Home Assistant (on the screen's
ESPHome device) starts it again. This USB route is for a panel that stays off after that,
or for a measurement report.
If calibration mode was opened only via the API, you can close it:
+2 -2
View File
@@ -83,8 +83,8 @@ under **Settings → Devices & services** in Home Assistant, and then choose the
ESPHome folder. `data/build` and `data/platformio` are caches.
- **Claude:** **Install for Claude Code** is meant for the Claude Code app on Home Assistant
OS. Use **Download for claude.ai** instead.
- **Camera images (Guition, app 0.2.66+):** the screens load camera pictures from port **8098**
of this host, on all its addresses, so keep that port open to the screens. The app uses Home
- **Camera images (Guition, app 0.2.66+):** the screens load camera pictures, and from app 0.2.77 the
album covers of the media card, from port **8098** of this host, on all its addresses, so keep that port open to the screens. The app uses Home
Assistant's own LAN address; when the screens reach this host under another one, set
`SCREEN_CAMERA_URL` (see below). The links are random and short-lived. [docs/CAMERA.md](CAMERA.md)
+35 -30
View File
@@ -117,7 +117,7 @@ Home Assistant without Wi-Fi sleep delay.
Select your screen, tap the bar at the top of a page to give the screen its name,
and search for entities in the **Library** on the right. It has domain filters with
colored icons. You can add up to 48 tiles, one for every slot
colored icons, a room filter, and **Hide placed**. You can add up to 48 tiles, one for every slot
(firmware 0.2.62+; see below for older firmware).
The screen preview shows their placement: two columns, six slots per page,
up to eight pages. Every tile has a fixed slot that only changes if
@@ -125,14 +125,15 @@ you drag it; empty slots stay empty, wherever you leave them. Drag a tile
onto an empty slot and it stays there; drag it onto another tile and the two
swap (the other tile takes the freed-up slot, or otherwise the nearest free
slot); everything else stays put. While dragging, the preview already shows where
everything will land; an empty page then stands ready below the last page. **Add
page** creates an empty page that's kept; an empty page gets
**Remove page**. Click an empty slot to place the next tile from the library
everything will land; drop a tile on the page after the last one to start a new page.
The pages stand side by side; **+ Add page** after the last one creates an empty page that's kept,
and an empty page gets **Remove page**. Click an empty slot to place the next tile from the library
there. Use the arrow keys to move a focused tile.
Click a tile and its settings open in a drawer on the right, with the preview
still in view: a custom name, click behavior, a mini-slider, a large value, a graph
(sensors), a weather forecast (weather), or the size: **Double-width** or **Full
page** (firmware 0.2.62+). A double-width tile for a climate, switch, light, fan,
(sensors), a weather forecast (weather), the size: **Double-width** or **Full
page** (firmware 0.2.62+), and on a screen with more pages the **Page** it is on, to move it without dragging.
A double-width tile for a climate, switch, light, fan,
vacuum, cover, media player, number, select, timer, scene, script, or button gets **direct
control** on the right, like the rows in Home Assistant (for example temperature − / +,
open/stop/close, volume with mute, a toggle); under **Direct control
@@ -161,6 +162,9 @@ Click **Save & send** to send your changes.
(firmware 0.2.58+).
- Long press a fan: speed, if the device supports percentages.
- Scene/script: tap to run; button/input_button: tap to press.
- Media player: tap for the media card with the cover (Guition), the keys, and the volume.
- Camera or image (Guition): tap for the picture full screen, refreshed every four seconds.
- A *Go to page* tile: tap to open its page.
- Sensor, number, binary sensor, and person: tap for the history card, for 1 hour,
24 hours, or 1 week. Long press a switch for its history. A sensor's graph on the tile
shows 1, 6, or 24 hours.
@@ -258,7 +262,8 @@ in your own YAML with an earlier release tag, without changing the keys.
automatically imported into the new management page.
HA Container without Supervisor has no App store. This installation guide
targets Home Assistant OS; the development server is not a production route for
targets Home Assistant OS; for Home Assistant Container, run the app next to it as in
[ESP Screens with Docker](DOCKER.md). The development server is not a production route for
a standalone public portal.
HA mechanisms used: [Ingress](https://developers.home-assistant.io/docs/apps/presentation/),
@@ -266,33 +271,33 @@ HA mechanisms used: [Ingress](https://developers.home-assistant.io/docs/apps/pre
[ESPHome packages](https://esphome.io/components/packages/).
## Adjusting screen settings (from 0.1.2)
## Adjusting screen settings
Update ESP Screen Manager to 0.1.2 and install the new firmware once
via your **existing** ESPHome device → Install → Wirelessly. Keep your own YAML
with Wi-Fi and keys. Then open the screen in ESP Screen Manager and its
**Screen settings** tab. A change there applies at once; there is nothing to save.
After this, changes to these settings don't need a new firmware flash.
Open the screen in ESP Screens and its **Screen settings** tab. A change there applies at
once; there is nothing to save, and no firmware flash is needed. The same settings are on the
screen itself (hold the top bar, firmware 0.2.44+) and, with firmware 0.2.49+, on the screen's
device in Home Assistant ([SETTINGS.md](SETTINGS.md)).
| Setting | Options | Default |
|---|---|---|
| Auto standby | On/off | On |
| Standby after | 1–1440 minutes after the last touch | 10 minutes |
| Normal brightness | 5–100% | 100% |
| Dark mode | On/off: black page, graphite cards, firmware 0.2.54+ | Off |
| Auto standby | On/off | On |
| Standby after | 1–1440 minutes after the last touch | 10 minutes |
| Standby brightness | 0–100%, capped at normal brightness | 20% |
| Night mode | On/off; applies during standby | On |
| Night start/end | Hour and minute, can span midnight | 22:00–07:00 |
| Night brightness | 0–100%, capped at normal brightness | 10% |
| Show clock | On/off | On |
| Time format | 24 or 12 hour, without AM/PM | 24 hour |
| Return to page 1 | Also closes detail menus on standby | Off |
| Clock | 24 or 12 hour; the clock shows no AM/PM | 24 hour |
| Back to page 1 | Closes an open card and goes back to page 1 after 30 seconds to 60 minutes without a touch, firmware 0.2.44+ | On, 2 minutes |
| Also on standby | Standby goes back to page 1 too (it always closes an open card) | Off |
| Swipe between pages | Native horizontal swipe, firmware 0.2.7+ | Off |
| Page buttons | Off: no buttons under the tiles, the tiles take their room, firmware 0.2.69+ | On |
| Guition rotation | 0°, 90°, 180°, 270°, firmware 0.2.9+ | 0° |
Home Assistant shows the same settings on each screen's ESPHome device: the switch
**Auto standby** (firmware 0.2.41+) and the numbers **Standby after**, **Normal brightness**,
Home Assistant shows these settings on each screen's ESPHome device, under *Configuration*:
with firmware 0.2.49+ every one of them, older firmware the switch **Auto standby**
(firmware 0.2.41+) and the numbers **Standby after**, **Normal brightness**,
**Standby brightness** and **Night brightness**. Changing them there, for example from an
automation, also changes them in ESP Screens and keeps them after a restart. Turning Auto
standby off wakes the screen and keeps it on; turning it on counts the standby time from
@@ -330,18 +335,18 @@ Night hours use the ESPHome device's timezone and the time from HA.
Without a valid time, the screen uses the regular standby brightness; matching
start and end times turn the night window off. At 0%, only the
backlight turns off: this is not deep sleep and not a screensaver.
The first tap wakes the screen without controlling a device.
The first tap wakes the screen without controlling a device, except on a page that is
one full-page switch (firmware 0.2.65+): there the waking push also switches it.
The add-on stores everything per screen in its persistent data. The screen also
stores the last received settings in preferences; ESPHome batches those
write operations (normally up to a minute). So don't unplug the power right after
saving. Existing CYD calibration, tiles, API, and OTA keys are preserved.
An offline screen gets the changes as soon as it comes back. Regular HA status
updates don't wake the screen and don't reset the standby timer.
With firmware 0.2.49+ the screen owns its settings and keeps them in its preferences;
an offline screen shows them as unknown in ESP Screens and takes no changes until it is back.
Older firmware gets them from the add-on's persistent data, also as soon as it comes back.
ESPHome batches the preference writes (normally up to a minute), so don't unplug the power
right after a change. Existing CYD calibration, tiles, API, and OTA keys are preserved.
Regular HA status updates don't wake the screen and don't reset the standby timer.
With older firmware, the management page shows that an update is needed first.
The tiles remain usable. Manual YAML profiles keep using their substitutions;
to manage through this app, use the Easy Setup package.
A setting that needs newer firmware than the screen has doesn't show in ESP Screens until
the screen is updated. The tiles remain usable.
The current Guition uses the native ST7701S configuration; see
[the hardware comparison](GUITION_FACTORY_REFERENCE.md). Settings and
+26 -19
View File
@@ -1,6 +1,6 @@
# Guition ESP32-S3 4-inch wallbox — 480 × 480
This branch adds a separate profile for the **Guition 4848S040** with an
The **Guition 4848S040** has a board file of its own, next to the CYD's, for its
ST7701S RGB display and **GT911 capacitive touch**, ESP32-S3, 16 MB flash, and
8 MB octal PSRAM. The name/2mm wall plate also describes the enclosure; always
check the electronics. This profile doesn't configure any relay.
@@ -32,7 +32,9 @@ Install Guition firmware 0.2.9 and ESP Screen Manager 0.2.9. Open the screen
in the management page, open the **Screen settings** tab, and choose 0°, 90°,
180°, or 270° (clockwise) under **Rotation**. It applies at once; there is
nothing to save. After that, a firmware flash is no longer needed to change the
angle. The setting is kept in the app data and on the screen after a restart.
angle. The screen keeps the angle after a restart; it can also be changed on the
screen's own settings page (Screen) and, with firmware 0.2.49+, as
`select.<screen>_rotation` in Home Assistant.
This uses native ESPHome/LVGL rotation for both display and touch, with no changes
to the panel initialization or GT911 mirroring. After mounting, physically check the
@@ -40,11 +42,13 @@ four corners and navigation; a render test doesn't test touches. The option is
only visible for the Guition once its new firmware has been discovered by HA.
The CYD stays on its existing orientation with its own calibration.
Six tiles of **218 × 108 pixels** per page, 12px spacing, and a
separate navigation strip. In ESP Screen Manager, up to 48 tiles fit across up to
eight pages (firmware 0.2.62+; twenty over four pages before); navigation disappears
at six or fewer. The current interface has a light gray background, white cards,
and colored domain icons. From 0.2.10, you can choose a pastel background with
Six tiles of **218 × 108 pixels** per page, 12px spacing, and the page buttons
below them. In ESP Screen Manager, up to 48 tiles fit across up to
eight pages (firmware 0.2.62+; twenty over four pages before); the page buttons disappear
at six or fewer, or with **Page buttons** off, and the tiles then grow to 218 × 122
(firmware 0.2.69+). The interface has a light gray background, white cards,
and colored domain icons; **Dark mode** (firmware 0.2.54+) turns it black with graphite
cards. From 0.2.10, you can choose a pastel background with
dark text per tile. Standby starts after ten minutes without touch by default and
is adjustable in the management page.
The backlight dims through ESPHome's own light transition (1.5 s to standby, 80 ms to
@@ -103,20 +107,20 @@ which shows the GT911 measurement screen right after the USB upload. After
checking, rebuild/reflash without that override. This compatibility name only
opens a pixel test; it doesn't perform any ADC calibration.
On the tested panel, both GT911 axes are mirrored: `TOUCH_MIRROR_X` and
`TOUCH_MIRROR_Y` are set to `true`. The default is `LVGL_ROTATION: "0"`. For a different mounting, set the
desired LVGL rotation and give the wizard the same value, for example
`--rotation 90`. Check every corner; only change the GT911 `TOUCH_SWAP_XY` /
`TOUCH_MIRROR_X` / `TOUCH_MIRROR_Y` if the physical measurement requires it.
On the tested panel, the GT911 needs no transform: `TOUCH_SWAP_XY`, `TOUCH_MIRROR_X` and
`TOUCH_MIRROR_Y` are all `false` in the board file, and the default is `LVGL_ROTATION: "0"`.
For a different mounting, choose the rotation under **Screen settings** (or on the screen) and
give the wizard the same value, for example `--rotation 90`. Check every corner; only change
the GT911 `TOUCH_SWAP_XY` / `TOUCH_MIRROR_X` / `TOUCH_MIRROR_Y` if the physical measurement requires it.
## HA and acceptance
Add the new device via the ESPHome integration (name/IP, port 6053,
API key from secrets), then choose its tiles in ESP Screens.
Add the new device via the ESPHome integration (name/IP, port 6053, the
API key from the screen's profile, which the New screen window also shows), then choose its tiles in ESP Screens.
```sh
python diagnostics/run_ui_test.py --host wallbox-kitchen.local --name wallbox-kitchen
python -m unittest discover -s tests -p 'test_*.py'
tools/check.sh
```
Also go through the physical checks, using the GT911 wizard instead of the XPT2046
@@ -157,9 +161,12 @@ committed or exported. Recovery happens at address 0, with the same
## RGB memory settings
The pixel clock is set to 16 MHz: on the test board, this removed the faint
flicker seen at the 12MHz setting. For the RGB bounce buffer, code and
constant data run from octal PSRAM, with a 64KB data cache and 64-byte
cache lines; RGB stream recovery happens on VSYNC. These settings
follow [Espressif's RGB LCD recommendations](https://docs.espressif.com/projects/esp-idf/en/v5.5.4/esp32s3/api-reference/peripherals/lcd/rgb_lcd.html).
flicker seen at the 12MHz setting. Code runs from the octal PSRAM (80 MHz,
`execute_from_psram`), and the panel otherwise uses ESPHome's own `st7701s`
defaults with the manufacturer's timings. The first profile also set a 64KB data
cache, 64-byte cache lines and RGB stream recovery on VSYNC, after
[Espressif's RGB LCD recommendations](https://docs.espressif.com/projects/esp-idf/en/v5.5.4/esp32s3/api-reference/peripherals/lcd/rgb_lcd.html);
those went when the native configuration proved clean without them
([the comparison](GUITION_FACTORY_REFERENCE.md)).
Physically check for occasional glitches under Wi-Fi/render load; a
software snapshot can't prove a disturbance in the panel signal.
+4 -2
View File
@@ -40,8 +40,10 @@ the board file replaces the core's. `esphome config home-like-2432s028.yaml` sho
with capacitive touch: the Guition) to `packages/boards/<board>.yaml` and change its hardware sections.
2. Fill the sizes table for the new resolution, and go through the hooks: keep, change or empty each one.
3. Add `packages/<board>.yaml` and `<board>.yaml` after the existing entries, `<board>` to `ENTRIES` in
`tools/profiles.py` and to `installation_yaml()` in `screen_manager/app/core.py`, and a `BANDS` entry to
`tools/render_topbar.py`.
`tools/profiles.py` and to `REFS` in `screen_manager/app/core.py` (the boards `installation_yaml()` writes a
profile for), and a `BANDS` entry to `tools/render_topbar.py`. The add-on and the editor still know two boards,
a Guition or not: the board a screen is (`core.py`), `ALERT_LIMITS`, the camera sizes in `camera_feed.py`, and
the editor's New screen choices and `BAR_METRICS` (`web/src`) need the new board too.
4. `python3 tools/check_packages.py`, `esphome config <board>.yaml`, `tools/check.sh --firmware`.
The tiles per page (two columns of three) are still fixed in the firmware, the add-on and the editor
+80 -4
View File
@@ -6,7 +6,7 @@
The old Guition branch is no longer updated; all board work goes to main.
- `screen_manager/config.yaml` holds the app version. Bump it on every app release.
A Git push alone isn't enough to offer an existing app an update.
- The app image contains only code. Layouts live in `/data/screens.json`
- The app image contains only code (and the CHANGELOG, for the Update badge's What's new). Layouts live in `/data/screens.json`
(`version: 1`, `screens: {...}`). An update/rebuild preserves this volume data.
- The device's own ESPHome YAML contains the name, Wi-Fi references, and unique API/OTA keys.
Shared packages contain no secrets, fixed owner entities, or Wi-Fi.
@@ -61,10 +61,12 @@
firmware against `FIRMWARE_VERSION`, keeps the CHANGELOG headings unique and newest first, and checks
that every `fonts/...` file the packages fetch from GitHub is in the tree.
5. Commit and push main (the only release branch). Create an immutable tag
`screens-vX.Y.Z` from the same commit. Test the remote YAML in an empty folder:
`screens-vX.Y.Z` from the same commit, and a GitHub release on that tag with the release notes in English
(`gh release create screens-vX.Y.Z --notes-file ...`). Test the remote YAML in an empty folder:
all components/fonts must be fetchable via GitHub.
6. The user checks the App store for updates and updates ESP Screen Manager.
For new screen features: existing ESPHome device → Install → Wirelessly.
For new screen features: **Update** on the screen in ESP Screens (or the nightly round); ESPHome Device
Builder's Install → Wirelessly on the existing device works too.
The existing YAML stays in place; `refresh: 0s` fetches current code on every build.
## Local development
@@ -183,7 +185,8 @@ new field is needed for it. No changed preferences or keys.
`FIRMWARE_VERSION` in `screen_manager/app/core.py` is the firmware that belongs to this
app; `tests/test_updates.py` requires it to equal
`SCREEN_FIRMWARE_VERSION` in both board profiles and packages. Bump them together.
`SCREEN_FIRMWARE_VERSION` in both board profiles and packages (since app 0.2.84 one line in
`packages/core.yaml` that every board and package takes). Bump them together.
A screen with a lower `Schermfirmware` gets an update offer; a build
fetches `main`, so publish firmware and app in the same commit.
@@ -216,6 +219,42 @@ icons sit off-center in the browser).
The `MDI_GLYPH_*` substitutions are retired: `TILEn_ICON` in manual
profiles must come from the set. No changed preferences or keys.
### Compatibility 0.2.85 / firmware 0.2.71
Tile colours as Home Assistant draws them. No protocol, storage or editor change: the state messages are the same as
0.2.84's, and the firmware works the colours out from what it already receives.
- Firmware: `Tile::active()` is a port of Home Assistant's `stateActive()` for the domains a tile shows, and
`render_slot` greys every tile that is not active (`Tile::slider_active()` keeps a closed blind's slider coloured).
Only `Tile::lights_up()` tiles, those that can be off, light up over a whole page. `tile_controls::accent()` replaces
`runtime_tiles::domain_accent()` and follows `stateColorCss()`; `theme.h` gained the extra Home Assistant colours. An
airco that is off reads "Off", with the current temperature when it reports one.
- App: `header_bar.ALARM_CLASSES` is Home Assistant's list of eleven red classes, the same list the firmware uses.
- The editor's mockup still draws icons in one colour. Details: docs/TEST_RESULTS_0285.md.
### Compatibility 0.2.84 (firmware stays 0.2.70)
The two board profiles became `packages/core.yaml` plus a board file under `packages/boards/`, put together by the
entry files (docs/PROFILES.md). No firmware, protocol or storage change: `packages/cyd.yaml` and `packages/guition.yaml`
keep their names and places, so every screen's own YAML (`files: [packages/<board>.yaml]`) builds as before, to the same
code (the one-to-one check in docs/TEST_RESULTS_0284.md). `SCREEN_FIRMWARE_VERSION` is one line in the core.
`tools/check_packages.py` replaces `tools/generate_packages.py`, and `tools/profiles.py` gives the tests and tools the
three files as one text.
### Compatibility 0.2.83 / firmware 0.2.70
A light's effects page. Additive in protocol version 1; storage unchanged.
- Wire: a light's state carries `effect`, and its `x` block `rows` (the select entities of the light's device:
`e`, `n`, `s`, `c`, `i`) and `nums` (its number entities: `e`, `n`, `lo`, `hi`, `st`, `v`, `i`), built by
`light_effects.rows` from what Home Assistant lists for the device. Older firmware ignores them.
- A picker asks for its names with the event `esphome.screen_options` (`entity`, `page`). The app answers only then,
and only for a light on that screen's layout or a select on its device, with `{op: options, e, i, n, o}`: one page of
names per message, under the 4096-byte limit. Firmware before 0.2.70 never asks, so it never gets an `options`
message.
- Firmware: `effects_page.h`; `Extra` gains `effect`, `option_rows` and `number_rows`. A hidden `roller_seed` makes
ESPHome compile LVGL's roller (CYD +20,288 bytes). Details: docs/TEST_RESULTS_0283.md.
### Compatibility 0.2.82 / firmware 0.2.69
Page buttons (GitHub issue #9): a setting the screen owns, `page_buttons`, on by default. It has a preference record
@@ -239,6 +278,15 @@ without the entity shows no row for it.
swiping are both off and the Go to page tiles leave a page out of reach, or give it no way back to page 1. The
warning shows above the pages and under the Screen card.
### Compatibility 0.2.79 to 0.2.81 / firmware 0.2.66 to 0.2.68
Firmware only (the app raises `FIRMWARE_VERSION`); no protocol or storage change, and an older app drives this firmware
as before. 0.2.79 fills a blind's small slider with its closed part, on the screen and in the editor's mockup. 0.2.80
takes a slider let go within `SLIDER_EDGE_SNAP_PX` of the left or right glass edge as its end (a size in the board file:
Guition 67 px, CYD 20 px since 0.2.81; 0 turns it off). 0.2.81 gives a compact card's whole area to its small slider,
keeps a slider's drag from turning the page, and no longer drops a second slider send within the 600 ms tap window.
The CHANGELOG has the details.
### Compatibility 0.2.78 / firmware 0.2.65
Repeated navigation tiles: the same `screen.page_<n>` may sit on several pages of one screen. Firmware 0.2.65 accepts
@@ -267,6 +315,26 @@ The app sends a repeat only to 0.2.65+ (`PAGE_TILE_REPEAT_MIN_FIRMWARE` in `min_
uses aiohttp's `handle_signals`.
- Editor: `npm run build` type-checks first (`vue-tsc --noEmit`), `devEngines` pins Node. Storage unchanged.
### Compatibility 0.2.77 / firmware 0.2.64
The media card. Additive in protocol version 1; storage unchanged.
- Wire: a media player's `x` block carries `artist`, `album`, `dur` and `pos` (seconds), `at` (the epoch of
`media_position_updated_at`) and `pic`, a short mark of the picture (`core.media_extras`). Older firmware ignores them.
- A Guition on 0.2.64+ asks for a cover with the event `esphome.screen_camera` plus `size` (48-320 px) and `bg` (six hex
digits of the colour behind the rounded corners). The app answers `{op: camera, t: cover, e, u}` with a link on port
8098, or an empty `u` for a player without a picture. It serves covers only to a Guition on 0.2.64+
(`COVER_MIN_FIRMWARE`) and only for players on that screen's layout; the CYD never asks.
- Firmware: `media_card.h` (the card's geometry, free of LVGL), `render_media_detail` and `render_media_full`, and one
image buffer shared by the camera, the alert's picture and the cover, so one picture loads at a time. Details:
docs/TEST_RESULTS_0277.md and docs/CAMERA.md.
### Compatibility 0.2.75 and 0.2.76 / firmware 0.2.63
0.2.75 draws the icon fonts at four bits per pixel (`bpp: 4`), like the text fonts: firmware only, 108 KB more flash
on the CYD. 0.2.76 changes only the editor's mockup, which now draws a tile's icon on the left as the screens do. No
protocol or storage change.
### Compatibility 0.2.74 / firmware 0.2.62
Forty-eight tiles per screen, a tile over the whole page (`size: full`) and navigation tiles (`screen.page_1` to
@@ -298,6 +366,14 @@ Supervisor restores the version and its data together).
(`tileLimit()`), the tile sheet has Size Normal / Double-width / Full page and, for a page tile, "Goes to page"
(which swaps the entity). Storage unchanged: `size` is one more value of an existing option.
### Compatibility 0.2.73 (firmware stays 0.2.61)
The editor became a Vue 3 + Vite app in `web/`, built into `screen_manager/app/static` (see Local development). The
add-on's API only gained `GET /api/states` (the mockup's live values, at most sixty entities per request),
`POST /api/screens/{inbox}/identify` and `POST /api/alerts/test`, both through a screen's own `show_alert`; data and
firmware are unchanged. The built files carry a hash of their content in their names, so a browser never combines an
old script with a new page.
### Compatibility 0.2.72 / firmware 0.2.61
Firmware only (both board profiles; `cyd_ui.h` gains a comment); the app raises `FIRMWARE_VERSION`. No protocol,
+9 -8
View File
@@ -121,7 +121,7 @@ that still fits a 480x480 board in one go.
### 3. The entity
In both board profiles, with the same name as the row:
In `packages/core.yaml`, which every board builds from, with the same name as the row:
```yaml
switch:
@@ -141,18 +141,19 @@ The screen's preferences hold the value, so the entity reads it in a lambda inst
(`restore_value` cannot be combined with a lambda). A switch publishes its own changes. A number, time or
select takes `update_interval: never` and one line in `apply_screen_settings`, which publishes it when it
differs; that script runs after every change and on every Home Assistant connection (the time sync), so the
entity has a value before Home Assistant reads the states. The entities live in `packages/core.yaml`; the
Rotation select, which only a Guition has, in its board file (docs/PROFILES.md).
entity has a value before Home Assistant reads the states. A setting only some boards have goes into their board
files instead, like the Rotation select of the Guition (docs/PROFILES.md).
### 4. The add-on
- `screen_manager/app/core.py`: one line in `SETTING_RULES` (`'beep': (False, None, None)`) for validation,
one in `SETTING_ENTITIES` (`'beep': ('switch', 'Beep on touch')`, the entity name exactly as in the
profiles), and the key in `SETTINGS_BESIDE_BLOCK` so it never enters the frozen block.
one in `SETTING_ENTITIES` (`'beep': ('switch', 'Beep on touch')`, the entity name exactly as in
`packages/core.yaml`), and the key in `SETTINGS_BESIDE_BLOCK` so it never enters the frozen block.
- `screen_manager/app/server.py`: `settings_view` already leaves a key out for a screen whose device has no
entity for it. Leave it out for a screen that does not own its settings too (`owner` `'layout'`), like
`auto_home` below firmware 0.2.44: such firmware cannot have it.
- `screen_manager/app/static/app.js`: one row in `SETTING_GROUPS`, with the label the screen uses.
entity for it. Leave it out for a screen that does not own its settings too (`owner` `'layout'`), as
`dark_mode` and `page_buttons` are: such firmware cannot have it.
- `web/src/store.ts`: one row in `SETTING_GROUPS`, with the label the screen uses; then build the editor
(`cd web && npm test && npm run build`, AGENTS.md).
- `screen_manager/app/claude_skill.py`: a row in the table of screen entities.
### 5. Tests and proof
+4 -5
View File
@@ -13,12 +13,12 @@
| No measurements | Five crosshairs visible, other log reader closed, correct port. Press Enter in the wizard first, then tap the requested point three times, releasing in between. |
| Tap jumps to a different spot | Check the independent `verify`, your own `calibration.yaml`, and a fixed orientation. Don't use the same taps to both fit and verify. |
| Fit reports spread/error | Measure again following the prompts. Don't fix unstable ADC readings by raising the tolerance; check power, cable, and touch hardware. |
| Duplicate HA action | Check both the touch logs and HA automations. Don't use direct actions together with an automation on the action sensor for the same operation. |
| Duplicate HA action | Check both the touch logs and your HA automations: an automation that reacts to the same entity can repeat or undo what the tile did. |
| Wi-Fi doesn't connect | 2.4GHz, correct local secrets, network range. USB calibration doesn't need HA. |
| HA doesn't see the board | Manually use the IP from the logs; port 6053 reachable, correct encryption key, no guest network isolation. |
| Status works but action doesn't | Check the HA option for allowed device actions, the real entity ID, and a supported action. |
| Vacuum/climate partly usable | Supported modes/attributes differ per integration; test the same action in Home Assistant first. |
| Wrong pagination | `TILE_COUNT` is 1–10; hidden buttons up to six, two pages from seven on. Reflash after changing it. |
| Wrong pagination | Tiles keep the slot you gave them in ESP Screens: six per page, up to eight pages, and a Save & send applies it without a reflash. The page buttons hide on a screen with one page, and **Page buttons** off hides them everywhere; then only swiping and Go to page tiles change the page, and the editor warns about a page nothing leads to. Firmware older than 0.2.26 packs the tiles in order instead. |
| Freeze/reset | Keep the USB log, check the reset reason/power, and run the render test. Note the action and time. |
For a USB log (stop other readers):
@@ -27,7 +27,6 @@ For a USB log (stop other readers):
python diagnostics/capture_serial.py --port <USB_PORT> --seconds 120
```
The existing `CYD_STABILITY.md` and `TEST_RESULTS.md` describe earlier
investigation on one specific board. Their measurements are not calibration for
a new board. Start at [README.md](../README.md), keep a working
The `docs/TEST_RESULTS_*.md` files describe tests on the owner's own boards. Their
measurements are not calibration for a new board. Start at [README.md](../README.md), keep a working
local configuration, and change one cause at a time.
+4 -3
View File
@@ -27,10 +27,11 @@ temperature, a door, the alarm, or "last changed"). Drag to reorder, tap
to configure; firmware 0.2.32 or newer renders them.
After pairing via the HA ESPHome integration, choose the tiles in ESP Screens.
Tap a tile and its settings open in a drawer on the right, with the mockup still in view: click behavior, larger values, mini-sliders, a wider tile, backgrounds.
Tap a tile and its settings open in a drawer on the right, with the mockup still in view: click behavior, larger values, mini-sliders, a wider tile or one over the whole page, backgrounds.
The mockup shows what Home Assistant reports right now: values, On or Off, positions, the song that plays. **Identify** in the ··· menu blinks a screen so you know which one it is; the same menu copies the layout of another screen, or exports and imports one as JSON. ⌘K searches screens, entities and actions.
**Screen settings**, the tab next to Layout, has brightness and standby. **Read current data** in the ··· menu of a screen helps with
missing attributes or an offline screen. New cards require firmware 0.2.0.
**Screen settings**, the tab next to Layout, has brightness, Dark mode and standby, the night hours, and the
clock, back to page 1, swiping, the page buttons and the rotation. **Read current data** in the ··· menu of a screen helps with
missing attributes or an offline screen. A new card needs new firmware on the screen: press **Update** on it.
The ··· menu of a screen also has **Override YAML** for a persistent, hardware-specific
`<screen>.local.yaml` file. It is loaded after the shared package and does not
replace the managed name, credentials, Wi-Fi, OTA or package connection.