mirror of
https://github.com/esphome/esphome.git
synced 2024-12-11 14:49:20 +01:00
[lvgl] Make image update via lambda work (#7886)
This commit is contained in:
parent
d305870284
commit
c9b0490305
@ -8,7 +8,7 @@ import logging
|
|||||||
|
|
||||||
from esphome import codegen as cg, config_validation as cv
|
from esphome import codegen as cg, config_validation as cv
|
||||||
from esphome.const import CONF_ITEMS
|
from esphome.const import CONF_ITEMS
|
||||||
from esphome.core import Lambda
|
from esphome.core import ID, Lambda
|
||||||
from esphome.cpp_generator import LambdaExpression, MockObj
|
from esphome.cpp_generator import LambdaExpression, MockObj
|
||||||
from esphome.cpp_types import uint32
|
from esphome.cpp_types import uint32
|
||||||
from esphome.schema_extractors import SCHEMA_EXTRACT, schema_extractor
|
from esphome.schema_extractors import SCHEMA_EXTRACT, schema_extractor
|
||||||
@ -72,6 +72,12 @@ class LValidator:
|
|||||||
)
|
)
|
||||||
if self.retmapper is not None:
|
if self.retmapper is not None:
|
||||||
return self.retmapper(value)
|
return self.retmapper(value)
|
||||||
|
if isinstance(value, ID):
|
||||||
|
return await cg.get_variable(value)
|
||||||
|
if isinstance(value, list):
|
||||||
|
value = [
|
||||||
|
await cg.get_variable(x) if isinstance(x, ID) else x for x in value
|
||||||
|
]
|
||||||
return cg.safe_exp(value)
|
return cg.safe_exp(value)
|
||||||
|
|
||||||
|
|
||||||
|
@ -1,6 +1,7 @@
|
|||||||
from typing import Union
|
from typing import Union
|
||||||
|
|
||||||
import esphome.codegen as cg
|
import esphome.codegen as cg
|
||||||
|
from esphome.components import image
|
||||||
from esphome.components.color import CONF_HEX, ColorStruct, from_rgbw
|
from esphome.components.color import CONF_HEX, ColorStruct, from_rgbw
|
||||||
from esphome.components.font import Font
|
from esphome.components.font import Font
|
||||||
from esphome.components.image import Image_
|
from esphome.components.image import Image_
|
||||||
@ -31,7 +32,7 @@ from .defines import (
|
|||||||
literal,
|
literal,
|
||||||
)
|
)
|
||||||
from .helpers import add_lv_use, esphome_fonts_used, lv_fonts_used, requires_component
|
from .helpers import add_lv_use, esphome_fonts_used, lv_fonts_used, requires_component
|
||||||
from .types import lv_font_t, lv_gradient_t, lv_img_t
|
from .types import lv_font_t, lv_gradient_t
|
||||||
|
|
||||||
opacity_consts = LvConstant("LV_OPA_", "TRANSP", "COVER")
|
opacity_consts = LvConstant("LV_OPA_", "TRANSP", "COVER")
|
||||||
|
|
||||||
@ -332,8 +333,12 @@ def image_validator(value):
|
|||||||
|
|
||||||
lv_image = LValidator(
|
lv_image = LValidator(
|
||||||
image_validator,
|
image_validator,
|
||||||
lv_img_t,
|
image.Image_.operator("ptr"),
|
||||||
retmapper=lambda x: MockObj(x, "->").get_lv_img_dsc(),
|
requires="image",
|
||||||
|
)
|
||||||
|
lv_image_list = LValidator(
|
||||||
|
cv.ensure_list(image_validator),
|
||||||
|
cg.std_vector.template(image.Image_.operator("ptr")),
|
||||||
requires="image",
|
requires="image",
|
||||||
)
|
)
|
||||||
lv_bool = LValidator(cv.boolean, cg.bool_, retmapper=literal)
|
lv_bool = LValidator(cv.boolean, cg.bool_, retmapper=literal)
|
||||||
|
@ -57,6 +57,22 @@ inline void lv_img_set_src(lv_obj_t *obj, esphome::image::Image *image) {
|
|||||||
lv_img_set_src(obj, image->get_lv_img_dsc());
|
lv_img_set_src(obj, image->get_lv_img_dsc());
|
||||||
}
|
}
|
||||||
#endif // USE_LVGL_IMAGE
|
#endif // USE_LVGL_IMAGE
|
||||||
|
#ifdef USE_LVGL_ANIMIMG
|
||||||
|
inline void lv_animimg_set_src(lv_obj_t *img, std::vector<image::Image *> images) {
|
||||||
|
auto *dsc = static_cast<std::vector<lv_img_dsc_t *> *>(lv_obj_get_user_data(img));
|
||||||
|
if (dsc == nullptr) {
|
||||||
|
// object will be lazily allocated but never freed.
|
||||||
|
dsc = new std::vector<lv_img_dsc_t *>(images.size()); // NOLINT
|
||||||
|
lv_obj_set_user_data(img, dsc);
|
||||||
|
}
|
||||||
|
dsc->clear();
|
||||||
|
for (auto &image : images) {
|
||||||
|
dsc->push_back(image->get_lv_img_dsc());
|
||||||
|
}
|
||||||
|
lv_animimg_set_src(img, (const void **) dsc->data(), dsc->size());
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif // USE_LVGL_ANIMIMG
|
||||||
|
|
||||||
// Parent class for things that wrap an LVGL object
|
// Parent class for things that wrap an LVGL object
|
||||||
class LvCompound {
|
class LvCompound {
|
||||||
|
@ -1,20 +1,18 @@
|
|||||||
from esphome import automation
|
from esphome import automation
|
||||||
import esphome.codegen as cg
|
|
||||||
import esphome.config_validation as cv
|
import esphome.config_validation as cv
|
||||||
from esphome.const import CONF_DURATION, CONF_ID
|
from esphome.const import CONF_DURATION, CONF_ID
|
||||||
|
|
||||||
from ..automation import action_to_code
|
from ..automation import action_to_code
|
||||||
from ..defines import CONF_AUTO_START, CONF_MAIN, CONF_REPEAT_COUNT, CONF_SRC
|
from ..defines import CONF_AUTO_START, CONF_MAIN, CONF_REPEAT_COUNT, CONF_SRC
|
||||||
from ..helpers import lvgl_components_required
|
from ..helpers import lvgl_components_required
|
||||||
from ..lv_validation import lv_image, lv_milliseconds
|
from ..lv_validation import lv_image_list, lv_milliseconds
|
||||||
from ..lvcode import lv
|
from ..lvcode import lv
|
||||||
from ..types import LvType, ObjUpdateAction, void_ptr
|
from ..types import LvType, ObjUpdateAction
|
||||||
from . import Widget, WidgetType, get_widgets
|
from . import Widget, WidgetType, get_widgets
|
||||||
from .img import CONF_IMAGE
|
from .img import CONF_IMAGE
|
||||||
from .label import CONF_LABEL
|
from .label import CONF_LABEL
|
||||||
|
|
||||||
CONF_ANIMIMG = "animimg"
|
CONF_ANIMIMG = "animimg"
|
||||||
CONF_SRC_LIST_ID = "src_list_id"
|
|
||||||
|
|
||||||
|
|
||||||
def lv_repeat_count(value):
|
def lv_repeat_count(value):
|
||||||
@ -32,14 +30,14 @@ ANIMIMG_BASE_SCHEMA = cv.Schema(
|
|||||||
ANIMIMG_SCHEMA = ANIMIMG_BASE_SCHEMA.extend(
|
ANIMIMG_SCHEMA = ANIMIMG_BASE_SCHEMA.extend(
|
||||||
{
|
{
|
||||||
cv.Required(CONF_DURATION): lv_milliseconds,
|
cv.Required(CONF_DURATION): lv_milliseconds,
|
||||||
cv.Required(CONF_SRC): cv.ensure_list(lv_image),
|
cv.Required(CONF_SRC): lv_image_list,
|
||||||
cv.GenerateID(CONF_SRC_LIST_ID): cv.declare_id(void_ptr),
|
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
|
|
||||||
ANIMIMG_MODIFY_SCHEMA = ANIMIMG_BASE_SCHEMA.extend(
|
ANIMIMG_MODIFY_SCHEMA = ANIMIMG_BASE_SCHEMA.extend(
|
||||||
{
|
{
|
||||||
cv.Optional(CONF_DURATION): lv_milliseconds,
|
cv.Optional(CONF_DURATION): lv_milliseconds,
|
||||||
|
cv.Optional(CONF_SRC): lv_image_list,
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
|
|
||||||
@ -59,17 +57,14 @@ class AnimimgType(WidgetType):
|
|||||||
async def to_code(self, w: Widget, config):
|
async def to_code(self, w: Widget, config):
|
||||||
lvgl_components_required.add(CONF_IMAGE)
|
lvgl_components_required.add(CONF_IMAGE)
|
||||||
lvgl_components_required.add(CONF_ANIMIMG)
|
lvgl_components_required.add(CONF_ANIMIMG)
|
||||||
if CONF_SRC in config:
|
if srcs := config.get(CONF_SRC):
|
||||||
srcs = [
|
srcs = await lv_image_list.process(srcs)
|
||||||
await lv_image.process(await cg.get_variable(x))
|
lv.animimg_set_src(w.obj, srcs)
|
||||||
for x in config[CONF_SRC]
|
if repeat_count := config.get(CONF_REPEAT_COUNT):
|
||||||
]
|
lv.animimg_set_repeat_count(w.obj, repeat_count)
|
||||||
src_id = cg.static_const_array(config[CONF_SRC_LIST_ID], srcs)
|
if duration := config.get(CONF_DURATION):
|
||||||
count = len(config[CONF_SRC])
|
lv.animimg_set_duration(w.obj, duration)
|
||||||
lv.animimg_set_src(w.obj, src_id, count)
|
if config[CONF_AUTO_START]:
|
||||||
lv.animimg_set_repeat_count(w.obj, config[CONF_REPEAT_COUNT])
|
|
||||||
lv.animimg_set_duration(w.obj, config[CONF_DURATION])
|
|
||||||
if config.get(CONF_AUTO_START):
|
|
||||||
lv.animimg_start(w.obj)
|
lv.animimg_start(w.obj)
|
||||||
|
|
||||||
def get_uses(self):
|
def get_uses(self):
|
||||||
|
@ -1,4 +1,3 @@
|
|||||||
import esphome.codegen as cg
|
|
||||||
import esphome.config_validation as cv
|
import esphome.config_validation as cv
|
||||||
from esphome.const import CONF_ANGLE, CONF_MODE
|
from esphome.const import CONF_ANGLE, CONF_MODE
|
||||||
|
|
||||||
@ -65,7 +64,6 @@ class ImgType(WidgetType):
|
|||||||
|
|
||||||
async def to_code(self, w: Widget, config):
|
async def to_code(self, w: Widget, config):
|
||||||
if src := config.get(CONF_SRC):
|
if src := config.get(CONF_SRC):
|
||||||
src = await cg.get_variable(src)
|
|
||||||
lv.img_set_src(w.obj, await lv_image.process(src))
|
lv.img_set_src(w.obj, await lv_image.process(src))
|
||||||
if (cf_angle := config.get(CONF_ANGLE)) is not None:
|
if (cf_angle := config.get(CONF_ANGLE)) is not None:
|
||||||
pivot_x = config[CONF_PIVOT_X]
|
pivot_x = config[CONF_PIVOT_X]
|
||||||
|
@ -171,9 +171,13 @@ lvgl:
|
|||||||
duration: 1s
|
duration: 1s
|
||||||
auto_start: true
|
auto_start: true
|
||||||
on_all_events:
|
on_all_events:
|
||||||
logger.log:
|
- logger.log:
|
||||||
format: "Event %s"
|
format: "Event %s"
|
||||||
args: ['lv_event_code_name_for(event->code).c_str()']
|
args: ['lv_event_code_name_for(event->code).c_str()']
|
||||||
|
- lvgl.animimg.update:
|
||||||
|
id: anim_img
|
||||||
|
src: !lambda "return {dog_image, cat_image};"
|
||||||
|
duration: 2s
|
||||||
- label:
|
- label:
|
||||||
id: hello_label
|
id: hello_label
|
||||||
text: Hello world
|
text: Hello world
|
||||||
@ -635,7 +639,7 @@ lvgl:
|
|||||||
- image:
|
- image:
|
||||||
grid_cell_row_pos: 0
|
grid_cell_row_pos: 0
|
||||||
grid_cell_column_pos: 0
|
grid_cell_column_pos: 0
|
||||||
src: dog_image
|
src: !lambda return dog_image;
|
||||||
on_click:
|
on_click:
|
||||||
then:
|
then:
|
||||||
- lvgl.tabview.select:
|
- lvgl.tabview.select:
|
||||||
|
@ -55,5 +55,5 @@ lvgl:
|
|||||||
|
|
||||||
packages:
|
packages:
|
||||||
lvgl: !include lvgl-package.yaml
|
lvgl: !include lvgl-package.yaml
|
||||||
|
xvgl: !include common.yaml
|
||||||
|
|
||||||
<<: !include common.yaml
|
|
||||||
|
Loading…
Reference in New Issue
Block a user