[remote_base] Keep constant IR codes in flash (#20083)

This commit is contained in:
J. Nick Koston
2026-10-09 09:22:32 -10:00
committed by GitHub
parent 3442bb6624
commit 9d02ab3734
7 changed files with 98 additions and 18 deletions
+20 -12
View File
@@ -2061,11 +2061,20 @@ def midea_dumper(var, config):
pass
async def _code_bytes(
value: Any, args: TemplateArgsType, set_template: MockObj, set_static: MockObj
) -> None:
"""Constant codes share one PROGMEM table pool across the remote protocols."""
await automation.templatable_bytes(
value, args, set_template, set_static, "remote_base_code"
)
@register_action("midea", MideaAction, MIDEA_SCHEMA)
async def midea_action(var, config, args):
vec_ = cg.std_vector.template(cg.uint8)
template_ = await cg.templatable(config[CONF_CODE], args, vec_, vec_)
cg.add(var.set_code(template_))
await _code_bytes(
config[CONF_CODE], args, var.set_code_template, var.set_code_static
)
# AEHA
@@ -2117,10 +2126,9 @@ def aeha_dumper(var, config):
async def aeha_action(var, config, args):
template_ = await cg.templatable(config[CONF_ADDRESS], args, cg.uint16)
cg.add(var.set_address(template_))
template_ = await cg.templatable(
config[CONF_DATA], args, cg.std_vector.template(cg.uint8)
await _code_bytes(
config[CONF_DATA], args, var.set_data_template, var.set_data_static
)
cg.add(var.set_data(template_))
templ = await cg.templatable(config[CONF_CARRIER_FREQUENCY], args, cg.uint32)
cg.add(var.set_carrier_frequency(templ))
@@ -2216,9 +2224,9 @@ def haier_dumper(var, config):
@register_action("haier", HaierAction, HAIER_SCHEMA)
async def haier_action(var, config, args):
vec_ = cg.std_vector.template(cg.uint8)
template_ = await cg.templatable(config[CONF_CODE], args, vec_, vec_)
cg.add(var.set_code(template_))
await _code_bytes(
config[CONF_CODE], args, var.set_code_template, var.set_code_static
)
# ABBWelcome
@@ -2359,9 +2367,9 @@ def mirage_dumper(var, config):
@register_action("mirage", MirageAction, MIRAGE_SCHEMA)
async def mirage_action(var, config, args):
vec_ = cg.std_vector.template(cg.uint8)
template_ = await cg.templatable(config[CONF_CODE], args, vec_, vec_)
cg.add(var.set_code(template_))
await _code_bytes(
config[CONF_CODE], args, var.set_code_template, var.set_code_static
)
# Toto
@@ -28,10 +28,9 @@ DECLARE_REMOTE_PROTOCOL(AEHA)
template<typename... Ts> class AEHAAction : public RemoteTransmitterActionBase<Ts...> {
public:
TEMPLATABLE_VALUE(uint16_t, address)
TEMPLATABLE_VALUE(std::vector<uint8_t>, data)
TEMPLATABLE_BYTES(data)
TEMPLATABLE_VALUE(uint32_t, carrier_frequency);
void set_data(const std::vector<uint8_t> &data) { data_ = data; }
void encode(RemoteTransmitData *dst, Ts... x) override {
AEHAData data{};
data.address = this->address_.value(x...);
@@ -25,7 +25,7 @@ DECLARE_REMOTE_PROTOCOL(Haier)
template<typename... Ts> class HaierAction : public RemoteTransmitterActionBase<Ts...> {
public:
TEMPLATABLE_VALUE(std::vector<uint8_t>, code)
TEMPLATABLE_BYTES(code)
void encode(RemoteTransmitData *dst, Ts... x) override {
HaierData data{};
@@ -4,6 +4,7 @@
#include <vector>
#include "esphome/core/component.h"
#include "esphome/core/hal.h"
#include "esphome/core/helpers.h"
#include "remote_base.h"
@@ -21,6 +22,9 @@ class MideaData {
MideaData(const std::vector<uint8_t> &data) {
std::copy_n(data.begin(), std::min(data.size(), this->data_.size()), this->data_.begin());
}
MideaData(const uint8_t *data, size_t len) {
progmem_memcpy(this->data_.data(), data, std::min(len, this->data_.size()));
}
uint8_t *data() { return this->data_.data(); }
const uint8_t *data() const { return this->data_.data(); }
@@ -75,10 +79,12 @@ class MideaProtocol : public RemoteProtocol<MideaData> {
DECLARE_REMOTE_PROTOCOL(Midea)
template<typename... Ts> class MideaAction : public RemoteTransmitterActionBase<Ts...> {
TEMPLATABLE_VALUE(std::vector<uint8_t>, code)
public:
TEMPLATABLE_BYTES(code)
void encode(RemoteTransmitData *dst, Ts... x) override {
MideaData data(this->code_.value(x...));
MideaData data = this->code_.is_static() ? MideaData(this->code_.data(), this->code_.size())
: MideaData(this->code_.value(x...));
data.finalize();
MideaProtocol().encode(dst, data);
}
@@ -25,7 +25,7 @@ DECLARE_REMOTE_PROTOCOL(Mirage)
template<typename... Ts> class MirageAction : public RemoteTransmitterActionBase<Ts...> {
public:
TEMPLATABLE_VALUE(std::vector<uint8_t>, code)
TEMPLATABLE_BYTES(code)
void encode(RemoteTransmitData *dst, Ts... x) override {
MirageData data{};
@@ -0,0 +1,43 @@
esphome:
name: test
esp32:
board: esp32dev
remote_transmitter:
pin: GPIO4
carrier_duty_percent: 50%
button:
- platform: template
name: Midea A
on_press:
- remote_transmitter.transmit_midea:
code: [0xA2, 0x08, 0xFF, 0xFF, 0xFF]
- platform: template
name: Midea B
on_press:
- remote_transmitter.transmit_midea:
code: [0xA2, 0x08, 0xFF, 0xFF, 0xFF]
- platform: template
name: AEHA
on_press:
- remote_transmitter.transmit_aeha:
address: 0x8008
data: [0x00, 0x02, 0xFD, 0xFF, 0x00, 0x33]
- platform: template
name: Haier lambda
on_press:
- remote_transmitter.transmit_haier:
code: !lambda |-
return {0xA6, 0xDA, 0x00, 0x00};
- platform: template
name: Haier static
on_press:
- remote_transmitter.transmit_haier:
code: [0xA6, 0xDA, 0x00, 0x00, 0x40, 0x40, 0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x05]
- platform: template
name: Mirage static
on_press:
- remote_transmitter.transmit_mirage:
code: [0x56, 0x6C, 0x00, 0x00, 0x20, 0x1A, 0x00, 0x00, 0x0C, 0x00, 0x0C, 0x00, 0x00, 0x42]
@@ -0,0 +1,24 @@
"""Constant IR byte codes live in shared PROGMEM tables; lambdas stay lambdas."""
from collections.abc import Callable
from pathlib import Path
import re
def test_ir_codes_use_shared_progmem_tables(
generate_main: Callable[[str | Path], str],
component_config_path: Callable[[str], Path],
) -> None:
main_cpp = generate_main(component_config_path("ir_codes.yaml"))
tables = re.findall(
r"static constexpr uint8_t (remote_base_code\w*)\[\] PROGMEM", main_cpp
)
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 "std::vector<uint8_t>{" not in main_cpp