ESPHome  2022.12.8
sprinkler.h
Go to the documentation of this file.
1 #pragma once
2 
5 #include "esphome/core/hal.h"
7 
8 #include <vector>
9 
10 namespace esphome {
11 namespace sprinkler {
12 
13 enum SprinklerState : uint8_t {
14  // NOTE: these states are used by both SprinklerValveOperator and Sprinkler (the controller)!
15  IDLE, // system/valve is off
16  STARTING, // system/valve is starting/"half open" -- either pump or valve is on, but the remaining pump/valve is not
17  ACTIVE, // system/valve is running its cycle
18  STOPPING, // system/valve is stopping/"half open" -- either pump or valve is on, but the remaining pump/valve is not
19  BYPASS // used by SprinklerValveOperator to ignore the instance checking pump status
20 };
21 
22 enum SprinklerTimerIndex : uint8_t {
23  TIMER_SM = 0,
25 };
26 
27 class Sprinkler; // this component
28 class SprinklerControllerSwitch; // switches that appear in the front end; based on switch core
29 class SprinklerSwitch; // switches representing any valve or pump; provides abstraction for latching valves
30 class SprinklerValveOperator; // manages all switching on/off of valves and associated pumps
31 class SprinklerValveRunRequest; // tells the sprinkler controller what valve to run and for how long as well as what
32  // SprinklerValveOperator is handling it
33 template<typename... Ts> class StartSingleValveAction;
34 template<typename... Ts> class ShutdownAction;
35 template<typename... Ts> class ResumeOrStartAction;
36 
38  public:
40  SprinklerSwitch(switch_::Switch *sprinkler_switch);
42 
43  bool is_latching_valve(); // returns true if configured as a latching valve
44  void loop(); // called as a part of loop(), used for latching valve pulses
45  uint32_t pulse_duration() { return this->pulse_duration_; }
46  bool state(); // returns the switch's current state
47  void set_off_switch(switch_::Switch *off_switch) { this->off_switch_ = off_switch; }
48  void set_on_switch(switch_::Switch *on_switch) { this->on_switch_ = on_switch; }
49  void set_pulse_duration(uint32_t pulse_duration) { this->pulse_duration_ = pulse_duration; }
50  void sync_valve_state(
51  bool latch_state); // syncs internal state to switch; if latching valve, sets state to latch_state
52  void turn_off(); // sets internal flag and actuates the switch
53  void turn_on(); // sets internal flag and actuates the switch
54  switch_::Switch *off_switch() { return this->off_switch_; }
55  switch_::Switch *on_switch() { return this->on_switch_; }
56 
57  protected:
58  bool state_{false};
59  uint32_t pulse_duration_{0};
60  uint64_t pinned_millis_{0};
61  switch_::Switch *off_switch_{nullptr}; // only used for latching valves
62  switch_::Switch *on_switch_{nullptr}; // used for both latching and non-latching valves
63 };
64 
66  size_t valve_number;
67  uint32_t run_duration;
68 };
69 
71  const std::string name;
72  bool active;
73  uint32_t time;
74  uint32_t start_time;
75  std::function<void()> func;
76 };
77 
82  uint32_t run_duration;
85  std::unique_ptr<ShutdownAction<>> valve_shutdown_action;
86  std::unique_ptr<StartSingleValveAction<>> valve_resumeorstart_action;
87  std::unique_ptr<Automation<>> valve_turn_off_automation;
88  std::unique_ptr<Automation<>> valve_turn_on_automation;
89 };
90 
92  public:
94 
95  void setup() override;
96  void dump_config() override;
97 
98  void set_state_lambda(std::function<optional<bool>()> &&f);
99  void set_restore_state(bool restore_state);
100  Trigger<> *get_turn_on_trigger() const;
101  Trigger<> *get_turn_off_trigger() const;
102  void set_optimistic(bool optimistic);
103  void set_assumed_state(bool assumed_state);
104  void loop() override;
105 
106  float get_setup_priority() const override;
107 
108  protected:
109  bool assumed_state() override;
110 
111  void write_state(bool state) override;
112 
114  bool optimistic_{false};
115  bool assumed_state_{false};
118  Trigger<> *prev_trigger_{nullptr};
119  bool restore_state_{false};
120 };
121 
123  public:
125  SprinklerValveOperator(SprinklerValve *valve, Sprinkler *controller);
126  void loop();
127  void set_controller(Sprinkler *controller);
128  void set_valve(SprinklerValve *valve);
129  void set_run_duration(uint32_t run_duration); // set the desired run duration in seconds
130  void set_start_delay(uint32_t start_delay, bool start_delay_is_valve_delay);
131  void set_stop_delay(uint32_t stop_delay, bool stop_delay_is_valve_delay);
132  void start();
133  void stop();
134  uint32_t run_duration(); // returns the desired run duration in seconds
135  uint32_t time_remaining(); // returns seconds remaining (does not include stop_delay_)
136  SprinklerState state(); // returns the valve's state/status
137  SprinklerSwitch *pump_switch(); // returns this SprinklerValveOperator's pump's SprinklerSwitch
138 
139  protected:
140  void pump_off_();
141  void pump_on_();
142  void valve_off_();
143  void valve_on_();
144  void kill_();
145  void run_();
146  bool start_delay_is_valve_delay_{false};
147  bool stop_delay_is_valve_delay_{false};
148  uint32_t start_delay_{0};
149  uint32_t stop_delay_{0};
150  uint32_t run_duration_{0};
151  uint64_t pinned_millis_{0};
152  Sprinkler *controller_{nullptr};
153  SprinklerValve *valve_{nullptr};
155 };
156 
158  public:
160  SprinklerValveRunRequest(size_t valve_number, uint32_t run_duration, SprinklerValveOperator *valve_op);
161  bool has_request();
162  bool has_valve_operator();
163  void set_run_duration(uint32_t run_duration);
164  void set_valve(size_t valve_number);
165  void set_valve_operator(SprinklerValveOperator *valve_op);
166  void reset();
167  uint32_t run_duration();
168  size_t valve();
169  optional<size_t> valve_as_opt();
170  SprinklerValveOperator *valve_operator();
171 
172  protected:
173  bool has_valve_{false};
174  size_t valve_number_{0};
175  uint32_t run_duration_{0};
176  SprinklerValveOperator *valve_op_{nullptr};
177 };
178 
179 class Sprinkler : public Component, public EntityBase {
180  public:
181  Sprinkler();
182  Sprinkler(const std::string &name);
183 
184  void setup() override;
185  void loop() override;
186  void dump_config() override;
187 
189  void add_valve(SprinklerControllerSwitch *valve_sw, SprinklerControllerSwitch *enable_sw = nullptr);
190 
192  void add_controller(Sprinkler *other_controller);
193 
195  void set_controller_main_switch(SprinklerControllerSwitch *controller_switch);
196  void set_controller_auto_adv_switch(SprinklerControllerSwitch *auto_adv_switch);
197  void set_controller_queue_enable_switch(SprinklerControllerSwitch *queue_enable_switch);
198  void set_controller_reverse_switch(SprinklerControllerSwitch *reverse_switch);
199 
201  void configure_valve_switch(size_t valve_number, switch_::Switch *valve_switch, uint32_t run_duration);
202  void configure_valve_switch_pulsed(size_t valve_number, switch_::Switch *valve_switch_off,
203  switch_::Switch *valve_switch_on, uint32_t pulse_duration, uint32_t run_duration);
204 
206  void configure_valve_pump_switch(size_t valve_number, switch_::Switch *pump_switch);
207  void configure_valve_pump_switch_pulsed(size_t valve_number, switch_::Switch *pump_switch_off,
208  switch_::Switch *pump_switch_on, uint32_t pulse_duration);
209 
211  void set_multiplier(optional<float> multiplier);
212 
214  void set_pump_start_delay(uint32_t start_delay);
215 
217  void set_pump_stop_delay(uint32_t stop_delay);
218 
220  void set_valve_start_delay(uint32_t start_delay);
221 
223  void set_valve_stop_delay(uint32_t stop_delay);
224 
227  void set_pump_switch_off_during_valve_open_delay(bool pump_switch_off_during_valve_open_delay);
228 
230  void set_valve_open_delay(uint32_t valve_open_delay);
231 
233  void set_valve_overlap(uint32_t valve_overlap);
234 
236  void set_manual_selection_delay(uint32_t manual_selection_delay);
237 
239  void set_valve_run_duration(optional<size_t> valve_number, optional<uint32_t> run_duration);
240 
242  void set_auto_advance(bool auto_advance);
243 
245  void set_repeat(optional<uint32_t> repeat);
246 
248  void set_queue_enable(bool queue_enable);
249 
251  void set_reverse(bool reverse);
252 
254  uint32_t valve_run_duration(size_t valve_number);
255 
257  uint32_t valve_run_duration_adjusted(size_t valve_number);
258 
260  bool auto_advance();
261 
263  float multiplier();
264 
266  optional<uint32_t> repeat();
267 
269  optional<uint32_t> repeat_count();
270 
272  bool queue_enabled();
273 
275  bool reverse();
276 
279  void start_from_queue();
280 
283  void start_full_cycle();
284 
286  void start_single_valve(optional<size_t> valve_number);
287 
290  void queue_valve(optional<size_t> valve_number, optional<uint32_t> run_duration);
291 
293  void clear_queued_valves();
294 
296  void next_valve();
297 
299  void previous_valve();
300 
302  void shutdown(bool clear_queue = false);
303 
305  void pause();
306 
308  void resume();
309 
311  void resume_or_start_full_cycle();
312 
314  void reset_resume();
315 
317  const char *valve_name(size_t valve_number);
318 
320  optional<size_t> active_valve();
321 
323  optional<size_t> paused_valve();
324 
326  optional<size_t> queued_valve();
327 
330  optional<size_t> manual_valve();
331 
333  size_t number_of_valves();
334 
336  bool is_a_valid_valve(size_t valve_number);
337 
339  bool pump_in_use(SprinklerSwitch *pump_switch);
340 
342  void set_pump_state(SprinklerSwitch *pump_switch, bool state);
343 
345  optional<uint32_t> time_remaining();
346 
348  SprinklerControllerSwitch *control_switch(size_t valve_number);
349 
351  SprinklerControllerSwitch *enable_switch(size_t valve_number);
352 
354  SprinklerSwitch *valve_switch(size_t valve_number);
355 
357  SprinklerSwitch *valve_pump_switch(size_t valve_number);
358 
360  SprinklerSwitch *valve_pump_switch_by_pump_index(size_t pump_index);
361 
362  protected:
363  uint32_t hash_base() override;
364 
366  bool valve_is_enabled_(size_t valve_number);
367 
369  void mark_valve_cycle_complete_(size_t valve_number);
370 
372  bool valve_cycle_complete_(size_t valve_number);
373 
375  size_t next_valve_number_(size_t first_valve);
376  size_t previous_valve_number_(size_t first_valve);
377 
380  optional<size_t> next_valve_number_in_cycle_(optional<size_t> first_valve = nullopt);
381 
386  void load_next_valve_run_request_(optional<size_t> first_valve = nullopt);
387 
390  optional<size_t> next_enabled_incomplete_valve_number_(optional<size_t> first_valve);
391  optional<size_t> previous_enabled_incomplete_valve_number_(optional<size_t> first_valve);
392 
394  bool any_valve_is_enabled_();
395 
398  void start_valve_(SprinklerValveRunRequest *req);
399 
401  void all_valves_off_(bool include_pump = false);
402 
404  void prep_full_cycle_();
405 
407  void reset_cycle_states_();
408 
410  void fsm_request_(size_t requested_valve, uint32_t requested_run_duration = 0);
411 
413  void fsm_kick_();
414 
416  void fsm_transition_();
417 
419  void fsm_transition_from_shutdown_();
420 
422  void fsm_transition_from_valve_run_();
423 
425  void fsm_transition_to_shutdown_();
426 
428  std::string state_as_str_(SprinklerState state);
429 
431  void start_timer_(SprinklerTimerIndex timer_index);
432  bool cancel_timer_(SprinklerTimerIndex timer_index);
434  bool timer_active_(SprinklerTimerIndex timer_index);
436  void set_timer_duration_(SprinklerTimerIndex timer_index, uint32_t time);
438  uint32_t timer_duration_(SprinklerTimerIndex timer_index);
439  std::function<void()> timer_cbf_(SprinklerTimerIndex timer_index);
440 
442  void valve_selection_callback_();
443  void sm_timer_callback_();
444  void pump_stop_delay_callback_();
445 
447  const uint8_t max_queue_size_{100};
448 
450  bool pump_switch_off_during_valve_open_delay_{false};
451 
453  bool valve_overlap_{false};
454 
456  bool start_delay_is_valve_delay_{false};
457  bool stop_delay_is_valve_delay_{false};
458 
460  uint32_t start_delay_{0};
461  uint32_t stop_delay_{0};
462 
465 
468 
471 
474 
477 
480 
483 
486 
489 
491  uint32_t repeat_count_{0};
492 
494  float multiplier_{1.0};
495 
497  std::vector<SprinklerQueueItem> queued_valves_;
498 
500  std::vector<SprinklerSwitch> pump_;
501 
503  std::vector<SprinklerValve> valve_;
504 
506  std::vector<SprinklerValveOperator> valve_op_{2};
507 
509  std::vector<SprinklerTimer> timer_{
510  {this->name_ + "sm", false, 0, 0, std::bind(&Sprinkler::sm_timer_callback_, this)},
511  {this->name_ + "vs", false, 0, 0, std::bind(&Sprinkler::valve_selection_callback_, this)}};
512 
514  std::vector<Sprinkler *> other_controllers_;
515 
517  SprinklerControllerSwitch *auto_adv_sw_{nullptr};
518  SprinklerControllerSwitch *controller_sw_{nullptr};
519  SprinklerControllerSwitch *queue_enable_sw_{nullptr};
520  SprinklerControllerSwitch *reverse_sw_{nullptr};
521 
522  std::unique_ptr<ShutdownAction<>> sprinkler_shutdown_action_;
523  std::unique_ptr<ResumeOrStartAction<>> sprinkler_resumeorstart_action_;
524 
525  std::unique_ptr<Automation<>> sprinkler_turn_off_automation_;
526  std::unique_ptr<Automation<>> sprinkler_turn_on_automation_;
527 };
528 
529 } // namespace sprinkler
530 } // namespace esphome
void setup()
Base class for all switches.
Definition: switch.h:32
const char * name
Definition: stm32flash.h:78
void set_off_switch(switch_::Switch *off_switch)
Definition: sprinkler.h:47
SprinklerControllerSwitch * controller_switch
Definition: sprinkler.h:79
SprinklerValveRunRequest next_req_
The next run request for the controller to consume after active_req_ is complete. ...
Definition: sprinkler.h:476
optional< uint32_t > resume_duration_
Set from time_remaining() when paused.
Definition: sprinkler.h:482
void valve_selection_callback_()
callback functions for timers
Definition: sprinkler.cpp:1283
std::vector< SprinklerValve > valve_
Sprinkler valve objects.
Definition: sprinkler.h:503
optional< uint32_t > switching_delay_
Valve switching delay.
Definition: sprinkler.h:488
void set_pulse_duration(uint32_t pulse_duration)
Definition: sprinkler.h:49
std::unique_ptr< ResumeOrStartAction<> > sprinkler_resumeorstart_action_
Definition: sprinkler.h:523
optional< size_t > pump_switch_index
Definition: sprinkler.h:83
std::unique_ptr< Automation<> > valve_turn_off_automation
Definition: sprinkler.h:87
std::vector< Sprinkler * > other_controllers_
Other Sprinkler instances we should be aware of (used to check if pumps are in use) ...
Definition: sprinkler.h:514
void set_on_switch(switch_::Switch *on_switch)
Definition: sprinkler.h:48
switch_::Switch * on_switch()
Definition: sprinkler.h:55
std::unique_ptr< Automation<> > sprinkler_turn_on_automation_
Definition: sprinkler.h:526
const nullopt_t nullopt((nullopt_t::init()))
std::function< void()> func
Definition: sprinkler.h:75
optional< size_t > manual_valve_
The number of the manually selected valve currently selected.
Definition: sprinkler.h:470
optional< uint32_t > target_repeats_
Set the number of times to repeat a full cycle.
Definition: sprinkler.h:479
std::vector< SprinklerSwitch > pump_
Sprinkler valve pump objects.
Definition: sprinkler.h:500
optional< size_t > paused_valve_
The number of the valve to resume from (if paused)
Definition: sprinkler.h:473
std::unique_ptr< StartSingleValveAction<> > valve_resumeorstart_action
Definition: sprinkler.h:86
void sync_valve_state(bool latch_state)
Definition: sprinkler.cpp:70
std::unique_ptr< ShutdownAction<> > sprinkler_shutdown_action_
Definition: sprinkler.h:522
std::unique_ptr< Automation<> > sprinkler_turn_off_automation_
Definition: sprinkler.h:525
Definition: a4988.cpp:4
optional< uint32_t > manual_selection_delay_
Manual switching delay.
Definition: sprinkler.h:485
std::unique_ptr< Automation<> > valve_turn_on_automation
Definition: sprinkler.h:88
std::vector< SprinklerQueueItem > queued_valves_
Queue of valves to activate next, regardless of auto-advance.
Definition: sprinkler.h:497
SprinklerControllerSwitch * enable_switch
Definition: sprinkler.h:80
switch_::Switch * off_switch()
Definition: sprinkler.h:54
SprinklerValveRunRequest active_req_
The valve run request that is currently active.
Definition: sprinkler.h:467
std::unique_ptr< ShutdownAction<> > valve_shutdown_action
Definition: sprinkler.h:85