From c8f5a97cef2e67356642abe127744e484fc2541f Mon Sep 17 00:00:00 2001 From: guillempages Date: Tue, 6 Jan 2026 00:33:06 +0100 Subject: [PATCH] [esphome OTA] Allow compilation on host platform (#11655) Co-authored-by: J. Nick Koston Co-authored-by: J. Nick Koston --- .../components/esphome/ota/ota_esphome.cpp | 8 +++---- esphome/components/ota/__init__.py | 8 +++++++ esphome/components/ota/ota_backend_host.cpp | 24 +++++++++++++++++++ esphome/components/ota/ota_backend_host.h | 21 ++++++++++++++++ tests/components/ota/test.host.yaml | 4 ++++ 5 files changed, 61 insertions(+), 4 deletions(-) create mode 100644 esphome/components/ota/ota_backend_host.cpp create mode 100644 esphome/components/ota/ota_backend_host.h create mode 100644 tests/components/ota/test.host.yaml diff --git a/esphome/components/esphome/ota/ota_esphome.cpp b/esphome/components/esphome/ota/ota_esphome.cpp index 16d7089f02..ba25c69fae 100644 --- a/esphome/components/esphome/ota/ota_esphome.cpp +++ b/esphome/components/esphome/ota/ota_esphome.cpp @@ -387,14 +387,14 @@ bool ESPHomeOTAComponent::readall_(uint8_t *buf, size_t len) { while (len - at > 0) { uint32_t now = millis(); if (now - start > OTA_SOCKET_TIMEOUT_DATA) { - ESP_LOGW(TAG, "Timeout reading %d bytes", len); + ESP_LOGW(TAG, "Timeout reading %zu bytes", len); return false; } ssize_t read = this->client_->read(buf + at, len - at); if (read == -1) { if (!this->would_block_(errno)) { - ESP_LOGW(TAG, "Read err %d bytes, errno %d", len, errno); + ESP_LOGW(TAG, "Read err %zu bytes, errno %d", len, errno); return false; } } else if (read == 0) { @@ -414,14 +414,14 @@ bool ESPHomeOTAComponent::writeall_(const uint8_t *buf, size_t len) { while (len - at > 0) { uint32_t now = millis(); if (now - start > OTA_SOCKET_TIMEOUT_DATA) { - ESP_LOGW(TAG, "Timeout writing %d bytes", len); + ESP_LOGW(TAG, "Timeout writing %zu bytes", len); return false; } ssize_t written = this->client_->write(buf + at, len - at); if (written == -1) { if (!this->would_block_(errno)) { - ESP_LOGW(TAG, "Write err %d bytes, errno %d", len, errno); + ESP_LOGW(TAG, "Write err %zu bytes, errno %d", len, errno); return false; } } else { diff --git a/esphome/components/ota/__init__.py b/esphome/components/ota/__init__.py index a514a7482f..ee54d5f8d3 100644 --- a/esphome/components/ota/__init__.py +++ b/esphome/components/ota/__init__.py @@ -1,3 +1,5 @@ +import logging + from esphome import automation import esphome.codegen as cg from esphome.config_helpers import filter_source_files_from_platform @@ -27,6 +29,8 @@ CONF_ON_PROGRESS = "on_progress" CONF_ON_STATE_CHANGE = "on_state_change" +_LOGGER = logging.getLogger(__name__) + ota_ns = cg.esphome_ns.namespace("ota") OTAComponent = ota_ns.class_("OTAComponent", cg.Component) OTAState = ota_ns.enum("OTAState") @@ -45,6 +49,10 @@ def _ota_final_validate(config): raise cv.Invalid( f"At least one platform must be specified for '{CONF_OTA}'; add '{CONF_PLATFORM}: {CONF_ESPHOME}' for original OTA functionality" ) + if CORE.is_host: + _LOGGER.warning( + "OTA not available for platform 'host'. OTA functionality disabled." + ) FINAL_VALIDATE_SCHEMA = _ota_final_validate diff --git a/esphome/components/ota/ota_backend_host.cpp b/esphome/components/ota/ota_backend_host.cpp new file mode 100644 index 0000000000..ddab174bed --- /dev/null +++ b/esphome/components/ota/ota_backend_host.cpp @@ -0,0 +1,24 @@ +#ifdef USE_HOST +#include "ota_backend_host.h" + +#include "esphome/core/defines.h" + +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 make_ota_backend() { return make_unique(); } + +OTAResponseTypes HostOTABackend::begin(size_t image_size) { return OTA_RESPONSE_ERROR_UPDATE_PREPARE; } + +void HostOTABackend::set_update_md5(const char *expected_md5) {} + +OTAResponseTypes HostOTABackend::write(uint8_t *data, size_t len) { return OTA_RESPONSE_ERROR_WRITING_FLASH; } + +OTAResponseTypes HostOTABackend::end() { return OTA_RESPONSE_ERROR_UPDATE_END; } + +void HostOTABackend::abort() {} + +} // namespace esphome::ota +#endif diff --git a/esphome/components/ota/ota_backend_host.h b/esphome/components/ota/ota_backend_host.h new file mode 100644 index 0000000000..ae7d0cb0b3 --- /dev/null +++ b/esphome/components/ota/ota_backend_host.h @@ -0,0 +1,21 @@ +#pragma once +#ifdef USE_HOST +#include "ota_backend.h" + +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 : public OTABackend { + 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; } +}; + +} // namespace esphome::ota +#endif diff --git a/tests/components/ota/test.host.yaml b/tests/components/ota/test.host.yaml new file mode 100644 index 0000000000..ae7c4d0add --- /dev/null +++ b/tests/components/ota/test.host.yaml @@ -0,0 +1,4 @@ +<<: !include common.yaml + +#host platform does not support wifi / network is automatically included +wifi: !remove