ESPHome  2022.8.0
filter.cpp
Go to the documentation of this file.
1 #include "filter.h"
2 
3 #include "binary_sensor.h"
4 #include <utility>
5 
6 namespace esphome {
7 
8 namespace binary_sensor {
9 
10 static const char *const TAG = "sensor.filter";
11 
12 void Filter::output(bool value, bool is_initial) {
13  if (!this->dedup_.next(value))
14  return;
15 
16  if (this->next_ == nullptr) {
17  this->parent_->send_state_internal(value, is_initial);
18  } else {
19  this->next_->input(value, is_initial);
20  }
21 }
22 void Filter::input(bool value, bool is_initial) {
23  auto b = this->new_value(value, is_initial);
24  if (b.has_value()) {
25  this->output(*b, is_initial);
26  }
27 }
28 
29 DelayedOnOffFilter::DelayedOnOffFilter(uint32_t delay) : delay_(delay) {}
30 optional<bool> DelayedOnOffFilter::new_value(bool value, bool is_initial) {
31  if (value) {
32  this->set_timeout("ON_OFF", this->delay_, [this, is_initial]() { this->output(true, is_initial); });
33  } else {
34  this->set_timeout("ON_OFF", this->delay_, [this, is_initial]() { this->output(false, is_initial); });
35  }
36  return {};
37 }
38 
40 
42 optional<bool> DelayedOnFilter::new_value(bool value, bool is_initial) {
43  if (value) {
44  this->set_timeout("ON", this->delay_, [this, is_initial]() { this->output(true, is_initial); });
45  return {};
46  } else {
47  this->cancel_timeout("ON");
48  return false;
49  }
50 }
51 
53 
55 optional<bool> DelayedOffFilter::new_value(bool value, bool is_initial) {
56  if (!value) {
57  this->set_timeout("OFF", this->delay_, [this, is_initial]() { this->output(false, is_initial); });
58  return {};
59  } else {
60  this->cancel_timeout("OFF");
61  return true;
62  }
63 }
64 
66 
67 optional<bool> InvertFilter::new_value(bool value, bool is_initial) { return !value; }
68 
69 AutorepeatFilter::AutorepeatFilter(std::vector<AutorepeatFilterTiming> timings) : timings_(std::move(timings)) {}
70 
71 optional<bool> AutorepeatFilter::new_value(bool value, bool is_initial) {
72  if (value) {
73  // Ignore if already running
74  if (this->active_timing_ != 0)
75  return {};
76 
77  this->next_timing_();
78  return true;
79  } else {
80  this->cancel_timeout("TIMING");
81  this->cancel_timeout("ON_OFF");
82  this->active_timing_ = 0;
83  return false;
84  }
85 }
86 
88  // Entering this method
89  // 1st time: starts waiting the first delay
90  // 2nd time: starts waiting the second delay and starts toggling with the first time_off / _on
91  // last time: no delay to start but have to bump the index to reflect the last
92  if (this->active_timing_ < this->timings_.size())
93  this->set_timeout("TIMING", this->timings_[this->active_timing_].delay, [this]() { this->next_timing_(); });
94 
95  if (this->active_timing_ <= this->timings_.size()) {
96  this->active_timing_++;
97  }
98 
99  if (this->active_timing_ == 2)
100  this->next_value_(false);
101 
102  // Leaving this method: if the toggling is started, it has to use [active_timing_ - 2] for the intervals
103 }
104 
106  const AutorepeatFilterTiming &timing = this->timings_[this->active_timing_ - 2];
107  this->output(val, false); // This is at least the second one so not initial
108  this->set_timeout("ON_OFF", val ? timing.time_on : timing.time_off, [this, val]() { this->next_value_(!val); });
109 }
110 
112 
113 LambdaFilter::LambdaFilter(std::function<optional<bool>(bool)> f) : f_(std::move(f)) {}
114 
115 optional<bool> LambdaFilter::new_value(bool value, bool is_initial) { return this->f_(value); }
116 
117 optional<bool> UniqueFilter::new_value(bool value, bool is_initial) {
118  if (this->last_value_.has_value() && *this->last_value_ == value) {
119  return {};
120  } else {
121  this->last_value_ = value;
122  return value;
123  }
124 }
125 
126 } // namespace binary_sensor
127 
128 } // namespace esphome
LambdaFilter(std::function< optional< bool >(bool)> f)
Definition: filter.cpp:113
float get_setup_priority() const override
Definition: filter.cpp:65
optional< bool > new_value(bool value, bool is_initial) override
Definition: filter.cpp:67
std::vector< AutorepeatFilterTiming > timings_
Definition: filter.h:92
bool cancel_timeout(const std::string &name)
Cancel a timeout function.
Definition: component.cpp:71
std::function< optional< bool >bool)> f_
Definition: filter.h:103
bool next(T value)
Feeds the next item in the series to the deduplicator and returns whether this is a duplicate...
Definition: helpers.h:479
void set_timeout(const std::string &name, uint32_t timeout, std::function< void()> &&f)
Set a timeout function with a unique name.
Definition: component.cpp:67
STL namespace.
optional< bool > new_value(bool value, bool is_initial) override
Definition: filter.cpp:117
virtual optional< bool > new_value(bool value, bool is_initial)=0
optional< bool > new_value(bool value, bool is_initial) override
Definition: filter.cpp:42
void send_state_internal(bool state, bool is_initial)
void input(bool value, bool is_initial)
Definition: filter.cpp:22
void output(bool value, bool is_initial)
Definition: filter.cpp:12
BinarySensor * parent_
Definition: filter.h:24
Deduplicator< bool > dedup_
Definition: filter.h:25
AutorepeatFilter(std::vector< AutorepeatFilterTiming > timings)
Definition: filter.cpp:69
const float HARDWARE
For components that deal with hardware and are very important like GPIO switch.
Definition: component.cpp:17
optional< bool > new_value(bool value, bool is_initial) override
Definition: filter.cpp:30
Definition: a4988.cpp:4
uint32_t val
Definition: datatypes.h:85
optional< bool > new_value(bool value, bool is_initial) override
Definition: filter.cpp:71
float get_setup_priority() const override
Definition: filter.cpp:52
optional< bool > new_value(bool value, bool is_initial) override
Definition: filter.cpp:55
float get_setup_priority() const override
Definition: filter.cpp:111
void IRAM_ATTR HOT delay(uint32_t ms)
Definition: core.cpp:27
float get_setup_priority() const override
Definition: filter.cpp:39
optional< bool > new_value(bool value, bool is_initial) override
Definition: filter.cpp:115