[lvgl] Migrate to 9.6.0 (#20257)

Co-authored-by: Claude <noreply@anthropic.com>
This commit is contained in:
Clyde Stubbs
2026-10-12 07:36:32 +11:00
committed by GitHub
co-authored by Claude
parent 153c51e39f
commit bea0ef264a
28 changed files with 413 additions and 101 deletions
@@ -0,0 +1,41 @@
esphome:
name: test-lv-conf-check-second
esp32:
board: lolin_c3_mini
spi:
mosi_pin:
number: GPIO2
ignore_strapping_warning: true
clk_pin: GPIO1
display:
- platform: mipi_spi
id: display_a
data_rate: 20MHz
model: st7735
cs_pin:
number: GPIO8
ignore_strapping_warning: true
dc_pin:
number: GPIO3
- platform: mipi_spi
id: display_b
data_rate: 20MHz
model: st7735
cs_pin: GPIO4
dc_pin: GPIO5
lvgl:
- id: lvgl_a
displays: display_a
widgets:
- label:
text: Hello
- id: lvgl_b
displays: display_b
check_args: true
widgets:
- label:
text: Hello
@@ -0,0 +1,27 @@
esphome:
name: test-lv-conf-check-warn
esp32:
board: lolin_c3_mini
spi:
mosi_pin:
number: GPIO2
ignore_strapping_warning: true
clk_pin: GPIO1
display:
- platform: mipi_spi
data_rate: 20MHz
model: st7735
cs_pin:
number: GPIO8
ignore_strapping_warning: true
dc_pin:
number: GPIO3
lvgl:
check_args: true
widgets:
- label:
text: Hello
@@ -0,0 +1,26 @@
esphome:
name: test-lv-conf-defaults
esp32:
board: lolin_c3_mini
spi:
mosi_pin:
number: GPIO2
ignore_strapping_warning: true
clk_pin: GPIO1
display:
- platform: mipi_spi
data_rate: 20MHz
model: st7735
cs_pin:
number: GPIO8
ignore_strapping_warning: true
dc_pin:
number: GPIO3
lvgl:
widgets:
- label:
text: Hello
@@ -0,0 +1,29 @@
esphome:
name: test-lv-conf-options
esp32:
board: lolin_c3_mini
spi:
mosi_pin:
number: GPIO2
ignore_strapping_warning: true
clk_pin: GPIO1
display:
- platform: mipi_spi
data_rate: 20MHz
model: st7735
byte_order: little_endian
cs_pin:
number: GPIO8
ignore_strapping_warning: true
dc_pin:
number: GPIO3
lvgl:
check_args: true
log_level: DEBUG
widgets:
- label:
text: Hello
+1 -4
View File
@@ -287,10 +287,7 @@ def test_add_text_with_index_moves_before_firing_on_add(main_cpp: str) -> None:
def test_add_button_with_checkable_flag(main_cpp: str) -> None:
assert "lv_obj_t *dyn_button_VAR_ = lv_button_create(test_list);" in main_cpp
assert (
"lv_obj_add_flag(dyn_button_VAR_, (lv_obj_flag_t)(LV_OBJ_FLAG_CHECKABLE));"
in main_cpp
)
assert "lv_obj_set_checkable(dyn_button_VAR_, true);" in main_cpp
assert (
'lv_label_set_text(lv_obj_get_child(dyn_button_VAR_, 0), "Entry");' in main_cpp
)
@@ -0,0 +1,80 @@
"""Tests for the LVGL configuration defines written to lv_conf.h."""
from __future__ import annotations
from collections.abc import Callable
from pathlib import Path
import pytest
from esphome.components.lvgl import defines as df
from esphome.components.lvgl.schemas import WIDGET_TYPES
# LVGL 9.6 stops the build with #error when an enabled option "selects" another
# option that is disabled. ESPHome sets every unused LV_USE_* to 0, so each widget
# must list these in get_uses().
LVGL_SELECTS = (
("SLIDER", "BAR"),
("BARCODE", "CANVAS"),
("QRCODE", "CANVAS"),
("CANVAS", "IMAGE"),
("DROPDOWN", "LABEL"),
("MSGBOX", "LABEL"),
("ROLLER", "LABEL"),
("TEXTAREA", "LABEL"),
)
def test_default_lv_conf_defines(
generate_main: Callable[[str | Path], str],
component_config_path: Callable[[str], Path],
) -> None:
generate_main(component_config_path("lv_conf_defaults.yaml"))
defines = df.get_defines()
assert defines["LV_COLOR_FORMAT_DEFAULT"] == "LV_COLOR_FORMAT_RGB565_SWAPPED"
assert defines["LV_DRAW_SW_SUPPORT_RGB565_SWAPPED"] == "1"
assert defines["LV_OBJ_STYLE_CACHE"] == "1"
assert defines["LV_USE_CHECK_ARG"] == "0"
assert "LV_CHECK_ARG_LOG_MODE" not in defines
# Both are deprecated in LVGL 9.6 and produce build warnings
assert "LV_COLOR_DEPTH" not in defines
assert "LV_COLOR_16_SWAP" not in defines
@pytest.mark.parametrize(
("yaml_file", "color_format", "log_mode"),
[
("lv_conf_options.yaml", "RGB565", "VERBOSE"),
("lv_conf_check_warn.yaml", "RGB565_SWAPPED", "MINIMAL"),
# Only the second LVGL instance sets check_args
("lv_conf_check_second.yaml", "RGB565_SWAPPED", "MINIMAL"),
],
)
def test_lv_conf_options(
generate_main: Callable[[str | Path], str],
component_config_path: Callable[[str], Path],
yaml_file: str,
color_format: str,
log_mode: str,
) -> None:
generate_main(component_config_path(yaml_file))
defines = df.get_defines()
assert defines["LV_COLOR_FORMAT_DEFAULT"] == f"LV_COLOR_FORMAT_{color_format}"
assert defines["LV_USE_CHECK_ARG"] == "1"
assert defines["LV_CHECK_ARG_LOG_MODE"] == f"LV_CHECK_ARG_LOG_MODE_{log_mode}"
def test_check_arg_log_modes_cover_all_log_levels() -> None:
assert df.LV_CHECK_ARG_LOG_MODES.keys() == df.LV_LOG_LEVELS.keys()
@pytest.mark.parametrize("widget_name", sorted(WIDGET_TYPES))
def test_widget_uses_satisfy_lvgl_selects(widget_name: str) -> None:
widget_type = WIDGET_TYPES[widget_name]
df.add_lv_use(widget_type.name, *widget_type.get_uses())
enabled = {use.upper() for use in df.get_lv_uses()}
for option, required in LVGL_SELECTS:
if option in enabled:
assert required in enabled, (
f"'{widget_name}' enables LV_USE_{option}, which needs LV_USE_{required}"
)
@@ -10,11 +10,15 @@ from esphome.config_validation import Invalid
def _config(
displays: list[str], theme: dict | None = None, debug_outline: bool = False
displays: list[str],
theme: dict | None = None,
debug_outline: bool = False,
check_args: bool = False,
) -> dict:
config = {
df.CONF_DISPLAYS: displays,
"log_level": "WARN",
df.CONF_CHECK_ARGS: check_args,
"color_depth": 16,
"byte_order": "big_endian",
df.CONF_TRANSPARENCY_KEY: 0x000400,
@@ -73,3 +77,8 @@ class TestDebugOutlineOnMultipleInstances:
_config(["disp_b"], debug_outline=True),
]
multi_conf_validate(configs)
def test_check_args_may_differ_between_instances() -> None:
configs = [_config(["disp_a"], check_args=True), _config(["disp_b"])]
multi_conf_validate(configs)