ESPHome 2026.1.2
Loading...
Searching...
No Matches
filter.h
Go to the documentation of this file.
1#pragma once
2
3#include <queue>
4#include <utility>
5#include <vector>
9
10namespace esphome::sensor {
11
12class Sensor;
13
19class Filter {
20 public:
30 virtual optional<float> new_value(float value) = 0;
31
33 virtual void initialize(Sensor *parent, Filter *next);
34
35 void input(float value);
36
37 void output(float value);
38
39 protected:
40 friend Sensor;
41
42 Filter *next_{nullptr};
43 Sensor *parent_{nullptr};
44};
45
52 public:
53 SlidingWindowFilter(size_t window_size, size_t send_every, size_t send_first_at);
54
55 optional<float> new_value(float value) final;
56
57 protected:
59 virtual float compute_result() = 0;
60
64 size_t window_head_{0};
65 size_t window_count_{0};
66 size_t window_size_;
67 size_t send_every_;
68 size_t send_at_;
69};
70
76 public:
78
79 protected:
82 template<typename Compare> float find_extremum_() {
83 float result = NAN;
84 Compare comp;
85 for (size_t i = 0; i < this->window_count_; i++) {
86 float v = this->window_[i];
87 if (!std::isnan(v)) {
88 result = std::isnan(result) ? v : (comp(v, result) ? v : result);
89 }
90 }
91 return result;
92 }
93};
94
109
115 public:
125 explicit QuantileFilter(size_t window_size, size_t send_every, size_t send_first_at, float quantile);
126
127 void set_quantile(float quantile) { this->quantile_ = quantile; }
128
129 protected:
130 float compute_result() override;
132};
133
139 public:
148 using SortedWindowFilter::SortedWindowFilter;
149
150 protected:
151 float compute_result() override;
152};
153
158class SkipInitialFilter : public Filter {
159 public:
164 explicit SkipInitialFilter(size_t num_to_ignore);
165
166 optional<float> new_value(float value) override;
167
168 protected:
170};
171
176class MinFilter : public MinMaxFilter {
177 public:
186 using MinMaxFilter::MinMaxFilter;
187
188 protected:
189 float compute_result() override;
190};
191
196class MaxFilter : public MinMaxFilter {
197 public:
206 using MinMaxFilter::MinMaxFilter;
207
208 protected:
209 float compute_result() override;
210};
211
218 public:
228
229 protected:
230 float compute_result() override;
231};
232
239 public:
240 ExponentialMovingAverageFilter(float alpha, size_t send_every, size_t send_first_at);
241
242 optional<float> new_value(float value) override;
243
244 void set_send_every(size_t send_every);
245 void set_alpha(float alpha);
246
247 protected:
248 float accumulator_{NAN};
249 float alpha_;
251 size_t send_at_;
252 bool first_value_{true};
253};
254
259class ThrottleAverageFilter : public Filter, public Component {
260 public:
261 explicit ThrottleAverageFilter(uint32_t time_period);
262
263 void setup() override;
264
265 optional<float> new_value(float value) override;
266
267 float get_setup_priority() const override;
268
269 protected:
270 float sum_{0.0f};
271 unsigned int n_{0};
272 uint32_t time_period_;
273 bool have_nan_{false};
274};
275
276using lambda_filter_t = std::function<optional<float>(float)>;
277
285class LambdaFilter : public Filter {
286 public:
287 explicit LambdaFilter(lambda_filter_t lambda_filter);
288
289 optional<float> new_value(float value) override;
290
291 const lambda_filter_t &get_lambda_filter() const;
292 void set_lambda_filter(const lambda_filter_t &lambda_filter);
293
294 protected:
296};
297
304 public:
305 explicit StatelessLambdaFilter(optional<float> (*lambda_filter)(float)) : lambda_filter_(lambda_filter) {}
306
307 optional<float> new_value(float value) override { return this->lambda_filter_(value); }
308
309 protected:
311};
312
314class OffsetFilter : public Filter {
315 public:
316 explicit OffsetFilter(TemplatableValue<float> offset);
317
318 optional<float> new_value(float value) override;
319
320 protected:
322};
323
325class MultiplyFilter : public Filter {
326 public:
327 explicit MultiplyFilter(TemplatableValue<float> multiplier);
328 optional<float> new_value(float value) override;
329
330 protected:
332};
333
340class ValueListFilter : public Filter {
341 protected:
342 explicit ValueListFilter(std::initializer_list<TemplatableValue<float>> values);
343
345 bool value_matches_any_(float sensor_value);
346
348};
349
352 public:
353 explicit FilterOutValueFilter(std::initializer_list<TemplatableValue<float>> values_to_filter_out);
354
355 optional<float> new_value(float value) override;
356};
357
358class ThrottleFilter : public Filter {
359 public:
360 explicit ThrottleFilter(uint32_t min_time_between_inputs);
361
362 optional<float> new_value(float value) override;
363
364 protected:
365 uint32_t last_input_{0};
367};
368
371 public:
372 explicit ThrottleWithPriorityFilter(uint32_t min_time_between_inputs,
373 std::initializer_list<TemplatableValue<float>> prioritized_values);
374
375 optional<float> new_value(float value) override;
376
377 protected:
378 uint32_t last_input_{0};
380};
381
382// Base class for timeout filters - contains common loop logic
383class TimeoutFilterBase : public Filter, public Component {
384 public:
385 void loop() override;
386 float get_setup_priority() const override;
387
388 protected:
389 explicit TimeoutFilterBase(uint32_t time_period) : time_period_(time_period) { this->disable_loop(); }
390 virtual float get_output_value() = 0;
391
392 uint32_t time_period_; // 4 bytes (timeout duration in ms)
393 uint32_t timeout_start_time_{0}; // 4 bytes (when the timeout was started)
394 // Total base: 8 bytes
395};
396
397// Timeout filter for "last" mode - outputs the last received value after timeout
399 public:
400 explicit TimeoutFilterLast(uint32_t time_period) : TimeoutFilterBase(time_period) {}
401
402 optional<float> new_value(float value) override;
403
404 protected:
405 float get_output_value() override { return this->pending_value_; }
406 float pending_value_{0}; // 4 bytes (value to output when timeout fires)
407 // Total: 8 (base) + 4 = 12 bytes + vtable ptr + Component overhead
408};
409
410// Timeout filter with configured value - evaluates TemplatableValue after timeout
412 public:
413 explicit TimeoutFilterConfigured(uint32_t time_period, const TemplatableValue<float> &new_value)
414 : TimeoutFilterBase(time_period), value_(new_value) {}
415
416 optional<float> new_value(float value) override;
417
418 protected:
419 float get_output_value() override { return this->value_.value(); }
420 TemplatableValue<float> value_; // 16 bytes (configured output value, can be lambda)
421 // Total: 8 (base) + 16 = 24 bytes + vtable ptr + Component overhead
422};
423
424class DebounceFilter : public Filter, public Component {
425 public:
426 explicit DebounceFilter(uint32_t time_period);
427
428 optional<float> new_value(float value) override;
429
430 float get_setup_priority() const override;
431
432 protected:
433 uint32_t time_period_;
434};
435
436class HeartbeatFilter : public Filter, public Component {
437 public:
438 explicit HeartbeatFilter(uint32_t time_period);
439
440 void setup() override;
441 optional<float> new_value(float value) override;
442 float get_setup_priority() const override;
443
444 void set_optimistic(bool optimistic) { this->optimistic_ = optimistic; }
445
446 protected:
447 uint32_t time_period_;
449 bool has_value_{false};
450 bool optimistic_{false};
451};
452
453class DeltaFilter : public Filter {
454 public:
455 explicit DeltaFilter(float delta, bool percentage_mode);
456
457 optional<float> new_value(float value) override;
458
459 protected:
460 float delta_;
462 float last_value_{NAN};
464};
465
466class OrFilter : public Filter {
467 public:
468 explicit OrFilter(std::initializer_list<Filter *> filters);
469
470 void initialize(Sensor *parent, Filter *next) override;
471
472 optional<float> new_value(float value) override;
473
474 protected:
475 class PhiNode : public Filter {
476 public:
477 PhiNode(OrFilter *or_parent);
478 optional<float> new_value(float value) override;
479
480 protected:
482 };
483
486 bool has_value_{false};
487};
488
490 public:
491 explicit CalibrateLinearFilter(std::initializer_list<std::array<float, 3>> linear_functions);
492 optional<float> new_value(float value) override;
493
494 protected:
496};
497
499 public:
500 explicit CalibratePolynomialFilter(std::initializer_list<float> coefficients);
501 optional<float> new_value(float value) override;
502
503 protected:
505};
506
507class ClampFilter : public Filter {
508 public:
509 ClampFilter(float min, float max, bool ignore_out_of_range);
510 optional<float> new_value(float value) override;
511
512 protected:
513 float min_{NAN};
514 float max_{NAN};
516};
517
518class RoundFilter : public Filter {
519 public:
520 explicit RoundFilter(uint8_t precision);
521 optional<float> new_value(float value) override;
522
523 protected:
524 uint8_t precision_;
525};
526
528 public:
529 explicit RoundMultipleFilter(float multiple);
530 optional<float> new_value(float value) override;
531
532 protected:
534};
535
537 public:
538 ToNTCResistanceFilter(double a, double b, double c) : a_(a), b_(b), c_(c) {}
539 optional<float> new_value(float value) override;
540
541 protected:
542 double a_;
543 double b_;
544 double c_;
545};
546
548 public:
549 ToNTCTemperatureFilter(double a, double b, double c) : a_(a), b_(b), c_(c) {}
550 optional<float> new_value(float value) override;
551
552 protected:
553 double a_;
554 double b_;
555 double c_;
556};
557
563class StreamingFilter : public Filter {
564 public:
565 StreamingFilter(size_t window_size, size_t send_first_at);
566
567 optional<float> new_value(float value) final;
568
569 protected:
571 virtual void process_value(float value) = 0;
572
574 virtual float compute_batch_result() = 0;
575
577 virtual void reset_batch() = 0;
578
580 size_t count_{0};
582 bool first_send_{true};
583};
584
590 public:
592
593 protected:
594 void process_value(float value) override;
595 float compute_batch_result() override;
596 void reset_batch() override;
597
598 float current_min_{NAN};
599};
600
606 public:
608
609 protected:
610 void process_value(float value) override;
611 float compute_batch_result() override;
612 void reset_batch() override;
613
614 float current_max_{NAN};
615};
616
622 public:
624
625 protected:
626 void process_value(float value) override;
627 float compute_batch_result() override;
628 void reset_batch() override;
629
630 float sum_{0.0f};
631 size_t valid_count_{0};
632};
633
634} // namespace esphome::sensor
void disable_loop()
Disable this component's loop.
Fixed-capacity vector - allocates once at runtime, never reallocates This avoids std::vector template...
Definition helpers.h:188
T value(X... x) const
Definition automation.h:148
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
Simple exponential moving average filter.
Definition filter.h:238
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
A simple filter that only forwards the filter chain if it doesn't receive value_to_filter_out.
Definition filter.h:351
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
void set_optimistic(bool optimistic)
Definition filter.h:444
float get_setup_priority() const override
Definition filter.cpp:414
This class allows for creation of simple template filters.
Definition filter.h:285
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
Simple max filter.
Definition filter.h:196
float compute_result() override
Definition filter.cpp:138
Simple median filter.
Definition filter.h:138
float compute_result() override
Definition filter.cpp:82
Simple min filter.
Definition filter.h:176
float compute_result() override
Definition filter.cpp:135
Base class for Min/Max filters.
Definition filter.h:75
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
A simple filter that multiplies to each value it receives by multiplier.
Definition filter.h:325
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
A simple filter that adds offset to each value it receives.
Definition filter.h:314
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
Simple quantile filter.
Definition filter.h:114
float compute_result() override
Definition filter.cpp:121
void set_quantile(float quantile)
Definition filter.h:127
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
SkipInitialFilter(size_t num_to_ignore)
Construct a SkipInitialFilter.
Definition filter.cpp:105
optional< float > new_value(float value) override
Definition filter.cpp:106
Base class for filters that use a sliding window of values.
Definition filter.h:51
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
Simple sliding window moving average filter.
Definition filter.h:217
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
Optimized lambda filter for stateless lambdas (no capture).
Definition filter.h:303
optional< float >(* lambda_filter_)(float)
Definition filter.h:310
optional< float > new_value(float value) override
Definition filter.h:307
StatelessLambdaFilter(optional< float >(*lambda_filter)(float))
Definition filter.h:305
Base class for streaming filters (batch windows where window_size == send_every).
Definition filter.h:563
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
Streaming max filter for batch windows (window_size == send_every).
Definition filter.h:605
void process_value(float value) override
Definition filter.cpp:547
float compute_batch_result() override
Definition filter.cpp:554
Streaming min filter for batch windows (window_size == send_every).
Definition filter.h:589
float compute_batch_result() override
Definition filter.cpp:542
void process_value(float value) override
Definition filter.cpp:535
Streaming moving average filter for batch windows (window_size == send_every).
Definition filter.h:621
void process_value(float value) override
Definition filter.cpp:559
Simple throttle average filter.
Definition filter.h:259
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
Same as 'throttle' but will immediately publish values contained in value_to_prioritize.
Definition filter.h:370
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
TimeoutFilterBase(uint32_t time_period)
Definition filter.h:389
float get_setup_priority() const override
Definition filter.cpp:355
TemplatableValue< float > value_
Definition filter.h:420
TimeoutFilterConfigured(uint32_t time_period, const TemplatableValue< float > &new_value)
Definition filter.h:413
optional< float > new_value(float value) override
Definition filter.cpp:370
float get_output_value() override
Definition filter.h:405
TimeoutFilterLast(uint32_t time_period)
Definition filter.h:400
optional< float > new_value(float value) override
Definition filter.cpp:358
optional< float > new_value(float value) override
Definition filter.cpp:480
ToNTCResistanceFilter(double a, double b, double c)
Definition filter.h:538
optional< float > new_value(float value) override
Definition filter.cpp:493
ToNTCTemperatureFilter(double a, double b, double c)
Definition filter.h:549
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
std::function< optional< float >(float)> lambda_filter_t
Definition filter.h:276