Files
homeassistant_espscreen/docs/SETTINGS.md
T
Max Gramser b83164d61a Change a screen's settings on the screen itself (0.2.52)
Holding the top bar for about a second and a half opens a settings page on the
screen, with a blue line filling along the top edge while you hold. A built-in
screen.settings tile and the esphome.<screen>_open_settings action open it too.

The page is one constexpr table of rows in settings_screen.h: Brightness,
Night, Screen (clock, back to page 1, swiping, rotation) and This screen (name,
address, firmware, Home Assistant, Restart). Toggles flip on a tap, numbers and
times step with -/+ (a held time walks whole hours), a choice cycles in a chip,
and a row that depends on a switch above it is greyed out. The LVGL objects exist
only while the page is open: +608 bytes of RAM and +10.7 KB of flash on the CYD.
A change is saved, applied and reported through the existing screen_setting
event, so ESP Screens shows the same value within a second.

New setting auto_home (default on, 2 minutes): an open card, the settings page
or a later page goes back to page 1 after that long without a touch, not only on
standby. It travels beside the frozen eleven-key settings block with its own
preference, so older firmware and older apps keep working.

docs/SETTINGS.md is the recipe for adding a setting; the Claude skill explains
the page. Firmware 0.2.44.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-09-16 10:05:53 +02:00

5.2 KiB

Settings: on the screen and in ESP Screens

Every screen setting lives in two places at once: the Screen settings block of the add-on editor, and the settings page on the screen itself (firmware 0.2.44+). This page says what that page is made of, and exactly what adding one more setting takes.

What the user sees

Holding the top bar of the overview for about one and a half seconds opens the page; a blue line grows along the top edge while you hold, and letting go before it finishes cancels. A screen can also carry a screen.settings tile, and Home Assistant can open it with esphome.<screen>_open_settings.

The page is a menu of groups, each of which opens a page of its own:

Group Rows
Brightness Brightness, Auto standby, Standby after, Standby brightness
Night Night mode, Starts, Ends, Night brightness
Screen Clock, Back to page 1, After, Also on standby, Swipe between pages, Rotation (boards that turn)
This screen Screen, Address, Firmware, Home Assistant, Restart

Every change is saved on the screen, applied at once, and sent to the add-on as an esphome.screen_setting event, so the editor shows the same value within a second. The add-on remains the owner: its next layout message repeats every setting, and a screen that was offline catches up then.

The rules the page follows

  • Two levels, never three. A group page is the deepest place a setting can live.
  • No free scrolling. A group that does not fit gets the same < Previous / Next > pager as the tile pages. A 320x240 board shows five rows, a 480x480 board six.
  • A row is a control, not a form. Toggles flip on tap, numbers and times have - and +, a choice cycles through its options in a chip on the right.
  • A row that depends on a switch above it is greyed out, not hidden, so the page never jumps around.
  • Only settings that belong to this piece of glass. Tiles, the top bar and pages belong to the editor, which has a mouse and a keyboard; the screen gets what you want to change while standing in front of it.

Adding a setting

The example below adds "Beep on touch" (beep), a switch.

1. Where the value lives

Two homes, and the choice is fixed by history:

  • screen_settings::Settings in components/smart_display/screen_settings.h is the frozen block of eleven values that ESP Screens sends as settings. Its format is version 1 and changing it needs a preference migration and firmware-version gating in the add-on, because older firmware refuses a settings object that does not have exactly its own keys. Don't.
  • Anything new is a plain value in settings_screen.h next to swipe_pages, rotation and auto_home, with its own preference and its own key in the layout message. That is backward and forward compatible in both directions: old firmware ignores the key, a new screen with an old add-on keeps its saved value.
// settings_screen.h, next to the others
inline int32_t swipe_pages = 0, rotation = 0, auto_home = 1, auto_home_seconds = 120, beep = 0;

Storing it (components/smart_display/runtime_tiles.h): extend HomeTimeout-style records or add one of your own, load it in load_settings(), write it in persist_settings(), and accept the key in receive() next to auto_home — validate first, then save.

2. The row

One line in the table of the group it belongs to, in settings_screen.h:

toggle("Beep on touch", [] { return beep; },
       [](int32_t value) { beep = value ? 1 : 0; changed("beep", beep); }),

changed(key, value) saves, applies and reports in one go; key must be the add-on's key exactly. The row kinds are toggle, number (fixed step, optional unit), duration (seconds, steps grow with the value), moment (minutes since midnight, quarters by tap and hours while held), choice, info and action. A row can carry shown (leave it out on boards that lack the hardware) and enabled (grey while the switch it depends on is off).

Watch the count: a group of more than five rows gets a pager on a 320x240 board. Six is the maximum that still fits a 480x480 board in one go.

3. The add-on

  • screen_manager/app/core.py: one line in SETTING_RULES ('beep': (False, None, None)), which gives you validation, storage and the write-back from the screen for free.
  • screen_manager/app/server.py: add the key to extra in layout_message and send it as its own key, next to auto_home. Never let it into the settings block.
  • screen_manager/app/static/app.js: one line in settingDefinitions for the editor's own control.
  • Needs new firmware? min_firmware() in core.py keeps the screen from being told about something it cannot do.

4. Tests and proof

  • tests/test_settings_screen.cpp (clang++ -std=c++17 -Wall -Wextra -Werror -I.) walks every page and every row: a new row is checked by the table test as soon as it exists.
  • tests/test_settings_view.py and tests/test_layout.py cover the add-on side.
  • Render it before believing it: .esphome/readme-render/host_build.py <board> --compile builds the real firmware for the Mac and render_settings.py <board> drives it over the API and saves PNGs of every page, including the hold gesture, the time picker and the settings tile.