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