ESPHome 2026.3.0-dev
Loading...
Searching...
No Matches
filter.h
Go to the documentation of this file.
1#pragma once
2
4#ifdef USE_SENSOR_FILTER
5
6#include <utility>
7#include <vector>
11
12namespace esphome::sensor {
13
14class Sensor;
15
21class Filter {
22 public:
32 virtual optional<float> new_value(float value) = 0;
33
35 virtual void initialize(Sensor *parent, Filter *next);
36
37 void input(float value);
38
39 void output(float value);
40
41 protected:
42 friend Sensor;
43
44 Filter *next_{nullptr};
45 Sensor *parent_{nullptr};
46};
47
54 public:
55 SlidingWindowFilter(size_t window_size, size_t send_every, size_t send_first_at);
56
57 optional<float> new_value(float value) final;
58
59 protected:
61 virtual float compute_result() = 0;
62
66 size_t window_head_{0};
67 size_t window_count_{0};
68 size_t window_size_;
69 size_t send_every_;
70 size_t send_at_;
71};
72
78 public:
80
81 protected:
84 template<typename Compare> float find_extremum_() {
85 float result = NAN;
86 Compare comp;
87 for (size_t i = 0; i < this->window_count_; i++) {
88 float v = this->window_[i];
89 if (!std::isnan(v)) {
90 result = std::isnan(result) ? v : (comp(v, result) ? v : result);
91 }
92 }
93 return result;
94 }
95};
96
111
117 public:
127 explicit QuantileFilter(size_t window_size, size_t send_every, size_t send_first_at, float quantile);
128
129 void set_quantile(float quantile) { this->quantile_ = quantile; }
130
131 protected:
132 float compute_result() override;
134};
135
141 public:
150 using SortedWindowFilter::SortedWindowFilter;
151
152 protected:
153 float compute_result() override;
154};
155
160class SkipInitialFilter : public Filter {
161 public:
166 explicit SkipInitialFilter(size_t num_to_ignore);
167
168 optional<float> new_value(float value) override;
169
170 protected:
172};
173
178class MinFilter : public MinMaxFilter {
179 public:
188 using MinMaxFilter::MinMaxFilter;
189
190 protected:
191 float compute_result() override;
192};
193
198class MaxFilter : public MinMaxFilter {
199 public:
208 using MinMaxFilter::MinMaxFilter;
209
210 protected:
211 float compute_result() override;
212};
213
220 public:
230
231 protected:
232 float compute_result() override;
233};
234
241 public:
242 ExponentialMovingAverageFilter(float alpha, size_t send_every, size_t send_first_at);
243
244 optional<float> new_value(float value) override;
245
246 void set_send_every(size_t send_every);
247 void set_alpha(float alpha);
248
249 protected:
250 float accumulator_{NAN};
251 float alpha_;
253 size_t send_at_;
254 bool first_value_{true};
255};
256
261class ThrottleAverageFilter : public Filter, public Component {
262 public:
263 explicit ThrottleAverageFilter(uint32_t time_period);
264
265 void setup() override;
266
267 optional<float> new_value(float value) override;
268
269 float get_setup_priority() const override;
270
271 protected:
272 float sum_{0.0f};
273 unsigned int n_{0};
274 uint32_t time_period_;
275 bool have_nan_{false};
276};
277
278using lambda_filter_t = std::function<optional<float>(float)>;
279
287class LambdaFilter : public Filter {
288 public:
289 explicit LambdaFilter(lambda_filter_t lambda_filter);
290
291 optional<float> new_value(float value) override;
292
293 const lambda_filter_t &get_lambda_filter() const;
294 void set_lambda_filter(const lambda_filter_t &lambda_filter);
295
296 protected:
298};
299
306 public:
307 explicit StatelessLambdaFilter(optional<float> (*lambda_filter)(float)) : lambda_filter_(lambda_filter) {}
308
309 optional<float> new_value(float value) override { return this->lambda_filter_(value); }
310
311 protected:
313};
314
316class OffsetFilter : public Filter {
317 public:
318 explicit OffsetFilter(TemplatableValue<float> offset);
319
320 optional<float> new_value(float value) override;
321
322 protected:
324};
325
327class MultiplyFilter : public Filter {
328 public:
329 explicit MultiplyFilter(TemplatableValue<float> multiplier);
330 optional<float> new_value(float value) override;
331
332 protected:
334};
335
342class ValueListFilter : public Filter {
343 protected:
344 explicit ValueListFilter(std::initializer_list<TemplatableValue<float>> values);
345
347 bool value_matches_any_(float sensor_value);
348
350};
351
354 public:
355 explicit FilterOutValueFilter(std::initializer_list<TemplatableValue<float>> values_to_filter_out);
356
357 optional<float> new_value(float value) override;
358};
359
360class ThrottleFilter : public Filter {
361 public:
362 explicit ThrottleFilter(uint32_t min_time_between_inputs);
363
364 optional<float> new_value(float value) override;
365
366 protected:
367 uint32_t last_input_{0};
369};
370
373 public:
374 explicit ThrottleWithPriorityFilter(uint32_t min_time_between_inputs,
375 std::initializer_list<TemplatableValue<float>> prioritized_values);
376
377 optional<float> new_value(float value) override;
378
379 protected:
380 uint32_t last_input_{0};
382};
383
384// Base class for timeout filters - contains common loop logic
385class TimeoutFilterBase : public Filter, public Component {
386 public:
387 void loop() override;
388 float get_setup_priority() const override;
389
390 protected:
391 explicit TimeoutFilterBase(uint32_t time_period) : time_period_(time_period) { this->disable_loop(); }
392 virtual float get_output_value() = 0;
393
394 uint32_t time_period_; // 4 bytes (timeout duration in ms)
395 uint32_t timeout_start_time_{0}; // 4 bytes (when the timeout was started)
396 // Total base: 8 bytes
397};
398
399// Timeout filter for "last" mode - outputs the last received value after timeout
401 public:
402 explicit TimeoutFilterLast(uint32_t time_period) : TimeoutFilterBase(time_period) {}
403
404 optional<float> new_value(float value) override;
405
406 protected:
407 float get_output_value() override { return this->pending_value_; }
408 float pending_value_{0}; // 4 bytes (value to output when timeout fires)
409 // Total: 8 (base) + 4 = 12 bytes + vtable ptr + Component overhead
410};
411
412// Timeout filter with configured value - evaluates TemplatableValue after timeout
414 public:
415 explicit TimeoutFilterConfigured(uint32_t time_period, const TemplatableValue<float> &new_value)
416 : TimeoutFilterBase(time_period), value_(new_value) {}
417
418 optional<float> new_value(float value) override;
419
420 protected:
421 float get_output_value() override { return this->value_.value(); }
422 TemplatableValue<float> value_; // 16 bytes (configured output value, can be lambda)
423 // Total: 8 (base) + 16 = 24 bytes + vtable ptr + Component overhead
424};
425
426class DebounceFilter : public Filter, public Component {
427 public:
428 explicit DebounceFilter(uint32_t time_period);
429
430 optional<float> new_value(float value) override;
431
432 float get_setup_priority() const override;
433
434 protected:
435 uint32_t time_period_;
436};
437
438class HeartbeatFilter : public Filter, public Component {
439 public:
440 explicit HeartbeatFilter(uint32_t time_period);
441
442 void setup() override;
443 optional<float> new_value(float value) override;
444 float get_setup_priority() const override;
445
446 void set_optimistic(bool optimistic) { this->optimistic_ = optimistic; }
447
448 protected:
449 uint32_t time_period_;
451 bool has_value_{false};
452 bool optimistic_{false};
453};
454
455class DeltaFilter : public Filter {
456 public:
457 explicit DeltaFilter(float min_a0, float min_a1, float max_a0, float max_a1);
458
459 void set_baseline(float (*fn)(float));
460
461 optional<float> new_value(float value) override;
462
463 protected:
464 // These values represent linear equations for the min and max values but in practice only one of a0 and a1 will be
465 // non-zero Each limit is calculated as fabs(a0 + value * a1)
466
468 // default baseline is the previous value
469 float (*baseline_)(float) = [](float last_value) { return last_value; };
470
471 float last_value_{NAN};
472};
473
474class OrFilter : public Filter {
475 public:
476 explicit OrFilter(std::initializer_list<Filter *> filters);
477
478 void initialize(Sensor *parent, Filter *next) override;
479
480 optional<float> new_value(float value) override;
481
482 protected:
483 class PhiNode : public Filter {
484 public:
485 PhiNode(OrFilter *or_parent);
486 optional<float> new_value(float value) override;
487
488 protected:
490 };
491
494 bool has_value_{false};
495};
496
498 public:
499 explicit CalibrateLinearFilter(std::initializer_list<std::array<float, 3>> linear_functions);
500 optional<float> new_value(float value) override;
501
502 protected:
504};
505
507 public:
508 explicit CalibratePolynomialFilter(std::initializer_list<float> coefficients);
509 optional<float> new_value(float value) override;
510
511 protected:
513};
514
515class ClampFilter : public Filter {
516 public:
517 ClampFilter(float min, float max, bool ignore_out_of_range);
518 optional<float> new_value(float value) override;
519
520 protected:
521 float min_{NAN};
522 float max_{NAN};
524};
525
526class RoundFilter : public Filter {
527 public:
528 explicit RoundFilter(uint8_t precision);
529 optional<float> new_value(float value) override;
530
531 protected:
532 uint8_t precision_;
533};
534
536 public:
537 explicit RoundMultipleFilter(float multiple);
538 optional<float> new_value(float value) override;
539
540 protected:
542};
543
545 public:
546 ToNTCResistanceFilter(double a, double b, double c) : a_(a), b_(b), c_(c) {}
547 optional<float> new_value(float value) override;
548
549 protected:
550 double a_;
551 double b_;
552 double c_;
553};
554
556 public:
557 ToNTCTemperatureFilter(double a, double b, double c) : a_(a), b_(b), c_(c) {}
558 optional<float> new_value(float value) override;
559
560 protected:
561 double a_;
562 double b_;
563 double c_;
564};
565
571class StreamingFilter : public Filter {
572 public:
573 StreamingFilter(size_t window_size, size_t send_first_at);
574
575 optional<float> new_value(float value) final;
576
577 protected:
579 virtual void process_value(float value) = 0;
580
582 virtual float compute_batch_result() = 0;
583
585 virtual void reset_batch() = 0;
586
588 size_t count_{0};
590 bool first_send_{true};
591};
592
598 public:
600
601 protected:
602 void process_value(float value) override;
603 float compute_batch_result() override;
604 void reset_batch() override;
605
606 float current_min_{NAN};
607};
608
614 public:
616
617 protected:
618 void process_value(float value) override;
619 float compute_batch_result() override;
620 void reset_batch() override;
621
622 float current_max_{NAN};
623};
624
630 public:
632
633 protected:
634 void process_value(float value) override;
635 float compute_batch_result() override;
636 void reset_batch() override;
637
638 float sum_{0.0f};
639 size_t valid_count_{0};
640};
641
642} // namespace esphome::sensor
643
644#endif // USE_SENSOR_FILTER
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:299
T value(X... x) const
Definition automation.h:160
FixedVector< std::array< float, 3 > > linear_functions_
Definition filter.h:503
optional< float > new_value(float value) override
Definition filter.cpp:433
CalibrateLinearFilter(std::initializer_list< std::array< float, 3 > > linear_functions)
Definition filter.cpp:430
CalibratePolynomialFilter(std::initializer_list< float > coefficients)
Definition filter.cpp:441
optional< float > new_value(float value) override
Definition filter.cpp:444
ClampFilter(float min, float max, bool ignore_out_of_range)
Definition filter.cpp:454
optional< float > new_value(float value) override
Definition filter.cpp:456
optional< float > new_value(float value) override
Definition filter.cpp:394
float get_setup_priority() const override
Definition filter.cpp:401
DebounceFilter(uint32_t time_period)
Definition filter.cpp:400
void set_baseline(float(*fn)(float))
Definition filter.cpp:306
DeltaFilter(float min_a0, float min_a1, float max_a0, float max_a1)
Definition filter.cpp:303
optional< float > new_value(float value) override
Definition filter.cpp:308
float(* baseline_)(float)
Definition filter.h:469
Simple exponential moving average filter.
Definition filter.h:240
optional< float > new_value(float value) override
Definition filter.cpp:166
ExponentialMovingAverageFilter(float alpha, size_t send_every, size_t send_first_at)
Definition filter.cpp:164
Apply a filter to sensor values such as moving average.
Definition filter.h:21
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:28
virtual void initialize(Sensor *parent, Filter *next)
Initialize this filter, please note this can be called more than once.
Definition filter.cpp:37
void input(float value)
Definition filter.cpp:22
A simple filter that only forwards the filter chain if it doesn't receive value_to_filter_out.
Definition filter.h:353
optional< float > new_value(float value) override
Definition filter.cpp:269
FilterOutValueFilter(std::initializer_list< TemplatableValue< float > > values_to_filter_out)
Definition filter.cpp:266
HeartbeatFilter(uint32_t time_period)
Definition filter.cpp:404
optional< float > new_value(float value) override
Definition filter.cpp:406
void set_optimistic(bool optimistic)
Definition filter.h:446
float get_setup_priority() const override
Definition filter.cpp:428
This class allows for creation of simple template filters.
Definition filter.h:287
const lambda_filter_t & get_lambda_filter() const
Definition filter.cpp:220
LambdaFilter(lambda_filter_t lambda_filter)
Definition filter.cpp:219
lambda_filter_t lambda_filter_
Definition filter.h:297
void set_lambda_filter(const lambda_filter_t &lambda_filter)
Definition filter.cpp:221
optional< float > new_value(float value) override
Definition filter.cpp:223
Simple max filter.
Definition filter.h:198
float compute_result() override
Definition filter.cpp:147
Simple median filter.
Definition filter.h:140
float compute_result() override
Definition filter.cpp:91
Simple min filter.
Definition filter.h:178
float compute_result() override
Definition filter.cpp:144
Base class for Min/Max filters.
Definition filter.h:77
float find_extremum_()
Helper to find min or max value in window, skipping NaN values Usage: find_extremum_<std::less<float>...
Definition filter.h:84
A simple filter that multiplies to each value it receives by multiplier.
Definition filter.h:327
optional< float > new_value(float value) override
Definition filter.cpp:237
MultiplyFilter(TemplatableValue< float > multiplier)
Definition filter.cpp:235
TemplatableValue< float > multiplier_
Definition filter.h:333
A simple filter that adds offset to each value it receives.
Definition filter.h:316
optional< float > new_value(float value) override
Definition filter.cpp:232
OffsetFilter(TemplatableValue< float > offset)
Definition filter.cpp:230
TemplatableValue< float > offset_
Definition filter.h:323
optional< float > new_value(float value) override
Definition filter.cpp:332
PhiNode(OrFilter *or_parent)
Definition filter.cpp:330
OrFilter(std::initializer_list< Filter * > filters)
Definition filter.cpp:329
optional< float > new_value(float value) override
Definition filter.cpp:340
void initialize(Sensor *parent, Filter *next) override
Definition filter.cpp:347
FixedVector< Filter * > filters_
Definition filter.h:492
Simple quantile filter.
Definition filter.h:116
float compute_result() override
Definition filter.cpp:130
void set_quantile(float quantile)
Definition filter.h:129
QuantileFilter(size_t window_size, size_t send_every, size_t send_first_at, float quantile)
Construct a QuantileFilter.
Definition filter.cpp:127
RoundFilter(uint8_t precision)
Definition filter.cpp:473
optional< float > new_value(float value) override
Definition filter.cpp:474
optional< float > new_value(float value) override
Definition filter.cpp:483
Base-class for all sensors.
Definition sensor.h:47
SkipInitialFilter(size_t num_to_ignore)
Construct a SkipInitialFilter.
Definition filter.cpp:114
optional< float > new_value(float value) override
Definition filter.cpp:115
Base class for filters that use a sliding window of values.
Definition filter.h:53
size_t window_head_
Index where next value will be written.
Definition filter.h:66
size_t window_size_
Maximum window size.
Definition filter.h:68
optional< float > new_value(float value) final
Definition filter.cpp:50
size_t window_count_
Number of valid values in window (0 to window_size_)
Definition filter.h:67
FixedVector< float > window_
Access the sliding window values (ring buffer implementation) Use: for (size_t i = 0; i < window_coun...
Definition filter.h:65
size_t send_at_
Counter for send_every.
Definition filter.h:70
size_t send_every_
Send result every N values.
Definition filter.h:69
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:44
Simple sliding window moving average filter.
Definition filter.h:219
Base class for filters that need a sorted window (Median, Quantile).
Definition filter.h:102
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:76
Optimized lambda filter for stateless lambdas (no capture).
Definition filter.h:305
optional< float >(* lambda_filter_)(float)
Definition filter.h:312
optional< float > new_value(float value) override
Definition filter.h:309
StatelessLambdaFilter(optional< float >(*lambda_filter)(float))
Definition filter.h:307
Base class for streaming filters (batch windows where window_size == send_every).
Definition filter.h:571
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:514
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:517
Streaming max filter for batch windows (window_size == send_every).
Definition filter.h:613
void process_value(float value) override
Definition filter.cpp:557
float compute_batch_result() override
Definition filter.cpp:564
Streaming min filter for batch windows (window_size == send_every).
Definition filter.h:597
float compute_batch_result() override
Definition filter.cpp:552
void process_value(float value) override
Definition filter.cpp:545
Streaming moving average filter for batch windows (window_size == send_every).
Definition filter.h:629
void process_value(float value) override
Definition filter.cpp:569
Simple throttle average filter.
Definition filter.h:261
optional< float > new_value(float value) override
Definition filter.cpp:192
ThrottleAverageFilter(uint32_t time_period)
Definition filter.cpp:190
float get_setup_priority() const override
Definition filter.cpp:216
ThrottleFilter(uint32_t min_time_between_inputs)
Definition filter.cpp:276
optional< float > new_value(float value) override
Definition filter.cpp:277
Same as 'throttle' but will immediately publish values contained in value_to_prioritize.
Definition filter.h:372
optional< float > new_value(float value) override
Definition filter.cpp:291
ThrottleWithPriorityFilter(uint32_t min_time_between_inputs, std::initializer_list< TemplatableValue< float > > prioritized_values)
Definition filter.cpp:287
TimeoutFilterBase(uint32_t time_period)
Definition filter.h:391
float get_setup_priority() const override
Definition filter.cpp:369
TemplatableValue< float > value_
Definition filter.h:422
TimeoutFilterConfigured(uint32_t time_period, const TemplatableValue< float > &new_value)
Definition filter.h:415
optional< float > new_value(float value) override
Definition filter.cpp:384
float get_output_value() override
Definition filter.h:407
TimeoutFilterLast(uint32_t time_period)
Definition filter.h:402
optional< float > new_value(float value) override
Definition filter.cpp:372
optional< float > new_value(float value) override
Definition filter.cpp:490
ToNTCResistanceFilter(double a, double b, double c)
Definition filter.h:546
optional< float > new_value(float value) override
Definition filter.cpp:503
ToNTCTemperatureFilter(double a, double b, double c)
Definition filter.h:557
Base class for filters that compare sensor values against a list of configured values.
Definition filter.h:342
ValueListFilter(std::initializer_list< TemplatableValue< float > > values)
Definition filter.cpp:240
FixedVector< TemplatableValue< float > > values_
Definition filter.h:349
bool value_matches_any_(float sensor_value)
Check if sensor value matches any configured value (with accuracy rounding)
Definition filter.cpp:242
std::function< optional< float >(float)> lambda_filter_t
Definition filter.h:278