Skip to content

Lambda-based labels refactor + live WiFi icon, configurable accuracy, ESPHome 2026.6 compat - #16

Open
oxc wants to merge 7 commits into
HomeDicator:mainfrom
oxc:feature/label-lambda-refactor
Open

Lambda-based labels refactor + live WiFi icon, configurable accuracy, ESPHome 2026.6 compat#16
oxc wants to merge 7 commits into
HomeDicator:mainfrom
oxc:feature/label-lambda-refactor

Conversation

@oxc

@oxc oxc commented Jul 8, 2026

Copy link
Copy Markdown

Summary

Refactors how display labels are populated and builds a few features on top of it.
Instead of every sensor's on_value handler formatting text and pushing it into a
label via lvgl.label.update, each label now owns a text: !lambda that reads the
source state directly, and the sensor just calls lvgl.widget.refresh. This
centralizes formatting and makes labels show the correct value on boot/reconnect
rather than only after the first update.

AI Disclaimer

I had written those changes months ago before I had started using AI agents (at least
for esphome). I have now used Claude Code to polish things and re-create the commits
in the forked repo (I only had them in my esphome config).

Changes

  • refactor: define lambdas in labels, let sensors refresh them — core sensor/
    climate templates, thermostat tiles, clock, About page and version labels now format
    their own text; handlers just refresh.
  • feat: lambda-based sensor tiles with configurable accuracy — sensor tiles render
    from a lambda and accept an optional accuracy var (default 1, e.g. accuracy: 0
    for integers). The coloured icon container is given an id so a consumer can pass a
    dynamic color: lambda and refresh it.
  • feat: show live WiFi signal strength icon — the top-bar WiFi icon is computed
    from wifi_signal_percent plus a wifi_connected global toggled on connect/
    disconnect, showing the dedicated offline glyph when disconnected. The SDL/host build
    stubs the sensor so the shared lambda still compiles.
  • chore: use recommended ESP-IDF version instead of pinning — drops the pinned
    version / platform_version.
  • chore: add water-percent and weather-dust glyphs — for humidity / air-quality
    tile icons.
  • chore: pre-create empty bottom_pager widget list — explicit widgets: [] needed
    to compile.
  • chore: drop show_test_card for LVGL/ESPHome 2026.6 compatibility — LVGL owns the
    framebuffer, so show_test_card is rejected on newer ESPHome; it never rendered here
    anyway.

Points worth discussing

  • ESP-IDF unpin: I dropped the pinned framework version to use ESPHome's
    recommended one. Happy to split this into its own PR if you'd rather keep the pin.
  • Minimum ESPHome version: accuracy uses a Jinja-filter substitution
    (%.${accuracy | default(1)}f), so this raises the minimum ESPHome version. Combined
    with the unpin + the show_test_card fix, the tree now validates cleanly on
    ESPHome 2026.6.4 (Configuration is valid!).

Testing

esphome config HomeDicator.yaml (SDL/host build) reports Configuration is valid!
on ESPHome 2026.6.4.

oxc and others added 7 commits July 8, 2026 13:59
Instead of having each on_value handler know exactly how the label needs
to be formatted and pushing text into it via lvgl.label.update, define
the label text as a !lambda that reads the source state (rendering a
placeholder while !has_state()), and have the sensor/text_sensor simply
lvgl.widget.refresh the label. This centralizes formatting and makes
labels show the correct value on boot/reconnect, not just after the
first update.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Render sensor tile values from a label !lambda (consistent with the
label refactor) and make the number of decimals configurable via an
optional `accuracy` var (default 1), e.g. `accuracy: 0` for integers.
Also expose the coloured icon container via an id so a consumer can
pass a dynamic `color:` lambda and refresh it, and quote `${unit}` so
values like empty strings are handled safely.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Compute the top-bar WiFi icon from a label !lambda based on
wifi_signal_percent (and a wifi_connected global toggled by the wifi
on_connect/on_disconnect handlers), refreshing it on value change and
connect/disconnect. When disconnected it shows the dedicated offline
glyph. The SDL/host build has no WiFi hardware, so it stubs
wifi_signal_percent and relies on the global default so the shared
lambda still compiles and the preview shows a signal.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Drop the pinned esp-idf `version` / `platform_version` so ESPHome uses
its recommended framework version.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Add mdi:water-percent and mdi:weather-dust to the icons35 tile font for
use as humidity / air-quality tile icons.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
The pager dots are created by a script at runtime, but an explicit empty
`widgets: []` is needed for the project to compile.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Newer ESPHome rejects show_test_card (along with auto_clear_enabled:
true, lambda: and pages:) on a display driven by LVGL, since LVGL owns
the framebuffer. This project always uses LVGL so the test card never
rendered anyway; removing it lets the SDL/host dev build validate and
run on current ESPHome.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Copilot AI review requested due to automatic review settings July 8, 2026 13:17

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

