diff --git a/esphome/components/tuya/tuya.cpp b/esphome/components/tuya/tuya.cpp index 1b35121c57..f4744064e3 100644 --- a/esphome/components/tuya/tuya.cpp +++ b/esphome/components/tuya/tuya.cpp @@ -11,6 +11,7 @@ namespace tuya { static const char *const TAG = "tuya"; static const int COMMAND_DELAY = 10; static const int RECEIVE_TIMEOUT = 300; +static const int MAX_RETRIES = 5; void Tuya::setup() { this->set_interval("heartbeat", 15000, [this] { this->send_empty_command_(TuyaCommandType::HEARTBEAT); }); @@ -31,8 +32,12 @@ void Tuya::loop() { void Tuya::dump_config() { ESP_LOGCONFIG(TAG, "Tuya:"); if (this->init_state_ != TuyaInitState::INIT_DONE) { - ESP_LOGCONFIG(TAG, " Configuration will be reported when setup is complete. Current init_state: %u", - static_cast(this->init_state_)); + if (this->init_failed_) { + ESP_LOGCONFIG(TAG, " Initialization failed. Current init_state: %u", static_cast(this->init_state_)); + } else { + ESP_LOGCONFIG(TAG, " Configuration will be reported when setup is complete. Current init_state: %u", + static_cast(this->init_state_)); + } ESP_LOGCONFIG(TAG, " If no further output is received, confirm that this is a supported Tuya device."); return; } @@ -54,8 +59,8 @@ void Tuya::dump_config() { } } if ((this->status_pin_reported_ != -1) || (this->reset_pin_reported_ != -1)) { - ESP_LOGCONFIG(TAG, " GPIO Configuration: status: pin %d, reset: pin %d (not supported)", - this->status_pin_reported_, this->reset_pin_reported_); + ESP_LOGCONFIG(TAG, " GPIO Configuration: status: pin %d, reset: pin %d", this->status_pin_reported_, + this->reset_pin_reported_); } if (this->status_pin_.has_value()) { LOG_PIN(" Status Pin: ", this->status_pin_.value()); @@ -134,6 +139,8 @@ void Tuya::handle_command_(uint8_t command, uint8_t version, const uint8_t *buff if (this->expected_response_.has_value() && this->expected_response_ == command_type) { this->expected_response_.reset(); + this->command_queue_.erase(command_queue_.begin()); + this->init_retries_ = 0; } switch (command_type) { @@ -396,13 +403,24 @@ void Tuya::process_command_queue_() { if (this->expected_response_.has_value() && delay > RECEIVE_TIMEOUT) { this->expected_response_.reset(); + if (init_state_ != TuyaInitState::INIT_DONE) { + if (++this->init_retries_ >= MAX_RETRIES) { + this->init_failed_ = true; + ESP_LOGE(TAG, "Initialization failed at init_state %u", static_cast(this->init_state_)); + this->command_queue_.erase(command_queue_.begin()); + this->init_retries_ = 0; + } + } else { + this->command_queue_.erase(command_queue_.begin()); + } } // Left check of delay since last command in case there's ever a command sent by calling send_raw_command_ directly if (delay > COMMAND_DELAY && !this->command_queue_.empty() && this->rx_message_.empty() && !this->expected_response_.has_value()) { this->send_raw_command_(command_queue_.front()); - this->command_queue_.erase(command_queue_.begin()); + if (!this->expected_response_.has_value()) + this->command_queue_.erase(command_queue_.begin()); } } diff --git a/esphome/components/tuya/tuya.h b/esphome/components/tuya/tuya.h index 3a267d75a7..1f21b09c0c 100644 --- a/esphome/components/tuya/tuya.h +++ b/esphome/components/tuya/tuya.h @@ -124,6 +124,8 @@ class Tuya : public Component, public uart::UARTDevice { optional time_id_{}; #endif TuyaInitState init_state_ = TuyaInitState::INIT_HEARTBEAT; + bool init_failed_{false}; + int init_retries_{0}; uint8_t protocol_version_ = -1; optional status_pin_{}; int status_pin_reported_ = -1;