From 4b143e1f3da9ac4fb225082e8505726677fa491c Mon Sep 17 00:00:00 2001 From: "J. Nick Koston" Date: Sat, 8 Nov 2025 21:54:05 -0600 Subject: [PATCH 1/8] Add ble_client lambda compile tests --- tests/components/ble_client/common.yaml | 22 ++++++++++++++++++++++ 1 file changed, 22 insertions(+) diff --git a/tests/components/ble_client/common.yaml b/tests/components/ble_client/common.yaml index aa4b639463..4ea1dd60f3 100644 --- a/tests/components/ble_client/common.yaml +++ b/tests/components/ble_client/common.yaml @@ -52,3 +52,25 @@ sensor: name: "BLE Sensor without Lambda" service_uuid: "abcd1234-abcd-1234-abcd-abcd12345678" characteristic_uuid: "abcd1237-abcd-1234-abcd-abcd12345678" + +number: + - platform: template + name: "Test Number" + id: test_number + optimistic: true + min_value: 0 + max_value: 255 + step: 1 + +button: + # Test ble_write with lambda that references a component (function pointer) + - platform: template + name: "BLE Write Lambda Test" + on_press: + - ble_client.ble_write: + id: test_blec + service_uuid: "abcd1234-abcd-1234-abcd-abcd12345678" + characteristic_uuid: "abcd1235-abcd-1234-abcd-abcd12345678" + value: !lambda |- + uint8_t val = (uint8_t)id(test_number).state; + return std::vector{0xAA, val, 0xBB}; From dad5a88ecf8edb8c4982ad3efcc23ca87cef708a Mon Sep 17 00:00:00 2001 From: "J. Nick Koston" Date: Sat, 8 Nov 2025 22:03:54 -0600 Subject: [PATCH 2/8] [canbus] Optimize canbus.send memory usage - store static data in flash --- esphome/components/canbus/__init__.py | 7 +++++-- esphome/components/canbus/canbus.h | 30 ++++++++++++++++++--------- tests/components/canbus/common.yaml | 13 ++++++++++++ 3 files changed, 38 insertions(+), 12 deletions(-) diff --git a/esphome/components/canbus/__init__.py b/esphome/components/canbus/__init__.py index e1de1eb2f2..7b51c2c45c 100644 --- a/esphome/components/canbus/__init__.py +++ b/esphome/components/canbus/__init__.py @@ -4,7 +4,7 @@ from esphome import automation import esphome.codegen as cg import esphome.config_validation as cv from esphome.const import CONF_DATA, CONF_ID, CONF_TRIGGER_ID -from esphome.core import CORE +from esphome.core import CORE, ID CODEOWNERS = ["@mvturnho", "@danielschramm"] IS_PLATFORM_COMPONENT = True @@ -176,5 +176,8 @@ async def canbus_action_to_code(config, action_id, template_arg, args): else: if isinstance(data, bytes): data = [int(x) for x in data] - cg.add(var.set_data_static(data)) + # Generate static array in flash to avoid RAM copy + arr_id = ID(f"{action_id}_data", is_declaration=True, type=cg.uint8) + arr = cg.static_const_array(arr_id, cg.ArrayInitializer(*data)) + cg.add(var.set_data_static(arr, len(data))) return var diff --git a/esphome/components/canbus/canbus.h b/esphome/components/canbus/canbus.h index 029eb278c0..122ccfe39e 100644 --- a/esphome/components/canbus/canbus.h +++ b/esphome/components/canbus/canbus.h @@ -112,12 +112,16 @@ class Canbus : public Component { template class CanbusSendAction : public Action, public Parented { public: - void set_data_template(const std::function(Ts...)> func) { - this->data_func_ = func; + void set_data_template(std::vector (*func)(Ts...)) { + // Stateless lambdas (generated by ESPHome) implicitly convert to function pointers + this->data_.func = func; this->static_ = false; } - void set_data_static(const std::vector &data) { - this->data_static_ = data; + + // Store pointer to static data in flash (no RAM copy) + void set_data_static(const uint8_t *data, size_t len) { + this->data_.static_data.ptr = data; + this->data_.static_data.len = len; this->static_ = true; } @@ -133,21 +137,27 @@ template class CanbusSendAction : public Action, public P auto can_id = this->can_id_.has_value() ? *this->can_id_ : this->parent_->can_id_; auto use_extended_id = this->use_extended_id_.has_value() ? *this->use_extended_id_ : this->parent_->use_extended_id_; + std::vector data; if (this->static_) { - this->parent_->send_data(can_id, use_extended_id, this->remote_transmission_request_, this->data_static_); + data.assign(this->data_.static_data.ptr, this->data_.static_data.ptr + this->data_.static_data.len); } else { - auto val = this->data_func_(x...); - this->parent_->send_data(can_id, use_extended_id, this->remote_transmission_request_, val); + data = this->data_.func(x...); } + this->parent_->send_data(can_id, use_extended_id, this->remote_transmission_request_, data); } protected: optional can_id_{}; optional use_extended_id_{}; bool remote_transmission_request_{false}; - bool static_{false}; - std::function(Ts...)> data_func_{}; - std::vector data_static_{}; + bool static_{true}; // Default to static mode (most common case) + union Data { + std::vector (*func)(Ts...); // 4 bytes on 32-bit + struct { + const uint8_t *ptr; // 4 bytes on 32-bit + size_t len; // 4 bytes on 32-bit + } static_data; // 8 bytes total on 32-bit + } data_; // Union size = 8 bytes (max of 4 and 8) }; class CanbusTrigger : public Trigger, uint32_t, bool>, public Component { diff --git a/tests/components/canbus/common.yaml b/tests/components/canbus/common.yaml index fd146cc3a3..8bddeb7409 100644 --- a/tests/components/canbus/common.yaml +++ b/tests/components/canbus/common.yaml @@ -37,6 +37,15 @@ canbus: break; } +number: + - platform: template + name: "Test Number" + id: test_number + optimistic: true + min_value: 0 + max_value: 255 + step: 1 + button: - platform: template name: Canbus Actions @@ -44,3 +53,7 @@ button: - canbus.send: "abc" - canbus.send: [0, 1, 2] - canbus.send: !lambda return {0, 1, 2}; + # Test canbus.send with lambda that references a component (function pointer) + - canbus.send: !lambda |- + uint8_t val = (uint8_t)id(test_number).state; + return std::vector{0xAA, val, 0xBB}; From 93a57831f40ffacc394b9c14aa5dd60e087ac1aa Mon Sep 17 00:00:00 2001 From: "J. Nick Koston" Date: Sat, 8 Nov 2025 22:08:07 -0600 Subject: [PATCH 3/8] Add additional compile time tests for canbus --- tests/components/canbus/common.yaml | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/tests/components/canbus/common.yaml b/tests/components/canbus/common.yaml index fd146cc3a3..8bddeb7409 100644 --- a/tests/components/canbus/common.yaml +++ b/tests/components/canbus/common.yaml @@ -37,6 +37,15 @@ canbus: break; } +number: + - platform: template + name: "Test Number" + id: test_number + optimistic: true + min_value: 0 + max_value: 255 + step: 1 + button: - platform: template name: Canbus Actions @@ -44,3 +53,7 @@ button: - canbus.send: "abc" - canbus.send: [0, 1, 2] - canbus.send: !lambda return {0, 1, 2}; + # Test canbus.send with lambda that references a component (function pointer) + - canbus.send: !lambda |- + uint8_t val = (uint8_t)id(test_number).state; + return std::vector{0xAA, val, 0xBB}; From 17df00809216a7505d9fbf12ed6e66d19d93bdf2 Mon Sep 17 00:00:00 2001 From: "J. Nick Koston" Date: Sat, 8 Nov 2025 22:16:39 -0600 Subject: [PATCH 4/8] [sx126x] Optimize send_packet action memory usage - store static data in flash --- esphome/components/sx126x/__init__.py | 7 +++++-- esphome/components/sx126x/automation.h | 26 +++++++++++++++++--------- tests/components/sx126x/common.yaml | 11 +++++++++++ 3 files changed, 33 insertions(+), 11 deletions(-) diff --git a/esphome/components/sx126x/__init__.py b/esphome/components/sx126x/__init__.py index 370cd102d4..f8f3b9d104 100644 --- a/esphome/components/sx126x/__init__.py +++ b/esphome/components/sx126x/__init__.py @@ -3,7 +3,7 @@ import esphome.codegen as cg from esphome.components import spi import esphome.config_validation as cv from esphome.const import CONF_BUSY_PIN, CONF_DATA, CONF_FREQUENCY, CONF_ID -from esphome.core import TimePeriod +from esphome.core import ID, TimePeriod MULTI_CONF = True CODEOWNERS = ["@swoboda1337"] @@ -329,5 +329,8 @@ async def send_packet_action_to_code(config, action_id, template_arg, args): templ = await cg.templatable(data, args, cg.std_vector.template(cg.uint8)) cg.add(var.set_data_template(templ)) else: - cg.add(var.set_data_static(data)) + # Generate static array in flash to avoid RAM copy + arr_id = ID(f"{action_id}_data", is_declaration=True, type=cg.uint8) + arr = cg.static_const_array(arr_id, cg.ArrayInitializer(*data)) + cg.add(var.set_data_static(arr, len(data))) return var diff --git a/esphome/components/sx126x/automation.h b/esphome/components/sx126x/automation.h index 6b2371e253..41f0a888e5 100644 --- a/esphome/components/sx126x/automation.h +++ b/esphome/components/sx126x/automation.h @@ -14,28 +14,36 @@ template class RunImageCalAction : public Action, public template class SendPacketAction : public Action, public Parented { public: - void set_data_template(std::function(Ts...)> func) { - this->data_func_ = func; + void set_data_template(std::vector (*func)(Ts...)) { + this->data_.func = func; this->static_ = false; } - void set_data_static(const std::vector &data) { - this->data_static_ = data; + void set_data_static(const uint8_t *data, size_t len) { + this->data_.static_data.ptr = data; + this->data_.static_data.len = len; this->static_ = true; } void play(const Ts &...x) override { + std::vector data; if (this->static_) { - this->parent_->transmit_packet(this->data_static_); + data.assign(this->data_.static_data.ptr, this->data_.static_data.ptr + this->data_.static_data.len); } else { - this->parent_->transmit_packet(this->data_func_(x...)); + data = this->data_.func(x...); } + this->parent_->transmit_packet(data); } protected: - bool static_{false}; - std::function(Ts...)> data_func_{}; - std::vector data_static_{}; + bool static_{true}; + union Data { + std::vector (*func)(Ts...); + struct { + const uint8_t *ptr; + size_t len; + } static_data; + } data_; }; template class SetModeTxAction : public Action, public Parented { diff --git a/tests/components/sx126x/common.yaml b/tests/components/sx126x/common.yaml index 3f540a4bae..659550cc01 100644 --- a/tests/components/sx126x/common.yaml +++ b/tests/components/sx126x/common.yaml @@ -26,6 +26,15 @@ sx126x: - lambda: |- ESP_LOGD("lambda", "packet %.2f %.2f %s", rssi, snr, format_hex(x).c_str()); +number: + - platform: template + name: "SX126x Number" + id: my_number + optimistic: true + min_value: 0 + max_value: 100 + step: 1 + button: - platform: template name: "SX126x Button" @@ -37,3 +46,5 @@ button: - sx126x.set_mode_rx - sx126x.send_packet: data: [0xC5, 0x51, 0x78, 0x82, 0xB7, 0xF9, 0x9C, 0x5C] + - sx126x.send_packet: !lambda |- + return {0x01, 0x02, (uint8_t)id(my_number).state}; From ba82d968eb40372103f1e9b9844972e5ada95848 Mon Sep 17 00:00:00 2001 From: "J. Nick Koston" Date: Sat, 8 Nov 2025 22:25:41 -0600 Subject: [PATCH 5/8] [sx127x] Optimize send_packet action memory usage - store static data in flash --- esphome/components/sx127x/__init__.py | 6 +++++- esphome/components/sx127x/automation.h | 26 +++++++++++++++++--------- tests/components/sx127x/common.yaml | 11 +++++++++++ 3 files changed, 33 insertions(+), 10 deletions(-) diff --git a/esphome/components/sx127x/__init__.py b/esphome/components/sx127x/__init__.py index 33b556db07..77cb61f7f8 100644 --- a/esphome/components/sx127x/__init__.py +++ b/esphome/components/sx127x/__init__.py @@ -3,6 +3,7 @@ import esphome.codegen as cg from esphome.components import spi import esphome.config_validation as cv from esphome.const import CONF_DATA, CONF_FREQUENCY, CONF_ID +from esphome.core import ID MULTI_CONF = True CODEOWNERS = ["@swoboda1337"] @@ -321,5 +322,8 @@ async def send_packet_action_to_code(config, action_id, template_arg, args): templ = await cg.templatable(data, args, cg.std_vector.template(cg.uint8)) cg.add(var.set_data_template(templ)) else: - cg.add(var.set_data_static(data)) + # Generate static array in flash to avoid RAM copy + arr_id = ID(f"{action_id}_data", is_declaration=True, type=cg.uint8) + arr = cg.static_const_array(arr_id, cg.ArrayInitializer(*data)) + cg.add(var.set_data_static(arr, len(data))) return var diff --git a/esphome/components/sx127x/automation.h b/esphome/components/sx127x/automation.h index eae16c11fa..52dbf37e09 100644 --- a/esphome/components/sx127x/automation.h +++ b/esphome/components/sx127x/automation.h @@ -14,28 +14,36 @@ template class RunImageCalAction : public Action, public template class SendPacketAction : public Action, public Parented { public: - void set_data_template(std::function(Ts...)> func) { - this->data_func_ = func; + void set_data_template(std::vector (*func)(Ts...)) { + this->data_.func = func; this->static_ = false; } - void set_data_static(const std::vector &data) { - this->data_static_ = data; + void set_data_static(const uint8_t *data, size_t len) { + this->data_.static_data.ptr = data; + this->data_.static_data.len = len; this->static_ = true; } void play(const Ts &...x) override { + std::vector data; if (this->static_) { - this->parent_->transmit_packet(this->data_static_); + data.assign(this->data_.static_data.ptr, this->data_.static_data.ptr + this->data_.static_data.len); } else { - this->parent_->transmit_packet(this->data_func_(x...)); + data = this->data_.func(x...); } + this->parent_->transmit_packet(data); } protected: - bool static_{false}; - std::function(Ts...)> data_func_{}; - std::vector data_static_{}; + bool static_{true}; + union Data { + std::vector (*func)(Ts...); + struct { + const uint8_t *ptr; + size_t len; + } static_data; + } data_; }; template class SetModeTxAction : public Action, public Parented { diff --git a/tests/components/sx127x/common.yaml b/tests/components/sx127x/common.yaml index 540381fc08..6e48952fcc 100644 --- a/tests/components/sx127x/common.yaml +++ b/tests/components/sx127x/common.yaml @@ -26,6 +26,15 @@ sx127x: - sx127x.send_packet: data: [0xC5, 0x51, 0x78, 0x82, 0xB7, 0xF9, 0x9C, 0x5C] +number: + - platform: template + name: "SX127x Number" + id: my_number + optimistic: true + min_value: 0 + max_value: 100 + step: 1 + button: - platform: template name: "SX127x Button" @@ -38,3 +47,5 @@ button: - sx127x.set_mode_rx - sx127x.send_packet: data: [0xC5, 0x51, 0x78, 0x82, 0xB7, 0xF9, 0x9C, 0x5C] + - sx127x.send_packet: !lambda |- + return {0x01, 0x02, (uint8_t)id(my_number).state}; From 2cac99dafaf7e3972127f3d22bec94ebe6634db8 Mon Sep 17 00:00:00 2001 From: "J. Nick Koston" Date: Sat, 8 Nov 2025 22:32:47 -0600 Subject: [PATCH 6/8] [udp] Optimize udp.write action memory usage - store static data in flash --- esphome/components/udp/__init__.py | 7 +++++-- esphome/components/udp/automation.h | 25 ++++++++++++++++--------- tests/components/udp/common.yaml | 19 +++++++++++++++++++ 3 files changed, 40 insertions(+), 11 deletions(-) diff --git a/esphome/components/udp/__init__.py b/esphome/components/udp/__init__.py index 6b1e4f8ed8..69abf4b989 100644 --- a/esphome/components/udp/__init__.py +++ b/esphome/components/udp/__init__.py @@ -12,7 +12,7 @@ from esphome.components.packet_transport import ( ) import esphome.config_validation as cv from esphome.const import CONF_DATA, CONF_ID, CONF_PORT, CONF_TRIGGER_ID -from esphome.core import Lambda +from esphome.core import ID, Lambda from esphome.cpp_generator import ExpressionStatement, MockObj CODEOWNERS = ["@clydebarrow"] @@ -158,5 +158,8 @@ async def udp_write_to_code(config, action_id, template_arg, args): templ = await cg.templatable(data, args, cg.std_vector.template(cg.uint8)) cg.add(var.set_data_template(templ)) else: - cg.add(var.set_data_static(data)) + # Generate static array in flash to avoid RAM copy + arr_id = ID(f"{action_id}_data", is_declaration=True, type=cg.uint8) + arr = cg.static_const_array(arr_id, cg.ArrayInitializer(*data)) + cg.add(var.set_data_static(arr, len(data))) return var diff --git a/esphome/components/udp/automation.h b/esphome/components/udp/automation.h index c5e5e2eae8..a3b76fb4ea 100644 --- a/esphome/components/udp/automation.h +++ b/esphome/components/udp/automation.h @@ -11,28 +11,35 @@ namespace udp { template class UDPWriteAction : public Action, public Parented { public: - void set_data_template(std::function(Ts...)> func) { - this->data_func_ = func; + void set_data_template(std::vector (*func)(Ts...)) { + this->data_.func = func; this->static_ = false; } - void set_data_static(const std::vector &data) { - this->data_static_ = data; + + void set_data_static(const uint8_t *data, size_t len) { + this->data_.static_data.ptr = data; + this->data_.static_data.len = len; this->static_ = true; } void play(const Ts &...x) override { if (this->static_) { - this->parent_->send_packet(this->data_static_); + this->parent_->send_packet(this->data_.static_data.ptr, this->data_.static_data.len); } else { - auto val = this->data_func_(x...); + auto val = this->data_.func(x...); this->parent_->send_packet(val); } } protected: - bool static_{false}; - std::function(Ts...)> data_func_{}; - std::vector data_static_{}; + bool static_{true}; + union Data { + std::vector (*func)(Ts...); + struct { + const uint8_t *ptr; + size_t len; + } static_data; + } data_; }; } // namespace udp diff --git a/tests/components/udp/common.yaml b/tests/components/udp/common.yaml index 96224d0d1f..98546d49ef 100644 --- a/tests/components/udp/common.yaml +++ b/tests/components/udp/common.yaml @@ -17,3 +17,22 @@ udp: id: my_udp data: !lambda |- return std::vector{1,3,4,5,6}; + +number: + - platform: template + name: "UDP Number" + id: my_number + optimistic: true + min_value: 0 + max_value: 100 + step: 1 + +button: + - platform: template + name: "UDP Button" + on_press: + then: + - udp.write: + data: [0x01, 0x02, 0x03] + - udp.write: !lambda |- + return {0x10, 0x20, (uint8_t)id(my_number).state}; From ecf7de7743c15981b4592d6a1425101a03198202 Mon Sep 17 00:00:00 2001 From: "J. Nick Koston" Date: Sat, 8 Nov 2025 22:39:51 -0600 Subject: [PATCH 7/8] [speaker] Optimize speaker.play action memory usage - store static data in flash --- esphome/components/speaker/__init__.py | 7 +++++-- esphome/components/speaker/automation.h | 25 ++++++++++++++++--------- tests/components/speaker/common.yaml | 18 ++++++++++++++++++ 3 files changed, 39 insertions(+), 11 deletions(-) diff --git a/esphome/components/speaker/__init__.py b/esphome/components/speaker/__init__.py index 5f1ba94ee6..18e1d9782c 100644 --- a/esphome/components/speaker/__init__.py +++ b/esphome/components/speaker/__init__.py @@ -3,7 +3,7 @@ import esphome.codegen as cg from esphome.components import audio, audio_dac import esphome.config_validation as cv from esphome.const import CONF_DATA, CONF_ID, CONF_VOLUME -from esphome.core import CORE +from esphome.core import CORE, ID from esphome.coroutine import CoroPriority, coroutine_with_priority AUTO_LOAD = ["audio"] @@ -90,7 +90,10 @@ async def speaker_play_action(config, action_id, template_arg, args): templ = await cg.templatable(data, args, cg.std_vector.template(cg.uint8)) cg.add(var.set_data_template(templ)) else: - cg.add(var.set_data_static(data)) + # Generate static array in flash to avoid RAM copy + arr_id = ID(f"{action_id}_data", is_declaration=True, type=cg.uint8) + arr = cg.static_const_array(arr_id, cg.ArrayInitializer(*data)) + cg.add(var.set_data_static(arr, len(data))) return var diff --git a/esphome/components/speaker/automation.h b/esphome/components/speaker/automation.h index 80bba25030..cae429cf8a 100644 --- a/esphome/components/speaker/automation.h +++ b/esphome/components/speaker/automation.h @@ -10,28 +10,35 @@ namespace speaker { template class PlayAction : public Action, public Parented { public: - void set_data_template(std::function(Ts...)> func) { - this->data_func_ = func; + void set_data_template(std::vector (*func)(Ts...)) { + this->data_.func = func; this->static_ = false; } - void set_data_static(const std::vector &data) { - this->data_static_ = data; + + void set_data_static(const uint8_t *data, size_t len) { + this->data_.static_data.ptr = data; + this->data_.static_data.len = len; this->static_ = true; } void play(const Ts &...x) override { if (this->static_) { - this->parent_->play(this->data_static_); + this->parent_->play(this->data_.static_data.ptr, this->data_.static_data.len); } else { - auto val = this->data_func_(x...); + auto val = this->data_.func(x...); this->parent_->play(val); } } protected: - bool static_{false}; - std::function(Ts...)> data_func_{}; - std::vector data_static_{}; + bool static_{true}; + union Data { + std::vector (*func)(Ts...); + struct { + const uint8_t *ptr; + size_t len; + } static_data; + } data_; }; template class VolumeSetAction : public Action, public Parented { diff --git a/tests/components/speaker/common.yaml b/tests/components/speaker/common.yaml index c04674ee29..fa54fa7e39 100644 --- a/tests/components/speaker/common.yaml +++ b/tests/components/speaker/common.yaml @@ -1,3 +1,12 @@ +number: + - platform: template + name: "Speaker Number" + id: my_number + optimistic: true + min_value: 0 + max_value: 100 + step: 1 + esphome: on_boot: then: @@ -14,6 +23,15 @@ esphome: - speaker.finish: - speaker.stop: +button: + - platform: template + name: "Speaker Button" + on_press: + then: + - speaker.play: [0x10, 0x20, 0x30, 0x40] + - speaker.play: !lambda |- + return {0x01, 0x02, (uint8_t)id(my_number).state}; + i2s_audio: i2s_lrclk_pin: ${i2s_bclk_pin} i2s_bclk_pin: ${i2s_lrclk_pin} From a239460724a9a6787f69b9061f3252be5b313ed2 Mon Sep 17 00:00:00 2001 From: "J. Nick Koston" Date: Sat, 8 Nov 2025 22:48:50 -0600 Subject: [PATCH 8/8] [remote_base] Optimize abbwelcome action memory usage - store static data in flash --- esphome/components/remote_base/__init__.py | 6 ++-- .../remote_base/abbwelcome_protocol.h | 31 +++++++++++++------ .../remote_transmitter/common-buttons.yaml | 25 +++++++++++++++ 3 files changed, 50 insertions(+), 12 deletions(-) diff --git a/esphome/components/remote_base/__init__.py b/esphome/components/remote_base/__init__.py index 8d735ea563..d24d24b000 100644 --- a/esphome/components/remote_base/__init__.py +++ b/esphome/components/remote_base/__init__.py @@ -39,7 +39,7 @@ from esphome.const import ( CONF_WAND_ID, CONF_ZERO, ) -from esphome.core import coroutine +from esphome.core import ID, coroutine from esphome.schema_extractors import SCHEMA_EXTRACT, schema_extractor from esphome.util import Registry, SimpleRegistry @@ -2104,7 +2104,9 @@ async def abbwelcome_action(var, config, args): ) cg.add(var.set_data_template(template_)) else: - cg.add(var.set_data_static(data_)) + arr_id = ID(f"{var.base}_data", is_declaration=True, type=cg.uint8) + arr = cg.static_const_array(arr_id, cg.ArrayInitializer(*data_)) + cg.add(var.set_data_static(arr, len(data_))) # Mirage diff --git a/esphome/components/remote_base/abbwelcome_protocol.h b/esphome/components/remote_base/abbwelcome_protocol.h index b258bd920b..2ed90c502e 100644 --- a/esphome/components/remote_base/abbwelcome_protocol.h +++ b/esphome/components/remote_base/abbwelcome_protocol.h @@ -214,10 +214,14 @@ template class ABBWelcomeAction : public RemoteTransmitterAction TEMPLATABLE_VALUE(uint8_t, message_type) TEMPLATABLE_VALUE(uint8_t, message_id) TEMPLATABLE_VALUE(bool, auto_message_id) - void set_data_static(std::vector data) { data_static_ = std::move(data); } - void set_data_template(std::function(Ts...)> func) { - this->data_func_ = func; - has_data_func_ = true; + void set_data_template(std::vector (*func)(Ts...)) { + this->data_.func = func; + this->static_ = false; + } + void set_data_static(const uint8_t *data, size_t len) { + this->data_.static_data.ptr = data; + this->data_.static_data.len = len; + this->static_ = true; } void encode(RemoteTransmitData *dst, Ts... x) override { ABBWelcomeData data; @@ -228,19 +232,26 @@ template class ABBWelcomeAction : public RemoteTransmitterAction data.set_message_type(this->message_type_.value(x...)); data.set_message_id(this->message_id_.value(x...)); data.auto_message_id = this->auto_message_id_.value(x...); - if (has_data_func_) { - data.set_data(this->data_func_(x...)); + std::vector data_vec; + if (this->static_) { + data_vec.assign(this->data_.static_data.ptr, this->data_.static_data.ptr + this->data_.static_data.len); } else { - data.set_data(this->data_static_); + data_vec = this->data_.func(x...); } + data.set_data(data_vec); data.finalize(); ABBWelcomeProtocol().encode(dst, data); } protected: - std::function(Ts...)> data_func_{}; - std::vector data_static_{}; - bool has_data_func_{false}; + bool static_{true}; + union Data { + std::vector (*func)(Ts...); + struct { + const uint8_t *ptr; + size_t len; + } static_data; + } data_; }; } // namespace remote_base diff --git a/tests/components/remote_transmitter/common-buttons.yaml b/tests/components/remote_transmitter/common-buttons.yaml index e9593cc97c..101d60a893 100644 --- a/tests/components/remote_transmitter/common-buttons.yaml +++ b/tests/components/remote_transmitter/common-buttons.yaml @@ -1,3 +1,11 @@ +number: + - platform: template + id: test_number + optimistic: true + min_value: 0 + max_value: 255 + step: 1 + button: - platform: template name: Beo4 audio mute @@ -217,6 +225,23 @@ button: command: 0xEC rc_code_1: 0x0D rc_code_2: 0x0D + - platform: template + name: ABBWelcome static + on_press: + remote_transmitter.transmit_abbwelcome: + source_address: 0x1234 + destination_address: 0x5678 + message_type: 0x01 + data: [0x10, 0x20, 0x30] + - platform: template + name: ABBWelcome lambda + on_press: + remote_transmitter.transmit_abbwelcome: + source_address: 0x1234 + destination_address: 0x5678 + message_type: 0x01 + data: !lambda |- + return {(uint8_t)id(test_number).state, 0x20, 0x30}; - platform: template name: Digital Write on_press: