mirror of
https://github.com/esphome/esphome.git
synced 2026-09-01 02:26:01 +00:00
[ota] Devirtualize OTA backend calls (#14473)
This commit is contained in:
@@ -2,7 +2,7 @@
|
||||
|
||||
#include "esphome/core/defines.h"
|
||||
#ifdef USE_OTA
|
||||
#include "esphome/components/ota/ota_backend.h"
|
||||
#include "esphome/components/ota/ota_backend_factory.h"
|
||||
#include "esphome/components/socket/socket.h"
|
||||
#include "esphome/core/helpers.h"
|
||||
#include "esphome/core/log.h"
|
||||
@@ -86,7 +86,7 @@ class ESPHomeOTAComponent final : public ota::OTAComponent {
|
||||
|
||||
socket::ListenSocket *server_{nullptr};
|
||||
std::unique_ptr<socket::Socket> client_;
|
||||
std::unique_ptr<ota::OTABackend> backend_;
|
||||
ota::OTABackendPtr backend_;
|
||||
|
||||
uint32_t client_connect_time_{0};
|
||||
uint16_t port_;
|
||||
|
||||
@@ -8,10 +8,6 @@
|
||||
|
||||
#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_esp8266.h"
|
||||
#include "esphome/components/ota/ota_backend_arduino_rp2040.h"
|
||||
#include "esphome/components/ota/ota_backend_esp_idf.h"
|
||||
|
||||
namespace esphome {
|
||||
namespace http_request {
|
||||
@@ -69,8 +65,7 @@ void OtaHttpRequestComponent::flash() {
|
||||
}
|
||||
}
|
||||
|
||||
void OtaHttpRequestComponent::cleanup_(std::unique_ptr<ota::OTABackend> backend,
|
||||
const std::shared_ptr<HttpContainer> &container) {
|
||||
void OtaHttpRequestComponent::cleanup_(ota::OTABackendPtr backend, const std::shared_ptr<HttpContainer> &container) {
|
||||
if (this->update_started_) {
|
||||
ESP_LOGV(TAG, "Aborting OTA backend");
|
||||
backend->abort();
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
#pragma once
|
||||
|
||||
#include "esphome/components/ota/ota_backend.h"
|
||||
#include "esphome/components/ota/ota_backend_factory.h"
|
||||
#include "esphome/core/component.h"
|
||||
#include "esphome/core/defines.h"
|
||||
#include "esphome/core/helpers.h"
|
||||
@@ -39,7 +39,7 @@ class OtaHttpRequestComponent final : public ota::OTAComponent, public Parented<
|
||||
void flash();
|
||||
|
||||
protected:
|
||||
void cleanup_(std::unique_ptr<ota::OTABackend> backend, const std::shared_ptr<HttpContainer> &container);
|
||||
void cleanup_(ota::OTABackendPtr backend, const std::shared_ptr<HttpContainer> &container);
|
||||
uint8_t do_ota_();
|
||||
std::string get_url_with_auth_(const std::string &url);
|
||||
bool http_get_md5_();
|
||||
|
||||
@@ -49,17 +49,6 @@ enum OTAState {
|
||||
OTA_ERROR,
|
||||
};
|
||||
|
||||
class OTABackend {
|
||||
public:
|
||||
virtual ~OTABackend() = default;
|
||||
virtual OTAResponseTypes begin(size_t image_size) = 0;
|
||||
virtual void set_update_md5(const char *md5) = 0;
|
||||
virtual OTAResponseTypes write(uint8_t *data, size_t len) = 0;
|
||||
virtual OTAResponseTypes end() = 0;
|
||||
virtual void abort() = 0;
|
||||
virtual bool supports_compression() = 0;
|
||||
};
|
||||
|
||||
/** Listener interface for OTA state changes.
|
||||
*
|
||||
* Components can implement this interface to receive OTA state updates
|
||||
@@ -130,7 +119,5 @@ OTAGlobalCallback *get_global_ota_callback();
|
||||
// - notify_state_deferred_() when in separate task (e.g., web_server OTA)
|
||||
// This ensures proper listener execution in all contexts.
|
||||
#endif
|
||||
std::unique_ptr<ota::OTABackend> make_ota_backend();
|
||||
|
||||
} // namespace ota
|
||||
} // namespace esphome
|
||||
|
||||
@@ -12,7 +12,7 @@ namespace ota {
|
||||
|
||||
static const char *const TAG = "ota.arduino_libretiny";
|
||||
|
||||
std::unique_ptr<ota::OTABackend> make_ota_backend() { return make_unique<ota::ArduinoLibreTinyOTABackend>(); }
|
||||
std::unique_ptr<ArduinoLibreTinyOTABackend> make_ota_backend() { return make_unique<ArduinoLibreTinyOTABackend>(); }
|
||||
|
||||
OTAResponseTypes ArduinoLibreTinyOTABackend::begin(size_t image_size) {
|
||||
// Handle UPDATE_SIZE_UNKNOWN (0) which is used by web server OTA
|
||||
|
||||
@@ -7,19 +7,21 @@
|
||||
namespace esphome {
|
||||
namespace ota {
|
||||
|
||||
class ArduinoLibreTinyOTABackend final : public OTABackend {
|
||||
class ArduinoLibreTinyOTABackend final {
|
||||
public:
|
||||
OTAResponseTypes begin(size_t image_size) override;
|
||||
void set_update_md5(const char *md5) override;
|
||||
OTAResponseTypes write(uint8_t *data, size_t len) override;
|
||||
OTAResponseTypes end() override;
|
||||
void abort() override;
|
||||
bool supports_compression() override { return false; }
|
||||
OTAResponseTypes begin(size_t image_size);
|
||||
void set_update_md5(const char *md5);
|
||||
OTAResponseTypes write(uint8_t *data, size_t len);
|
||||
OTAResponseTypes end();
|
||||
void abort();
|
||||
bool supports_compression() { return false; }
|
||||
|
||||
private:
|
||||
bool md5_set_{false};
|
||||
};
|
||||
|
||||
std::unique_ptr<ArduinoLibreTinyOTABackend> make_ota_backend();
|
||||
|
||||
} // namespace ota
|
||||
} // namespace esphome
|
||||
|
||||
|
||||
@@ -14,7 +14,7 @@ namespace ota {
|
||||
|
||||
static const char *const TAG = "ota.arduino_rp2040";
|
||||
|
||||
std::unique_ptr<ota::OTABackend> make_ota_backend() { return make_unique<ota::ArduinoRP2040OTABackend>(); }
|
||||
std::unique_ptr<ArduinoRP2040OTABackend> make_ota_backend() { return make_unique<ArduinoRP2040OTABackend>(); }
|
||||
|
||||
OTAResponseTypes ArduinoRP2040OTABackend::begin(size_t image_size) {
|
||||
// OTA size of 0 is not currently handled, but
|
||||
|
||||
@@ -9,19 +9,21 @@
|
||||
namespace esphome {
|
||||
namespace ota {
|
||||
|
||||
class ArduinoRP2040OTABackend final : public OTABackend {
|
||||
class ArduinoRP2040OTABackend final {
|
||||
public:
|
||||
OTAResponseTypes begin(size_t image_size) override;
|
||||
void set_update_md5(const char *md5) override;
|
||||
OTAResponseTypes write(uint8_t *data, size_t len) override;
|
||||
OTAResponseTypes end() override;
|
||||
void abort() override;
|
||||
bool supports_compression() override { return false; }
|
||||
OTAResponseTypes begin(size_t image_size);
|
||||
void set_update_md5(const char *md5);
|
||||
OTAResponseTypes write(uint8_t *data, size_t len);
|
||||
OTAResponseTypes end();
|
||||
void abort();
|
||||
bool supports_compression() { return false; }
|
||||
|
||||
private:
|
||||
bool md5_set_{false};
|
||||
};
|
||||
|
||||
std::unique_ptr<ArduinoRP2040OTABackend> make_ota_backend();
|
||||
|
||||
} // namespace ota
|
||||
} // namespace esphome
|
||||
|
||||
|
||||
@@ -48,7 +48,7 @@ namespace esphome::ota {
|
||||
|
||||
static const char *const TAG = "ota.esp8266";
|
||||
|
||||
std::unique_ptr<ota::OTABackend> make_ota_backend() { return make_unique<ota::ESP8266OTABackend>(); }
|
||||
std::unique_ptr<ESP8266OTABackend> make_ota_backend() { return make_unique<ESP8266OTABackend>(); }
|
||||
|
||||
OTAResponseTypes ESP8266OTABackend::begin(size_t image_size) {
|
||||
// Handle UPDATE_SIZE_UNKNOWN (0) by calculating available space
|
||||
|
||||
@@ -12,15 +12,15 @@ namespace esphome::ota {
|
||||
/// OTA backend for ESP8266 using native SDK functions.
|
||||
/// This implementation bypasses the Arduino Updater library to save ~228 bytes of RAM
|
||||
/// by not having a global Update object in .bss.
|
||||
class ESP8266OTABackend final : public OTABackend {
|
||||
class ESP8266OTABackend final {
|
||||
public:
|
||||
OTAResponseTypes begin(size_t image_size) override;
|
||||
void set_update_md5(const char *md5) override;
|
||||
OTAResponseTypes write(uint8_t *data, size_t len) override;
|
||||
OTAResponseTypes end() override;
|
||||
void abort() override;
|
||||
OTAResponseTypes begin(size_t image_size);
|
||||
void set_update_md5(const char *md5);
|
||||
OTAResponseTypes write(uint8_t *data, size_t len);
|
||||
OTAResponseTypes end();
|
||||
void abort();
|
||||
// Compression supported in all ESP8266 Arduino versions ESPHome supports (>= 2.7.0)
|
||||
bool supports_compression() override { return true; }
|
||||
bool supports_compression() { return true; }
|
||||
|
||||
protected:
|
||||
/// Erase flash sector if current address is at sector boundary
|
||||
@@ -54,5 +54,7 @@ class ESP8266OTABackend final : public OTABackend {
|
||||
bool md5_set_{false};
|
||||
};
|
||||
|
||||
std::unique_ptr<ESP8266OTABackend> make_ota_backend();
|
||||
|
||||
} // namespace esphome::ota
|
||||
#endif // USE_ESP8266
|
||||
|
||||
@@ -11,7 +11,7 @@
|
||||
namespace esphome {
|
||||
namespace ota {
|
||||
|
||||
std::unique_ptr<ota::OTABackend> make_ota_backend() { return make_unique<ota::IDFOTABackend>(); }
|
||||
std::unique_ptr<IDFOTABackend> make_ota_backend() { return make_unique<IDFOTABackend>(); }
|
||||
|
||||
OTAResponseTypes IDFOTABackend::begin(size_t image_size) {
|
||||
#ifdef USE_OTA_ROLLBACK
|
||||
|
||||
@@ -10,14 +10,14 @@
|
||||
namespace esphome {
|
||||
namespace ota {
|
||||
|
||||
class IDFOTABackend final : public OTABackend {
|
||||
class IDFOTABackend final {
|
||||
public:
|
||||
OTAResponseTypes begin(size_t image_size) override;
|
||||
void set_update_md5(const char *md5) override;
|
||||
OTAResponseTypes write(uint8_t *data, size_t len) override;
|
||||
OTAResponseTypes end() override;
|
||||
void abort() override;
|
||||
bool supports_compression() override { return false; }
|
||||
OTAResponseTypes begin(size_t image_size);
|
||||
void set_update_md5(const char *md5);
|
||||
OTAResponseTypes write(uint8_t *data, size_t len);
|
||||
OTAResponseTypes end();
|
||||
void abort();
|
||||
bool supports_compression() { return false; }
|
||||
|
||||
private:
|
||||
esp_ota_handle_t update_handle_{0};
|
||||
@@ -27,6 +27,8 @@ class IDFOTABackend final : public OTABackend {
|
||||
bool md5_set_{false};
|
||||
};
|
||||
|
||||
std::unique_ptr<IDFOTABackend> make_ota_backend();
|
||||
|
||||
} // namespace ota
|
||||
} // namespace esphome
|
||||
#endif // USE_ESP32
|
||||
|
||||
@@ -0,0 +1,27 @@
|
||||
#pragma once
|
||||
|
||||
#include "ota_backend.h"
|
||||
|
||||
#include <memory>
|
||||
|
||||
#ifdef USE_ESP8266
|
||||
#include "ota_backend_esp8266.h"
|
||||
#elif defined(USE_ESP32)
|
||||
#include "ota_backend_esp_idf.h"
|
||||
#elif defined(USE_RP2040)
|
||||
#include "ota_backend_arduino_rp2040.h"
|
||||
#elif defined(USE_LIBRETINY)
|
||||
#include "ota_backend_arduino_libretiny.h"
|
||||
#elif defined(USE_HOST)
|
||||
#include "ota_backend_host.h"
|
||||
#else
|
||||
// Stub for static analysis when no platform is defined
|
||||
namespace esphome::ota {
|
||||
struct StubOTABackend {};
|
||||
std::unique_ptr<StubOTABackend> make_ota_backend();
|
||||
} // namespace esphome::ota
|
||||
#endif
|
||||
|
||||
namespace esphome::ota {
|
||||
using OTABackendPtr = decltype(make_ota_backend());
|
||||
} // namespace esphome::ota
|
||||
@@ -8,7 +8,7 @@ namespace esphome::ota {
|
||||
// Stub implementation - OTA is not supported on host platform.
|
||||
// All methods return error codes to allow compilation of configs with OTA triggers.
|
||||
|
||||
std::unique_ptr<ota::OTABackend> make_ota_backend() { return make_unique<ota::HostOTABackend>(); }
|
||||
std::unique_ptr<HostOTABackend> make_ota_backend() { return make_unique<HostOTABackend>(); }
|
||||
|
||||
OTAResponseTypes HostOTABackend::begin(size_t image_size) { return OTA_RESPONSE_ERROR_UPDATE_PREPARE; }
|
||||
|
||||
|
||||
@@ -7,15 +7,17 @@ namespace esphome::ota {
|
||||
/// Stub OTA backend for host platform - allows compilation but does not implement OTA.
|
||||
/// All operations return error codes immediately. This enables configurations with
|
||||
/// OTA triggers to compile for host platform during development.
|
||||
class HostOTABackend final : public OTABackend {
|
||||
class HostOTABackend final {
|
||||
public:
|
||||
OTAResponseTypes begin(size_t image_size) override;
|
||||
void set_update_md5(const char *md5) override;
|
||||
OTAResponseTypes write(uint8_t *data, size_t len) override;
|
||||
OTAResponseTypes end() override;
|
||||
void abort() override;
|
||||
bool supports_compression() override { return false; }
|
||||
OTAResponseTypes begin(size_t image_size);
|
||||
void set_update_md5(const char *md5);
|
||||
OTAResponseTypes write(uint8_t *data, size_t len);
|
||||
OTAResponseTypes end();
|
||||
void abort();
|
||||
bool supports_compression() { return false; }
|
||||
};
|
||||
|
||||
std::unique_ptr<HostOTABackend> make_ota_backend();
|
||||
|
||||
} // namespace esphome::ota
|
||||
#endif
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
#include "ota_web_server.h"
|
||||
#ifdef USE_WEBSERVER_OTA
|
||||
|
||||
#include "esphome/components/ota/ota_backend.h"
|
||||
#include "esphome/components/ota/ota_backend_factory.h"
|
||||
#include "esphome/core/application.h"
|
||||
#include "esphome/core/log.h"
|
||||
|
||||
@@ -71,7 +71,7 @@ class OTARequestHandler : public AsyncWebHandler {
|
||||
bool ota_success_{false};
|
||||
|
||||
private:
|
||||
std::unique_ptr<ota::OTABackend> ota_backend_{nullptr};
|
||||
ota::OTABackendPtr ota_backend_{nullptr};
|
||||
};
|
||||
|
||||
void OTARequestHandler::report_ota_progress_(AsyncWebServerRequest *request) {
|
||||
|
||||
Reference in New Issue
Block a user