Download a screen's firmware and put it on from your own computer (0.2.68)

GitHub issue #8: Home Assistant on a server or virtual machine is out of
reach of the screen. New screen and Firmware & USB get a Download choice:
ESP Screens builds the profile's firmware as always and offers ESPHome's
factory image, which the owner flashes with ESPHome Web in Chrome or Edge.

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

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
Max Gramser
2026-09-17 15:42:32 +02:00
parent 6809d3b941
commit 66b1590184
14 changed files with 588 additions and 66 deletions
+3
View File
@@ -75,6 +75,9 @@ under **Settings → Devices & services** in Home Assistant, and then choose the
- **USB (Linux only):** connect the screen, uncomment `devices:` in `compose.yaml` with its
port (`/dev/ttyUSB0` or `/dev/ttyACM0`), and run `docker compose up -d` again. Installs
over Wi-Fi (OTA) and the nightly updates need nothing extra.
- **Without USB passthrough (app 0.2.68+):** in **New screen**, choose **Download · flash from
your own computer**. The container builds the firmware, and you put it on the screen with
[ESPHome Web](https://web.esphome.io) in Chrome or Edge on the computer the screen is plugged into.
- **Backups:** Home Assistant backups don't include this container. Keep a copy of
`data/screens.json` and `data/updates.json` (layouts and update settings) and of the
ESPHome folder. `data/build` and `data/platformio` are caches.
+15 -4
View File
@@ -64,10 +64,21 @@ again for an existing screen generates new keys and is not the
update route.
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 **Settings → Firmware & USB**.
machine running Home Assistant, and a server or virtual machine may have no USB port
within reach at all. Then put the firmware on the screen from your own computer:
1. Under **Install via**, choose **Download · flash from your own computer** and click
**Build & download**. ESP Screens builds the firmware the same way; when it's ready,
the window offers the file, for example `kitchen.factory.bin`.
2. Plug the screen into your own computer with a USB data cable.
3. Open [ESPHome Web](https://web.esphome.io/?dashboard_install) in Chrome or Edge on that
computer (other browsers can't reach USB), click **Connect** and choose the screen's port.
4. Click **Install** and select the downloaded file. The screen restarts and joins your Wi-Fi.
The file holds your Wi-Fi password and the screen's keys: keep it to yourself. Pairing works
as in chapter 3, and every later update goes over Wi-Fi, so the cable is only needed once.
For an existing profile, the same file is under **Settings → Firmware & USB**: choose the
profile and **Download · flash from your own computer**, then **Build & download**.
**CYD:** calibration appears on first boot. Calmly tap the visible crosshair
three times, hold each tap briefly, and follow each next crosshair in turn.
+95
View File
@@ -0,0 +1,95 @@
# Test results app 0.2.68 / firmware 0.2.58 (2026-09-17)
GitHub issue #8 asked for a firmware download, because Home Assistant runs on a Proxmox server and plugging the
screen into it is awkward. ESP Screens already builds a profile's firmware with its own ESPHome CLI and flashes it over
USB; this release adds a third choice: build, download the file, and put it on the screen from your own computer with
ESPHome Web. Max's calls: the three routes are "build and flash on the Home Assistant machine", "build and flash in the
browser" (later) and "build and download" (this release); USB on the Home Assistant machine must always stay visible,
also before a board is plugged in, "or people think it isn't possible at all". App only. Built on 0.2.67 (`6809d3b`).
## ESPHome, read first
- ESPHome 2026.6.2 `components/esp32/__init__.py` `get_download_types`: the "Factory format (Previously Modern)" is
`firmware.factory.bin` next to `firmware.bin`, "For use with ESPHome Web and other tools"; the dashboard's download
handler serves it from `firmware_bin_path.parent`. `core/config.py`: `ESPHOME_BUILD_PATH` becomes
`<build path>/<node>`, so the app's `data/build/<profile>` holds `<node>/.pioenvs/<node>/firmware.factory.bin`
(PlatformIO) or `<node>/build/firmware.factory.bin` (`espidf/toolchain.py`, native ESP-IDF). Both are searched; the
newest wins and links are skipped.
- ESPHome's own install dialog (`esphome_dashboard` source maps, `install-choose-dialog.ts`) offers Wirelessly, Plug
into this computer, Plug into the computer running ESPHome Device Builder and Manual download. Browser flashing needs
`"serial" in navigator` and `window.isSecureContext` (HTTPS); otherwise it falls back to the download plus
`https://web.esphome.io/?dashboard_install`. ESP Screens links to that same address.
- ESPHome Web's words (`esphome/device-builder-frontend` `src/translations/en.json`): "Connect your device below, then
click Install to flash your downloaded project", Connect, Install, "Select the factory binary you want to install on
your device", and holding BOOT when it fails to initialise. The steps in the window and the docs use those words.
## Automated
- Python (`.venv-portal`): 386 tests OK (377 on 0.2.67).
- New `tests/test_firmware_download.py` (9), with a stand-in ESPHome CLI that writes the factory image where ESPHome
2026.6.2 does: the Download target is checked (CLI, busy slot, unknown targets) before anything is written; the
download job compiles without uploading and offers `<profile>.factory.bin`; a build without a factory image fails
instead of offering nothing; the native ESP-IDF layout is found; a new job withdraws the old file until it succeeds,
so a failed rebuild offers nothing; Build only offers the file and Check does not; only a file built by this process
is served (not one left from before a restart, not another name, not a link); the newest image wins after a node
rename; and the HTTP route: CSRF on the create, 400 while building, `application/octet-stream`,
`attachment; filename="kitchen.factory.bin"`, `no-store`, identical bytes, and the *not yet in Home Assistant* card
turning to "downloaded".
- `node --check screen_manager/app/static/app.js` clean.
## Real ESPHome builds (2026.6.2, Mac)
Through `Firmware.install(target='download')` itself, with the app's environment (`ESPHOME_BUILD_PATH` per profile,
`PLATFORMIO_CORE_DIR` under data), a profile made by `installation_yaml` and the remote packages from `main`:
- **CYD** (`download-check-cyd`): success after 132 s, `Succeeded: download`, the image found at
`data/build/download-check-cyd/download-check-cyd/.pioenvs/download-check-cyd/firmware.factory.bin`, 1,602,272 bytes.
Layout checked: padding to 0x1000, bootloader magic 0xE9 at 0x1000, partition table at 0x8000 (otadata, phy_init,
app0 at 0x10000, app1 at 0x1D0000, nvs at 0x390000), app at 0x10000: `esptool image-info` checksum valid, validation
hash valid, project `download-check-cyd`, ESP-IDF 5.5.4; the image contains firmware version 0.2.58. The file ends
far below NVS, so flashing it keeps a CYD's touch calibration, as a USB install does.
- **Guition** (`download-check-guition`): success after 126 s, 1,841,760 bytes at the same place. Bootloader magic
0xE9 at 0x0 (ESP32-S3), partition table at 0x8000 (app0 at 0x10000 and app1 at 0x7D0000, 0x7C0000 each; nvs at
0xF90000), app at 0x10000 with a valid checksum and validation hash, project `download-check-guition`, firmware
0.2.58 inside.
## Editor, clicked through
Demo home with the real app code (fake Home Assistant, stand-in CLI with ESPHome's log lines, USB ports from a file),
desktop 1280×900 and phone 375×812:
- New screen without a board: **Install via** lists `USB · no board found on the Home Assistant machine yet` first and
selects it, **Install** waits (disabled) and the hint says where to plug in or to choose Download.
- A board plugged in: the list shows its port within a poll and selects it; **Install** is enabled. A second board:
"More than one board connected". Unplugged while chosen: back to the waiting USB entry.
- **Download** or **Later** chosen: kept while boards come and go. Button: **Build & download** / **Save profile**.
- **Build & download**: `POST firmware/profiles` with `target: download`, "Building firmware…" with the spinner;
closed and reopened during the build, the window shows the running build again and ends on the download. Done:
"Ready to download.", **Download garage-screen.factory.bin** (`api/firmware/profiles/garage-screen.yaml/download`,
fetched from the page: 200, `application/octet-stream`, attachment name, `no-store`, 1,504,097 bytes; not clicked,
so nothing landed in Downloads), the ESPHome Web link to `?dashboard_install` with `target="_blank"`, the CYD
calibration note, the API key and the pairing steps.
- A failing build: "That didn't work." / "Build failed" with the error line; **Retry** posts `action: download` without
a target. **Later**: "Profile saved." with the new text that points to Firmware & USB and Download.
- The card under My screens: "Firmware downloaded, not yet in Home Assistant…".
- Firmware & USB: Wi-Fi / OTA, the USB entry (waiting or the ports, refreshed while open), Download; with Download the
host field hides and the button says **Build & download**; a profile never built shows no link; after the build,
**Download kitchen-screen.factory.bin** appears; back to Wi-Fi / OTA: **Build & install** with the host field.
- Phone width: the page does not scroll sideways; the download box wraps.
- Found on the way: the device name field's `pattern="[a-z][a-z0-9-]{0,29}"` is invalid under the `v` flag that current
Chrome uses for `pattern`, so Chrome skipped the check and logged an error. Now `[a-z][a-z0-9\-]{0,29}`: "Bad Name",
"9lives" and 31 characters are flagged while typing, "living-room" and "ok-2" pass.
## Home Assistant ingress (read only)
The Yellow runs the store add-on 0.2.66. Its existing zip download (`api/claude-skill.zip`, the same kind of GET with
`Content-Disposition`) fetched through `/api/hassio_ingress/…` with an ingress session: 200, `application/zip`,
`attachment; filename="esp-screens.zip"`, `no-store`, `Content-Length` kept and a valid zip. The firmware file takes
the same path (below Home Assistant's 4 MB limit for a buffered response).
## Not tested / for the owner
- Nothing was flashed. A real flash with ESPHome Web in Chrome, with a file downloaded from the add-on in Home
Assistant, is still to do: New screen (or Firmware & USB → Download) → Build & download → Download → web.esphome.io
→ Connect → Install → select the file. A board keeps its identity when the file comes from its own profile.
- The first build on the Yellow takes minutes, as with USB.
+1
View File
@@ -6,6 +6,7 @@
| 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. |
| ESPHome Web shows no port or can't connect (Download) | Chrome or Edge on a computer; Safari, Firefox and phones can't reach USB. A data cable, and the driver for the board's USB chip if the computer asks for one (CH340 on most CYDs). Hold BOOT while choosing the port if it keeps failing to connect. |
| 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. |