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