11static const char *
const TAG =
"sensor.filter";
15 ESP_LOGVV(TAG,
"Filter(%p)::input(%f)",
this, value);
21 if (this->
next_ ==
nullptr) {
22 ESP_LOGVV(TAG,
"Filter(%p)::output(%f) -> SENSOR",
this, value);
25 ESP_LOGVV(TAG,
"Filter(%p)::output(%f) -> %p",
this, value, this->
next_);
30 ESP_LOGVV(TAG,
"Filter(%p)::initialize(parent=%p next=%p)",
this, parent, next);
37 : send_every_(send_every), send_at_(send_every - send_first_at), window_size_(window_size) {}
41 while (this->
queue_.size() >= this->window_size_) {
44 this->
queue_.push_back(value);
45 ESP_LOGVV(TAG,
"MedianFilter(%p)::new_value(%f)",
this, value);
51 if (!this->
queue_.empty()) {
53 std::vector<float> median_queue;
54 median_queue.reserve(this->
queue_.size());
55 for (
auto v : this->
queue_) {
57 median_queue.push_back(v);
61 sort(median_queue.begin(), median_queue.end());
63 size_t queue_size = median_queue.size();
66 median = median_queue[queue_size / 2];
68 median = (median_queue[queue_size / 2] + median_queue[(queue_size / 2) - 1]) / 2.0f;
73 ESP_LOGVV(TAG,
"MedianFilter(%p)::new_value(%f) SENDING %f",
this, value, median);
84 ESP_LOGV(TAG,
"SkipInitialFilter(%p)::new_value(%f) SKIPPING, %zu left",
this, value,
num_to_ignore_);
88 ESP_LOGV(TAG,
"SkipInitialFilter(%p)::new_value(%f) SENDING",
this, value);
94 : send_every_(send_every), send_at_(send_every - send_first_at), window_size_(window_size), quantile_(quantile) {}
99 while (this->
queue_.size() >= this->window_size_) {
102 this->
queue_.push_back(value);
103 ESP_LOGVV(TAG,
"QuantileFilter(%p)::new_value(%f), quantile:%f",
this, value, this->
quantile_);
109 if (!this->
queue_.empty()) {
111 std::vector<float> quantile_queue;
112 for (
auto v : this->
queue_) {
113 if (!std::isnan(v)) {
114 quantile_queue.push_back(v);
118 sort(quantile_queue.begin(), quantile_queue.end());
120 size_t queue_size = quantile_queue.size();
123 ESP_LOGVV(TAG,
"QuantileFilter(%p)::position: %zu/%zu",
this,
position + 1, queue_size);
128 ESP_LOGVV(TAG,
"QuantileFilter(%p)::new_value(%f) SENDING %f",
this, value, result);
136 : send_every_(send_every), send_at_(send_every - send_first_at), window_size_(window_size) {}
140 while (this->
queue_.size() >= this->window_size_) {
143 this->
queue_.push_back(value);
144 ESP_LOGVV(TAG,
"MinFilter(%p)::new_value(%f)",
this, value);
150 for (
auto v : this->
queue_) {
151 if (!std::isnan(v)) {
152 min = std::isnan(min) ? v : std::min(min, v);
156 ESP_LOGVV(TAG,
"MinFilter(%p)::new_value(%f) SENDING %f",
this, value, min);
164 : send_every_(send_every), send_at_(send_every - send_first_at), window_size_(window_size) {}
168 while (this->
queue_.size() >= this->window_size_) {
171 this->
queue_.push_back(value);
172 ESP_LOGVV(TAG,
"MaxFilter(%p)::new_value(%f)",
this, value);
178 for (
auto v : this->
queue_) {
179 if (!std::isnan(v)) {
180 max = std::isnan(max) ? v : std::max(max, v);
184 ESP_LOGVV(TAG,
"MaxFilter(%p)::new_value(%f) SENDING %f",
this, value, max);
192 size_t send_first_at)
193 : send_every_(send_every), send_at_(send_every - send_first_at), window_size_(window_size) {}
197 while (this->
queue_.size() >= this->window_size_) {
200 this->
queue_.push_back(value);
201 ESP_LOGVV(TAG,
"SlidingWindowMovingAverageFilter(%p)::new_value(%f)",
this, value);
207 size_t valid_count = 0;
208 for (
auto v : this->
queue_) {
209 if (!std::isnan(v)) {
217 average = sum / valid_count;
220 ESP_LOGVV(TAG,
"SlidingWindowMovingAverageFilter(%p)::new_value(%f) SENDING %f",
this, value, average);
228 : alpha_(alpha), send_every_(send_every), send_at_(send_every - send_first_at) {}
230 if (!std::isnan(value)) {
239 const float average = std::isnan(value) ? value : this->
accumulator_;
240 ESP_LOGVV(TAG,
"ExponentialMovingAverageFilter(%p)::new_value(%f) -> %f",
this, value, average);
243 ESP_LOGVV(TAG,
"ExponentialMovingAverageFilter(%p)::new_value(%f) SENDING %f",
this, value, average);
256 ESP_LOGVV(TAG,
"ThrottleAverageFilter(%p)::new_value(value=%f)",
this, value);
257 if (std::isnan(value)) {
267 ESP_LOGVV(TAG,
"ThrottleAverageFilter(%p)::interval(sum=%f, n=%i)",
this, this->
sum_, this->
n_);
288 ESP_LOGVV(TAG,
"LambdaFilter(%p)::new_value(%f) -> %f",
this, value, it.value_or(INFINITY));
304 : values_to_filter_out_(std::move(values_to_filter_out)) {}
308 float accuracy_mult = powf(10.0f, accuracy);
310 if (std::isnan(filter_value.value())) {
311 if (std::isnan(value)) {
316 float rounded_filter_out = roundf(accuracy_mult * filter_value.value());
317 float rounded_value = roundf(accuracy_mult * value);
318 if (rounded_filter_out == rounded_value) {
339 : min_time_between_inputs_(min_time_between_inputs), prioritized_values_(std::move(prioritized_values)) {}
342 bool is_prioritized_value =
false;
344 float accuracy_mult = powf(10.0f, accuracy);
348 if (std::isnan(prioritized_value.value())) {
349 if (std::isnan(value)) {
350 is_prioritized_value =
true;
355 float rounded_prioritized_value = roundf(accuracy_mult * prioritized_value.value());
356 float rounded_value = roundf(accuracy_mult * value);
357 if (rounded_prioritized_value == rounded_value) {
358 is_prioritized_value =
true;
372 : delta_(delta), current_delta_(delta), last_value_(NAN), percentage_mode_(percentage_mode) {}
374 if (std::isnan(value)) {
396 if (!this->or_parent_->has_value_) {
397 this->or_parent_->output(value);
398 this->or_parent_->has_value_ =
true;
406 filter->input(value);
413 filter->initialize(parent, &this->
phi_);
420 if (this->value_.has_value()) {
421 this->set_timeout(
"timeout", this->time_period_, [
this]() { this->
output(this->value_.value().value()); });
423 this->set_timeout(
"timeout", this->time_period_, [
this, value]() { this->
output(value); });
430 : time_period_(time_period), value_(new_value) {}
447 ESP_LOGVV(TAG,
"HeartbeatFilter(%p)::new_value(value=%f)",
this, value);
455 ESP_LOGVV(TAG,
"HeartbeatFilter(%p)::interval(has_value=%s, last_input=%f)",
this, YESNO(this->
has_value_),
467 if (!std::isfinite(f[2]) || value < f[2])
468 return (value * f[0]) + f[1];
477 res +=
x * coefficient;
484 : min_(min), max_(max), ignore_out_of_range_(ignore_out_of_range) {}
486 if (std::isfinite(value)) {
487 if (std::isfinite(this->
min_) && value < this->
min_) {
495 if (std::isfinite(this->
max_) && value > this->
max_) {
508 if (std::isfinite(value)) {
509 float accuracy_mult = powf(10.0f, this->
precision_);
510 return roundf(accuracy_mult * value) / accuracy_mult;
517 if (std::isfinite(value)) {
518 return value - remainderf(value, this->
multiple_);
524 if (!std::isfinite(value)) {
529 double t = value + k;
530 double y = (this->
a_ - 1 / (t)) / (2 * this->
c_);
531 double x = sqrt(pow(this->
b_ / (3 * this->
c_), 3) + y *
y);
532 double resistance = exp(pow(
x -
y, 1 / 3.0) - pow(
x +
y, 1 / 3.0));
537 if (!std::isfinite(value)) {
540 double lr = log(
double(value));
541 double v = this->
a_ + this->
b_ * lr + this->
c_ * lr * lr * lr;
542 double temp = float(1.0 / v - 273.15);
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.
void set_timeout(const std::string &name, uint32_t timeout, std::function< void()> &&f)
Set a timeout function with a unique name.
optional< float > new_value(float value) override
std::vector< std::array< float, 3 > > linear_functions_
std::vector< float > coefficients_
optional< float > new_value(float value) override
bool ignore_out_of_range_
ClampFilter(float min, float max, bool ignore_out_of_range)
optional< float > new_value(float value) override
optional< float > new_value(float value) override
float get_setup_priority() const override
DebounceFilter(uint32_t time_period)
DeltaFilter(float delta, bool percentage_mode)
optional< float > new_value(float value) override
void set_send_every(size_t send_every)
optional< float > new_value(float value) override
ExponentialMovingAverageFilter(float alpha, size_t send_every, size_t send_first_at)
void set_alpha(float alpha)
Apply a filter to sensor values such as moving average.
virtual optional< float > new_value(float value)=0
This will be called every time the filter receives a new value.
virtual void initialize(Sensor *parent, Filter *next)
Initialize this filter, please note this can be called more than once.
std::vector< TemplatableValue< float > > values_to_filter_out_
FilterOutValueFilter(std::vector< TemplatableValue< float > > values_to_filter_out)
optional< float > new_value(float value) override
HeartbeatFilter(uint32_t time_period)
optional< float > new_value(float value) override
float get_setup_priority() const override
const lambda_filter_t & get_lambda_filter() const
LambdaFilter(lambda_filter_t lambda_filter)
lambda_filter_t lambda_filter_
void set_lambda_filter(const lambda_filter_t &lambda_filter)
optional< float > new_value(float value) override
void set_send_every(size_t send_every)
void set_window_size(size_t window_size)
std::deque< float > queue_
optional< float > new_value(float value) override
MaxFilter(size_t window_size, size_t send_every, size_t send_first_at)
Construct a MaxFilter.
void set_window_size(size_t window_size)
void set_send_every(size_t send_every)
MinFilter(size_t window_size, size_t send_every, size_t send_first_at)
Construct a MinFilter.
std::deque< float > queue_
optional< float > new_value(float value) override
optional< float > new_value(float value) override
MultiplyFilter(TemplatableValue< float > multiplier)
TemplatableValue< float > multiplier_
optional< float > new_value(float value) override
OffsetFilter(TemplatableValue< float > offset)
TemplatableValue< float > offset_
optional< float > new_value(float value) override
PhiNode(OrFilter *or_parent)
std::vector< Filter * > filters_
optional< float > new_value(float value) override
void initialize(Sensor *parent, Filter *next) override
OrFilter(std::vector< Filter * > filters)
void set_window_size(size_t window_size)
void set_send_every(size_t send_every)
std::deque< float > queue_
void set_quantile(float quantile)
optional< float > new_value(float value) override
QuantileFilter(size_t window_size, size_t send_every, size_t send_first_at, float quantile)
Construct a QuantileFilter.
RoundFilter(uint8_t precision)
optional< float > new_value(float value) override
optional< float > new_value(float value) override
RoundMultipleFilter(float multiple)
Base-class for all sensors.
void internal_send_state_to_frontend(float state)
int8_t get_accuracy_decimals()
Get the accuracy in decimals, using the manual override if set.
SkipInitialFilter(size_t num_to_ignore)
Construct a SkipInitialFilter.
optional< float > new_value(float value) override
std::deque< float > queue_
void set_window_size(size_t window_size)
void set_send_every(size_t send_every)
optional< float > new_value(float value) override
SlidingWindowMovingAverageFilter(size_t window_size, size_t send_every, size_t send_first_at)
Construct a SlidingWindowMovingAverageFilter.
optional< float > new_value(float value) override
ThrottleAverageFilter(uint32_t time_period)
float get_setup_priority() const override
uint32_t min_time_between_inputs_
ThrottleFilter(uint32_t min_time_between_inputs)
optional< float > new_value(float value) override
std::vector< TemplatableValue< float > > prioritized_values_
ThrottleWithPriorityFilter(uint32_t min_time_between_inputs, std::vector< TemplatableValue< float > > prioritized_values)
optional< float > new_value(float value) override
uint32_t min_time_between_inputs_
optional< float > new_value(float value) override
TimeoutFilter(uint32_t time_period)
float get_setup_priority() const override
optional< float > new_value(float value) override
optional< float > new_value(float value) override
std::function< optional< float >(float)> lambda_filter_t
const float HARDWARE
For components that deal with hardware and are very important like GPIO switch.
Providing packet encoding functions for exchanging data with a remote host.
Application App
Global storage of Application pointer - only one Application can exist.