Build the autorepeat timing table with cg.shared_progmem_array

This commit is contained in:
J. Nick Koston
2026-10-02 19:49:24 -05:00
parent fe66ac546a
commit aac085c5c7
3 changed files with 9 additions and 22 deletions
+5 -22
View File
@@ -1,4 +1,3 @@
from dataclasses import dataclass, field
from logging import getLogger
from esphome import automation, core
@@ -75,7 +74,6 @@ from esphome.types import ConfigType
from esphome.util import Registry
CODEOWNERS = ["@esphome/core"]
DOMAIN = "binary_sensor"
DEVICE_CLASSES = [
DEVICE_CLASS_BATTERY,
DEVICE_CLASS_BATTERY_CHARGING,
@@ -266,29 +264,14 @@ async def autorepeat_filter_to_code(config: list[ConfigType], filter_id: ID) ->
)
for conf in config
]
tables = _get_data().autorepeat_timings
key = tuple(str(t) for t in timings)
if (table := tables.get(key)) is None:
# Derived from the filter id, like noise _psk and socket _ipv4_allow.
table_id = ID(
f"{filter_id}_timings", is_declaration=True, type=AutorepeatFilterTiming
)
table = tables[key] = cg.progmem_array(table_id, cg.ArrayInitializer(*timings))
table = cg.shared_progmem_array(
"binary_sensor_autorepeat_timings",
AutorepeatFilterTiming,
cg.ArrayInitializer(*timings),
)
return cg.new_Pvariable(filter_id, table, len(timings))
@dataclass
class BinarySensorData:
# Rendered timings -> the PROGMEM table shared by every autorepeat filter using them.
autorepeat_timings: dict[tuple[str, ...], MockObj] = field(default_factory=dict)
def _get_data() -> BinarySensorData:
if DOMAIN not in CORE.data:
CORE.data[DOMAIN] = BinarySensorData()
return CORE.data[DOMAIN]
@register_filter("lambda", LambdaFilter, cv.returning_lambda)
async def lambda_filter_to_code(config, filter_id):
lambda_ = await cg.process_lambda(
@@ -18,6 +18,7 @@ def test_autorepeat_timings_shared_progmem_table(
shared, default = tables
assert main_cpp.count(f"AutorepeatFilter({shared}, 2);") == 2
assert f"AutorepeatFilter({default}, 1);" in main_cpp
assert "binary_sensor_autorepeat_timings" not in tables
default_table = main_cpp.split(f"{default}[] PROGMEM = ", 1)[1].split(";", 1)[0]
for field in (".delay = 1000", ".time_off = 100", ".time_on = 900"):
assert field in default_table
@@ -30,3 +30,6 @@ binary_sensor:
id: repeat_default
filters:
- autorepeat:
# A user id equal to the table's preferred name must not break codegen.
- platform: template
id: binary_sensor_autorepeat_timings