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