This PR refactors LVGL label rendering to be lambda-driven (labels read source state directly and are updated via lvgl.widget.refresh), and builds new UI behavior on top of that (notably a live WiFi strength icon and configurable numeric precision), while also aligning configs with ESPHome/LVGL 2026.6 compatibility.

Changes:

  • Migrate multiple labels from lvgl.label.update in on_value handlers to text: !lambda + lvgl.widget.refresh.
  • Add lambda-rendered sensor tiles with optional accuracy and expose icon-container id for dynamic color refresh.
  • Implement a live WiFi icon (connected/offline + strength tiers), stubbed for SDL/host builds; remove show_test_card and unpin ESP-IDF version for 2026.6 compat.

Reviewed changes

Copilot reviewed 22 out of 22 changed files in this pull request and generated 2 comments.

Show a summary per file
File Description
HomeDicator/user_interface/templates/tiles/thermostat/wide.yaml Thermostat value label now renders from a lambda instead of static text.
HomeDicator/user_interface/templates/tiles/thermostat/wide_half_height.yaml Same lambda-based thermostat value label refactor.
HomeDicator/user_interface/templates/tiles/thermostat/wide_half_height_icon_right.yaml Same lambda-based thermostat value label refactor.
HomeDicator/user_interface/templates/tiles/thermostat/square.yaml Same lambda-based thermostat value label refactor.
HomeDicator/user_interface/templates/tiles/thermostat/helpers/on_value.yaml Thermostat interaction handler switched from label updates to widget refresh + HA action.
HomeDicator/user_interface/templates/tiles/sensor/wide.yaml Sensor tile uses lambda text with configurable accuracy; exposes icon container id.
HomeDicator/user_interface/templates/tiles/sensor/square.yaml Same as wide sensor tile: lambda text + accuracy + icon container id.
HomeDicator/user_interface/pages/top_layer/wifi.yaml WiFi icon is now computed dynamically from connection + signal percent.
HomeDicator/user_interface/pages/top_layer/time.yaml Time label now formats itself via lambda (24h/12h).
HomeDicator/user_interface/pages/top_layer/bottom_pager.yaml Pre-creates an explicit empty widgets: [] list for compatibility.
HomeDicator/user_interface/pages/about.yaml ESPHome version label now reads the text sensor directly via lambda.
HomeDicator/device/sdl.yaml Stubs wifi_signal_percent for host builds so shared UI lambdas compile.
HomeDicator/core/templates/sensor.yaml HA sensor template now refreshes the widget instead of pushing formatted text.
HomeDicator/core/templates/climate_sensor.yaml Climate sensor template now refreshes the value label instead of pushing formatted text.
HomeDicator/core/templates/climate_sensor_wide.yaml Same refresh-based refactor for wide climate sensor template.
HomeDicator/core/config/device/seeed-sensecap-indicator/hardware.yaml Unpins ESP-IDF version; adds WiFi connect/disconnect handling to refresh icon + track connected state.
HomeDicator/core/config/device/sdl/hardware.yaml Drops show_test_card for ESPHome/LVGL 2026.6 compatibility.
HomeDicator/core/config/common/text_sensors/esphome_version.yaml Text sensor now triggers widget refresh instead of updating label text directly.
HomeDicator/core/config/common/sensors/wifi_signal_percent.yaml WiFi percent sensor now refreshes the icon widget instead of formatting the glyph in-place.
HomeDicator/core/config/common/scripts.yaml update_time now refreshes the time widget rather than setting formatted text.
HomeDicator/core/config/common/globals.yaml Adds wifi_connected global used by the WiFi icon lambda.
HomeDicator/core/config/common/fonts.yaml Adds water-percent and weather-dust glyphs to the icon font.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment on lines 5 to 7
then:
- lvgl.label.update:
id: lvgl_value_label_${hass_climate_id}
text: !lambda |-
char buffer[10];
snprintf(buffer, sizeof(buffer), "%.0f", x);
return buffer;
- lvgl.widget.refresh: lvgl_value_label_${hass_climate_id}
- homeassistant.action:
Comment on lines +7 to +8
# Host build has no WiFi hardware; stub the sensor the shared WiFi icon
# lambda reads so it compiles and shows a signal in the preview.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants