diff --git a/esphome/components/sensor/filter.cpp b/esphome/components/sensor/filter.cpp index a226ed5af1..7afc43b8aa 100644 --- a/esphome/components/sensor/filter.cpp +++ b/esphome/components/sensor/filter.cpp @@ -222,7 +222,14 @@ MultiplyFilter::MultiplyFilter(TemplatableValue multiplier) : multiplier_ optional MultiplyFilter::new_value(float value) { return value * this->multiplier_.value(); } -uint32_t get_loop_component_start_time() { return App.get_loop_component_start_time(); } +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 instantiations) bool value_list_matches_any(Sensor *parent, float sensor_value, const TemplatableValue *values, size_t count) { diff --git a/esphome/components/sensor/filter.h b/esphome/components/sensor/filter.h index 69fa3f10df..9e97ad432a 100644 --- a/esphome/components/sensor/filter.h +++ b/esphome/components/sensor/filter.h @@ -332,8 +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 *values, size_t count); -/// Non-template helper to get cached loop start time (avoids circular include of application.h) -uint32_t get_loop_component_start_time(); +/// 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. * @@ -389,10 +390,8 @@ template class ThrottleWithPriorityFilter : public ValueListFilter : ValueListFilter(prioritized_values), min_time_between_inputs_(min_time_between_inputs) {} optional new_value(float value) override { - const uint32_t now = 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 {}; diff --git a/esphome/core/helpers.h b/esphome/core/helpers.h index c7f35a2361..ce730e1aed 100644 --- a/esphome/core/helpers.h +++ b/esphome/core/helpers.h @@ -504,7 +504,9 @@ template::max()> /// falls back to element-wise copy for non-trivially copyable types (e.g. TemplatableValue). /// N is set by code generation; ESPHOME_DEBUG_ASSERT catches mismatches in debug/integration tests. template inline void init_array_from(std::array &dest, std::initializer_list src) { - ESPHOME_DEBUG_ASSERT(src.size() == N); +#ifdef ESPHOME_DEBUG + assert(src.size() == N); +#endif if constexpr (std::is_trivially_copyable_v) { __builtin_memcpy(dest.data(), src.begin(), N * sizeof(T)); } else {