ESPHome 2026.1.2
Loading...
Searching...
No Matches
filter.cpp
Go to the documentation of this file.
1#include "filter.h"
2#include <cmath>
4#include "esphome/core/hal.h"
5#include "esphome/core/log.h"
6#include "sensor.h"
7
8namespace esphome::sensor {
9
10static const char *const TAG = "sensor.filter";
11
12// Filter
13void Filter::input(float value) {
14 ESP_LOGVV(TAG, "Filter(%p)::input(%f)", this, value);
15 optional<float> out = this->new_value(value);
16 if (out.has_value())
17 this->output(*out);
18}
19void Filter::output(float value) {
20 if (this->next_ == nullptr) {
21 ESP_LOGVV(TAG, "Filter(%p)::output(%f) -> SENSOR", this, value);
23 } else {
24 ESP_LOGVV(TAG, "Filter(%p)::output(%f) -> %p", this, value, this->next_);
25 this->next_->input(value);
26 }
27}
28void Filter::initialize(Sensor *parent, Filter *next) {
29 ESP_LOGVV(TAG, "Filter(%p)::initialize(parent=%p next=%p)", this, parent, next);
30 this->parent_ = parent;
31 this->next_ = next;
32}
33
34// SlidingWindowFilter
35SlidingWindowFilter::SlidingWindowFilter(size_t window_size, size_t send_every, size_t send_first_at)
36 : window_size_(window_size), send_every_(send_every), send_at_(send_every - send_first_at) {
37 // Allocate ring buffer once at initialization
38 this->window_.init(window_size);
39}
40
42 // Add value to ring buffer
44 // Buffer not yet full - just append
45 this->window_.push_back(value);
46 this->window_count_++;
47 } else {
48 // Buffer full - overwrite oldest value (ring buffer)
49 this->window_[this->window_head_] = value;
50 this->window_head_++;
51 if (this->window_head_ >= this->window_size_) {
52 this->window_head_ = 0;
53 }
54 }
55
56 // Check if we should send a result
57 if (++this->send_at_ >= this->send_every_) {
58 this->send_at_ = 0;
59 float result = this->compute_result();
60 ESP_LOGVV(TAG, "SlidingWindowFilter(%p)::new_value(%f) SENDING %f", this, value, result);
61 return result;
62 }
63 return {};
64}
65
66// SortedWindowFilter
68 // Copy window without NaN values using FixedVector (no heap allocation)
69 // Returns unsorted values - caller will use std::nth_element for partial sorting as needed
70 FixedVector<float> values;
71 values.init(this->window_count_);
72 for (size_t i = 0; i < this->window_count_; i++) {
73 float v = this->window_[i];
74 if (!std::isnan(v)) {
75 values.push_back(v);
76 }
77 }
78 return values;
79}
80
81// MedianFilter
84 if (values.empty())
85 return NAN;
86
87 size_t size = values.size();
88 size_t mid = size / 2;
89
90 if (size % 2) {
91 // Odd number of elements - use nth_element to find middle element
92 std::nth_element(values.begin(), values.begin() + mid, values.end());
93 return values[mid];
94 }
95 // Even number of elements - need both middle elements
96 // Use nth_element to find upper middle element
97 std::nth_element(values.begin(), values.begin() + mid, values.end());
98 float upper = values[mid];
99 // Find the maximum of the lower half (which is now everything before mid)
100 float lower = *std::max_element(values.begin(), values.begin() + mid);
101 return (lower + upper) / 2.0f;
102}
103
104// SkipInitialFilter
105SkipInitialFilter::SkipInitialFilter(size_t num_to_ignore) : num_to_ignore_(num_to_ignore) {}
107 if (num_to_ignore_ > 0) {
109 ESP_LOGV(TAG, "SkipInitialFilter(%p)::new_value(%f) SKIPPING, %zu left", this, value, num_to_ignore_);
110 return {};
111 }
112
113 ESP_LOGV(TAG, "SkipInitialFilter(%p)::new_value(%f) SENDING", this, value);
114 return value;
115}
116
117// QuantileFilter
118QuantileFilter::QuantileFilter(size_t window_size, size_t send_every, size_t send_first_at, float quantile)
119 : SortedWindowFilter(window_size, send_every, send_first_at), quantile_(quantile) {}
120
122 FixedVector<float> values = this->get_window_values_();
123 if (values.empty())
124 return NAN;
125
126 size_t position = ceilf(values.size() * this->quantile_) - 1;
127 ESP_LOGVV(TAG, "QuantileFilter(%p)::position: %zu/%zu", this, position + 1, values.size());
128
129 // Use nth_element to find the quantile element (O(n) instead of O(n log n))
130 std::nth_element(values.begin(), values.begin() + position, values.end());
131 return values[position];
132}
133
134// MinFilter
136
137// MaxFilter
139
140// SlidingWindowMovingAverageFilter
142 float sum = 0;
143 size_t valid_count = 0;
144 for (size_t i = 0; i < this->window_count_; i++) {
145 float v = this->window_[i];
146 if (!std::isnan(v)) {
147 sum += v;
148 valid_count++;
149 }
150 }
151 return valid_count ? sum / valid_count : NAN;
152}
153
154// ExponentialMovingAverageFilter
155ExponentialMovingAverageFilter::ExponentialMovingAverageFilter(float alpha, size_t send_every, size_t send_first_at)
156 : alpha_(alpha), send_every_(send_every), send_at_(send_every - send_first_at) {}
158 if (!std::isnan(value)) {
159 if (this->first_value_) {
160 this->accumulator_ = value;
161 this->first_value_ = false;
162 } else {
163 this->accumulator_ = (this->alpha_ * value) + (1.0f - this->alpha_) * this->accumulator_;
164 }
165 }
166
167 const float average = std::isnan(value) ? value : this->accumulator_;
168 ESP_LOGVV(TAG, "ExponentialMovingAverageFilter(%p)::new_value(%f) -> %f", this, value, average);
169
170 if (++this->send_at_ >= this->send_every_) {
171 ESP_LOGVV(TAG, "ExponentialMovingAverageFilter(%p)::new_value(%f) SENDING %f", this, value, average);
172 this->send_at_ = 0;
173 return average;
174 }
175 return {};
176}
177void ExponentialMovingAverageFilter::set_send_every(size_t send_every) { this->send_every_ = send_every; }
178void ExponentialMovingAverageFilter::set_alpha(float alpha) { this->alpha_ = alpha; }
179
180// ThrottleAverageFilter
181ThrottleAverageFilter::ThrottleAverageFilter(uint32_t time_period) : time_period_(time_period) {}
182
184 ESP_LOGVV(TAG, "ThrottleAverageFilter(%p)::new_value(value=%f)", this, value);
185 if (std::isnan(value)) {
186 this->have_nan_ = true;
187 } else {
188 this->sum_ += value;
189 this->n_++;
190 }
191 return {};
192}
194 this->set_interval("throttle_average", this->time_period_, [this]() {
195 ESP_LOGVV(TAG, "ThrottleAverageFilter(%p)::interval(sum=%f, n=%i)", this, this->sum_, this->n_);
196 if (this->n_ == 0) {
197 if (this->have_nan_)
198 this->output(NAN);
199 } else {
200 this->output(this->sum_ / this->n_);
201 this->sum_ = 0.0f;
202 this->n_ = 0;
203 }
204 this->have_nan_ = false;
205 });
206}
208
209// LambdaFilter
210LambdaFilter::LambdaFilter(lambda_filter_t lambda_filter) : lambda_filter_(std::move(lambda_filter)) {}
212void LambdaFilter::set_lambda_filter(const lambda_filter_t &lambda_filter) { this->lambda_filter_ = lambda_filter; }
213
215 auto it = this->lambda_filter_(value);
216 ESP_LOGVV(TAG, "LambdaFilter(%p)::new_value(%f) -> %f", this, value, it.value_or(INFINITY));
217 return it;
218}
219
220// OffsetFilter
221OffsetFilter::OffsetFilter(TemplatableValue<float> offset) : offset_(std::move(offset)) {}
222
223optional<float> OffsetFilter::new_value(float value) { return value + this->offset_.value(); }
224
225// MultiplyFilter
226MultiplyFilter::MultiplyFilter(TemplatableValue<float> multiplier) : multiplier_(std::move(multiplier)) {}
227
228optional<float> MultiplyFilter::new_value(float value) { return value * this->multiplier_.value(); }
229
230// ValueListFilter (base class)
231ValueListFilter::ValueListFilter(std::initializer_list<TemplatableValue<float>> values) : values_(values) {}
232
233bool ValueListFilter::value_matches_any_(float sensor_value) {
234 int8_t accuracy = this->parent_->get_accuracy_decimals();
235 float accuracy_mult = powf(10.0f, accuracy);
236 float rounded_sensor = roundf(accuracy_mult * sensor_value);
237
238 for (auto &filter_value : this->values_) {
239 float fv = filter_value.value();
240
241 // Handle NaN comparison
242 if (std::isnan(fv)) {
243 if (std::isnan(sensor_value))
244 return true;
245 continue;
246 }
247
248 // Compare rounded values
249 if (roundf(accuracy_mult * fv) == rounded_sensor)
250 return true;
251 }
252
253 return false;
254}
255
256// FilterOutValueFilter
257FilterOutValueFilter::FilterOutValueFilter(std::initializer_list<TemplatableValue<float>> values_to_filter_out)
258 : ValueListFilter(values_to_filter_out) {}
259
261 if (this->value_matches_any_(value))
262 return {}; // Filter out
263 return value; // Pass through
264}
265
266// ThrottleFilter
267ThrottleFilter::ThrottleFilter(uint32_t min_time_between_inputs) : min_time_between_inputs_(min_time_between_inputs) {}
269 const uint32_t now = App.get_loop_component_start_time();
270 if (this->last_input_ == 0 || now - this->last_input_ >= min_time_between_inputs_) {
271 this->last_input_ = now;
272 return value;
273 }
274 return {};
275}
276
277// ThrottleWithPriorityFilter
279 uint32_t min_time_between_inputs, std::initializer_list<TemplatableValue<float>> prioritized_values)
280 : ValueListFilter(prioritized_values), min_time_between_inputs_(min_time_between_inputs) {}
281
283 const uint32_t now = App.get_loop_component_start_time();
284 // Allow value through if: no previous input, time expired, or is prioritized
285 if (this->last_input_ == 0 || now - this->last_input_ >= min_time_between_inputs_ ||
286 this->value_matches_any_(value)) {
287 this->last_input_ = now;
288 return value;
289 }
290 return {};
291}
292
293// DeltaFilter
294DeltaFilter::DeltaFilter(float delta, bool percentage_mode)
295 : delta_(delta), current_delta_(delta), last_value_(NAN), percentage_mode_(percentage_mode) {}
297 if (std::isnan(value)) {
298 if (std::isnan(this->last_value_)) {
299 return {};
300 } else {
301 return this->last_value_ = value;
302 }
303 }
304 float diff = fabsf(value - this->last_value_);
305 if (std::isnan(this->last_value_) || (diff > 0.0f && diff >= this->current_delta_)) {
306 if (this->percentage_mode_) {
307 this->current_delta_ = fabsf(value * this->delta_);
308 }
309 return this->last_value_ = value;
310 }
311 return {};
312}
313
314// OrFilter
315OrFilter::OrFilter(std::initializer_list<Filter *> filters) : filters_(filters), phi_(this) {}
316OrFilter::PhiNode::PhiNode(OrFilter *or_parent) : or_parent_(or_parent) {}
317
319 if (!this->or_parent_->has_value_) {
320 this->or_parent_->output(value);
321 this->or_parent_->has_value_ = true;
322 }
323
324 return {};
325}
327 this->has_value_ = false;
328 for (auto *filter : this->filters_)
329 filter->input(value);
330
331 return {};
332}
333void OrFilter::initialize(Sensor *parent, Filter *next) {
334 Filter::initialize(parent, next);
335 for (auto *filter : this->filters_) {
336 filter->initialize(parent, &this->phi_);
337 }
338 this->phi_.initialize(parent, nullptr);
339}
340
341// TimeoutFilterBase - shared loop logic
343 // Check if timeout period has elapsed
344 // Use cached loop start time to avoid repeated millis() calls
345 const uint32_t now = App.get_loop_component_start_time();
346 if (now - this->timeout_start_time_ >= this->time_period_) {
347 // Timeout fired - get output value from derived class and output it
348 this->output(this->get_output_value());
349
350 // Disable loop until next value arrives
351 this->disable_loop();
352 }
353}
354
356
357// TimeoutFilterLast - "last" mode implementation
359 // Store the value to output when timeout fires
360 this->pending_value_ = value;
361
362 // Record when timeout started and enable loop
363 this->timeout_start_time_ = millis();
364 this->enable_loop();
365
366 return value;
367}
368
369// TimeoutFilterConfigured - configured value mode implementation
371 // Record when timeout started and enable loop
372 // Note: we don't store the incoming value since we have a configured value
373 this->timeout_start_time_ = millis();
374 this->enable_loop();
375
376 return value;
377}
378
379// DebounceFilter
381 this->set_timeout("debounce", this->time_period_, [this, value]() { this->output(value); });
382
383 return {};
384}
385
386DebounceFilter::DebounceFilter(uint32_t time_period) : time_period_(time_period) {}
388
389// HeartbeatFilter
390HeartbeatFilter::HeartbeatFilter(uint32_t time_period) : time_period_(time_period), last_input_(NAN) {}
391
393 ESP_LOGVV(TAG, "HeartbeatFilter(%p)::new_value(value=%f)", this, value);
394 this->last_input_ = value;
395 this->has_value_ = true;
396
397 if (this->optimistic_) {
398 return value;
399 }
400 return {};
401}
402
404 this->set_interval("heartbeat", this->time_period_, [this]() {
405 ESP_LOGVV(TAG, "HeartbeatFilter(%p)::interval(has_value=%s, last_input=%f)", this, YESNO(this->has_value_),
406 this->last_input_);
407 if (!this->has_value_)
408 return;
409
410 this->output(this->last_input_);
411 });
412}
413
415
416CalibrateLinearFilter::CalibrateLinearFilter(std::initializer_list<std::array<float, 3>> linear_functions)
417 : linear_functions_(linear_functions) {}
418
420 for (const auto &f : this->linear_functions_) {
421 if (!std::isfinite(f[2]) || value < f[2])
422 return (value * f[0]) + f[1];
423 }
424 return NAN;
425}
426
427CalibratePolynomialFilter::CalibratePolynomialFilter(std::initializer_list<float> coefficients)
428 : coefficients_(coefficients) {}
429
431 float res = 0.0f;
432 float x = 1.0f;
433 for (const auto &coefficient : this->coefficients_) {
434 res += x * coefficient;
435 x *= value;
436 }
437 return res;
438}
439
440ClampFilter::ClampFilter(float min, float max, bool ignore_out_of_range)
441 : min_(min), max_(max), ignore_out_of_range_(ignore_out_of_range) {}
443 if (std::isfinite(value)) {
444 if (std::isfinite(this->min_) && value < this->min_) {
445 if (this->ignore_out_of_range_) {
446 return {};
447 } else {
448 return this->min_;
449 }
450 }
451
452 if (std::isfinite(this->max_) && value > this->max_) {
453 if (this->ignore_out_of_range_) {
454 return {};
455 } else {
456 return this->max_;
457 }
458 }
459 }
460 return value;
461}
462
463RoundFilter::RoundFilter(uint8_t precision) : precision_(precision) {}
465 if (std::isfinite(value)) {
466 float accuracy_mult = powf(10.0f, this->precision_);
467 return roundf(accuracy_mult * value) / accuracy_mult;
468 }
469 return value;
470}
471
472RoundMultipleFilter::RoundMultipleFilter(float multiple) : multiple_(multiple) {}
474 if (std::isfinite(value)) {
475 return value - remainderf(value, this->multiple_);
476 }
477 return value;
478}
479
481 if (!std::isfinite(value)) {
482 return NAN;
483 }
484 double k = 273.15;
485 // https://de.wikipedia.org/wiki/Steinhart-Hart-Gleichung#cite_note-stein2_s4-3
486 double t = value + k;
487 double y = (this->a_ - 1 / (t)) / (2 * this->c_);
488 double x = sqrt(pow(this->b_ / (3 * this->c_), 3) + y * y);
489 double resistance = exp(pow(x - y, 1 / 3.0) - pow(x + y, 1 / 3.0));
490 return resistance;
491}
492
494 if (!std::isfinite(value)) {
495 return NAN;
496 }
497 double lr = log(double(value));
498 double v = this->a_ + this->b_ * lr + this->c_ * lr * lr * lr;
499 double temp = float(1.0 / v - 273.15);
500 return temp;
501}
502
503// StreamingFilter (base class)
504StreamingFilter::StreamingFilter(size_t window_size, size_t send_first_at)
505 : window_size_(window_size), send_first_at_(send_first_at) {}
506
508 // Process the value (child class tracks min/max/sum/etc)
509 this->process_value(value);
510
511 this->count_++;
512
513 // Check if we should send (handle send_first_at for first value)
514 bool should_send = false;
515 if (this->first_send_ && this->count_ >= this->send_first_at_) {
516 should_send = true;
517 this->first_send_ = false;
518 } else if (!this->first_send_ && this->count_ >= this->window_size_) {
519 should_send = true;
520 }
521
522 if (should_send) {
523 float result = this->compute_batch_result();
524 // Reset for next batch
525 this->count_ = 0;
526 this->reset_batch();
527 ESP_LOGVV(TAG, "StreamingFilter(%p)::new_value(%f) SENDING %f", this, value, result);
528 return result;
529 }
530
531 return {};
532}
533
534// StreamingMinFilter
536 // Update running minimum (ignore NaN values)
537 if (!std::isnan(value)) {
538 this->current_min_ = std::isnan(this->current_min_) ? value : std::min(this->current_min_, value);
539 }
540}
541
543
545
546// StreamingMaxFilter
548 // Update running maximum (ignore NaN values)
549 if (!std::isnan(value)) {
550 this->current_max_ = std::isnan(this->current_max_) ? value : std::max(this->current_max_, value);
551 }
552}
553
555
557
558// StreamingMovingAverageFilter
560 // Accumulate sum (ignore NaN values)
561 if (!std::isnan(value)) {
562 this->sum_ += value;
563 this->valid_count_++;
564 }
566
568 return this->valid_count_ > 0 ? this->sum_ / this->valid_count_ : NAN;
569}
570
572 this->sum_ = 0.0f;
573 this->valid_count_ = 0;
574}
575
576} // namespace esphome::sensor
uint32_t IRAM_ATTR HOT get_loop_component_start_time() const
Get the cached time in milliseconds from when the current component started its loop execution.
ESPDEPRECATED("Use const char* or uint32_t overload instead. Removed in 2026.7.0", "2026.1.0") void set_interval(const std voi set_interval)(const char *name, uint32_t interval, std::function< void()> &&f)
Set an interval function with a unique name.
Definition component.h:327
Fixed-capacity vector - allocates once at runtime, never reallocates This avoids std::vector template...
Definition helpers.h:188
bool empty() const
Definition helpers.h:346
size_t size() const
Definition helpers.h:345
void push_back(const T &value)
Add element without bounds checking Caller must ensure sufficient capacity was allocated via init() S...
Definition helpers.h:305
void init(size_t n)
Definition helpers.h:278
T value(X... x) const
Definition automation.h:148
bool has_value() const
Definition optional.h:92
FixedVector< std::array< float, 3 > > linear_functions_
Definition filter.h:495
optional< float > new_value(float value) override
Definition filter.cpp:419
CalibrateLinearFilter(std::initializer_list< std::array< float, 3 > > linear_functions)
Definition filter.cpp:416
CalibratePolynomialFilter(std::initializer_list< float > coefficients)
Definition filter.cpp:427
optional< float > new_value(float value) override
Definition filter.cpp:430
ClampFilter(float min, float max, bool ignore_out_of_range)
Definition filter.cpp:440
optional< float > new_value(float value) override
Definition filter.cpp:442
optional< float > new_value(float value) override
Definition filter.cpp:380
float get_setup_priority() const override
Definition filter.cpp:387
DebounceFilter(uint32_t time_period)
Definition filter.cpp:386
DeltaFilter(float delta, bool percentage_mode)
Definition filter.cpp:294
optional< float > new_value(float value) override
Definition filter.cpp:296
optional< float > new_value(float value) override
Definition filter.cpp:157
ExponentialMovingAverageFilter(float alpha, size_t send_every, size_t send_first_at)
Definition filter.cpp:155
Apply a filter to sensor values such as moving average.
Definition filter.h:19
virtual optional< float > new_value(float value)=0
This will be called every time the filter receives a new value.
void output(float value)
Definition filter.cpp:19
virtual void initialize(Sensor *parent, Filter *next)
Initialize this filter, please note this can be called more than once.
Definition filter.cpp:28
void input(float value)
Definition filter.cpp:13
optional< float > new_value(float value) override
Definition filter.cpp:260
FilterOutValueFilter(std::initializer_list< TemplatableValue< float > > values_to_filter_out)
Definition filter.cpp:257
HeartbeatFilter(uint32_t time_period)
Definition filter.cpp:390
optional< float > new_value(float value) override
Definition filter.cpp:392
float get_setup_priority() const override
Definition filter.cpp:414
const lambda_filter_t & get_lambda_filter() const
Definition filter.cpp:211
LambdaFilter(lambda_filter_t lambda_filter)
Definition filter.cpp:210
lambda_filter_t lambda_filter_
Definition filter.h:295
void set_lambda_filter(const lambda_filter_t &lambda_filter)
Definition filter.cpp:212
optional< float > new_value(float value) override
Definition filter.cpp:214
float compute_result() override
Definition filter.cpp:138
float compute_result() override
Definition filter.cpp:82
float compute_result() override
Definition filter.cpp:135
float find_extremum_()
Helper to find min or max value in window, skipping NaN values Usage: find_extremum_<std::less<float>...
Definition filter.h:82
optional< float > new_value(float value) override
Definition filter.cpp:228
MultiplyFilter(TemplatableValue< float > multiplier)
Definition filter.cpp:226
TemplatableValue< float > multiplier_
Definition filter.h:331
optional< float > new_value(float value) override
Definition filter.cpp:223
OffsetFilter(TemplatableValue< float > offset)
Definition filter.cpp:221
TemplatableValue< float > offset_
Definition filter.h:321
optional< float > new_value(float value) override
Definition filter.cpp:318
PhiNode(OrFilter *or_parent)
Definition filter.cpp:316
OrFilter(std::initializer_list< Filter * > filters)
Definition filter.cpp:315
optional< float > new_value(float value) override
Definition filter.cpp:326
void initialize(Sensor *parent, Filter *next) override
Definition filter.cpp:333
FixedVector< Filter * > filters_
Definition filter.h:484
float compute_result() override
Definition filter.cpp:121
QuantileFilter(size_t window_size, size_t send_every, size_t send_first_at, float quantile)
Construct a QuantileFilter.
Definition filter.cpp:118
RoundFilter(uint8_t precision)
Definition filter.cpp:463
optional< float > new_value(float value) override
Definition filter.cpp:464
optional< float > new_value(float value) override
Definition filter.cpp:473
Base-class for all sensors.
Definition sensor.h:42
void internal_send_state_to_frontend(float state)
Definition sensor.cpp:126
int8_t get_accuracy_decimals()
Get the accuracy in decimals, using the manual override if set.
Definition sensor.cpp:56
SkipInitialFilter(size_t num_to_ignore)
Construct a SkipInitialFilter.
Definition filter.cpp:105
optional< float > new_value(float value) override
Definition filter.cpp:106
size_t window_head_
Index where next value will be written.
Definition filter.h:64
size_t window_size_
Maximum window size.
Definition filter.h:66
optional< float > new_value(float value) final
Definition filter.cpp:41
size_t window_count_
Number of valid values in window (0 to window_size_)
Definition filter.h:65
FixedVector< float > window_
Access the sliding window values (ring buffer implementation) Use: for (size_t i = 0; i < window_coun...
Definition filter.h:63
size_t send_at_
Counter for send_every.
Definition filter.h:68
size_t send_every_
Send result every N values.
Definition filter.h:67
virtual float compute_result()=0
Called by new_value() to compute the filtered result from the current window.
SlidingWindowFilter(size_t window_size, size_t send_every, size_t send_first_at)
Definition filter.cpp:35
Base class for filters that need a sorted window (Median, Quantile).
Definition filter.h:100
FixedVector< float > get_window_values_()
Helper to get non-NaN values from the window (not sorted - caller will use nth_element) Returns empty...
Definition filter.cpp:67
virtual void process_value(float value)=0
Called by new_value() to process each value in the batch.
virtual float compute_batch_result()=0
Called by new_value() to compute the result after collecting window_size values.
StreamingFilter(size_t window_size, size_t send_first_at)
Definition filter.cpp:504
virtual void reset_batch()=0
Called by new_value() to reset internal state after sending a result.
optional< float > new_value(float value) final
Definition filter.cpp:507
void process_value(float value) override
Definition filter.cpp:547
float compute_batch_result() override
Definition filter.cpp:554
float compute_batch_result() override
Definition filter.cpp:542
void process_value(float value) override
Definition filter.cpp:535
void process_value(float value) override
Definition filter.cpp:559
optional< float > new_value(float value) override
Definition filter.cpp:183
ThrottleAverageFilter(uint32_t time_period)
Definition filter.cpp:181
float get_setup_priority() const override
Definition filter.cpp:207
ThrottleFilter(uint32_t min_time_between_inputs)
Definition filter.cpp:267
optional< float > new_value(float value) override
Definition filter.cpp:268
optional< float > new_value(float value) override
Definition filter.cpp:282
ThrottleWithPriorityFilter(uint32_t min_time_between_inputs, std::initializer_list< TemplatableValue< float > > prioritized_values)
Definition filter.cpp:278
float get_setup_priority() const override
Definition filter.cpp:355
optional< float > new_value(float value) override
Definition filter.cpp:370
optional< float > new_value(float value) override
Definition filter.cpp:358
optional< float > new_value(float value) override
Definition filter.cpp:480
optional< float > new_value(float value) override
Definition filter.cpp:493
Base class for filters that compare sensor values against a list of configured values.
Definition filter.h:340
ValueListFilter(std::initializer_list< TemplatableValue< float > > values)
Definition filter.cpp:231
FixedVector< TemplatableValue< float > > values_
Definition filter.h:347
bool value_matches_any_(float sensor_value)
Check if sensor value matches any configured value (with accuracy rounding)
Definition filter.cpp:233
float position
Definition cover.h:0
std::function< optional< float >(float)> lambda_filter_t
Definition filter.h:276
const float HARDWARE
For components that deal with hardware and are very important like GPIO switch.
Definition component.cpp:80
uint32_t IRAM_ATTR HOT millis()
Definition core.cpp:25
Application App
Global storage of Application pointer - only one Application can exist.
uint16_t x
Definition tt21100.cpp:5
uint16_t y
Definition tt21100.cpp:6