ESPHome 2026.11.0-dev
Loading...
Searching...
No Matches
automation.h
Go to the documentation of this file.
1#pragma once
2
3#if defined(USE_ESP32) || defined(USE_ESP8266)
4
5#include "espnow_component.h"
6
9
10namespace esphome::espnow {
11
12template<typename... Ts> class SendAction final : public Action<Ts...>, public Parented<ESPNowComponent> {
13 TEMPLATABLE_VALUE(peer_address_t, address);
14 TEMPLATABLE_BYTES(data)
15
16 public:
17 void add_on_sent(const std::initializer_list<Action<Ts...> *> &actions) {
18 this->sent_.add_actions(actions);
19 if (this->flags_.wait_for_sent) {
20 this->sent_.add_action(new LambdaAction<Ts...>([this](Ts... x) { this->play_next_(x...); }));
21 }
22 }
23 void add_on_error(const std::initializer_list<Action<Ts...> *> &actions) {
24 this->error_.add_actions(actions);
25 if (this->flags_.wait_for_sent) {
26 this->error_.add_action(new LambdaAction<Ts...>([this](Ts... x) {
27 if (this->flags_.continue_on_error) {
28 this->play_next_(x...);
29 } else {
30 this->stop_complex();
31 }
32 }));
33 }
34 }
35
36 void set_wait_for_sent(bool wait_for_sent) { this->flags_.wait_for_sent = wait_for_sent; }
37 void set_continue_on_error(bool continue_on_error) { this->flags_.continue_on_error = continue_on_error; }
38
39 void play_complex(const Ts &...x) override {
40 this->num_running_++;
41 send_callback_t send_callback = [this, x...](esp_err_t status) {
42 if (status == ESP_OK) {
43 if (!this->sent_.empty()) {
44 this->sent_.play(x...);
45 } else if (this->flags_.wait_for_sent) {
46 this->play_next_(x...);
47 }
48 } else {
49 if (!this->error_.empty()) {
50 this->error_.play(x...);
51 } else if (this->flags_.wait_for_sent) {
52 if (this->flags_.continue_on_error) {
53 this->play_next_(x...);
54 } else {
55 this->stop_complex();
56 }
57 }
58 }
59 };
60 peer_address_t address = this->address_.value(x...);
61 esp_err_t err = ESP_OK;
62 this->data_.visit(
63 [&](const uint8_t *data, size_t len) { err = this->parent_->send(address.data(), data, len, send_callback); },
64 x...);
65 if (err != ESP_OK) {
66 send_callback(err);
67 } else if (!this->flags_.wait_for_sent) {
68 this->play_next_(x...);
69 }
70 }
71
72 protected:
73 void play(const Ts &...x) override { /* ignore - see play_complex */ }
74
75 void stop() override {
76 this->sent_.stop();
77 this->error_.stop();
78 }
79
82
83 struct {
84 uint8_t wait_for_sent : 1; // Wait for the send operation to complete before continuing automation
85 uint8_t continue_on_error : 1; // Continue automation even if the send operation fails
86 uint8_t reserved : 6; // Reserved for future use
87 } flags_{0};
88};
89
90class OnReceiveTrigger final : public Trigger<const ESPNowRecvInfo &, const uint8_t *, uint16_t>,
91 public ESPNowReceivedPacketHandler {
92 public:
93 explicit OnReceiveTrigger(std::array<uint8_t, ESP_NOW_ETH_ALEN> address) : has_address_(true) {
94 memcpy(this->address_, address.data(), ESP_NOW_ETH_ALEN);
95 }
96
97 explicit OnReceiveTrigger() {}
98
99 bool on_receive(const ESPNowRecvInfo &info, const uint8_t *data, uint16_t size) override {
100 bool match = !this->has_address_ || (memcmp(this->address_, info.src_addr, ESP_NOW_ETH_ALEN) == 0);
101 if (!match)
102 return false;
103
104 this->trigger(info, data, size);
105 return false; // Return false to continue processing other internal handlers
106 }
107
108 protected:
109 bool has_address_{false};
110 uint8_t address_[ESP_NOW_ETH_ALEN]{};
111};
112class OnUnknownPeerTrigger final : public Trigger<const ESPNowRecvInfo &, const uint8_t *, uint16_t>,
113 public ESPNowUnknownPeerHandler {
114 public:
115 bool on_unknown_peer(const ESPNowRecvInfo &info, const uint8_t *data, uint16_t size) override {
116 this->trigger(info, data, size);
117 return false; // Return false to continue processing other internal handlers
118 }
119};
120class OnBroadcastTrigger final : public Trigger<const ESPNowRecvInfo &, const uint8_t *, uint16_t>,
121 public ESPNowBroadcastHandler {
122 public:
123 explicit OnBroadcastTrigger(std::array<uint8_t, ESP_NOW_ETH_ALEN> address) : has_address_(true) {
124 memcpy(this->address_, address.data(), ESP_NOW_ETH_ALEN);
125 }
126 explicit OnBroadcastTrigger() {}
127
128 bool on_broadcast(const ESPNowRecvInfo &info, const uint8_t *data, uint16_t size) override {
129 bool match = !this->has_address_ || (memcmp(this->address_, info.src_addr, ESP_NOW_ETH_ALEN) == 0);
130 if (!match)
131 return false;
132
133 this->trigger(info, data, size);
134 return false; // Return false to continue processing other internal handlers
135 }
136
137 protected:
138 bool has_address_{false};
139 uint8_t address_[ESP_NOW_ETH_ALEN]{};
140};
141
142} // namespace esphome::espnow
143
144#endif // USE_ESP32 || USE_ESP8266
uint8_t address
Definition bl0906.h:4
uint8_t status
Definition bl0942.h:8
void add_action(Action< Ts... > *action)
Definition automation.h:664
void add_actions(const std::initializer_list< Action< Ts... > * > &actions)
Definition automation.h:668
Helper class to easily give an object a parent of type T.
Definition helpers.h:2073
bool on_broadcast(const ESPNowRecvInfo &info, const uint8_t *data, uint16_t size) override
Definition automation.h:128
OnBroadcastTrigger(std::array< uint8_t, ESP_NOW_ETH_ALEN > address)
Definition automation.h:123
bool on_receive(const ESPNowRecvInfo &info, const uint8_t *data, uint16_t size) override
Definition automation.h:99
OnReceiveTrigger(std::array< uint8_t, ESP_NOW_ETH_ALEN > address)
Definition automation.h:93
bool on_unknown_peer(const ESPNowRecvInfo &info, const uint8_t *data, uint16_t size) override
Definition automation.h:115
ActionList< Ts... > sent_
Definition automation.h:80
void play(const Ts &...x) override
Definition automation.h:73
struct esphome::espnow::SendAction::@87 flags_
ActionList< Ts... > error_
Definition automation.h:81
std::function< void(esp_err_t)> send_callback_t
const void size_t len
Definition hal.h:68
uint8_t src_addr[ESP_NOW_ETH_ALEN]
Source address of ESPNOW packet.
uint16_t x
Definition tt21100.cpp:5