[remote_base] Generate the byte payload transmit actions with no C++ class (#20568)

This commit is contained in:
J. Nick Koston
2026-10-12 07:14:19 -10:00
committed by GitHub
parent 9e8845885b
commit 72ea9ae458
17 changed files with 223 additions and 217 deletions
@@ -3,7 +3,7 @@
import re
_PROTOCOL_CALL_BODY = re.compile(
r"auto apply_call = \S+->protocol_call<remote_base::\w+>\(\);\n(.*?)apply_call\.perform\(\);",
r"auto apply_call = \S+->(?:protocol|encode)_call<remote_base::\w+>\(\);\n(.*?)apply_call\.perform\(\);",
re.DOTALL,
)
@@ -0,0 +1,33 @@
esphome:
name: test
esp8266:
board: esp01_1m
remote_transmitter:
pin: GPIO4
carrier_duty_percent: 50%
button:
- platform: template
name: ABBWelcome fixed id
on_press:
- remote_transmitter.transmit_abbwelcome:
source_address: 0x123456
destination_address: 0x56789A
three_byte_address: true
message_type: 0x01
message_id: 0x42
data: [0x10]
- platform: template
name: AEHA lambda
on_press:
- remote_transmitter.transmit_aeha:
address: !lambda return 0x8008;
carrier_frequency: 36700Hz
data: !lambda return {0x00, 0x02};
- platform: template
name: Midea lambda
on_press:
- remote_transmitter.transmit_midea:
code: !lambda return {0xA2, 0x08, 0xFF, 0xFF, 0xFF};
@@ -9,13 +9,17 @@ def test_constant_data_shares_progmem_tables(
generate_main: Callable[[str | Path], str],
component_config_path: Callable[[str], Path],
) -> None:
"""Equal data shares one table, empty or missing data is an empty table, lambdas stay templates."""
"""Equal data shares one table, empty data is a null table, lambdas are called inline."""
main_cpp = generate_main(component_config_path("abbwelcome_payload_tables.yaml"))
tables = re.findall(
r"static constexpr uint8_t (\w+)\[\] PROGMEM = (\{[^}]*\});", main_cpp
)
assert [v for _, v in tables] == ["{0x10, 0x20, 0x30}"]
assert main_cpp.count(f"set_data_static({tables[0][0]}, 3);") == 2
assert main_cpp.count("set_data_static(nullptr, 0);") == 2
assert main_cpp.count("set_data_template(") == 1
assert main_cpp.count(f"apply_call.data.set_data({tables[0][0]}, 3);") == 2
# Empty data is a null table; missing data leaves the default empty payload
assert main_cpp.count("apply_call.data.set_data(nullptr, 0);") == 1
assert (
main_cpp.count("apply_call.data.set_data([]() -> std::vector<uint8_t> {") == 1
)
assert "std::vector<uint8_t>{" not in main_cpp
@@ -0,0 +1,33 @@
"""The byte payload transmit actions as generated code."""
from collections.abc import Callable
from pathlib import Path
from tests.component_tests.remote_transmitter import protocol_call_bodies
def test_byte_payloads(
generate_main: Callable[[str | Path], str],
component_config_path: Callable[[str], Path],
) -> None:
main_cpp = generate_main(component_config_path("byte_payloads.yaml"))
abb, aeha, midea = protocol_call_bodies(main_cpp)
# The address length goes first, a configured id turns the automatic one off
assert abb.index("set_three_byte_address(true);") < abb.index("set_source_address(")
assert abb.index("auto_message_id = true;") < abb.index(
"set_fixed_message_id(0x42);"
)
assert abb.rstrip().endswith("apply_call.data.finalize();")
# The carrier is set before the payload is encoded
assert aeha.index("set_carrier_frequency(36700);") < aeha.index(
"apply_call.encode("
)
assert (
"apply_call.encode(static_cast<uint16_t>(0x8008), []() -> std::vector<uint8_t> {"
in aeha
)
assert (
"apply_call.data = remote_base::MideaData([]() -> std::vector<uint8_t> {"
in midea
)
assert midea.rstrip().endswith("apply_call.data.finalize();")
@@ -1,4 +1,4 @@
"""Constant IR byte codes live in shared PROGMEM tables; lambdas stay lambdas."""
"""Constant IR byte codes are encoded from shared PROGMEM tables; lambdas are called inline."""
from collections.abc import Callable
from pathlib import Path
@@ -16,9 +16,10 @@ def test_ir_codes_use_shared_progmem_tables(
)
assert len(tables) == 4 # Midea (shared by two actions), AEHA, Haier, Mirage
midea = tables[0]
assert main_cpp.count(f"->set_code_static({midea}, 5);") == 2
assert re.search(r"->set_data_static\(remote_base_code\w*, 6\);", main_cpp)
assert re.search(r"->set_code_static\(remote_base_code\w*, 13\);", main_cpp)
assert re.search(r"->set_code_static\(remote_base_code\w*, 14\);", main_cpp)
assert "->set_code_template([](" in main_cpp
assert main_cpp.count(f"apply_call.data = remote_base::MideaData({midea}, 5);") == 2
assert re.search(r"apply_call\.encode\(0x8008, remote_base_code\w*, 6\);", main_cpp)
assert re.search(r"apply_call\.encode\(remote_base_code\w*, 13\);", main_cpp)
assert re.search(r"apply_call\.encode\(remote_base_code\w*, 14\);", main_cpp)
assert "apply_call.encode([]() -> std::vector<uint8_t> {" in main_cpp
# Constant codes are read from the table, never copied into a vector
assert "std::vector<uint8_t>{" not in main_cpp