[lvgl] Add start_value to bar; make values templatable and updateable (#9056)

This commit is contained in:
Clyde Stubbs 2025-06-23 12:23:41 +10:00 committed by GitHub
parent 2a45467bf6
commit 78ec9856fb
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
3 changed files with 49 additions and 21 deletions

View File

@ -454,9 +454,13 @@ def container_validator(schema, widget_type: WidgetType):
""" """
def validator(value): def validator(value):
result = schema
if w_sch := widget_type.schema: if w_sch := widget_type.schema:
result = result.extend(w_sch) if isinstance(w_sch, dict):
w_sch = cv.Schema(w_sch)
# order is important here to preserve extras
result = w_sch.extend(schema)
else:
result = schema
ltype = df.TYPE_NONE ltype = df.TYPE_NONE
if value and (layout := value.get(df.CONF_LAYOUT)): if value and (layout := value.get(df.CONF_LAYOUT)):
if not isinstance(layout, dict): if not isinstance(layout, dict):

View File

@ -1,8 +1,15 @@
import esphome.config_validation as cv import esphome.config_validation as cv
from esphome.const import CONF_MAX_VALUE, CONF_MIN_VALUE, CONF_MODE, CONF_VALUE from esphome.const import CONF_MAX_VALUE, CONF_MIN_VALUE, CONF_MODE, CONF_VALUE
from ..defines import BAR_MODES, CONF_ANIMATED, CONF_INDICATOR, CONF_MAIN, literal from ..defines import (
from ..lv_validation import animated, get_start_value, lv_float BAR_MODES,
CONF_ANIMATED,
CONF_INDICATOR,
CONF_MAIN,
CONF_START_VALUE,
literal,
)
from ..lv_validation import animated, lv_int
from ..lvcode import lv from ..lvcode import lv
from ..types import LvNumber, NumberType from ..types import LvNumber, NumberType
from . import Widget from . import Widget
@ -10,22 +17,30 @@ from . import Widget
# Note this file cannot be called "bar.py" because that name is disallowed. # Note this file cannot be called "bar.py" because that name is disallowed.
CONF_BAR = "bar" CONF_BAR = "bar"
BAR_MODIFY_SCHEMA = cv.Schema(
{
cv.Optional(CONF_VALUE): lv_float, def validate_bar(config):
cv.Optional(CONF_ANIMATED, default=True): animated, if config.get(CONF_MODE) != "LV_BAR_MODE_RANGE" and CONF_START_VALUE in config:
} raise cv.Invalid(
) f"{CONF_START_VALUE} is only allowed when {CONF_MODE} is set to 'RANGE'"
)
if (CONF_MIN_VALUE in config) != (CONF_MAX_VALUE in config):
raise cv.Invalid(
f"If either {CONF_MIN_VALUE} or {CONF_MAX_VALUE} is set, both must be set"
)
return config
BAR_SCHEMA = cv.Schema( BAR_SCHEMA = cv.Schema(
{ {
cv.Optional(CONF_VALUE): lv_float, cv.Optional(CONF_VALUE): lv_int,
cv.Optional(CONF_MIN_VALUE, default=0): cv.int_, cv.Optional(CONF_START_VALUE): lv_int,
cv.Optional(CONF_MAX_VALUE, default=100): cv.int_, cv.Optional(CONF_MIN_VALUE): lv_int,
cv.Optional(CONF_MODE, default="NORMAL"): BAR_MODES.one_of, cv.Optional(CONF_MAX_VALUE): lv_int,
cv.Optional(CONF_MODE): BAR_MODES.one_of,
cv.Optional(CONF_ANIMATED, default=True): animated, cv.Optional(CONF_ANIMATED, default=True): animated,
} }
) ).add_extra(validate_bar)
class BarType(NumberType): class BarType(NumberType):
@ -35,17 +50,23 @@ class BarType(NumberType):
LvNumber("lv_bar_t"), LvNumber("lv_bar_t"),
parts=(CONF_MAIN, CONF_INDICATOR), parts=(CONF_MAIN, CONF_INDICATOR),
schema=BAR_SCHEMA, schema=BAR_SCHEMA,
modify_schema=BAR_MODIFY_SCHEMA,
) )
async def to_code(self, w: Widget, config): async def to_code(self, w: Widget, config):
var = w.obj var = w.obj
if mode := config.get(CONF_MODE):
lv.bar_set_mode(var, literal(mode))
is_animated = literal(config[CONF_ANIMATED])
if CONF_MIN_VALUE in config: if CONF_MIN_VALUE in config:
lv.bar_set_range(var, config[CONF_MIN_VALUE], config[CONF_MAX_VALUE]) lv.bar_set_range(
lv.bar_set_mode(var, literal(config[CONF_MODE])) var,
value = await get_start_value(config) await lv_int.process(config[CONF_MIN_VALUE]),
if value is not None: await lv_int.process(config[CONF_MAX_VALUE]),
lv.bar_set_value(var, value, literal(config[CONF_ANIMATED])) )
if value := await lv_int.process(config.get(CONF_VALUE)):
lv.bar_set_value(var, value, is_animated)
if start_value := await lv_int.process(config.get(CONF_START_VALUE)):
lv.bar_set_start_value(var, start_value, is_animated)
@property @property
def animated(self): def animated(self):

View File

@ -728,12 +728,15 @@ lvgl:
value: 30 value: 30
max_value: 100 max_value: 100
min_value: 10 min_value: 10
start_value: 20
mode: range mode: range
on_click: on_click:
then: then:
- lvgl.bar.update: - lvgl.bar.update:
id: bar_id id: bar_id
value: !lambda return (int)((float)rand() / RAND_MAX * 100); value: !lambda return (int)((float)rand() / RAND_MAX * 100);
start_value: !lambda return (int)((float)rand() / RAND_MAX * 100);
mode: symmetrical
- logger.log: - logger.log:
format: "bar value %f" format: "bar value %f"
args: [x] args: [x]