[sensor] Drop Component from filter classes, use self-keyed scheduler (#16132)

This commit is contained in:
J. Nick Koston
2026-04-30 19:11:30 -05:00
committed by GitHub
parent 2fbfb4c385
commit e085cb50d9
3 changed files with 18 additions and 37 deletions
+6 -13
View File
@@ -266,7 +266,7 @@ StreamingMovingAverageFilter = sensor_ns.class_("StreamingMovingAverageFilter",
ExponentialMovingAverageFilter = sensor_ns.class_(
"ExponentialMovingAverageFilter", Filter
)
ThrottleAverageFilter = sensor_ns.class_("ThrottleAverageFilter", Filter, cg.Component)
ThrottleAverageFilter = sensor_ns.class_("ThrottleAverageFilter", Filter)
LambdaFilter = sensor_ns.class_("LambdaFilter", Filter)
StatelessLambdaFilter = sensor_ns.class_("StatelessLambdaFilter", Filter)
OffsetFilter = sensor_ns.class_("OffsetFilter", Filter)
@@ -283,8 +283,8 @@ ThrottleWithPriorityNanFilter = sensor_ns.class_(
TimeoutFilterBase = sensor_ns.class_("TimeoutFilterBase", Filter, cg.Component)
TimeoutFilterLast = sensor_ns.class_("TimeoutFilterLast", TimeoutFilterBase)
TimeoutFilterConfigured = sensor_ns.class_("TimeoutFilterConfigured", TimeoutFilterBase)
DebounceFilter = sensor_ns.class_("DebounceFilter", Filter, cg.Component)
HeartbeatFilter = sensor_ns.class_("HeartbeatFilter", Filter, cg.Component)
DebounceFilter = sensor_ns.class_("DebounceFilter", Filter)
HeartbeatFilter = sensor_ns.class_("HeartbeatFilter", Filter)
DeltaFilter = sensor_ns.class_("DeltaFilter", Filter)
OrFilter = sensor_ns.class_("OrFilter", Filter)
CalibrateLinearFilter = sensor_ns.class_("CalibrateLinearFilter", Filter)
@@ -567,9 +567,7 @@ async def exponential_moving_average_filter_to_code(config, filter_id):
"throttle_average", ThrottleAverageFilter, cv.positive_time_period_milliseconds
)
async def throttle_average_filter_to_code(config, filter_id):
var = cg.new_Pvariable(filter_id, config)
await cg.register_component(var, {})
return var
return cg.new_Pvariable(filter_id, config)
@FILTER_REGISTRY.register("lambda", LambdaFilter, cv.returning_lambda)
@@ -698,13 +696,10 @@ HEARTBEAT_SCHEMA = cv.Schema(
async def heartbeat_filter_to_code(config, filter_id):
if isinstance(config, dict):
var = cg.new_Pvariable(filter_id, config[CONF_PERIOD])
await cg.register_component(var, {})
cg.add(var.set_optimistic(config[CONF_OPTIMISTIC]))
return var
var = cg.new_Pvariable(filter_id, config)
await cg.register_component(var, {})
return var
return cg.new_Pvariable(filter_id, config)
TIMEOUT_SCHEMA = cv.maybe_simple_value(
@@ -738,9 +733,7 @@ async def timeout_filter_to_code(config, filter_id):
"debounce", DebounceFilter, cv.positive_time_period_milliseconds
)
async def debounce_filter_to_code(config, filter_id):
var = cg.new_Pvariable(filter_id, config)
await cg.register_component(var, {})
return var
return cg.new_Pvariable(filter_id, config)
CONF_DATAPOINTS = "datapoints"
+7 -14
View File
@@ -13,11 +13,6 @@ namespace esphome::sensor {
static const char *const TAG = "sensor.filter";
// Filter scheduler IDs.
// Each filter is its own Component instance, so the scheduler scopes
// IDs by component pointer — no risk of collisions between instances.
constexpr uint32_t FILTER_ID = 0;
// Filter
void Filter::input(float value) {
ESP_LOGVV(TAG, "Filter(%p)::input(%f)", this, value);
@@ -185,8 +180,9 @@ optional<float> ThrottleAverageFilter::new_value(float value) {
}
return {};
}
void ThrottleAverageFilter::setup() {
this->set_interval(FILTER_ID, this->time_period_, [this]() {
void ThrottleAverageFilter::initialize(Sensor *parent, Filter *next) {
Filter::initialize(parent, next);
App.scheduler.set_interval(this, this->time_period_, [this]() {
ESP_LOGVV(TAG, "ThrottleAverageFilter(%p)::interval(sum=%f, n=%i)", this, this->sum_, this->n_);
if (this->n_ == 0) {
if (this->have_nan_)
@@ -199,7 +195,6 @@ void ThrottleAverageFilter::setup() {
this->have_nan_ = false;
});
}
float ThrottleAverageFilter::get_setup_priority() const { return setup_priority::HARDWARE; }
// LambdaFilter
LambdaFilter::LambdaFilter(lambda_filter_t lambda_filter) : lambda_filter_(std::move(lambda_filter)) {}
@@ -362,13 +357,12 @@ optional<float> TimeoutFilterConfigured::new_value(float value) {
// DebounceFilter
optional<float> DebounceFilter::new_value(float value) {
this->set_timeout(FILTER_ID, this->time_period_, [this, value]() { this->output(value); });
App.scheduler.set_timeout(this, this->time_period_, [this, value]() { this->output(value); });
return {};
}
DebounceFilter::DebounceFilter(uint32_t time_period) : time_period_(time_period) {}
float DebounceFilter::get_setup_priority() const { return setup_priority::HARDWARE; }
// HeartbeatFilter
HeartbeatFilter::HeartbeatFilter(uint32_t time_period) : time_period_(time_period), last_input_(NAN) {}
@@ -384,8 +378,9 @@ optional<float> HeartbeatFilter::new_value(float value) {
return {};
}
void HeartbeatFilter::setup() {
this->set_interval(FILTER_ID, this->time_period_, [this]() {
void HeartbeatFilter::initialize(Sensor *parent, Filter *next) {
Filter::initialize(parent, next);
App.scheduler.set_interval(this, this->time_period_, [this]() {
ESP_LOGVV(TAG, "HeartbeatFilter(%p)::interval(has_value=%s, last_input=%f)", this, YESNO(this->has_value_),
this->last_input_);
if (!this->has_value_)
@@ -395,8 +390,6 @@ void HeartbeatFilter::setup() {
});
}
float HeartbeatFilter::get_setup_priority() const { return setup_priority::HARDWARE; }
optional<float> calibrate_linear_compute(const std::array<float, 3> *functions, size_t count, float value) {
for (size_t i = 0; i < count; i++) {
if (!std::isfinite(functions[i][2]) || value < functions[i][2])
+5 -10
View File
@@ -254,16 +254,14 @@ class ExponentialMovingAverageFilter : public Filter {
*
* It takes the average of all the values received in a period of time.
*/
class ThrottleAverageFilter : public Filter, public Component {
class ThrottleAverageFilter : public Filter {
public:
explicit ThrottleAverageFilter(uint32_t time_period);
void setup() override;
void initialize(Sensor *parent, Filter *next) override;
optional<float> new_value(float value) override;
float get_setup_priority() const override;
protected:
float sum_{0.0f};
unsigned int n_{0};
@@ -454,25 +452,22 @@ class TimeoutFilterConfigured : public TimeoutFilterBase {
// Total: 8 (base) + 4 = 12 bytes + vtable ptr + Component overhead
};
class DebounceFilter : public Filter, public Component {
class DebounceFilter : public Filter {
public:
explicit DebounceFilter(uint32_t time_period);
optional<float> new_value(float value) override;
float get_setup_priority() const override;
protected:
uint32_t time_period_;
};
class HeartbeatFilter : public Filter, public Component {
class HeartbeatFilter : public Filter {
public:
explicit HeartbeatFilter(uint32_t time_period);
void setup() override;
void initialize(Sensor *parent, Filter *next) override;
optional<float> new_value(float value) override;
float get_setup_priority() const override;
void set_optimistic(bool optimistic) { this->optimistic_ = optimistic; }