mirror of
https://github.com/esphome/esphome.git
synced 2025-08-01 07:57:47 +00:00
[sensor] Add new filter: `throttle_with_priority
` (#9937)
This commit is contained in:
parent
14dd48f9c3
commit
374858efeb
@ -256,6 +256,7 @@ OffsetFilter = sensor_ns.class_("OffsetFilter", Filter)
|
|||||||
MultiplyFilter = sensor_ns.class_("MultiplyFilter", Filter)
|
MultiplyFilter = sensor_ns.class_("MultiplyFilter", Filter)
|
||||||
FilterOutValueFilter = sensor_ns.class_("FilterOutValueFilter", Filter)
|
FilterOutValueFilter = sensor_ns.class_("FilterOutValueFilter", Filter)
|
||||||
ThrottleFilter = sensor_ns.class_("ThrottleFilter", Filter)
|
ThrottleFilter = sensor_ns.class_("ThrottleFilter", Filter)
|
||||||
|
ThrottleWithPriorityFilter = sensor_ns.class_("ThrottleWithPriorityFilter", Filter)
|
||||||
TimeoutFilter = sensor_ns.class_("TimeoutFilter", Filter, cg.Component)
|
TimeoutFilter = sensor_ns.class_("TimeoutFilter", Filter, cg.Component)
|
||||||
DebounceFilter = sensor_ns.class_("DebounceFilter", Filter, cg.Component)
|
DebounceFilter = sensor_ns.class_("DebounceFilter", Filter, cg.Component)
|
||||||
HeartbeatFilter = sensor_ns.class_("HeartbeatFilter", Filter, cg.Component)
|
HeartbeatFilter = sensor_ns.class_("HeartbeatFilter", Filter, cg.Component)
|
||||||
@ -595,6 +596,25 @@ async def throttle_filter_to_code(config, filter_id):
|
|||||||
return cg.new_Pvariable(filter_id, config)
|
return cg.new_Pvariable(filter_id, config)
|
||||||
|
|
||||||
|
|
||||||
|
TIMEOUT_WITH_PRIORITY_SCHEMA = cv.maybe_simple_value(
|
||||||
|
{
|
||||||
|
cv.Required(CONF_TIMEOUT): cv.positive_time_period_milliseconds,
|
||||||
|
cv.Optional(CONF_VALUE, default="nan"): cv.ensure_list(cv.float_),
|
||||||
|
},
|
||||||
|
key=CONF_TIMEOUT,
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
|
@FILTER_REGISTRY.register(
|
||||||
|
"throttle_with_priority",
|
||||||
|
ThrottleWithPriorityFilter,
|
||||||
|
TIMEOUT_WITH_PRIORITY_SCHEMA,
|
||||||
|
)
|
||||||
|
async def throttle_with_priority_filter_to_code(config, filter_id):
|
||||||
|
template_ = [await cg.templatable(x, [], float) for x in config[CONF_VALUE]]
|
||||||
|
return cg.new_Pvariable(filter_id, config[CONF_TIMEOUT], template_)
|
||||||
|
|
||||||
|
|
||||||
@FILTER_REGISTRY.register(
|
@FILTER_REGISTRY.register(
|
||||||
"heartbeat", HeartbeatFilter, cv.positive_time_period_milliseconds
|
"heartbeat", HeartbeatFilter, cv.positive_time_period_milliseconds
|
||||||
)
|
)
|
||||||
|
@ -1,5 +1,6 @@
|
|||||||
#include "filter.h"
|
#include "filter.h"
|
||||||
#include <cmath>
|
#include <cmath>
|
||||||
|
#include "esphome/core/application.h"
|
||||||
#include "esphome/core/hal.h"
|
#include "esphome/core/hal.h"
|
||||||
#include "esphome/core/log.h"
|
#include "esphome/core/log.h"
|
||||||
#include "sensor.h"
|
#include "sensor.h"
|
||||||
@ -332,6 +333,40 @@ optional<float> ThrottleFilter::new_value(float value) {
|
|||||||
return {};
|
return {};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// ThrottleWithPriorityFilter
|
||||||
|
ThrottleWithPriorityFilter::ThrottleWithPriorityFilter(uint32_t min_time_between_inputs,
|
||||||
|
std::vector<TemplatableValue<float>> prioritized_values)
|
||||||
|
: min_time_between_inputs_(min_time_between_inputs), prioritized_values_(std::move(prioritized_values)) {}
|
||||||
|
|
||||||
|
optional<float> ThrottleWithPriorityFilter::new_value(float value) {
|
||||||
|
bool is_prioritized_value = false;
|
||||||
|
int8_t accuracy = this->parent_->get_accuracy_decimals();
|
||||||
|
float accuracy_mult = powf(10.0f, accuracy);
|
||||||
|
const uint32_t now = App.get_loop_component_start_time();
|
||||||
|
// First, determine if the new value is one of the prioritized values
|
||||||
|
for (auto prioritized_value : this->prioritized_values_) {
|
||||||
|
if (std::isnan(prioritized_value.value())) {
|
||||||
|
if (std::isnan(value)) {
|
||||||
|
is_prioritized_value = true;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
float rounded_prioritized_value = roundf(accuracy_mult * prioritized_value.value());
|
||||||
|
float rounded_value = roundf(accuracy_mult * value);
|
||||||
|
if (rounded_prioritized_value == rounded_value) {
|
||||||
|
is_prioritized_value = true;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// Finally, determine if the new value should be throttled and pass it through if not
|
||||||
|
if (this->last_input_ == 0 || now - this->last_input_ >= min_time_between_inputs_ || is_prioritized_value) {
|
||||||
|
this->last_input_ = now;
|
||||||
|
return value;
|
||||||
|
}
|
||||||
|
return {};
|
||||||
|
}
|
||||||
|
|
||||||
// DeltaFilter
|
// DeltaFilter
|
||||||
DeltaFilter::DeltaFilter(float delta, bool percentage_mode)
|
DeltaFilter::DeltaFilter(float delta, bool percentage_mode)
|
||||||
: delta_(delta), current_delta_(delta), percentage_mode_(percentage_mode), last_value_(NAN) {}
|
: delta_(delta), current_delta_(delta), percentage_mode_(percentage_mode), last_value_(NAN) {}
|
||||||
|
@ -314,6 +314,20 @@ class ThrottleFilter : public Filter {
|
|||||||
uint32_t min_time_between_inputs_;
|
uint32_t min_time_between_inputs_;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/// Same as 'throttle' but will immediately publish values contained in `value_to_prioritize`.
|
||||||
|
class ThrottleWithPriorityFilter : public Filter {
|
||||||
|
public:
|
||||||
|
explicit ThrottleWithPriorityFilter(uint32_t min_time_between_inputs,
|
||||||
|
std::vector<TemplatableValue<float>> prioritized_values);
|
||||||
|
|
||||||
|
optional<float> new_value(float value) override;
|
||||||
|
|
||||||
|
protected:
|
||||||
|
uint32_t last_input_{0};
|
||||||
|
uint32_t min_time_between_inputs_;
|
||||||
|
std::vector<TemplatableValue<float>> prioritized_values_;
|
||||||
|
};
|
||||||
|
|
||||||
class TimeoutFilter : public Filter, public Component {
|
class TimeoutFilter : public Filter, public Component {
|
||||||
public:
|
public:
|
||||||
explicit TimeoutFilter(uint32_t time_period, TemplatableValue<float> new_value);
|
explicit TimeoutFilter(uint32_t time_period, TemplatableValue<float> new_value);
|
||||||
|
Loading…
x
Reference in New Issue
Block a user