mirror of
				https://github.com/esphome/esphome.git
				synced 2025-10-31 07:03:55 +00:00 
			
		
		
		
	| @@ -118,12 +118,17 @@ class ESP32Preferences : public ESPPreferences { | |||||||
|     // go through vector from back to front (makes erase easier/more efficient) |     // go through vector from back to front (makes erase easier/more efficient) | ||||||
|     for (ssize_t i = s_pending_save.size() - 1; i >= 0; i--) { |     for (ssize_t i = s_pending_save.size() - 1; i >= 0; i--) { | ||||||
|       const auto &save = s_pending_save[i]; |       const auto &save = s_pending_save[i]; | ||||||
|       esp_err_t err = nvs_set_blob(nvs_handle, save.key.c_str(), save.data.data(), save.data.size()); |       ESP_LOGVV(TAG, "Checking if NVS data %s has changed", save.key.c_str()); | ||||||
|       if (err != 0) { |       if (is_changed(nvs_handle, save)) { | ||||||
|         ESP_LOGV(TAG, "nvs_set_blob('%s', len=%u) failed: %s", save.key.c_str(), save.data.size(), |         esp_err_t err = nvs_set_blob(nvs_handle, save.key.c_str(), save.data.data(), save.data.size()); | ||||||
|                  esp_err_to_name(err)); |         if (err != 0) { | ||||||
|         any_failed = true; |           ESP_LOGV(TAG, "nvs_set_blob('%s', len=%u) failed: %s", save.key.c_str(), save.data.size(), | ||||||
|         continue; |                    esp_err_to_name(err)); | ||||||
|  |           any_failed = true; | ||||||
|  |           continue; | ||||||
|  |         } | ||||||
|  |       } else { | ||||||
|  |         ESP_LOGD(TAG, "NVS data not changed skipping %s  len=%u", save.key.c_str(), save.data.size()); | ||||||
|       } |       } | ||||||
|       s_pending_save.erase(s_pending_save.begin() + i); |       s_pending_save.erase(s_pending_save.begin() + i); | ||||||
|     } |     } | ||||||
| @@ -137,6 +142,22 @@ class ESP32Preferences : public ESPPreferences { | |||||||
|  |  | ||||||
|     return !any_failed; |     return !any_failed; | ||||||
|   } |   } | ||||||
|  |   bool is_changed(const uint32_t nvs_handle, const NVSData &to_save) { | ||||||
|  |     NVSData stored_data{}; | ||||||
|  |     size_t actual_len; | ||||||
|  |     esp_err_t err = nvs_get_blob(nvs_handle, to_save.key.c_str(), nullptr, &actual_len); | ||||||
|  |     if (err != 0) { | ||||||
|  |       ESP_LOGV(TAG, "nvs_get_blob('%s'): %s - the key might not be set yet", to_save.key.c_str(), esp_err_to_name(err)); | ||||||
|  |       return true; | ||||||
|  |     } | ||||||
|  |     stored_data.data.reserve(actual_len); | ||||||
|  |     err = nvs_get_blob(nvs_handle, to_save.key.c_str(), stored_data.data.data(), &actual_len); | ||||||
|  |     if (err != 0) { | ||||||
|  |       ESP_LOGV(TAG, "nvs_get_blob('%s') failed: %s", to_save.key.c_str(), esp_err_to_name(err)); | ||||||
|  |       return true; | ||||||
|  |     } | ||||||
|  |     return to_save.data == stored_data.data; | ||||||
|  |   } | ||||||
| }; | }; | ||||||
|  |  | ||||||
| void setup_preferences() { | void setup_preferences() { | ||||||
|   | |||||||
| @@ -1,7 +1,7 @@ | |||||||
| #include "tuya.h" | #include "tuya.h" | ||||||
| #include "esphome/core/log.h" |  | ||||||
| #include "esphome/components/network/util.h" | #include "esphome/components/network/util.h" | ||||||
| #include "esphome/core/helpers.h" | #include "esphome/core/helpers.h" | ||||||
|  | #include "esphome/core/log.h" | ||||||
| #include "esphome/core/util.h" | #include "esphome/core/util.h" | ||||||
|  |  | ||||||
| namespace esphome { | namespace esphome { | ||||||
| @@ -10,6 +10,7 @@ namespace tuya { | |||||||
| static const char *const TAG = "tuya"; | static const char *const TAG = "tuya"; | ||||||
| static const int COMMAND_DELAY = 10; | static const int COMMAND_DELAY = 10; | ||||||
| static const int RECEIVE_TIMEOUT = 300; | static const int RECEIVE_TIMEOUT = 300; | ||||||
|  | static const int MAX_RETRIES = 5; | ||||||
|  |  | ||||||
| void Tuya::setup() { | void Tuya::setup() { | ||||||
|   this->set_interval("heartbeat", 15000, [this] { this->send_empty_command_(TuyaCommandType::HEARTBEAT); }); |   this->set_interval("heartbeat", 15000, [this] { this->send_empty_command_(TuyaCommandType::HEARTBEAT); }); | ||||||
| @@ -27,8 +28,12 @@ void Tuya::loop() { | |||||||
| void Tuya::dump_config() { | void Tuya::dump_config() { | ||||||
|   ESP_LOGCONFIG(TAG, "Tuya:"); |   ESP_LOGCONFIG(TAG, "Tuya:"); | ||||||
|   if (this->init_state_ != TuyaInitState::INIT_DONE) { |   if (this->init_state_ != TuyaInitState::INIT_DONE) { | ||||||
|     ESP_LOGCONFIG(TAG, "  Configuration will be reported when setup is complete. Current init_state: %u", |     if (this->init_failed_) { | ||||||
|                   static_cast<uint8_t>(this->init_state_)); |       ESP_LOGCONFIG(TAG, "  Initialization failed. Current init_state: %u", static_cast<uint8_t>(this->init_state_)); | ||||||
|  |     } else { | ||||||
|  |       ESP_LOGCONFIG(TAG, "  Configuration will be reported when setup is complete. Current init_state: %u", | ||||||
|  |                     static_cast<uint8_t>(this->init_state_)); | ||||||
|  |     } | ||||||
|     ESP_LOGCONFIG(TAG, "  If no further output is received, confirm that this is a supported Tuya device."); |     ESP_LOGCONFIG(TAG, "  If no further output is received, confirm that this is a supported Tuya device."); | ||||||
|     return; |     return; | ||||||
|   } |   } | ||||||
| @@ -127,6 +132,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) { |   if (this->expected_response_.has_value() && this->expected_response_ == command_type) { | ||||||
|     this->expected_response_.reset(); |     this->expected_response_.reset(); | ||||||
|  |     this->command_queue_.erase(command_queue_.begin()); | ||||||
|  |     this->init_retries_ = 0; | ||||||
|   } |   } | ||||||
|  |  | ||||||
|   switch (command_type) { |   switch (command_type) { | ||||||
| @@ -378,13 +385,24 @@ void Tuya::process_command_queue_() { | |||||||
|  |  | ||||||
|   if (this->expected_response_.has_value() && delay > RECEIVE_TIMEOUT) { |   if (this->expected_response_.has_value() && delay > RECEIVE_TIMEOUT) { | ||||||
|     this->expected_response_.reset(); |     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<uint8_t>(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 |   // 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() && |   if (delay > COMMAND_DELAY && !this->command_queue_.empty() && this->rx_message_.empty() && | ||||||
|       !this->expected_response_.has_value()) { |       !this->expected_response_.has_value()) { | ||||||
|     this->send_raw_command_(command_queue_.front()); |     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()); | ||||||
|   } |   } | ||||||
| } | } | ||||||
|  |  | ||||||
|   | |||||||
| @@ -122,6 +122,8 @@ class Tuya : public Component, public uart::UARTDevice { | |||||||
|   optional<time::RealTimeClock *> time_id_{}; |   optional<time::RealTimeClock *> time_id_{}; | ||||||
| #endif | #endif | ||||||
|   TuyaInitState init_state_ = TuyaInitState::INIT_HEARTBEAT; |   TuyaInitState init_state_ = TuyaInitState::INIT_HEARTBEAT; | ||||||
|  |   bool init_failed_{false}; | ||||||
|  |   int init_retries_{0}; | ||||||
|   uint8_t protocol_version_ = -1; |   uint8_t protocol_version_ = -1; | ||||||
|   int gpio_status_ = -1; |   int gpio_status_ = -1; | ||||||
|   int gpio_reset_ = -1; |   int gpio_reset_ = -1; | ||||||
|   | |||||||
| @@ -1,6 +1,6 @@ | |||||||
| """Constants used by esphome.""" | """Constants used by esphome.""" | ||||||
|  |  | ||||||
| __version__ = "2022.5.0b3" | __version__ = "2022.5.0b4" | ||||||
|  |  | ||||||
| ALLOWED_NAME_CHARS = "abcdefghijklmnopqrstuvwxyz0123456789-_" | ALLOWED_NAME_CHARS = "abcdefghijklmnopqrstuvwxyz0123456789-_" | ||||||
|  |  | ||||||
|   | |||||||
		Reference in New Issue
	
	Block a user