[ld6002b] Share one generated function per platform, picking the type by entity pointer

This commit is contained in:
J. Nick Koston
2026-10-16 11:07:32 -10:00
parent 7070d516ca
commit bed58f5895
5 changed files with 114 additions and 45 deletions
+48 -1
View File
@@ -1,9 +1,12 @@
from collections.abc import Awaitable, Callable
from esphome import pins
import esphome.codegen as cg
from esphome.components import uart
import esphome.config_validation as cv
from esphome.const import CONF_ID, CONF_WAKEUP_PIN
from esphome.types import ConfigType
from esphome.cpp_generator import MockObj
from esphome.types import ConfigType, Expression
from .const import CONF_AUTO_WAKE, CONF_WAKEUP_PULSE
@@ -73,3 +76,47 @@ async def to_code(config: ConfigType) -> None:
cg.add(var.set_wakeup_pulse_ms(config[CONF_WAKEUP_PULSE].total_milliseconds))
cg.add(var.set_auto_wake(config[CONF_AUTO_WAKE]))
# (type, entity config, creates the entity from its template arguments, hub setter or None)
DispatchEntity = tuple[
MockObj,
ConfigType,
Callable[[cg.TemplateArguments], Awaitable[MockObj]],
Callable[[MockObj], Expression] | None,
]
async def build_type_dispatch(
hub: MockObj,
params: str,
call: str,
entities: list[DispatchEntity],
publish_before: str | None = None,
publish_after: str | None = None,
) -> None:
"""Give all of a platform's entities one generated function that finds the type by pointer.
One class per domain instead of one per entity; ``call`` names the type as ``type``.
"""
if not entities:
return
fn = f"esphome__{entities[0][1][CONF_ID].id}__fn"
# Declared first: the entities' types name it and its body names the entities.
cg.add_global(cg.RawStatement(f"static void {fn}({params});"))
template = cg.TemplateArguments(cg.RawExpression(fn))
created: list[tuple[MockObj, MockObj]] = []
for type_, _, create, setter in entities:
var = await create(template)
if setter is not None:
cg.add(setter(var))
created.append((type_, var))
*head, (last_type, _) = created
chain = "".join(f"entity == ::{var} ? {type_} : " for type_, var in head)
body = [f"const auto type = {chain}{last_type};", f"::{hub}->{call};"]
if publish_before:
body.insert(0, publish_before)
if publish_after:
body.append(publish_after)
lines = "\n ".join(body)
cg.add_global(cg.RawStatement(f"static void {fn}({params}) {{\n {lines}\n}}"))
+13 -4
View File
@@ -1,3 +1,6 @@
from functools import partial
import esphome.codegen as cg
from esphome.components import button
from esphome.components.select import DOMAIN as SELECT_DOMAIN
import esphome.config_validation as cv
@@ -10,7 +13,7 @@ from esphome.const import (
import esphome.final_validate as fv
from esphome.types import ConfigType
from .. import LD6002BComponent, ld6002b_ns
from .. import LD6002BComponent, build_type_dispatch, ld6002b_ns
from ..const import (
CONF_APPLY_AREA,
CONF_AUTO_INTERFERENCE,
@@ -128,6 +131,12 @@ BUTTON_MAP = {
async def to_code(config: ConfigType) -> None:
buttons = button.sub_buttons(config, parent=config[CONF_LD6002B_ID])
for key, button_type in BUTTON_MAP.items():
await buttons(key, None, apply=f"press_button({button_type})")
hub = await cg.get_variable(config[CONF_LD6002B_ID])
entities = [
(button_type, conf, partial(button.new_button, conf), None)
for key, button_type in BUTTON_MAP.items()
if (conf := config.get(key)) is not None
]
await build_type_dispatch(
hub, "button::Button *entity", "press_button(type)", entities
)
+25 -21
View File
@@ -1,3 +1,5 @@
from functools import partial
import esphome.codegen as cg
from esphome.components import number
from esphome.components.button import DOMAIN as BUTTON_DOMAIN
@@ -15,7 +17,7 @@ from esphome.const import (
import esphome.final_validate as fv
from esphome.types import ConfigType
from .. import LD6002BComponent, ld6002b_ns
from .. import DispatchEntity, LD6002BComponent, build_type_dispatch, ld6002b_ns
from ..const import (
CONF_APPLY_AREA,
CONF_AREA_CONFIG,
@@ -138,7 +140,7 @@ FINAL_VALIDATE_SCHEMA = final_validate
async def to_code(config: ConfigType) -> None:
hub = await cg.get_variable(config[CONF_LD6002B_ID])
numbers = number.sub_numbers(config, parent=hub)
entities: list[DispatchEntity] = []
for key, number_type, setter, min_value, max_value, step in (
(CONF_HOLD_DELAY, NumberType.HOLD_DELAY, "set_hold_delay_number", 0, 65535, 1),
@@ -156,18 +158,17 @@ async def to_code(config: ConfigType) -> None:
100,
),
):
await numbers(
key,
getattr(hub, setter),
min_value=min_value,
max_value=max_value,
step=step,
apply=f"set_number_value({number_type}, value)",
publish="before",
)
if (conf := config.get(key)) is not None:
create = partial(
number.new_number,
conf,
min_value=min_value,
max_value=max_value,
step=step,
)
entities.append((number_type, conf, create, getattr(hub, setter)))
if area_config := config.get(CONF_AREA_CONFIG):
area_numbers = number.sub_numbers(area_config, parent=hub)
for key, number_type, setter in (
(KEY_X_MIN, NumberType.AREA_X_MIN, "set_area_x_min_number"),
(KEY_X_MAX, NumberType.AREA_X_MAX, "set_area_x_max_number"),
@@ -176,12 +177,15 @@ async def to_code(config: ConfigType) -> None:
(CONF_Z_MIN, NumberType.AREA_Z_MIN, "set_area_z_min_number"),
(CONF_Z_MAX, NumberType.AREA_Z_MAX, "set_area_z_max_number"),
):
await area_numbers(
key,
getattr(hub, setter),
min_value=-10,
max_value=10,
step=0.1,
apply=f"set_number_value({number_type}, value)",
publish="before",
)
if (conf := area_config.get(key)) is not None:
create = partial(
number.new_number, conf, min_value=-10, max_value=10, step=0.1
)
entities.append((number_type, conf, create, getattr(hub, setter)))
await build_type_dispatch(
hub,
"number::Number *entity, float value",
"set_number_value(type, value)",
entities,
publish_before="entity->publish_state(value);",
)
+14 -10
View File
@@ -1,10 +1,12 @@
from functools import partial
import esphome.codegen as cg
from esphome.components import select
import esphome.config_validation as cv
from esphome.const import CONF_AREA_ID, CONF_SENSITIVITY, ENTITY_CATEGORY_CONFIG
from esphome.types import ConfigType
from .. import LD6002BComponent, ld6002b_ns
from .. import DispatchEntity, LD6002BComponent, build_type_dispatch, ld6002b_ns
from ..const import CONF_INSTALLATION_MODE, CONF_LD6002B_ID, CONF_TRIGGER_SPEED
DEPENDENCIES = ["ld6002b"]
@@ -66,13 +68,15 @@ SELECT_MAP = (
async def to_code(config: ConfigType) -> None:
hub = await cg.get_variable(config[CONF_LD6002B_ID])
selects = select.sub_selects(config, parent=hub)
entities: list[DispatchEntity] = []
for key, select_type, setter, options in SELECT_MAP:
await selects(
key,
getattr(hub, setter),
options=options,
apply=f"set_select_value({select_type}, index)",
publish="before",
)
if (conf := config.get(key)) is not None:
create = partial(select.new_select, conf, options=options)
entities.append((select_type, conf, create, getattr(hub, setter)))
await build_type_dispatch(
hub,
"select::Select *entity, size_t index",
"set_select_value(type, index)",
entities,
publish_before="entity->publish_state(index);",
)
+14 -9
View File
@@ -1,10 +1,12 @@
from functools import partial
import esphome.codegen as cg
from esphome.components import switch
import esphome.config_validation as cv
from esphome.const import DEVICE_CLASS_SWITCH, ENTITY_CATEGORY_CONFIG
from esphome.types import ConfigType
from .. import LD6002BComponent, ld6002b_ns
from .. import DispatchEntity, LD6002BComponent, build_type_dispatch, ld6002b_ns
from ..const import (
CONF_LD6002B_ID,
CONF_LOW_POWER,
@@ -48,16 +50,19 @@ CONFIG_SCHEMA = cv.Schema(
async def to_code(config: ConfigType) -> None:
hub = await cg.get_variable(config[CONF_LD6002B_ID])
switches = switch.sub_switches(config, parent=hub)
entities: list[DispatchEntity] = []
for key, switch_type, setter in (
(CONF_LOW_POWER, SwitchType.LOW_POWER, "set_low_power_switch"),
(CONF_POINT_CLOUD, SwitchType.POINT_CLOUD, "set_point_cloud_switch"),
(CONF_TARGET_DISPLAY, SwitchType.TARGET_DISPLAY, "set_target_display_switch"),
):
await switches(
key,
getattr(hub, setter),
apply=f"set_switch_state({switch_type}, state)",
publish="after",
)
if (conf := config.get(key)) is not None:
create = partial(switch.new_switch, conf)
entities.append((switch_type, conf, create, getattr(hub, setter)))
await build_type_dispatch(
hub,
"switch_::Switch *entity, bool state",
"set_switch_state(type, state)",
entities,
publish_after="entity->publish_state(state);",
)