ESPHome  1.15.3
base_automation.h
Go to the documentation of this file.
1 #pragma once
2 
5 
6 namespace esphome {
7 
8 template<typename... Ts> class AndCondition : public Condition<Ts...> {
9  public:
10  explicit AndCondition(const std::vector<Condition<Ts...> *> &conditions) : conditions_(conditions) {}
11  bool check(Ts... x) override {
12  for (auto *condition : this->conditions_) {
13  if (!condition->check(x...))
14  return false;
15  }
16 
17  return true;
18  }
19 
20  protected:
21  std::vector<Condition<Ts...> *> conditions_;
22 };
23 
24 template<typename... Ts> class OrCondition : public Condition<Ts...> {
25  public:
26  explicit OrCondition(const std::vector<Condition<Ts...> *> &conditions) : conditions_(conditions) {}
27  bool check(Ts... x) override {
28  for (auto *condition : this->conditions_) {
29  if (condition->check(x...))
30  return true;
31  }
32 
33  return false;
34  }
35 
36  protected:
37  std::vector<Condition<Ts...> *> conditions_;
38 };
39 
40 template<typename... Ts> class NotCondition : public Condition<Ts...> {
41  public:
42  explicit NotCondition(Condition<Ts...> *condition) : condition_(condition) {}
43  bool check(Ts... x) override { return !this->condition_->check(x...); }
44 
45  protected:
47 };
48 
49 template<typename... Ts> class LambdaCondition : public Condition<Ts...> {
50  public:
51  explicit LambdaCondition(std::function<bool(Ts...)> &&f) : f_(std::move(f)) {}
52  bool check(Ts... x) override { return this->f_(x...); }
53 
54  protected:
55  std::function<bool(Ts...)> f_;
56 };
57 
58 template<typename... Ts> class ForCondition : public Condition<Ts...>, public Component {
59  public:
60  explicit ForCondition(Condition<> *condition) : condition_(condition) {}
61 
62  TEMPLATABLE_VALUE(uint32_t, time);
63 
64  void loop() override { this->check_internal(); }
65  float get_setup_priority() const override { return setup_priority::DATA; }
66  bool check_internal() {
67  bool cond = this->condition_->check();
68  if (!cond)
69  this->last_inactive_ = millis();
70  return cond;
71  }
72 
73  bool check(Ts... x) override {
74  if (!this->check_internal())
75  return false;
76  return millis() - this->last_inactive_ >= this->time_.value(x...);
77  }
78 
79  protected:
81  uint32_t last_inactive_{0};
82 };
83 
84 class StartupTrigger : public Trigger<>, public Component {
85  public:
86  explicit StartupTrigger(float setup_priority) : setup_priority_(setup_priority) {}
87  void setup() override { this->trigger(); }
88  float get_setup_priority() const override { return this->setup_priority_; }
89 
90  protected:
92 };
93 
94 class ShutdownTrigger : public Trigger<>, public Component {
95  public:
96  void on_shutdown() override { this->trigger(); }
97 };
98 
99 class LoopTrigger : public Trigger<>, public Component {
100  public:
101  void loop() override { this->trigger(); }
102  float get_setup_priority() const override { return setup_priority::DATA; }
103 };
104 
105 template<typename... Ts> class DelayAction : public Action<Ts...>, public Component {
106  public:
107  explicit DelayAction() = default;
108 
109  TEMPLATABLE_VALUE(uint32_t, delay)
110 
111  void play_complex(Ts... x) override {
112  auto f = std::bind(&DelayAction<Ts...>::play_next_, this, x...);
113  this->num_running_++;
114  this->set_timeout(this->delay_.value(x...), f);
115  }
116  float get_setup_priority() const override { return setup_priority::HARDWARE; }
117 
118  void play(Ts... x) override { /* ignore - see play_complex */
119  }
120 
121  void stop() override { this->cancel_timeout(""); }
122 };
123 
124 template<typename... Ts> class LambdaAction : public Action<Ts...> {
125  public:
126  explicit LambdaAction(std::function<void(Ts...)> &&f) : f_(std::move(f)) {}
127 
128  void play(Ts... x) override { this->f_(x...); }
129 
130  protected:
131  std::function<void(Ts...)> f_;
132 };
133 
134 template<typename... Ts> class IfAction : public Action<Ts...> {
135  public:
136  explicit IfAction(Condition<Ts...> *condition) : condition_(condition) {}
137 
138  void add_then(const std::vector<Action<Ts...> *> &actions) {
139  this->then_.add_actions(actions);
140  this->then_.add_action(new LambdaAction<Ts...>([this](Ts... x) { this->play_next_(x...); }));
141  }
142 
143  void add_else(const std::vector<Action<Ts...> *> &actions) {
144  this->else_.add_actions(actions);
145  this->else_.add_action(new LambdaAction<Ts...>([this](Ts... x) { this->play_next_(x...); }));
146  }
147 
148  void play_complex(Ts... x) override {
149  this->num_running_++;
150  bool res = this->condition_->check(x...);
151  if (res) {
152  if (this->then_.empty()) {
153  this->play_next_(x...);
154  } else if (this->num_running_ > 0) {
155  this->then_.play(x...);
156  }
157  } else {
158  if (this->else_.empty()) {
159  this->play_next_(x...);
160  } else if (this->num_running_ > 0) {
161  this->else_.play(x...);
162  }
163  }
164  }
165 
166  void play(Ts... x) override { /* ignore - see play_complex */
167  }
168 
169  void stop() override {
170  this->then_.stop();
171  this->else_.stop();
172  }
173 
174  protected:
178 };
179 
180 template<typename... Ts> class WhileAction : public Action<Ts...> {
181  public:
182  WhileAction(Condition<Ts...> *condition) : condition_(condition) {}
183 
184  void add_then(const std::vector<Action<Ts...> *> &actions) {
185  this->then_.add_actions(actions);
186  this->then_.add_action(new LambdaAction<Ts...>([this](Ts... x) {
187  if (this->num_running_ > 0 && this->condition_->check_tuple(this->var_)) {
188  // play again
189  if (this->num_running_ > 0) {
190  this->then_.play_tuple(this->var_);
191  }
192  } else {
193  // condition false, play next
194  this->play_next_tuple_(this->var_);
195  }
196  }));
197  }
198 
199  void play_complex(Ts... x) override {
200  this->num_running_++;
201  // Store loop parameters
202  this->var_ = std::make_tuple(x...);
203  // Initial condition check
204  if (!this->condition_->check_tuple(this->var_)) {
205  // If new condition check failed, stop loop if running
206  this->then_.stop();
207  this->play_next_tuple_(this->var_);
208  return;
209  }
210 
211  if (this->num_running_ > 0) {
212  this->then_.play_tuple(this->var_);
213  }
214  }
215 
216  void play(Ts... x) override { /* ignore - see play_complex */
217  }
218 
219  void stop() override { this->then_.stop(); }
220 
221  protected:
224  std::tuple<Ts...> var_{};
225 };
226 
227 template<typename... Ts> class WaitUntilAction : public Action<Ts...>, public Component {
228  public:
229  WaitUntilAction(Condition<Ts...> *condition) : condition_(condition) {}
230 
231  void play_complex(Ts... x) override {
232  this->num_running_++;
233  // Check if we can continue immediately.
234  if (this->condition_->check(x...)) {
235  if (this->num_running_ > 0) {
236  this->play_next_(x...);
237  }
238  return;
239  }
240  this->var_ = std::make_tuple(x...);
241  this->loop();
242  }
243 
244  void loop() override {
245  if (this->num_running_ == 0)
246  return;
247 
248  if (!this->condition_->check_tuple(this->var_)) {
249  return;
250  }
251 
252  this->play_next_tuple_(this->var_);
253  }
254 
255  float get_setup_priority() const override { return setup_priority::DATA; }
256 
257  void play(Ts... x) override { /* ignore - see play_complex */
258  }
259 
260  protected:
262  std::tuple<Ts...> var_{};
263 };
264 
265 template<typename... Ts> class UpdateComponentAction : public Action<Ts...> {
266  public:
267  UpdateComponentAction(PollingComponent *component) : component_(component) {}
268 
269  void play(Ts... x) override { this->component_->update(); }
270 
271  protected:
273 };
274 
275 } // namespace esphome
ForCondition(Condition<> *condition)
const float DATA
For components that import data from directly connected sensors like DHT.
Definition: component.cpp:16
void play(Ts... x) override
float get_setup_priority() const override
void stop() override
NotCondition(Condition< Ts... > *condition)
Condition< Ts... > * condition_
void play(Ts... x) override
Condition< Ts... > * condition_
void loop() override
ActionList< Ts... > else_
Condition< Ts... > * condition_
float get_setup_priority() const override
IfAction(Condition< Ts... > *condition)
STL namespace.
void stop() override
ActionList< Ts... > then_
bool check(Ts... x) override
This class simplifies creating components that periodically check a state.
Definition: component.h:210
void on_shutdown() override
void add_then(const std::vector< Action< Ts... > *> &actions)
std::function< void(Ts...)> f_
void play(Ts... x) override
float get_setup_priority() const override
void play(Ts... x) override
WhileAction(Condition< Ts... > *condition)
Base class for all automation conditions.
Definition: automation.h:33
std::vector< Condition< Ts... > * > conditions_
LambdaAction(std::function< void(Ts...)> &&f)
bool check(Ts... x) override
void add_else(const std::vector< Action< Ts... > *> &actions)
ActionList< Ts... > then_
bool check(Ts... x) override
TEMPLATABLE_VALUE(uint32_t, delay) void play_complex(Ts... x) override
AndCondition(const std::vector< Condition< Ts... > *> &conditions)
LambdaCondition(std::function< bool(Ts...)> &&f)
void play_complex(Ts... x) override
void add_then(const std::vector< Action< Ts... > *> &actions)
float get_setup_priority() const override
void play_complex(Ts... x) override
void play_complex(Ts... x) override
void play(Ts... x) override
const float HARDWARE
For components that deal with hardware and are very important like GPIO switch.
Definition: component.cpp:15
StartupTrigger(float setup_priority)
void play(Ts... x) override
bool check(Ts... x) override
Definition: a4988.cpp:4
WaitUntilAction(Condition< Ts... > *condition)
Condition< Ts... > * condition_
UpdateComponentAction(PollingComponent *component)
float get_setup_priority() const override
OrCondition(const std::vector< Condition< Ts... > *> &conditions)
bool check(Ts... x) override
void stop() override
std::vector< Condition< Ts... > * > conditions_
void loop() override
std::function< bool(Ts...)> f_