mirror of
				https://github.com/esphome/esphome.git
				synced 2025-10-31 15:12:06 +00:00 
			
		
		
		
	move more
This commit is contained in:
		| @@ -1,6 +1,7 @@ | |||||||
| from esphome import automation | from esphome import automation | ||||||
| import esphome.codegen as cg | import esphome.codegen as cg | ||||||
| from esphome.components.ota import BASE_OTA_SCHEMA, OTAComponent, ota_to_code | from esphome.components.ota import BASE_OTA_SCHEMA, ota_to_code | ||||||
|  | from esphome.components.ota_base import OTAComponent | ||||||
| import esphome.config_validation as cv | import esphome.config_validation as cv | ||||||
| from esphome.const import CONF_ID, CONF_PASSWORD, CONF_URL, CONF_USERNAME | from esphome.const import CONF_ID, CONF_PASSWORD, CONF_URL, CONF_USERNAME | ||||||
| from esphome.core import coroutine_with_priority | from esphome.core import coroutine_with_priority | ||||||
|   | |||||||
| @@ -6,8 +6,7 @@ | |||||||
|  |  | ||||||
| #include "esphome/components/md5/md5.h" | #include "esphome/components/md5/md5.h" | ||||||
| #include "esphome/components/watchdog/watchdog.h" | #include "esphome/components/watchdog/watchdog.h" | ||||||
| #include "esphome/components/ota/ota.h"               // For OTAComponent and callbacks | #include "esphome/components/ota_base/ota_backend.h" | ||||||
| #include "esphome/components/ota_base/ota_backend.h"  // For OTABackend class |  | ||||||
| #include "esphome/components/ota_base/ota_backend_arduino_esp32.h" | #include "esphome/components/ota_base/ota_backend_arduino_esp32.h" | ||||||
| #include "esphome/components/ota_base/ota_backend_arduino_esp8266.h" | #include "esphome/components/ota_base/ota_backend_arduino_esp8266.h" | ||||||
| #include "esphome/components/ota_base/ota_backend_arduino_rp2040.h" | #include "esphome/components/ota_base/ota_backend_arduino_rp2040.h" | ||||||
| @@ -51,15 +50,15 @@ void OtaHttpRequestComponent::flash() { | |||||||
|  |  | ||||||
|   ESP_LOGI(TAG, "Starting update"); |   ESP_LOGI(TAG, "Starting update"); | ||||||
| #ifdef USE_OTA_STATE_CALLBACK | #ifdef USE_OTA_STATE_CALLBACK | ||||||
|   this->state_callback_.call(ota::OTA_STARTED, 0.0f, 0); |   this->state_callback_.call(ota_base::OTA_STARTED, 0.0f, 0); | ||||||
| #endif | #endif | ||||||
|  |  | ||||||
|   auto ota_status = this->do_ota_(); |   auto ota_status = this->do_ota_(); | ||||||
|  |  | ||||||
|   switch (ota_status) { |   switch (ota_status) { | ||||||
|     case ota::OTA_RESPONSE_OK: |     case ota_base::OTA_RESPONSE_OK: | ||||||
| #ifdef USE_OTA_STATE_CALLBACK | #ifdef USE_OTA_STATE_CALLBACK | ||||||
|       this->state_callback_.call(ota::OTA_COMPLETED, 100.0f, ota_status); |       this->state_callback_.call(ota_base::OTA_COMPLETED, 100.0f, ota_status); | ||||||
| #endif | #endif | ||||||
|       delay(10); |       delay(10); | ||||||
|       App.safe_reboot(); |       App.safe_reboot(); | ||||||
| @@ -67,7 +66,7 @@ void OtaHttpRequestComponent::flash() { | |||||||
|  |  | ||||||
|     default: |     default: | ||||||
| #ifdef USE_OTA_STATE_CALLBACK | #ifdef USE_OTA_STATE_CALLBACK | ||||||
|       this->state_callback_.call(ota::OTA_ERROR, 0.0f, ota_status); |       this->state_callback_.call(ota_base::OTA_ERROR, 0.0f, ota_status); | ||||||
| #endif | #endif | ||||||
|       this->md5_computed_.clear();  // will be reset at next attempt |       this->md5_computed_.clear();  // will be reset at next attempt | ||||||
|       this->md5_expected_.clear();  // will be reset at next attempt |       this->md5_expected_.clear();  // will be reset at next attempt | ||||||
| @@ -75,7 +74,7 @@ void OtaHttpRequestComponent::flash() { | |||||||
|   } |   } | ||||||
| } | } | ||||||
|  |  | ||||||
| void OtaHttpRequestComponent::cleanup_(std::unique_ptr<ota::OTABackend> backend, | void OtaHttpRequestComponent::cleanup_(std::unique_ptr<ota_base::OTABackend> backend, | ||||||
|                                        const std::shared_ptr<HttpContainer> &container) { |                                        const std::shared_ptr<HttpContainer> &container) { | ||||||
|   if (this->update_started_) { |   if (this->update_started_) { | ||||||
|     ESP_LOGV(TAG, "Aborting OTA backend"); |     ESP_LOGV(TAG, "Aborting OTA backend"); | ||||||
| @@ -118,7 +117,7 @@ uint8_t OtaHttpRequestComponent::do_ota_() { | |||||||
|   ESP_LOGV(TAG, "OTA backend begin"); |   ESP_LOGV(TAG, "OTA backend begin"); | ||||||
|   auto backend = ota_base::make_ota_backend(); |   auto backend = ota_base::make_ota_backend(); | ||||||
|   auto error_code = backend->begin(container->content_length); |   auto error_code = backend->begin(container->content_length); | ||||||
|   if (error_code != ota::OTA_RESPONSE_OK) { |   if (error_code != ota_base::OTA_RESPONSE_OK) { | ||||||
|     ESP_LOGW(TAG, "backend->begin error: %d", error_code); |     ESP_LOGW(TAG, "backend->begin error: %d", error_code); | ||||||
|     this->cleanup_(std::move(backend), container); |     this->cleanup_(std::move(backend), container); | ||||||
|     return error_code; |     return error_code; | ||||||
| @@ -145,7 +144,7 @@ uint8_t OtaHttpRequestComponent::do_ota_() { | |||||||
|       // write bytes to OTA backend |       // write bytes to OTA backend | ||||||
|       this->update_started_ = true; |       this->update_started_ = true; | ||||||
|       error_code = backend->write(buf, bufsize); |       error_code = backend->write(buf, bufsize); | ||||||
|       if (error_code != ota::OTA_RESPONSE_OK) { |       if (error_code != ota_base::OTA_RESPONSE_OK) { | ||||||
|         // error code explanation available at |         // error code explanation available at | ||||||
|         // https://github.com/esphome/esphome/blob/dev/esphome/components/ota/ota_backend.h |         // https://github.com/esphome/esphome/blob/dev/esphome/components/ota/ota_backend.h | ||||||
|         ESP_LOGE(TAG, "Error code (%02X) writing binary data to flash at offset %d and size %d", error_code, |         ESP_LOGE(TAG, "Error code (%02X) writing binary data to flash at offset %d and size %d", error_code, | ||||||
| @@ -161,7 +160,7 @@ uint8_t OtaHttpRequestComponent::do_ota_() { | |||||||
|       float percentage = container->get_bytes_read() * 100.0f / container->content_length; |       float percentage = container->get_bytes_read() * 100.0f / container->content_length; | ||||||
|       ESP_LOGD(TAG, "Progress: %0.1f%%", percentage); |       ESP_LOGD(TAG, "Progress: %0.1f%%", percentage); | ||||||
| #ifdef USE_OTA_STATE_CALLBACK | #ifdef USE_OTA_STATE_CALLBACK | ||||||
|       this->state_callback_.call(ota::OTA_IN_PROGRESS, percentage, 0); |       this->state_callback_.call(ota_base::OTA_IN_PROGRESS, percentage, 0); | ||||||
| #endif | #endif | ||||||
|     } |     } | ||||||
|   }  // while |   }  // while | ||||||
| @@ -175,7 +174,7 @@ uint8_t OtaHttpRequestComponent::do_ota_() { | |||||||
|   if (strncmp(this->md5_computed_.c_str(), this->md5_expected_.c_str(), MD5_SIZE) != 0) { |   if (strncmp(this->md5_computed_.c_str(), this->md5_expected_.c_str(), MD5_SIZE) != 0) { | ||||||
|     ESP_LOGE(TAG, "MD5 computed: %s - Aborting due to MD5 mismatch", this->md5_computed_.c_str()); |     ESP_LOGE(TAG, "MD5 computed: %s - Aborting due to MD5 mismatch", this->md5_computed_.c_str()); | ||||||
|     this->cleanup_(std::move(backend), container); |     this->cleanup_(std::move(backend), container); | ||||||
|     return ota::OTA_RESPONSE_ERROR_MD5_MISMATCH; |     return ota_base::OTA_RESPONSE_ERROR_MD5_MISMATCH; | ||||||
|   } else { |   } else { | ||||||
|     backend->set_update_md5(md5_receive_str.get()); |     backend->set_update_md5(md5_receive_str.get()); | ||||||
|   } |   } | ||||||
| @@ -188,14 +187,14 @@ uint8_t OtaHttpRequestComponent::do_ota_() { | |||||||
|   delay(100);  // NOLINT |   delay(100);  // NOLINT | ||||||
|  |  | ||||||
|   error_code = backend->end(); |   error_code = backend->end(); | ||||||
|   if (error_code != ota::OTA_RESPONSE_OK) { |   if (error_code != ota_base::OTA_RESPONSE_OK) { | ||||||
|     ESP_LOGW(TAG, "Error ending update! error_code: %d", error_code); |     ESP_LOGW(TAG, "Error ending update! error_code: %d", error_code); | ||||||
|     this->cleanup_(std::move(backend), container); |     this->cleanup_(std::move(backend), container); | ||||||
|     return error_code; |     return error_code; | ||||||
|   } |   } | ||||||
|  |  | ||||||
|   ESP_LOGI(TAG, "Update complete"); |   ESP_LOGI(TAG, "Update complete"); | ||||||
|   return ota::OTA_RESPONSE_OK; |   return ota_base::OTA_RESPONSE_OK; | ||||||
| } | } | ||||||
|  |  | ||||||
| std::string OtaHttpRequestComponent::get_url_with_auth_(const std::string &url) { | std::string OtaHttpRequestComponent::get_url_with_auth_(const std::string &url) { | ||||||
|   | |||||||
| @@ -1,6 +1,6 @@ | |||||||
| #pragma once | #pragma once | ||||||
|  |  | ||||||
| #include "esphome/components/ota/ota.h" | #include "esphome/components/ota_base/ota_backend.h" | ||||||
| #include "esphome/core/component.h" | #include "esphome/core/component.h" | ||||||
| #include "esphome/core/defines.h" | #include "esphome/core/defines.h" | ||||||
| #include "esphome/core/helpers.h" | #include "esphome/core/helpers.h" | ||||||
| @@ -22,7 +22,7 @@ enum OtaHttpRequestError : uint8_t { | |||||||
|   OTA_CONNECTION_ERROR = 0x12, |   OTA_CONNECTION_ERROR = 0x12, | ||||||
| }; | }; | ||||||
|  |  | ||||||
| class OtaHttpRequestComponent : public ota::OTAComponent, public Parented<HttpRequestComponent> { | class OtaHttpRequestComponent : public ota_base::OTAComponent, public Parented<HttpRequestComponent> { | ||||||
|  public: |  public: | ||||||
|   void setup() override; |   void setup() override; | ||||||
|   void dump_config() override; |   void dump_config() override; | ||||||
| @@ -40,7 +40,7 @@ class OtaHttpRequestComponent : public ota::OTAComponent, public Parented<HttpRe | |||||||
|   void flash(); |   void flash(); | ||||||
|  |  | ||||||
|  protected: |  protected: | ||||||
|   void cleanup_(std::unique_ptr<ota::OTABackend> backend, const std::shared_ptr<HttpContainer> &container); |   void cleanup_(std::unique_ptr<ota_base::OTABackend> backend, const std::shared_ptr<HttpContainer> &container); | ||||||
|   uint8_t do_ota_(); |   uint8_t do_ota_(); | ||||||
|   std::string get_url_with_auth_(const std::string &url); |   std::string get_url_with_auth_(const std::string &url); | ||||||
|   bool http_get_md5_(); |   bool http_get_md5_(); | ||||||
|   | |||||||
| @@ -5,6 +5,7 @@ | |||||||
|  |  | ||||||
| #include "esphome/components/json/json_util.h" | #include "esphome/components/json/json_util.h" | ||||||
| #include "esphome/components/network/util.h" | #include "esphome/components/network/util.h" | ||||||
|  | #include "esphome/components/ota_base/ota_backend.h" | ||||||
|  |  | ||||||
| namespace esphome { | namespace esphome { | ||||||
| namespace http_request { | namespace http_request { | ||||||
| @@ -21,13 +22,13 @@ static const char *const TAG = "http_request.update"; | |||||||
| static const size_t MAX_READ_SIZE = 256; | static const size_t MAX_READ_SIZE = 256; | ||||||
|  |  | ||||||
| void HttpRequestUpdate::setup() { | void HttpRequestUpdate::setup() { | ||||||
|   this->ota_parent_->add_on_state_callback([this](ota::OTAState state, float progress, uint8_t err) { |   this->ota_parent_->add_on_state_callback([this](ota_base::OTAState state, float progress, uint8_t err) { | ||||||
|     if (state == ota::OTAState::OTA_IN_PROGRESS) { |     if (state == ota_base::OTAState::OTA_IN_PROGRESS) { | ||||||
|       this->state_ = update::UPDATE_STATE_INSTALLING; |       this->state_ = update::UPDATE_STATE_INSTALLING; | ||||||
|       this->update_info_.has_progress = true; |       this->update_info_.has_progress = true; | ||||||
|       this->update_info_.progress = progress; |       this->update_info_.progress = progress; | ||||||
|       this->publish_state(); |       this->publish_state(); | ||||||
|     } else if (state == ota::OTAState::OTA_ABORT || state == ota::OTAState::OTA_ERROR) { |     } else if (state == ota_base::OTAState::OTA_ABORT || state == ota_base::OTAState::OTA_ERROR) { | ||||||
|       this->state_ = update::UPDATE_STATE_AVAILABLE; |       this->state_ = update::UPDATE_STATE_AVAILABLE; | ||||||
|       this->status_set_error("Failed to install firmware"); |       this->status_set_error("Failed to install firmware"); | ||||||
|       this->publish_state(); |       this->publish_state(); | ||||||
|   | |||||||
| @@ -1,5 +1,6 @@ | |||||||
| from esphome import automation | from esphome import automation | ||||||
| import esphome.codegen as cg | import esphome.codegen as cg | ||||||
|  | from esphome.components.ota_base import OTAState | ||||||
| import esphome.config_validation as cv | import esphome.config_validation as cv | ||||||
| from esphome.const import ( | from esphome.const import ( | ||||||
|     CONF_ESPHOME, |     CONF_ESPHOME, | ||||||
| @@ -23,8 +24,7 @@ CONF_ON_STATE_CHANGE = "on_state_change" | |||||||
|  |  | ||||||
|  |  | ||||||
| ota_ns = cg.esphome_ns.namespace("ota") | ota_ns = cg.esphome_ns.namespace("ota") | ||||||
| OTAComponent = ota_ns.class_("OTAComponent", cg.Component) | # OTAComponent and OTAState are imported from ota_base | ||||||
| OTAState = ota_ns.enum("OTAState") |  | ||||||
| OTAAbortTrigger = ota_ns.class_("OTAAbortTrigger", automation.Trigger.template()) | OTAAbortTrigger = ota_ns.class_("OTAAbortTrigger", automation.Trigger.template()) | ||||||
| OTAEndTrigger = ota_ns.class_("OTAEndTrigger", automation.Trigger.template()) | OTAEndTrigger = ota_ns.class_("OTAEndTrigger", automation.Trigger.template()) | ||||||
| OTAErrorTrigger = ota_ns.class_("OTAErrorTrigger", automation.Trigger.template()) | OTAErrorTrigger = ota_ns.class_("OTAErrorTrigger", automation.Trigger.template()) | ||||||
|   | |||||||
| @@ -1,12 +1,17 @@ | |||||||
| #pragma once | #pragma once | ||||||
| #ifdef USE_OTA_STATE_CALLBACK | #ifdef USE_OTA_STATE_CALLBACK | ||||||
| #include "ota.h" | #include "ota.h" | ||||||
|  | #include "esphome/components/ota_base/ota_backend.h" | ||||||
|  |  | ||||||
| #include "esphome/core/automation.h" | #include "esphome/core/automation.h" | ||||||
|  |  | ||||||
| namespace esphome { | namespace esphome { | ||||||
| namespace ota { | namespace ota { | ||||||
|  |  | ||||||
|  | // Import types from ota_base for the automation triggers | ||||||
|  | using ota_base::OTAComponent; | ||||||
|  | using ota_base::OTAState; | ||||||
|  |  | ||||||
| class OTAStateChangeTrigger : public Trigger<OTAState> { | class OTAStateChangeTrigger : public Trigger<OTAState> { | ||||||
|  public: |  public: | ||||||
|   explicit OTAStateChangeTrigger(OTAComponent *parent) { |   explicit OTAStateChangeTrigger(OTAComponent *parent) { | ||||||
| @@ -22,7 +27,7 @@ class OTAStartTrigger : public Trigger<> { | |||||||
|  public: |  public: | ||||||
|   explicit OTAStartTrigger(OTAComponent *parent) { |   explicit OTAStartTrigger(OTAComponent *parent) { | ||||||
|     parent->add_on_state_callback([this, parent](OTAState state, float progress, uint8_t error) { |     parent->add_on_state_callback([this, parent](OTAState state, float progress, uint8_t error) { | ||||||
|       if (state == OTA_STARTED && !parent->is_failed()) { |       if (state == ota_base::OTA_STARTED && !parent->is_failed()) { | ||||||
|         trigger(); |         trigger(); | ||||||
|       } |       } | ||||||
|     }); |     }); | ||||||
| @@ -33,7 +38,7 @@ class OTAProgressTrigger : public Trigger<float> { | |||||||
|  public: |  public: | ||||||
|   explicit OTAProgressTrigger(OTAComponent *parent) { |   explicit OTAProgressTrigger(OTAComponent *parent) { | ||||||
|     parent->add_on_state_callback([this, parent](OTAState state, float progress, uint8_t error) { |     parent->add_on_state_callback([this, parent](OTAState state, float progress, uint8_t error) { | ||||||
|       if (state == OTA_IN_PROGRESS && !parent->is_failed()) { |       if (state == ota_base::OTA_IN_PROGRESS && !parent->is_failed()) { | ||||||
|         trigger(progress); |         trigger(progress); | ||||||
|       } |       } | ||||||
|     }); |     }); | ||||||
| @@ -44,7 +49,7 @@ class OTAEndTrigger : public Trigger<> { | |||||||
|  public: |  public: | ||||||
|   explicit OTAEndTrigger(OTAComponent *parent) { |   explicit OTAEndTrigger(OTAComponent *parent) { | ||||||
|     parent->add_on_state_callback([this, parent](OTAState state, float progress, uint8_t error) { |     parent->add_on_state_callback([this, parent](OTAState state, float progress, uint8_t error) { | ||||||
|       if (state == OTA_COMPLETED && !parent->is_failed()) { |       if (state == ota_base::OTA_COMPLETED && !parent->is_failed()) { | ||||||
|         trigger(); |         trigger(); | ||||||
|       } |       } | ||||||
|     }); |     }); | ||||||
| @@ -55,7 +60,7 @@ class OTAAbortTrigger : public Trigger<> { | |||||||
|  public: |  public: | ||||||
|   explicit OTAAbortTrigger(OTAComponent *parent) { |   explicit OTAAbortTrigger(OTAComponent *parent) { | ||||||
|     parent->add_on_state_callback([this, parent](OTAState state, float progress, uint8_t error) { |     parent->add_on_state_callback([this, parent](OTAState state, float progress, uint8_t error) { | ||||||
|       if (state == OTA_ABORT && !parent->is_failed()) { |       if (state == ota_base::OTA_ABORT && !parent->is_failed()) { | ||||||
|         trigger(); |         trigger(); | ||||||
|       } |       } | ||||||
|     }); |     }); | ||||||
| @@ -66,7 +71,7 @@ class OTAErrorTrigger : public Trigger<uint8_t> { | |||||||
|  public: |  public: | ||||||
|   explicit OTAErrorTrigger(OTAComponent *parent) { |   explicit OTAErrorTrigger(OTAComponent *parent) { | ||||||
|     parent->add_on_state_callback([this, parent](OTAState state, float progress, uint8_t error) { |     parent->add_on_state_callback([this, parent](OTAState state, float progress, uint8_t error) { | ||||||
|       if (state == OTA_ERROR && !parent->is_failed()) { |       if (state == ota_base::OTA_ERROR && !parent->is_failed()) { | ||||||
|         trigger(error); |         trigger(error); | ||||||
|       } |       } | ||||||
|     }); |     }); | ||||||
|   | |||||||
| @@ -1,69 +1,12 @@ | |||||||
| #pragma once | #pragma once | ||||||
|  |  | ||||||
| #include "esphome/core/defines.h" | #include "esphome/core/defines.h" | ||||||
| #include "esphome/components/ota_base/ota_backend.h" |  | ||||||
|  |  | ||||||
| namespace esphome { | namespace esphome { | ||||||
| namespace ota { | namespace ota { | ||||||
|  |  | ||||||
| // Import types from ota_base namespace for backward compatibility | // All OTA backend functionality has been moved to the ota_base component. | ||||||
| using ota_base::OTABackend; | // This file remains for the high-level OTA automation triggers defined in automation.h | ||||||
| using ota_base::OTAComponent; |  | ||||||
| using ota_base::OTAResponseTypes; |  | ||||||
| using ota_base::OTAState; |  | ||||||
|  |  | ||||||
| // Re-export specific enum values for backward compatibility |  | ||||||
| // OTAState values |  | ||||||
| static constexpr auto OTA_COMPLETED = ota_base::OTA_COMPLETED; |  | ||||||
| static constexpr auto OTA_STARTED = ota_base::OTA_STARTED; |  | ||||||
| static constexpr auto OTA_IN_PROGRESS = ota_base::OTA_IN_PROGRESS; |  | ||||||
| static constexpr auto OTA_ABORT = ota_base::OTA_ABORT; |  | ||||||
| static constexpr auto OTA_ERROR = ota_base::OTA_ERROR; |  | ||||||
|  |  | ||||||
| // OTAResponseTypes values |  | ||||||
| static constexpr auto OTA_RESPONSE_OK = ota_base::OTA_RESPONSE_OK; |  | ||||||
| static constexpr auto OTA_RESPONSE_REQUEST_AUTH = ota_base::OTA_RESPONSE_REQUEST_AUTH; |  | ||||||
| static constexpr auto OTA_RESPONSE_HEADER_OK = ota_base::OTA_RESPONSE_HEADER_OK; |  | ||||||
| static constexpr auto OTA_RESPONSE_AUTH_OK = ota_base::OTA_RESPONSE_AUTH_OK; |  | ||||||
| static constexpr auto OTA_RESPONSE_UPDATE_PREPARE_OK = ota_base::OTA_RESPONSE_UPDATE_PREPARE_OK; |  | ||||||
| static constexpr auto OTA_RESPONSE_BIN_MD5_OK = ota_base::OTA_RESPONSE_BIN_MD5_OK; |  | ||||||
| static constexpr auto OTA_RESPONSE_RECEIVE_OK = ota_base::OTA_RESPONSE_RECEIVE_OK; |  | ||||||
| static constexpr auto OTA_RESPONSE_UPDATE_END_OK = ota_base::OTA_RESPONSE_UPDATE_END_OK; |  | ||||||
| static constexpr auto OTA_RESPONSE_SUPPORTS_COMPRESSION = ota_base::OTA_RESPONSE_SUPPORTS_COMPRESSION; |  | ||||||
| static constexpr auto OTA_RESPONSE_CHUNK_OK = ota_base::OTA_RESPONSE_CHUNK_OK; |  | ||||||
| static constexpr auto OTA_RESPONSE_ERROR_MAGIC = ota_base::OTA_RESPONSE_ERROR_MAGIC; |  | ||||||
| static constexpr auto OTA_RESPONSE_ERROR_UPDATE_PREPARE = ota_base::OTA_RESPONSE_ERROR_UPDATE_PREPARE; |  | ||||||
| static constexpr auto OTA_RESPONSE_ERROR_AUTH_INVALID = ota_base::OTA_RESPONSE_ERROR_AUTH_INVALID; |  | ||||||
| static constexpr auto OTA_RESPONSE_ERROR_WRITING_FLASH = ota_base::OTA_RESPONSE_ERROR_WRITING_FLASH; |  | ||||||
| static constexpr auto OTA_RESPONSE_ERROR_UPDATE_END = ota_base::OTA_RESPONSE_ERROR_UPDATE_END; |  | ||||||
| static constexpr auto OTA_RESPONSE_ERROR_INVALID_BOOTSTRAPPING = ota_base::OTA_RESPONSE_ERROR_INVALID_BOOTSTRAPPING; |  | ||||||
| static constexpr auto OTA_RESPONSE_ERROR_WRONG_CURRENT_FLASH_CONFIG = |  | ||||||
|     ota_base::OTA_RESPONSE_ERROR_WRONG_CURRENT_FLASH_CONFIG; |  | ||||||
| static constexpr auto OTA_RESPONSE_ERROR_WRONG_NEW_FLASH_CONFIG = ota_base::OTA_RESPONSE_ERROR_WRONG_NEW_FLASH_CONFIG; |  | ||||||
| static constexpr auto OTA_RESPONSE_ERROR_ESP8266_NOT_ENOUGH_SPACE = |  | ||||||
|     ota_base::OTA_RESPONSE_ERROR_ESP8266_NOT_ENOUGH_SPACE; |  | ||||||
| static constexpr auto OTA_RESPONSE_ERROR_ESP32_NOT_ENOUGH_SPACE = ota_base::OTA_RESPONSE_ERROR_ESP32_NOT_ENOUGH_SPACE; |  | ||||||
| static constexpr auto OTA_RESPONSE_ERROR_NO_UPDATE_PARTITION = ota_base::OTA_RESPONSE_ERROR_NO_UPDATE_PARTITION; |  | ||||||
| static constexpr auto OTA_RESPONSE_ERROR_MD5_MISMATCH = ota_base::OTA_RESPONSE_ERROR_MD5_MISMATCH; |  | ||||||
| static constexpr auto OTA_RESPONSE_ERROR_RP2040_NOT_ENOUGH_SPACE = ota_base::OTA_RESPONSE_ERROR_RP2040_NOT_ENOUGH_SPACE; |  | ||||||
| static constexpr auto OTA_RESPONSE_ERROR_UNKNOWN = ota_base::OTA_RESPONSE_ERROR_UNKNOWN; |  | ||||||
|  |  | ||||||
| #ifdef USE_OTA_STATE_CALLBACK |  | ||||||
| using ota_base::OTAGlobalCallback; |  | ||||||
|  |  | ||||||
| // Deprecated: Use ota_base::get_global_ota_callback() instead |  | ||||||
| // Will be removed after 2025-12-30 (6 months from 2025-06-30) |  | ||||||
| [[deprecated("Use ota_base::get_global_ota_callback() instead")]] inline OTAGlobalCallback *get_global_ota_callback() { |  | ||||||
|   return ota_base::get_global_ota_callback(); |  | ||||||
| } |  | ||||||
|  |  | ||||||
| // Deprecated: Use ota_base::register_ota_platform() instead |  | ||||||
| // Will be removed after 2025-12-30 (6 months from 2025-06-30) |  | ||||||
| [[deprecated("Use ota_base::register_ota_platform() instead")]] inline void register_ota_platform( |  | ||||||
|     OTAComponent *ota_caller) { |  | ||||||
|   ota_base::register_ota_platform(ota_caller); |  | ||||||
| } |  | ||||||
| #endif |  | ||||||
|  |  | ||||||
| }  // namespace ota | }  // namespace ota | ||||||
| }  // namespace esphome | }  // namespace esphome | ||||||
|   | |||||||
| @@ -5,6 +5,8 @@ CODEOWNERS = ["@esphome/core"] | |||||||
| AUTO_LOAD = ["md5"] | AUTO_LOAD = ["md5"] | ||||||
|  |  | ||||||
| ota_base_ns = cg.esphome_ns.namespace("ota_base") | ota_base_ns = cg.esphome_ns.namespace("ota_base") | ||||||
|  | OTAComponent = ota_base_ns.class_("OTAComponent", cg.Component) | ||||||
|  | OTAState = ota_base_ns.enum("OTAState") | ||||||
|  |  | ||||||
|  |  | ||||||
| @coroutine_with_priority(52.0) | @coroutine_with_priority(52.0) | ||||||
|   | |||||||
| @@ -69,7 +69,29 @@ class OTAComponent : public Component { | |||||||
|   } |   } | ||||||
|  |  | ||||||
|  protected: |  protected: | ||||||
|   CallbackManager<void(OTAState, float, uint8_t)> state_callback_{}; |   /** Thread-safe callback manager that automatically defers to main loop. | ||||||
|  |    * | ||||||
|  |    * This ensures all OTA callbacks are executed in the main loop task, | ||||||
|  |    * making them safe to call from any context (including web_server's OTA task). | ||||||
|  |    * Existing code doesn't need changes - callbacks are automatically deferred. | ||||||
|  |    */ | ||||||
|  |   class DeferredCallbackManager : public CallbackManager<void(OTAState, float, uint8_t)> { | ||||||
|  |    public: | ||||||
|  |     DeferredCallbackManager(OTAComponent *component) : component_(component) {} | ||||||
|  |  | ||||||
|  |     /// Override call to automatically defer to main loop | ||||||
|  |     void call(OTAState state, float progress, uint8_t error) { | ||||||
|  |       // Always defer to main loop for thread safety | ||||||
|  |       component_->defer([this, state, progress, error]() { | ||||||
|  |         CallbackManager<void(OTAState, float, uint8_t)>::call(state, progress, error); | ||||||
|  |       }); | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |    private: | ||||||
|  |     OTAComponent *component_; | ||||||
|  |   }; | ||||||
|  |  | ||||||
|  |   DeferredCallbackManager state_callback_{this}; | ||||||
| #endif | #endif | ||||||
| }; | }; | ||||||
|  |  | ||||||
| @@ -92,13 +114,10 @@ class OTAGlobalCallback { | |||||||
| OTAGlobalCallback *get_global_ota_callback(); | OTAGlobalCallback *get_global_ota_callback(); | ||||||
| void register_ota_platform(OTAComponent *ota_caller); | void register_ota_platform(OTAComponent *ota_caller); | ||||||
|  |  | ||||||
| // TODO: When web_server is updated to use ota_base, we need to add thread-safe | // Thread-safe callback execution is automatically provided by DeferredCallbackManager | ||||||
| // callback execution. The web_server OTA runs in a separate task, so callbacks | // which overrides call() to use Component::defer(). This ensures all OTA callbacks | ||||||
| // need to be deferred to the main loop task to avoid race conditions. | // run in the main loop task, making them safe to call from any context including | ||||||
| // This could be implemented using: | // web_server's separate OTA task. No code changes needed. | ||||||
| // - A queue of callback events that the main loop processes |  | ||||||
| // - Or using App.schedule() to defer callback execution to the main loop |  | ||||||
| // Example: App.schedule([=]() { state_callback_.call(state, progress, error); }); |  | ||||||
| #endif | #endif | ||||||
|  |  | ||||||
| }  // namespace ota_base | }  // namespace ota_base | ||||||
|   | |||||||
| @@ -111,7 +111,7 @@ class WebServerBase : public Component { | |||||||
|   void add_handler(AsyncWebHandler *handler); |   void add_handler(AsyncWebHandler *handler); | ||||||
|  |  | ||||||
|   // TODO: In future PR, update this to use ota_base instead of duplicating OTA code |   // TODO: In future PR, update this to use ota_base instead of duplicating OTA code | ||||||
|   // Important: OTA callbacks must be thread-safe as web server OTA runs in a separate task |   // Note: OTA callbacks in ota_base are automatically thread-safe via defer() | ||||||
|   void add_ota_handler(); |   void add_ota_handler(); | ||||||
|  |  | ||||||
|   void set_port(uint16_t port) { port_ = port; } |   void set_port(uint16_t port) { port_ = port; } | ||||||
|   | |||||||
		Reference in New Issue
	
	Block a user