ESPHome 2026.2.3
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 min_a0, float min_a1, float max_a0, float max_a1);
456
457 void set_baseline(float (*fn)(float));
458
459 optional<float> new_value(float value) override;
460
461 protected:
462 // These values represent linear equations for the min and max values but in practice only one of a0 and a1 will be
463 // non-zero Each limit is calculated as fabs(a0 + value * a1)
464
466 // default baseline is the previous value
467 float (*baseline_)(float) = [](float last_value) { return last_value; };
468
469 float last_value_{NAN};
470};
471
472class OrFilter : public Filter {
473 public:
474 explicit OrFilter(std::initializer_list<Filter *> filters);
475
476 void initialize(Sensor *parent, Filter *next) override;
477
478 optional<float> new_value(float value) override;
479
480 protected:
481 class PhiNode : public Filter {
482 public:
483 PhiNode(OrFilter *or_parent);
484 optional<float> new_value(float value) override;
485
486 protected:
488 };
489
492 bool has_value_{false};
493};
494
496 public:
497 explicit CalibrateLinearFilter(std::initializer_list<std::array<float, 3>> linear_functions);
498 optional<float> new_value(float value) override;
499
500 protected:
502};
503
505 public:
506 explicit CalibratePolynomialFilter(std::initializer_list<float> coefficients);
507 optional<float> new_value(float value) override;
508
509 protected:
511};
512
513class ClampFilter : public Filter {
514 public:
515 ClampFilter(float min, float max, bool ignore_out_of_range);
516 optional<float> new_value(float value) override;
517
518 protected:
519 float min_{NAN};
520 float max_{NAN};
522};
523
524class RoundFilter : public Filter {
525 public:
526 explicit RoundFilter(uint8_t precision);
527 optional<float> new_value(float value) override;
528
529 protected:
530 uint8_t precision_;
531};
532
534 public:
535 explicit RoundMultipleFilter(float multiple);
536 optional<float> new_value(float value) override;
537
538 protected:
540};
541
543 public:
544 ToNTCResistanceFilter(double a, double b, double c) : a_(a), b_(b), c_(c) {}
545 optional<float> new_value(float value) override;
546
547 protected:
548 double a_;
549 double b_;
550 double c_;
551};
552
554 public:
555 ToNTCTemperatureFilter(double a, double b, double c) : a_(a), b_(b), c_(c) {}
556 optional<float> new_value(float value) override;
557
558 protected:
559 double a_;
560 double b_;
561 double c_;
562};
563
569class StreamingFilter : public Filter {
570 public:
571 StreamingFilter(size_t window_size, size_t send_first_at);
572
573 optional<float> new_value(float value) final;
574
575 protected:
577 virtual void process_value(float value) = 0;
578
580 virtual float compute_batch_result() = 0;
581
583 virtual void reset_batch() = 0;
584
586 size_t count_{0};
588 bool first_send_{true};
589};
590
596 public:
598
599 protected:
600 void process_value(float value) override;
601 float compute_batch_result() override;
602 void reset_batch() override;
603
604 float current_min_{NAN};
605};
606
612 public:
614
615 protected:
616 void process_value(float value) override;
617 float compute_batch_result() override;
618 void reset_batch() override;
619
620 float current_max_{NAN};
621};
622
628 public:
630
631 protected:
632 void process_value(float value) override;
633 float compute_batch_result() override;
634 void reset_batch() override;
635
636 float sum_{0.0f};
637 size_t valid_count_{0};
638};
639
640} // 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:227
T value(X... x) const
Definition automation.h:149
FixedVector< std::array< float, 3 > > linear_functions_
Definition filter.h:501
optional< float > new_value(float value) override
Definition filter.cpp:429
CalibrateLinearFilter(std::initializer_list< std::array< float, 3 > > linear_functions)
Definition filter.cpp:426
CalibratePolynomialFilter(std::initializer_list< float > coefficients)
Definition filter.cpp:437
optional< float > new_value(float value) override
Definition filter.cpp:440
ClampFilter(float min, float max, bool ignore_out_of_range)
Definition filter.cpp:450
optional< float > new_value(float value) override
Definition filter.cpp:452
optional< float > new_value(float value) override
Definition filter.cpp:390
float get_setup_priority() const override
Definition filter.cpp:397
DebounceFilter(uint32_t time_period)
Definition filter.cpp:396
void set_baseline(float(*fn)(float))
Definition filter.cpp:302
DeltaFilter(float min_a0, float min_a1, float max_a0, float max_a1)
Definition filter.cpp:299
optional< float > new_value(float value) override
Definition filter.cpp:304
float(* baseline_)(float)
Definition filter.h:467
Simple exponential moving average filter.
Definition filter.h:238
optional< float > new_value(float value) override
Definition filter.cpp:162
ExponentialMovingAverageFilter(float alpha, size_t send_every, size_t send_first_at)
Definition filter.cpp:160
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:24
virtual void initialize(Sensor *parent, Filter *next)
Initialize this filter, please note this can be called more than once.
Definition filter.cpp:33
void input(float value)
Definition filter.cpp:18
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:265
FilterOutValueFilter(std::initializer_list< TemplatableValue< float > > values_to_filter_out)
Definition filter.cpp:262
HeartbeatFilter(uint32_t time_period)
Definition filter.cpp:400
optional< float > new_value(float value) override
Definition filter.cpp:402
void set_optimistic(bool optimistic)
Definition filter.h:444
float get_setup_priority() const override
Definition filter.cpp:424
This class allows for creation of simple template filters.
Definition filter.h:285
const lambda_filter_t & get_lambda_filter() const
Definition filter.cpp:216
LambdaFilter(lambda_filter_t lambda_filter)
Definition filter.cpp:215
lambda_filter_t lambda_filter_
Definition filter.h:295
void set_lambda_filter(const lambda_filter_t &lambda_filter)
Definition filter.cpp:217
optional< float > new_value(float value) override
Definition filter.cpp:219
Simple max filter.
Definition filter.h:196
float compute_result() override
Definition filter.cpp:143
Simple median filter.
Definition filter.h:138
float compute_result() override
Definition filter.cpp:87
Simple min filter.
Definition filter.h:176
float compute_result() override
Definition filter.cpp:140
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:233
MultiplyFilter(TemplatableValue< float > multiplier)
Definition filter.cpp:231
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:228
OffsetFilter(TemplatableValue< float > offset)
Definition filter.cpp:226
TemplatableValue< float > offset_
Definition filter.h:321
optional< float > new_value(float value) override
Definition filter.cpp:328
PhiNode(OrFilter *or_parent)
Definition filter.cpp:326
OrFilter(std::initializer_list< Filter * > filters)
Definition filter.cpp:325
optional< float > new_value(float value) override
Definition filter.cpp:336
void initialize(Sensor *parent, Filter *next) override
Definition filter.cpp:343
FixedVector< Filter * > filters_
Definition filter.h:490
Simple quantile filter.
Definition filter.h:114
float compute_result() override
Definition filter.cpp:126
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:123
RoundFilter(uint8_t precision)
Definition filter.cpp:469
optional< float > new_value(float value) override
Definition filter.cpp:470
optional< float > new_value(float value) override
Definition filter.cpp:479
Base-class for all sensors.
Definition sensor.h:43
SkipInitialFilter(size_t num_to_ignore)
Construct a SkipInitialFilter.
Definition filter.cpp:110
optional< float > new_value(float value) override
Definition filter.cpp:111
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:46
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:40
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:72
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:569
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:510
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:513
Streaming max filter for batch windows (window_size == send_every).
Definition filter.h:611
void process_value(float value) override
Definition filter.cpp:553
float compute_batch_result() override
Definition filter.cpp:560
Streaming min filter for batch windows (window_size == send_every).
Definition filter.h:595
float compute_batch_result() override
Definition filter.cpp:548
void process_value(float value) override
Definition filter.cpp:541
Streaming moving average filter for batch windows (window_size == send_every).
Definition filter.h:627
void process_value(float value) override
Definition filter.cpp:565
Simple throttle average filter.
Definition filter.h:259
optional< float > new_value(float value) override
Definition filter.cpp:188
ThrottleAverageFilter(uint32_t time_period)
Definition filter.cpp:186
float get_setup_priority() const override
Definition filter.cpp:212
ThrottleFilter(uint32_t min_time_between_inputs)
Definition filter.cpp:272
optional< float > new_value(float value) override
Definition filter.cpp:273
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:287
ThrottleWithPriorityFilter(uint32_t min_time_between_inputs, std::initializer_list< TemplatableValue< float > > prioritized_values)
Definition filter.cpp:283
TimeoutFilterBase(uint32_t time_period)
Definition filter.h:389
float get_setup_priority() const override
Definition filter.cpp:365
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:380
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:368
optional< float > new_value(float value) override
Definition filter.cpp:486
ToNTCResistanceFilter(double a, double b, double c)
Definition filter.h:544
optional< float > new_value(float value) override
Definition filter.cpp:499
ToNTCTemperatureFilter(double a, double b, double c)
Definition filter.h:555
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:236
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:238
std::function< optional< float >(float)> lambda_filter_t
Definition filter.h:276