mirror of
https://github.com/esphome/esphome.git
synced 2026-06-24 13:43:00 +00:00
[lvgl][mipi_spi][mipi_rgb][mipi_dsi][display] Metadata (#16702)
This commit is contained in:
@@ -4,77 +4,145 @@ from unittest.mock import patch
|
||||
|
||||
import pytest
|
||||
|
||||
from esphome.components.const import BYTE_ORDER_BIG, BYTE_ORDER_LITTLE
|
||||
from esphome.components.display import (
|
||||
DisplayMetaData,
|
||||
add_metadata,
|
||||
get_all_display_metadata,
|
||||
get_display_metadata,
|
||||
)
|
||||
from esphome.cpp_generator import MockObj
|
||||
from esphome.config import Config
|
||||
from esphome.core import ID
|
||||
from esphome.final_validate import full_config
|
||||
|
||||
|
||||
def test_add_metadata_with_string_id():
|
||||
"""Test adding metadata with a plain string ID."""
|
||||
def test_add_metadata_basic():
|
||||
"""Test adding metadata with an ID object."""
|
||||
with patch("esphome.components.display.CORE.data", {}):
|
||||
add_metadata("my_display", 320, 240, True)
|
||||
meta = get_display_metadata("my_display")
|
||||
add_metadata(ID("my_display"), 320, 240)
|
||||
meta = get_display_metadata(ID("my_display"))
|
||||
assert meta == DisplayMetaData(
|
||||
width=320, height=240, has_writer=True, has_hardware_rotation=False
|
||||
width=320,
|
||||
height=240,
|
||||
has_hardware_rotation=False,
|
||||
byte_order=BYTE_ORDER_BIG,
|
||||
)
|
||||
|
||||
|
||||
def test_add_metadata_with_mockobj_id():
|
||||
"""Test adding metadata with a MockObj ID (converted via str())."""
|
||||
def test_add_metadata_with_all_fields():
|
||||
"""Test adding metadata with all fields set."""
|
||||
with patch("esphome.components.display.CORE.data", {}):
|
||||
mock_id = MockObj("my_display_obj")
|
||||
add_metadata(mock_id, 480, 320, False, has_hardware_rotation=True)
|
||||
meta = get_display_metadata("my_display_obj")
|
||||
add_metadata(
|
||||
ID("my_display"),
|
||||
480,
|
||||
320,
|
||||
has_hardware_rotation=True,
|
||||
byte_order=BYTE_ORDER_LITTLE,
|
||||
)
|
||||
meta = get_display_metadata(ID("my_display"))
|
||||
assert meta == DisplayMetaData(
|
||||
width=480, height=320, has_writer=False, has_hardware_rotation=True
|
||||
width=480,
|
||||
height=320,
|
||||
has_hardware_rotation=True,
|
||||
byte_order=BYTE_ORDER_LITTLE,
|
||||
)
|
||||
|
||||
|
||||
def test_add_metadata_hardware_rotation_default():
|
||||
"""Test that has_hardware_rotation defaults to False."""
|
||||
with patch("esphome.components.display.CORE.data", {}):
|
||||
add_metadata("disp", 128, 64, False)
|
||||
meta = get_display_metadata("disp")
|
||||
add_metadata(ID("disp"), 128, 64)
|
||||
meta = get_display_metadata(ID("disp"))
|
||||
assert meta.has_hardware_rotation is False
|
||||
assert meta.byte_order == BYTE_ORDER_BIG
|
||||
|
||||
|
||||
def test_get_display_metadata_missing_returns_none():
|
||||
"""Test that querying a non-existent ID returns None."""
|
||||
def test_add_metadata_with_byte_order():
|
||||
"""Test adding metadata with explicit byte_order."""
|
||||
with patch("esphome.components.display.CORE.data", {}):
|
||||
data = get_display_metadata("no_such_display")
|
||||
assert data.width == 0
|
||||
assert data.height == 0
|
||||
assert data.has_writer is False
|
||||
add_metadata(ID("disp"), 240, 320, byte_order=BYTE_ORDER_LITTLE)
|
||||
meta = get_display_metadata(ID("disp"))
|
||||
assert meta.byte_order == BYTE_ORDER_LITTLE
|
||||
|
||||
|
||||
def test_get_display_metadata_missing_reads_raw_config():
|
||||
"""Querying a non-existent ID falls back to raw config lookup."""
|
||||
with patch("esphome.components.display.CORE.data", {}):
|
||||
# Set up a minimal full_config with a display entry so the fallback
|
||||
# path in get_display_metadata can find the display config.
|
||||
fc = Config()
|
||||
fc["display"] = [
|
||||
{
|
||||
"id": ID("no_such_display", True),
|
||||
"auto_clear_enabled": True,
|
||||
"dimensions": {"width": 320, "height": 240},
|
||||
"byte_order": BYTE_ORDER_LITTLE,
|
||||
"rotation": 90,
|
||||
},
|
||||
{
|
||||
"id": ID("other_display", True),
|
||||
"auto_clear_enabled": "undefined",
|
||||
"dimensions": (1024, 600),
|
||||
},
|
||||
]
|
||||
fc.declare_ids.append((ID("no_such_display", True), ["display", 0, "id"]))
|
||||
fc.declare_ids.append((ID("other_display", True), ["display", 1, "id"]))
|
||||
full_config.set(fc)
|
||||
data = get_display_metadata(ID("no_such_display"))
|
||||
assert data.width == 320
|
||||
assert data.height == 240
|
||||
assert data.has_hardware_rotation is False
|
||||
assert data.has_writer is True
|
||||
assert data.byte_order == BYTE_ORDER_LITTLE
|
||||
assert data.rotation == 90
|
||||
|
||||
data = get_display_metadata(ID("other_display"))
|
||||
assert data.width == 1024
|
||||
assert data.height == 600
|
||||
assert data.has_writer is False
|
||||
|
||||
|
||||
def test_add_multiple_displays():
|
||||
"""Test adding metadata for multiple displays."""
|
||||
with patch("esphome.components.display.CORE.data", {}):
|
||||
add_metadata("disp_a", 320, 240, True)
|
||||
add_metadata("disp_b", 128, 64, False, has_hardware_rotation=True)
|
||||
add_metadata(ID("disp_a"), 320, 240)
|
||||
add_metadata(ID("disp_b"), 128, 64, has_hardware_rotation=True)
|
||||
|
||||
all_meta = get_all_display_metadata()
|
||||
assert len(all_meta) == 2
|
||||
assert all_meta["disp_a"] == DisplayMetaData(320, 240, True, False)
|
||||
assert all_meta["disp_b"] == DisplayMetaData(128, 64, False, True)
|
||||
assert all_meta["disp_a"] == DisplayMetaData(320, 240, False)
|
||||
assert all_meta["disp_b"] == DisplayMetaData(128, 64, True, BYTE_ORDER_BIG)
|
||||
|
||||
|
||||
def test_add_metadata_overwrites_existing():
|
||||
"""Test that adding metadata for the same ID overwrites the previous entry."""
|
||||
def test_add_duplicate_id_asserts():
|
||||
"""Adding metadata for the same ID object twice should assert."""
|
||||
with patch("esphome.components.display.CORE.data", {}):
|
||||
add_metadata("disp", 320, 240, True)
|
||||
add_metadata("disp", 640, 480, False, has_hardware_rotation=True)
|
||||
meta = get_display_metadata("disp")
|
||||
assert meta == DisplayMetaData(640, 480, False, True)
|
||||
id_obj = ID("disp")
|
||||
add_metadata(id_obj, 320, 240)
|
||||
with pytest.raises(AssertionError, match="Duplicate"):
|
||||
add_metadata(id_obj, 640, 480)
|
||||
|
||||
|
||||
def test_metadata_is_frozen():
|
||||
"""Test that DisplayMetaData instances are immutable (frozen dataclass)."""
|
||||
meta = DisplayMetaData(320, 240, True, False)
|
||||
meta = DisplayMetaData(320, 240, False, BYTE_ORDER_BIG)
|
||||
with pytest.raises(AttributeError):
|
||||
meta.width = 640
|
||||
with pytest.raises(AttributeError):
|
||||
meta.byte_order = BYTE_ORDER_LITTLE
|
||||
|
||||
|
||||
def test_get_all_metadata_asserts_on_unresolved_id():
|
||||
"""get_all_display_metadata should assert if any ID has id=None."""
|
||||
with patch("esphome.components.display.CORE.data", {}):
|
||||
add_metadata(ID(None), 320, 240)
|
||||
with pytest.raises(AssertionError, match="resolved"):
|
||||
get_all_display_metadata()
|
||||
|
||||
|
||||
def test_get_metadata_asserts_on_unresolved_id():
|
||||
"""get_display_metadata should assert if any ID has id=None."""
|
||||
with patch("esphome.components.display.CORE.data", {}):
|
||||
add_metadata(ID(None), 320, 240)
|
||||
with pytest.raises(AssertionError, match="resolved"):
|
||||
get_display_metadata(ID("anything"))
|
||||
|
||||
177
tests/component_tests/lvgl/test_validation.py
Normal file
177
tests/component_tests/lvgl/test_validation.py
Normal file
@@ -0,0 +1,177 @@
|
||||
"""Tests for LVGL final_validation display metadata checks."""
|
||||
|
||||
from __future__ import annotations
|
||||
|
||||
import pytest
|
||||
|
||||
from esphome.components.const import BYTE_ORDER_BIG, BYTE_ORDER_LITTLE, CONF_BYTE_ORDER
|
||||
from esphome.components.display import add_metadata
|
||||
from esphome.components.lvgl import final_validation
|
||||
from esphome.config import Config
|
||||
from esphome.config_validation import Invalid
|
||||
from esphome.const import KEY_CORE, KEY_TARGET_FRAMEWORK, KEY_TARGET_PLATFORM
|
||||
from esphome.core import CORE, ID
|
||||
from esphome.final_validate import full_config
|
||||
|
||||
|
||||
@pytest.fixture(autouse=True)
|
||||
def _setup_core():
|
||||
"""Ensure CORE.data has enough context for final_validation."""
|
||||
CORE.data[KEY_CORE] = {
|
||||
KEY_TARGET_PLATFORM: "host",
|
||||
KEY_TARGET_FRAMEWORK: "",
|
||||
}
|
||||
full_config.set(Config())
|
||||
yield
|
||||
CORE.reset()
|
||||
|
||||
|
||||
def _register_displays(*display_ids: str) -> None:
|
||||
"""Register display IDs in full_config so get_path_for_id works."""
|
||||
fc = full_config.get()
|
||||
display_list = [{"id": ID(d, True)} for d in display_ids]
|
||||
fc["display"] = display_list
|
||||
for i, disp_id in enumerate(display_ids):
|
||||
fc.declare_ids.append((ID(disp_id, True), ["display", i, "id"]))
|
||||
|
||||
|
||||
def _make_lvgl_config(
|
||||
display_ids: list[str],
|
||||
byte_order: str | None = None,
|
||||
) -> dict:
|
||||
"""Build a minimal LVGL config dict for final_validation."""
|
||||
_register_displays(*display_ids)
|
||||
config = {
|
||||
"displays": [ID(d, True) for d in display_ids],
|
||||
"log_level": "WARN",
|
||||
"color_depth": 16,
|
||||
"transparency_key": 0x000400,
|
||||
"draw_rounding": 2,
|
||||
"buffer_size": 0,
|
||||
}
|
||||
if byte_order is not None:
|
||||
config[CONF_BYTE_ORDER] = byte_order
|
||||
return config
|
||||
|
||||
|
||||
class TestByteOrderAutoConfig:
|
||||
"""Test that LVGL auto-configures byte_order from display metadata."""
|
||||
|
||||
def test_inherits_big_endian_from_display(self) -> None:
|
||||
"""LVGL should inherit big_endian from display metadata."""
|
||||
add_metadata(ID("my_disp"), 320, 240, byte_order=BYTE_ORDER_BIG)
|
||||
configs = [_make_lvgl_config(["my_disp"])]
|
||||
final_validation(configs)
|
||||
assert configs[0][CONF_BYTE_ORDER] == BYTE_ORDER_BIG
|
||||
|
||||
def test_inherits_little_endian_from_display(self) -> None:
|
||||
"""LVGL should inherit little_endian from display metadata."""
|
||||
add_metadata(ID("my_disp"), 320, 240, byte_order=BYTE_ORDER_LITTLE)
|
||||
configs = [_make_lvgl_config(["my_disp"])]
|
||||
final_validation(configs)
|
||||
assert configs[0][CONF_BYTE_ORDER] == BYTE_ORDER_LITTLE
|
||||
|
||||
def test_defaults_to_big_endian_when_no_metadata(self) -> None:
|
||||
"""LVGL should default to big_endian when display has no metadata."""
|
||||
configs = [_make_lvgl_config(["my_disp"])]
|
||||
final_validation(configs)
|
||||
assert configs[0][CONF_BYTE_ORDER] == BYTE_ORDER_BIG
|
||||
|
||||
|
||||
class TestByteOrderExplicitMismatchError:
|
||||
"""Test that LVGL rejects explicit byte_order mismatch with display."""
|
||||
|
||||
def test_raises_on_mismatch(self) -> None:
|
||||
"""Explicit LVGL byte_order different from display should raise."""
|
||||
add_metadata(ID("my_disp"), 320, 240, byte_order=BYTE_ORDER_LITTLE)
|
||||
configs = [_make_lvgl_config(["my_disp"], byte_order=BYTE_ORDER_BIG)]
|
||||
with pytest.raises(
|
||||
Invalid, match="LVGL byte order must match the display byte order"
|
||||
):
|
||||
final_validation(configs)
|
||||
|
||||
def test_no_error_when_matching(self) -> None:
|
||||
"""Explicit LVGL byte_order matching display should pass."""
|
||||
add_metadata(ID("my_disp"), 320, 240, byte_order=BYTE_ORDER_BIG)
|
||||
configs = [_make_lvgl_config(["my_disp"], byte_order=BYTE_ORDER_BIG)]
|
||||
final_validation(configs)
|
||||
|
||||
|
||||
class TestByteOrderMultipleDisplays:
|
||||
"""Test byte_order validation with multiple displays."""
|
||||
|
||||
def test_consistent_displays_inherit(self) -> None:
|
||||
"""All displays with same byte_order should set LVGL byte_order."""
|
||||
add_metadata(ID("disp_a"), 320, 240, byte_order=BYTE_ORDER_LITTLE)
|
||||
add_metadata(ID("disp_b"), 128, 64, byte_order=BYTE_ORDER_LITTLE)
|
||||
configs = [_make_lvgl_config(["disp_a", "disp_b"])]
|
||||
final_validation(configs)
|
||||
assert configs[0][CONF_BYTE_ORDER] == BYTE_ORDER_LITTLE
|
||||
|
||||
def test_inconsistent_displays_raises(self) -> None:
|
||||
"""Displays with different byte_order should raise an error."""
|
||||
add_metadata(ID("disp_a"), 320, 240, byte_order=BYTE_ORDER_BIG)
|
||||
add_metadata(ID("disp_b"), 128, 64, byte_order=BYTE_ORDER_LITTLE)
|
||||
configs = [_make_lvgl_config(["disp_a", "disp_b"])]
|
||||
with pytest.raises(Invalid, match="same byte_order"):
|
||||
final_validation(configs)
|
||||
|
||||
|
||||
class TestHasWriterCheck:
|
||||
"""Test that LVGL rejects displays with has_writer set."""
|
||||
|
||||
def test_display_with_writer_raises(self) -> None:
|
||||
"""Display with lambda/pages/auto_clear should be rejected."""
|
||||
add_metadata(ID("my_disp"), 320, 240, has_writer=True)
|
||||
configs = [_make_lvgl_config(["my_disp"])]
|
||||
with pytest.raises(Invalid, match="not compatible with LVGL"):
|
||||
final_validation(configs)
|
||||
|
||||
def test_display_without_writer_passes(self) -> None:
|
||||
"""Display without writer should pass."""
|
||||
add_metadata(ID("my_disp"), 320, 240, has_writer=False)
|
||||
configs = [_make_lvgl_config(["my_disp"])]
|
||||
final_validation(configs)
|
||||
|
||||
|
||||
class TestRotationCheck:
|
||||
"""Test that LVGL rejects displays with non-zero rotation."""
|
||||
|
||||
def test_display_with_rotation_raises(self) -> None:
|
||||
"""Display with rotation should be rejected."""
|
||||
add_metadata(ID("my_disp"), 320, 240, rotation=90)
|
||||
configs = [_make_lvgl_config(["my_disp"])]
|
||||
with pytest.raises(Invalid, match="rotation.*not compatible with LVGL"):
|
||||
final_validation(configs)
|
||||
|
||||
def test_display_without_rotation_passes(self) -> None:
|
||||
"""Display with rotation=0 should pass."""
|
||||
add_metadata(ID("my_disp"), 320, 240, rotation=0)
|
||||
configs = [_make_lvgl_config(["my_disp"])]
|
||||
final_validation(configs)
|
||||
|
||||
|
||||
class TestDrawRoundingMerge:
|
||||
"""Test that display draw_rounding is merged into LVGL config."""
|
||||
|
||||
def test_display_draw_rounding_overrides_lower(self) -> None:
|
||||
"""Display draw_rounding higher than LVGL default should win."""
|
||||
add_metadata(ID("my_disp"), 320, 240, draw_rounding=8)
|
||||
configs = [_make_lvgl_config(["my_disp"])]
|
||||
final_validation(configs)
|
||||
assert configs[0]["draw_rounding"] == 8
|
||||
|
||||
def test_display_draw_rounding_does_not_lower(self) -> None:
|
||||
"""Display draw_rounding lower than LVGL config should not reduce it."""
|
||||
add_metadata(ID("my_disp"), 320, 240, draw_rounding=1)
|
||||
configs = [_make_lvgl_config(["my_disp"])]
|
||||
configs[0]["draw_rounding"] = 4
|
||||
final_validation(configs)
|
||||
assert configs[0]["draw_rounding"] == 4
|
||||
|
||||
def test_zero_draw_rounding_no_change(self) -> None:
|
||||
"""Display with draw_rounding=0 should not affect LVGL config."""
|
||||
add_metadata(ID("my_disp"), 320, 240, draw_rounding=0)
|
||||
configs = [_make_lvgl_config(["my_disp"])]
|
||||
final_validation(configs)
|
||||
assert configs[0]["draw_rounding"] == 2
|
||||
@@ -3,22 +3,15 @@
|
||||
from collections.abc import Callable
|
||||
from pathlib import Path
|
||||
|
||||
from esphome.components.display import (
|
||||
DisplayMetaData,
|
||||
get_all_display_metadata,
|
||||
get_display_metadata,
|
||||
)
|
||||
from esphome.components.const import BYTE_ORDER_BIG
|
||||
from esphome.components.display import get_all_display_metadata, get_display_metadata
|
||||
from esphome.components.esp32 import (
|
||||
KEY_BOARD,
|
||||
KEY_VARIANT,
|
||||
VARIANT_ESP32,
|
||||
VARIANT_ESP32S3,
|
||||
)
|
||||
from esphome.components.mipi_spi.display import (
|
||||
CONFIG_SCHEMA,
|
||||
FINAL_VALIDATE_SCHEMA,
|
||||
get_instance,
|
||||
)
|
||||
from esphome.components.mipi_spi.display import CONFIG_SCHEMA, FINAL_VALIDATE_SCHEMA
|
||||
from esphome.const import PlatformFramework
|
||||
from tests.component_tests.types import SetCoreConfigCallable
|
||||
|
||||
@@ -38,38 +31,32 @@ def test_metadata_native_quad_default_test_card(
|
||||
PlatformFramework.ESP32_IDF,
|
||||
platform_data={KEY_BOARD: "esp32-s3-devkitc-1", KEY_VARIANT: VARIANT_ESP32S3},
|
||||
)
|
||||
config = validated_config({"model": "JC3636W518"})
|
||||
get_instance(config)
|
||||
meta = get_display_metadata(str(config["id"]))
|
||||
config = CONFIG_SCHEMA({"model": "JC3636W518", "id": "jc3232w518"})
|
||||
meta = get_display_metadata(config["id"])
|
||||
assert meta is not None
|
||||
assert meta.width == 360
|
||||
assert meta.height == 360
|
||||
# final validation auto-enables show_test_card when no drawing methods are configured
|
||||
assert meta.has_writer is True
|
||||
assert meta.has_hardware_rotation is True
|
||||
assert meta.byte_order == BYTE_ORDER_BIG
|
||||
|
||||
|
||||
def test_metadata_single_mode_with_dc_pin(
|
||||
set_core_config: SetCoreConfigCallable,
|
||||
) -> None:
|
||||
"""A single-mode display with no explicit drawing gets a test card from final validation."""
|
||||
"""A single-mode display with no explicit drawing gets metadata from schema validation."""
|
||||
set_core_config(
|
||||
PlatformFramework.ESP32_IDF,
|
||||
platform_data={KEY_BOARD: "esp32dev", KEY_VARIANT: VARIANT_ESP32},
|
||||
)
|
||||
config = validated_config(
|
||||
{
|
||||
"model": "ST7735",
|
||||
"dc_pin": 18,
|
||||
}
|
||||
config = CONFIG_SCHEMA(
|
||||
{"model": "ST7735", "dc_pin": 18, "id": "single_mode_with_dc_pin"}
|
||||
)
|
||||
get_instance(config)
|
||||
meta = get_display_metadata(str(config["id"]))
|
||||
meta = get_display_metadata(config["id"])
|
||||
assert meta is not None
|
||||
assert meta.width == 128
|
||||
assert meta.height == 160
|
||||
assert meta.has_writer is True
|
||||
assert meta.has_hardware_rotation is True
|
||||
assert meta.byte_order == BYTE_ORDER_BIG
|
||||
|
||||
|
||||
def test_metadata_custom_dimensions(
|
||||
@@ -80,47 +67,22 @@ def test_metadata_custom_dimensions(
|
||||
PlatformFramework.ESP32_IDF,
|
||||
platform_data={KEY_BOARD: "esp32dev", KEY_VARIANT: VARIANT_ESP32},
|
||||
)
|
||||
config = validated_config(
|
||||
config = CONFIG_SCHEMA(
|
||||
{
|
||||
"model": "custom",
|
||||
"dc_pin": 18,
|
||||
"dimensions": {"width": 480, "height": 320},
|
||||
"init_sequence": [[0xA0, 0x01]],
|
||||
"id": "custom_dimensions",
|
||||
}
|
||||
)
|
||||
get_instance(config)
|
||||
meta = get_display_metadata(str(config["id"]))
|
||||
meta = get_display_metadata(config["id"])
|
||||
assert meta is not None
|
||||
assert meta.width == 480
|
||||
assert meta.height == 320
|
||||
# final validation auto-enables show_test_card
|
||||
assert meta.has_writer is True
|
||||
assert meta.has_hardware_rotation is True
|
||||
|
||||
|
||||
def test_metadata_with_test_card_has_writer(
|
||||
set_core_config: SetCoreConfigCallable,
|
||||
) -> None:
|
||||
"""When show_test_card is enabled, has_writer should be True."""
|
||||
set_core_config(
|
||||
PlatformFramework.ESP32_IDF,
|
||||
platform_data={KEY_BOARD: "esp32dev", KEY_VARIANT: VARIANT_ESP32},
|
||||
)
|
||||
config = validated_config(
|
||||
{
|
||||
"model": "custom",
|
||||
"dc_pin": 18,
|
||||
"dimensions": {"width": 240, "height": 240},
|
||||
"init_sequence": [[0xA0, 0x01]],
|
||||
"show_test_card": True,
|
||||
}
|
||||
)
|
||||
get_instance(config)
|
||||
meta = get_display_metadata(str(config["id"]))
|
||||
assert meta is not None
|
||||
assert meta.has_writer is True
|
||||
|
||||
|
||||
def test_metadata_no_swap_xy_not_full_hardware_rotation(
|
||||
set_core_config: SetCoreConfigCallable,
|
||||
) -> None:
|
||||
@@ -130,9 +92,8 @@ def test_metadata_no_swap_xy_not_full_hardware_rotation(
|
||||
platform_data={KEY_BOARD: "esp32-s3-devkitc-1", KEY_VARIANT: VARIANT_ESP32S3},
|
||||
)
|
||||
# JC3248W535 has swap_xy=cv.UNDEFINED -> transforms={mirror_x, mirror_y} only
|
||||
config = validated_config({"model": "JC3248W535"})
|
||||
get_instance(config)
|
||||
meta = get_display_metadata(str(config["id"]))
|
||||
config = CONFIG_SCHEMA({"model": "JC3248W535", "id": "jc3248w535"})
|
||||
meta = get_display_metadata(config["id"])
|
||||
assert meta is not None
|
||||
assert meta.has_hardware_rotation is False
|
||||
|
||||
@@ -145,7 +106,7 @@ def test_metadata_multiple_displays_independent(
|
||||
PlatformFramework.ESP32_IDF,
|
||||
platform_data={KEY_BOARD: "esp32dev", KEY_VARIANT: VARIANT_ESP32},
|
||||
)
|
||||
config_a = validated_config(
|
||||
CONFIG_SCHEMA(
|
||||
{
|
||||
"id": "disp_a",
|
||||
"model": "custom",
|
||||
@@ -154,7 +115,7 @@ def test_metadata_multiple_displays_independent(
|
||||
"init_sequence": [[0xA0, 0x01]],
|
||||
}
|
||||
)
|
||||
config_b = validated_config(
|
||||
CONFIG_SCHEMA(
|
||||
{
|
||||
"id": "disp_b",
|
||||
"model": "custom",
|
||||
@@ -163,13 +124,16 @@ def test_metadata_multiple_displays_independent(
|
||||
"init_sequence": [[0xA0, 0x01]],
|
||||
}
|
||||
)
|
||||
get_instance(config_a)
|
||||
get_instance(config_b)
|
||||
|
||||
all_meta = get_all_display_metadata()
|
||||
# final validation auto-enables show_test_card for both
|
||||
assert all_meta["disp_a"] == DisplayMetaData(320, 240, True, True)
|
||||
assert all_meta["disp_b"] == DisplayMetaData(128, 64, True, True)
|
||||
assert all_meta["disp_a"].width == 320
|
||||
assert all_meta["disp_a"].height == 240
|
||||
assert all_meta["disp_a"].has_hardware_rotation is True
|
||||
assert all_meta["disp_a"].byte_order == BYTE_ORDER_BIG
|
||||
assert all_meta["disp_b"].width == 128
|
||||
assert all_meta["disp_b"].height == 64
|
||||
assert all_meta["disp_b"].has_hardware_rotation is True
|
||||
assert all_meta["disp_b"].byte_order == BYTE_ORDER_BIG
|
||||
|
||||
|
||||
def test_metadata_via_code_generation_native(
|
||||
@@ -179,12 +143,13 @@ def test_metadata_via_code_generation_native(
|
||||
"""Full code generation for native.yaml should produce correct metadata."""
|
||||
generate_main(component_fixture_path("native.yaml"))
|
||||
all_meta = get_all_display_metadata()
|
||||
# native.yaml: model JC3636W518 -> 360x360, no writer, full hardware rotation
|
||||
# native.yaml: model JC3636W518 -> 360x360, full hardware rotation
|
||||
assert len(all_meta) == 1
|
||||
meta = next(iter(all_meta.values()))
|
||||
assert meta == DisplayMetaData(
|
||||
width=360, height=360, has_writer=True, has_hardware_rotation=True
|
||||
)
|
||||
assert meta.width == 360
|
||||
assert meta.height == 360
|
||||
assert meta.has_hardware_rotation is True
|
||||
assert meta.byte_order == BYTE_ORDER_BIG
|
||||
|
||||
|
||||
def test_metadata_via_code_generation_lvgl(
|
||||
@@ -194,9 +159,10 @@ def test_metadata_via_code_generation_lvgl(
|
||||
"""Full code generation for lvgl.yaml should produce correct metadata."""
|
||||
generate_main(component_fixture_path("lvgl.yaml"))
|
||||
all_meta = get_all_display_metadata()
|
||||
# lvgl.yaml: model ST7735 -> 128x160, no writer (lvgl draws directly), full hw rotation
|
||||
# lvgl.yaml: model ST7735 -> 128x160, full hw rotation
|
||||
assert len(all_meta) == 1
|
||||
meta = next(iter(all_meta.values()))
|
||||
assert meta == DisplayMetaData(
|
||||
width=128, height=160, has_writer=False, has_hardware_rotation=True
|
||||
)
|
||||
assert meta.width == 128
|
||||
assert meta.height == 160
|
||||
assert meta.has_hardware_rotation is True
|
||||
assert meta.byte_order == BYTE_ORDER_BIG
|
||||
|
||||
Reference in New Issue
Block a user