diff --git a/esphome/core/component.cpp b/esphome/core/component.cpp index b20964b872..a7e451b93d 100644 --- a/esphome/core/component.cpp +++ b/esphome/core/component.cpp @@ -39,6 +39,9 @@ const uint32_t STATUS_LED_OK = 0x0000; const uint32_t STATUS_LED_WARNING = 0x0100; const uint32_t STATUS_LED_ERROR = 0x0200; +const uint32_t WARN_IF_BLOCKING_OVER_MS = 50U; ///< Initial blocking time allowed without warning +const uint32_t WARN_IF_BLOCKING_INCREMENT_MS = 10U; ///< How long the blocking time must be larger to warn again + uint32_t global_state = 0; // NOLINT(cppcoreguidelines-avoid-non-const-global-variables) float Component::get_loop_priority() const { return 0.0f; } @@ -115,6 +118,13 @@ const char *Component::get_component_source() const { return ""; return this->component_source_; } +bool Component::should_warn_of_blocking(uint32_t blocking_time) { + if (blocking_time > this->warn_if_blocking_over_) { + this->warn_if_blocking_over_ = blocking_time + WARN_IF_BLOCKING_INCREMENT_MS; + return true; + } + return false; +} void Component::mark_failed() { ESP_LOGE(TAG, "Component %s was marked as failed.", this->get_component_source()); this->component_state_ &= ~COMPONENT_STATE_MASK; @@ -233,10 +243,16 @@ void PollingComponent::set_update_interval(uint32_t update_interval) { this->upd WarnIfComponentBlockingGuard::WarnIfComponentBlockingGuard(Component *component) : started_(millis()), component_(component) {} WarnIfComponentBlockingGuard::~WarnIfComponentBlockingGuard() { - uint32_t now = millis(); - if (now - started_ > 50) { + uint32_t blocking_time = millis() - this->started_; + bool should_warn; + if (this->component_ != nullptr) { + should_warn = this->component_->should_warn_of_blocking(blocking_time); + } else { + should_warn = blocking_time > WARN_IF_BLOCKING_OVER_MS; + } + if (should_warn) { const char *src = component_ == nullptr ? "" : component_->get_component_source(); - ESP_LOGW(TAG, "Component %s took a long time for an operation (%" PRIu32 " ms).", src, (now - started_)); + ESP_LOGW(TAG, "Component %s took a long time for an operation (%" PRIu32 " ms).", src, blocking_time); ESP_LOGW(TAG, "Components should block for at most 30 ms."); ; } diff --git a/esphome/core/component.h b/esphome/core/component.h index f5c56459b1..412074282d 100644 --- a/esphome/core/component.h +++ b/esphome/core/component.h @@ -65,6 +65,8 @@ extern const uint32_t STATUS_LED_ERROR; enum class RetryResult { DONE, RETRY }; +extern const uint32_t WARN_IF_BLOCKING_OVER_MS; + class Component { public: /** Where the component's initialization should happen. @@ -158,6 +160,8 @@ class Component { */ const char *get_component_source() const; + bool should_warn_of_blocking(uint32_t blocking_time); + protected: friend class Application; @@ -284,6 +288,7 @@ class Component { uint32_t component_state_{0x0000}; ///< State of this component. float setup_priority_override_{NAN}; const char *component_source_{nullptr}; + uint32_t warn_if_blocking_over_{WARN_IF_BLOCKING_OVER_MS}; std::string error_message_{}; };