From 313b9fd5bf9503da438e6368892fb99426aaf072 Mon Sep 17 00:00:00 2001 From: Szewcson Date: Wed, 8 Apr 2026 05:05:18 +0200 Subject: [PATCH] [gdk101] Retry reset on interval for slow-booting sensor MCU (#11750) Co-authored-by: J. Nick Koston Co-authored-by: pre-commit-ci-lite[bot] <117423508+pre-commit-ci-lite[bot]@users.noreply.github.com> Co-authored-by: J. Nick Koston --- esphome/components/gdk101/gdk101.cpp | 62 ++++++++++++++++++---------- esphome/components/gdk101/gdk101.h | 3 ++ 2 files changed, 44 insertions(+), 21 deletions(-) diff --git a/esphome/components/gdk101/gdk101.cpp b/esphome/components/gdk101/gdk101.cpp index 8b381564b2..149973ba8a 100644 --- a/esphome/components/gdk101/gdk101.cpp +++ b/esphome/components/gdk101/gdk101.cpp @@ -6,9 +6,15 @@ namespace esphome { namespace gdk101 { static const char *const TAG = "gdk101"; -static const uint8_t NUMBER_OF_READ_RETRIES = 5; +static constexpr uint8_t NUMBER_OF_READ_RETRIES = 5; +static constexpr uint8_t NUMBER_OF_RESET_RETRIES = 10; +static constexpr uint32_t RESET_INTERVAL_ID = 0; +static constexpr uint32_t RESET_INTERVAL_MS = 1000; void GDK101Component::update() { + if (!this->reset_complete_) + return; + uint8_t data[2]; if (!this->read_dose_1m_(data)) { this->status_set_warning(LOG_STR("Failed to read dose 1m")); @@ -33,26 +39,45 @@ void GDK101Component::update() { } void GDK101Component::setup() { - uint8_t data[2]; - // first, reset the sensor - if (!this->reset_sensor_(data)) { - this->status_set_error(LOG_STR("Reset failed!")); - this->mark_failed(); - return; + if (!this->try_reset_()) { + // Sensor MCU boots slowly after power cycle — retry on a short interval + this->reset_retries_remaining_ = NUMBER_OF_RESET_RETRIES; + this->set_interval(RESET_INTERVAL_ID, RESET_INTERVAL_MS, [this]() { + if (this->try_reset_()) { + if (this->reset_complete_) { + this->update(); + } + return; + } + if (--this->reset_retries_remaining_ == 0) { + this->cancel_interval(RESET_INTERVAL_ID); + this->mark_failed(LOG_STR("Reset failed after retries")); + } + }); + } +} + +/// Attempt to reset the sensor and read firmware version. Returns true on success or hard failure. +bool GDK101Component::try_reset_() { + uint8_t data[2] = {0}; + if (!this->reset_sensor_(data)) { + this->status_set_warning(LOG_STR("Sensor not answering reset, will retry")); + return false; } - // sensor should acknowledge success of the reset procedure if (data[0] != 1) { - this->status_set_error(LOG_STR("Reset not acknowledged!")); - this->mark_failed(); - return; + this->status_set_warning(LOG_STR("Reset not acknowledged, will retry")); + return false; } delay(10); - // read firmware version if (!this->read_fw_version_(data)) { - this->status_set_error(LOG_STR("Failed to read firmware version")); - this->mark_failed(); - return; + this->cancel_interval(RESET_INTERVAL_ID); + this->mark_failed(LOG_STR("Failed to read firmware version")); + return true; } + this->reset_complete_ = true; + this->status_clear_warning(); + this->cancel_interval(RESET_INTERVAL_ID); + return true; } void GDK101Component::dump_config() { @@ -92,12 +117,7 @@ bool GDK101Component::reset_sensor_(uint8_t *data) { // After sending reset command it looks that sensor start performing reset and is unresponsible during read // after a while we can send another reset command and read "0x01" as confirmation // Documentation not going in to such details unfortunately - if (!this->read_bytes_with_retry_(GDK101_REG_RESET, data, 2)) { - ESP_LOGE(TAG, "Updating GDK101 failed!"); - return false; - } - - return true; + return this->read_bytes_with_retry_(GDK101_REG_RESET, data, 2); } bool GDK101Component::read_dose_1m_(uint8_t *data) { diff --git a/esphome/components/gdk101/gdk101.h b/esphome/components/gdk101/gdk101.h index abe417e0f9..abe3fd60d8 100644 --- a/esphome/components/gdk101/gdk101.h +++ b/esphome/components/gdk101/gdk101.h @@ -44,12 +44,15 @@ class GDK101Component : public PollingComponent, public i2c::I2CDevice { protected: bool read_bytes_with_retry_(uint8_t a_register, uint8_t *data, uint8_t len); + bool try_reset_(); bool reset_sensor_(uint8_t *data); bool read_dose_1m_(uint8_t *data); bool read_dose_10m_(uint8_t *data); bool read_status_(uint8_t *data); bool read_fw_version_(uint8_t *data); bool read_measurement_duration_(uint8_t *data); + bool reset_complete_{false}; + uint8_t reset_retries_remaining_{0}; }; } // namespace gdk101