ESPHome 2026.5.2
Loading...
Searching...
No Matches
filter.cpp
Go to the documentation of this file.
2#ifdef USE_BINARY_SENSOR_FILTER
3
4#include "filter.h"
5
6#include "binary_sensor.h"
8
10
11static const char *const TAG = "sensor.filter";
12
13void Filter::output(bool value) {
14 if (this->next_ == nullptr) {
15 this->parent_->send_state_internal(value);
16 } else {
17 this->next_->input(value);
18 }
19}
20void Filter::input(bool value) {
21 if (!this->dedup_.next(value))
22 return;
23 auto b = this->new_value(value);
24 if (b.has_value()) {
25 this->output(*b);
26 }
27}
28
29void TimeoutFilter::input(bool value) {
30 App.scheduler.set_timeout(this, this->timeout_delay_.value(), [this]() { this->parent_->invalidate_state(); });
31 // we do not de-dup here otherwise changes from invalid to valid state will not be output
32 this->output(value);
33}
34
35optional<bool> DelayedOnOffFilter::new_value(bool value) {
36 if (value) {
37 App.scheduler.set_timeout(this, this->on_delay_.value(), [this]() { this->output(true); });
38 } else {
39 App.scheduler.set_timeout(this, this->off_delay_.value(), [this]() { this->output(false); });
40 }
41 return {};
42}
43
44optional<bool> DelayedOnFilter::new_value(bool value) {
45 if (value) {
46 App.scheduler.set_timeout(this, this->delay_.value(), [this]() { this->output(true); });
47 return {};
48 } else {
49 App.scheduler.cancel_timeout(this);
50 return false;
51 }
52}
53
54optional<bool> DelayedOffFilter::new_value(bool value) {
55 if (!value) {
56 App.scheduler.set_timeout(this, this->delay_.value(), [this]() { this->output(false); });
57 return {};
58 } else {
59 App.scheduler.cancel_timeout(this);
60 return true;
61 }
62}
63
64optional<bool> InvertFilter::new_value(bool value) { return !value; }
65
66// AutorepeatFilterBase
67// Two independent timers per instance, keyed off two stable addresses inside
68// the filter: `this` for the timing-step timer, `&active_timing_` for the
69// on/off timer. Both are unique per instance and don't collide with anything
70// else, so the self-keyed scheduler API is sufficient.
71optional<bool> AutorepeatFilterBase::new_value(bool value) {
72 if (value) {
73 if (this->active_timing_ != 0)
74 return {};
75 this->next_timing_();
76 return true;
77 } else {
78 App.scheduler.cancel_timeout(this);
79 App.scheduler.cancel_timeout(&this->active_timing_);
80 this->active_timing_ = 0;
81 return false;
82 }
83}
84
87 App.scheduler.set_timeout(this, this->timings_[this->active_timing_].delay, [this]() { this->next_timing_(); });
88 }
89 if (this->active_timing_ <= this->timings_count_) {
90 this->active_timing_++;
91 }
92 if (this->active_timing_ == 2)
93 this->next_value_(false);
94}
95
97 const AutorepeatFilterTiming &timing = this->timings_[this->active_timing_ - 2];
98 this->output(val);
99 App.scheduler.set_timeout(&this->active_timing_, val ? timing.time_on : timing.time_off,
100 [this, val]() { this->next_value_(!val); });
101}
102
103LambdaFilter::LambdaFilter(std::function<optional<bool>(bool)> f) : f_(std::move(f)) {}
104
105optional<bool> LambdaFilter::new_value(bool value) { return this->f_(value); }
106
107optional<bool> SettleFilter::new_value(bool value) {
108 if (!this->steady_) {
109 App.scheduler.set_timeout(this, this->delay_.value(), [this, value]() {
110 this->steady_ = true;
111 this->output(value);
112 });
113 return {};
114 } else {
115 this->steady_ = false;
116 App.scheduler.set_timeout(this, this->delay_.value(), [this]() { this->steady_ = true; });
117 return value;
118 }
119}
120
121} // namespace esphome::binary_sensor
122
123#endif // USE_BINARY_SENSOR_FILTER
bool next(T value)
Feeds the next item in the series to the deduplicator and returns false if this is a duplicate.
Definition helpers.h:1836
T value(X... x) const
Definition automation.h:79
optional< bool > new_value(bool value) override
Definition filter.cpp:71
const AutorepeatFilterTiming * timings_
Definition filter.h:100
void send_state_internal(bool new_state)
optional< bool > new_value(bool value) override
Definition filter.cpp:54
TemplatableFn< uint32_t > delay_
Definition filter.h:71
optional< bool > new_value(bool value) override
Definition filter.cpp:44
TemplatableFn< uint32_t > delay_
Definition filter.h:61
TemplatableFn< uint32_t > on_delay_
Definition filter.h:50
TemplatableFn< uint32_t > off_delay_
Definition filter.h:51
optional< bool > new_value(bool value) override
Definition filter.cpp:35
virtual void input(bool value)
Definition filter.cpp:20
virtual optional< bool > new_value(bool value)=0
Deduplicator< bool > dedup_
Definition filter.h:29
void output(bool value)
Definition filter.cpp:13
optional< bool > new_value(bool value) override
Definition filter.cpp:64
LambdaFilter(std::function< optional< bool >(bool)> f)
Definition filter.cpp:103
std::function< optional< bool >(bool)> f_
Definition filter.h:126
optional< bool > new_value(bool value) override
Definition filter.cpp:105
TemplatableFn< uint32_t > delay_
Definition filter.h:151
optional< bool > new_value(bool value) override
Definition filter.cpp:107
TemplatableFn< uint32_t > timeout_delay_
Definition filter.h:39
void input(bool value) override
Definition filter.cpp:29
mopeka_std_values val[3]
void HOT delay(uint32_t ms)
Definition hal.cpp:85
Application App
Global storage of Application pointer - only one Application can exist.