[lvgl] Add refresh action to re-evaluate initial widget properties (#8675)

This commit is contained in:
Clyde Stubbs 2025-05-05 13:26:16 +10:00 committed by GitHub
parent c7523ace78
commit 0b032e5c19
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
3 changed files with 61 additions and 4 deletions

View File

@ -18,13 +18,13 @@ from esphome.const import (
CONF_TRIGGER_ID, CONF_TRIGGER_ID,
CONF_TYPE, CONF_TYPE,
) )
from esphome.core import CORE, ID from esphome.core import CORE, ID, Lambda
from esphome.cpp_generator import MockObj from esphome.cpp_generator import MockObj
from esphome.final_validate import full_config from esphome.final_validate import full_config
from esphome.helpers import write_file_if_changed from esphome.helpers import write_file_if_changed
from . import defines as df, helpers, lv_validation as lvalid from . import defines as df, helpers, lv_validation as lvalid
from .automation import disp_update, focused_widgets, update_to_code from .automation import disp_update, focused_widgets, refreshed_widgets, update_to_code
from .defines import add_define from .defines import add_define
from .encoders import ( from .encoders import (
ENCODERS_CONFIG, ENCODERS_CONFIG,
@ -240,6 +240,13 @@ def final_validation(configs):
"A non adjustable arc may not be focused", "A non adjustable arc may not be focused",
path, path,
) )
for w in refreshed_widgets:
path = global_config.get_path_for_id(w)
widget_conf = global_config.get_config_for_path(path[:-1])
if not any(isinstance(v, Lambda) for v in widget_conf.values()):
raise cv.Invalid(
f"Widget '{w}' does not have any templated properties to refresh",
)
async def to_code(configs): async def to_code(configs):

View File

@ -35,7 +35,13 @@ from .lvcode import (
lv_obj, lv_obj,
lvgl_comp, lvgl_comp,
) )
from .schemas import DISP_BG_SCHEMA, LIST_ACTION_SCHEMA, LVGL_SCHEMA, base_update_schema from .schemas import (
ALL_STYLES,
DISP_BG_SCHEMA,
LIST_ACTION_SCHEMA,
LVGL_SCHEMA,
base_update_schema,
)
from .types import ( from .types import (
LV_STATE, LV_STATE,
LvglAction, LvglAction,
@ -57,6 +63,7 @@ from .widgets import (
# Record widgets that are used in a focused action here # Record widgets that are used in a focused action here
focused_widgets = set() focused_widgets = set()
refreshed_widgets = set()
async def action_to_code( async def action_to_code(
@ -361,3 +368,45 @@ async def obj_update_to_code(config, action_id, template_arg, args):
return await action_to_code( return await action_to_code(
widgets, do_update, action_id, template_arg, args, config widgets, do_update, action_id, template_arg, args, config
) )
def validate_refresh_config(config):
for w in config:
refreshed_widgets.add(w[CONF_ID])
return config
@automation.register_action(
"lvgl.widget.refresh",
ObjUpdateAction,
cv.All(
cv.ensure_list(
cv.maybe_simple_value(
{
cv.Required(CONF_ID): cv.use_id(lv_obj_t),
},
key=CONF_ID,
)
),
validate_refresh_config,
),
)
async def obj_refresh_to_code(config, action_id, template_arg, args):
widget = await get_widgets(config)
async def do_refresh(widget: Widget):
# only update style properties that might have changed, i.e. are templated
config = {k: v for k, v in widget.config.items() if isinstance(v, Lambda)}
await set_obj_properties(widget, config)
# must pass all widget-specific options here, even if not templated, but only do so if at least one is
# templated. First filter out common style properties.
config = {k: v for k, v in widget.config.items() if k not in ALL_STYLES}
if any(isinstance(v, Lambda) for v in config.values()):
await widget.type.to_code(widget, config)
if (
widget.type.w_type.value_property is not None
and widget.type.w_type.value_property in config
):
lv.event_send(widget.obj, UPDATE_EVENT, nullptr)
return await action_to_code(widget, do_refresh, action_id, template_arg, args)

View File

@ -212,7 +212,7 @@ lvgl:
- animimg: - animimg:
height: 60 height: 60
id: anim_img id: anim_img
src: [cat_image, dog_image] src: !lambda "return {dog_image, cat_image};"
repeat_count: 10 repeat_count: 10
duration: 1s duration: 1s
auto_start: true auto_start: true
@ -224,6 +224,7 @@ lvgl:
id: anim_img id: anim_img
src: !lambda "return {dog_image, cat_image};" src: !lambda "return {dog_image, cat_image};"
duration: 2s duration: 2s
- lvgl.widget.refresh: anim_img
- label: - label:
on_boot: on_boot:
lvgl.label.update: lvgl.label.update: