1
0
mirror of https://github.com/esphome/esphome.git synced 2025-11-18 15:55:46 +00:00

Merge branch 'integration' into memory_api

This commit is contained in:
J. Nick Koston
2025-11-08 23:43:35 -06:00
8 changed files with 88 additions and 90 deletions

View File

@@ -107,15 +107,14 @@ template<typename... Ts> class BLEClientWriteAction : public Action<Ts...>, publ
void set_char_uuid128(uint8_t *uuid) { this->char_uuid_ = espbt::ESPBTUUID::from_raw(uuid); } void set_char_uuid128(uint8_t *uuid) { this->char_uuid_ = espbt::ESPBTUUID::from_raw(uuid); }
void set_value_template(std::vector<uint8_t> (*func)(Ts...)) { void set_value_template(std::vector<uint8_t> (*func)(Ts...)) {
this->value_.template_func = func; this->value_.func = func;
this->has_simple_value_ = false; this->len_ = -1; // Sentinel value indicates template mode
} }
// Store pointer to static data in flash (no RAM copy) // Store pointer to static data in flash (no RAM copy)
void set_value_simple(const uint8_t *data, size_t len) { void set_value_simple(const uint8_t *data, size_t len) {
this->value_.simple_data.ptr = data; this->value_.data = data;
this->value_.simple_data.len = len; this->len_ = len; // Length >= 0 indicates static mode
this->has_simple_value_ = true;
} }
void play(const Ts &...x) override {} void play(const Ts &...x) override {}
@@ -124,10 +123,12 @@ template<typename... Ts> class BLEClientWriteAction : public Action<Ts...>, publ
this->num_running_++; this->num_running_++;
this->var_ = std::make_tuple(x...); this->var_ = std::make_tuple(x...);
std::vector<uint8_t> value; std::vector<uint8_t> value;
if (this->has_simple_value_) { if (this->len_ >= 0) {
value.assign(this->value_.simple_data.ptr, this->value_.simple_data.ptr + this->value_.simple_data.len); // Static mode: copy from flash to vector
value.assign(this->value_.data, this->value_.data + this->len_);
} else { } else {
value = this->value_.template_func(x...); // Template mode: call function
value = this->value_.func(x...);
} }
// on write failure, continue the automation chain rather than stopping so that e.g. disconnect can work. // on write failure, continue the automation chain rather than stopping so that e.g. disconnect can work.
if (!write(value)) if (!write(value))
@@ -202,13 +203,10 @@ template<typename... Ts> class BLEClientWriteAction : public Action<Ts...>, publ
private: private:
BLEClient *ble_client_; BLEClient *ble_client_;
bool has_simple_value_{true}; ssize_t len_{-1}; // -1 = template mode, >=0 = static mode with length
union Value { union Value {
std::vector<uint8_t> (*template_func)(Ts...); std::vector<uint8_t> (*func)(Ts...); // Function pointer (stateless lambdas)
struct { const uint8_t *data; // Pointer to static data in flash
const uint8_t *ptr;
size_t len;
} simple_data;
} value_; } value_;
espbt::ESPBTUUID service_uuid_; espbt::ESPBTUUID service_uuid_;
espbt::ESPBTUUID char_uuid_; espbt::ESPBTUUID char_uuid_;

View File

@@ -115,14 +115,13 @@ template<typename... Ts> class CanbusSendAction : public Action<Ts...>, public P
void set_data_template(std::vector<uint8_t> (*func)(Ts...)) { void set_data_template(std::vector<uint8_t> (*func)(Ts...)) {
// Stateless lambdas (generated by ESPHome) implicitly convert to function pointers // Stateless lambdas (generated by ESPHome) implicitly convert to function pointers
this->data_.func = func; this->data_.func = func;
this->static_ = false; this->len_ = -1; // Sentinel value indicates template mode
} }
// Store pointer to static data in flash (no RAM copy) // Store pointer to static data in flash (no RAM copy)
void set_data_static(const uint8_t *data, size_t len) { void set_data_static(const uint8_t *data, size_t len) {
this->data_.static_data.ptr = data; this->data_.data = data;
this->data_.static_data.len = len; this->len_ = len; // Length >= 0 indicates static mode
this->static_ = true;
} }
void set_can_id(uint32_t can_id) { this->can_id_ = can_id; } void set_can_id(uint32_t can_id) { this->can_id_ = can_id; }
@@ -138,9 +137,11 @@ template<typename... Ts> class CanbusSendAction : public Action<Ts...>, public P
auto use_extended_id = auto use_extended_id =
this->use_extended_id_.has_value() ? *this->use_extended_id_ : this->parent_->use_extended_id_; this->use_extended_id_.has_value() ? *this->use_extended_id_ : this->parent_->use_extended_id_;
std::vector<uint8_t> data; std::vector<uint8_t> data;
if (this->static_) { if (this->len_ >= 0) {
data.assign(this->data_.static_data.ptr, this->data_.static_data.ptr + this->data_.static_data.len); // Static mode: copy from flash to vector
data.assign(this->data_.data, this->data_.data + this->len_);
} else { } else {
// Template mode: call function
data = this->data_.func(x...); data = this->data_.func(x...);
} }
this->parent_->send_data(can_id, use_extended_id, this->remote_transmission_request_, data); this->parent_->send_data(can_id, use_extended_id, this->remote_transmission_request_, data);
@@ -150,14 +151,11 @@ template<typename... Ts> class CanbusSendAction : public Action<Ts...>, public P
optional<uint32_t> can_id_{}; optional<uint32_t> can_id_{};
optional<bool> use_extended_id_{}; optional<bool> use_extended_id_{};
bool remote_transmission_request_{false}; bool remote_transmission_request_{false};
bool static_{true}; // Default to static mode (most common case) ssize_t len_{-1}; // -1 = template mode, >=0 = static mode with length
union Data { union Data {
std::vector<uint8_t> (*func)(Ts...); // 4 bytes on 32-bit std::vector<uint8_t> (*func)(Ts...); // Function pointer (stateless lambdas)
struct { const uint8_t *data; // Pointer to static data in flash
const uint8_t *ptr; // 4 bytes on 32-bit } data_;
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<std::vector<uint8_t>, uint32_t, bool>, public Component { class CanbusTrigger : public Trigger<std::vector<uint8_t>, uint32_t, bool>, public Component {

View File

@@ -42,17 +42,20 @@ class RawTrigger : public Trigger<RawTimings>, public Component, public RemoteRe
template<typename... Ts> class RawAction : public RemoteTransmitterActionBase<Ts...> { template<typename... Ts> class RawAction : public RemoteTransmitterActionBase<Ts...> {
public: public:
void set_code_template(std::function<RawTimings(Ts...)> func) { this->code_func_ = func; } void set_code_template(RawTimings (*func)(Ts...)) {
this->code_.func = func;
this->len_ = -1; // Sentinel value indicates template mode
}
void set_code_static(const int32_t *code, size_t len) { void set_code_static(const int32_t *code, size_t len) {
this->code_static_ = code; this->code_.data = code;
this->code_static_len_ = len; this->len_ = len; // Length >= 0 indicates static mode
} }
TEMPLATABLE_VALUE(uint32_t, carrier_frequency); TEMPLATABLE_VALUE(uint32_t, carrier_frequency);
void encode(RemoteTransmitData *dst, Ts... x) override { void encode(RemoteTransmitData *dst, Ts... x) override {
if (this->code_static_ != nullptr) { if (this->len_ >= 0) {
for (size_t i = 0; i < this->code_static_len_; i++) { for (size_t i = 0; i < static_cast<size_t>(this->len_); i++) {
auto val = this->code_static_[i]; auto val = this->code_.data[i];
if (val < 0) { if (val < 0) {
dst->space(static_cast<uint32_t>(-val)); dst->space(static_cast<uint32_t>(-val));
} else { } else {
@@ -60,15 +63,17 @@ template<typename... Ts> class RawAction : public RemoteTransmitterActionBase<Ts
} }
} }
} else { } else {
dst->set_data(this->code_func_(x...)); dst->set_data(this->code_.func(x...));
} }
dst->set_carrier_frequency(this->carrier_frequency_.value(x...)); dst->set_carrier_frequency(this->carrier_frequency_.value(x...));
} }
protected: protected:
std::function<RawTimings(Ts...)> code_func_{nullptr}; ssize_t len_{-1}; // -1 = template mode, >=0 = static mode with length
const int32_t *code_static_{nullptr}; union Code {
int32_t code_static_len_{0}; RawTimings (*func)(Ts...);
const int32_t *data;
} code_;
}; };
class RawDumper : public RemoteReceiverDumperBase { class RawDumper : public RemoteReceiverDumperBase {

View File

@@ -16,33 +16,31 @@ template<typename... Ts> class SendPacketAction : public Action<Ts...>, public P
public: public:
void set_data_template(std::vector<uint8_t> (*func)(Ts...)) { void set_data_template(std::vector<uint8_t> (*func)(Ts...)) {
this->data_.func = func; this->data_.func = func;
this->static_ = false; this->len_ = -1; // Sentinel value indicates template mode
} }
void set_data_static(const uint8_t *data, size_t len) { void set_data_static(const uint8_t *data, size_t len) {
this->data_.static_data.ptr = data; this->data_.data = data;
this->data_.static_data.len = len; this->len_ = len; // Length >= 0 indicates static mode
this->static_ = true;
} }
void play(const Ts &...x) override { void play(const Ts &...x) override {
std::vector<uint8_t> data; std::vector<uint8_t> data;
if (this->static_) { if (this->len_ >= 0) {
data.assign(this->data_.static_data.ptr, this->data_.static_data.ptr + this->data_.static_data.len); // Static mode: copy from flash to vector
data.assign(this->data_.data, this->data_.data + this->len_);
} else { } else {
// Template mode: call function
data = this->data_.func(x...); data = this->data_.func(x...);
} }
this->parent_->transmit_packet(data); this->parent_->transmit_packet(data);
} }
protected: protected:
bool static_{true}; ssize_t len_{-1}; // -1 = template mode, >=0 = static mode with length
union Data { union Data {
std::vector<uint8_t> (*func)(Ts...); std::vector<uint8_t> (*func)(Ts...); // Function pointer (stateless lambdas)
struct { const uint8_t *data; // Pointer to static data in flash
const uint8_t *ptr;
size_t len;
} static_data;
} data_; } data_;
}; };

View File

@@ -16,33 +16,31 @@ template<typename... Ts> class SendPacketAction : public Action<Ts...>, public P
public: public:
void set_data_template(std::vector<uint8_t> (*func)(Ts...)) { void set_data_template(std::vector<uint8_t> (*func)(Ts...)) {
this->data_.func = func; this->data_.func = func;
this->static_ = false; this->len_ = -1; // Sentinel value indicates template mode
} }
void set_data_static(const uint8_t *data, size_t len) { void set_data_static(const uint8_t *data, size_t len) {
this->data_.static_data.ptr = data; this->data_.data = data;
this->data_.static_data.len = len; this->len_ = len; // Length >= 0 indicates static mode
this->static_ = true;
} }
void play(const Ts &...x) override { void play(const Ts &...x) override {
std::vector<uint8_t> data; std::vector<uint8_t> data;
if (this->static_) { if (this->len_ >= 0) {
data.assign(this->data_.static_data.ptr, this->data_.static_data.ptr + this->data_.static_data.len); // Static mode: copy from flash to vector
data.assign(this->data_.data, this->data_.data + this->len_);
} else { } else {
// Template mode: call function
data = this->data_.func(x...); data = this->data_.func(x...);
} }
this->parent_->transmit_packet(data); this->parent_->transmit_packet(data);
} }
protected: protected:
bool static_{true}; ssize_t len_{-1}; // -1 = template mode, >=0 = static mode with length
union Data { union Data {
std::vector<uint8_t> (*func)(Ts...); std::vector<uint8_t> (*func)(Ts...); // Function pointer (stateless lambdas)
struct { const uint8_t *data; // Pointer to static data in flash
const uint8_t *ptr;
size_t len;
} static_data;
} data_; } data_;
}; };

View File

@@ -12,36 +12,33 @@ template<typename... Ts> class UARTWriteAction : public Action<Ts...>, public Pa
public: public:
void set_data_template(std::vector<uint8_t> (*func)(Ts...)) { void set_data_template(std::vector<uint8_t> (*func)(Ts...)) {
// Stateless lambdas (generated by ESPHome) implicitly convert to function pointers // Stateless lambdas (generated by ESPHome) implicitly convert to function pointers
this->data_.func = func; this->code_.func = func;
this->static_ = false; this->len_ = -1; // Sentinel value indicates template mode
} }
// Store pointer to static data in flash (no RAM copy) // Store pointer to static data in flash (no RAM copy)
void set_data_static(const uint8_t *data, size_t len) { void set_data_static(const uint8_t *data, size_t len) {
// Simply set pointer and length - no construction needed for POD types this->code_.data = data;
this->data_.static_data.ptr = data; this->len_ = len; // Length >= 0 indicates static mode
this->data_.static_data.len = len;
this->static_ = true;
} }
void play(const Ts &...x) override { void play(const Ts &...x) override {
if (this->static_) { if (this->len_ >= 0) {
this->parent_->write_array(this->data_.static_data.ptr, this->data_.static_data.len); // Static mode: use pointer and length
this->parent_->write_array(this->code_.data, static_cast<size_t>(this->len_));
} else { } else {
auto val = this->data_.func(x...); // Template mode: call function
auto val = this->code_.func(x...);
this->parent_->write_array(val); this->parent_->write_array(val);
} }
} }
protected: protected:
bool static_{true}; // Default to static mode (most common case) ssize_t len_{-1}; // -1 = template mode, >=0 = static mode with length
union Data { union Code {
std::vector<uint8_t> (*func)(Ts...); // Function pointer (stateless lambdas) std::vector<uint8_t> (*func)(Ts...); // Function pointer (stateless lambdas)
struct { const uint8_t *data; // Pointer to static data in flash
const uint8_t *ptr; } code_;
size_t len;
} static_data;
} data_;
}; };
} // namespace uart } // namespace uart

