mirror of
https://github.com/esphome/esphome.git
synced 2026-05-20 01:16:26 +08:00
[sensor] Specialize throttle_with_priority NaN-only case (#15823)
This commit is contained in:
@@ -275,6 +275,9 @@ ThrottleFilter = sensor_ns.class_("ThrottleFilter", Filter)
|
||||
ThrottleWithPriorityFilter = sensor_ns.class_(
|
||||
"ThrottleWithPriorityFilter", ValueListFilter
|
||||
)
|
||||
ThrottleWithPriorityNanFilter = sensor_ns.class_(
|
||||
"ThrottleWithPriorityNanFilter", Filter
|
||||
)
|
||||
TimeoutFilterBase = sensor_ns.class_("TimeoutFilterBase", Filter, cg.Component)
|
||||
TimeoutFilterLast = sensor_ns.class_("TimeoutFilterLast", TimeoutFilterBase)
|
||||
TimeoutFilterConfigured = sensor_ns.class_("TimeoutFilterConfigured", TimeoutFilterBase)
|
||||
@@ -656,9 +659,18 @@ THROTTLE_WITH_PRIORITY_SCHEMA = cv.maybe_simple_value(
|
||||
THROTTLE_WITH_PRIORITY_SCHEMA,
|
||||
)
|
||||
async def throttle_with_priority_filter_to_code(config, filter_id):
|
||||
if not isinstance(config[CONF_VALUE], list):
|
||||
config[CONF_VALUE] = [config[CONF_VALUE]]
|
||||
template_ = [await cg.templatable(x, [], cg.float_) for x in config[CONF_VALUE]]
|
||||
values = config[CONF_VALUE]
|
||||
if not isinstance(values, list):
|
||||
values = [values]
|
||||
# Specialize the common "NaN-only" case (the schema default when the user
|
||||
# omits `value:`) to avoid the TemplatableFn<float> array + NaN lambda the
|
||||
# generic ValueListFilter path requires. Behavior is identical: NaN sensor
|
||||
# readings always bypass the throttle.
|
||||
if values and all(isinstance(v, float) and math.isnan(v) for v in values):
|
||||
filter_id = filter_id.copy()
|
||||
filter_id.type = ThrottleWithPriorityNanFilter
|
||||
return cg.new_Pvariable(filter_id, config[CONF_TIMEOUT])
|
||||
template_ = [await cg.templatable(x, [], cg.float_) for x in values]
|
||||
return cg.new_Pvariable(
|
||||
filter_id, cg.TemplateArguments(len(template_)), config[CONF_TIMEOUT], template_
|
||||
)
|
||||
|
||||
@@ -269,6 +269,18 @@ optional<float> throttle_with_priority_new_value(Sensor *parent, float value, co
|
||||
return {};
|
||||
}
|
||||
|
||||
// ThrottleWithPriorityNanFilter
|
||||
ThrottleWithPriorityNanFilter::ThrottleWithPriorityNanFilter(uint32_t min_time_between_inputs)
|
||||
: min_time_between_inputs_(min_time_between_inputs) {}
|
||||
optional<float> ThrottleWithPriorityNanFilter::new_value(float value) {
|
||||
const uint32_t now = App.get_loop_component_start_time();
|
||||
if (this->last_input_ == 0 || now - this->last_input_ >= this->min_time_between_inputs_ || std::isnan(value)) {
|
||||
this->last_input_ = now;
|
||||
return value;
|
||||
}
|
||||
return {};
|
||||
}
|
||||
|
||||
// DeltaFilter
|
||||
DeltaFilter::DeltaFilter(float min_a0, float min_a1, float max_a0, float max_a1)
|
||||
: min_a0_(min_a0), min_a1_(min_a1), max_a0_(max_a0), max_a1_(max_a1) {}
|
||||
|
||||
@@ -399,6 +399,19 @@ template<size_t N> class ThrottleWithPriorityFilter : public ValueListFilter<N>
|
||||
uint32_t min_time_between_inputs_;
|
||||
};
|
||||
|
||||
/// Specialization of ThrottleWithPriorityFilter for the common "prioritize NaN"
|
||||
/// case: skips the TemplatableFn<float> array + lambda and inlines the check.
|
||||
class ThrottleWithPriorityNanFilter : public Filter {
|
||||
public:
|
||||
explicit ThrottleWithPriorityNanFilter(uint32_t min_time_between_inputs);
|
||||
|
||||
optional<float> new_value(float value) override;
|
||||
|
||||
protected:
|
||||
uint32_t last_input_{0};
|
||||
uint32_t min_time_between_inputs_;
|
||||
};
|
||||
|
||||
// Base class for timeout filters - contains common loop logic
|
||||
class TimeoutFilterBase : public Filter, public Component {
|
||||
public:
|
||||
|
||||
Reference in New Issue
Block a user