ESPHome 2025.5.0
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>
32
33 template<typename F, enable_if_t<is_invocable<F, X...>::value, int> = 0>
35
36 bool has_value() { return this->type_ != NONE; }
37
38 T value(X... x) {
39 if (this->type_ == LAMBDA) {
40 return this->f_(x...);
41 }
42 // return value also when none
43 return this->value_;
44 }
45
47 if (!this->has_value()) {
48 return {};
49 }
50 return this->value(x...);
51 }
52
53 T value_or(X... x, T default_value) {
54 if (!this->has_value()) {
55 return default_value;
56 }
57 return this->value(x...);
58 }
59
60 protected:
61 enum {
66
67 T value_{};
68 std::function<T(X...)> f_{};
69};
70
75template<typename... Ts> class Condition {
76 public:
78 virtual bool check(Ts... x) = 0;
79
81 bool check_tuple(const std::tuple<Ts...> &tuple) {
82 return this->check_tuple_(tuple, typename gens<sizeof...(Ts)>::type());
83 }
84
85 protected:
86 template<int... S> bool check_tuple_(const std::tuple<Ts...> &tuple, seq<S...> /*unused*/) {
87 return this->check(std::get<S>(tuple)...);
88 }
89};
90
91template<typename... Ts> class Automation;
92
93template<typename... Ts> class Trigger {
94 public:
96 void trigger(Ts... x) {
97 if (this->automation_parent_ == nullptr)
98 return;
99 this->automation_parent_->trigger(x...);
100 }
101 void set_automation_parent(Automation<Ts...> *automation_parent) { this->automation_parent_ = automation_parent; }
102
104 void stop_action() {
105 if (this->automation_parent_ == nullptr)
106 return;
107 this->automation_parent_->stop();
108 }
111 if (this->automation_parent_ == nullptr)
112 return false;
113 return this->automation_parent_->is_running();
114 }
115
116 protected:
118};
119
120template<typename... Ts> class ActionList;
121
122template<typename... Ts> class Action {
123 public:
124 virtual void play_complex(Ts... x) {
125 this->num_running_++;
126 this->play(x...);
127 this->play_next_(x...);
128 }
129 virtual void stop_complex() {
130 if (num_running_) {
131 this->stop();
132 this->num_running_ = 0;
133 }
134 this->stop_next_();
135 }
137 virtual bool is_running() { return this->num_running_ > 0 || this->is_running_next_(); }
138
142 int total = this->num_running_;
143 if (this->next_ != nullptr)
144 total += this->next_->num_running_total();
145 return total;
146 }
147
148 protected:
149 friend ActionList<Ts...>;
150
151 virtual void play(Ts... x) = 0;
152 void play_next_(Ts... x) {
153 if (this->num_running_ > 0) {
154 this->num_running_--;
155 if (this->next_ != nullptr) {
156 this->next_->play_complex(x...);
157 }
158 }
159 }
160 template<int... S> void play_next_tuple_(const std::tuple<Ts...> &tuple, seq<S...> /*unused*/) {
161 this->play_next_(std::get<S>(tuple)...);
162 }
163 void play_next_tuple_(const std::tuple<Ts...> &tuple) {
164 this->play_next_tuple_(tuple, typename gens<sizeof...(Ts)>::type());
165 }
166
167 virtual void stop() {}
168 void stop_next_() {
169 if (this->next_ != nullptr) {
170 this->next_->stop_complex();
171 }
172 }
173
175 if (this->next_ == nullptr)
176 return false;
177 return this->next_->is_running();
178 }
179
180 Action<Ts...> *next_{nullptr};
181
185};
186
187template<typename... Ts> class ActionList {
188 public:
189 void add_action(Action<Ts...> *action) {
190 if (this->actions_end_ == nullptr) {
191 this->actions_begin_ = action;
192 } else {
193 this->actions_end_->next_ = action;
194 }
195 this->actions_end_ = action;
196 }
197 void add_actions(const std::vector<Action<Ts...> *> &actions) {
198 for (auto *action : actions) {
199 this->add_action(action);
200 }
201 }
202 void play(Ts... x) {
203 if (this->actions_begin_ != nullptr)
204 this->actions_begin_->play_complex(x...);
205 }
206 void play_tuple(const std::tuple<Ts...> &tuple) { this->play_tuple_(tuple, typename gens<sizeof...(Ts)>::type()); }
207 void stop() {
208 if (this->actions_begin_ != nullptr)
210 }
211 bool empty() const { return this->actions_begin_ == nullptr; }
212
214 bool is_running() {
215 if (this->actions_begin_ == nullptr)
216 return false;
217 return this->actions_begin_->is_running();
218 }
221 if (this->actions_begin_ == nullptr)
222 return 0;
223 return this->actions_begin_->num_running_total();
224 }
225
226 protected:
227 template<int... S> void play_tuple_(const std::tuple<Ts...> &tuple, seq<S...> /*unused*/) {
228 this->play(std::get<S>(tuple)...);
229 }
230
231 Action<Ts...> *actions_begin_{nullptr};
232 Action<Ts...> *actions_end_{nullptr};
233};
234
235template<typename... Ts> class Automation {
236 public:
238
239 void add_action(Action<Ts...> *action) { this->actions_.add_action(action); }
240 void add_actions(const std::vector<Action<Ts...> *> &actions) { this->actions_.add_actions(actions); }
241
242 void stop() { this->actions_.stop(); }
243
244 void trigger(Ts... x) { this->actions_.play(x...); }
245
246 bool is_running() { return this->actions_.is_running(); }
247
249 int num_running() { return this->actions_.num_running(); }
250
251 protected:
254};
255
256} // namespace esphome
virtual bool is_running()
Check if this or any of the following actions are currently running.
Definition automation.h:137
virtual void play_complex(Ts... x)
Definition automation.h:124
void play_next_tuple_(const std::tuple< Ts... > &tuple, seq< S... >)
Definition automation.h:160
Action< Ts... > * next_
Definition automation.h:180
virtual void stop_complex()
Definition automation.h:129
void play_next_tuple_(const std::tuple< Ts... > &tuple)
Definition automation.h:163
virtual void stop()
Definition automation.h:167
bool is_running_next_()
Definition automation.h:174
int num_running_
The number of instances of this sequence in the list of actions that is currently being executed.
Definition automation.h:184
void play_next_(Ts... x)
Definition automation.h:152
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:141
virtual void play(Ts... x)=0
void add_action(Action< Ts... > *action)
Definition automation.h:189
Action< Ts... > * actions_end_
Definition automation.h:232
void play(Ts... x)
Definition automation.h:202
void play_tuple(const std::tuple< Ts... > &tuple)
Definition automation.h:206
bool is_running()
Check if any action in this action list is currently running.
Definition automation.h:214
void add_actions(const std::vector< Action< Ts... > * > &actions)
Definition automation.h:197
void play_tuple_(const std::tuple< Ts... > &tuple, seq< S... >)
Definition automation.h:227
bool empty() const
Definition automation.h:211
Action< Ts... > * actions_begin_
Definition automation.h:231
int num_running()
Return the number of actions in this action list that are currently running.
Definition automation.h:220
void add_action(Action< Ts... > *action)
Definition automation.h:239
Trigger< Ts... > * trigger_
Definition automation.h:252
void add_actions(const std::vector< Action< Ts... > * > &actions)
Definition automation.h:240
int num_running()
Return the number of actions in the action part of this automation that are currently running.
Definition automation.h:249
void trigger(Ts... x)
Definition automation.h:244
Automation(Trigger< Ts... > *trigger)
Definition automation.h:237
ActionList< Ts... > actions_
Definition automation.h:253
Base class for all automation conditions.
Definition automation.h:75
bool check_tuple(const std::tuple< Ts... > &tuple)
Call check with a tuple of values as parameter.
Definition automation.h:81
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:86
std::function< T(X...)> f_
Definition automation.h:68
enum esphome::TemplatableValue::@154 type_
T value_or(X... x, T default_value)
Definition automation.h:53
optional< T > optional_value(X... x)
Definition automation.h:46
Automation< Ts... > * automation_parent_
Definition automation.h:117
void stop_action()
Stop any action connected to this trigger.
Definition automation.h:104
bool is_action_running()
Returns true if any action connected to this trigger is running.
Definition automation.h:110
void trigger(Ts... x)
Inform the parent automation that the event has triggered.
Definition automation.h:96
void set_automation_parent(Automation< Ts... > *automation_parent)
Definition automation.h:101
uint8_t type
Providing packet encoding functions for exchanging data with a remote host.
Definition a01nyub.cpp:7
typename std::enable_if< B, T >::type enable_if_t
Definition helpers.h:94
uint16_t x
Definition tt21100.cpp:5