mirror of
https://github.com/esphome/esphome.git
synced 2025-09-02 19:32:19 +01:00
[lvgl] Various validation fixes (#10141)
This commit is contained in:
@@ -287,10 +287,14 @@ def angle(value):
|
|||||||
:param value: The input in the range 0..360
|
:param value: The input in the range 0..360
|
||||||
:return: An angle in 1/10 degree units.
|
:return: An angle in 1/10 degree units.
|
||||||
"""
|
"""
|
||||||
return int(cv.float_range(0.0, 360.0)(cv.angle(value)) * 10)
|
return cv.float_range(0.0, 360.0)(cv.angle(value))
|
||||||
|
|
||||||
|
|
||||||
lv_angle = LValidator(angle, uint32)
|
# Validator for angles in LVGL expressed in 1/10 degree units.
|
||||||
|
lv_angle = LValidator(angle, uint32, retmapper=lambda x: int(x * 10))
|
||||||
|
|
||||||
|
# Validator for angles in LVGL expressed in whole degrees
|
||||||
|
lv_angle_degrees = LValidator(angle, uint32, retmapper=int)
|
||||||
|
|
||||||
|
|
||||||
@schema_extractor("one_of")
|
@schema_extractor("one_of")
|
||||||
|
@@ -161,7 +161,7 @@ class WidgetType:
|
|||||||
"""
|
"""
|
||||||
return []
|
return []
|
||||||
|
|
||||||
def obj_creator(self, parent: MockObjClass, config: dict):
|
async def obj_creator(self, parent: MockObjClass, config: dict):
|
||||||
"""
|
"""
|
||||||
Create an instance of the widget type
|
Create an instance of the widget type
|
||||||
:param parent: The parent to which it should be attached
|
:param parent: The parent to which it should be attached
|
||||||
|
@@ -439,7 +439,7 @@ async def widget_to_code(w_cnfig, w_type: WidgetType, parent):
|
|||||||
:return:
|
:return:
|
||||||
"""
|
"""
|
||||||
spec: WidgetType = WIDGET_TYPES[w_type]
|
spec: WidgetType = WIDGET_TYPES[w_type]
|
||||||
creator = spec.obj_creator(parent, w_cnfig)
|
creator = await spec.obj_creator(parent, w_cnfig)
|
||||||
add_lv_use(spec.name)
|
add_lv_use(spec.name)
|
||||||
add_lv_use(*spec.get_uses())
|
add_lv_use(*spec.get_uses())
|
||||||
wid = w_cnfig[CONF_ID]
|
wid = w_cnfig[CONF_ID]
|
||||||
|
@@ -20,7 +20,7 @@ from ..defines import (
|
|||||||
CONF_START_ANGLE,
|
CONF_START_ANGLE,
|
||||||
literal,
|
literal,
|
||||||
)
|
)
|
||||||
from ..lv_validation import angle, get_start_value, lv_float
|
from ..lv_validation import get_start_value, lv_angle_degrees, lv_float, lv_int
|
||||||
from ..lvcode import lv, lv_expr, lv_obj
|
from ..lvcode import lv, lv_expr, lv_obj
|
||||||
from ..types import LvNumber, NumberType
|
from ..types import LvNumber, NumberType
|
||||||
from . import Widget
|
from . import Widget
|
||||||
@@ -29,11 +29,11 @@ CONF_ARC = "arc"
|
|||||||
ARC_SCHEMA = cv.Schema(
|
ARC_SCHEMA = cv.Schema(
|
||||||
{
|
{
|
||||||
cv.Optional(CONF_VALUE): lv_float,
|
cv.Optional(CONF_VALUE): lv_float,
|
||||||
cv.Optional(CONF_MIN_VALUE, default=0): cv.int_,
|
cv.Optional(CONF_MIN_VALUE, default=0): lv_int,
|
||||||
cv.Optional(CONF_MAX_VALUE, default=100): cv.int_,
|
cv.Optional(CONF_MAX_VALUE, default=100): lv_int,
|
||||||
cv.Optional(CONF_START_ANGLE, default=135): angle,
|
cv.Optional(CONF_START_ANGLE, default=135): lv_angle_degrees,
|
||||||
cv.Optional(CONF_END_ANGLE, default=45): angle,
|
cv.Optional(CONF_END_ANGLE, default=45): lv_angle_degrees,
|
||||||
cv.Optional(CONF_ROTATION, default=0.0): angle,
|
cv.Optional(CONF_ROTATION, default=0.0): lv_angle_degrees,
|
||||||
cv.Optional(CONF_ADJUSTABLE, default=False): bool,
|
cv.Optional(CONF_ADJUSTABLE, default=False): bool,
|
||||||
cv.Optional(CONF_MODE, default="NORMAL"): ARC_MODES.one_of,
|
cv.Optional(CONF_MODE, default="NORMAL"): ARC_MODES.one_of,
|
||||||
cv.Optional(CONF_CHANGE_RATE, default=720): cv.uint16_t,
|
cv.Optional(CONF_CHANGE_RATE, default=720): cv.uint16_t,
|
||||||
@@ -59,11 +59,14 @@ class ArcType(NumberType):
|
|||||||
|
|
||||||
async def to_code(self, w: Widget, config):
|
async def to_code(self, w: Widget, config):
|
||||||
if CONF_MIN_VALUE in config:
|
if CONF_MIN_VALUE in config:
|
||||||
lv.arc_set_range(w.obj, config[CONF_MIN_VALUE], config[CONF_MAX_VALUE])
|
max_value = await lv_int.process(config[CONF_MAX_VALUE])
|
||||||
lv.arc_set_bg_angles(
|
min_value = await lv_int.process(config[CONF_MIN_VALUE])
|
||||||
w.obj, config[CONF_START_ANGLE] // 10, config[CONF_END_ANGLE] // 10
|
lv.arc_set_range(w.obj, min_value, max_value)
|
||||||
)
|
start = await lv_angle_degrees.process(config[CONF_START_ANGLE])
|
||||||
lv.arc_set_rotation(w.obj, config[CONF_ROTATION] // 10)
|
end = await lv_angle_degrees.process(config[CONF_END_ANGLE])
|
||||||
|
rotation = await lv_angle_degrees.process(config[CONF_ROTATION])
|
||||||
|
lv.arc_set_bg_angles(w.obj, start, end)
|
||||||
|
lv.arc_set_rotation(w.obj, rotation)
|
||||||
lv.arc_set_mode(w.obj, literal(config[CONF_MODE]))
|
lv.arc_set_mode(w.obj, literal(config[CONF_MODE]))
|
||||||
lv.arc_set_change_rate(w.obj, config[CONF_CHANGE_RATE])
|
lv.arc_set_change_rate(w.obj, config[CONF_CHANGE_RATE])
|
||||||
|
|
||||||
|
@@ -4,7 +4,7 @@ from esphome.const import CONF_SIZE, CONF_TEXT
|
|||||||
from esphome.cpp_generator import MockObjClass
|
from esphome.cpp_generator import MockObjClass
|
||||||
|
|
||||||
from ..defines import CONF_MAIN
|
from ..defines import CONF_MAIN
|
||||||
from ..lv_validation import color, color_retmapper, lv_text
|
from ..lv_validation import lv_color, lv_text
|
||||||
from ..lvcode import LocalVariable, lv, lv_expr
|
from ..lvcode import LocalVariable, lv, lv_expr
|
||||||
from ..schemas import TEXT_SCHEMA
|
from ..schemas import TEXT_SCHEMA
|
||||||
from ..types import WidgetType, lv_obj_t
|
from ..types import WidgetType, lv_obj_t
|
||||||
@@ -16,8 +16,8 @@ CONF_LIGHT_COLOR = "light_color"
|
|||||||
|
|
||||||
QRCODE_SCHEMA = TEXT_SCHEMA.extend(
|
QRCODE_SCHEMA = TEXT_SCHEMA.extend(
|
||||||
{
|
{
|
||||||
cv.Optional(CONF_DARK_COLOR, default="black"): color,
|
cv.Optional(CONF_DARK_COLOR, default="black"): lv_color,
|
||||||
cv.Optional(CONF_LIGHT_COLOR, default="white"): color,
|
cv.Optional(CONF_LIGHT_COLOR, default="white"): lv_color,
|
||||||
cv.Required(CONF_SIZE): cv.int_,
|
cv.Required(CONF_SIZE): cv.int_,
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
@@ -34,11 +34,11 @@ class QrCodeType(WidgetType):
|
|||||||
)
|
)
|
||||||
|
|
||||||
def get_uses(self):
|
def get_uses(self):
|
||||||
return ("canvas", "img", "label")
|
return "canvas", "img", "label"
|
||||||
|
|
||||||
def obj_creator(self, parent: MockObjClass, config: dict):
|
async def obj_creator(self, parent: MockObjClass, config: dict):
|
||||||
dark_color = color_retmapper(config[CONF_DARK_COLOR])
|
dark_color = await lv_color.process(config[CONF_DARK_COLOR])
|
||||||
light_color = color_retmapper(config[CONF_LIGHT_COLOR])
|
light_color = await lv_color.process(config[CONF_LIGHT_COLOR])
|
||||||
size = config[CONF_SIZE]
|
size = config[CONF_SIZE]
|
||||||
return lv_expr.call("qrcode_create", parent, size, dark_color, light_color)
|
return lv_expr.call("qrcode_create", parent, size, dark_color, light_color)
|
||||||
|
|
||||||
|
@@ -2,7 +2,7 @@ import esphome.config_validation as cv
|
|||||||
from esphome.cpp_generator import MockObjClass
|
from esphome.cpp_generator import MockObjClass
|
||||||
|
|
||||||
from ..defines import CONF_ARC_LENGTH, CONF_INDICATOR, CONF_MAIN, CONF_SPIN_TIME
|
from ..defines import CONF_ARC_LENGTH, CONF_INDICATOR, CONF_MAIN, CONF_SPIN_TIME
|
||||||
from ..lv_validation import angle
|
from ..lv_validation import lv_angle_degrees, lv_milliseconds
|
||||||
from ..lvcode import lv_expr
|
from ..lvcode import lv_expr
|
||||||
from ..types import LvType
|
from ..types import LvType
|
||||||
from . import Widget, WidgetType
|
from . import Widget, WidgetType
|
||||||
@@ -12,8 +12,8 @@ CONF_SPINNER = "spinner"
|
|||||||
|
|
||||||
SPINNER_SCHEMA = cv.Schema(
|
SPINNER_SCHEMA = cv.Schema(
|
||||||
{
|
{
|
||||||
cv.Required(CONF_ARC_LENGTH): angle,
|
cv.Required(CONF_ARC_LENGTH): lv_angle_degrees,
|
||||||
cv.Required(CONF_SPIN_TIME): cv.positive_time_period_milliseconds,
|
cv.Required(CONF_SPIN_TIME): lv_milliseconds,
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
|
|
||||||
@@ -34,9 +34,9 @@ class SpinnerType(WidgetType):
|
|||||||
def get_uses(self):
|
def get_uses(self):
|
||||||
return (CONF_ARC,)
|
return (CONF_ARC,)
|
||||||
|
|
||||||
def obj_creator(self, parent: MockObjClass, config: dict):
|
async def obj_creator(self, parent: MockObjClass, config: dict):
|
||||||
spin_time = config[CONF_SPIN_TIME].total_milliseconds
|
spin_time = await lv_milliseconds.process(config[CONF_SPIN_TIME])
|
||||||
arc_length = config[CONF_ARC_LENGTH] // 10
|
arc_length = await lv_angle_degrees.process(config[CONF_ARC_LENGTH])
|
||||||
return lv_expr.call("spinner_create", parent, spin_time, arc_length)
|
return lv_expr.call("spinner_create", parent, spin_time, arc_length)
|
||||||
|
|
||||||
|
|
||||||
|
@@ -87,12 +87,12 @@ class TabviewType(WidgetType):
|
|||||||
) as content_obj:
|
) as content_obj:
|
||||||
await set_obj_properties(Widget(content_obj, obj_spec), content_style)
|
await set_obj_properties(Widget(content_obj, obj_spec), content_style)
|
||||||
|
|
||||||
def obj_creator(self, parent: MockObjClass, config: dict):
|
async def obj_creator(self, parent: MockObjClass, config: dict):
|
||||||
return lv_expr.call(
|
return lv_expr.call(
|
||||||
"tabview_create",
|
"tabview_create",
|
||||||
parent,
|
parent,
|
||||||
literal(config[CONF_POSITION]),
|
await DIRECTIONS.process(config[CONF_POSITION]),
|
||||||
literal(config[CONF_SIZE]),
|
await size.process(config[CONF_SIZE]),
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
|
@@ -723,6 +723,20 @@ lvgl:
|
|||||||
arc_color: 0xFFFF00
|
arc_color: 0xFFFF00
|
||||||
focused:
|
focused:
|
||||||
arc_color: 0x808080
|
arc_color: 0x808080
|
||||||
|
- arc:
|
||||||
|
align: center
|
||||||
|
id: lv_arc_1
|
||||||
|
value: !lambda return 75;
|
||||||
|
min_value: !lambda return 50;
|
||||||
|
max_value: !lambda return 60;
|
||||||
|
arc_color: 0xFF0000
|
||||||
|
indicator:
|
||||||
|
arc_width: !lambda return 20;
|
||||||
|
arc_color: 0xF000FF
|
||||||
|
pressed:
|
||||||
|
arc_color: 0xFFFF00
|
||||||
|
focused:
|
||||||
|
arc_color: 0x808080
|
||||||
- bar:
|
- bar:
|
||||||
id: bar_id
|
id: bar_id
|
||||||
align: top_mid
|
align: top_mid
|
||||||
|
Reference in New Issue
Block a user