ESPHome  2022.11.3
sprinkler.h
Go to the documentation of this file.
1 #pragma once
2 
5 #include "esphome/core/hal.h"
7 
8 namespace esphome {
9 namespace sprinkler {
10 
11 enum SprinklerState : uint8_t {
12  // NOTE: these states are used by both SprinklerValveOperator and Sprinkler (the controller)!
13  IDLE, // system/valve is off
14  STARTING, // system/valve is starting/"half open" -- either pump or valve is on, but the remaining pump/valve is not
15  ACTIVE, // system/valve is running its cycle
16  STOPPING, // system/valve is stopping/"half open" -- either pump or valve is on, but the remaining pump/valve is not
17  BYPASS // used by SprinklerValveOperator to ignore the instance checking pump status
18 };
19 
20 enum SprinklerTimerIndex : uint8_t {
21  TIMER_SM = 0,
23 };
24 
25 class Sprinkler; // this component
26 class SprinklerControllerSwitch; // switches that appear in the front end; based on switch core
27 class SprinklerSwitch; // switches representing any valve or pump; provides abstraction for latching valves
28 class SprinklerValveOperator; // manages all switching on/off of valves and associated pumps
29 class SprinklerValveRunRequest; // tells the sprinkler controller what valve to run and for how long as well as what
30  // SprinklerValveOperator is handling it
31 template<typename... Ts> class StartSingleValveAction;
32 template<typename... Ts> class ShutdownAction;
33 template<typename... Ts> class ResumeOrStartAction;
34 
36  public:
38  SprinklerSwitch(switch_::Switch *sprinkler_switch);
40 
41  bool is_latching_valve(); // returns true if configured as a latching valve
42  void loop(); // called as a part of loop(), used for latching valve pulses
43  uint32_t pulse_duration() { return this->pulse_duration_; }
44  bool state(); // returns the switch's current state
45  void set_off_switch(switch_::Switch *off_switch) { this->off_switch_ = off_switch; }
46  void set_on_switch(switch_::Switch *on_switch) { this->on_switch_ = on_switch; }
47  void set_pulse_duration(uint32_t pulse_duration) { this->pulse_duration_ = pulse_duration; }
48  void sync_valve_state(
49  bool latch_state); // syncs internal state to switch; if latching valve, sets state to latch_state
50  void turn_off(); // sets internal flag and actuates the switch
51  void turn_on(); // sets internal flag and actuates the switch
52  switch_::Switch *off_switch() { return this->off_switch_; }
53  switch_::Switch *on_switch() { return this->on_switch_; }
54 
55  protected:
56  bool state_{false};
57  uint32_t pulse_duration_{0};
58  uint64_t pinned_millis_{0};
59  switch_::Switch *off_switch_{nullptr}; // only used for latching valves
60  switch_::Switch *on_switch_{nullptr}; // used for both latching and non-latching valves
61 };
62 
64  size_t valve_number;
65  uint32_t run_duration;
66 };
67 
69  const std::string name;
70  bool active;
71  uint32_t time;
72  uint32_t start_time;
73  std::function<void()> func;
74 };
75 
80  uint32_t run_duration;
83  std::unique_ptr<ShutdownAction<>> valve_shutdown_action;
84  std::unique_ptr<StartSingleValveAction<>> valve_resumeorstart_action;
85  std::unique_ptr<Automation<>> valve_turn_off_automation;
86  std::unique_ptr<Automation<>> valve_turn_on_automation;
87 };
88 
90  public:
92 
93  void setup() override;
94  void dump_config() override;
95 
96  void set_state_lambda(std::function<optional<bool>()> &&f);
97  void set_restore_state(bool restore_state);
98  Trigger<> *get_turn_on_trigger() const;
99  Trigger<> *get_turn_off_trigger() const;
100  void set_optimistic(bool optimistic);
101  void set_assumed_state(bool assumed_state);
102  void loop() override;
103 
104  float get_setup_priority() const override;
105 
106  protected:
107  bool assumed_state() override;
108 
109  void write_state(bool state) override;
110 
112  bool optimistic_{false};
113  bool assumed_state_{false};
116  Trigger<> *prev_trigger_{nullptr};
117  bool restore_state_{false};
118 };
119 
121  public:
123  SprinklerValveOperator(SprinklerValve *valve, Sprinkler *controller);
124  void loop();
125  void set_controller(Sprinkler *controller);
126  void set_valve(SprinklerValve *valve);
127  void set_run_duration(uint32_t run_duration); // set the desired run duration in seconds
128  void set_start_delay(uint32_t start_delay, bool start_delay_is_valve_delay);
129  void set_stop_delay(uint32_t stop_delay, bool stop_delay_is_valve_delay);
130  void start();
131  void stop();
132  uint32_t run_duration(); // returns the desired run duration in seconds
133  uint32_t time_remaining(); // returns seconds remaining (does not include stop_delay_)
134  SprinklerState state(); // returns the valve's state/status
135  SprinklerSwitch *pump_switch(); // returns this SprinklerValveOperator's pump's SprinklerSwitch
136 
137  protected:
138  void pump_off_();
139  void pump_on_();
140  void valve_off_();
141  void valve_on_();
142  void kill_();
143  void run_();
144  bool start_delay_is_valve_delay_{false};
145  bool stop_delay_is_valve_delay_{false};
146  uint32_t start_delay_{0};
147  uint32_t stop_delay_{0};
148  uint32_t run_duration_{0};
149  uint64_t pinned_millis_{0};
150  Sprinkler *controller_{nullptr};
151  SprinklerValve *valve_{nullptr};
153 };
154 
156  public:
158  SprinklerValveRunRequest(size_t valve_number, uint32_t run_duration, SprinklerValveOperator *valve_op);
159  bool has_request();
160  bool has_valve_operator();
161  void set_run_duration(uint32_t run_duration);
162  void set_valve(size_t valve_number);
163  void set_valve_operator(SprinklerValveOperator *valve_op);
164  void reset();
165  uint32_t run_duration();
166  size_t valve();
167  optional<size_t> valve_as_opt();
168  SprinklerValveOperator *valve_operator();
169 
170  protected:
171  bool has_valve_{false};
172  size_t valve_number_{0};
173  uint32_t run_duration_{0};
174  SprinklerValveOperator *valve_op_{nullptr};
175 };
176 
177 class Sprinkler : public Component, public EntityBase {
178  public:
179  Sprinkler();
180  Sprinkler(const std::string &name);
181 
182  void setup() override;
183  void loop() override;
184  void dump_config() override;
185 
187  void add_valve(SprinklerControllerSwitch *valve_sw, SprinklerControllerSwitch *enable_sw = nullptr);
188 
190  void add_controller(Sprinkler *other_controller);
191 
193  void set_controller_main_switch(SprinklerControllerSwitch *controller_switch);
194  void set_controller_auto_adv_switch(SprinklerControllerSwitch *auto_adv_switch);
195  void set_controller_queue_enable_switch(SprinklerControllerSwitch *queue_enable_switch);
196  void set_controller_reverse_switch(SprinklerControllerSwitch *reverse_switch);
197 
199  void configure_valve_switch(size_t valve_number, switch_::Switch *valve_switch, uint32_t run_duration);
200  void configure_valve_switch_pulsed(size_t valve_number, switch_::Switch *valve_switch_off,
201  switch_::Switch *valve_switch_on, uint32_t pulse_duration, uint32_t run_duration);
202 
204  void configure_valve_pump_switch(size_t valve_number, switch_::Switch *pump_switch);
205  void configure_valve_pump_switch_pulsed(size_t valve_number, switch_::Switch *pump_switch_off,
206  switch_::Switch *pump_switch_on, uint32_t pulse_duration);
207 
209  void set_multiplier(optional<float> multiplier);
210 
212  void set_pump_start_delay(uint32_t start_delay);
213 
215  void set_pump_stop_delay(uint32_t stop_delay);
216 
218  void set_valve_start_delay(uint32_t start_delay);
219 
221  void set_valve_stop_delay(uint32_t stop_delay);
222 
225  void set_pump_switch_off_during_valve_open_delay(bool pump_switch_off_during_valve_open_delay);
226 
228  void set_valve_open_delay(uint32_t valve_open_delay);
229 
231  void set_valve_overlap(uint32_t valve_overlap);
232 
234  void set_manual_selection_delay(uint32_t manual_selection_delay);
235 
237  void set_valve_run_duration(optional<size_t> valve_number, optional<uint32_t> run_duration);
238 
240  void set_auto_advance(bool auto_advance);
241 
243  void set_repeat(optional<uint32_t> repeat);
244 
246  void set_queue_enable(bool queue_enable);
247 
249  void set_reverse(bool reverse);
250 
252  uint32_t valve_run_duration(size_t valve_number);
253 
255  uint32_t valve_run_duration_adjusted(size_t valve_number);
256 
258  bool auto_advance();
259 
261  float multiplier();
262 
264  optional<uint32_t> repeat();
265 
267  optional<uint32_t> repeat_count();
268 
270  bool queue_enabled();
271 
273  bool reverse();
274 
277  void start_from_queue();
278 
281  void start_full_cycle();
282 
284  void start_single_valve(optional<size_t> valve_number);
285 
288  void queue_valve(optional<size_t> valve_number, optional<uint32_t> run_duration);
289 
291  void clear_queued_valves();
292 
294  void next_valve();
295 
297  void previous_valve();
298 
300  void shutdown(bool clear_queue = false);
301 
303  void pause();
304 
306  void resume();
307 
309  void resume_or_start_full_cycle();
310 
312  void reset_resume();
313 
315  const char *valve_name(size_t valve_number);
316 
318  optional<size_t> active_valve();
319 
321  optional<size_t> paused_valve();
322 
324  optional<size_t> queued_valve();
325 
328  optional<size_t> manual_valve();
329 
331  size_t number_of_valves();
332 
334  bool is_a_valid_valve(size_t valve_number);
335 
337  bool pump_in_use(SprinklerSwitch *pump_switch);
338 
340  void set_pump_state(SprinklerSwitch *pump_switch, bool state);
341 
343  optional<uint32_t> time_remaining();
344 
346  SprinklerControllerSwitch *control_switch(size_t valve_number);
347 
349  SprinklerControllerSwitch *enable_switch(size_t valve_number);
350 
352  SprinklerSwitch *valve_switch(size_t valve_number);
353 
355  SprinklerSwitch *valve_pump_switch(size_t valve_number);
356 
358  SprinklerSwitch *valve_pump_switch_by_pump_index(size_t pump_index);
359 
360  protected:
361  uint32_t hash_base() override;
362 
364  bool valve_is_enabled_(size_t valve_number);
365 
367  void mark_valve_cycle_complete_(size_t valve_number);
368 
370  bool valve_cycle_complete_(size_t valve_number);
371 
373  size_t next_valve_number_(size_t first_valve);
374  size_t previous_valve_number_(size_t first_valve);
375 
378  optional<size_t> next_valve_number_in_cycle_(optional<size_t> first_valve = nullopt);
379 
384  void load_next_valve_run_request_(optional<size_t> first_valve = nullopt);
385 
388  optional<size_t> next_enabled_incomplete_valve_number_(optional<size_t> first_valve);
389  optional<size_t> previous_enabled_incomplete_valve_number_(optional<size_t> first_valve);
390 
392  bool any_valve_is_enabled_();
393 
396  void start_valve_(SprinklerValveRunRequest *req);
397 
399  void all_valves_off_(bool include_pump = false);
400 
402  void prep_full_cycle_();
403 
405  void reset_cycle_states_();
406 
408  void fsm_request_(size_t requested_valve, uint32_t requested_run_duration = 0);
409 
411  void fsm_kick_();
412 
414  void fsm_transition_();
415 
417  void fsm_transition_from_shutdown_();
418 
420  void fsm_transition_from_valve_run_();
421 
423  void fsm_transition_to_shutdown_();
424 
426  std::string state_as_str_(SprinklerState state);
427 
429  void start_timer_(SprinklerTimerIndex timer_index);
430  bool cancel_timer_(SprinklerTimerIndex timer_index);
432  bool timer_active_(SprinklerTimerIndex timer_index);
434  void set_timer_duration_(SprinklerTimerIndex timer_index, uint32_t time);
436  uint32_t timer_duration_(SprinklerTimerIndex timer_index);
437  std::function<void()> timer_cbf_(SprinklerTimerIndex timer_index);
438 
440  void valve_selection_callback_();
441  void sm_timer_callback_();
442  void pump_stop_delay_callback_();
443 
445  const uint8_t max_queue_size_{100};
446 
448  bool pump_switch_off_during_valve_open_delay_{false};
449 
451  bool valve_overlap_{false};
452 
454  bool start_delay_is_valve_delay_{false};
455  bool stop_delay_is_valve_delay_{false};
456 
458  uint32_t start_delay_{0};
459  uint32_t stop_delay_{0};
460 
463 
466 
469 
472 
475 
478 
481 
484 
487 
489  uint32_t repeat_count_{0};
490 
492  float multiplier_{1.0};
493 
495  std::vector<SprinklerQueueItem> queued_valves_;
496 
498  std::vector<SprinklerSwitch> pump_;
499 
501  std::vector<SprinklerValve> valve_;
502 
504  std::vector<SprinklerValveOperator> valve_op_{2};
505 
507  std::vector<SprinklerTimer> timer_{
508  {this->name_ + "sm", false, 0, 0, std::bind(&Sprinkler::sm_timer_callback_, this)},
509  {this->name_ + "vs", false, 0, 0, std::bind(&Sprinkler::valve_selection_callback_, this)}};
510 
512  std::vector<Sprinkler *> other_controllers_;
513 
515  SprinklerControllerSwitch *auto_adv_sw_{nullptr};
516  SprinklerControllerSwitch *controller_sw_{nullptr};
517  SprinklerControllerSwitch *queue_enable_sw_{nullptr};
518  SprinklerControllerSwitch *reverse_sw_{nullptr};
519 
520  std::unique_ptr<ShutdownAction<>> sprinkler_shutdown_action_;
521  std::unique_ptr<ResumeOrStartAction<>> sprinkler_resumeorstart_action_;
522 
523  std::unique_ptr<Automation<>> sprinkler_turn_off_automation_;
524  std::unique_ptr<Automation<>> sprinkler_turn_on_automation_;
525 };
526 
527 } // namespace sprinkler
528 } // namespace esphome
void setup()
Base class for all switches.
Definition: switch.h:33
const char * name
Definition: stm32flash.h:78
void set_off_switch(switch_::Switch *off_switch)
Definition: sprinkler.h:45
SprinklerControllerSwitch * controller_switch
Definition: sprinkler.h:77
SprinklerValveRunRequest next_req_
The next run request for the controller to consume after active_req_ is complete. ...
Definition: sprinkler.h:474
optional< uint32_t > resume_duration_
Set from time_remaining() when paused.
Definition: sprinkler.h:480
void valve_selection_callback_()
callback functions for timers
Definition: sprinkler.cpp:1283
std::vector< SprinklerValve > valve_
Sprinkler valve objects.
Definition: sprinkler.h:501
optional< uint32_t > switching_delay_
Valve switching delay.
Definition: sprinkler.h:486
void set_pulse_duration(uint32_t pulse_duration)
Definition: sprinkler.h:47
std::unique_ptr< ResumeOrStartAction<> > sprinkler_resumeorstart_action_
Definition: sprinkler.h:521
optional< size_t > pump_switch_index
Definition: sprinkler.h:81
std::unique_ptr< Automation<> > valve_turn_off_automation
Definition: sprinkler.h:85
std::vector< Sprinkler * > other_controllers_
Other Sprinkler instances we should be aware of (used to check if pumps are in use) ...
Definition: sprinkler.h:512
void set_on_switch(switch_::Switch *on_switch)
Definition: sprinkler.h:46
switch_::Switch * on_switch()
Definition: sprinkler.h:53
std::unique_ptr< Automation<> > sprinkler_turn_on_automation_
Definition: sprinkler.h:524
const nullopt_t nullopt((nullopt_t::init()))
std::function< void()> func
Definition: sprinkler.h:73
optional< size_t > manual_valve_
The number of the manually selected valve currently selected.
Definition: sprinkler.h:468
optional< uint32_t > target_repeats_
Set the number of times to repeat a full cycle.
Definition: sprinkler.h:477
std::vector< SprinklerSwitch > pump_
Sprinkler valve pump objects.
Definition: sprinkler.h:498
optional< size_t > paused_valve_
The number of the valve to resume from (if paused)
Definition: sprinkler.h:471
std::unique_ptr< StartSingleValveAction<> > valve_resumeorstart_action
Definition: sprinkler.h:84
void sync_valve_state(bool latch_state)
Definition: sprinkler.cpp:70
std::unique_ptr< ShutdownAction<> > sprinkler_shutdown_action_
Definition: sprinkler.h:520
std::unique_ptr< Automation<> > sprinkler_turn_off_automation_
Definition: sprinkler.h:523
Definition: a4988.cpp:4
optional< uint32_t > manual_selection_delay_
Manual switching delay.
Definition: sprinkler.h:483
std::unique_ptr< Automation<> > valve_turn_on_automation
Definition: sprinkler.h:86
std::vector< SprinklerQueueItem > queued_valves_
Queue of valves to activate next, regardless of auto-advance.
Definition: sprinkler.h:495
SprinklerControllerSwitch * enable_switch
Definition: sprinkler.h:78
switch_::Switch * off_switch()
Definition: sprinkler.h:52
SprinklerValveRunRequest active_req_
The valve run request that is currently active.
Definition: sprinkler.h:465
std::unique_ptr< ShutdownAction<> > valve_shutdown_action
Definition: sprinkler.h:83