ESPHome 2025.9.0-dev
Loading...
Searching...
No Matches
automation.h
Go to the documentation of this file.
1#pragma once
2
7#include <utility>
8#include <vector>
9
10namespace esphome {
11
12// https://stackoverflow.com/questions/7858817/unpacking-a-tuple-to-call-a-matching-function-pointer/7858971#7858971
13template<int...> struct seq {}; // NOLINT
14template<int N, int... S> struct gens : gens<N - 1, N - 1, S...> {}; // NOLINT
15template<int... S> struct gens<0, S...> { using type = seq<S...>; }; // NOLINT
16
17#define TEMPLATABLE_VALUE_(type, name) \
18 protected: \
19 TemplatableValue<type, Ts...> name##_{}; \
20\
21 public: \
22 template<typename V> void set_##name(V name) { this->name##_ = name; }
23
24#define TEMPLATABLE_VALUE(type, name) TEMPLATABLE_VALUE_(type, name)
25
26template<typename T, typename... X> class TemplatableValue {
27 public:
29
30 template<typename F, enable_if_t<!is_invocable<F, X...>::value, int> = 0> TemplatableValue(F value) : type_(VALUE) {
31 new (&this->value_) T(std::move(value));
32 }
33
34 template<typename F, enable_if_t<is_invocable<F, X...>::value, int> = 0> TemplatableValue(F f) : type_(LAMBDA) {
35 this->f_ = new std::function<T(X...)>(std::move(f));
36 }
37
38 // Copy constructor
40 if (type_ == VALUE) {
41 new (&this->value_) T(other.value_);
42 } else if (type_ == LAMBDA) {
43 this->f_ = new std::function<T(X...)>(*other.f_);
44 }
45 }
46
47 // Move constructor
48 TemplatableValue(TemplatableValue &&other) noexcept : type_(other.type_) {
49 if (type_ == VALUE) {
50 new (&this->value_) T(std::move(other.value_));
51 } else if (type_ == LAMBDA) {
52 this->f_ = other.f_;
53 other.f_ = nullptr;
54 }
55 other.type_ = NONE;
56 }
57
58 // Assignment operators
60 if (this != &other) {
61 this->~TemplatableValue();
62 new (this) TemplatableValue(other);
63 }
64 return *this;
65 }
66
68 if (this != &other) {
69 this->~TemplatableValue();
70 new (this) TemplatableValue(std::move(other));
71 }
72 return *this;
73 }
74
76 if (type_ == VALUE) {
77 this->value_.~T();
78 } else if (type_ == LAMBDA) {
79 delete this->f_;
80 }
81 }
82
83 bool has_value() { return this->type_ != NONE; }
84
85 T value(X... x) {
86 if (this->type_ == LAMBDA) {
87 return (*this->f_)(x...);
88 }
89 // return value also when none
90 return this->type_ == VALUE ? this->value_ : T{};
91 }
92
94 if (!this->has_value()) {
95 return {};
96 }
97 return this->value(x...);
98 }
99
100 T value_or(X... x, T default_value) {
101 if (!this->has_value()) {
102 return default_value;
103 }
104 return this->value(x...);
105 }
106
107 protected:
108 enum : uint8_t {
113
114 union {
116 std::function<T(X...)> *f_;
117 };
118};
119
124template<typename... Ts> class Condition {
125 public:
127 virtual bool check(Ts... x) = 0;
128
130 bool check_tuple(const std::tuple<Ts...> &tuple) {
131 return this->check_tuple_(tuple, typename gens<sizeof...(Ts)>::type());
132 }
133
134 protected:
135 template<int... S> bool check_tuple_(const std::tuple<Ts...> &tuple, seq<S...> /*unused*/) {
136 return this->check(std::get<S>(tuple)...);
137 }
138};
139
140template<typename... Ts> class Automation;
141
142template<typename... Ts> class Trigger {
143 public:
145 void trigger(Ts... x) {
146 if (this->automation_parent_ == nullptr)
147 return;
148 this->automation_parent_->trigger(x...);
149 }
150 void set_automation_parent(Automation<Ts...> *automation_parent) { this->automation_parent_ = automation_parent; }
151
153 void stop_action() {
154 if (this->automation_parent_ == nullptr)
155 return;
156 this->automation_parent_->stop();
157 }
160 if (this->automation_parent_ == nullptr)
161 return false;
162 return this->automation_parent_->is_running();
163 }
164
165 protected:
167};
168
169template<typename... Ts> class ActionList;
170
171template<typename... Ts> class Action {
172 public:
173 virtual void play_complex(Ts... x) {
174 this->num_running_++;
175 this->play(x...);
176 this->play_next_(x...);
177 }
178 virtual void stop_complex() {
179 if (num_running_) {
180 this->stop();
181 this->num_running_ = 0;
182 }
183 this->stop_next_();
184 }
186 virtual bool is_running() { return this->num_running_ > 0 || this->is_running_next_(); }
187
191 int total = this->num_running_;
192 if (this->next_ != nullptr)
193 total += this->next_->num_running_total();
194 return total;
195 }
196
197 protected:
198 friend ActionList<Ts...>;
199
200 virtual void play(Ts... x) = 0;
201 void play_next_(Ts... x) {
202 if (this->num_running_ > 0) {
203 this->num_running_--;
204 if (this->next_ != nullptr) {
205 this->next_->play_complex(x...);
206 }
207 }
208 }
209 template<int... S> void play_next_tuple_(const std::tuple<Ts...> &tuple, seq<S...> /*unused*/) {
210 this->play_next_(std::get<S>(tuple)...);
211 }
212 void play_next_tuple_(const std::tuple<Ts...> &tuple) {
213 this->play_next_tuple_(tuple, typename gens<sizeof...(Ts)>::type());
214 }
215
216 virtual void stop() {}
217 void stop_next_() {
218 if (this->next_ != nullptr) {
219 this->next_->stop_complex();
220 }
221 }
222
224 if (this->next_ == nullptr)
225 return false;
226 return this->next_->is_running();
227 }
228
229 Action<Ts...> *next_{nullptr};
230
234};
235
236template<typename... Ts> class ActionList {
237 public:
238 void add_action(Action<Ts...> *action) {
239 if (this->actions_end_ == nullptr) {
240 this->actions_begin_ = action;
241 } else {
242 this->actions_end_->next_ = action;
243 }
244 this->actions_end_ = action;
245 }
246 void add_actions(const std::vector<Action<Ts...> *> &actions) {
247 for (auto *action : actions) {
248 this->add_action(action);
249 }
250 }
251 void play(Ts... x) {
252 if (this->actions_begin_ != nullptr)
253 this->actions_begin_->play_complex(x...);
254 }
255 void play_tuple(const std::tuple<Ts...> &tuple) { this->play_tuple_(tuple, typename gens<sizeof...(Ts)>::type()); }
256 void stop() {
257 if (this->actions_begin_ != nullptr)
259 }
260 bool empty() const { return this->actions_begin_ == nullptr; }
261
263 bool is_running() {
264 if (this->actions_begin_ == nullptr)
265 return false;
266 return this->actions_begin_->is_running();
267 }
270 if (this->actions_begin_ == nullptr)
271 return 0;
272 return this->actions_begin_->num_running_total();
273 }
274
275 protected:
276 template<int... S> void play_tuple_(const std::tuple<Ts...> &tuple, seq<S...> /*unused*/) {
277 this->play(std::get<S>(tuple)...);
278 }
279
280 Action<Ts...> *actions_begin_{nullptr};
281 Action<Ts...> *actions_end_{nullptr};
282};
283
284template<typename... Ts> class Automation {
285 public:
287
288 void add_action(Action<Ts...> *action) { this->actions_.add_action(action); }
289 void add_actions(const std::vector<Action<Ts...> *> &actions) { this->actions_.add_actions(actions); }
290
291 void stop() { this->actions_.stop(); }
292
293 void trigger(Ts... x) { this->actions_.play(x...); }
294
295 bool is_running() { return this->actions_.is_running(); }
296
298 int num_running() { return this->actions_.num_running(); }
299
300 protected:
303};
304
305} // namespace esphome
virtual bool is_running()
Check if this or any of the following actions are currently running.
Definition automation.h:186
virtual void play_complex(Ts... x)
Definition automation.h:173
void play_next_tuple_(const std::tuple< Ts... > &tuple, seq< S... >)
Definition automation.h:209
Action< Ts... > * next_
Definition automation.h:229
virtual void stop_complex()
Definition automation.h:178
void play_next_tuple_(const std::tuple< Ts... > &tuple)
Definition automation.h:212
virtual void stop()
Definition automation.h:216
bool is_running_next_()
Definition automation.h:223
int num_running_
The number of instances of this sequence in the list of actions that is currently being executed.
Definition automation.h:233
void play_next_(Ts... x)
Definition automation.h:201
int num_running_total()
The total number of actions that are currently running in this plus any of the following actions in t...
Definition automation.h:190
virtual void play(Ts... x)=0
void add_action(Action< Ts... > *action)
Definition automation.h:238
Action< Ts... > * actions_end_
Definition automation.h:281
void play(Ts... x)
Definition automation.h:251
void play_tuple(const std::tuple< Ts... > &tuple)
Definition automation.h:255
bool is_running()
Check if any action in this action list is currently running.
Definition automation.h:263
void add_actions(const std::vector< Action< Ts... > * > &actions)
Definition automation.h:246
void play_tuple_(const std::tuple< Ts... > &tuple, seq< S... >)
Definition automation.h:276
bool empty() const
Definition automation.h:260
Action< Ts... > * actions_begin_
Definition automation.h:280
int num_running()
Return the number of actions in this action list that are currently running.
Definition automation.h:269
void add_action(Action< Ts... > *action)
Definition automation.h:288
Trigger< Ts... > * trigger_
Definition automation.h:301
void add_actions(const std::vector< Action< Ts... > * > &actions)
Definition automation.h:289
int num_running()
Return the number of actions in the action part of this automation that are currently running.
Definition automation.h:298
void trigger(Ts... x)
Definition automation.h:293
Automation(Trigger< Ts... > *trigger)
Definition automation.h:286
ActionList< Ts... > actions_
Definition automation.h:302
Base class for all automation conditions.
Definition automation.h:124
bool check_tuple(const std::tuple< Ts... > &tuple)
Call check with a tuple of values as parameter.
Definition automation.h:130
virtual bool check(Ts... x)=0
Check whether this condition passes. This condition check must be instant, and not cause any delays.
bool check_tuple_(const std::tuple< Ts... > &tuple, seq< S... >)
Definition automation.h:135
TemplatableValue(const TemplatableValue &other)
Definition automation.h:39
std::function< T(X...)> * f_
Definition automation.h:116
TemplatableValue & operator=(TemplatableValue &&other) noexcept
Definition automation.h:67
TemplatableValue(TemplatableValue &&other) noexcept
Definition automation.h:48
enum esphome::TemplatableValue::@159 type_
TemplatableValue & operator=(const TemplatableValue &other)
Definition automation.h:59
T value_or(X... x, T default_value)
Definition automation.h:100
optional< T > optional_value(X... x)
Definition automation.h:93
Automation< Ts... > * automation_parent_
Definition automation.h:166
void stop_action()
Stop any action connected to this trigger.
Definition automation.h:153
bool is_action_running()
Returns true if any action connected to this trigger is running.
Definition automation.h:159
void trigger(Ts... x)
Inform the parent automation that the event has triggered.
Definition automation.h:145
void set_automation_parent(Automation< Ts... > *automation_parent)
Definition automation.h:150
uint8_t type
Providing packet encoding functions for exchanging data with a remote host.
Definition a01nyub.cpp:7
uint16_t x
Definition tt21100.cpp:5