Files
Xandrossian 9857cc3bda
CI / checks (push) Successful in 12m50s
CI / firmware (add-on) (push) Successful in 18m19s
CI / firmware (min_version) (push) Successful in 17m55s
Add the Elecrow CrowPanel 7.0" as a third board, and take the packages and the add-on from Gitea (0.2.93)
A board file for the Elecrow CrowPanel 7.0" (DIS08070H, ESP32-S3-WROOM-1-N4R8): 800x480 through mipi_rgb, GT911 on the
ESP32-S3's USB pins (elecrow_usb_phy.h frees them, behind a flag only this board sets), the Guition's vertical sizes
across a wider page, no rotation. Its 4 MB of flash take the CYD's budget: a partition table of the component's
(smart_display: partitions: 4mb_wide_slots, 1,984 KB slots), the icon fonts at 2 bits a pixel and the TLS client only
bring the firmware to 1,865,440 bytes, 91.8 % of a slot, with camera images kept. docs/ELECROW.md has the numbers and
the trade.

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

This fork builds from gittea.trippedonmy.name/Xandrossian/homeassistant_espscreen: the packages, the fonts, the
component and the add-on repository point there instead of GitHub.
2026-09-20 23:18:01 -07:00

153 lines
9.8 KiB
Markdown
Raw Permalink Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# Camera images on a Guition
App 0.2.66 with firmware 0.2.57 shows camera images on a Guition 4848S040 (and, from app 0.2.93 with firmware
0.2.79, on an Elecrow CrowPanel 7.0" at its own 800×480 size, docs/ELECROW.md; "Guition" below reads for both):
- **A camera tile.** Add a `camera.*` or `image.*` entity as a tile. A tap opens the image full
screen, with the round back key at the top left like every card, and a spinner until the first
image is there (firmware 0.2.73). The image is refreshed every four seconds while it is open. It
is not video: ESPHome has no video decoder.
- **An alert with a picture.** Add `camera: camera.front_door` to the `esp_screens_show_alert`
event. The card shows the picture of that moment across its top (it stays that picture), with
the card's round corners (firmware 0.2.73); a tap on it opens the camera full screen over the
alert, and Back returns to the alert.
The CYD has no memory for images (a 320×180 image needs 115 KB in one piece, the CYD's largest
free block is about 45 KB). It shows the alert without the picture, and the editor doesn't offer
camera tiles for it.
## The album cover on the media card
App 0.2.77 with firmware 0.2.64 uses the same road for a media player's picture. The media card
(a tap on a media player's tile, or a media tile of size *Full page*) shows the album cover of
what plays, with the title, the artist and the album, a progress bar and the keys under it.
- The screen asks ESP Screen Manager for the cover with the size it draws it at and the colour
behind it (the event `esphome.screen_camera` with `size` and `bg`). The app fetches the
picture where Home Assistant's state points (`entity_picture`), cuts it square, sizes it,
rounds the corners over that colour and serves it on port 8098 as a BMP, like a camera image.
- A cover is fetched once per picture: the state carries a short mark of the picture, and the
screen asks again only when the mark changes (a new track), when the card opens again or
when the page turns back to a full-page media tile. Nothing polls.
- A player without a picture (a radio station, a player that is off) keeps the player's icon in
the cover's place; the app answers with an empty link and the screen stops asking.
- The CYD shows the same card without the picture: its icon stands in for the cover.
- One picture loads at a time. An alert closes an open card and its cover. Under a media tile of
size *Full page* the alert's picture goes first: the tile's cover waits until the alert's picture
is there, and a cover already on its way finishes before the alert's picture starts.
## A live picture on a camera tile
App 0.2.91 with firmware 0.2.77 puts the camera on the tile itself: **Display → Live picture** in the
tile's settings, with a pace of 15 or 30 seconds (`refresh`). The tile shows a small square of the
camera's view in the icon's place, the middle of the snapshot cut square with the tile's rounded
corners, and refreshes it while that page is on the screen. A tap still opens the camera full screen.
- **One download per page.** The screen asks ESP Screen Manager for all the live tiles of the page at
once (the event `esphome.screen_camera` with `tiles`, the entities in slot order, `size`, the side of
the icon's circle, and `bg`, the colour of each tile behind the corners). The app answers with one
BMP: a strip of squares, top to bottom in that order, and every tile draws its own square out of it
(LVGL's image offset). Six live tiles cost the screen one download of about 50 KB; a tile over the
whole page gets one square of 128 px.
- **At the pace of the fastest tile.** The page loads its strip every 15 s when any of its tiles says
15 s. The app fetches a camera again only when that camera's own pace has passed, so a 30 s camera
on a 15 s page is fetched every other load. The strip comes whole every time, never as a 304:
ESPHome's `http_request` logs a 304 as a failed request and raises its error flag, which a page of
slow cameras would do every 15 s. Nobody loading means nothing fetched, as with the camera full
screen.
- **After the other pictures.** The strip waits for the alert's picture, a cover on its way and the
camera full screen (one picture loads at a time), and does not load under an open card, in standby
or under a finger. A page turn, dark mode (other colours behind the corners) or a changed tile drops
the strip and asks for a new one.
- **A camera without a picture** keeps its icon: the app names it with an empty entry in its answer
and paints a plain square of the tile's colour in the strip.
- **A media tile's album cover** (app 0.2.92, firmware 0.2.78) rides in the same strip: **Display →
Album cover** on a single or double-width media player tile. The app fetches the player's picture
only when its address changes (a new track), so a page with a camera and a Sonos loads its strip at
the camera's pace with the cover reused, and a page of media tiles alone loads once. The screen asks
for the page again the moment a player's picture mark in its state changes. A player without a
picture keeps its icon; the tile over the whole page keeps the card's big cover.
- The strip lives in a third `online_image` of the Guition profile (`tile_image`, PSRAM); the CYD has
none and the editor does not offer the live picture there.
## A doorbell
```yaml
triggers:
- trigger: state
entity_id: event.front_door_ding
actions:
- event: esp_screens_show_alert
event_data:
title: Someone is at the door
icon: doorbell
camera: camera.front_door
timeout: 60
```
Any `camera.*` entity works, and so does an `image.*` entity, such as the snapshot a doorbell or
motion integration keeps of its last event.
## How the image gets to the screen
The screen never talks to Home Assistant about images, and it never holds a Home Assistant token.
1. The screen asks ESP Screen Manager for a camera (the event `esphome.screen_camera`), or the app
sends the picture of an alert by itself.
2. The app fetches the snapshot from Home Assistant with its own access (the same pictures the
Home Assistant frontend shows), and makes it exactly as large as the screen draws it: at most
480×480 full screen, 392×220 on an alert card, proportions kept.
3. It serves the result as an uncompressed 24-bit BMP on **port 8098** under a random link, and
sends the link to the screen. ESPHome's `online_image` loads it.
While a camera is open, the screen loads its link every four seconds, one image at a time. The app
serves the last snapshot at once and starts fetching the next one, so each load gets a picture one
load younger: the picture changes at the screen's steady pace. (A fetch on its own clock next to the
screen's made the picture change after 1.5 s one time and 6 s the next.) A slow camera makes the
images older, never the screen slower, and nothing queues up. Nobody loading means nothing fetched.
A link that nobody loads for two minutes stops working; an alert's picture stays for half an hour.
**Why BMP.** ESPHome decodes a BMP piece by piece while it downloads (16 KB per round of its main
loop since firmware 0.2.73, 4 KB before). A JPEG of the full screen took 0.6 s in one piece on the
Guition, during which the screen missed taps. A full-screen BMP is about 390 KB; on the bench
Guition it comes in about 1.8 s (2.8 s with 4 KB).
## Network
- **Home Assistant OS:** the app publishes port 8098 on the Home Assistant host. Keep it at 8098 in
the app's network settings; the screens need to reach Home Assistant's address on that port.
- **Docker** (docs/DOCKER.md): the container uses the host network, so 8098 is open as is. When
the screens reach the host under another address, set `SCREEN_CAMERA_URL`, for example
`http://192.168.1.20:8098`.
- The images travel unencrypted over the LAN, like the screens' other HTTP traffic. Links are
random, short-lived, and only issued for a camera on that screen's tiles or in a recent alert.
## Memory and speed (Guition, measured 2026-09-17)
- Full screen: 480×270 RGB565 is 259 KB of PSRAM; the alert picture 172 KB. Both are freed when
the camera or the alert closes. A new alert closes an open camera first.
- The internal heap stays level while a camera refreshes: 77.2 KB free after 91 images in six minutes,
and PSRAM unchanged.
- Standby, **Back to page 1** and a new layout close the camera; nothing loads in standby.
- The first image (firmware 0.2.73, measured 2026-09-19 with an EZVIZ camera): the screen asks when
the camera opens and loads the link as soon as it comes. About 2 s when the app still has the
camera's last snapshot (it keeps one for 30 s after the last load), 4.5 s when it must ask Home
Assistant first, of which 2.4 s is the camera's own snapshot. Firmware 0.2.72 took 3.4 s and
5.8 s. Details in docs/TEST_RESULTS_0287.md.
- Wi-Fi without power save (firmware 0.2.74 sets `power_save_mode: none` itself) makes the screen
wait on its Wi-Fi less often while an image comes in: a loop held over 50 ms in one of eleven
opens, against five of twelve with power save.
## For developers
- `screen_manager/app/camera_feed.py`: fetching, sizing, links and the port; `encode_live` and `CameraFeed.live`
make the strip for a page's live tiles (`Manager.answer_live` in `server.py` checks the tiles against the layout).
- `components/smart_display/camera_view.h`: when to ask for a link and when to load again
(`tests/test_camera_view.cpp`).
- `components/smart_display/runtime_tiles.h`: the full-screen view, the alert picture, the live tiles
(`live_tick`, `live_place`) and the `camera` message.
- `packages/boards/guition-4848s040.yaml`: the three `online_image` components (the camera full screen and the
cover, the alert's picture, the live tiles' strip), the alert frame, and the diagnostic action `preview_camera`
(an entity opens it, an empty entity closes it).
- `tests/test_camera.py`: the app side and the words both sides share.