ESPHome 2026.3.0-dev
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"
7
9
10static const char *const TAG = "sensor.filter";
11
12// Timeout IDs for filter classes.
13// Each filter is its own Component instance, so the scheduler scopes
14// IDs by component pointer — no risk of collisions between instances.
15constexpr uint32_t FILTER_TIMEOUT_ID = 0;
16// AutorepeatFilter needs two distinct IDs (both timeouts on the same component)
17constexpr uint32_t AUTOREPEAT_TIMING_ID = 0;
18constexpr uint32_t AUTOREPEAT_ON_OFF_ID = 1;
19
20void Filter::output(bool value) {
21 if (this->next_ == nullptr) {
22 this->parent_->send_state_internal(value);
23 } else {
24 this->next_->input(value);
25 }
26}
27void Filter::input(bool value) {
28 if (!this->dedup_.next(value))
29 return;
30 auto b = this->new_value(value);
31 if (b.has_value()) {
32 this->output(*b);
33 }
34}
35
36void TimeoutFilter::input(bool value) {
37 this->set_timeout(FILTER_TIMEOUT_ID, this->timeout_delay_.value(), [this]() { this->parent_->invalidate_state(); });
38 // we do not de-dup here otherwise changes from invalid to valid state will not be output
39 this->output(value);
40}
41
43 if (value) {
44 this->set_timeout(FILTER_TIMEOUT_ID, this->on_delay_.value(), [this]() { this->output(true); });
45 } else {
46 this->set_timeout(FILTER_TIMEOUT_ID, this->off_delay_.value(), [this]() { this->output(false); });
47 }
48 return {};
49}
50
52
54 if (value) {
55 this->set_timeout(FILTER_TIMEOUT_ID, this->delay_.value(), [this]() { this->output(true); });
56 return {};
57 } else {
58 this->cancel_timeout(FILTER_TIMEOUT_ID);
59 return false;
60 }
61}
62
64
66 if (!value) {
67 this->set_timeout(FILTER_TIMEOUT_ID, this->delay_.value(), [this]() { this->output(false); });
68 return {};
69 } else {
70 this->cancel_timeout(FILTER_TIMEOUT_ID);
71 return true;
72 }
73}
74
76
77optional<bool> InvertFilter::new_value(bool value) { return !value; }
78
79AutorepeatFilter::AutorepeatFilter(std::initializer_list<AutorepeatFilterTiming> timings) : timings_(timings) {}
80
82 if (value) {
83 // Ignore if already running
84 if (this->active_timing_ != 0)
85 return {};
86
87 this->next_timing_();
88 return true;
89 } else {
90 this->cancel_timeout(AUTOREPEAT_TIMING_ID);
91 this->cancel_timeout(AUTOREPEAT_ON_OFF_ID);
92 this->active_timing_ = 0;
93 return false;
94 }
95}
96
98 // Entering this method
99 // 1st time: starts waiting the first delay
100 // 2nd time: starts waiting the second delay and starts toggling with the first time_off / _on
101 // last time: no delay to start but have to bump the index to reflect the last
102 if (this->active_timing_ < this->timings_.size()) {
103 this->set_timeout(AUTOREPEAT_TIMING_ID, this->timings_[this->active_timing_].delay,
104 [this]() { this->next_timing_(); });
105 }
106
107 if (this->active_timing_ <= this->timings_.size()) {
108 this->active_timing_++;
109 }
110
111 if (this->active_timing_ == 2)
112 this->next_value_(false);
113
114 // Leaving this method: if the toggling is started, it has to use [active_timing_ - 2] for the intervals
115}
116
118 const AutorepeatFilterTiming &timing = this->timings_[this->active_timing_ - 2];
119 this->output(val); // This is at least the second one so not initial
120 this->set_timeout(AUTOREPEAT_ON_OFF_ID, val ? timing.time_on : timing.time_off,
121 [this, val]() { this->next_value_(!val); });
122}
123
125
126LambdaFilter::LambdaFilter(std::function<optional<bool>(bool)> f) : f_(std::move(f)) {}
127
128optional<bool> LambdaFilter::new_value(bool value) { return this->f_(value); }
129
131 if (!this->steady_) {
132 this->set_timeout(FILTER_TIMEOUT_ID, this->delay_.value(), [this, value]() {
133 this->steady_ = true;
134 this->output(value);
135 });
136 return {};
137 } else {
138 this->steady_ = false;
139 this->output(value);
140 this->set_timeout(FILTER_TIMEOUT_ID, this->delay_.value(), [this]() { this->steady_ = true; });
141 return value;
142 }
143}
144
146
147} // namespace esphome::binary_sensor
148
149#endif // USE_BINARY_SENSOR_FILTER
ESPDEPRECATED("Use const char* or uint32_t overload instead. Removed in 2026.7.0", "2026.1.0") void set_timeout(const std voi set_timeout)(const char *name, uint32_t timeout, std::function< void()> &&f)
Set a timeout function with a unique name.
Definition component.h:443
ESPDEPRECATED("Use const char* or uint32_t overload instead. Removed in 2026.7.0", "2026.1.0") bool cancel_timeout(const std boo cancel_timeout)(const char *name)
Cancel a timeout function.
Definition component.h:465
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:1593
T value(X... x) const
Definition automation.h:160
float get_setup_priority() const override
Definition filter.cpp:124
AutorepeatFilter(std::initializer_list< AutorepeatFilterTiming > timings)
Definition filter.cpp:79
FixedVector< AutorepeatFilterTiming > timings_
Definition filter.h:101
optional< bool > new_value(bool value) override
Definition filter.cpp:81
float get_setup_priority() const override
Definition filter.cpp:75
optional< bool > new_value(bool value) override
Definition filter.cpp:65
TemplatableValue< uint32_t > delay_
Definition filter.h:75
optional< bool > new_value(bool value) override
Definition filter.cpp:53
TemplatableValue< uint32_t > delay_
Definition filter.h:63
float get_setup_priority() const override
Definition filter.cpp:63
TemplatableValue< uint32_t > on_delay_
Definition filter.h:50
float get_setup_priority() const override
Definition filter.cpp:51
optional< bool > new_value(bool value) override
Definition filter.cpp:42
TemplatableValue< uint32_t > off_delay_
Definition filter.h:51
virtual void input(bool value)
Definition filter.cpp:27
virtual optional< bool > new_value(bool value)=0
Deduplicator< bool > dedup_
Definition filter.h:27
void output(bool value)
Definition filter.cpp:20
optional< bool > new_value(bool value) override
Definition filter.cpp:77
LambdaFilter(std::function< optional< bool >(bool)> f)
Definition filter.cpp:126
std::function< optional< bool >(bool)> f_
Definition filter.h:112
optional< bool > new_value(bool value) override
Definition filter.cpp:128
float get_setup_priority() const override
Definition filter.cpp:145
TemplatableValue< uint32_t > delay_
Definition filter.h:139
optional< bool > new_value(bool value) override
Definition filter.cpp:130
void input(bool value) override
Definition filter.cpp:36
TemplatableValue< uint32_t > timeout_delay_
Definition filter.h:37
mopeka_std_values val[4]
constexpr uint32_t AUTOREPEAT_TIMING_ID
Definition filter.cpp:17
constexpr uint32_t AUTOREPEAT_ON_OFF_ID
Definition filter.cpp:18
constexpr uint32_t FILTER_TIMEOUT_ID
Definition filter.cpp:15
constexpr float HARDWARE
For components that deal with hardware and are very important like GPIO switch.
Definition component.h:29
void HOT delay(uint32_t ms)
Definition core.cpp:27