mirror of
https://github.com/esphome/esphome.git
synced 2025-09-12 08:12:22 +01: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