Replace forward-declared App with throttle_check_and_update helper

Forward declaration fails when filter.h is included before application.h
(incomplete type error). Instead, extract the throttle time check into a
non-template helper in filter.cpp that accesses App directly. This keeps
the same call overhead as the old ThrottleFilter (one function call) but
the helper does the time check AND updates last_input, so the template
new_value() body has no App dependency at all.
This commit is contained in:
J. Nick Koston
2026-03-27 17:09:44 -10:00
parent 2a80ba3e9e
commit a3ccb656b2
2 changed files with 13 additions and 11 deletions
+9
View File
@@ -222,6 +222,15 @@ MultiplyFilter::MultiplyFilter(TemplatableValue<float> multiplier) : multiplier_
optional<float> MultiplyFilter::new_value(float value) { return value * this->multiplier_.value(); }
bool throttle_check_and_update(uint32_t &last_input, uint32_t min_time_between_inputs) {
const uint32_t now = App.get_loop_component_start_time();
if (last_input == 0 || now - last_input >= min_time_between_inputs) {
last_input = now;
return true;
}
return false;
}
// ValueListFilter helper (non-template, shared by all ValueListFilter<N> instantiations)
bool value_list_matches_any(Sensor *parent, float sensor_value, const TemplatableValue<float> *values, size_t count) {
int8_t accuracy = parent->get_accuracy_decimals();
+4 -11
View File
@@ -332,14 +332,9 @@ class MultiplyFilter : public Filter {
/// Non-template helper for value matching (implementation in filter.cpp)
bool value_list_matches_any(Sensor *parent, float sensor_value, const TemplatableValue<float> *values, size_t count);
} // namespace esphome::sensor
// Forward declaration — avoids circular include of application.h.
// Template bodies are only instantiated in main.cpp where Application is fully defined.
namespace esphome {
class Application;
extern Application App;
} // namespace esphome
namespace esphome::sensor {
/// Returns true if throttle should allow the value through (time expired or first input).
/// Updates last_input in-place. Implementation in filter.cpp (accesses App without circular include).
bool throttle_check_and_update(uint32_t &last_input, uint32_t min_time_between_inputs);
/** Base class for filters that compare sensor values against a fixed list of configured values.
*
@@ -395,10 +390,8 @@ template<size_t N> class ThrottleWithPriorityFilter : public ValueListFilter<N>
: ValueListFilter<N>(prioritized_values), min_time_between_inputs_(min_time_between_inputs) {}
optional<float> new_value(float value) override {
const uint32_t now = App.get_loop_component_start_time();
if (this->last_input_ == 0 || now - this->last_input_ >= this->min_time_between_inputs_ ||
if (throttle_check_and_update(this->last_input_, this->min_time_between_inputs_) ||
this->value_matches_any_(value)) {
this->last_input_ = now;
return value;
}
return {};