Put ESP Screens in English and keep layouts when entity IDs change (0.2.40)

Everything a user sees or reads is now English: both boards' labels,
status replies and logs, the ESP Screens editor and Alerts cheatsheet,
and the README and guides (docs/TILES.md, CALIBRATING.md, ACCEPTANCE.md
and TROUBLESHOOTING.md replace the Dutch file names). Labels follow
Home Assistant's own English names (Heat/Cool modes, Heating/Cooling
actions, Away, Returning to dock, weather conditions), dates use English
abbreviations and the top bar writes numbers the English way. Docs use
HA 2026.9's menu names (Settings -> Apps, App store, Settings -> Tools).
Unused legacy files (home-like.yaml, buttons.yaml, a.out) are removed.

Firmware 0.2.34 names its entities in English. Home Assistant registers
a renamed ESPHome entity under a new entity ID, so the inbox
text.<screen>_tegelinstellingen becomes text.<screen>_tile_settings and
the layout stored under the old ID would be lost. The manager now
recognises the screen by its device, during a run or after a restart,
and moves its layout and update history along; the Update button and
the nightly round follow the screen through the rename. Screens that
still run 0.2.33 or older keep working: both languages are matched.

Main is the only release branch from now on.

Tested on a Home Assistant Yellow (HA 2026.9.1) with both bench boards:
see docs/TEST_RESULTS_0240.md.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
Max Gramser
2026-09-15 02:08:43 +02:00
parent f60eed3ff6
commit 3e959b3df9
87 changed files with 5049 additions and 11167 deletions
+98
View File
@@ -0,0 +1,98 @@
# Acceptance test and handover
Note the date, board variant/MAC, Git commit, ESPHome version, device name, and the
names of the two measurement files. Don't include passwords in the report.
## Without real HA actions
1. Calibrate using [CALIBRATING.md](CALIBRATING.md); flash the result and run a
new, independent measurement with `verify`. A successful fit alone
doesn't prove the firmware coordinates are correct.
2. Flash normal mode. Check that the measurement screen disappears.
3. Check every visible tile and its edges: no other tile should respond.
Tap calmly and rapidly in succession, but expect no repeat within the
deliberate debounce period. A swipe should not trigger a tile action afterward.
4. With 1–6 tiles: no page button. With 7–10: repeat at least twenty times:
Next → tile → Previous. The bottom tile should not respond to the
page button. Open/close overlays; a tap inside one should not leak through.
5. Run the built-in render test via the encrypted API:
```sh
python diagnostics/run_ui_test.py --host display-kitchen.local --name display-kitchen
```
Requires ten successful page checks, fifty overlay cycles, and progress
from real draw callbacks. This doesn't test physical touch or HA actions.
6. Leave the board on for at least 15 minutes. Check that it doesn't restart,
that standby only starts after ten minutes without touch, and that the first
tap wakes the screen without toggling a device.
## With Home Assistant
Only now enable direct actions, reflash, and choose safe test devices.
Check every configured tile with its real HA entity:
- A tap performs exactly one intended action; the feedback is correct.
- Changes from HA also appear on the screen.
- Light slider/color, climate setpoint, and supported modes work where used.
- Vacuum actions and speeds work where supported. Note any missing functionality.
- After a power interruption, Wi-Fi and HA come back; name, calibration, and tiles persist.
- After a brief Wi-Fi/HA interruption, the connection recovers without a USB flash.
Keep logs local only. Check for resets, watchdog messages, repeated
connection errors, and noticeably slow components. A short render test doesn't
prove stability over days; note the duration actually observed.
## Automated development checks
From the repo, with the Python environment active:
```sh
python -m unittest discover -s tests -p 'test_*.py'
c++ -std=c++17 -Wall -Wextra -pedantic tests/test_cyd_ui.cpp -o /tmp/test_cyd_ui
/tmp/test_cyd_ui
c++ -std=c++17 -Wall -Wextra -pedantic tests/test_touch_filter.cpp -o /tmp/test_touch_filter
c++ -std=c++17 -Wall -Wextra -pedantic tests/test_light_controls.cpp -o /tmp/test_light_controls
/tmp/test_light_controls
/tmp/test_touch_filter
c++ -std=c++17 -Wall -Wextra -pedantic tests/test_light_controls.cpp -o /tmp/test_light_controls
/tmp/test_light_controls
python -m esphome config device.yaml
python -m esphome compile device.yaml
```
The C++ commands above are for macOS/Linux with a compiler. On Windows,
the developer can use whatever C++17 toolchain is available. Only flash the
checked profile to the identified board.
## Handover report
```text
Board / MAC:
Git commit / ESPHome version:
Device name / HA entities:
Calibration measurement + independent verification:
Render test:
Physical pagination/touch/standby:
Real HA actions:
Observed stable duration:
Limitations / not yet tested:
Local profile files safely stored:
```
Give the owner the three local YAML files and the measurement files through a
suitable private channel. For a different owner, use the clean repository
or starter ZIP, so they get their own keys and their own panel calibration.
## Light card
- RGB+white light: three sliders; RGB-only: color and brightness; white-only:
white temperature and brightness. A plain dimmer keeps the brightness card.
- Drag slowly across the rainbow, release, and check the physical light.
Repeat for white temperature and brightness. Brightness keeps the color mode.
- Reopen the card and check the received values. Test two lights with
different temperature ranges; no value should leak from the other light.
- The firmware render diagnostic includes `Light sliders: PASS`: twenty preview events
per slider, exactly one commit on release, no duplicate commit, no commit
after an aborted touch, and four capability combinations. This runs with
swapped-in callbacks and doesn't control any real lights.
-98
View File
@@ -1,98 +0,0 @@
# Acceptatietest en oplevering
Noteer datum, bordvariant/MAC, Git-commit, ESPHome-versie, apparaatnaam en de
namen van de twee meetbestanden. Neem geen wachtwoorden in het rapport op.
## Zonder echte HA-acties
1. Kalibreer met [CALIBREREN.md](CALIBREREN.md); flash de uitkomst en voer een
nieuwe, onafhankelijke meting met `verify` uit. Een geslaagde fit alleen
bewijst niet dat de firmwarecoördinaten kloppen.
2. Flash de normale modus. Controleer dat het meetscherm verdwijnt.
3. Controleer elk zichtbaar vak en de randen: geen andere tegel mag reageren.
Tik rustig en snel achter elkaar, maar verwacht geen herhaling binnen de
bewuste debounceperiode. Een veeg mag geen tegelactie achteraf veroorzaken.
4. Bij 1–6 tegels: geen paginaknop. Bij 7–10: herhaal minstens twintig keer
Volgende → tegel → Vorige. De onderste tegel mag niet reageren op de
paginaknop. Open/sluit overlays; een tik daarin mag niet doorlekken.
5. Draai de ingebouwde renderproef via de versleutelde API:
```sh
python diagnostics/run_ui_test.py --host display-keuken.local --name display-keuken
```
Vereist tien geslaagde paginacontroles, vijftig overlaycycli en voortgang
van echte draw-callbacks. Dit test geen fysieke touch of HA-acties.
6. Laat het bord minstens 15 minuten aan. Controleer dat het niet herstart,
dat standby pas na tien minuten zonder aanraking begint en dat de eerste
tik het scherm wekt zonder een apparaat te schakelen.
## Met Home Assistant
Schakel directe acties pas nu in, flash opnieuw en kies veilige testapparaten.
Controleer elke geconfigureerde tegel met zijn echte HA-entiteit:
- Een tik voert precies één bedoelde actie uit; de terugmelding klopt.
- Veranderen vanuit HA wordt ook op het scherm zichtbaar.
- Lichtslider/kleur, climate-setpoint en ondersteunde modi werken waar gebruikt.
- Vacuumacties en snelheden werken waar ondersteund. Noteer ontbrekende functies.
- Na stroomonderbreking komen wifi en HA terug; naam, kalibratie en tegels blijven.
- Na een korte wifi-/HA-onderbreking herstelt de verbinding zonder USB-flash.
Bewaar logs alleen lokaal. Controleer op resets, watchdogmeldingen, herhaalde
connectiefouten en opvallend trage componenten. Een korte renderproef bewijst
geen stabiliteit over dagen; noteer de werkelijk geobserveerde duur.
## Geautomatiseerde ontwikkelchecks
Vanuit de repo, met de Python-omgeving actief:
```sh
python -m unittest discover -s tests -p 'test_*.py'
c++ -std=c++17 -Wall -Wextra -pedantic tests/test_cyd_ui.cpp -o /tmp/test_cyd_ui
/tmp/test_cyd_ui
c++ -std=c++17 -Wall -Wextra -pedantic tests/test_touch_filter.cpp -o /tmp/test_touch_filter
c++ -std=c++17 -Wall -Wextra -pedantic tests/test_light_controls.cpp -o /tmp/test_light_controls
/tmp/test_light_controls
/tmp/test_touch_filter
c++ -std=c++17 -Wall -Wextra -pedantic tests/test_light_controls.cpp -o /tmp/test_light_controls
/tmp/test_light_controls
python -m esphome config device.yaml
python -m esphome compile device.yaml
```
De C++-commando's hierboven zijn voor macOS/Linux met een compiler. Op Windows
kan de developer een beschikbare C++17-toolchain gebruiken. Flash alleen het
gecontroleerde profiel naar het geïdentificeerde bord.
## Opleverrapport
```text
Bord / MAC:
Git-commit / ESPHome-versie:
Apparaatnaam / HA-entiteiten:
Kalibratiemeting + onafhankelijke verificatie:
Renderproef:
Fysieke paginering/touch/standby:
Werkelijke HA-acties:
Geobserveerde stabiele duur:
Beperkingen / nog niet getest:
Lokale profielbestanden veilig bewaard:
```
Geef de eigenaar de drie lokale YAML-bestanden en de meetbestanden via een
passend privé-kanaal. Gebruik voor een andere eigenaar de schone repository
of starter-ZIP, zodat die eigen sleutels en eigen paneelkalibratie krijgt.
## Lichtkaart
- RGB+wit-lamp: drie schuiven; RGB-only: kleur en helderheid; wit-only:
wittemperatuur en helderheid. Een gewone dimmer behoudt de helderheidskaart.
- Sleep langzaam over de regenboog, laat los en controleer de fysieke lamp.
Herhaal voor wittemperatuur en helderheid. Helderheid behoudt de kleurmodus.
- Heropen de kaart en controleer de ontvangen waarden. Test twee lampen met
verschillende temperatuurbereiken; er mag geen waarde van de andere lamp lekken.
- Firmware-renderdiagnose bevat `Light sliders: PASS`: twintig preview-events
per schuif, precies één commit bij loslaten, geen dubbele commit, geen commit
na een afgebroken aanraking en vier capabilitycombinaties. Dit gebeurt met
vervangen callbacks en bedient geen echte lampen.
+127
View File
@@ -0,0 +1,127 @@
# Calibrating a new panel
This protocol is for **320×240, LVGL rotation 90°, swap_xy=false,
mirror_x=true, mirror_y=false**. Other orientations, GT911 touch, and other
controllers require a separate profile. Don't change rotation or mirroring
partway through the measurement.
The filter in this repo stabilizes the XPT2046 measurements. Calibration then
corrects offset, scale, and skew. Calibration does not fix a defective
panel, a loose connection, unstable power, or random outliers.
## Preparing
1. Use the `device.yaml` from `tools/new_device.py`, with your own
`calibration.yaml` that starts as identity. Don't carry over the personal
correction from the historical base profile.
2. Check the data cable and the USB port with `python -m serial.tools.list_ports`.
3. Flash from the repo root:
```sh
python -m esphome -s CALIBRATION_ON_BOOT true run device.yaml --device <USB_PORT>
```
4. Physically check for the **dark screen with five white + marks**.
It stays on, and tile actions aren't accessible here.
5. Stop the ESPHome log reader with Ctrl+C. Leave the board and USB cable connected.
Only one program may use the serial port at a time.
Wi-Fi/HA aren't needed for this USB route. If the board is already on Wi-Fi,
the screen can also be opened via the encrypted API:
```sh
python diagnostics/control_ui.py touch_diagnostics --host display-kitchen.local --name display-kitchen
```
That doesn't change the boot mode. For a new installation, use the
USB route above, so calibration mode also stays active after a reset.
## Measurement A: collecting data
```sh
python tools/calibrate.py capture --port <USB_PORT> --device-name display-kitchen --output measurements-before.json
```
The wizard guides you through **one target at a time**:
1. Read in the terminal which crosshair is up next.
2. Press Enter, then tap only that crosshair **three times**.
3. Hold each tap for about half a second and release fully in between.
4. Wait for the next terminal prompt. Don't move on to another corner yourself.
Order: top-left, top-right, bottom-right, bottom-left, center.
Use a suitably blunt stylus or a small, deliberate fingertip tap; no
sharp point. The targets are at `(20,20)`, `(299,20)`, `(299,219)`, `(20,219)`,
and `(160,120)`.
The wizard only reads touch logs with `calibration=1`. It doesn't flash anything, make
any network connection, or send any HA actions. An incomplete measurement is
not saved as a valid file. On a mistaken tap: Ctrl+C and start
over. Use a new filename if a measurement already exists.
## Calculating a correction
```sh
python tools/calibrate.py fit measurements-before.json --output calibration.yaml --replace
```
The script:
- takes the median of the three raw ADC measurements per corner;
- determines an affine correction from the four corners;
- checks the **center point, which is not used for the fit**;
- rejects errors that are too large (>12 px), spread (>18 px), and unusable measurement geometry;
- saves the existing `calibration.yaml` as a dated `.bak` before
placing a new, complete version.
The output contains only the four base bounds and six affine coefficients in
an ESPHome substitutions map. `device.yaml` imports this as the calibration
package. Don't change the coefficients by feel, and don't add a second correction
in the driver. The `raw=` logs contain the filtered **physical ADC values**,
even once a correction is already set; recalibrating therefore doesn't stack twice.
A successful fit on existing data is not yet a successful physical test.
## Measurement B: independently testing the flashed result
Flash the correction, still with the measurement screen:
```sh
python -m esphome -s CALIBRATION_ON_BOOT true run device.yaml --device <USB_PORT>
```
Close the log reader with Ctrl+C and collect **new taps**:
```sh
python tools/calibrate.py capture --port <USB_PORT> --device-name display-kitchen --output measurements-after.json
python tools/calibrate.py verify measurements-after.json
```
`verify` uses the firmware's real `native=` coordinates, rotates them
to screen coordinates, and compares them with the targets. It does **not
run a new fit**. All five points must pass. Don't accidentally
use the pre-flash file for this check.
Doesn't work? Check which point fails, check the order/pressure, measure again,
and read [TROUBLESHOOTING.md](TROUBLESHOOTING.md). Don't just raise the tolerance to get the
test to pass. Report any remaining hardware deviation honestly.
## Back to normal operation
```sh
python -m esphome run device.yaml --device <USB_PORT>
```
No `-s CALIBRATION_ON_BOOT true` is given here. In `device.yaml`, the
setting stays `false`. Check the actual tiles and navigation per
[ACCEPTANCE.md](ACCEPTANCE.md).
If calibration mode was opened only via the API, you can close it:
```sh
python diagnostics/control_ui.py end_touch_diagnostics --host display-kitchen.local --name display-kitchen
```
Keep both measurement files and `calibration.yaml` with this physical screen.
Start over after replacing the panel; give only the neutral
starter files to a next owner.
-127
View File
@@ -1,127 +0,0 @@
# Een nieuw paneel kalibreren
Dit protocol is voor **320×240, LVGL-rotatie 90°, swap_xy=false,
mirror_x=true, mirror_y=false**. Andere oriëntaties, GT911-touch en andere
controllers vereisen een apart profiel. Verander rotatie of mirroring niet
halverwege de meting.
De filter in deze repo stabiliseert de XPT2046-metingen. Kalibratie corrigeert
vervolgens offset, schaal en scheefstand. Kalibratie repareert geen defect
paneel, losse verbinding, instabiele voeding of willekeurige uitschieters.
## Voorbereiden
1. Gebruik `device.yaml` van `tools/new_device.py`, met een eigen
`calibration.yaml` die begint als identiteit. De persoonlijke correctie
in het historische basisprofiel mag niet worden overgenomen.
2. Controleer de datakabel en de USB-poort met `python -m serial.tools.list_ports`.
3. Flash vanaf de reporoot:
```sh
python -m esphome -s CALIBRATION_ON_BOOT true run device.yaml --device <USB_POORT>
```
4. Controleer fysiek het **donkere scherm met vijf witte + tekens**.
Het blijft aan en de tegelacties zijn hier niet toegankelijk.
5. Stop de ESPHome-loglezer met Ctrl+C. Laat het bord en de USB-kabel zitten.
Slechts één programma mag tegelijk de seriële poort gebruiken.
Wifi/HA zijn voor deze USB-route niet nodig. Als het bord al op wifi staat,
kan het scherm ook via de versleutelde API worden geopend:
```sh
python diagnostics/control_ui.py touch_diagnostics --host display-keuken.local --name display-keuken
```
Dat verandert de startmodus niet. Gebruik voor een nieuwe installatie de
USB-route hierboven, zodat de kalibratiemodus ook na een reset actief blijft.
## Meting A: gegevens verzamelen
```sh
python tools/calibrate.py capture --port <USB_POORT> --device-name display-keuken --output measurements-before.json
```
De wizard begeleidt **één doel tegelijk**:
1. Lees in de terminal welk kruisje aan de beurt is.
2. Druk op Enter en tik daarna alleen dat kruisje **drie keer**.
3. Houd elke tik circa een halve seconde vast en laat tussendoor volledig los.
4. Wacht op de volgende terminalprompt. Ga niet zelf alvast naar een andere hoek.
Volgorde: linksboven, rechtsboven, rechtsonder, linksonder, midden.
Gebruik een geschikte stompe stylus of een kleine, bewuste vingertik; geen
scherpe punt. De doelen staan op `(20,20)`, `(299,20)`, `(299,219)`, `(20,219)`
en `(160,120)`.
De wizard leest alleen touchlogs met `calibration=1`. Hij flasht niets, maakt
geen netwerkverbinding en stuurt geen HA-acties. Een onvolledige meting wordt
niet als geldig bestand opgeslagen. Bij een verkeerde tik: Ctrl+C en opnieuw
beginnen. Gebruik een nieuwe bestandsnaam als een meting al bestaat.
## Een correctie berekenen
```sh
python tools/calibrate.py fit measurements-before.json --output calibration.yaml --replace
```
Het script:
- neemt per hoek de mediaan van de drie ruwe ADC-metingen;
- bepaalt een affine correctie uit de vier hoeken;
- controleert het **niet voor de fit gebruikte middenpunt**;
- weigert te grote fouten (>12 px), spreiding (>18 px) en onbruikbare meetgeometrie;
- bewaart de bestaande `calibration.yaml` als een gedateerde `.bak` voordat
een nieuwe, complete versie wordt geplaatst.
De output bevat alleen de vier basisgrenzen en zes affine coëfficiënten in
een ESPHome-substitutions-map. `device.yaml` importeert deze als calibration-
package. Verander de coëfficiënten niet op gevoel en voeg geen tweede correctie
in de driver toe. De `raw=`-logs bevatten de gefilterde **fysieke ADC-waarden**,
ook als al een correctie is ingesteld; opnieuw kalibreren telt dus niet dubbel op.
Een geslaagde fit op bestaande data is nog geen geslaagde fysieke test.
## Meting B: de geflashte uitkomst onafhankelijk testen
Flash de correctie, nog steeds met het meetscherm:
```sh
python -m esphome -s CALIBRATION_ON_BOOT true run device.yaml --device <USB_POORT>
```
Sluit de loglezer met Ctrl+C en verzamel **nieuwe tikken**:
```sh
python tools/calibrate.py capture --port <USB_POORT> --device-name display-keuken --output measurements-after.json
python tools/calibrate.py verify measurements-after.json
```
`verify` gebruikt de echte `native=`-coördinaten van de firmware, draait die
naar de schermcoördinaten en vergelijkt ze met de doelen. Hij voert **geen
nieuwe fit** uit. Alle vijf punten moeten slagen. Gebruik niet per ongeluk
het bestand van vóór de flash voor deze controle.
Lukt dit niet? Bekijk welk punt faalt, controleer de volgorde/druk, meet opnieuw
en lees [PROBLEMEN.md](PROBLEMEN.md). Verhoog niet alleen de tolerantie om de
test groen te krijgen. Rapporteer een resterende hardwareafwijking eerlijk.
## Terug naar normale bediening
```sh
python -m esphome run device.yaml --device <USB_POORT>
```
Hier is **geen** `-s CALIBRATION_ON_BOOT true` opgegeven. In `device.yaml` blijft
de instelling `false`. Controleer de werkelijke tegels en navigatie volgens
[ACCEPTATIE.md](ACCEPTATIE.md).
Als de kalibratiemodus uitsluitend via de API was geopend, kun je hem sluiten:
```sh
python diagnostics/control_ui.py end_touch_diagnostics --host display-keuken.local --name display-keuken
```
Bewaar beide meetbestanden en `calibration.yaml` bij dit fysieke scherm.
Na vervangen van het paneel opnieuw beginnen; geef alleen de neutrale
starterbestanden aan een volgende eigenaar.
+53 -53
View File
@@ -1,66 +1,66 @@
# Upgrade bestaand CYD-paneel naar runtime 0.2.7
# Upgrading an existing CYD panel to runtime 0.2.7
Bord: ESP32-2432S028, ESP32-D0WD-V3; MAC b0:cb:d8:e7:bd:7c.
Bestaande identiteit CYD 2.8in Display / cyd-2432s028 behouden. USB-poort werd
vooraf met esptool geïdentificeerd; Guition zat op een andere USB-poort.
Board: ESP32-2432S028, ESP32-D0WD-V3; MAC b0:cb:d8:e7:bd:7c.
Kept the existing identity CYD 2.8in Display / cyd-2432s028. The USB port was
identified beforehand with esptool; the Guition was on a different USB port.
Eigen profiel: genegeerd easy-cyd-device.yaml, met de bestaande lokale
calibration.yaml en API/OTA/wifi-secretverwijzingen. Een back-up van de eerste
64 KiB (partitie/configuratieruimte) is lokaal opgeslagen. Een volledige snelle
uitlezing gaf een seriële fout; de volledige langzame uitlezing is afgebroken.
Dit is dus geen volledige oude-firmwareback-up. USB-upload op 115200 geslaagd;
verdere correctie via de geverifieerde OTA-host.
Own profile: gitignored easy-cyd-device.yaml, with the existing local
calibration.yaml and API/OTA/Wi-Fi secret references. A backup of the first
64 KiB (partition/configuration space) is stored locally. A full fast
read gave a serial error; the full slow read was aborted.
So this is not a complete old-firmware backup. USB upload at 115200 succeeded;
further correction via the verified OTA host.
De bestaande affine kalibratie is eenmalig in preference-key 0x43594403 gezet.
Daarna gebruikt het definitieve profiel de standaard opstart en bestaande NVS.
The existing affine calibration was written once into preference key 0x43594403.
After that, the final profile uses the standard boot and existing NVS.
## Tijdens de upgrade gevonden
## Found during the upgrade
Een tijdelijk on_boot-list in het lokale migratieprofiel verving het on_boot-
object van het pakket. Daardoor ontbrak de normale UI-initialisatie en crashte
het begin van de renderdiagnose. De tijdelijke import is verwijderd nadat de
kalibratie was opgeslagen. In de definitieve gegenereerde C++ zijn runtime-bind,
light_controls::setup en screen_calibration::setup weer aanwezig. De volledige
renderdiagnose slaagt daarna (tien paginacontroles en vijftig overlays).
Gebruik dit tijdelijke migratieprofiel niet voor toekomstige flashes.
A temporary on_boot list in the local migration profile replaced the package's
on_boot object. As a result, the normal UI initialization was missing and
the start of the render diagnostic crashed. The temporary import was removed after the
calibration had been saved. In the final generated C++, runtime-bind,
light_controls::setup, and screen_calibration::setup are present again. The full
render diagnostic then passes (ten page checks and fifty overlays).
Don't use this temporary migration profile for future flashes.
HA ontdekte de nieuwe Tegelinstellingen-entity zonder nieuwe API-sleutel. De oude
tien entiteiten zijn overgezet; daarna heeft de gebruiker de indeling gewijzigd.
Die actuele indeling is behouden. Swipe is aan, standby 600 seconden. Bij maximaal
zes tegels blijft de paginering verborgen.
HA discovered the new Tegelinstellingen entity without a new API key. The old
ten entities were carried over; the user then changed the layout.
That current layout is preserved. Swipe is on, standby 600 seconds. With six
tiles or fewer, pagination stays hidden.
Definitieve build: ESPHome 2026.6.2, 2026-09-12 17:50:49 +0200,
config_hash=0x0a15a59f, broncommit a14a66f.
Final build: ESPHome 2026.6.2, 2026-09-12 17:50:49 +0200,
config_hash=0x0a15a59f, source commit a14a66f.
## Verificatie
## Verification
- Definitieve build en OTA-upload geslaagd; identiteit en firmwareversie via de
versleutelde API gecontroleerd.
- Renderdiagnose: tien geslaagde paginacontroles, vijftig overlaycycli en
`Light sliders: PASS`. De diagnose gebruikte de toen ingestelde twee tegels;
dit is geen fysieke swipecontrole van vier pagina's.
- Home Assistant en ESP Screen Manager melden het paneel online met versie 0.2.7.
Wijzigingen van de gebruiker in de tegelindeling blijven behouden.
- Bestaande kalibratie hergebruikt; tijdens deze upgrade is geen nieuwe
onafhankelijke fysieke kalibratiemeting uitgevoerd.
- Final build and OTA upload succeeded; identity and firmware version checked
via the encrypted API.
- Render diagnostic: ten successful page checks, fifty overlay cycles, and
`Light sliders: PASS`. The diagnostic used the two tiles configured at the time;
this is not a physical swipe check of four pages.
- Home Assistant and ESP Screen Manager report the panel online with version 0.2.7.
The user's changes to the tile layout are preserved.
- Existing calibration reused; no new independent physical calibration
measurement was performed during this upgrade.
De 0.2.7-observatie is vijftien minuten voltooid met een levende API-respons elke
dertig seconden, zonder herstart of verbindingsverlies. Vrij geheugen circa
111–119 kB. Door fysieke bediening werd tien minuten onafgebroken inactiviteit
niet bereikt; standby/ontwaken is in deze observatie niet bevestigd.
The 0.2.7 observation ran for fifteen minutes complete, with a live API response every
thirty seconds, with no restart or connection loss. Free memory around
111–119 kB. Because of physical use, ten minutes of uninterrupted inactivity
was not reached; standby/wake was not confirmed in this observation.
## Vervolg: tekstlayout 0.2.8
## Follow-up: text layout 0.2.8
De eigenaar meldde vervolgens afvallende titels, te vroeg afgekorte ondertitels
en een overlappende mini-slider. Stabiliteit alleen bevestigt dus niet de
bruikbaarheid van de layout. De titels hadden geen expliciete breedte en de
ondertitel nam de inhoudsbreedte van de titel over. De compacte kaart had daarnaast
onvoldoende verticale ruimte voor de extra slider.
The owner then reported titles running off the edge, subtitles truncated too early,
and an overlapping mini-slider. So stability alone doesn't confirm the
layout's usability. The titles had no explicit width, and the
subtitle inherited the title's content width. The compact card also had
insufficient vertical space for the extra slider.
Runtime 0.2.8 begrenst beide regels op de beschikbare inhoudsbreedte, vergroot die
bij een verborgen icoon en reserveert op de CYD aparte ruimte voor de schuif.
De renderdiagnose controleert nu de echte LVGL-coördinaten op afkapping buiten het
vak en overlapping van tekstregels/slider. Met de actuele vier tegels, waaronder
een lamp met mini-slider: tien paginacontroles en vijftig overlaycycli geslaagd.
De slidertest slaagt ook. Fysieke bevestiging van de nieuwe layout staat nog open.
De vijftien minuten hierboven gelden voor 0.2.7, niet voor deze vervolgbuild.
Runtime 0.2.8 bounds both lines to the available content width, expands that
when an icon is hidden, and reserves separate space for the slider on the CYD.
The render diagnostic now checks the real LVGL coordinates for clipping outside the
box and overlap between text lines/slider. With the current four tiles, including
a light with a mini-slider: ten page checks and fifty overlay cycles passed.
The slider test also passes. Physical confirmation of the new layout is still open.
The fifteen minutes above apply to 0.2.7, not to this follow-up build.
+215 -215
View File
@@ -1,260 +1,260 @@
# Installeren en beheren vanuit ESP Screens
# Installing and managing from ESP Screens
Een nieuw scherm, van USB naar dagelijks gebruik
A new screen, from USB to everyday use
Met **ESP Screen Manager** kies je je tegels in Home Assistant. Je zoekt op
naam, apparaat, ruimte of entity-ID, zet ze in de gewenste volgorde en klikt
op **Opslaan & naar scherm**. Daarna blijft de status automatisch actueel.
Je hoeft voor andere tegels **niet opnieuw te flashen**.
With **ESP Screen Manager**, you choose your tiles in Home Assistant. You search by
name, device, room, or entity ID, arrange them in the order you want, and click
**Save & send to screen**. After that, the status stays automatically up to date.
You don't need to **reflash** for different tiles.
Dit werkt met Home Assistant OS op een 64-bits Raspberry Pi of een amd64-machine,
en een van deze exacte schermvarianten. De ESPHome-CLI zit in ESP Screen Manager;
ESPHome Device Builder is optioneel:
This works with Home Assistant OS on a 64-bit Raspberry Pi or an amd64 machine,
and one of these exact screen variants. The ESPHome CLI is included in ESP Screen Manager;
ESPHome Device Builder is optional:
| Keuze | Hardware |
| Choice | Hardware |
| --- | --- |
| CYD | ESP32-2432S028, 320×240, ILI9341 en XPT2046 |
| Guition | ESP32-S3-4848S040, 480×480, ST7701S en GT911 |
| CYD | ESP32-2432S028, 320×240, ILI9341 and XPT2046 |
| Guition | ESP32-S3-4848S040, 480×480, ST7701S and GT911 |
Andere schermen met ongeveer dezelfde naam kunnen andere pinnen hebben. Gebruik
het bordprofiel dat bij de hardware hoort. Gebruik een USB-kabel die data ondersteunt.
De wallbox-relais worden niet gebruikt.
Other screens with roughly the same name can have different pins. Use
the board profile that matches the hardware. Use a USB cable that supports data.
The wallbox relays are not used.
## 1. Installeer ESP Screen Manager
## 1. Install ESP Screen Manager
1. Open **Instellingen → Apps → Installeer een app** (in oudere HA-versies:
**Instellingen → Add-ons → Add-onwinkel**).
2. Open het menu rechtsboven → **Repositories** en voeg toe:
1. Open **Settings → Apps → Install app** (on older HA versions:
**Settings → Add-ons → Add-on Store**).
2. Open the menu in the top right → **Repositories** and add:
`https://github.com/MaxGramser/homeassistant_espscreen`.
3. Installeer en start **ESP Screen Manager**. Zet **Starten bij opstarten**
en **Tonen in zijbalk** aan. Open de webinterface **ESP Screens**.
3. Install and start **ESP Screen Manager**. Turn on **Start on boot**
and **Show in sidebar**. Open the **ESP Screens** web interface.
Deze app bevat de geteste ESPHome 2026.6.2-CLI en draait binnen je HA-aanmelding.
Een tweede ESPHome-beheerpagina, MQTT, blueprint of long-lived token is niet nodig.
Gebruik de GitHub-versie voor updates; een lokale test-add-on is een andere app.
This app includes the tested ESPHome 2026.6.2 CLI and runs within your HA login.
A second ESPHome management page, MQTT, blueprint, or long-lived token is not needed.
Use the GitHub version for updates; a local test add-on is a separate app.
## 2. Nieuw scherm: aansluiten en installeren
## 2. New screen: connecting and installing
1. Sluit het scherm met een **USB-datakabel** aan op de machine waarop Home
Assistant draait. Bij meerdere borden: sluit ze voor de eerste installatie
één voor één aan, of controleer welke poort bij dit scherm hoort.
2. Klik **Nieuw scherm**. Kies CYD of Guition en geef het scherm een naam,
bijvoorbeeld `Keuken`. De apparaatnaam (`keuken`) volgt daaruit; met
**aanpassen** kies je een andere.
3. Wifi: staan `wifi_ssid` en `wifi_password` al in de ESPHome `secrets.yaml`,
dan gebruikt het scherm die automatisch. Ontbreken ze, of bestaat het bestand
nog niet, dan vraagt het venster ze eenmalig en zet ESP Screens alleen de
ontbrekende regels in `secrets.yaml`; commentaar en andere secrets blijven
staan. Een `secrets.yaml` die geen geldige YAML is, herstel je eerst zelf.
4. Kies bij **Installeren via** de USB-poort van dit scherm en klik
**Installeren**. ESP Screens bewaart het profiel (`keuken.yaml`, met unieke
API- en OTA-sleutels) in de ESPHome-map, bouwt de firmware en schrijft die
via USB. Het ESPHome-log en de fase (bouwen, schrijven) staan in hetzelfde
venster; een eerste build duurt op een Raspberry enkele minuten. Je mag het
venster sluiten: de installatie loopt door en staat bij heropenen weer klaar.
5. Na **Klaar** toont het venster de API-sleutel met een kopieerknop en de
koppelstappen uit hoofdstuk 3. Mislukt de build, dan staat het log open en
kun je **Opnieuw proberen**.
1. Connect the screen with a **USB data cable** to the machine running Home
Assistant. With multiple boards: connect them one at a time for the first
installation, or check which port belongs to this screen.
2. Click **New screen**. Choose CYD or Guition and give the screen a name,
for example `Kitchen`. The device name (`kitchen`) follows from that; use
**customize** to choose a different one.
3. Wi-Fi: if `wifi_ssid` and `wifi_password` are already in the ESPHome `secrets.yaml`,
the screen uses them automatically. If they're missing, or the file doesn't
exist yet, the window asks for them once and ESP Screens only adds the
missing lines to `secrets.yaml`; comments and other secrets are left
alone. If `secrets.yaml` isn't valid YAML, fix that yourself first.
4. Under **Install via**, choose this screen's USB port and click
**Install**. ESP Screens stores the profile (`kitchen.yaml`, with unique
API and OTA keys) in the ESPHome folder, builds the firmware, and writes it
over USB. The ESPHome log and the current phase (building, writing) are in the same
window; a first build takes a few minutes on a Raspberry Pi. You can close the
window: the installation keeps running and picks back up when you reopen it.
5. After **Done**, the window shows the API key with a copy button and the
pairing steps from chapter 3. If the build fails, the log stays open and
you can **Retry**.
Elk scherm krijgt zijn eigen profiel: vier schermen betekent vier keer **Nieuw
scherm** met vier verschillende namen. Het gedeelde bordpakket is voor alle
schermen gelijk; het profiel bevat alleen naam, sleutels en de wifi-verwijzing.
Bewaar dat profiel en gebruik het opnieuw bij updates. Voor een bestaand scherm
opnieuw **Nieuw scherm** doorlopen maakt nieuwe sleutels aan en is niet de
updateroute.
Every screen gets its own profile: four screens means going through **New
screen** four times, with four different names. The shared board package is the
same for every screen; the profile only holds the name, keys, and the Wi-Fi reference.
Keep that profile and reuse it for updates. Going through **New screen**
again for an existing screen generates new keys and is not the
update route.
Geen USB-poort in de lijst? Een kabel aan je laptop is niet zichtbaar voor de
Raspberry. Kies dan **Later · alleen het profiel bewaren**: het profiel staat
daarna in dezelfde map die ESPHome Device Builder gebruikt, dus je kunt het daar
openen en vanuit je browser flashen (**Install → Plug into this computer**), of
het later via **Firmware & USB** alsnog aan de HA-machine installeren.
No USB port in the list? A cable plugged into your laptop isn't visible to the
Raspberry Pi. In that case, choose **Later · save profile only**: the profile then
sits in the same folder ESPHome Device Builder uses, so you can open it there
and flash from your browser (**Install → Plug into this computer**), or
install it to the HA machine later via **Firmware & USB**.
**CYD:** bij de eerste start verschijnt de kalibratie. Tik het zichtbare kruisje
drie keer rustig aan, houd elke tik kort vast en volg steeds het volgende kruisje.
Er zijn vijf posities. Het midden controleert de nauwkeurigheid. Bij een mislukte
meting vraagt het scherm opnieuw te beginnen. De correctie wordt lokaal opgeslagen
en blijft bij OTA-updates behouden. Via de HA-apparaatknop **Touch kalibreren** kun
je later opnieuw meten. Voor diagnose en de oudere handmatige installatie:
[CALIBREREN.md](CALIBREREN.md).
**CYD:** calibration appears on first boot. Calmly tap the visible crosshair
three times, hold each tap briefly, and follow each next crosshair in turn.
There are five positions. The center checks accuracy. On a failed
measurement, the screen asks you to start over. The correction is stored locally
and survives OTA updates. Use the HA device button **Calibrate touch** to
measure again later. For diagnostics and the older manual installation, see:
[CALIBRATING.md](CALIBRATING.md).
**Guition:** de GT911-touchmapping zit in het bordprofiel; er is geen ADC-kalibratie.
**Guition:** the GT911 touch mapping is baked into the board profile; there's no ADC calibration.
## 3. Koppel het scherm aan Home Assistant
## 3. Pair the screen with Home Assistant
Dit gebeurt in Home Assistant zelf, buiten ESP Screens. Zolang een profiel nog
niet aan Home Assistant is toegevoegd, staat het links onder **Mijn schermen**
als kaart *nog niet in Home Assistant*, met de knop **Open Apparaten & diensten**
en **Kopieer API-sleutel**; het klaar-scherm van **Nieuw scherm** heeft dezelfde
knop. De kaart verdwijnt zodra het scherm in de lijst staat.
This happens in Home Assistant itself, outside ESP Screens. As long as a profile
hasn't been added to Home Assistant yet, it appears on the left under **My screens**
as a *not yet in Home Assistant* card, with an **Open Devices & services**
button and **Copy API key**; the done screen of **New screen** has the same
button. The card disappears once the screen is in the list.
1. Open **Instellingen → Apparaten & diensten**. Voeg het ontdekte ESPHome-apparaat
toe. Niet ontdekt? Voeg de integratie **ESPHome** handmatig toe met het IP-adres
van het scherm, poort 6053.
2. Vraagt HA om een encryptiesleutel? Plak de API-sleutel die het venster na de
installatie toont (ook terug te vinden als **api → encryption → key** in het
profiel). Gebruik niet het OTA-wachtwoord.
3. Open bij de ESPHome-integratie **Configureren** en zet **Allow the device to
perform Home Assistant actions** aan. Zonder deze toestemming verschijnen
waarden wel, maar kan het scherm lampen en apparaten niet bedienen.
4. Open ESP Screens. Het scherm verschijnt binnen ongeveer 30 seconden.
1. Open **Settings → Devices & services**. Add the discovered ESPHome device.
Not discovered? Manually add the **ESPHome** integration with the screen's
IP address, port 6053.
2. Does HA ask for an encryption key? Paste the API key the window shows after
installation (also found as **api → encryption → key** in the
profile). Don't use the OTA password.
3. On the ESPHome integration, open **Configure** and enable **Allow the device to
perform Home Assistant actions**. Without this permission, values still show up,
but the screen can't control lights and devices.
4. Open ESP Screens. The screen appears within about 30 seconds.
## 4. Kies en wijzig je tegels
## 4. Choose and edit your tiles
Tip: zet in je ESPHome-YAML onder `wifi:` de regel `power_save_mode: none` (nieuwe
wizard-YAML's hebben hem al); het scherm hangt aan het lichtnet en reageert dan zonder
wifi-slaapvertraging op Home Assistant.
Tip: in your ESPHome YAML, add the line `power_save_mode: none` under `wifi:` (new
wizard YAMLs already have it); the screen is mains-powered, so this keeps it responding to
Home Assistant without Wi-Fi sleep delay.
Selecteer je scherm, vul de titel in en zoek entiteiten. De kiezer heeft
domeinfilters met gekleurde iconen. Je kunt maximaal twintig tegels toevoegen.
Het schermvoorbeeld toont hun plaats: twee kolommen, zes plekken per pagina,
maximaal acht pagina's. Elke tegel heeft een vaste plek die alleen verandert als
jij hem versleept; lege plekken blijven leeg, waar je ze ook laat. Sleep een tegel
op een lege plek en hij staat daar; sleep hem op een andere tegel en die twee
wisselen (de ander neemt de vrijgekomen plek, of anders de dichtstbijzijnde vrije
plek); de rest blijft staan. Tijdens het slepen zie je in het voorbeeld al waar
alles komt; onder de laatste pagina staat dan een lege pagina klaar. **Pagina
toevoegen** maakt een lege pagina die bewaard blijft; een lege pagina heeft
**Pagina weghalen**. Klik op een lege plek om de volgende tegel uit de kiezer
daar te zetten. Met de pijltjestoetsen verplaats je een gefocuste tegel.
Klik op een tegel voor een eigen naam en **Bediening & weergave instellen**:
klikgedrag, een mini-slider, een grote waarde, een grafiek (sensoren), een
weersvoorspelling (weer) of de breedte **Dubbelbreed**. Een dubbelbrede tegel van
een klimaat, schakelaar, lamp, ventilator, stofzuiger, zonwering, mediaspeler,
getal, keuzelijst, kookwekker, scène, script of knop krijgt rechts **directe
bediening** zoals de rijen in Home Assistant (bijvoorbeeld temperatuur − / +,
open/stop/dicht, volume met dempen, een toggle); kies onder **Directe bediening
op de tegel** welke set, of **Geen** (firmware 0.2.19+). **Bediening openen** op
een weertegel toont de weerkaart met de komende uren en dagen (regen inbegrepen);
op een klimaattegel de kaart met aan/uit-knop en de modus-, ventilator- en
zwenkstanden. De ingebouwde **Klok**
staat bovenaan de kiezer; zon, kookwekkers en personen vind je via de filters. Kies bij
**Pastel achtergrond** een eigen kleur met donkere tekst; **Standaard** herstelt
de normale weergave en **Geen** laat de kaart weg, zodat de inhoud even groot
direct op de schermachtergrond staat (firmware 0.2.16+). Hiervoor is firmware 0.2.10+ nodig.
Toevoegen zonder gekozen plek vult de eerste vrije plek. Vaste plekken en lege
plekken werken op het scherm vanaf firmware 0.2.26; oudere firmware schuift de
tegels aan tot de eerste vrije plek, de editor meldt dat onder het voorbeeld.
Het voorbeeld toont de indeling, geen live sensorwaarden.
Klik **Opslaan & naar scherm** om je wijzigingen door te sturen.
Select your screen, fill in the title, and search for entities. The picker has
domain filters with colored icons. You can add up to twenty tiles.
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
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 picker
there. Use the arrow keys to move a focused tile.
Click a tile for a custom name and **Configure control & display**:
click behavior, a mini-slider, a large value, a graph (sensors), a
weather forecast (weather), or the **Double-width** setting. 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
on the tile**, choose which set, or **None** (firmware 0.2.19+). **Open control** on
a weather tile shows the weather card with the coming hours and days (rain included);
on a climate tile, the card with an on/off button and the mode, fan, and
swing settings. The built-in **Clock**
sits at the top of the picker; find sun, timers, and people via the filters. Under
**Pastel background**, choose a custom color with dark text; **Default** restores
the normal look, and **None** drops the card, so the content sits the same size
directly on the screen background (firmware 0.2.16+). This requires firmware 0.2.10+.
Adding without a chosen slot fills the first free slot. Fixed slots and empty
slots work on the screen from firmware 0.2.26 on; older firmware shifts the
tiles up to the first free slot, and the editor notes that below the preview.
The preview shows the layout, not live sensor values.
Click **Save & send to screen** to send your changes.
- Lamp, switch, input_boolean en fan: tik om aan/uit te zetten.
- Lamp lang indrukken: helderheid, regenboogkleur en wittemperatuur, voor zover
de lamp die functies ondersteunt.
- Climate, vacuum en cover: tik om de bedieningskaart te openen.
- Fan lang indrukken: snelheid als het apparaat percentages ondersteunt.
- Scene/script: tik om uit te voeren; button/input_button: tik om in te drukken.
- Sensor: tik voor de historiekaart; stel bij de tegel 1, 6 of 24 uur in.
- Binary sensor: status bekijken. Select/input_select: open het keuzemenu.
- Light, switch, input_boolean, and fan: tap to turn on/off.
- Long press a light: brightness, rainbow color, and white temperature, as far as
the light supports those features.
- Climate, vacuum, and cover: tap to open the control card.
- Long press a fan: speed, if the device supports percentages.
- Scene/script: tap to run; button/input_button: tap to press.
- Sensor: tap for the history card; set 1, 6, or 24 hours on the tile.
- Binary sensor: view status. Select/input_select: open the picker menu.
Vanaf firmware 0.2.7 passen twintig tegels op maximaal vier pagina’s. Oudere
firmware houdt de limiet van tien totdat je bijwerkt. Via **Algemene instellingen
→ Vegen tussen pagina’s** kun je vegen inschakelen. Op de Guition (firmware
0.2.24+) veeg je dan vanaf de linker- of rechterrand naar binnen, zoals
terug-vegen op een telefoon; langzaam of snel, en een veeg die midden op het
scherm begint doet niets, zodat tikken en slepen op tegels nooit per ongeluk van
pagina wisselen. Op de CYD blijft het een snelle veeg over het scherm. Sliders
bedienen alleen hun waarde; detailmenu’s en standby wisselen niet van pagina.
From firmware 0.2.7, twenty tiles fit across up to four pages. Older
firmware keeps the limit of ten until you update. Under **General settings
→ Swipe between pages**, you can enable swiping. On the Guition (firmware
0.2.24+), you then swipe inward from the left or right edge, like the
back-swipe gesture on a phone; slow or fast, and a swipe starting in the
middle of the screen does nothing, so tapping and dragging tiles never
accidentally changes pages. On the CYD, it stays a quick swipe across the screen. Sliders
only control their value; detail menus and standby don't change pages.
Er staan zes tegels op een pagina. Bij maximaal zes verdwijnen Vorige/Volgende.
De standby-tijd is standaard tien minuten. Bij offline apparaten blokkeert het
scherm acties. Valt de verbinding met Home Assistant weg, dan meldt het scherm
direct "HA niet verbonden"; stuurt de app twee rondes (circa vijf minuten) niets,
dan "ESP Screens niet actief". In beide gevallen is de bediening geblokkeerd
totdat de gegevens opnieuw ontvangen zijn.
Six tiles sit on a page. With six or fewer, Previous/Next disappear.
The default standby time is ten minutes. For offline devices, the screen blocks
actions. If the connection to Home Assistant drops, the screen immediately shows
"HA not connected"; if the app sends nothing for two rounds (about five minutes),
it shows "ESP Screens not active". In both cases, control is blocked
until data is received again.
Je mag indelingen opslaan terwijl een scherm offline is. De app verstuurt ze
zodra het scherm terugkomt. De app moet blijven draaien voor actuele tegeldata.
You can save layouts while a screen is offline. The app sends them
as soon as the screen comes back. The app must keep running for current tile data.
## 5. Updates zonder je instellingen kwijt te raken
## 5. Updates without losing your settings
| Wat verandert? | Wat doe je? | Wat blijft behouden? |
| What changes? | What do you do? | What's kept? |
| --- | --- | --- |
| Andere entiteiten, namen of volgorde | Opslaan in ESP Screens | Wifi, sleutels, kalibratie |
| Nieuwe beheerpagina/appversie | Appwinkel → ESP Screen Manager → Update | Alle indelingen in `/data/screens.json` |
| Nieuwe schermfunctie/kaart | Knop **Bijwerken** bij het scherm, of vinkje **Elke nacht automatisch bijwerken** (handmatig: Firmware & USB → Wifi / OTA) | Eigen YAML, sleutels en CYD-kalibratie; app stuurt tegels opnieuw |
| Different entities, names, or order | Save in ESP Screens | Wi-Fi, keys, calibration |
| New management page/app version | App store → ESP Screen Manager → Update | All layouts in `/data/screens.json` |
| New screen feature/card | The **Update** button on the screen, or the **Update automatically every night** checkbox (manually: Firmware & USB → Wi-Fi / OTA) | Own YAML, keys, and CYD calibration; the app resends tiles |
De eigen YAML verwijst naar de firmwarepakketten in `main`. Bij een nieuwe build
haalt ESPHome de nieuwste gepubliceerde pakket- en componentcode op. Je vervangt
je eigen YAML dus niet door een nieuw downloadbestand. Wifi, naam en sleutels
staan buiten het gedeelde pakket en blijven gelijk.
The device's own YAML references the firmware packages on `main`. On a new build,
ESPHome fetches the latest published package and component code. So you don't
replace your own YAML with a new downloaded file. Wi-Fi, name, and keys
live outside the shared package and stay the same.
Maak vóór updates een Home Assistant-back-up inclusief ESP Screen Manager en
de eigen ESPHome-configuraties. **Verwijderen/herinstalleren** van een app is niet hetzelfde
als updaten; daarmee kun je de gegevensmap wissen. Houd de apparaatnaam en de
entity-ID van **Tegelinstellingen** gelijk, zodat de bestaande indeling gekoppeld blijft.
Make a Home Assistant backup before updates, including ESP Screen Manager and
the device's own ESPHome configurations. **Removing/reinstalling** an app is not the same
as updating; that can wipe the data folder. Keep the device name and the
entity ID of **Tile settings** the same, so the existing layout stays linked.
Voor een nieuwe ondersteunde kaart update je eerst de app, daarna de firmware.
De beheerder moet protocol- en gegevensmigraties achterwaarts compatibel maken;
zie [RELEASING.md](RELEASING.md). Voor terugrollen kun je `ref: main` in je eigen
YAML tijdelijk vervangen door een eerdere releasetag, zonder de sleutels te wijzigen.
For a newly supported card, update the app first, then the firmware.
The maintainer keeps protocol and data migrations backward compatible;
see [RELEASING.md](RELEASING.md). To roll back, you can temporarily replace `ref: main`
in your own YAML with an earlier release tag, without changing the keys.
## Als iets niet werkt
## If something doesn't work
- **Geen scherm in de lijst:** controleer of de nieuwe Easy Setup-firmware draait,
de ESPHome-integratie verbonden is en de tekstentiteit **Tegelinstellingen**
niet uitgeschakeld is. De oude handmatige firmware publiceert die standaard niet.
- **Wel tegels, geen acties:** geef het apparaat toestemming voor HA-acties.
- **Niet beschikbaar:** controleer of de geselecteerde entiteit in HA bestaat en
beschikbaar is. Een hernoemde entity-ID moet je opnieuw kiezen.
- **Geen OTA:** controleer wifi/IP en het oorspronkelijke OTA-wachtwoord. Gebruik
zo nodig dezelfde eigen YAML via USB. Genereer geen nieuwe identiteit.
- **Build mislukt:** lees de eerste fout, controleer ESPHome-versie en internet voor
GitHub/fontdownloads. Gebruik bij te weinig Raspberry-geheugen tijdelijk een
krachtigere computer voor compileren; de YAML blijft hetzelfde.
- **Bestaand handmatig scherm migreren:** bewaar de oude YAML en neem de bestaande
apparaatnaam, API-sleutel en OTA-wachtwoord over in het nieuwe installatieprofiel.
Kies daarna de tegels in de app. De oude vaste tegel-substituties worden niet
automatisch in de nieuwe beheerpagina geïmporteerd.
- **No screen in the list:** check that the new Easy Setup firmware is running,
the ESPHome integration is connected, and the **Tile settings** text entity
isn't disabled. The old manual firmware doesn't publish that by default.
- **Tiles show but no actions:** grant the device permission for HA actions.
- **Unavailable:** check that the selected entity exists in HA and is
available. A renamed entity ID needs to be chosen again.
- **No OTA:** check Wi-Fi/IP and the original OTA password. If needed,
use the same own YAML over USB. Don't generate a new identity.
- **Build fails:** read the first error, check the ESPHome version and internet for
GitHub/font downloads. If the Raspberry Pi is low on memory, temporarily use a
more powerful computer to compile; the YAML stays the same.
- **Migrating an existing manual screen:** keep the old YAML and carry over the
existing device name, API key, and OTA password into the new installation profile.
Then choose the tiles in the app. The old fixed tile substitutions aren't
automatically imported into the new management page.
HA Container zonder Supervisor heeft geen appwinkel. Deze installatiehandleiding
richt zich op Home Assistant OS; de ontwikkelserver is geen productieroute voor
een los openbaar portal.
HA Container without Supervisor has no App store. This installation guide
targets Home Assistant OS; the development server is not a production route for
a standalone public portal.
Gebruikte HA-mechanismen: [Ingress](https://developers.home-assistant.io/docs/apps/presentation/),
[interne HA-API](https://developers.home-assistant.io/docs/apps/communication/) en
[ESPHome-pakketten](https://esphome.io/components/packages/).
HA mechanisms used: [Ingress](https://developers.home-assistant.io/docs/apps/presentation/),
[the internal HA API](https://developers.home-assistant.io/docs/apps/communication/), and
[ESPHome packages](https://esphome.io/components/packages/).
## Scherminstellingen aanpassen (vanaf 0.1.2)
## Adjusting screen settings (from 0.1.2)
Update ESP Screen Manager naar 0.1.2 en installeer één keer de nieuwe firmware
via je **bestaande** ESPHome-apparaat → Install → Wirelessly. Behoud de eigen YAML
met wifi en sleutels. Open daarna het scherm in ESP Screen Manager en klap
**Scherminstellingen** open. Klik na aanpassen op **Opslaan & naar scherm**.
Hierna vragen wijzigingen aan deze instellingen geen nieuwe firmwareflash.
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 expand
**Screen settings**. After adjusting, click **Save & send to screen**.
After this, changes to these settings don't need a new firmware flash.
| Instelling | Mogelijkheden | Standaard |
| Setting | Options | Default |
|---|---|---|
| Automatisch standby | Aan/uit | Aan |
| Standby na | 1–1440 minuten na de laatste aanraking | 10 minuten |
| Helderheid normaal | 5–100% | 100% |
| Helderheid standby | 0–100%, maximaal normale helderheid | 20% |
| Nachtstand | Aan/uit; geldt tijdens standby | Aan |
| Begin/einde nacht | Uur en minuut, ook over middernacht | 22:00–07:00 |
| Helderheid nacht | 0–100%, maximaal normale helderheid | 10% |
| Klok tonen | Aan/uit | Aan |
| Tijdnotatie | 24 of 12 uur, zonder AM/PM | 24 uur |
| Terug naar pagina 1 | Sluit ook detailmenu’s bij standby | Uit |
| Vegen tussen pagina’s | Native horizontale swipe, firmware 0.2.7+ | Uit |
| Guition draaien | 0°, 90°, 180°, 270°, firmware 0.2.9+ | 0° |
| Auto standby | On/off | On |
| Standby after | 1–1440 minutes after the last touch | 10 minutes |
| Normal brightness | 5–100% | 100% |
| 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 |
| Swipe between pages | Native horizontal swipe, firmware 0.2.7+ | Off |
| Guition rotation | 0°, 90°, 180°, 270°, firmware 0.2.9+ | 0° |
Nachturen gebruiken de tijdzone van het ESPHome-apparaat en de tijd uit HA.
Zonder geldige tijd gebruikt het scherm de gewone standbyhelderheid; gelijke
begin- en eindtijd schakelen het nachtvenster uit. Op 0% gaat alleen de
achtergrondverlichting uit: dit is geen deep sleep en geen schermbeveiliging.
De eerste tik wekt het scherm zonder een apparaat te bedienen.
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.
De add-on bewaart alles per scherm in zijn permanente gegevens. Het scherm bewaart
de laatst ontvangen instellingen ook in preferences; ESPHome bundelt die
schrijfacties (normaal maximaal een minuut). Trek daarom niet direct na opslaan
de voeding los. Bestaande CYD-kalibratie, tegels, API- en OTA-sleutels blijven staan.
Een offline scherm krijgt wijzigingen zodra het terugkomt. Gewone HA-statusupdates
wekken het scherm niet en veranderen de standbytimer niet.
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.
Bij oudere firmware toont de beheerpagina dat eerst een update nodig is.
De tegels blijven bruikbaar. Handmatige YAML-profielen blijven hun substitutions
gebruiken; voor beheer via deze app gebruik je het Easy Setup-pakket.
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.
De huidige Guition gebruikt de native ST7701S-configuratie; zie
[de hardwarevergelijking](GUITION_FACTORY_REFERENCE.md). Instellingen en
tegelkleuren veranderen geen paneeltimings. Controleer beeld en touch fysiek.
The current Guition uses the native ST7701S configuration; see
[the hardware comparison](GUITION_FACTORY_REFERENCE.md). Settings and
tile colors don't change panel timings. Physically check the display and touch.
+113 -113
View File
@@ -1,173 +1,173 @@
# Guition ESP32-S3 4-inch wallbox — 480 × 480
Deze branch voegt een apart profiel toe voor de **Guition 4848S040** met
ST7701S RGB-display en **GT911 capacitieve touch**, ESP32-S3, 16 MB flash en
8 MB octal PSRAM. De naam/2mm-wandplaat beschrijft ook de behuizing; controleer
altijd de elektronica. Dit profiel configureert geen relais.
This branch adds a separate profile for the **Guition 4848S040** with an
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.
Hardwarebron: [ESPHome Guition-bordbeschrijving](https://devices.esphome.io/devices/guition-esp32-s3-4848s040/)
en de ingebouwde [ST7701S-driver](https://esphome.io/components/display/st7701s/).
De paneelconfiguratie volgt de originele, fysiek schoon bevonden fabrikantdemo;
zie [de vergelijking](GUITION_FACTORY_REFERENCE.md). Er is geen lokale RGB-driver
of periodiek herstel-script nodig. De GT911 gebruikt ongemirrorde coördinaten.
Hardware source: the [ESPHome Guition board writeup](https://devices.esphome.io/devices/guition-esp32-s3-4848s040/)
and the built-in [ST7701S driver](https://esphome.io/components/display/st7701s/).
The panel configuration follows the original manufacturer demo, found physically clean;
see [the comparison](GUITION_FACTORY_REFERENCE.md). No local RGB driver
or periodic recovery script is needed. The GT911 uses unmirrored coordinates.
## Bestanden
## Files
- `guition-4848s040.yaml`: neutrale hardware + 480×480-interface.
- `guition-device.example.yaml`: eigen apparaat-/tegelinstellingen.
- `guition-device.yaml`: jouw lokale profiel, buiten Git.
- `secrets.yaml`: lokale wifi/API/OTA-instellingen, buiten Git.
- `tools/verify_gt911.py`: fysieke pixelcontrole; geen resistieve ADC-kalibratie.
- `guition-4848s040.yaml`: neutral hardware + 480×480 interface.
- `guition-device.example.yaml`: personal device/tile settings.
- `guition-device.yaml`: your local profile, outside Git.
- `secrets.yaml`: local Wi-Fi/API/OTA settings, outside Git.
- `tools/verify_gt911.py`: physical pixel check; no resistive ADC calibration.
Het 2,8-inch CYD-profiel blijft apart. Flash dat niet naar de Guition en neem
geen `calibration.yaml` of XPT2046-correctie over.
The 2.8-inch CYD profile stays separate. Don't flash that to the Guition, and don't
carry over `calibration.yaml` or the XPT2046 correction.
## Interface
### Montage en schermrotatie (runtime 0.2.9+)
### Mounting and screen rotation (runtime 0.2.9+)
Installeer Guition-firmware 0.2.9 en ESP Screen Manager 0.2.9. Open het scherm
in de beheerpagina, ga naar **Scherminstellingen** en kies bij **Scherm draaien**
0°, 90°, 180° of 270°, met de klok mee. Klik op opslaan. Een firmwareflash is
daarna niet meer nodig om de hoek te wijzigen. De instelling blijft in de appdata
en op het scherm bewaard na een herstart.
Install Guition firmware 0.2.9 and ESP Screen Manager 0.2.9. Open the screen
in the management page, go to **Screen settings**, and choose 0°, 90°, 180°,
or 270° (clockwise) under **Rotate screen**. Click 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.
Dit gebruikt de native ESPHome/LVGL-rotatie voor beeld én touch, zonder wijzigingen
aan de paneelinitialisatie of GT911-spiegeling. Controleer na montage de vier
hoeken en de navigatie fysiek; een renderproef test geen aanrakingen. De optie is
alleen zichtbaar voor de Guition nadat zijn nieuwe firmware door HA is ontdekt.
De CYD blijft op zijn bestaande oriëntatie met zijn eigen kalibratie.
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
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.
Zes tegels van **218 × 108 pixels** per pagina, 12px tussenruimte en een
aparte navigatiestrook. In ESP Screen Manager passen twintig tegels op maximaal
vier pagina’s; tot zes verdwijnt de navigatie. De huidige interface heeft een
lichtgrijze achtergrond, witte kaarten en gekleurde domeiniconen. Vanaf 0.2.10 kun
je per tegel een pastel achtergrond kiezen met donkere tekst. Standby begint
standaard na tien minuten zonder aanraking en is instelbaar in de beheerpagina.
Vanaf 0.2.13 dimt de backlight via de LEDC-hardwarefader (`backlight_fade.h`,
1,5 s naar standby, 80 ms wakker): de volledige LVGL-herteken bij standby
onderbreekt de overgang dan niet meer. ESPHome's lichtstatus wordt na de fade
gesynchroniseerd, zodat de entity in HA en latere overgangen kloppen.
Six tiles of **218 × 108 pixels** per page, 12px spacing, and a
separate navigation strip. In ESP Screen Manager, twenty tiles fit across up to
four pages; 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 dark text per tile. Standby starts
after ten minutes without touch by default and is adjustable in the management page.
From 0.2.13, the backlight dims via the LEDC hardware fader (`backlight_fade.h`,
1.5 s to standby, 80 ms to wake): the full LVGL redraw on standby no longer
interrupts the transition. ESPHome's light state is synced after the fade,
so the entity in HA and later transitions stay correct.
De bestaande tegelacties, climatebediening en vacuumkaart zijn behouden.
Alle kaarttypen zijn beschikbaar op alle twintig runtime-posities. Alleen in
het oude handmatige profiel blijft de vacuumkaart op tegel 6 en hebben posities
8/10 beperkingen; zie [TEGELS.md](TEGELS.md).
The existing tile actions, climate control, and vacuum card are preserved.
All card types are available at all twenty runtime positions. Only in
the old manual profile does the vacuum card stay on tile 6 and do positions
8/10 have limitations; see [TILES.md](TILES.md).
## Nieuwe installatie
## New installation
Volg de Python-/USB-voorbereiding in [README.md](../README.md), in een verse
kopie. Maak dit profiel:
Follow the Python/USB setup in [README.md](../README.md), in a fresh
copy. Create this profile:
```sh
python tools/new_device.py --board guition --name wallbox-keuken --friendly-name "Wallbox keuken"
python tools/new_device.py --board guition --name wallbox-kitchen --friendly-name "Wallbox kitchen"
```
Dit maakt `guition-device.yaml` en nieuwe secrets; bestaande bestanden worden
niet overschreven. Vul wifi in en wijzig de tegelentiteiten. Gebruik bij
meerdere borden een aparte map per apparaat. Het huidige lokale Guition-profiel
van de eigenaar mag diens bestaande secrets gebruiken.
This creates `guition-device.yaml` and new secrets; existing files are
not overwritten. Fill in Wi-Fi and change the tile entities. With
multiple boards, use a separate folder per device. The owner's current local
Guition profile may use their existing secrets.
Controleer de seriële poort en chip voordat je uploadt. Voor het geteste bord
bleken hogere seriële snelheden bij uitlezen onbetrouwbaar. Gebruik 115200 baud:
Check the serial port and chip before uploading. On the tested board,
higher serial speeds proved unreliable when reading. Use 115200 baud:
```sh
python -m esphome config guition-device.yaml
python -m esphome compile guition-device.yaml
```
Flash via `esphome run` als de USB-verbinding betrouwbaar is. Voor expliciet
115200 baud kun je de gecombineerde factory-image gebruiken. Vervang zowel
poort als apparaatnaam in het pad door jouw waarden:
Flash via `esphome run` if the USB connection is reliable. For explicit
115200 baud, you can use the combined factory image. Replace both the
port and the device name in the path with your own values:
```sh
python -m esptool --chip esp32s3 --port <USB_POORT> --baud 115200 write-flash 0 .esphome/build/wallbox-keuken/.pioenvs/wallbox-keuken/firmware.factory.bin
python -m esptool --chip esp32s3 --port <USB_PORT> --baud 115200 write-flash 0 .esphome/build/wallbox-kitchen/.pioenvs/wallbox-kitchen/firmware.factory.bin
```
De factory-image hoort bij dit S3-profiel en begint op adres **0**, anders dan
sommige klassieke ESP32-images. Bewaar een herstelkopie vóór vervanging van
bestaande firmware als die later nog nodig is. Houd binaries en logs lokaal.
The factory image belongs to this S3 profile and starts at address **0**, unlike
some classic ESP32 images. Keep a recovery copy before replacing
existing firmware if you might need it later. Keep binaries and logs local.
## GT911 en oriëntatie testen
## Testing GT911 and orientation
De GT911 geeft pixels door. Meestal is geen kalibratie nodig; een verkeerde
rotatie/transform mag niet met de CYD-affinewizard worden weggewerkt.
The GT911 reports pixels directly. Usually no calibration is needed; a wrong
rotation/transform should not be papered over with the CYD affine wizard.
Met een werkende wifi/API-verbinding:
With a working Wi-Fi/API connection:
```sh
python diagnostics/control_ui.py touch_diagnostics --host wallbox-keuken.local --name wallbox-keuken
python tools/verify_gt911.py --port <USB_POORT> --output measurements-guition.json
python diagnostics/control_ui.py end_touch_diagnostics --host wallbox-keuken.local --name wallbox-keuken
python diagnostics/control_ui.py touch_diagnostics --host wallbox-kitchen.local --name wallbox-kitchen
python tools/verify_gt911.py --port <USB_PORT> --output measurements-guition.json
python diagnostics/control_ui.py end_touch_diagnostics --host wallbox-kitchen.local --name wallbox-kitchen
```
Er verschijnen vijf kruisjes. De wizard vraagt drie afzonderlijke tikken per
punt; eerst Enter en daarna uitsluitend het genoemde kruisje aanraken. Fout
maximaal 16px, spreiding maximaal 18px. De test stuurt geen HA-acties.
Five crosshairs appear. The wizard asks for three separate taps per
point; press Enter first, then touch only the named crosshair. Error
at most 16px, spread at most 18px. The test doesn't send any HA actions.
Zonder wifi kun je eerst een build maken met `-s CALIBRATION_ON_BOOT true`,
die na USB-upload direct het GT911-meetscherm toont. Na controle opnieuw
bouwen/flashen zonder die override. Deze compatibiliteitsnaam opent alleen
een pixeltest; hij voert geen ADC-kalibratie uit.
Without Wi-Fi, you can first build with `-s CALIBRATION_ON_BOOT true`,
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.
Op het geteste paneel zijn beide GT911-assen gespiegeld: `TOUCH_MIRROR_X` en
`TOUCH_MIRROR_Y` staan op `true`. Standaard is `LVGL_ROTATION: "0"`. Bij een andere montage stel je de gewenste
LVGL-rotatie in en geef je dezelfde waarde aan de wizard, bijvoorbeeld
`--rotation 90`. Controleer alle hoeken; verander de GT911 `TOUCH_SWAP_XY` /
`TOUCH_MIRROR_X` / `TOUCH_MIRROR_Y` alleen als de fysieke meting dat vereist.
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.
## HA en acceptatie
## HA and acceptance
Voeg het nieuwe apparaat toe via de ESPHome-integratie (naam/IP, poort 6053,
API-sleutel uit secrets). Geef toestemming voor HA-acties en gebruik
`DIRECT_ACTIONS: "true"` zodra de juiste entiteiten gecontroleerd zijn.
Add the new device via the ESPHome integration (name/IP, port 6053,
API key from secrets). Grant permission for HA actions and use
`DIRECT_ACTIONS: "true"` once the correct entities have been checked.
```sh
python diagnostics/run_ui_test.py --host wallbox-keuken.local --name wallbox-keuken
python diagnostics/run_ui_test.py --host wallbox-kitchen.local --name wallbox-kitchen
python -m unittest discover -s tests -p 'test_*.py'
```
Doorloop ook de fysieke controles uit [ACCEPTATIE.md](ACCEPTATIE.md), met de
GT911-wizard in plaats van de XPT2046-kalibratie. Controleer beeld, juiste
aanrakingen, paginering, lange druk, climate/vacuum, echte HA-terugmelding,
standby en herstel na herstart. Een compilatie/renderproef vervangt die
fysieke controle niet. De testuitkomst van het oorspronkelijke CYD-bord
zegt niets over dit nieuwe bord.
Also go through the physical checks in [ACCEPTANCE.md](ACCEPTANCE.md), using the
GT911 wizard instead of the XPT2046 calibration. Check the display, correct
touches, pagination, long press, climate/vacuum, real HA feedback,
standby, and recovery after a restart. A compile/render test doesn't replace
that physical check. The original CYD board's test outcome
says nothing about this new board.
## Gerenderde interface inspecteren
## Inspecting the rendered interface
```sh
python diagnostics/capture_ui.py --host wallbox-keuken.local --name wallbox-keuken --output diagnostics/guition-home.png
python diagnostics/capture_ui.py --host wallbox-kitchen.local --name wallbox-kitchen --output diagnostics/guition-home.png
```
Dit maakt alleen op verzoek een LVGL-snapshot en stuurt een 240×240-preview
via de versleutelde API. De tijdelijke buffer wordt na ongeveer 24 seconden
vrijgegeven. Het beeld controleert de renderer; het bewijst niet dat de fysieke
RGB-signalen, schermkleuren of montageoriëntatie goed zijn. De renderproef
controleert ook of zichtbare klikgebieden binnen het 480×480-scherm vallen.
This only takes an LVGL snapshot on request and sends a 240×240 preview
over the encrypted API. The temporary buffer is released after about 24 seconds.
The image verifies the renderer; it doesn't prove the physical
RGB signals, screen colors, or mounting orientation are correct. The render test
also checks that visible click areas fall within the 480×480 screen.
## Herstelkopie van dit testbord
## Recovery copy of this test board
De oorspronkelijke gebruikte firmware inclusief bootloader, partitietabel
en NVS is lokaal bewaard als `diagnostics/guition-original-recovery.bin`.
De lengtes van de vijf applicatiesegmenten bepaalden de benodigde 4.788.224
bytes; dit is geen kopie van alle 16 MB flash. De stub controleerde de MD5
van ieder uitgelezen blok. SHA-256 van het complete herstelbestand:
The original firmware in use, including bootloader, partition table,
and NVS, is stored locally as `diagnostics/guition-original-recovery.bin`.
The lengths of the five application segments determined the needed 4,788,224
bytes; this is not a copy of the full 16 MB flash. The stub verified the MD5
of every block read. SHA-256 of the complete recovery file:
```text
a656c793c422848b5ad72bc16545fb92c844b7dfba029f4e4399d22444a9e046
```
Deze kopie is privé, hoort uitsluitend bij het geteste bord en wordt niet
meegecommit of geëxporteerd. Herstellen gebeurt op adres 0, met dezelfde
115200-baudopdracht als de factory-image, maar met dit herstelbestand.
This copy is private, belongs only to the tested board, and is not
committed or exported. Recovery happens at address 0, with the same
115200-baud command as the factory image, but with this recovery file.
## RGB-geheugeninstellingen
## RGB memory settings
De pixelklok staat op 16 MHz: op het testbord verdween daarmee het zachte
flikkeren van de 12MHz-instelling. Voor de RGB-bouncebuffer worden code en
constante data vanuit octal PSRAM uitgevoerd, met 64KB datacache en 64-byte
cachelijnen; herstel van de RGB-stroom gebeurt op VSYNC. Deze instellingen
volgen [Espressifs RGB-LCD-aanbevelingen](https://docs.espressif.com/projects/esp-idf/en/v5.5.4/esp32s3/api-reference/peripherals/lcd/rgb_lcd.html).
Controleer fysiek op incidentele glitches onder wifi-/renderbelasting; een
software-snapshot kan een verstoring van het paneelsignaal niet bewijzen.
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).
Physically check for occasional glitches under Wi-Fi/render load; a
software snapshot can't prove a disturbance in the panel signal.
+77 -77
View File
@@ -1,99 +1,99 @@
# Guition 4848S040: onafhankelijke fabrikanttest
# Guition 4848S040: independent manufacturer test
Deze test onderscheidt onze ESPHome/UI van de oorspronkelijke paneelaansturing.
Een passende demo is gevonden in het fabrikantpakket dat SpotPear aanbiedt:
This test distinguishes our ESPHome/UI from the original panel driving.
A matching demo was found in the manufacturer package offered by SpotPear:
- [Verkoper met downloadlink](https://spotpear.com/ESP32-S3-4-inch-LCD-Touchscreen-Display-SHT20-Temperature-Humidity-480x480-RS485-Relay-GC9503-ST7701-FT6336U-GT911-86-TVbox/forum-answer/357.html)
- [Origineel archief](https://cdn.static.spotpear.com/uploads/picture/learn/ESP32/ESP32-S3-4inch/4.0inch_ESP32-4848S040.zip)
- [Community-uitleg voor bouwen met LVGL 8/9](https://github.com/paulhamsh/LVGL_GUITION)
- [Vendor with download link](https://spotpear.com/ESP32-S3-4-inch-LCD-Touchscreen-Display-SHT20-Temperature-Humidity-480x480-RS485-Relay-GC9503-ST7701-FT6336U-GT911-86-TVbox/forum-answer/357.html)
- [Original archive](https://cdn.static.spotpear.com/uploads/picture/learn/ESP32/ESP32-S3-4inch/4.0inch_ESP32-4848S040.zip)
- [Community write-up for building with LVGL 8/9](https://github.com/paulhamsh/LVGL_GUITION)
In het archief:
In the archive:
- `1-Demo/Demo_Arduino/1_2_4.0_LvglWidgets/4.0_LvglWidgets/`: broncode.
- `1-Demo/Demo_Arduino/Libraries/Arduino_GFX-master/`: meegeleverde paneeldriver.
- `8-Burn operation/Burn files/4.0_LvglWidgets.bin`: samengevoegde firmware,
652640 bytes, flashadres 0. Bootloader op 0, partitietabel op 0x8000,
applicatie op 0x10000.
- SHA256 van die demo: `9662c193fc52407bba2ed1462c582d40148f7d8eedfc806db4e8fff7685abba1`.
- `1-Demo/Demo_Arduino/1_2_4.0_LvglWidgets/4.0_LvglWidgets/`: source code.
- `1-Demo/Demo_Arduino/Libraries/Arduino_GFX-master/`: bundled panel driver.
- `8-Burn operation/Burn files/4.0_LvglWidgets.bin`: combined firmware,
652640 bytes, flash address 0. Bootloader at 0, partition table at 0x8000,
application at 0x10000.
- SHA256 of that demo: `9662c193fc52407bba2ed1462c582d40148f7d8eedfc806db4e8fff7685abba1`.
Gebruik uitsluitend de Widgets-demo voor de displaytest. De andere meegeleverde
voorbeelden zijn relay- en muziektoepassingen. De Widgets-bron gebruikt alleen
paneel, GT911 en achtergrondverlichting en heeft geen HA-/wifi-configuratie.
Use only the Widgets demo for the display test. The other bundled
examples are relay and music applications. The Widgets source only uses the
panel, GT911, and backlight, and has no HA/Wi-Fi configuration.
## Opvallende referentie-instellingen
## Notable reference settings
De oorspronkelijke bron gebruikt ArduinoGFX, `st7701_type1_init_operations`,
16 MHz pixelklok, RGB-pinnen R=11/12/13/14/0, G=8/20/3/46/9/10,
B=4/5/6/7/15. Horizontaal front/pulse/back=10/8/50; verticaal=10/8/20.
De paneelmodus is 0x3A=0x60, RGB666 op een 16-bits bedrade bus, met 0xCD=0x00.
Rotatie 0 schrijft C7=0 in registerbank 0x10 en MADCTL=0 in bank 0.
De achtergrondverlichting staat via GPIO38 continu aan, zonder PWM.
The original source uses ArduinoGFX, `st7701_type1_init_operations`,
a 16 MHz pixel clock, RGB pins R=11/12/13/14/0, G=8/20/3/46/9/10,
B=4/5/6/7/15. Horizontal front/pulse/back=10/8/50; vertical=10/8/20.
The panel mode is 0x3A=0x60, RGB666 on a 16-bit wired bus, with 0xCD=0x00.
Rotation 0 writes C7=0 in register bank 0x10 and MADCTL=0 in bank 0.
The backlight is on continuously via GPIO38, without PWM.
De gamma- en spanningswaarden lijken op ESPHome's ST7701S-basis, maar de volgorde,
porches en rotatiecommando's verschillen. Dat is aanleiding voor vergelijking,
geen bewijs dat een specifieke wijziging strepen oplost.
The gamma and voltage values resemble ESPHome's ST7701S base, but the order,
porches, and rotation commands differ. That's grounds for comparison,
not proof that a specific change fixes banding.
## Back-up en terugkeer
## Backup and recovery
Verifieer eerst de chip/MAC en de echte USB-poort. Een volledige flashback-up is
het veiligst. Voor deze specifieke demo worden alleen sectoren binnen de eerste
1 MiB overschreven. Een exacte back-up van dat bereik is voldoende om die
overschrijving terug te draaien als de demo geen andere flashgebieden beschrijft.
Bewaar daarnaast de eigen firmware/YAML. Flashback-ups bevatten persoonlijke
sleutels: alleen lokaal opslaan, nooit in Git.
First verify the chip/MAC and the actual USB port. A full flash backup is
safest. For this specific demo, only sectors within the first
1 MiB are overwritten. An exact backup of that range is enough to
undo that overwrite, as long as the demo doesn't write to other flash regions.
Also keep the device's own firmware/YAML. Flash backups contain personal
keys: keep them local only, never in Git.
Gebruik geen erase-all. Herstel na de test de geback-upte sectoren en verifieer de
ESPHome-identiteit, versie, voorkeuren en HA-koppeling. Leg het fysieke resultaat
apart vast: een succesvolle upload zegt niets over het zichtbare beeld.
Don't use erase-all. After the test, restore the backed-up sectors and verify the
ESPHome identity, version, preferences, and HA pairing. Record the physical result
separately: a successful upload says nothing about the visible image.
## Uitgevoerde test op 12 september 2026
## Test performed on September 12, 2026
- Fabrikantarchief opgehaald en de Widgets-bron plus meegeleverde driver gelezen.
- De eerste 1 MiB (alle door deze demo overschreven sectoren) via USB geback-upt;
921600/460800 baud gaven communicatieproblemen, 115200 baud werkte.
- Originele Widgets-binary ongewijzigd op adres 0 geschreven; hashverificatie geslaagd.
- USB-bootlog meldt `LVGL Widgets Demo` en `Setup done`, vervolgens GT911-polling.
Ook meldt de oorspronkelijke demo GPIO-fouten bij het opzetten; daarom blijft
fysieke bevestiging nodig. De eigenaar bevestigt daarna: de fabrikantdemo is schoon, zonder strepen.
Daarmee is goede beeldweergave op dit fysieke paneel aangetoond. Dit sluit
niet iedere hardware-/voedingsfactor uit, maar maakt onze aansturing de
eerste onderzoekslijn.
- Fetched the manufacturer archive and read the Widgets source plus bundled driver.
- Backed up the first 1 MiB (every sector this demo overwrites) over USB;
921600/460800 baud caused communication problems, 115200 baud worked.
- Wrote the original Widgets binary unchanged at address 0; hash verification passed.
- The USB boot log reports `LVGL Widgets Demo` and `Setup done`, then GT911 polling.
The original demo also reports GPIO errors during setup; physical
confirmation therefore remains necessary. The owner then confirmed: the manufacturer demo is clean, no banding.
That demonstrates good image output on this physical panel. This doesn't
rule out every hardware/power factor, but it makes our own driving the
first line of investigation.
## Native ESPHome-kandidaat 0.1.3
## Native ESPHome candidate 0.1.3
De standaard `st7701s`-component krijgt dezelfde 16 MHz-klok en horizontale
10/8/50 en verticale 10/8/20 timing als de fabrikantdemo. SPI gebruikt MODE0;
kleurvolgorde RGB, geen inversie of hardwarematige spiegeling. Na de ingebouwde
initialisatie worden de 16-bits busconfiguratie CD=00 en de standaard registerbank
expliciet gekozen, gevolgd door 3A=60 en de wachttijd na sleep-out. De GT911 blijft
in dezelfde ongemirrorde oriëntatie. De ESPHome RGB-driver wordt niet gekopieerd
of gepatcht; de eerdere extra SDK-cache-/restart-instellingen zijn verwijderd.
The standard `st7701s` component gets the same 16 MHz clock and horizontal
10/8/50 and vertical 10/8/20 timing as the manufacturer demo. SPI uses MODE0;
color order RGB, no inversion or hardware mirroring. After the built-in
initialization, the 16-bit bus configuration CD=00 and the standard register bank
are explicitly selected, followed by 3A=60 and the wait after sleep-out. The GT911 stays
in the same unmirrored orientation. The ESPHome RGB driver isn't copied
or patched; the earlier extra SDK cache/restart settings have been removed.
De eigenaar meldt dat deze kandidaat schoner is, maar nog enkele vaste verticale
banden toont. Dit is dus geen afgeronde oplossing. De fabrikantdemo blijft de
schone referentie. Verschillen zijn onder meer ESP-IDF/LVGL-versies, framebuffer-
en bouncebuffergebruik, wifi/API, PWM en de extra initialisatiestappen van de
standaarddriver (inclusief software-reset). Native betekent hier de ingebouwde
ESPHome-driver, niet byte-voor-byte dezelfde uitvoering als de fabrikantdemo.
The owner reports that this candidate is cleaner but still shows a few fixed vertical
bands. So this is not a finished solution. The manufacturer demo remains the
clean reference. Differences include ESP-IDF/LVGL versions, framebuffer
and bounce buffer usage, Wi-Fi/API, PWM, and the extra initialization steps of the
standard driver (including a software reset). "Native" here means the built-in
ESPHome driver, not a byte-for-byte identical execution to the manufacturer demo.
Daarna is alleen de Guition-interface licht vormgegeven: achtergrond F7F7F7,
witte kaarten, rand DDDDDD, donkere tekst en blauwe accenten. Ook de detailkaarten
gebruiken lichte bedieningselementen. Geometrie, paginering, touch, HA-indeling en
opgeslagen instellingen blijven behouden. Deze stijlwijziging is geen strepenfix.
After that, only the Guition interface was given a light design: background F7F7F7,
white cards, border DDDDDD, dark text, and blue accents. The detail cards also
use light controls. Geometry, pagination, touch, HA layout, and
saved settings are preserved. This style change is not a banding fix.
### Lichte interface: softwarecontrole
### Light interface: software check
De Python-suite (33 tests), zeven C++-regressietests en packagegeneratorcontrole
slagen. De eerste lichte firmware is via OTA geïnstalleerd; tien paginacontroles
plus vijftig overlaywisselingen slagen zonder HA-acties. De schermopname toont de
nieuwe lichte kaarten met de bestaande HA-indeling. Lange namen kregen daarna
vaste regelhoogtes met afkapping, zodat titel en status niet overlappen.
Een interne schermopname bewijst geen storingsvrije fysieke paneeluitvoer.
The Python suite (33 tests), seven C++ regression tests, and the package generator check
pass. The first light firmware was installed over OTA; ten page checks
plus fifty overlay switches pass without HA actions. The screen capture shows the
new light cards with the existing HA layout. Long names then got
fixed line heights with truncation, so the title and status don't overlap.
An internal screen capture doesn't prove glitch-free physical panel output.
De definitieve lichte versie (config_hash 0x0a70a194) is via OTA geïnstalleerd.
Beide Easy Setup- en beide handmatige profielen bouwen succesvol. De eigenaar
bevestigt vervolgens: ‘Stijl goed, geen banden zichtbaar’. Dit is fysieke
acceptatie van het huidige beeld, geen duurtest na langdurige standby en geen
bewijs dat alleen een driverwijziging de oorzaak heeft opgelost.
The final light version (config_hash 0x0a70a194) was installed over OTA.
Both Easy Setup and both manual profiles build successfully. The owner
then confirmed: 'Style good, no bands visible'. This is physical
acceptance of the current image, not an endurance test after prolonged standby, and not
proof that a driver change alone fixed the root cause.
-32
View File
@@ -1,32 +0,0 @@
# Problemen oplossen
| Symptoom | Eerst controleren |
|---|---|
| Geen USB-poort | Datakabel, andere USB-poort, bordvoeding; vergelijk `python -m serial.tools.list_ports` voor/na aansluiten. Installeer zo nodig de driver van de USB-chipfabrikant. |
| Permission denied op Linux | Toegang tot de seriële devicegroep (vaak `dialout`); opnieuw inloggen na een groepswijziging. |
| Poort bezet | Stop ESPHome-logs, IDE-monitor en andere seriële lezers. Eén lezer tegelijk. |
| Upload blijft verbinden | Controleer juiste bord/poort. Houd BOOT ingedrukt tijdens verbinden en laat daarna los als het bord dat vereist. |
| Build faalt | Python 3.11–3.14 en ESPHome 2026.6.2; volledige uitgepakte map, lokale fonts/components aanwezig, internet en schijfruimte. Bewaar eerste echte fout uit de buildlog. |
| Wit/zwart of verkeerd gedraaid beeld | Controleer ILI9341 + XPT2046-variant. Niet willekeurig de pinnen, rotatie of SPI-instellingen van een ander CYD-model kopiëren. |
| Geen meetscherm | De upload moet klaar zijn, niet alleen de build. Flash met `-s CALIBRATION_ON_BOOT true`. Zoek in USB-logs `USB calibration ready`; normaal opstarten toont geen kruisjes. |
| Geen metingen | Vijf kruisjes zichtbaar, andere loglezer dicht, juiste poort. Druk eerst Enter in de wizard en tik daarna drie keer hetzelfde gevraagde punt, met loslaten ertussen. |
| Tik springt naar andere plek | Controleer onafhankelijke `verify`, eigen `calibration.yaml` en vaste oriëntatie. Niet dezelfde tikken gebruiken om zowel te fitten als te verifiëren. |
| Fit meldt spreiding/fout | Meet opnieuw volgens de prompts. Instabiele ADC-metingen niet oplossen door de tolerantie te verhogen; controleer voeding, kabel en touchhardware. |
| Dubbele HA-actie | Controleer zowel touchlogs als HA-automations. Gebruik niet tegelijk directe acties én een automation op de actie-sensor voor dezelfde handeling. |
| Wifi verbindt niet | 2,4GHz, juiste lokale secrets, netwerkbereik. USB-kalibratie heeft HA niet nodig. |
| HA ziet het bord niet | Handmatig IP uit logs gebruiken; poort 6053 bereikbaar, juiste encryptiesleutel, geen gastnetwerkisolatie. |
| Status werkt maar actie niet | HA-optie voor toegestane apparaat-acties, `DIRECT_ACTIONS: "true"`, echte entity-ID en ondersteunde actie controleren. |
| Vacuum/climate deels bruikbaar | Ondersteunde modi/attributen verschillen per integratie; zie TEGELS.md en test dezelfde actie eerst in HA. |
| Verkeerde paginering | `TILE_COUNT` is 1–10; tot zes verborgen knoppen, vanaf zeven twee pagina's. Opnieuw flashen na wijzigen. |
| Vastloper/reset | USB-log bewaren, resetreden/voeding controleren en renderproef draaien. Noteer handeling en tijdstip. |
Voor een USB-log (stop andere lezers):
```sh
python diagnostics/capture_serial.py --port <USB_POORT> --seconds 120
```
De bestaande `CYD_STABILITY.md` en `TEST_RESULTS.md` beschrijven eerder
onderzoek aan één specifiek bord. Hun meetwaarden zijn geen kalibratie voor
een nieuw bord. Begin bij [README.md](../README.md), behoud een werkende
lokale configuratie en verander één oorzaak tegelijk.
+380 -349
View File
@@ -1,52 +1,51 @@
# Updates publiceren zonder gebruikersconfiguratie te vervangen
# Publishing updates without replacing user configuration
## Indeling van de code en gegevens
## Layout of the code and data
- `main` is de distributiebranch voor de app **en beide** firmwarepakketten.
De Guition-branch blijft beschikbaar voor bordwerk; publiceer gedeelde releases
altijd ook naar main.
- `screen_manager/config.yaml` bevat de appversie. Verhoog die bij iedere apprelease.
Git push alleen is niet genoeg om een bestaande app een update aan te bieden.
- De appimage bevat uitsluitend code. Indelingen leven in `/data/screens.json`
(`version: 1`, `screens: {...}`). Een update/herbuild behoudt deze volumegegevens.
- De eigen ESPHome-YAML bevat naam, wifi-verwijzingen en unieke API/OTA-sleutels.
Gedeelde pakketten bevatten geen secrets, vaste eigenaarsentiteiten of wifi.
- CYD-kalibratie staat in ESP32-preferences. Behoud de preference-key, structuur
en partitie-indeling, of schrijf een expliciete migratie.
- Het tegelprotocol gebruikt `v: 1`. Houd oudere velden en domeinen bruikbaar.
Een gewijzigde opslagversie moet een geteste migratie met back-up krijgen.
De app weigert onbekende versies in plaats van de data leeg te overschrijven.
- `main` is the only distribution branch for the app **and both** firmware packages.
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`
(`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.
- CYD calibration lives in ESP32 preferences. Preserve the preference key, structure,
and partition layout, or write an explicit migration.
- The tile protocol uses `v: 1`. Keep older fields and domains usable.
A changed storage version must get a tested migration with a backup.
The app refuses unknown versions instead of overwriting the data blank.
## Voor elke release
## For every release
1. Pas de bronprofielen en gedeelde componenten aan. Draai
`python3 tools/generate_packages.py`; bewerk `packages/*.yaml` nooit rechtstreeks.
2. Draai alle Python-tests met aiohttp geïnstalleerd, alle `tests/*.cpp`, de
generator met `--check`, en compileer beide Easy Setup-profielen plus de
bestaande handmatige profielen. Doe dat na elkaar: profielen met dezelfde
`DEVICE_NAME` delen één build-map, en een parallelle build laat een upload
het verkeerde `firmware.bin` kiezen. Controleer dat er geen secrets in Git staan.
3. Test appstart, opslaan, opnieuw starten/updaten met bestaande indelingen,
opnieuw verbinden met HA en een ESP-herstart. Test een nieuwe kaart op echte
hardware. Een goede build vervangt fysieke touchacceptatie niet.
4. Verhoog appversie en firmwareprojectversie; schrijf CHANGELOG en concrete
testresultaten. Publiceer alleen compatibele wijzigingen rechtstreeks op main.
5. Commit en push main. Maak een onveranderlijke tag `screens-vX.Y.Z` van dezelfde
commit. Werk de Guition-branch bij. Test de remote YAML in een lege map:
alle componenten/fonts moeten via GitHub kunnen worden opgehaald.
6. De gebruiker controleert de appwinkel op updates en update ESP Screen Manager.
Voor nieuwe schermfuncties: bestaand ESPHome-apparaat → Install → Wirelessly.
De bestaande YAML blijft staan; `refresh: 0s` haalt bij elke build actuele code.
1. Update the source profiles and shared components. Run
`python3 tools/generate_packages.py`; never edit `packages/*.yaml` directly.
2. Run all Python tests with aiohttp installed, all `tests/*.cpp`, the
generator with `--check`, and compile both Easy Setup profiles plus the
existing manual profiles. Do that sequentially: profiles with the same
`DEVICE_NAME` share one build folder, and a parallel build can make an upload
pick the wrong `firmware.bin`. Check that no secrets are in Git.
3. Test app start, saving, restarting/updating with existing layouts,
reconnecting to HA, and an ESP restart. Test a new card on real
hardware. A good build doesn't replace physical touch acceptance.
4. Bump the app version and firmware project version; write the CHANGELOG and concrete
test results. Only publish compatible changes directly to main.
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:
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.
The existing YAML stays in place; `refresh: 0s` fetches current code on every build.
## Lokale ontwikkeling
## Local development
Kopieer alleen `screen_manager/` naar de gedeelde `addons/esp_screen_manager/`.
Herlaad de appwinkel, installeer de lokale versie en bouw na codewijzigingen opnieuw.
Een lokale testversie heeft een andere add-onidentiteit dan de GitHub-versie; de
gegevens verhuizen niet automatisch. Test voor de uiteindelijke installatie de
GitHub-versie en zet de lokale versie uit om twee schrijvers te voorkomen.
Copy only `screen_manager/` to the shared `addons/esp_screen_manager/`.
Reload the App store, install the local version, and rebuild after code changes.
A local test version has a different add-on identity than the GitHub version; the
data doesn't move over automatically. For the final installation, test the
GitHub version and turn off the local version to avoid two writers.
Voor backendtests op een ontwikkelcomputer:
For backend tests on a development machine:
```sh
python3 -m venv .venv-portal
@@ -54,371 +53,403 @@ python3 -m venv .venv-portal
.venv-portal/bin/python -m unittest discover -s tests
```
Een tijdelijke ontwikkelserver ondersteunt `SCREEN_DEV=1`, `HA_API` (eindigt op
`/api`), `HA_TOKEN_FILE` en `SCREEN_DATA`. Hij bindt alleen op localhost. Zet een
token nooit in broncode, URL's of Git. Productie gebruikt Supervisor en accepteert
alleen het Ingress-proxyadres; er is geen extra publieke poort.
A temporary development server supports `SCREEN_DEV=1`, `HA_API` (ending in
`/api`), `HA_TOKEN_FILE`, and `SCREEN_DATA`. It only binds on localhost. Never put a
token in source code, URLs, or Git. Production uses Supervisor and only accepts
the Ingress proxy address; there is no additional public port.
### Instellingencompatibiliteit 0.1.2
### Settings compatibility 0.1.2
`settings` is een optioneel object binnen een schermindeling en binnen het bestaande
`v: 1, op: layout`-bericht. Een ontbrekend object behoudt eerder gedrag. Oude
firmware negeert dit extra veld en blijft tegels ontvangen. De beheerpagina meldt
dat nieuwe firmware nodig is. Een oude browser die alleen tegels opslaat, wist
opgeslagen instellingen niet. Onbekende instellingen worden geweigerd.
`settings` is an optional object within a screen layout and within the existing
`v: 1, op: layout` message. A missing object preserves prior behavior. Old
firmware ignores this extra field and keeps receiving tiles. The management page reports
that new firmware is needed. An old browser that only saves tiles doesn't wipe
saved settings. Unknown settings are refused.
Firmware gebruikt een afzonderlijke preferences-key `0x53435231` met een vaste
versie-1 structuur (elf int32-velden en een uint32-versie). Wijzig key, structuur
of versie niet zonder migratie. Alleen gewijzigde instellingen worden opgeslagen;
periodieke herhaling veroorzaakt geen flashwrites en geen nieuwe idle-timer.
Firmware uses a separate preferences key `0x53435231` with a fixed
version-1 structure (eleven int32 fields and a uint32 version). Don't change the key,
structure, or version without a migration. Only changed settings are saved;
periodic repeats cause no flash writes and no new idle timer.
### Compatibiliteit 0.2.0
### Compatibility 0.2.0
Opslagversie en tegelprotocol blijven 1. Optionele `tiles[].options`, `o` in
statusberichten, `history` en `inbox` in het layoutbericht zijn additief. Een
oudere browser die opties niet meestuurt behoudt de bestaande opties voor dezelfde
entiteit. Oudere firmware negeert extra velden. Nieuwe entiteitsdomeinen vereisen
wel firmware 0.2.0; bij terugrollen naar een oudere app eerst de gegevensback-up
herstellen, omdat die app nieuwe domeinen nog niet kan laden. Geen oude opslag
stilzwijgend overschrijven. Bestaande preference-keys blijven ongewijzigd.
Storage version and tile protocol stay 1. Optional `tiles[].options`, `o` in
status messages, `history`, and `inbox` in the layout message are additive. An
older browser that doesn't send options keeps the existing options for the same
entity. Older firmware ignores extra fields. New entity domains do
require firmware 0.2.0; when rolling back to an older app, restore the data backup
first, since that app can't yet load new domains. Don't silently
overwrite old storage. Existing preference keys stay unchanged.
De app gebruikt nu de officiële ESPHome-container, mapped `homeassistant_config`
naar `/homeassistant` en vraagt UART/USB voor de door de gebruiker gekozen poort.
Config/secrets blijven in de eigen HA-configmap; builds in `/data`. App-updates
vervangen deze mappen niet. Native getalinstellingen melden wijzigingen via
`esphome.screen_setting`; de manager valideert inbox, sleutel en waarde.
The app now uses the official ESPHome container, maps `homeassistant_config`
to `/homeassistant`, and requests UART/USB for the port the user chose.
Config/secrets stay in the device's own HA config folder; builds in `/data`. App updates
don't replace these folders. Native number settings report changes via
`esphome.screen_setting`; the manager validates the inbox, key, and value.
De ingebouwde CLI bewaart opnieuw te downloaden caches onder `/data/build` en
`/data/platformio`. Alleen deze mappen zijn uitgesloten van appback-ups via
`backup_exclude`. `/data/screens.json` en eigen ESPHome-configuraties blijven
back-upgegevens; sluit nooit `/data` als geheel uit.
The built-in CLI stores re-downloadable caches under `/data/build` and
`/data/platformio`. Only these folders are excluded from app backups via
`backup_exclude`. `/data/screens.json` and the device's own ESPHome configurations remain
backup data; never exclude `/data` as a whole.
### Compatibiliteit 0.2.7
### Compatibility 0.2.7
Twintig runtime-tegels vereisen firmware 0.2.7+. De manager controleert die versie
voor opslaan en verzenden van grotere indelingen. Bestaande indelingen blijven
behouden bij oudere firmware. Oude appversies ondersteunen niet meer dan tien;
breng de indeling eerst terug tot tien of herstel hun gegevensback-up bij rollback.
`settings.swipe_pages` is additief in opslagversie 1. Op de draad staat het buiten
het ongewijzigde elfvelden-settingsobject. De bestaande preferences blijven gelijk;
alleen swipe gebruikt een nieuwe eigen uint32-key `0x53575031`, standaard uit.
Twenty runtime tiles require firmware 0.2.7+. The manager checks that version
before saving and sending larger layouts. Existing layouts are
preserved on older firmware. Old app versions don't support more than ten;
first bring the layout back down to ten, or restore their data backup on rollback.
`settings.swipe_pages` is additive in storage version 1. On the wire, it sits outside
the unchanged eleven-field settings object. Existing preferences stay the same;
only swipe uses a new, separate uint32 key `0x53575031`, off by default.
### Compatibiliteit 0.2.9
### Compatibility 0.2.9
Guition-rotatie is additief als `settings.rotation` in appdata, uitsluitend
0/90/180/270. Oude beheerpagina's die het veld weglaten behouden de opgeslagen
hoek. Op de draad staat `rotation` naast het ongewijzigde elfvelden-settingsobject.
De firmware bewaart de hoek als afzonderlijke uint32 op key `0x524F5431`; de
bestaande Settings-structuur en CYD-kalibratie blijven ongewijzigd. Alleen de
Guition activeert de rotatiecallback. De diagnostische entity `Guition schermtype`
maakt deze capability herkenbaar, ook als het scherm offline of hernoemd is.
Guition rotation is additive as `settings.rotation` in app data, restricted to
0/90/180/270. Old management pages that omit the field keep the stored
angle. On the wire, `rotation` sits alongside the unchanged eleven-field settings object.
The firmware stores the angle as a separate uint32 at key `0x524F5431`; the
existing Settings structure and CYD calibration stay unchanged. Only the
Guition activates the rotation callback. The diagnostic entity `Guition schermtype`
makes this capability recognizable, even when the screen is offline or renamed.
### Compatibiliteit 0.2.10
### Compatibility 0.2.10
`tiles[].options.background` is een optionele paletnaam binnen opslagversie 1.
Op de draad staat dit in het bestaande `o`-object. Oudere firmware negeert het
veld; nieuwe firmware valt bij onbekende namen terug op de normale kleuren.
De app accepteert uitsluitend het lichte palet uit `TILE_BACKGROUNDS`. Een oude
editor die `background` weglaat behoudt de opgeslagen kleur voor dezelfde entity;
expliciet `auto` herstelt de standaard. Geen gewijzigde voorkeurstructuur of
sleutels, geen nieuwe firmwareflash nodig voor latere kleurkeuzes.
`tiles[].options.background` is an optional palette name within storage version 1.
On the wire, this sits in the existing `o` object. Older firmware ignores the
field; newer firmware falls back to the normal colors for unknown names.
The app only accepts the light palette from `TILE_BACKGROUNDS`. An old
editor that omits `background` keeps the stored color for the same entity;
explicit `auto` restores the default. No changed preference structure or
keys, no new firmware flash needed for later color choices.
Een oude apprelease van vóór 0.2.10 kent dit optieveld niet. Bij terugrollen van
de app herstel je daarom de bijbehorende gegevensback-up; wis of negeer geen
onbekende opties om een oud opslagbestand toch te openen.
An old app release from before 0.2.10 doesn't know this option field. When rolling back
the app, restore the corresponding data backup; don't wipe or ignore
unknown options just to open an old storage file anyway.
### Compatibiliteit app 0.2.15 / firmware 0.2.16
### Compatibility app 0.2.15 / firmware 0.2.16
Opslagversie en tegelprotocol blijven 1. `tiles[].options.background` krijgt de
extra paletnaam `none` ("Geen"): geen kaart achter de tegelinhoud. Oudere
firmware kent de naam niet en valt terug op de normale kaart; omdat dat voor de
gebruiker onzichtbaar misgaat, stuurt de manager zo'n indeling pas na firmware
0.2.16 (`min_firmware`) en bewaart haar ondertussen. De firmware verbergt
uitsluitend vulling en rand (`bg_opa`/`border_opa`); maten, padding en de
pressed-feedback op de PRESSED-state blijven gelijk. De analoge klok wijzigt
alleen de tekening (streepjes, cijfers, kalenderblok op enkele tegels); er is
geen nieuw veld voor nodig. Geen gewijzigde preferences of sleutels.
Storage version and tile protocol stay 1. `tiles[].options.background` gets the
extra palette name `none` ("None"): no card behind the tile content. Older
firmware doesn't know the name and falls back to the normal card; because that fails
invisibly for the user, the manager only sends such a layout once firmware
0.2.16 or newer is detected (`min_firmware`), holding it back in the meantime. The firmware only hides
the fill and border (`bg_opa`/`border_opa`); sizes, padding, and the
pressed feedback on the PRESSED state stay the same. The analog clock only changes
the drawing (ticks, numerals, calendar block on single tiles); no
new field is needed for it. No changed preferences or keys.
### Compatibiliteit 0.2.16 / firmware 0.2.17
### Compatibility 0.2.16 / firmware 0.2.17
`FIRMWARE_VERSION` in `screen_manager/app/core.py` is de firmware die bij deze
app hoort; `tests/test_updates.py` eist dat hij gelijk is aan
`SCREEN_FIRMWARE_VERSION` in beide bordprofielen en pakketten. Verhoog ze samen.
Een scherm met een lagere `Schermfirmware` krijgt een update-aanbod; een build
haalt `main`, dus publiceer firmware en app in dezelfde commit.
`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.
A screen with a lower `Schermfirmware` gets an update offer; a build
fetches `main`, so publish firmware and app in the same commit.
Firmware 0.2.17 voegt de diagnostische text sensors `Apparaatnaam`
(`${DEVICE_NAME}`) en `IP-adres` (`wifi_info`) toe. De app koppelt een scherm
via `Apparaatnaam` aan het profiel met dezelfde `esphome.name`; oudere firmware
valt terug op één profiel met gelijke `friendly_name` en een handmatig ingevuld
adres. Hernoem deze sensors niet zonder `core.discover` aan te passen.
Firmware 0.2.17 adds the diagnostic text sensors `Apparaatnaam`
(`${DEVICE_NAME}`) and `IP-adres` (`wifi_info`). The app links a screen
to the profile with the same `esphome.name` via `Apparaatnaam`; older firmware
falls back to a single profile with a matching `friendly_name` and a manually entered
address. Don't rename these sensors without also updating `core.discover`.
Updatestatus staat in `/data/updates.json` (`version: 1`: `auto`, `hosts`,
`results`, `last_round`), los van `screens.json`. Onbekende versies worden
geweigerd. De ronde draait één scherm tegelijk, wacht op `Schermfirmware >=`
doelversie en één minuut stabiliteit, en stopt bij de eerste fout. Alleen de
nachtelijke ronde schrijft een `persistent_notification` in HA.
Update status lives in `/data/updates.json` (`version: 1`: `auto`, `hosts`,
`results`, `last_round`), separate from `screens.json`. Unknown versions are
refused. The round runs one screen at a time, waits for `Schermfirmware >=`
target version and one minute of stability, and stops on the first error. Only the
nightly round writes a `persistent_notification` in HA.
### Compatibiliteit 0.2.18 / firmware 0.2.18
### Compatibility 0.2.18 / firmware 0.2.18
Opslagversie en tegelprotocol blijven 1. `tiles[].options.icon` is additief:
`auto` of een naam uit `screen_manager/app/tile_icons.py`. Op de draad stuurt de
manager in `o.icon` alleen de opgeloste codepoint in hex (`F06B5`): de gekozen
naam, of bij `auto` het `mdi:`-icoon uit de HA-attributen als dat in de set zit.
Oudere firmware negeert het veld; nieuwe firmware controleert of de glyph in de
font zit en valt anders terug op het domeinicoon. Daarom geen `min_firmware`.
Een oude editor die `icon` weglaat behoudt de opgeslagen keuze.
Storage version and tile protocol stay 1. `tiles[].options.icon` is additive:
`auto` or a name from `screen_manager/app/tile_icons.py`. On the wire, the
manager sends only the resolved codepoint in hex (`F06B5`) in `o.icon`: the chosen
name, or, for `auto`, the `mdi:` icon from the HA attributes if it's in the set.
Older firmware ignores the field; newer firmware checks whether the glyph is in the
font and otherwise falls back to the domain icon. Hence no `min_firmware`.
An old editor that omits `icon` keeps the stored choice.
`tile_icons.py` is de enige lijst. `tools/generate_icons.py` schrijft de glyphs
als YAML-anker in de drie MDI-fonts van beide bordprofielen en bouwt
`static/tile-icons.woff` voor de editor (met left bearing gelijk aan xMin, anders
staan iconen in de browser uit het midden); draai daarna `generate_packages.py`.
De substituties `MDI_GLYPH_*` zijn vervallen: `TILEn_ICON` in handmatige
profielen moet uit de set komen. Geen gewijzigde preferences of sleutels.
`tile_icons.py` is the single source list. `tools/generate_icons.py` writes the glyphs
as a YAML anchor into the three MDI fonts of both board profiles and builds
`static/tile-icons.woff` for the editor (with left bearing equal to xMin, otherwise
icons sit off-center in the browser); run `generate_packages.py` afterward.
The `MDI_GLYPH_*` substitutions are retired: `TILEn_ICON` in manual
profiles must come from the set. No changed preferences or keys.
### Compatibiliteit 0.2.38 / firmware 0.2.32
### Compatibility 0.2.40 / firmware 0.2.34
Opslagversie en tegelprotocol blijven 1. Een indeling mag een optioneel object
`header: {items: [...]}` hebben (maximaal zes): `{type: clock|analog|date}` of
`{type: entity, entity, content: state|last_changed, icon: auto|none|<naam>, show:
always|active}`. Zonder `header` geldt wat de firmware altijd deed (de klok van
`show_clock`); een oude editor die `header` weglaat behoudt de opgeslagen balk. Bij
opslaan volgt `settings.show_clock` de klok in de balk, zodat oudere firmware de tijd
alleen toont als hij erin staat. Entiteiten in de balk mogen naast de tegeldomeinen
ook `device_tracker`, `zone`, `lock`, `alarm_control_panel`, `counter`, `event`,
`input_datetime`, `input_text`, `water_heater` en `humidifier` zijn; de inventaris
markeert die met `tile: false` zodat de tegelkiezer ze overslaat.
Storage version and tile protocol stay 1; no new message fields, preferences or keys.
Firmware 0.2.34 changes only text: every on-screen label, log line and status reply is
English, and so are the entity names. The status replies the manager reacts to are now
`Ready for tile configuration`, `Loading tiles`, `Resend needed`, `Synced` and
`Error: …`; `RESEND_STATES` in `server.py` and `diagnostics/*.py` accept both
languages, so screens on firmware 0.2.33 and older keep working unchanged.
Op de draad stuurt de manager direct na het layoutbericht `{v:1, op: header, items}`
met per onderdeel `k` (`clock`, `analog`, `date`, `text`, `ago`), `i` (codepoint),
`t` (tekst, al in het Nederlands opgemaakt en beperkt tot de glyphs van
`sublabel_big`), `e` (unix-tijd voor `ago`) en `c` (accentkleur). Onderdelen met
`show: active` die niet actief zijn stuurt de manager niet. Alleen firmware 0.2.32+
krijgt dit bericht (`HEADER_MIN_FIRMWARE`, op basis van `Schermfirmware`): oudere
firmware zou `op: header` weigeren met "Fout: ongeldig bericht". Het bericht wordt
apart vergeleken; een gewijzigde waarde verstuurt alleen de balk, niet de indeling.
De firmware antwoordt met dezelfde status als een tegelstatus, dus de
Tegelinstellingen-entiteit flipt niet bij iedere waarde.
The entity names are part of the compatibility contract. Home Assistant's ESPHome
integration builds the unique ID from the entity name (`<MAC>/0/text_info/Tile settings`),
so a renamed entity gets a **new entity ID** and the old one is removed as soon as the
screen reconnects (seen on HA 2026.9.1: `text.cyd_2_8in_display_tegelinstellingen` →
`text.cyd_2_8in_display_tile_settings` within the same second). Renamed: `Tegelinstellingen` →
`Tile settings`, `Schermfirmware` → `Screen firmware`, `Apparaatnaam` → `Device name`,
`IP-adres` → `IP address`, `Guition schermtype` → `Guition screen type`, `Opgestart` →
`Last boot`, `Helderheid normaal/standby/nacht` → `Normal/Standby/Night brightness`,
`Standby na` → `Standby after`, `Touch kalibreren` → `Calibrate touch`.
Firmware: `header_bar.h` (LVGL-vrij: parsen, "5 min geleden", datum, afstanden,
plaatsing) en `runtime_tiles::draw_header()`. Het tijdlabel van het profiel blijft
bestaan als referentie (rechtermarge, tekenvolgorde) maar is in runtime-modus
verborgen. Waarden gebruiken `sublabel_big`, iconen `materialdesign_icons_mini`;
`sublabel_big` kreeg `'`, `#`, `*`, `=`, `;`, `²`, `³`, `µ`, `–` en veelvoorkomende
accenten; `tests/test_header_bar.py` houdt `header_bar.GLYPHS` gelijk aan die lijst.
De editor (`barLayout` in `app.js`) en de firmware (`header_bar::gaps/place`) delen
dezelfde gehele rekensommen; de test controleert dat. `tools/render_topbar.py`
rendert de echte `draw_header()` op een Mac/Linux-machine (ESPHome host + SDL2) naar
PNG, zonder scherm. Geen gewijzigde preferences of sleutels.
`core.discover_screens` matches both names (`NAME_*` pairs). Because the manager keys
`screens.json` and `updates.json` by the inbox entity ID, `Manager.follow_renamed_inboxes`
(run whenever the screen list is rebuilt) moves a screen's layout, update address and last
result to its new inbox ID: first by the HA device an inbox was seen on during this run,
otherwise (after a restart) when a stored ID's device part (`core.inbox_prefix`) matches
the entity ID prefix of one of the device's ESPHome entities (`core.device_prefixes`; the
unchanged `Node Status`, `Restart` and `Wifi Signal` entities keep the old prefix). An existing
layout on the new ID is never overwritten; layouts of other screens are never taken.
`Manager.aliases` maps old to new IDs so `save()`, the inspector and the updater
(`Updater.current_id`, `Updater.renamed`) follow a screen that is renamed mid-update: the
Update button and the nightly round verify the new ID and record success there. Don't rename
these entities again without keeping this path. Tests: `tests/test_renamed_inbox.py`.
### Compatibiliteit 0.2.35 / firmware 0.2.30
### Compatibility 0.2.38 / firmware 0.2.32
Alleen firmware (Guition). `on_boot` haalt `LV_OBJ_FLAG_CLICKABLE` van `home_page` en
`tile_scroll`: een druk buiten de tegels heeft geen LVGL-object meer (geen pressed-stijl,
geen hertekening, geen events); de randveeg loopt via de touchscreen-triggers en heeft dat
niet nodig, `lv_indev_wait_release` werkt ook zonder actief object. Trace-regels `veeg …`
op INFO alleen zolang `edge_swipe.armed()`. Verder ongewijzigd.
Storage version and tile protocol stay 1. A layout may have an optional object
`header: {items: [...]}` (six max): `{type: clock|analog|date}` or
`{type: entity, entity, content: state|last_changed, icon: auto|none|<name>, show:
always|active}`. Without `header`, the firmware's prior always-on behavior applies (the clock from
`show_clock`); an old editor that omits `header` keeps the stored bar. When
saving, `settings.show_clock` follows the clock in the bar, so older firmware only shows the
time if it's in the bar. Besides the tile domains, entities in the bar may
also be `device_tracker`, `zone`, `lock`, `alarm_control_panel`, `counter`, `event`,
`input_datetime`, `input_text`, `water_heater`, and `humidifier`; the inventory
marks those with `tile: false` so the tile picker skips them.
### Compatibiliteit 0.2.34 / firmware 0.2.29
On the wire, right after the layout message, the manager sends `{v:1, op: header, items}`
with, per item, `k` (`clock`, `analog`, `date`, `text`, `ago`), `i` (codepoint),
`t` (text, already formatted — in English since app 0.2.40 — and limited to the glyphs of
`sublabel_big`), `e` (unix time for `ago`), and `c` (accent color). Items with
`show: active` that aren't active are not sent by the manager. Only firmware 0.2.32+
gets this message (`HEADER_MIN_FIRMWARE`, based on the reported screen firmware): older
firmware would refuse `op: header` with "Fout: ongeldig bericht" (that firmware still reports in Dutch). The message is
compared separately; a changed value sends only the bar, not the full layout.
The firmware replies with the same status as a tile status, so the
inbox entity doesn't flip on every value.
Alleen firmware. LVGL 9.5.0's `send_event()` in `lv_indev.c` stuurt het invoerapparaat
PRESSED, RELEASED, CLICKED, LONG_PRESSED en KEY, maar geen PRESSING; een
`lv_indev_add_event_cb` krijgt dus geen positie-updates tijdens een druk. `cyd::EdgeSwipe`
werkt daarom weer op de native touchpunten uit `on_touch`/`on_update`/`on_release`
(`configure(width, height, band, travel)`, `begin(x, y, rotation)` met ESPHome's
rotatiemapping, `update()`, `end()`), de indev-callback is weg. Verder ongewijzigd.
Firmware: `header_bar.h` (LVGL-free: parsing, "5 min ago", date, distances,
placement) and `runtime_tiles::draw_header()`. The profile's time label still
exists as a reference (right margin, draw order) but is hidden in runtime
mode. Values use `sublabel_big`, icons `materialdesign_icons_mini`;
`sublabel_big` gained `'`, `#`, `*`, `=`, `;`, `²`, `³`, `µ`, `–`, and common
accented characters; `tests/test_header_bar.py` keeps `header_bar.GLYPHS` matching that list.
The editor (`barLayout` in `app.js`) and the firmware (`header_bar::gaps/place`) share
the same integer math; the test checks that. `tools/render_topbar.py`
renders the real `draw_header()` on a Mac/Linux machine (ESPHome host + SDL2) to
a PNG, without a screen. No changed preferences or keys.
### Compatibiliteit 0.2.33 / firmware 0.2.28
### Compatibility 0.2.35 / firmware 0.2.30
Alleen firmware. `TouchGuard::configure(0, ...)` schakelt de verplaatsingsgrens uit
(`moved_` wordt dan nooit gezet; LVGL's press-lost bepaalt of een tik doorgaat). Het
Guition-profiel zet `TOUCH_MOVE_LIMIT_PX` op 0, de CYD houdt 56. Verder ongewijzigd.
Firmware only (Guition). `on_boot` removes `LV_OBJ_FLAG_CLICKABLE` from `home_page` and
`tile_scroll`: a press outside the tiles no longer has an LVGL object (no pressed style,
no redraw, no events); the edge swipe runs via the touchscreen triggers and doesn't need
that, `lv_indev_wait_release` also works without an active object. Trace lines `swipe …`
(`veeg …` before firmware 0.2.34) at INFO only while `edge_swipe.armed()`. Otherwise unchanged.
### Compatibiliteit 0.2.32 / firmware 0.2.27
### Compatibility 0.2.34 / firmware 0.2.29
Alleen firmware. `cyd::EdgeSwipe` werkt op LVGL-pointercoördinaten: `configure(band, travel)`,
`begin(x, y, width)` met `lv_display_get_horizontal_resolution()`, `update()` met de 45°-regel,
plus `inward()`/`sideways()` voor het log. De Guition registreert één `lv_indev_add_event_cb`
(PRESSED/PRESSING/RELEASED) in `on_boot`; de touchscreen-triggers voeden alleen nog de
`TouchGuard`. Beide bordprofielen krijgen het script `close_cards` (roept
`runtime_tiles::dismiss()` aan, anders overlays verbergen en `active_entity` wissen); de
kruisjes en achtergrondtikken van de kaarten en `wake_display` gebruiken het. Protocol, opslag,
preferences en sleutels ongewijzigd.
Firmware only. LVGL 9.5.0's `send_event()` in `lv_indev.c` sends the input device
PRESSED, RELEASED, CLICKED, LONG_PRESSED, and KEY, but no PRESSING; an
`lv_indev_add_event_cb` therefore gets no position updates during a press. `cyd::EdgeSwipe`
therefore works again on the native touch points from `on_touch`/`on_update`/`on_release`
(`configure(width, height, band, travel)`, `begin(x, y, rotation)` with ESPHome's
rotation mapping, `update()`, `end()`); the indev callback is gone. Otherwise unchanged.
### Compatibiliteit 0.2.31 / firmware 0.2.26
### Compatibility 0.2.33 / firmware 0.2.28
Opslagversie en tegelprotocol blijven 1. `tiles[].slot` is additief: de absolute plek
van een tegel (pagina × 6 + rij × 2 + kolom, 0–47, `MAX_SLOTS` in `core.py`); een
dubbelbrede tegel staat op een even plek en bedekt ook de plek rechts ervan. Lege plekken
zijn toegestaan. `validate_layout` eist plekken voor alle tegels of voor geen: zonder
plekken (oude editor, oude opslag) krijgt de indeling de plekken van de oude
volgorde-packing (`pack_slots`, hetzelfde als `pack()` in de firmware), zodat er op
het scherm niets verandert; met plekken worden overlap, oneven dubbelbreed en bereik
geweigerd en de tegels op plek gesorteerd. `save()` herhaalt de packing na het
terugzetten van opgeslagen opties (die kunnen een tegel verbreden). `pages` (1–8) is
een optioneel, additief veld: pagina's die de gebruiker leeg wil houden.
Firmware only. `TouchGuard::configure(0, ...)` disables the movement limit
(`moved_` is then never set; LVGL's press-lost decides whether a tap goes through). The
Guition profile sets `TOUCH_MOVE_LIMIT_PX` to 0, the CYD keeps 56. Otherwise unchanged.
Op de draad krijgt het layoutbericht `slots` (één plek per entity, in dezelfde
volgorde) en `pages`. Firmware 0.2.26 (`Model::set_layout` met posities, `place()`
naast het oude `pack()`, `MAX_PAGES` 8) tekent de tegels op die plekken; een wijziging
van alleen plekken (`moved`) herplaatst de pagina's zonder tegelstatussen te wissen.
Oudere firmware negeert beide velden en pakt de entities in volgorde; omdat de
entities op plek gesorteerd zijn is dat de oude weergave zonder gaten, daarom geen
`min_firmware`. De editor meldt het (`has_gaps`/`hasGaps`) bij firmware < 0.2.26. Geen
gewijzigde preferences of sleutels.
### Compatibility 0.2.32 / firmware 0.2.27
### Compatibiliteit 0.2.30 / firmware 0.2.25
Firmware only. `cyd::EdgeSwipe` works on LVGL pointer coordinates: `configure(band, travel)`,
`begin(x, y, width)` with `lv_display_get_horizontal_resolution()`, `update()` with the 45° rule,
plus `inward()`/`sideways()` for the log. The Guition registers a single `lv_indev_add_event_cb`
(PRESSED/PRESSING/RELEASED) in `on_boot`; the touchscreen triggers now only feed the
`TouchGuard`. Both board profiles get the `close_cards` script (calls
`runtime_tiles::dismiss()`, otherwise hiding overlays and clearing `active_entity`); the
cards' close buttons and background taps, and `wake_display`, use it. Protocol, storage,
preferences, and keys unchanged.
Alleen de editor: het statusbolletje in de schermlijst is een eigen `span.dot`
(groen met `.online`). Firmware krijgt alleen een nieuw versienummer; protocol,
opslag, preferences en sleutels ongewijzigd.
### Compatibility 0.2.31 / firmware 0.2.26
### Compatibiliteit 0.2.29 / firmware 0.2.24
Storage version and tile protocol stay 1. `tiles[].slot` is additive: the absolute slot
of a tile (page × 6 + row × 2 + column, 0–47, `MAX_SLOTS` in `core.py`); a
double-width tile sits on an even slot and also covers the slot to its right. Empty slots
are allowed. `validate_layout` requires slots for all tiles or for none: without
slots (old editor, old storage), the layout gets the slots from the old
order-based packing (`pack_slots`, the same as `pack()` in the firmware), so
nothing changes on the screen; with slots, overlap, odd double-width, and out-of-range are
refused, and the tiles are sorted by slot. `save()` repeats the packing after
restoring saved options (which can widen a tile). `pages` (1–8) is
an optional, additive field: pages the user wants to keep empty.
Alleen firmware (Guition). `cyd::EdgeSwipe` (in `cyd_ui.h`, getest in
`test_cyd_ui.cpp`) vervangt op de Guition de LVGL-gesture op `home_page`: `begin()`
in `on_touch` met de LVGL-rotatie, `update()` in `on_update` voor het eerste contact;
bij een treffer `touch_guard.consume()`, `lv_indev_wait_release()` op alle indevs en
`show_tile_page`. Substituties `EDGE_SWIPE_BAND_PX`/`EDGE_SWIPE_TRAVEL_PX`;
`DISPLAY_W`/`DISPLAY_H` bepalen de rotatiemapping (ESPHome: 90° `x=y, y=W-x-1`,
270° `x=H-y-1, y=x`, 180° spiegelt beide). De CYD houdt de LVGL-gesture. De
instelling `swipe_pages` blijft de schakelaar; protocol, opslag en sleutels ongewijzigd.
On the wire, the layout message gets `slots` (one slot per entity, in the same
order) and `pages`. Firmware 0.2.26 (`Model::set_layout` with positions, `place()`
alongside the old `pack()`, `MAX_PAGES` 8) draws the tiles at those slots; a change
to slots only (`moved`) repositions the pages without clearing tile statuses.
Older firmware ignores both fields and packs the entities in order; since the
entities are sorted by slot, that's the old gap-free display, hence no
`min_firmware`. The editor reports this (`has_gaps`/`hasGaps`) for firmware < 0.2.26. No
changed preferences or keys.
### Compatibiliteit 0.2.28 / firmware 0.2.23
### Compatibility 0.2.30 / firmware 0.2.25
Alleen firmware. `cyd::TouchGuard` krijgt `configure(move_limit_px, min_press_ms)`
(aangeroepen in `on_boot` uit de substituties `TOUCH_MOVE_LIMIT_PX` en
`TOUCH_MIN_PRESS_MS`; zonder aanroep gelden de oude 18 px en 60 ms), volgt alleen
het contact-id waarmee de aanraking begon, meet de verplaatsing als afstand tot een
over vier metingen gesetteld referentiepunt en meldt via `reason()` waarom een tik
is geweigerd; `runtime_tiles::allowed()` logt dat op INFO met tag `touch`.
Protocol, opslag, preferences en sleutels ongewijzigd.
Editor only: the status dot in the screen list is its own `span.dot`
(green with `.online`). Firmware only gets a new version number; protocol,
storage, preferences, and keys unchanged.
### Compatibiliteit 0.2.27 (firmware 0.2.22 blijft)
### Compatibility 0.2.29 / firmware 0.2.24
Alleen de app. `POST /api/install` (YAML-download) is verwijderd; `POST
/api/firmware/profiles` schrijft het profiel, vult ontbrekende wifi-sleutels in
`secrets.yaml` aan (alleen de ontbrekende regels, geverifieerd door het resultaat
opnieuw te parsen; een ongeldig bestand blijft onaangeraakt) en start met `target`
(een gemelde USB-poort) direct `install`. Poort en bouwslot worden vóór het
schrijven gecontroleerd. Het antwoord bevat `api_key`; de pagina toont hem eenmalig
voor de HA-koppeling. Het jobobject krijgt `stage` (`config`, `compile`, `upload`).
`profile_meta` levert extra `screen` (profiel gebruikt het bordpakket van dit
project) en `api_key`; `/api/inventory` krijgt de additieve lijst `pending` met
zulke profielen zonder gekoppeld scherm. Opslag, protocol, preferences en sleutels
ongewijzigd.
Firmware only (Guition). `cyd::EdgeSwipe` (in `cyd_ui.h`, tested in
`test_cyd_ui.cpp`) replaces the LVGL gesture on `home_page` on the Guition: `begin()`
in `on_touch` with the LVGL rotation, `update()` in `on_update` for the first contact;
on a hit, `touch_guard.consume()`, `lv_indev_wait_release()` on all indevs, and
`show_tile_page`. Substitutions `EDGE_SWIPE_BAND_PX`/`EDGE_SWIPE_TRAVEL_PX`;
`DISPLAY_W`/`DISPLAY_H` determine the rotation mapping (ESPHome: 90° `x=y, y=W-x-1`,
270° `x=H-y-1, y=x`, 180° mirrors both). The CYD keeps the LVGL gesture. The
`swipe_pages` setting remains the toggle; protocol, storage, and keys unchanged.
### Compatibiliteit 0.2.26 / firmware 0.2.22
### Compatibility 0.2.28 / firmware 0.2.23
Opslagversie en tegelprotocol blijven 1. Het layoutbericht krijgt het additieve veld
`keepalive` (seconden, 5–3600): het interval waarin de app de hele indeling herhaalt
(`KEEPALIVE_SECONDS` in `server.py`, 120 s sinds 0.2.20). De firmware leidt daar zijn
bewaking van de gegevensstroom uit af (twee rondes plus 60 s) en meldt daarna
"ESP Screens niet actief"; "HA niet verbonden" komt nu van ESPHome's eigen
API-verbindingsstatus (`api_is_connected()`), niet meer uit de leeftijd van het laatste
bericht. Zonder het veld rekent firmware 0.2.22 met 120 s; firmware tot 0.2.21 negeert
het veld en houdt zijn vaste 95 s, wat met een keepalive van 120 s de bekende
"HA niet verbonden"-flikkering geeft. Verander `KEEPALIVE_SECONDS` daarom alleen samen
met een firmwareflash van bestaande schermen, of houd hem onder 40 s. Geen gewijzigde
preferences of sleutels.
Firmware only. `cyd::TouchGuard` gets `configure(move_limit_px, min_press_ms)`
(called in `on_boot` from the substitutions `TOUCH_MOVE_LIMIT_PX` and
`TOUCH_MIN_PRESS_MS`; without the call, the old 18 px and 60 ms apply), tracks only
the contact id the touch started with, measures displacement as distance to a
reference point settled over four measurements, and reports via `reason()` why a tap
was rejected; `runtime_tiles::allowed()` logs that at INFO with tag `touch`.
Protocol, storage, preferences, and keys unchanged.
### Compatibiliteit 0.2.24 / firmware 0.2.20
### Compatibility 0.2.27 (firmware stays 0.2.22)
Alleen intern: `Tile::forecast` en `Tile::hours` zijn vectoren (voorheen vaste arrays in
elke tegel); protocol en opslag ongewijzigd. De wizard-YAML krijgt `power_save_mode: none`
onder `wifi:`; de gedeelde pakketten bevatten geen wifi-blok, dus bestaande schermen
veranderen pas als de gebruiker de regel zelf toevoegt.
App only. `POST /api/install` (YAML download) has been removed; `POST
/api/firmware/profiles` writes the profile, fills in missing Wi-Fi keys in
`secrets.yaml` (only the missing lines, verified by re-parsing the result;
an invalid file is left untouched), and, given `target` (a reported USB port),
immediately starts `install`. Port and build slot are checked before
writing. The response contains `api_key`; the page shows it once
for the HA pairing. The job object gets `stage` (`config`, `compile`, `upload`).
`profile_meta` provides extra `screen` (profile uses this project's board package)
and `api_key`; `/api/inventory` gets the additive list `pending`, with
such profiles that have no paired screen. Storage, protocol, preferences, and keys
unchanged.
### Compatibiliteit 0.2.23 / firmware 0.2.19
### Compatibility 0.2.26 / firmware 0.2.22
Opslagversie en tegelprotocol blijven 1. `tiles[].options.controls` is additief:
`none` of een set uit `CONTROLS` in `core.py` per domein (climate `setpoint`/`mode`,
Storage version and tile protocol stay 1. The layout message gets the additive field
`keepalive` (seconds, 5–3600): the interval at which the app repeats the entire layout
(`KEEPALIVE_SECONDS` in `server.py`, 120 s since 0.2.20). The firmware derives its
data-flow monitoring from that (two rounds plus 60 s) and then reports
"ESP Screens not active"; "HA not connected" now comes from ESPHome's own
API connection status (`api_is_connected()`), no longer from the age of the last
message. Without the field, firmware 0.2.22 assumes 120 s; firmware up to 0.2.21 ignores
the field and keeps its fixed 95 s, which, with a 120 s keepalive, causes the known
"HA not connected" flicker. So only change `KEEPALIVE_SECONDS` together
with a firmware flash of existing screens, or keep it under 40 s. No changed
preferences or keys.
### Compatibility 0.2.24 / firmware 0.2.20
Internal only: `Tile::forecast` and `Tile::hours` are vectors (previously fixed arrays in
each tile); protocol and storage unchanged. The wizard YAML gets `power_save_mode: none`
under `wifi:`; the shared packages contain no Wi-Fi block, so existing screens
only change once the user adds the line themselves.
### Compatibility 0.2.23 / firmware 0.2.19
Storage version and tile protocol stay 1. `tiles[].options.controls` is additive:
`none` or a set from `CONTROLS` in `core.py` per domain (climate `setpoint`/`mode`,
switch/light/fan `toggle` plus `brightness`/`speed`, vacuum/cover/timer `buttons`,
cover `position`, media_player `volume`/`playback`, number `stepper`/`slider`,
select `stepper`, scene/script/button `run`). Op de draad stuurt de manager in
`o.controls` alleen de set die de kaart werkelijk toont: uitsluitend dubbelbreed,
weergave standaard en zonder mini-schuif; zonder keuze de eerste set van het
domein, bij `none` niets. Statusberichten krijgen de attributen `device_class`,
`hvac_action` en `is_volume_muted` (de enige boolean die meegaat). Oudere
firmware negeert het veld en toont de gewone brede kaart, daarom geen
`min_firmware`; het tegelpaneel meldt vanaf welke firmware het werkt. Een oude
editor die `controls` weglaat behoudt de opgeslagen keuze (zoals `background`).
De firmware bouwt het paneel lui per set (`layout_panel`), stuurt −/+ na 700 ms
als één `set_temperature`/`set_value` en laat de lokale waarde staan tot HA hem
meldt (of 10 s). De iconfonts krijgen 18 vaste bedieningsglyphs
(`tile_icons.FIXED`). Geen gewijzigde preferences of sleutels.
select `stepper`, scene/script/button `run`). On the wire, the manager sends in
`o.controls` only the set the card actually shows: double-width only,
default display, and without a mini-slider; without a choice, the domain's first
set; with `none`, nothing. Status messages get the attributes `device_class`,
`hvac_action`, and `is_volume_muted` (the only boolean included). Older
firmware ignores the field and shows the regular wide card, hence no
`min_firmware`; the tile panel reports from which firmware it works. An old
editor that omits `controls` keeps the stored choice (like `background`).
The firmware builds the panel lazily per set (`layout_panel`), sends −/+ after 700 ms
as a single `set_temperature`/`set_value`, and leaves the local value in place until HA
reports it (or 10 s). The icon fonts get 18 fixed control glyphs
(`tile_icons.FIXED`). No changed preferences or keys.
Ook additief in dezelfde release: `x.hours` (maximaal acht uren `t`, `c`, `h`,
`p`, `r`) en `p`/`r` per dag in `x.days` voor de weerkaart; `x.last` (unix-tijd)
voor scènes, scripts en knoppen; de attributen `humidity`, `wind_speed`,
`wind_speed_unit`, `apparent_temperature`, `fan_modes`, `swing_modes`, `fan_mode`
en `swing_mode`. `supported_features` mag boven de grens van een miljoen. Oudere
firmware negeert al deze velden. De bezig-status gebruikt LVGL's spinner; beide
bordprofielen bevatten daarvoor een verborgen `spinner` (`busy_spinner_seed`),
anders compileert ESPHome `LV_USE_SPINNER` als 0.
Also additive in the same release: `x.hours` (up to eight hours of `t`, `c`, `h`,
`p`, `r`) and `p`/`r` per day in `x.days` for the weather card; `x.last` (unix time)
for scenes, scripts, and buttons; the attributes `humidity`, `wind_speed`,
`wind_speed_unit`, `apparent_temperature`, `fan_modes`, `swing_modes`, `fan_mode`,
and `swing_mode`. `supported_features` may exceed the one-million limit. Older
firmware ignores all these fields. The busy status uses LVGL's spinner; both
board profiles include a hidden `spinner` for that (`busy_spinner_seed`),
otherwise ESPHome compiles `LV_USE_SPINNER` as 0.
### Compatibiliteit 0.2.12 / firmware 0.2.14
### Compatibility 0.2.12 / firmware 0.2.14
Opslagversie en tegelprotocol blijven 1. Additief: `tiles[].options.size`
(`single`/`wide`), nieuwe `display`-waarden (`forecast` voor weer, `graph` voor
sensoren, `digital`/`analog` voor `screen.clock`), de ingebouwde entity
`screen.clock` en de HA-domeinen `sun`, `timer` en `person`. Statusberichten
krijgen een optioneel object `x` met door de manager berekende waarden
(voorspellingsdagen, zontijden in de HA-tijdzone, timer-eindtijd als epoch).
Oudere firmware negeert `size`, nieuwe displays en `x`, maar weigert onbekende
domeinen in de hele indeling; de manager stuurt zo'n indeling daarom pas na
firmware 0.2.14 (`min_firmware`) en bewaart haar ondertussen. Voorspellingen
komen via `weather.get_forecasts` met `return_response`; zonder antwoord blijft
de weerkaart de gewone kaart. Geen gewijzigde preferences of sleutels.
Storage version and tile protocol stay 1. Additive: `tiles[].options.size`
(`single`/`wide`), new `display` values (`forecast` for weather, `graph` for
sensors, `digital`/`analog` for `screen.clock`), the built-in entity
`screen.clock`, and the HA domains `sun`, `timer`, and `person`. Status messages
get an optional object `x` with values computed by the manager
(forecast days, sun times in the HA timezone, timer end time as epoch).
Older firmware ignores `size`, new displays, and `x`, but refuses unknown
domains across the whole layout; the manager therefore only sends such a layout once
firmware 0.2.14 or newer is detected (`min_firmware`), holding it back in the meantime. Forecasts
come via `weather.get_forecasts` with `return_response`; without a response,
the weather card stays the regular card. No changed preferences or keys.
### Compatibiliteit 0.2.39 / firmware 0.2.33
### Compatibility 0.2.39 / firmware 0.2.33
Opslagversie en tegelprotocol blijven 1; geen nieuwe velden in `screens.json`, geen
gewijzigde preferences of sleutels. Alles is additief en per scherm gekoppeld aan de
gemelde `Schermfirmware`:
Storage version and tile protocol stay 1; no new fields in `screens.json`, no
changed preferences or keys. Everything is additive and, per screen, gated on the
reported screen firmware:
- **Transport.** Firmware 0.2.33 heeft de API-actie `screen_message` (één string
`message`, het complete JSON-bericht, maximaal 4096 bytes). De manager roept
`esphome.<apparaatnaam>_screen_message` aan zodra het scherm 0.2.33+ meldt
(`TRANSPORT_MIN_FIRMWARE` in `core.py`, `Manager.transport`); daaronder blijven de
base64-blokjes in de tekstentiteit `Tegelinstellingen`. De actie publiceert het
resultaat op dezelfde inbox-entiteit, dus de status op de beheerpagina blijft gelijk.
Het API-frame van ESPHome op de ESP32 is 32 KiB; `receive()` weigert boven 4096.
- **Keepalive.** Het layoutbericht krijgt `rev` (twaalf hex-tekens, `core.revision`
van het layoutbericht zonder `rev`); oudere firmware negeert het veld. Firmware
0.2.33 bewaart de revisie en beantwoordt `{v:1, op:"ping", rev, keepalive}` met
`Gesynchroniseerd`/`Tegels laden` (revisie gelijk) of `Indeling opnieuw nodig`
(anders, of na een herstart). Een ping ververst het feed-venster (`last_received`)
net als een layout. De manager pingt elke `KEEPALIVE_SECONDS` (120 s) en herhaalt
alles pas na `FULL_REPEAT_SECONDS` (3600 s), of direct wanneer de inbox een status
uit `RESEND_STATES` meldt (`Klaar voor tegelconfiguratie`, `Indeling opnieuw
nodig`, `Tegels laden`), met een guard van 120 s na de laatste volledige verzending.
Firmware onder 0.2.33 krijgt elke 120 s de volledige herhaling zoals voorheen.
Een herhaald, ongewijzigd layoutbericht antwoordt nu `Gesynchroniseerd` in plaats
van `Indeling ontvangen`; `diagnostics/send_layout.py` accepteert beide.
- **Incrementeel.** `HomeAssistant.dirty` verzamelt de gewijzigde entity-id's;
`Manager.sync_one(..., dirty=...)` bouwt alleen die tegels en, als een van hen in
de bovenbalk staat, de balk. `dirty=None` (eerste ronde, nieuw register, offline
geweest) bouwt alles en stuurt de verschillen; `force=True` stuurt alles. `sent`
bewaart per scherm `{'layout','header','states','rev'}`. `Manager.screens()`
vervangt `inventory()[0]` in de lus en de updater: alleen de ESPHome-schermentiteiten
worden gelezen, gecachet op register-identiteit plus de status van die entiteiten.
`inventory()` (volledig) blijft voor de editor en `save()`.
- **Historie.** `Manager.history_loop` (eigen taak in `main()`) haalt per venster
(1/6/24 uur) één `recorder/statistics_during_period` op (`hour` voor 24 uur,
`5minute` daaronder, `types: [mean, state]`; `mean`, anders `state`), valt per
sensor zonder rijen terug op `GET /history/period`, en markeert gewijzigde
entiteiten dirty. Het `history`-veld in het statusbericht is ongewijzigd (24
waarden, `None` tot de eerste). Een sensortegel gaat de eerste keer zonder
`history` de deur uit en krijgt hem seconden later; firmware toont dan de grafiek.
- **Diagnostiek (firmware).** De sensor `Uptime` (seconden, elke 15 s) is weg;
ervoor in de plaats `Opgestart` (`platform: uptime`, `type: timestamp`, device
class timestamp, één waarde per opstart; `time:` is al aanwezig). Bewust een nieuwe
entiteit: het entity-register van Home Assistant houdt bij de oude de eenheid `s`
vast en weigert dan een tijdstempel ("has a unit of measurement ... non-numeric
device class: timestamp", gezien op 2026-09-14). De ESPHome-integratie verwijdert
de oude `sensor.<scherm>_uptime` zelf zodra het scherm met de nieuwe firmware
verbindt. Verder `debug: update_interval` 300 s en de vier template-numbers op
`update_interval: never`, gepubliceerd vanuit `apply_screen_settings` als de waarde
afwijkt van hun laatste state (dus ook eenmaal na opstarten).
- **Transport.** Firmware 0.2.33 has the API action `screen_message` (one string
`message`, the complete JSON message, 4096 bytes max). The manager calls
`esphome.<device_name>_screen_message` as soon as the screen reports 0.2.33+
(`TRANSPORT_MIN_FIRMWARE` in `core.py`, `Manager.transport`); below that, the
base64 chunks in the inbox text entity are still used. The action publishes the
result to the same inbox entity, so the status on the management page stays the same.
ESPHome's API frame on the ESP32 is 32 KiB; `receive()` refuses anything above 4096.
- **Keepalive.** The layout message gets `rev` (twelve hex characters, `core.revision`
of the layout message without `rev`); older firmware ignores the field. Firmware
0.2.33 stores the revision and replies to `{v:1, op:"ping", rev, keepalive}` with
`Synced`/`Loading tiles` (revision matches) or `Resend needed`
(otherwise, or after a restart; firmware before 0.2.34 says `Gesynchroniseerd`/`Tegels laden`/`Indeling opnieuw nodig`). A ping refreshes the feed window (`last_received`)
just like a layout does. The manager pings every `KEEPALIVE_SECONDS` (120 s) and only repeats
everything after `FULL_REPEAT_SECONDS` (3600 s), or immediately when the inbox reports a status
from `RESEND_STATES` (`Ready for tile configuration`, `Resend needed`, `Loading tiles`,
and the Dutch originals of older firmware), with a 120 s guard after the last full send.
Firmware below 0.2.33 still gets the full repeat every 120 s as before.
A repeated, unchanged layout message now replies `Synced` instead
of `Layout received`; `diagnostics/send_layout.py` accepts both, in both languages.
- **Incremental.** `HomeAssistant.dirty` collects the changed entity IDs;
`Manager.sync_one(..., dirty=...)` builds only those tiles and, if one of them is in
the top bar, the bar too. `dirty=None` (first round, new registry, was
offline) builds everything and sends the diffs; `force=True` sends everything. `sent`
stores `{'layout','header','states','rev'}` per screen. `Manager.screens()`
replaces `inventory()[0]` in the loop and the updater: only the ESPHome screen entities
are read, cached on registry identity plus the status of those entities.
`inventory()` (full) remains for the editor and `save()`.
- **History.** `Manager.history_loop` (its own task in `main()`) fetches one
`recorder/statistics_during_period` call per window (1/6/24 hours) (`hour` for 24 hours,
`5minute` below that, `types: [mean, state]`; `mean`, otherwise `state`), and, per
sensor with no rows, falls back to `GET /history/period`, marking changed
entities dirty. The `history` field in the status message is unchanged (24
values, `None` until the first). A sensor tile goes out the door without
`history` the first time and gets it seconds later; the firmware then shows the graph.
- **Diagnostics (firmware).** The `Uptime` sensor (seconds, every 15 s) is gone;
replaced by `Opgestart` (`Last boot` since firmware 0.2.34; `platform: uptime`, `type: timestamp`, device
class timestamp, one value per boot; `time:` is already present). Deliberately a new
entity: Home Assistant's entity registry keeps the unit `s` for the old
one and then refuses a timestamp ("has a unit of measurement ... non-numeric
device class: timestamp", seen on 2026-09-14). The ESPHome integration removes
the old `sensor.<screen>_uptime` itself as soon as the screen connects with the
new firmware. Also `debug: update_interval` 300 s, and the four template numbers set to
`update_interval: never`, published from `apply_screen_settings` when the value
differs from their last state (so also once after boot).
-183
View File
@@ -1,183 +0,0 @@
# Tegels instellen voor jouw Home Assistant
Bewerk `device.yaml`, binnen de bestaande `substitutions:`. De basiscode hoef
je voor de onderstaande voorbeelden niet aan te passen. Elke wijziging vraagt
opnieuw bouwen en flashen. Doorloop eerst de [installatie](../README.md).
## Entity-ID's verzamelen
Open in HA **Ontwikkelaarstools → Statussen**. Zoek de gewenste entiteit en
kopieer de volledige ID, bijvoorbeeld `light.keuken`. Controleer status en
attributen. De schermtitel is vrij te kiezen; de entity-ID moet exact kloppen.
Test onder **Ontwikkelaarstools → Acties** de gewenste actie met die entiteit.
Een actie kan het echte apparaat bedienen: kies een geschikte test.
Zie [HA-acties](https://www.home-assistant.io/docs/scripts/perform-actions/).
Maak eerst een lijst met positie, titel, entity-ID, tikactie en lange-drukactie.
Gebruik bestaande HA-scripts/scènes voor meerdere apparaten of complexe logica.
## Posities en grenzen
| Posities | Bedoeld gebruik in deze firmware |
|---|---|
| 1–6 | Hoofdtegels; light, switch, scene, script, fan, cover en climate |
| 6 | Ook de vacuumkaart; de kaart is specifiek met tegel 6 verbonden |
| 7 en 9 | Extra lichttegels met helderheid/kleurbediening |
| 8 en 10 | Extra status-/actietegels; geen volledige numerieke/climatekaart |
`TILE_COUNT: "1"` tot `"10"` bepaalt hoeveel **opeenvolgende** posities zichtbaar
zijn. Tot en met zes zijn Vorige/Volgende verborgen; vanaf zeven staat 1–6 op
pagina één en de rest op pagina twee. Vrij scrollen is vervangen door vaste
pagina's. Laat ongebruikte posities op de neutrale voorbeeldentiteiten staan.
Verander geen rastermaten om tegels toe te voegen.
## Belangrijkste instellingen
| Instelling (`N` = tegelnummer) | Betekenis |
|---|---|
| `TILEN_ENTITY` | Entiteit waarop de actie wordt uitgevoerd |
| `TILEN_STATE_ENTITY` | Entiteit voor status/attributen; meestal dezelfde |
| `TILEN_TITLE` | Korte titel, liefst maximaal circa 12 tekens |
| `TILEN_TYPE` | Domein, bijvoorbeeld `light`, `scene`, `climate` |
| `TILEN_TAP_ACTION` | `auto`, `toggle` of `custom` voor onderstaande voorbeelden |
| `TILEN_TAP_SERVICE` | Expliciete HA-actie bij custom, bijvoorbeeld `script.turn_on` |
| `TILEN_LONGPRESS` | `none`, `slider` of (alleen tegel 6) `vacuum` |
| `TILEN_LONGPRESS_SLIDER` | `auto`; kiest passende regeling op basis van type |
| `TILEN_LABEL_ON/OFF` | Tekst voor eenvoudige aan/uitstatus |
De voorbeeldconfig vult ook de overige velden in. Laat die staan tenzij je
ze bewust gebruikt. `STATE_ENTITY` kan bij een scène/script een echte lamp of
schakelaar volgen; een scène heeft zelf geen betrouwbare aan/uitstatus.
## Kleur, wittemperatuur en helderheid
Een RGB-/kleurenlamp met `LONGPRESS: "slider"` opent direct de lampkaart.
Deze bevat maximaal drie horizontale schuiven:
- **Kleur:** een doorlopende regenboog (0–360° hue, 100% verzadiging).
- **Wittemperatuur:** warm naar koel, binnen de minimum-/maximum-Kelvinwaarden
die de lamp in Home Assistant meldt.
- **Helderheid:** 1–100%; aan/uit blijft via de tegel beschikbaar.
De kleur- en witschuif verschijnen alleen als `supported_color_modes` deze
ondersteunt. Een uitsluitend dimbare lamp houdt de gewone helderheidskaart.
Er zijn geen extra tegelinstellingen nodig. Gebruik voor een lamp dezelfde
`ENTITY` en `STATE_ENTITY`. De kleurkaart volgt `hs_color`, `color_temp_kelvin`,
`min_color_temp_kelvin` en `max_color_temp_kelvin` van de bediende entiteit.
Ontbreekt het temperatuurbereik, dan wacht de witschuif op HA-gegevens.
De kaart neemt bij openen de laatst ontvangen lampwaarden over. Slepen toont
lokaal de gekozen waarde; pas loslaten verstuurt één opdracht. Kleur kiest de
kleurmodus, wittemperatuur kiest de witmodus. Helderheid verandert de kleurmodus
niet. De regenboog regelt hue; pastel/verzadiging is geen aparte regelaar.
De hue-lijst wordt via ESPHome `data_template` naar HA gestuurd; zie de
[officiële API-documentatie](https://esphome.io/components/api/#homeassistantaction-action).
De gedeelde implementatie staat in `light_controls.h`. Beide schermprofielen
gebruiken deze; de Guition heeft grotere regelaars, de CYD een compacte kaart.
`diagnostics/run_ui_test.py` controleert ook de schuifevents met vervangen
callbacks: geen echte HA-acties. Voor een veilige 40-secondenvoorbeeldkaart:
```sh
python diagnostics/control_ui.py light_controls_preview --host guition-wallbox.local --name guition-wallbox
```
Gebruik voor CYD de eigen host en naam. Tijdens deze voorbeeldkaart worden
lichtopdrachten onderdrukt en verdwijnt de kaart vanzelf. Test vervolgens de
werkelijke lamp: lang indrukken, kleur kiezen, wit kiezen, helderheid aanpassen,
sluiten en heropenen. Controleer de fysieke lamp en de waarden in HA.
## Voorbeelden
Wijzig deze sleutels in de bestaande map; plak niet nogmaals `substitutions:`.
Dimbare lamp op positie 1 (tik schakelt, lang indrukken opent de regeling):
```yaml
TILE1_ENTITY: "light.keuken"
TILE1_STATE_ENTITY: "light.keuken"
TILE1_TITLE: "Keuken"
TILE1_TYPE: "light"
TILE1_TAP_ACTION: "auto"
TILE1_LONGPRESS: "slider"
```
Een niet-dimbare lamp/schakelaar krijgt `LONGPRESS: "none"`. Kleurbediening
vereist dat de lamp de betreffende kleurmodus ondersteunt.
Scène op positie 3:
```yaml
TILE3_ENTITY: "scene.avond"
TILE3_STATE_ENTITY: "light.keuken"
TILE3_TITLE: "Avond"
TILE3_TYPE: "scene"
TILE3_TAP_ACTION: "auto"
TILE3_LONGPRESS: "none"
```
Script op positie 4:
```yaml
TILE4_ENTITY: "script.alles_uit"
TILE4_STATE_ENTITY: "script.alles_uit"
TILE4_TITLE: "Alles uit"
TILE4_TYPE: "script"
TILE4_TAP_ACTION: "auto"
TILE4_LONGPRESS: "none"
```
Airco op positie 5 (lang indrukken opent climate):
```yaml
TILE5_ENTITY: "climate.woonkamer"
TILE5_STATE_ENTITY: "climate.woonkamer"
TILE5_TITLE: "Airco"
TILE5_TYPE: "climate"
TILE5_TAP_ACTION: "toggle"
TILE5_TAP_SERVICE: "climate.toggle"
TILE5_LONGPRESS: "slider"
```
Controleer `min_temp`, `max_temp`, `target_temp_step`, `hvac_modes` en de
ondersteunde fan-/swingmodes in HA. Deze kaart is primair voor een **enkel
setpoint**, niet een thermostaat die uitsluitend een temperatuurinterval
gebruikt. Test de modi van jouw integratie afzonderlijk; een andere airco
kan andere mogelijkheden hebben.
Robotstofzuiger op positie 6 (tik start; lang indrukken opent de kaart):
```yaml
TILE6_ENTITY: "vacuum.robot"
TILE6_STATE_ENTITY: "vacuum.robot"
TILE6_TITLE: "Stofzuiger"
TILE6_TYPE: "vacuum"
TILE6_TAP_ACTION: "custom"
TILE6_TAP_SERVICE: "vacuum.start"
TILE6_LONGPRESS: "vacuum"
```
De vacuumkaart gebruikt start/pauze/stop/terugkeren/lokaliseren en de
snelheidsnamen `quiet`, `balanced`, `turbo`, `max`. Vergelijk deze met de
ondersteunde acties en `fan_speed_list` in HA. De snelheidsknoppen moeten in
de basiscode aangepast worden als jouw integratie andere namen verwacht.
Dit is geen universele kaart voor ieder robotmodel.
## Acties inschakelen en controleren
Zet na kalibratie en HA-koppeling `DIRECT_ACTIONS: "true"`. Geef in de
ESPHome-integratie toestemming voor Home Assistant-acties. Gebruik geen
HA-automation die dezelfde schermactie daarnaast nogmaals uitvoert; dat kan
een dubbele toggle veroorzaken. Bij `DIRECT_ACTIONS: "false"` kan de
actie-sensor nog gebeurtenissen publiceren voor eigen automations.
Flash `device.yaml` en test één tegel tegelijk: juiste status, juiste fysieke
actie, terugmelding vanuit HA en lange druk. Controleer ook dat externe
wijzigingen in HA op het scherm verschijnen. Voer daarna de
[acceptatietest](ACCEPTATIE.md) uit.
De iconfonts bevatten de tegeliconenset uit `screen_manager/app/tile_icons.py`;
kies `TILEn_ICON` daaruit. Een ander icoon voeg je daar toe en draai je
`tools/generate_icons.py`. De bundel bevat de fonts lokaal. De oudere uitgebreide
[TILE_CONFIGURATION.md](../TILE_CONFIGURATION.md) beschrijft ook het oude
scrollprofiel; gebruik die niet als hardware-/layoutinstructie voor dit bord.
+93
View File
@@ -0,0 +1,93 @@
# Test results app 0.2.40 / firmware 0.2.34 (2026-09-15)
ESP Screens in English: the screens, the management page, the Home Assistant entities
and the docs. See CHANGELOG 0.2.40 and RELEASING "Compatibility 0.2.40".
## What changed
- Text only on both boards and in the app: every on-screen label, status reply, log
line, editor string and guide. Labels follow Home Assistant's English names (climate
modes Heat/Cool, actions Heating/Cooling, Away, Returning to dock, weather conditions),
dates use English abbreviations (Mo 14 Sep), the top bar writes 21.5 °C and 1,249 W.
- Entity names in English (Tile settings, Screen firmware, Device name, IP address,
Guition screen type, Last boot, Normal/Standby/Night brightness, Standby after,
Calibrate touch). Home Assistant gives renamed ESPHome entities new entity IDs.
- App: `core.NAME_*` pairs and `RESEND_STATES` accept both languages;
`Manager.follow_renamed_inboxes` moves a screen's layout and update history to its new
inbox ID (`core.inbox_prefix`, `core.device_prefixes`, `Manager.aliases`,
`Updater.current_id`/`renamed`).
- Docs use Home Assistant 2026.9's menu names (Settings → Apps, App store, Settings → Tools);
guides renamed to `docs/TILES.md`, `CALIBRATING.md`, `ACCEPTANCE.md`, `TROUBLESHOOTING.md`.
## Review method
- Token-level diff of every changed Python, JavaScript, C++ and YAML file with string
literals and comments neutralised (YAML compared as parsed trees, lambdas as C++): 33
code changes, all intended (dual matching, singular hour/year, number format, a log
filter). Every changed string that sits in a comparison, key or subscript was checked.
- No Home Assistant identifier (entity ID, `domain.service`, state or attribute name,
`mdi:` icon, event type, YAML key in doc examples) disappeared from any translated string.
UI terms and state labels were checked against the English translations of the running
HA 2026.9.1 (`frontend/get_translations` and the frontend's own `en` files).
- The 0.2.39 test suites were run against the new code: 15 Python and 4 C++ failures,
every one an assertion on Dutch text; nothing behavioural.
- A dictionary sweep of all string literals and every `text:` value in both board
profiles found Dutch labels the translation had missed (page navigation, climate
card, vacuum status, calibration hints, one entity name); fixed.
## Automated
- Python (`.venv-portal`): 139 tests OK, 9 new in `test_renamed_inbox.py` (slugs and
prefixes, discovery in both languages, a reflash moves layout plus update address and
result, lookups and saves through the old ID, inventory, inspector and save endpoints
called with the old ID, restart after a reflash adopts by device
prefix, other screens' orphaned layouts stay put, an existing layout on the new ID is
never overwritten, an update round that renames mid-update records success under the new
ID, a failing nightly round still notifies).
- C++ (clang++ -std=c++17 -Wall -Wextra -Werror -I.): 13/13 PASS.
- `generate_packages.py --check` green.
- ESPHome 2026.6.2 compile SUCCESS: `easy-cyd-device.yaml` (RAM 31.5%, flash 77.3%),
`easy-guition-device.yaml` (RAM 32.5%, flash 18.6%), manual `device.yaml` and
`guition-device.yaml`.
## Hardware and Home Assistant (Home Assistant Yellow, HA 2026.9.1)
- Local add-on 0.2.40 (SMB + Supervisor), GitHub add-on 0.2.39 stopped with its data kept
(Supervisor backup first).
- Guition on firmware 0.2.33 (Dutch entities) with app 0.2.40: discovered by its Dutch
names (firmware, board, node, IP), layout sent, status `Gesynchroniseerd`, top bar in
English number format, update offer 0.2.34 with profile and address.
- USB flash of the CYD with English entities: HA removed `text.cyd_2_8in_display_tegelinstellingen`
and created `text.cyd_2_8in_display_tile_settings` in the same second (also the other
renamed entities); the inbox reported `Ready for tile configuration`.
- USB flash of the Guition to 0.2.34 while app 0.2.40 ran: log
`Screen text.guition_wallbox_tegelinstellingen now reports as text.guition_wallbox_tile_settings; moved its layout`;
all 10 tiles, 2 pages, settings and top bar back on screen within seconds.
- Both boards on 0.2.34 (`device_info` compile times match the builds), status `Synced`.
- Rollback: USB flash of the CYD back to 0.2.33 while app 0.2.40 ran; the app moved the layout
back to `text.cyd_2_8in_display_tegelinstellingen` (status `Gesynchroniseerd`, 8 tiles).
- **Update** button on the Yellow for that 0.2.33 CYD (profile pointed at a local copy of this
commit's package): ESPHome inside the add-on built and uploaded over Wi-Fi (23 min, first build
with a fresh toolchain); the screen came back as `text.cyd_2_8in_display_tile_settings` on 0.2.34,
the round followed it through verify and settle and recorded "Updated to firmware 0.2.34." under
the new ID; layout intact, no update offered afterwards.
- Guition LVGL captures of every card type and detail card (demo layout, direct controls,
weather forecast, sensor graphs, person, timer, sun path, climate, vacuum, media,
cover, fan, number, select, scene, script), the climate mode picker and light controls:
all English, nothing clipped except long weather names in the five-day list (ellipsis, as before).
- Firmware self-tests: CYD 10 page checks and 50 overlay cycles PASS; Guition page checks
PASS with 18 tiles, light sliders PASS.
- Alerts through Home Assistant: `show_alert` with a timeout (event `timeout`), empty
title falls back to "Notification", a new alert replaces the old one (`replaced`),
`dismiss_alert` (`remote`); every ending arrived as `esphome.screen_alert`.
- Settings: `number.guition_wallbox_normal_brightness` 100 → 90 → 100 in HA; the app
stored each value within a second.
- Editor through ingress: screens, top bar sheet (date preview "Tu 15 Sep"), tile sheet,
Firmware & USB, New screen, Alerts cheatsheet (action names, fields, icons), saving a
new title reached the screen and was restored; no console errors.
## Not tested / for the owner
- The physical look of the alert card: the LVGL capture does not include the top layer.
- Touch on the physical screens after the flash (the owner's check).
- The Supervisor reports an add-on as `error` after a stop; 0.2.39 does the same, not changed here.
+184
View File
@@ -0,0 +1,184 @@
# Configuring tiles for your Home Assistant
Edit `device.yaml`, within the existing `substitutions:`. You don't need to
touch the base code for the examples below. Every change requires a rebuild
and reflash. Go through the [installation](../README.md) first.
## Collecting entity IDs
In HA, open **Settings → Tools → States** (**Developer tools → States** on older
HA versions). Find the entity you want and
copy the full ID, for example `light.kitchen`. Check its state and
attributes. The tile's title is free to choose; the entity ID must be exact.
Under **Settings → Tools → Actions**, test the intended action with that entity.
An action can control the real device: choose a suitable test.
See [HA actions](https://www.home-assistant.io/docs/scripts/perform-actions/).
First make a list of position, title, entity ID, tap action, and long-press action.
Use existing HA scripts/scenes for multiple devices or complex logic.
## Positions and limits
| Positions | Intended use in this firmware |
|---|---|
| 1–6 | Main tiles; light, switch, scene, script, fan, cover, and climate |
| 6 | Also the vacuum card; the card is specifically tied to tile 6 |
| 7 and 9 | Extra light tiles with brightness/color control |
| 8 and 10 | Extra status/action tiles; no full number/climate card |
`TILE_COUNT: "1"` through `"10"` determines how many **consecutive** positions are
visible. Up to and including six, Previous/Next stay hidden; from seven on, 1–6 sit
on page one and the rest on page two. Free scrolling has been replaced by fixed
pages. Leave unused positions on the neutral example entities.
Don't change grid dimensions to add tiles.
## Key settings
| Setting (`N` = tile number) | Meaning |
|---|---|
| `TILEN_ENTITY` | Entity the action is performed on |
| `TILEN_STATE_ENTITY` | Entity for status/attributes; usually the same one |
| `TILEN_TITLE` | Short title, ideally about 12 characters max |
| `TILEN_TYPE` | Domain, for example `light`, `scene`, `climate` |
| `TILEN_TAP_ACTION` | `auto`, `toggle`, or `custom` for the examples below |
| `TILEN_TAP_SERVICE` | Explicit HA action when using custom, for example `script.turn_on` |
| `TILEN_LONGPRESS` | `none`, `slider`, or (tile 6 only) `vacuum` |
| `TILEN_LONGPRESS_SLIDER` | `auto`; picks a suitable control based on type |
| `TILEN_LABEL_ON/OFF` | Text for a simple on/off status |
The example config also fills in the remaining fields. Leave those as they are unless
you deliberately use them. For a scene/script, `STATE_ENTITY` can follow a real light or
switch; a scene itself has no reliable on/off status.
## Color, white temperature, and brightness
An RGB/color light with `LONGPRESS: "slider"` opens the light card directly.
It contains up to three horizontal sliders:
- **Color:** a continuous rainbow (0–360° hue, 100% saturation).
- **White temperature:** warm to cool, within the minimum/maximum Kelvin values
the light reports in Home Assistant.
- **Brightness:** 1–100%; on/off stays available via the tile.
The color and white sliders only appear if `supported_color_modes` supports
them. A dimmable-only light keeps the regular brightness card.
No extra tile settings are needed. For a light, use the same
`ENTITY` and `STATE_ENTITY`. The color card follows `hs_color`, `color_temp_kelvin`,
`min_color_temp_kelvin`, and `max_color_temp_kelvin` of the controlled entity.
If the temperature range is missing, the white slider waits for HA data.
When opened, the card takes over the last received light values. Dragging shows
the chosen value locally; only releasing sends a single command. Color selects the
color mode, white temperature selects the white mode. Brightness doesn't change the
color mode. The rainbow controls hue; pastel/saturation isn't a separate control.
The hue list is sent to HA via ESPHome `data_template`; see the
[official API documentation](https://esphome.io/components/api/#homeassistantaction-action).
The shared implementation lives in `light_controls.h`. Both screen profiles
use it; the Guition has larger controls, the CYD a compact card.
`diagnostics/run_ui_test.py` also checks the slider events with swapped-in
callbacks: no real HA actions. For a safe 40-second preview card:
```sh
python diagnostics/control_ui.py light_controls_preview --host guition-wallbox.local --name guition-wallbox
```
For the CYD, use its own host and name. During this preview card,
light commands are suppressed and the card disappears on its own. Then test the
actual light: long press, choose a color, choose white, adjust brightness,
close, and reopen. Check the physical light and the values in HA.
## Examples
Change these keys in the existing map; don't paste `substitutions:` a second time.
Dimmable light at position 1 (tap toggles, long press opens the control):
```yaml
TILE1_ENTITY: "light.kitchen"
TILE1_STATE_ENTITY: "light.kitchen"
TILE1_TITLE: "Kitchen"
TILE1_TYPE: "light"
TILE1_TAP_ACTION: "auto"
TILE1_LONGPRESS: "slider"
```
A non-dimmable light/switch gets `LONGPRESS: "none"`. Color control
requires that the light supports the relevant color mode.
Scene at position 3:
```yaml
TILE3_ENTITY: "scene.evening"
TILE3_STATE_ENTITY: "light.kitchen"
TILE3_TITLE: "Evening"
TILE3_TYPE: "scene"
TILE3_TAP_ACTION: "auto"
TILE3_LONGPRESS: "none"
```
Script at position 4:
```yaml
TILE4_ENTITY: "script.all_off"
TILE4_STATE_ENTITY: "script.all_off"
TILE4_TITLE: "All off"
TILE4_TYPE: "script"
TILE4_TAP_ACTION: "auto"
TILE4_LONGPRESS: "none"
```
AC at position 5 (long press opens climate):
```yaml
TILE5_ENTITY: "climate.living_room"
TILE5_STATE_ENTITY: "climate.living_room"
TILE5_TITLE: "AC"
TILE5_TYPE: "climate"
TILE5_TAP_ACTION: "toggle"
TILE5_TAP_SERVICE: "climate.toggle"
TILE5_LONGPRESS: "slider"
```
Check `min_temp`, `max_temp`, `target_temp_step`, `hvac_modes`, and the
supported fan/swing modes in HA. This card is primarily for a **single
setpoint**, not a thermostat that only uses a temperature range.
Test your integration's modes individually; a different AC unit
may have different capabilities.
Robot vacuum at position 6 (tap starts; long press opens the card):
```yaml
TILE6_ENTITY: "vacuum.robot"
TILE6_STATE_ENTITY: "vacuum.robot"
TILE6_TITLE: "Vacuum"
TILE6_TYPE: "vacuum"
TILE6_TAP_ACTION: "custom"
TILE6_TAP_SERVICE: "vacuum.start"
TILE6_LONGPRESS: "vacuum"
```
The vacuum card uses start/pause/stop/return/locate and the
speed names `quiet`, `balanced`, `turbo`, `max`. Compare these with the
supported actions and `fan_speed_list` in HA. The speed buttons need to be
adjusted in the base code if your integration expects different names.
This is not a universal card for every robot model.
## Enabling and checking actions
After calibration and HA pairing, set `DIRECT_ACTIONS: "true"`. In the
ESPHome integration, grant permission for Home Assistant actions. Don't use an
HA automation that also runs the same screen action again separately; that can
cause a double toggle. With `DIRECT_ACTIONS: "false"`, the action sensor can
still publish events for your own automations.
Flash `device.yaml` and test one tile at a time: correct status, correct physical
action, feedback from HA, and long press. Also check that external
changes in HA appear on the screen. Then run the
[acceptance test](ACCEPTANCE.md).
The icon fonts contain the tile icon set from `screen_manager/app/tile_icons.py`;
pick `TILEn_ICON` from there. To add a different icon, add it there and run
`tools/generate_icons.py`. The bundle includes the fonts locally. The older, more extensive
[TILE_CONFIGURATION.md](../TILE_CONFIGURATION.md) also describes the removed
scroll profile as a historical record; don't use it as hardware/layout instructions for this board.
+32
View File
@@ -0,0 +1,32 @@
# Troubleshooting
| Symptom | Check first |
|---|---|
| No USB port | Data cable, a different USB port, board power; compare `python -m serial.tools.list_ports` before/after connecting. Install the USB chip vendor's driver if needed. |
| Permission denied on Linux | Access to the serial device group (often `dialout`); log in again after a group change. |
| Port busy | Stop ESPHome logs, the IDE monitor, and other serial readers. One reader at a time. |
| Upload keeps connecting | Check the correct board/port. Hold BOOT while connecting and release afterward if the board requires it. |
| Build fails | Python 3.11–3.14 and ESPHome 2026.6.2; the full unpacked folder, local fonts/components present, internet, and disk space. Save the first real error from the build log. |
| White/black or wrongly rotated image | Check the ILI9341 + XPT2046 variant. Don't blindly copy the pins, rotation, or SPI settings from a different CYD model. |
| No measurement screen | The upload must be complete, not just the build. Flash with `-s CALIBRATION_ON_BOOT true`. Look for `USB calibration ready` in the USB logs; a normal boot shows no crosshairs. |
| 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. |
| 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, `DIRECT_ACTIONS: "true"`, the real entity ID, and a supported action. |
| Vacuum/climate partly usable | Supported modes/attributes differ per integration; see TILES.md and test the same action in HA first. |
| Wrong pagination | `TILE_COUNT` is 1–10; hidden buttons up to six, two pages from seven on. Reflash after changing it. |
| 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):
```sh
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
local configuration, and change one cause at a time.