View File

@@ -13,32 +13,30 @@ template<typename... Ts> class UDPWriteAction : public Action<Ts...>, public Par
public: public:
void set_data_template(std::vector<uint8_t> (*func)(Ts...)) { void set_data_template(std::vector<uint8_t> (*func)(Ts...)) {
this->data_.func = func; this->data_.func = func;
this->static_ = false; this->len_ = -1; // Sentinel value indicates template mode
} }
void set_data_static(const uint8_t *data, size_t len) { void set_data_static(const uint8_t *data, size_t len) {
this->data_.static_data.ptr = data; this->data_.data = data;
this->data_.static_data.len = len; this->len_ = len; // Length >= 0 indicates static mode
this->static_ = true;
} }
void play(const Ts &...x) override { void play(const Ts &...x) override {
if (this->static_) { if (this->len_ >= 0) {
this->parent_->send_packet(this->data_.static_data.ptr, this->data_.static_data.len); // Static mode: pass pointer directly to send_packet(const uint8_t *, size_t)
this->parent_->send_packet(this->data_.data, static_cast<size_t>(this->len_));
} else { } else {
// Template mode: call function and pass vector to send_packet(const std::vector<uint8_t> &)
auto val = this->data_.func(x...); auto val = this->data_.func(x...);
this->parent_->send_packet(val); this->parent_->send_packet(val);
} }
} }
protected: protected:
bool static_{true}; ssize_t len_{-1}; // -1 = template mode, >=0 = static mode with length
union Data { union Data {
std::vector<uint8_t> (*func)(Ts...); std::vector<uint8_t> (*func)(Ts...); // Function pointer (stateless lambdas)
struct { const uint8_t *data; // Pointer to static data in flash
const uint8_t *ptr;
size_t len;
} static_data;
} data_; } data_;
}; };

View File

@@ -136,10 +136,16 @@ button:
address: 0x00 address: 0x00
command: 0x0B command: 0x0B
- platform: template - platform: template
name: RC5 Raw name: RC5 Raw static
on_press: on_press:
remote_transmitter.transmit_raw: remote_transmitter.transmit_raw:
code: [1000, -1000] code: [1000, -1000]
- platform: template
name: RC5 Raw lambda
on_press:
remote_transmitter.transmit_raw:
code: !lambda |-
return {(int32_t)id(test_number).state * 100, -1000};
- platform: template - platform: template
name: AEHA name: AEHA
id: eaha_hitachi_climate_power_on id: eaha_hitachi_climate_power_on