From f4d32c7def97506ca93595280a35228f6d977c93 Mon Sep 17 00:00:00 2001 From: "J. Nick Koston" Date: Wed, 29 Oct 2025 16:08:27 -0500 Subject: [PATCH 1/5] relo --- .../binary_sensor/template_binary_sensor.h | 2 +- .../template/cover/template_cover.h | 2 +- .../template/datetime/template_date.h | 2 +- .../template/datetime/template_datetime.h | 2 +- .../template/datetime/template_time.h | 2 +- .../components/template/lock/template_lock.h | 2 +- .../template/number/template_number.h | 2 +- .../template/select/template_select.h | 2 +- .../template/sensor/template_sensor.h | 2 +- .../template/switch/template_switch.h | 2 +- esphome/components/template/template_lambda.h | 51 ++++++++ .../components/template/text/template_text.h | 2 +- .../text_sensor/template_text_sensor.h | 2 +- .../template/valve/template_valve.h | 2 +- esphome/core/template_lambda.h | 120 ------------------ tests/components/template/common-base.yaml | 16 +-- 16 files changed, 65 insertions(+), 148 deletions(-) create mode 100644 esphome/components/template/template_lambda.h delete mode 100644 esphome/core/template_lambda.h diff --git a/esphome/components/template/binary_sensor/template_binary_sensor.h b/esphome/components/template/binary_sensor/template_binary_sensor.h index 0373f898a8..f63738d93f 100644 --- a/esphome/components/template/binary_sensor/template_binary_sensor.h +++ b/esphome/components/template/binary_sensor/template_binary_sensor.h @@ -1,7 +1,7 @@ #pragma once #include "esphome/core/component.h" -#include "esphome/core/template_lambda.h" +#include "../template_lambda.h" #include "esphome/components/binary_sensor/binary_sensor.h" namespace esphome { diff --git a/esphome/components/template/cover/template_cover.h b/esphome/components/template/cover/template_cover.h index 56ab61c3fb..57a5e11c5c 100644 --- a/esphome/components/template/cover/template_cover.h +++ b/esphome/components/template/cover/template_cover.h @@ -2,7 +2,7 @@ #include "esphome/core/component.h" #include "esphome/core/automation.h" -#include "esphome/core/template_lambda.h" +#include "../template_lambda.h" #include "esphome/components/cover/cover.h" namespace esphome { diff --git a/esphome/components/template/datetime/template_date.h b/esphome/components/template/datetime/template_date.h index 7fed704d0e..b0fdbcbfbb 100644 --- a/esphome/components/template/datetime/template_date.h +++ b/esphome/components/template/datetime/template_date.h @@ -9,7 +9,7 @@ #include "esphome/core/component.h" #include "esphome/core/preferences.h" #include "esphome/core/time.h" -#include "esphome/core/template_lambda.h" +#include "../template_lambda.h" namespace esphome { namespace template_ { diff --git a/esphome/components/template/datetime/template_datetime.h b/esphome/components/template/datetime/template_datetime.h index ec45bf0326..b1c94d7d34 100644 --- a/esphome/components/template/datetime/template_datetime.h +++ b/esphome/components/template/datetime/template_datetime.h @@ -9,7 +9,7 @@ #include "esphome/core/component.h" #include "esphome/core/preferences.h" #include "esphome/core/time.h" -#include "esphome/core/template_lambda.h" +#include "../template_lambda.h" namespace esphome { namespace template_ { diff --git a/esphome/components/template/datetime/template_time.h b/esphome/components/template/datetime/template_time.h index ea7474c0ba..c6938fe7a0 100644 --- a/esphome/components/template/datetime/template_time.h +++ b/esphome/components/template/datetime/template_time.h @@ -9,7 +9,7 @@ #include "esphome/core/component.h" #include "esphome/core/preferences.h" #include "esphome/core/time.h" -#include "esphome/core/template_lambda.h" +#include "../template_lambda.h" namespace esphome { namespace template_ { diff --git a/esphome/components/template/lock/template_lock.h b/esphome/components/template/lock/template_lock.h index 347c4effb3..2bb11bfef6 100644 --- a/esphome/components/template/lock/template_lock.h +++ b/esphome/components/template/lock/template_lock.h @@ -2,7 +2,7 @@ #include "esphome/core/component.h" #include "esphome/core/automation.h" -#include "esphome/core/template_lambda.h" +#include "../template_lambda.h" #include "esphome/components/lock/lock.h" namespace esphome { diff --git a/esphome/components/template/number/template_number.h b/esphome/components/template/number/template_number.h index a9307e9246..1a6e9d964f 100644 --- a/esphome/components/template/number/template_number.h +++ b/esphome/components/template/number/template_number.h @@ -4,7 +4,7 @@ #include "esphome/core/automation.h" #include "esphome/core/component.h" #include "esphome/core/preferences.h" -#include "esphome/core/template_lambda.h" +#include "../template_lambda.h" namespace esphome { namespace template_ { diff --git a/esphome/components/template/select/template_select.h b/esphome/components/template/select/template_select.h index 1c33153872..53cadfa303 100644 --- a/esphome/components/template/select/template_select.h +++ b/esphome/components/template/select/template_select.h @@ -4,7 +4,7 @@ #include "esphome/core/automation.h" #include "esphome/core/component.h" #include "esphome/core/preferences.h" -#include "esphome/core/template_lambda.h" +#include "../template_lambda.h" namespace esphome { namespace template_ { diff --git a/esphome/components/template/sensor/template_sensor.h b/esphome/components/template/sensor/template_sensor.h index 793d754a0f..27980414f9 100644 --- a/esphome/components/template/sensor/template_sensor.h +++ b/esphome/components/template/sensor/template_sensor.h @@ -1,7 +1,7 @@ #pragma once #include "esphome/core/component.h" -#include "esphome/core/template_lambda.h" +#include "../template_lambda.h" #include "esphome/components/sensor/sensor.h" namespace esphome { diff --git a/esphome/components/template/switch/template_switch.h b/esphome/components/template/switch/template_switch.h index 47154fd047..f436f657ae 100644 --- a/esphome/components/template/switch/template_switch.h +++ b/esphome/components/template/switch/template_switch.h @@ -2,7 +2,7 @@ #include "esphome/core/component.h" #include "esphome/core/automation.h" -#include "esphome/core/template_lambda.h" +#include "../template_lambda.h" #include "esphome/components/switch/switch.h" namespace esphome { diff --git a/esphome/components/template/template_lambda.h b/esphome/components/template/template_lambda.h new file mode 100644 index 0000000000..894b5edffa --- /dev/null +++ b/esphome/components/template/template_lambda.h @@ -0,0 +1,51 @@ +#pragma once + +#include "esphome/core/optional.h" + +namespace esphome { + +/** Lightweight wrapper for template platform lambdas (stateless function pointers only). + * + * This optimizes template platforms by storing only a function pointer (4 bytes on ESP32) + * instead of std::function (16-32 bytes). + * + * IMPORTANT: This only supports stateless lambdas (no captures). The set_template() method + * is an internal API used by YAML codegen, not intended for external use. + * + * Lambdas must return optional to support the pattern: + * return {}; // Don't publish a value + * return 42.0; // Publish this value + * + * operator() returns optional, returning nullopt when no lambda is set (nullptr check). + * + * @tparam T The return type (e.g., float for sensor values) + * @tparam Args Optional arguments for the lambda + */ +template class TemplateLambda { + public: + TemplateLambda() : f_(nullptr) {} + + /** Set the lambda function pointer. + * INTERNAL API: Only for use by YAML codegen. + * Only stateless lambdas (no captures) are supported. + */ + void set(optional (*f)(Args...)) { this->f_ = f; } + + /** Check if a lambda is set */ + bool has_value() const { return this->f_ != nullptr; } + + /** Call the lambda, returning nullopt if no lambda is set */ + optional operator()(Args... args) { + if (this->f_ == nullptr) + return nullopt; + return this->f_(args...); + } + + /** Alias for operator() for compatibility */ + optional call(Args... args) { return (*this)(args...); } + + protected: + optional (*f_)(Args...); // Function pointer (4 bytes on ESP32) +}; + +} // namespace esphome diff --git a/esphome/components/template/text/template_text.h b/esphome/components/template/text/template_text.h index c12021f80e..fd28800bab 100644 --- a/esphome/components/template/text/template_text.h +++ b/esphome/components/template/text/template_text.h @@ -4,7 +4,7 @@ #include "esphome/core/automation.h" #include "esphome/core/component.h" #include "esphome/core/preferences.h" -#include "esphome/core/template_lambda.h" +#include "../template_lambda.h" namespace esphome { namespace template_ { diff --git a/esphome/components/template/text_sensor/template_text_sensor.h b/esphome/components/template/text_sensor/template_text_sensor.h index 0d01c72023..fda28f53c7 100644 --- a/esphome/components/template/text_sensor/template_text_sensor.h +++ b/esphome/components/template/text_sensor/template_text_sensor.h @@ -2,7 +2,7 @@ #include "esphome/core/component.h" #include "esphome/core/automation.h" -#include "esphome/core/template_lambda.h" +#include "../template_lambda.h" #include "esphome/components/text_sensor/text_sensor.h" namespace esphome { diff --git a/esphome/components/template/valve/template_valve.h b/esphome/components/template/valve/template_valve.h index 23a77ff918..7713091673 100644 --- a/esphome/components/template/valve/template_valve.h +++ b/esphome/components/template/valve/template_valve.h @@ -2,7 +2,7 @@ #include "esphome/core/component.h" #include "esphome/core/automation.h" -#include "esphome/core/template_lambda.h" +#include "../template_lambda.h" #include "esphome/components/valve/valve.h" namespace esphome { diff --git a/esphome/core/template_lambda.h b/esphome/core/template_lambda.h deleted file mode 100644 index 1977265c33..0000000000 --- a/esphome/core/template_lambda.h +++ /dev/null @@ -1,120 +0,0 @@ -#pragma once - -#include -#include -#include "esphome/core/optional.h" - -namespace esphome { - -/** Helper class for template platforms that stores either a stateless lambda (function pointer) - * or a stateful lambda (std::function pointer). - * - * This provides backward compatibility with PR #11555 while maintaining the optimization: - * - Stateless lambdas (no capture) → function pointer (4 bytes on ESP32) - * - Stateful lambdas (with capture) → pointer to std::function (4 bytes on ESP32) - * Total size: enum (1 byte) + union (4 bytes) + padding = 8 bytes (same as PR #11555) - * - * Both lambda types must return optional (as YAML codegen does) to support the pattern: - * return {}; // Don't publish a value - * return 42.0; // Publish this value - * - * operator() returns optional, returning nullopt when no lambda is set (type == NONE). - * This eliminates redundant "is lambda set" checks by reusing optional's discriminator. - * - * @tparam T The return type (e.g., float for TemplateLambda>) - * @tparam Args Optional arguments for the lambda - */ -template class TemplateLambda { - public: - TemplateLambda() : type_(NONE) {} - - // For stateless lambdas: use function pointer - template - requires std::invocable && std::convertible_to < F, optional(*) - (Args...) > void set(F f) { - this->reset_(); - this->type_ = STATELESS_LAMBDA; - this->stateless_f_ = f; // Implicit conversion to function pointer - } - - // For stateful lambdas: use std::function pointer - template - requires std::invocable && - (!std::convertible_to (*)(Args...)>) &&std::convertible_to, - optional> void set(F &&f) { - this->reset_(); - this->type_ = LAMBDA; - this->f_ = new std::function(Args...)>(std::forward(f)); - } - - ~TemplateLambda() { this->reset_(); } - - // Copy constructor - TemplateLambda(const TemplateLambda &) = delete; - TemplateLambda &operator=(const TemplateLambda &) = delete; - - // Move constructor - TemplateLambda(TemplateLambda &&other) noexcept : type_(other.type_) { - if (type_ == LAMBDA) { - this->f_ = other.f_; - other.f_ = nullptr; - } else if (type_ == STATELESS_LAMBDA) { - this->stateless_f_ = other.stateless_f_; - } - other.type_ = NONE; - } - - TemplateLambda &operator=(TemplateLambda &&other) noexcept { - if (this != &other) { - this->reset_(); - this->type_ = other.type_; - if (type_ == LAMBDA) { - this->f_ = other.f_; - other.f_ = nullptr; - } else if (type_ == STATELESS_LAMBDA) { - this->stateless_f_ = other.stateless_f_; - } - other.type_ = NONE; - } - return *this; - } - - bool has_value() const { return this->type_ != NONE; } - - // Returns optional, returning nullopt if no lambda is set - optional operator()(Args... args) { - switch (this->type_) { - case STATELESS_LAMBDA: - return this->stateless_f_(args...); // Direct function pointer call - case LAMBDA: - return (*this->f_)(args...); // std::function call via pointer - case NONE: - default: - return nullopt; // No lambda set - } - } - - optional call(Args... args) { return (*this)(args...); } - - protected: - void reset_() { - if (this->type_ == LAMBDA) { - delete this->f_; - this->f_ = nullptr; - } - this->type_ = NONE; - } - - enum : uint8_t { - NONE, - STATELESS_LAMBDA, - LAMBDA, - } type_; - - union { - optional (*stateless_f_)(Args...); // Function pointer (4 bytes on ESP32) - std::function(Args...)> *f_; // Pointer to std::function (4 bytes on ESP32) - }; -}; - -} // namespace esphome diff --git a/tests/components/template/common-base.yaml b/tests/components/template/common-base.yaml index 7d2cb19077..da449111a2 100644 --- a/tests/components/template/common-base.yaml +++ b/tests/components/template/common-base.yaml @@ -10,26 +10,12 @@ esphome: state: !lambda "return 42.0;" # Test C++ API: set_template() with stateless lambda (no captures) + # IMPORTANT: set_template() is an internal API. Only stateless lambdas are supported. - lambda: |- id(template_sens).set_template([]() -> esphome::optional { return 123.0f; }); - # Test C++ API: set_template() with stateful lambda (with captures) - # This is the regression test for issue #11555 - - lambda: |- - float captured_value = 456.0f; - id(template_sens).set_template([captured_value]() -> esphome::optional { - return captured_value; - }); - - # Test C++ API: set_template() with more complex capture - - lambda: |- - auto sensor_id = id(template_sens); - id(template_number).set_template([sensor_id]() -> esphome::optional { - return sensor_id->state * 2.0f; - }); - - datetime.date.set: id: test_date date: From a849ddd57d288d984dcd91c316104608a86a4b00 Mon Sep 17 00:00:00 2001 From: "J. Nick Koston" Date: Wed, 29 Oct 2025 16:10:32 -0500 Subject: [PATCH 2/5] wip --- .../binary_sensor/template_binary_sensor.h | 2 +- .../template/cover/template_cover.h | 2 +- .../template/datetime/template_date.h | 2 +- .../template/datetime/template_datetime.h | 2 +- .../template/datetime/template_time.h | 2 +- .../components/template/lock/template_lock.h | 2 +- .../template/number/template_number.h | 2 +- .../template/select/template_select.h | 2 +- .../template/sensor/template_sensor.h | 2 +- .../template/switch/template_switch.h | 2 +- esphome/components/template/template_lambda.h | 51 ------------------- .../components/template/text/template_text.h | 2 +- .../text_sensor/template_text_sensor.h | 2 +- .../template/valve/template_valve.h | 2 +- tests/components/template/common-base.yaml | 2 +- 15 files changed, 14 insertions(+), 65 deletions(-) delete mode 100644 esphome/components/template/template_lambda.h diff --git a/esphome/components/template/binary_sensor/template_binary_sensor.h b/esphome/components/template/binary_sensor/template_binary_sensor.h index f63738d93f..0373f898a8 100644 --- a/esphome/components/template/binary_sensor/template_binary_sensor.h +++ b/esphome/components/template/binary_sensor/template_binary_sensor.h @@ -1,7 +1,7 @@ #pragma once #include "esphome/core/component.h" -#include "../template_lambda.h" +#include "esphome/core/template_lambda.h" #include "esphome/components/binary_sensor/binary_sensor.h" namespace esphome { diff --git a/esphome/components/template/cover/template_cover.h b/esphome/components/template/cover/template_cover.h index 57a5e11c5c..56ab61c3fb 100644 --- a/esphome/components/template/cover/template_cover.h +++ b/esphome/components/template/cover/template_cover.h @@ -2,7 +2,7 @@ #include "esphome/core/component.h" #include "esphome/core/automation.h" -#include "../template_lambda.h" +#include "esphome/core/template_lambda.h" #include "esphome/components/cover/cover.h" namespace esphome { diff --git a/esphome/components/template/datetime/template_date.h b/esphome/components/template/datetime/template_date.h index b0fdbcbfbb..7fed704d0e 100644 --- a/esphome/components/template/datetime/template_date.h +++ b/esphome/components/template/datetime/template_date.h @@ -9,7 +9,7 @@ #include "esphome/core/component.h" #include "esphome/core/preferences.h" #include "esphome/core/time.h" -#include "../template_lambda.h" +#include "esphome/core/template_lambda.h" namespace esphome { namespace template_ { diff --git a/esphome/components/template/datetime/template_datetime.h b/esphome/components/template/datetime/template_datetime.h index b1c94d7d34..ec45bf0326 100644 --- a/esphome/components/template/datetime/template_datetime.h +++ b/esphome/components/template/datetime/template_datetime.h @@ -9,7 +9,7 @@ #include "esphome/core/component.h" #include "esphome/core/preferences.h" #include "esphome/core/time.h" -#include "../template_lambda.h" +#include "esphome/core/template_lambda.h" namespace esphome { namespace template_ { diff --git a/esphome/components/template/datetime/template_time.h b/esphome/components/template/datetime/template_time.h index c6938fe7a0..ea7474c0ba 100644 --- a/esphome/components/template/datetime/template_time.h +++ b/esphome/components/template/datetime/template_time.h @@ -9,7 +9,7 @@ #include "esphome/core/component.h" #include "esphome/core/preferences.h" #include "esphome/core/time.h" -#include "../template_lambda.h" +#include "esphome/core/template_lambda.h" namespace esphome { namespace template_ { diff --git a/esphome/components/template/lock/template_lock.h b/esphome/components/template/lock/template_lock.h index 2bb11bfef6..347c4effb3 100644 --- a/esphome/components/template/lock/template_lock.h +++ b/esphome/components/template/lock/template_lock.h @@ -2,7 +2,7 @@ #include "esphome/core/component.h" #include "esphome/core/automation.h" -#include "../template_lambda.h" +#include "esphome/core/template_lambda.h" #include "esphome/components/lock/lock.h" namespace esphome { diff --git a/esphome/components/template/number/template_number.h b/esphome/components/template/number/template_number.h index 1a6e9d964f..a9307e9246 100644 --- a/esphome/components/template/number/template_number.h +++ b/esphome/components/template/number/template_number.h @@ -4,7 +4,7 @@ #include "esphome/core/automation.h" #include "esphome/core/component.h" #include "esphome/core/preferences.h" -#include "../template_lambda.h" +#include "esphome/core/template_lambda.h" namespace esphome { namespace template_ { diff --git a/esphome/components/template/select/template_select.h b/esphome/components/template/select/template_select.h index 53cadfa303..1c33153872 100644 --- a/esphome/components/template/select/template_select.h +++ b/esphome/components/template/select/template_select.h @@ -4,7 +4,7 @@ #include "esphome/core/automation.h" #include "esphome/core/component.h" #include "esphome/core/preferences.h" -#include "../template_lambda.h" +#include "esphome/core/template_lambda.h" namespace esphome { namespace template_ { diff --git a/esphome/components/template/sensor/template_sensor.h b/esphome/components/template/sensor/template_sensor.h index 27980414f9..793d754a0f 100644 --- a/esphome/components/template/sensor/template_sensor.h +++ b/esphome/components/template/sensor/template_sensor.h @@ -1,7 +1,7 @@ #pragma once #include "esphome/core/component.h" -#include "../template_lambda.h" +#include "esphome/core/template_lambda.h" #include "esphome/components/sensor/sensor.h" namespace esphome { diff --git a/esphome/components/template/switch/template_switch.h b/esphome/components/template/switch/template_switch.h index f436f657ae..47154fd047 100644 --- a/esphome/components/template/switch/template_switch.h +++ b/esphome/components/template/switch/template_switch.h @@ -2,7 +2,7 @@ #include "esphome/core/component.h" #include "esphome/core/automation.h" -#include "../template_lambda.h" +#include "esphome/core/template_lambda.h" #include "esphome/components/switch/switch.h" namespace esphome { diff --git a/esphome/components/template/template_lambda.h b/esphome/components/template/template_lambda.h deleted file mode 100644 index 894b5edffa..0000000000 --- a/esphome/components/template/template_lambda.h +++ /dev/null @@ -1,51 +0,0 @@ -#pragma once - -#include "esphome/core/optional.h" - -namespace esphome { - -/** Lightweight wrapper for template platform lambdas (stateless function pointers only). - * - * This optimizes template platforms by storing only a function pointer (4 bytes on ESP32) - * instead of std::function (16-32 bytes). - * - * IMPORTANT: This only supports stateless lambdas (no captures). The set_template() method - * is an internal API used by YAML codegen, not intended for external use. - * - * Lambdas must return optional to support the pattern: - * return {}; // Don't publish a value - * return 42.0; // Publish this value - * - * operator() returns optional, returning nullopt when no lambda is set (nullptr check). - * - * @tparam T The return type (e.g., float for sensor values) - * @tparam Args Optional arguments for the lambda - */ -template class TemplateLambda { - public: - TemplateLambda() : f_(nullptr) {} - - /** Set the lambda function pointer. - * INTERNAL API: Only for use by YAML codegen. - * Only stateless lambdas (no captures) are supported. - */ - void set(optional (*f)(Args...)) { this->f_ = f; } - - /** Check if a lambda is set */ - bool has_value() const { return this->f_ != nullptr; } - - /** Call the lambda, returning nullopt if no lambda is set */ - optional operator()(Args... args) { - if (this->f_ == nullptr) - return nullopt; - return this->f_(args...); - } - - /** Alias for operator() for compatibility */ - optional call(Args... args) { return (*this)(args...); } - - protected: - optional (*f_)(Args...); // Function pointer (4 bytes on ESP32) -}; - -} // namespace esphome diff --git a/esphome/components/template/text/template_text.h b/esphome/components/template/text/template_text.h index fd28800bab..c12021f80e 100644 --- a/esphome/components/template/text/template_text.h +++ b/esphome/components/template/text/template_text.h @@ -4,7 +4,7 @@ #include "esphome/core/automation.h" #include "esphome/core/component.h" #include "esphome/core/preferences.h" -#include "../template_lambda.h" +#include "esphome/core/template_lambda.h" namespace esphome { namespace template_ { diff --git a/esphome/components/template/text_sensor/template_text_sensor.h b/esphome/components/template/text_sensor/template_text_sensor.h index fda28f53c7..0d01c72023 100644 --- a/esphome/components/template/text_sensor/template_text_sensor.h +++ b/esphome/components/template/text_sensor/template_text_sensor.h @@ -2,7 +2,7 @@ #include "esphome/core/component.h" #include "esphome/core/automation.h" -#include "../template_lambda.h" +#include "esphome/core/template_lambda.h" #include "esphome/components/text_sensor/text_sensor.h" namespace esphome { diff --git a/esphome/components/template/valve/template_valve.h b/esphome/components/template/valve/template_valve.h index 7713091673..23a77ff918 100644 --- a/esphome/components/template/valve/template_valve.h +++ b/esphome/components/template/valve/template_valve.h @@ -2,7 +2,7 @@ #include "esphome/core/component.h" #include "esphome/core/automation.h" -#include "../template_lambda.h" +#include "esphome/core/template_lambda.h" #include "esphome/components/valve/valve.h" namespace esphome { diff --git a/tests/components/template/common-base.yaml b/tests/components/template/common-base.yaml index da449111a2..f101eea942 100644 --- a/tests/components/template/common-base.yaml +++ b/tests/components/template/common-base.yaml @@ -10,7 +10,7 @@ esphome: state: !lambda "return 42.0;" # Test C++ API: set_template() with stateless lambda (no captures) - # IMPORTANT: set_template() is an internal API. Only stateless lambdas are supported. + # NOTE: set_template() is not intended to be a public API, but we test it to ensure it doesn't break. - lambda: |- id(template_sens).set_template([]() -> esphome::optional { return 123.0f; From 922acda1a808235c8c252c156d4374a53c3e2e7c Mon Sep 17 00:00:00 2001 From: "J. Nick Koston" Date: Wed, 29 Oct 2025 16:12:05 -0500 Subject: [PATCH 3/5] wip --- esphome/core/template_lambda.h | 51 ++++++++++++++++++++++++++++++++++ 1 file changed, 51 insertions(+) create mode 100644 esphome/core/template_lambda.h diff --git a/esphome/core/template_lambda.h b/esphome/core/template_lambda.h new file mode 100644 index 0000000000..894b5edffa --- /dev/null +++ b/esphome/core/template_lambda.h @@ -0,0 +1,51 @@ +#pragma once + +#include "esphome/core/optional.h" + +namespace esphome { + +/** Lightweight wrapper for template platform lambdas (stateless function pointers only). + * + * This optimizes template platforms by storing only a function pointer (4 bytes on ESP32) + * instead of std::function (16-32 bytes). + * + * IMPORTANT: This only supports stateless lambdas (no captures). The set_template() method + * is an internal API used by YAML codegen, not intended for external use. + * + * Lambdas must return optional to support the pattern: + * return {}; // Don't publish a value + * return 42.0; // Publish this value + * + * operator() returns optional, returning nullopt when no lambda is set (nullptr check). + * + * @tparam T The return type (e.g., float for sensor values) + * @tparam Args Optional arguments for the lambda + */ +template class TemplateLambda { + public: + TemplateLambda() : f_(nullptr) {} + + /** Set the lambda function pointer. + * INTERNAL API: Only for use by YAML codegen. + * Only stateless lambdas (no captures) are supported. + */ + void set(optional (*f)(Args...)) { this->f_ = f; } + + /** Check if a lambda is set */ + bool has_value() const { return this->f_ != nullptr; } + + /** Call the lambda, returning nullopt if no lambda is set */ + optional operator()(Args... args) { + if (this->f_ == nullptr) + return nullopt; + return this->f_(args...); + } + + /** Alias for operator() for compatibility */ + optional call(Args... args) { return (*this)(args...); } + + protected: + optional (*f_)(Args...); // Function pointer (4 bytes on ESP32) +}; + +} // namespace esphome From 68d1a7e3effc93411549924234cedb6e6ef64ef8 Mon Sep 17 00:00:00 2001 From: "J. Nick Koston" Date: Wed, 29 Oct 2025 16:15:15 -0500 Subject: [PATCH 4/5] wip --- .../components/template/binary_sensor/template_binary_sensor.h | 2 +- esphome/components/template/cover/template_cover.h | 2 +- esphome/components/template/datetime/template_date.h | 2 +- esphome/components/template/datetime/template_datetime.h | 2 +- esphome/components/template/datetime/template_time.h | 2 +- esphome/components/template/lock/template_lock.h | 2 +- esphome/components/template/number/template_number.h | 2 +- esphome/components/template/select/template_select.h | 2 +- esphome/components/template/sensor/template_sensor.h | 2 +- esphome/components/template/switch/template_switch.h | 2 +- esphome/{core => components/template}/template_lambda.h | 0 esphome/components/template/text/template_text.h | 2 +- esphome/components/template/text_sensor/template_text_sensor.h | 2 +- esphome/components/template/valve/template_valve.h | 2 +- 14 files changed, 13 insertions(+), 13 deletions(-) rename esphome/{core => components/template}/template_lambda.h (100%) diff --git a/esphome/components/template/binary_sensor/template_binary_sensor.h b/esphome/components/template/binary_sensor/template_binary_sensor.h index 0373f898a8..f63738d93f 100644 --- a/esphome/components/template/binary_sensor/template_binary_sensor.h +++ b/esphome/components/template/binary_sensor/template_binary_sensor.h @@ -1,7 +1,7 @@ #pragma once #include "esphome/core/component.h" -#include "esphome/core/template_lambda.h" +#include "../template_lambda.h" #include "esphome/components/binary_sensor/binary_sensor.h" namespace esphome { diff --git a/esphome/components/template/cover/template_cover.h b/esphome/components/template/cover/template_cover.h index 56ab61c3fb..57a5e11c5c 100644 --- a/esphome/components/template/cover/template_cover.h +++ b/esphome/components/template/cover/template_cover.h @@ -2,7 +2,7 @@ #include "esphome/core/component.h" #include "esphome/core/automation.h" -#include "esphome/core/template_lambda.h" +#include "../template_lambda.h" #include "esphome/components/cover/cover.h" namespace esphome { diff --git a/esphome/components/template/datetime/template_date.h b/esphome/components/template/datetime/template_date.h index 7fed704d0e..b0fdbcbfbb 100644 --- a/esphome/components/template/datetime/template_date.h +++ b/esphome/components/template/datetime/template_date.h @@ -9,7 +9,7 @@ #include "esphome/core/component.h" #include "esphome/core/preferences.h" #include "esphome/core/time.h" -#include "esphome/core/template_lambda.h" +#include "../template_lambda.h" namespace esphome { namespace template_ { diff --git a/esphome/components/template/datetime/template_datetime.h b/esphome/components/template/datetime/template_datetime.h index ec45bf0326..b1c94d7d34 100644 --- a/esphome/components/template/datetime/template_datetime.h +++ b/esphome/components/template/datetime/template_datetime.h @@ -9,7 +9,7 @@ #include "esphome/core/component.h" #include "esphome/core/preferences.h" #include "esphome/core/time.h" -#include "esphome/core/template_lambda.h" +#include "../template_lambda.h" namespace esphome { namespace template_ { diff --git a/esphome/components/template/datetime/template_time.h b/esphome/components/template/datetime/template_time.h index ea7474c0ba..c6938fe7a0 100644 --- a/esphome/components/template/datetime/template_time.h +++ b/esphome/components/template/datetime/template_time.h @@ -9,7 +9,7 @@ #include "esphome/core/component.h" #include "esphome/core/preferences.h" #include "esphome/core/time.h" -#include "esphome/core/template_lambda.h" +#include "../template_lambda.h" namespace esphome { namespace template_ { diff --git a/esphome/components/template/lock/template_lock.h b/esphome/components/template/lock/template_lock.h index 347c4effb3..2bb11bfef6 100644 --- a/esphome/components/template/lock/template_lock.h +++ b/esphome/components/template/lock/template_lock.h @@ -2,7 +2,7 @@ #include "esphome/core/component.h" #include "esphome/core/automation.h" -#include "esphome/core/template_lambda.h" +#include "../template_lambda.h" #include "esphome/components/lock/lock.h" namespace esphome { diff --git a/esphome/components/template/number/template_number.h b/esphome/components/template/number/template_number.h index a9307e9246..1a6e9d964f 100644 --- a/esphome/components/template/number/template_number.h +++ b/esphome/components/template/number/template_number.h @@ -4,7 +4,7 @@ #include "esphome/core/automation.h" #include "esphome/core/component.h" #include "esphome/core/preferences.h" -#include "esphome/core/template_lambda.h" +#include "../template_lambda.h" namespace esphome { namespace template_ { diff --git a/esphome/components/template/select/template_select.h b/esphome/components/template/select/template_select.h index 1c33153872..53cadfa303 100644 --- a/esphome/components/template/select/template_select.h +++ b/esphome/components/template/select/template_select.h @@ -4,7 +4,7 @@ #include "esphome/core/automation.h" #include "esphome/core/component.h" #include "esphome/core/preferences.h" -#include "esphome/core/template_lambda.h" +#include "../template_lambda.h" namespace esphome { namespace template_ { diff --git a/esphome/components/template/sensor/template_sensor.h b/esphome/components/template/sensor/template_sensor.h index 793d754a0f..27980414f9 100644 --- a/esphome/components/template/sensor/template_sensor.h +++ b/esphome/components/template/sensor/template_sensor.h @@ -1,7 +1,7 @@ #pragma once #include "esphome/core/component.h" -#include "esphome/core/template_lambda.h" +#include "../template_lambda.h" #include "esphome/components/sensor/sensor.h" namespace esphome { diff --git a/esphome/components/template/switch/template_switch.h b/esphome/components/template/switch/template_switch.h index 47154fd047..f436f657ae 100644 --- a/esphome/components/template/switch/template_switch.h +++ b/esphome/components/template/switch/template_switch.h @@ -2,7 +2,7 @@ #include "esphome/core/component.h" #include "esphome/core/automation.h" -#include "esphome/core/template_lambda.h" +#include "../template_lambda.h" #include "esphome/components/switch/switch.h" namespace esphome { diff --git a/esphome/core/template_lambda.h b/esphome/components/template/template_lambda.h similarity index 100% rename from esphome/core/template_lambda.h rename to esphome/components/template/template_lambda.h diff --git a/esphome/components/template/text/template_text.h b/esphome/components/template/text/template_text.h index c12021f80e..fd28800bab 100644 --- a/esphome/components/template/text/template_text.h +++ b/esphome/components/template/text/template_text.h @@ -4,7 +4,7 @@ #include "esphome/core/automation.h" #include "esphome/core/component.h" #include "esphome/core/preferences.h" -#include "esphome/core/template_lambda.h" +#include "../template_lambda.h" namespace esphome { namespace template_ { diff --git a/esphome/components/template/text_sensor/template_text_sensor.h b/esphome/components/template/text_sensor/template_text_sensor.h index 0d01c72023..fda28f53c7 100644 --- a/esphome/components/template/text_sensor/template_text_sensor.h +++ b/esphome/components/template/text_sensor/template_text_sensor.h @@ -2,7 +2,7 @@ #include "esphome/core/component.h" #include "esphome/core/automation.h" -#include "esphome/core/template_lambda.h" +#include "../template_lambda.h" #include "esphome/components/text_sensor/text_sensor.h" namespace esphome { diff --git a/esphome/components/template/valve/template_valve.h b/esphome/components/template/valve/template_valve.h index 23a77ff918..7713091673 100644 --- a/esphome/components/template/valve/template_valve.h +++ b/esphome/components/template/valve/template_valve.h @@ -2,7 +2,7 @@ #include "esphome/core/component.h" #include "esphome/core/automation.h" -#include "esphome/core/template_lambda.h" +#include "../template_lambda.h" #include "esphome/components/valve/valve.h" namespace esphome { From 5478fa69e9c550c18a54bdfa3f83e7a9b0ef2c10 Mon Sep 17 00:00:00 2001 From: "J. Nick Koston" Date: Wed, 29 Oct 2025 16:20:11 -0500 Subject: [PATCH 5/5] twip --- .../components/template/binary_sensor/template_binary_sensor.h | 2 +- esphome/components/template/cover/template_cover.h | 2 +- esphome/components/template/datetime/template_date.h | 2 +- esphome/components/template/datetime/template_datetime.h | 2 +- esphome/components/template/datetime/template_time.h | 2 +- esphome/components/template/lock/template_lock.h | 2 +- esphome/components/template/number/template_number.h | 2 +- esphome/components/template/select/template_select.h | 2 +- esphome/components/template/sensor/template_sensor.h | 2 +- esphome/components/template/switch/template_switch.h | 2 +- esphome/components/template/text/template_text.h | 2 +- esphome/components/template/text_sensor/template_text_sensor.h | 2 +- esphome/components/template/valve/template_valve.h | 2 +- esphome/{components/template => core}/template_lambda.h | 0 14 files changed, 13 insertions(+), 13 deletions(-) rename esphome/{components/template => core}/template_lambda.h (100%) diff --git a/esphome/components/template/binary_sensor/template_binary_sensor.h b/esphome/components/template/binary_sensor/template_binary_sensor.h index f63738d93f..0373f898a8 100644 --- a/esphome/components/template/binary_sensor/template_binary_sensor.h +++ b/esphome/components/template/binary_sensor/template_binary_sensor.h @@ -1,7 +1,7 @@ #pragma once #include "esphome/core/component.h" -#include "../template_lambda.h" +#include "esphome/core/template_lambda.h" #include "esphome/components/binary_sensor/binary_sensor.h" namespace esphome { diff --git a/esphome/components/template/cover/template_cover.h b/esphome/components/template/cover/template_cover.h index 57a5e11c5c..56ab61c3fb 100644 --- a/esphome/components/template/cover/template_cover.h +++ b/esphome/components/template/cover/template_cover.h @@ -2,7 +2,7 @@ #include "esphome/core/component.h" #include "esphome/core/automation.h" -#include "../template_lambda.h" +#include "esphome/core/template_lambda.h" #include "esphome/components/cover/cover.h" namespace esphome { diff --git a/esphome/components/template/datetime/template_date.h b/esphome/components/template/datetime/template_date.h index b0fdbcbfbb..7fed704d0e 100644 --- a/esphome/components/template/datetime/template_date.h +++ b/esphome/components/template/datetime/template_date.h @@ -9,7 +9,7 @@ #include "esphome/core/component.h" #include "esphome/core/preferences.h" #include "esphome/core/time.h" -#include "../template_lambda.h" +#include "esphome/core/template_lambda.h" namespace esphome { namespace template_ { diff --git a/esphome/components/template/datetime/template_datetime.h b/esphome/components/template/datetime/template_datetime.h index b1c94d7d34..ec45bf0326 100644 --- a/esphome/components/template/datetime/template_datetime.h +++ b/esphome/components/template/datetime/template_datetime.h @@ -9,7 +9,7 @@ #include "esphome/core/component.h" #include "esphome/core/preferences.h" #include "esphome/core/time.h" -#include "../template_lambda.h" +#include "esphome/core/template_lambda.h" namespace esphome { namespace template_ { diff --git a/esphome/components/template/datetime/template_time.h b/esphome/components/template/datetime/template_time.h index c6938fe7a0..ea7474c0ba 100644 --- a/esphome/components/template/datetime/template_time.h +++ b/esphome/components/template/datetime/template_time.h @@ -9,7 +9,7 @@ #include "esphome/core/component.h" #include "esphome/core/preferences.h" #include "esphome/core/time.h" -#include "../template_lambda.h" +#include "esphome/core/template_lambda.h" namespace esphome { namespace template_ { diff --git a/esphome/components/template/lock/template_lock.h b/esphome/components/template/lock/template_lock.h index 2bb11bfef6..347c4effb3 100644 --- a/esphome/components/template/lock/template_lock.h +++ b/esphome/components/template/lock/template_lock.h @@ -2,7 +2,7 @@ #include "esphome/core/component.h" #include "esphome/core/automation.h" -#include "../template_lambda.h" +#include "esphome/core/template_lambda.h" #include "esphome/components/lock/lock.h" namespace esphome { diff --git a/esphome/components/template/number/template_number.h b/esphome/components/template/number/template_number.h index 1a6e9d964f..a9307e9246 100644 --- a/esphome/components/template/number/template_number.h +++ b/esphome/components/template/number/template_number.h @@ -4,7 +4,7 @@ #include "esphome/core/automation.h" #include "esphome/core/component.h" #include "esphome/core/preferences.h" -#include "../template_lambda.h" +#include "esphome/core/template_lambda.h" namespace esphome { namespace template_ { diff --git a/esphome/components/template/select/template_select.h b/esphome/components/template/select/template_select.h index 53cadfa303..1c33153872 100644 --- a/esphome/components/template/select/template_select.h +++ b/esphome/components/template/select/template_select.h @@ -4,7 +4,7 @@ #include "esphome/core/automation.h" #include "esphome/core/component.h" #include "esphome/core/preferences.h" -#include "../template_lambda.h" +#include "esphome/core/template_lambda.h" namespace esphome { namespace template_ { diff --git a/esphome/components/template/sensor/template_sensor.h b/esphome/components/template/sensor/template_sensor.h index 27980414f9..793d754a0f 100644 --- a/esphome/components/template/sensor/template_sensor.h +++ b/esphome/components/template/sensor/template_sensor.h @@ -1,7 +1,7 @@ #pragma once #include "esphome/core/component.h" -#include "../template_lambda.h" +#include "esphome/core/template_lambda.h" #include "esphome/components/sensor/sensor.h" namespace esphome { diff --git a/esphome/components/template/switch/template_switch.h b/esphome/components/template/switch/template_switch.h index f436f657ae..47154fd047 100644 --- a/esphome/components/template/switch/template_switch.h +++ b/esphome/components/template/switch/template_switch.h @@ -2,7 +2,7 @@ #include "esphome/core/component.h" #include "esphome/core/automation.h" -#include "../template_lambda.h" +#include "esphome/core/template_lambda.h" #include "esphome/components/switch/switch.h" namespace esphome { diff --git a/esphome/components/template/text/template_text.h b/esphome/components/template/text/template_text.h index fd28800bab..c12021f80e 100644 --- a/esphome/components/template/text/template_text.h +++ b/esphome/components/template/text/template_text.h @@ -4,7 +4,7 @@ #include "esphome/core/automation.h" #include "esphome/core/component.h" #include "esphome/core/preferences.h" -#include "../template_lambda.h" +#include "esphome/core/template_lambda.h" namespace esphome { namespace template_ { diff --git a/esphome/components/template/text_sensor/template_text_sensor.h b/esphome/components/template/text_sensor/template_text_sensor.h index fda28f53c7..0d01c72023 100644 --- a/esphome/components/template/text_sensor/template_text_sensor.h +++ b/esphome/components/template/text_sensor/template_text_sensor.h @@ -2,7 +2,7 @@ #include "esphome/core/component.h" #include "esphome/core/automation.h" -#include "../template_lambda.h" +#include "esphome/core/template_lambda.h" #include "esphome/components/text_sensor/text_sensor.h" namespace esphome { diff --git a/esphome/components/template/valve/template_valve.h b/esphome/components/template/valve/template_valve.h index 7713091673..23a77ff918 100644 --- a/esphome/components/template/valve/template_valve.h +++ b/esphome/components/template/valve/template_valve.h @@ -2,7 +2,7 @@ #include "esphome/core/component.h" #include "esphome/core/automation.h" -#include "../template_lambda.h" +#include "esphome/core/template_lambda.h" #include "esphome/components/valve/valve.h" namespace esphome { diff --git a/esphome/components/template/template_lambda.h b/esphome/core/template_lambda.h similarity index 100% rename from esphome/components/template/template_lambda.h rename to esphome/core/template_lambda.h