mirror of
				https://github.com/esphome/esphome.git
				synced 2025-10-30 22:53:59 +00: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