Extract OTA backend functionality into separate ota_base component

This commit is contained in:
J. Nick Koston 2025-06-30 10:33:43 -05:00
parent aaa7117ec9
commit 9f51546023
No known key found for this signature in database
24 changed files with 130 additions and 93 deletions

View File

@ -18,7 +18,7 @@
#include <cinttypes>
#ifdef USE_OTA
#include "esphome/components/ota/ota_backend.h"
#include "esphome/components/ota/ota.h"
#endif
#ifdef USE_ESP32_BLE_SOFTWARE_COEXISTENCE

View File

@ -2,12 +2,13 @@
#ifdef USE_OTA
#include "esphome/components/md5/md5.h"
#include "esphome/components/network/util.h"
#include "esphome/components/ota/ota_backend.h"
#include "esphome/components/ota/ota_backend_arduino_esp32.h"
#include "esphome/components/ota/ota_backend_arduino_esp8266.h"
#include "esphome/components/ota/ota_backend_arduino_libretiny.h"
#include "esphome/components/ota/ota_backend_arduino_rp2040.h"
#include "esphome/components/ota/ota_backend_esp_idf.h"
#include "esphome/components/ota/ota.h" // For OTAComponent and callbacks
#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_esp8266.h"
#include "esphome/components/ota_base/ota_backend_arduino_libretiny.h"
#include "esphome/components/ota_base/ota_backend_arduino_rp2040.h"
#include "esphome/components/ota_base/ota_backend_esp_idf.h"
#include "esphome/core/application.h"
#include "esphome/core/hal.h"
#include "esphome/core/log.h"
@ -149,7 +150,7 @@ void ESPHomeOTAComponent::handle_() {
buf[1] = USE_OTA_VERSION;
this->writeall_(buf, 2);
backend = ota::make_ota_backend();
backend = ota_base::make_ota_backend();
// Read features - 1 byte
if (!this->readall_(buf, 1)) {

View File

@ -4,7 +4,7 @@
#ifdef USE_OTA
#include "esphome/core/helpers.h"
#include "esphome/core/preferences.h"
#include "esphome/components/ota/ota_backend.h"
#include "esphome/components/ota/ota.h"
#include "esphome/components/socket/socket.h"
namespace esphome {

View File

@ -6,11 +6,12 @@
#include "esphome/components/md5/md5.h"
#include "esphome/components/watchdog/watchdog.h"
#include "esphome/components/ota/ota_backend.h"
#include "esphome/components/ota/ota_backend_arduino_esp32.h"
#include "esphome/components/ota/ota_backend_arduino_esp8266.h"
#include "esphome/components/ota/ota_backend_arduino_rp2040.h"
#include "esphome/components/ota/ota_backend_esp_idf.h"
#include "esphome/components/ota/ota.h" // For OTAComponent and callbacks
#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_esp8266.h"
#include "esphome/components/ota_base/ota_backend_arduino_rp2040.h"
#include "esphome/components/ota_base/ota_backend_esp_idf.h"
namespace esphome {
namespace http_request {
@ -115,7 +116,7 @@ uint8_t OtaHttpRequestComponent::do_ota_() {
ESP_LOGV(TAG, "MD5Digest initialized");
ESP_LOGV(TAG, "OTA backend begin");
auto backend = ota::make_ota_backend();
auto backend = ota_base::make_ota_backend();
auto error_code = backend->begin(container->content_length);
if (error_code != ota::OTA_RESPONSE_OK) {
ESP_LOGW(TAG, "backend->begin error: %d", error_code);

View File

@ -1,6 +1,6 @@
#pragma once
#include "esphome/components/ota/ota_backend.h"
#include "esphome/components/ota/ota.h"
#include "esphome/core/component.h"
#include "esphome/core/defines.h"
#include "esphome/core/helpers.h"

View File

@ -9,7 +9,7 @@
#include "esphome/components/audio/audio_transfer_buffer.h"
#ifdef USE_OTA
#include "esphome/components/ota/ota_backend.h"
#include "esphome/components/ota/ota.h"
#endif
namespace esphome {

View File

@ -8,10 +8,10 @@ from esphome.const import (
CONF_PLATFORM,
CONF_TRIGGER_ID,
)
from esphome.core import CORE, coroutine_with_priority
from esphome.core import coroutine_with_priority
CODEOWNERS = ["@esphome/core"]
AUTO_LOAD = ["md5", "safe_mode"]
AUTO_LOAD = ["safe_mode", "ota_base"]
IS_PLATFORM_COMPONENT = True
@ -84,12 +84,6 @@ BASE_OTA_SCHEMA = cv.Schema(
async def to_code(config):
cg.add_define("USE_OTA")
if CORE.is_esp32 and CORE.using_arduino:
cg.add_library("Update", None)
if CORE.is_rp2040 and CORE.using_arduino:
cg.add_library("Updater", None)
async def ota_to_code(var, config):
await cg.past_safe_mode()

View File

@ -1,6 +1,6 @@
#pragma once
#ifdef USE_OTA_STATE_CALLBACK
#include "ota_backend.h"
#include "ota.h"
#include "esphome/core/automation.h"

View File

@ -1,4 +1,4 @@
#include "ota_backend.h"
#include "ota.h"
namespace esphome {
namespace ota {

View File

@ -0,0 +1,52 @@
#pragma once
#include "esphome/core/component.h"
#include "esphome/core/defines.h"
#include "esphome/components/ota_base/ota_backend.h"
#ifdef USE_OTA_STATE_CALLBACK
#include "esphome/core/automation.h"
#endif
namespace esphome {
namespace ota {
// Import types from ota_base namespace for backward compatibility
using ota_base::OTABackend;
using ota_base::OTAResponseTypes;
using ota_base::OTAState;
class OTAComponent : public Component {
#ifdef USE_OTA_STATE_CALLBACK
public:
void add_on_state_callback(std::function<void(ota_base::OTAState, float, uint8_t)> &&callback) {
this->state_callback_.add(std::move(callback));
}
protected:
CallbackManager<void(ota_base::OTAState, float, uint8_t)> state_callback_{};
#endif
};
#ifdef USE_OTA_STATE_CALLBACK
class OTAGlobalCallback {
public:
void register_ota(OTAComponent *ota_caller) {
ota_caller->add_on_state_callback([this, ota_caller](ota_base::OTAState state, float progress, uint8_t error) {
this->state_callback_.call(state, progress, error, ota_caller);
});
}
void add_on_state_callback(std::function<void(ota_base::OTAState, float, uint8_t, OTAComponent *)> &&callback) {
this->state_callback_.add(std::move(callback));
}
protected:
CallbackManager<void(ota_base::OTAState, float, uint8_t, OTAComponent *)> state_callback_{};
};
OTAGlobalCallback *get_global_ota_callback();
void register_ota_platform(OTAComponent *ota_caller);
#endif
} // namespace ota
} // namespace esphome

View File

@ -0,0 +1,16 @@
import esphome.codegen as cg
from esphome.core import CORE, coroutine_with_priority
CODEOWNERS = ["@esphome/core"]
AUTO_LOAD = ["md5"]
ota_base_ns = cg.esphome_ns.namespace("ota_base")
@coroutine_with_priority(52.0)
async def to_code(config):
if CORE.is_esp32 and CORE.using_arduino:
cg.add_library("Update", None)
if CORE.is_rp2040 and CORE.using_arduino:
cg.add_library("Updater", None)

View File

@ -0,0 +1,9 @@
#include "ota_backend.h"
namespace esphome {
namespace ota_base {
// The make_ota_backend() implementation is provided by each platform-specific backend
} // namespace ota_base
} // namespace esphome

View File

@ -1,15 +1,10 @@
#pragma once
#include "esphome/core/component.h"
#include "esphome/core/defines.h"
#include "esphome/core/helpers.h"
#ifdef USE_OTA_STATE_CALLBACK
#include "esphome/core/automation.h"
#endif
namespace esphome {
namespace ota {
namespace ota_base {
enum OTAResponseTypes {
OTA_RESPONSE_OK = 0x00,
@ -59,38 +54,7 @@ class OTABackend {
virtual bool supports_compression() = 0;
};
class OTAComponent : public Component {
#ifdef USE_OTA_STATE_CALLBACK
public:
void add_on_state_callback(std::function<void(ota::OTAState, float, uint8_t)> &&callback) {
this->state_callback_.add(std::move(callback));
}
std::unique_ptr<OTABackend> make_ota_backend();
protected:
CallbackManager<void(ota::OTAState, float, uint8_t)> state_callback_{};
#endif
};
#ifdef USE_OTA_STATE_CALLBACK
class OTAGlobalCallback {
public:
void register_ota(OTAComponent *ota_caller) {
ota_caller->add_on_state_callback([this, ota_caller](OTAState state, float progress, uint8_t error) {
this->state_callback_.call(state, progress, error, ota_caller);
});
}
void add_on_state_callback(std::function<void(OTAState, float, uint8_t, OTAComponent *)> &&callback) {
this->state_callback_.add(std::move(callback));
}
protected:
CallbackManager<void(OTAState, float, uint8_t, OTAComponent *)> state_callback_{};
};
OTAGlobalCallback *get_global_ota_callback();
void register_ota_platform(OTAComponent *ota_caller);
#endif
std::unique_ptr<ota::OTABackend> make_ota_backend();
} // namespace ota
} // namespace esphome
} // namespace ota_base
} // namespace esphome

View File

@ -8,11 +8,11 @@
#include <Update.h>
namespace esphome {
namespace ota {
namespace ota_base {
static const char *const TAG = "ota.arduino_esp32";
std::unique_ptr<ota::OTABackend> make_ota_backend() { return make_unique<ota::ArduinoESP32OTABackend>(); }
std::unique_ptr<OTABackend> make_ota_backend() { return make_unique<ArduinoESP32OTABackend>(); }
OTAResponseTypes ArduinoESP32OTABackend::begin(size_t image_size) {
bool ret = Update.begin(image_size, U_FLASH);
@ -56,7 +56,7 @@ OTAResponseTypes ArduinoESP32OTABackend::end() {
void ArduinoESP32OTABackend::abort() { Update.abort(); }
} // namespace ota
} // namespace ota_base
} // namespace esphome
#endif // USE_ESP32_FRAMEWORK_ARDUINO

View File

@ -6,7 +6,7 @@
#include "esphome/core/helpers.h"
namespace esphome {
namespace ota {
namespace ota_base {
class ArduinoESP32OTABackend : public OTABackend {
public:
@ -18,7 +18,7 @@ class ArduinoESP32OTABackend : public OTABackend {
bool supports_compression() override { return false; }
};
} // namespace ota
} // namespace ota_base
} // namespace esphome
#endif // USE_ESP32_FRAMEWORK_ARDUINO

View File

@ -10,11 +10,11 @@
#include <Updater.h>
namespace esphome {
namespace ota {
namespace ota_base {
static const char *const TAG = "ota.arduino_esp8266";
std::unique_ptr<ota::OTABackend> make_ota_backend() { return make_unique<ota::ArduinoESP8266OTABackend>(); }
std::unique_ptr<OTABackend> make_ota_backend() { return make_unique<ArduinoESP8266OTABackend>(); }
OTAResponseTypes ArduinoESP8266OTABackend::begin(size_t image_size) {
bool ret = Update.begin(image_size, U_FLASH);
@ -68,7 +68,7 @@ void ArduinoESP8266OTABackend::abort() {
esp8266::preferences_prevent_write(false);
}
} // namespace ota
} // namespace ota_base
} // namespace esphome
#endif

View File

@ -7,7 +7,7 @@
#include "esphome/core/macros.h"
namespace esphome {
namespace ota {
namespace ota_base {
class ArduinoESP8266OTABackend : public OTABackend {
public:
@ -23,7 +23,7 @@ class ArduinoESP8266OTABackend : public OTABackend {
#endif
};
} // namespace ota
} // namespace ota_base
} // namespace esphome
#endif

View File

@ -8,11 +8,11 @@
#include <Update.h>
namespace esphome {
namespace ota {
namespace ota_base {
static const char *const TAG = "ota.arduino_libretiny";
std::unique_ptr<ota::OTABackend> make_ota_backend() { return make_unique<ota::ArduinoLibreTinyOTABackend>(); }
std::unique_ptr<OTABackend> make_ota_backend() { return make_unique<ArduinoLibreTinyOTABackend>(); }
OTAResponseTypes ArduinoLibreTinyOTABackend::begin(size_t image_size) {
bool ret = Update.begin(image_size, U_FLASH);
@ -56,7 +56,7 @@ OTAResponseTypes ArduinoLibreTinyOTABackend::end() {
void ArduinoLibreTinyOTABackend::abort() { Update.abort(); }
} // namespace ota
} // namespace ota_base
} // namespace esphome
#endif // USE_LIBRETINY

View File

@ -5,7 +5,7 @@
#include "esphome/core/defines.h"
namespace esphome {
namespace ota {
namespace ota_base {
class ArduinoLibreTinyOTABackend : public OTABackend {
public:
@ -17,7 +17,7 @@ class ArduinoLibreTinyOTABackend : public OTABackend {
bool supports_compression() override { return false; }
};
} // namespace ota
} // namespace ota_base
} // namespace esphome
#endif // USE_LIBRETINY

View File

@ -10,11 +10,11 @@
#include <Updater.h>
namespace esphome {
namespace ota {
namespace ota_base {
static const char *const TAG = "ota.arduino_rp2040";
std::unique_ptr<ota::OTABackend> make_ota_backend() { return make_unique<ota::ArduinoRP2040OTABackend>(); }
std::unique_ptr<OTABackend> make_ota_backend() { return make_unique<ArduinoRP2040OTABackend>(); }
OTAResponseTypes ArduinoRP2040OTABackend::begin(size_t image_size) {
bool ret = Update.begin(image_size, U_FLASH);
@ -68,7 +68,7 @@ void ArduinoRP2040OTABackend::abort() {
rp2040::preferences_prevent_write(false);
}
} // namespace ota
} // namespace ota_base
} // namespace esphome
#endif // USE_RP2040

View File

@ -7,7 +7,7 @@
#include "esphome/core/macros.h"
namespace esphome {
namespace ota {
namespace ota_base {
class ArduinoRP2040OTABackend : public OTABackend {
public:
@ -19,7 +19,7 @@ class ArduinoRP2040OTABackend : public OTABackend {
bool supports_compression() override { return false; }
};
} // namespace ota
} // namespace ota_base
} // namespace esphome
#endif // USE_RP2040

View File

@ -12,9 +12,9 @@
#endif
namespace esphome {
namespace ota {
namespace ota_base {
std::unique_ptr<ota::OTABackend> make_ota_backend() { return make_unique<ota::IDFOTABackend>(); }
std::unique_ptr<OTABackend> make_ota_backend() { return make_unique<IDFOTABackend>(); }
OTAResponseTypes IDFOTABackend::begin(size_t image_size) {
this->partition_ = esp_ota_get_next_update_partition(nullptr);
@ -111,6 +111,6 @@ void IDFOTABackend::abort() {
this->update_handle_ = 0;
}
} // namespace ota
} // namespace ota_base
} // namespace esphome
#endif

View File

@ -8,7 +8,7 @@
#include <esp_ota_ops.h>
namespace esphome {
namespace ota {
namespace ota_base {
class IDFOTABackend : public OTABackend {
public:
@ -26,6 +26,6 @@ class IDFOTABackend : public OTABackend {
char expected_bin_md5_[32];
};
} // namespace ota
} // namespace ota_base
} // namespace esphome
#endif

View File

@ -6,7 +6,7 @@
#include "esphome/components/audio/audio.h"
#ifdef USE_OTA
#include "esphome/components/ota/ota_backend.h"
#include "esphome/components/ota/ota.h"
#endif
namespace esphome {