[ld6002b] Check each area_config setting on its own for duplicates, and test the check

This commit is contained in:
J. Nick Koston
2026-10-16 15:51:05 -10:00
parent 204a7cd1dd
commit 7dbec6abf7
2 changed files with 79 additions and 8 deletions
+19 -7
View File
@@ -6,7 +6,7 @@ from esphome.const import CONF_ID, CONF_PLATFORM, CONF_WAKEUP_PIN
import esphome.final_validate as fv
from esphome.types import ConfigType
from .const import CONF_AUTO_WAKE, CONF_LD6002B_ID, CONF_WAKEUP_PULSE
from .const import CONF_AREA_CONFIG, CONF_AUTO_WAKE, CONF_LD6002B_ID, CONF_WAKEUP_PULSE
CODEOWNERS = ["@hepter"]
DEPENDENCIES = ["uart"]
@@ -84,11 +84,23 @@ def validate_unique_settings(domain: str, config: ConfigType) -> None:
for entry in fv.full_config.get().get(domain, [])
if entry.get(CONF_PLATFORM) == DOMAIN and entry.get(CONF_LD6002B_ID) == hub_id
]
for key in config:
for key, value in config.items():
if key in (CONF_PLATFORM, CONF_LD6002B_ID):
continue
if sum(key in entry for entry in entries) > 1:
raise cv.Invalid(
f"{key} is already set for this ld6002b in another {domain} block",
path=[key],
)
# area_config groups six settings, so each one is checked on its own
for path in (
[[key, sub] for sub in value] if key == CONF_AREA_CONFIG else [[key]]
):
if sum(_has_path(entry, path) for entry in entries) > 1:
raise cv.Invalid(
f"{'.'.join(path)} is already set for this ld6002b in another {domain} block",
path=path,
)
def _has_path(entry: ConfigType, path: list[str]) -> bool:
for key in path:
if key not in entry:
return False
entry = entry[key]
return True
@@ -9,11 +9,17 @@ from __future__ import annotations
import pytest
from esphome.components.ld6002b import validate_unique_settings
from esphome.components.ld6002b.button import (
CONFIG_SCHEMA as BUTTON_CONFIG_SCHEMA,
FINAL_VALIDATE_SCHEMA as BUTTON_FINAL_VALIDATE_SCHEMA,
)
from esphome.components.ld6002b.const import CONF_AREA_CONFIG, CONF_Z_MIN
from esphome.components.ld6002b.const import (
CONF_AREA_CONFIG,
CONF_HOLD_DELAY,
CONF_Z_MAX,
CONF_Z_MIN,
)
from esphome.components.ld6002b.number import (
CONFIG_SCHEMA as NUMBER_CONFIG_SCHEMA,
FINAL_VALIDATE_SCHEMA as NUMBER_FINAL_VALIDATE_SCHEMA,
@@ -40,6 +46,7 @@ def _full_config(
*,
selects: list[ConfigType] | None = None,
buttons: list[ConfigType] | None = None,
numbers: list[ConfigType] | None = None,
) -> Config:
"""A full config carrying one ld6002b hub, as the ID pass leaves it.
@@ -57,6 +64,8 @@ def _full_config(
full["select"] = selects
if buttons is not None:
full[CONF_BUTTON] = buttons
if numbers is not None:
full["number"] = numbers
return full
@@ -214,3 +223,53 @@ def test_area_config_without_select_is_rejected(
),
):
_validated_numbers(_area_numbers())
def _number_block(**settings: ConfigType) -> ConfigType:
"""A number platform block on the shared hub, as final validation sees it."""
return {
"platform": "ld6002b",
"ld6002b_id": ID(HUB_ID, is_declaration=False, type="ld6002b"),
**settings,
}
@pytest.mark.parametrize(
("first", "second", "error"),
[
(
{CONF_HOLD_DELAY: {"name": "A"}},
{CONF_HOLD_DELAY: {"name": "B"}},
r"^hold_delay is already set .* @ data\['hold_delay'\]$",
),
(
{CONF_AREA_CONFIG: {CONF_Z_MIN: {"name": "A"}}},
{CONF_AREA_CONFIG: {CONF_Z_MIN: {"name": "B"}}},
r"^area_config\.z_min is already set .* @ data\['area_config'\]\['z_min'\]$",
),
(
{CONF_AREA_CONFIG: {CONF_Z_MIN: {"name": "A"}}},
{CONF_AREA_CONFIG: {CONF_Z_MAX: {"name": "B"}}},
None,
),
({CONF_HOLD_DELAY: {"name": "A"}}, {CONF_Z_MIN: {"name": "B"}}, None),
],
)
def test_setting_in_two_blocks_of_one_hub(
set_core_config: SetCoreConfigCallable,
first: ConfigType,
second: ConfigType,
error: str | None,
) -> None:
"""Each setting maps to one entity pointer, so two blocks cannot share one."""
blocks = [_number_block(**first), _number_block(**second)]
set_core_config(
PlatformFramework.ESP32_IDF,
full_config=_full_config(_hub(wakeup_pin=False), numbers=blocks),
)
if error is None:
validate_unique_settings("number", blocks[1])
return
with pytest.raises(cv.Invalid, match=error):
validate_unique_settings("number", blocks[1])