diff --git a/esphome/components/ota_base/ota_backend_arduino_esp8266.cpp b/esphome/components/ota_base/ota_backend_arduino_esp8266.cpp index 38d0ad96c3..1133ce7b05 100644 --- a/esphome/components/ota_base/ota_backend_arduino_esp8266.cpp +++ b/esphome/components/ota_base/ota_backend_arduino_esp8266.cpp @@ -17,6 +17,11 @@ static const char *const TAG = "ota.arduino_esp8266"; std::unique_ptr make_ota_backend() { return make_unique(); } OTAResponseTypes ArduinoESP8266OTABackend::begin(size_t image_size) { + // Handle UPDATE_SIZE_UNKNOWN (0) by calculating available space + if (image_size == 0) { + // NOLINTNEXTLINE(readability-static-accessed-through-instance) + image_size = (ESP.getFreeSketchSpace() - 0x1000) & 0xFFFFF000; + } bool ret = Update.begin(image_size, U_FLASH); if (ret) { esp8266::preferences_prevent_write(true); diff --git a/esphome/components/web_server_base/web_server_base.cpp b/esphome/components/web_server_base/web_server_base.cpp index fbc3adbf03..babef752d9 100644 --- a/esphome/components/web_server_base/web_server_base.cpp +++ b/esphome/components/web_server_base/web_server_base.cpp @@ -4,20 +4,18 @@ #include "esphome/core/helpers.h" #include "esphome/core/log.h" -#ifdef USE_ARDUINO -#include -#if defined(USE_ESP32) || defined(USE_LIBRETINY) -#include -#endif -#ifdef USE_ESP8266 -#include -#endif -#endif - #ifdef USE_WEBSERVER_OTA #include "esphome/components/ota_base/ota_backend.h" #endif +#ifdef USE_ARDUINO +#ifdef USE_ESP8266 +#include +#elif defined(USE_ESP32) || defined(USE_LIBRETINY) +#include +#endif +#endif + namespace esphome { namespace web_server_base { @@ -62,72 +60,39 @@ void OTARequestHandler::ota_init_(const char *filename) { this->ota_read_length_ = 0; } -void report_ota_error() { -#ifdef USE_ARDUINO - StreamString ss; - Update.printError(ss); - ESP_LOGW(TAG, "OTA Update failed! Error: %s", ss.c_str()); -#endif -} - void OTARequestHandler::handleUpload(AsyncWebServerRequest *request, const String &filename, size_t index, uint8_t *data, size_t len, bool final) { -#ifdef USE_ARDUINO - bool success; - if (index == 0) { - this->ota_init_(filename.c_str()); -#ifdef USE_ESP8266 - Update.runAsync(true); - // NOLINTNEXTLINE(readability-static-accessed-through-instance) - success = Update.begin((ESP.getFreeSketchSpace() - 0x1000) & 0xFFFFF000); -#endif -#if defined(USE_ESP32_FRAMEWORK_ARDUINO) || defined(USE_LIBRETINY) - if (Update.isRunning()) { - Update.abort(); - } - success = Update.begin(UPDATE_SIZE_UNKNOWN, U_FLASH); -#endif - if (!success) { - report_ota_error(); - return; - } - } else if (Update.hasError()) { - // don't spam logs with errors if something failed at start - return; - } - - success = Update.write(data, len) == len; - if (!success) { - report_ota_error(); - return; - } - this->ota_read_length_ += len; - this->report_ota_progress_(request); - - if (final) { - if (Update.end(true)) { - this->schedule_ota_reboot_(); - } else { - report_ota_error(); - } - } -#endif // USE_ARDUINO - -#ifdef USE_ESP_IDF - // ESP-IDF implementation using ota_base backend ota_base::OTAResponseTypes error_code = ota_base::OTA_RESPONSE_OK; if (index == 0 && !this->ota_backend_) { // Initialize OTA on first call this->ota_init_(filename.c_str()); + // Platform-specific pre-initialization +#ifdef USE_ARDUINO +#ifdef USE_ESP8266 + Update.runAsync(true); +#endif +#if defined(USE_ESP32_FRAMEWORK_ARDUINO) || defined(USE_LIBRETINY) + if (Update.isRunning()) { + Update.abort(); + } +#endif +#endif // USE_ARDUINO + this->ota_backend_ = ota_base::make_ota_backend(); if (!this->ota_backend_) { ESP_LOGE(TAG, "Failed to create OTA backend"); return; } - error_code = this->ota_backend_->begin(request->contentLength()); + size_t ota_size = request->contentLength(); + if (ota_size == 0) { + // For chunked encoding, we don't know the size + ota_size = UPDATE_SIZE_UNKNOWN; + } + + error_code = this->ota_backend_->begin(ota_size); if (error_code != ota_base::OTA_RESPONSE_OK) { ESP_LOGE(TAG, "OTA begin failed: %d", error_code); this->ota_backend_.reset(); @@ -162,25 +127,12 @@ void OTARequestHandler::handleUpload(AsyncWebServerRequest *request, const Strin } this->ota_backend_.reset(); } -#endif // USE_ESP_IDF } void OTARequestHandler::handleRequest(AsyncWebServerRequest *request) { AsyncWebServerResponse *response; -#ifdef USE_ARDUINO - if (!Update.hasError()) { - response = request->beginResponse(200, "text/plain", "Update Successful!"); - } else { - StreamString ss; - ss.print("Update Failed: "); - Update.printError(ss); - response = request->beginResponse(200, "text/plain", ss); - } -#endif // USE_ARDUINO -#ifdef USE_ESP_IDF // Send response based on whether backend still exists (error) or was reset (success) response = request->beginResponse(200, "text/plain", !this->ota_backend_ ? "Update Successful!" : "Update Failed!"); -#endif // USE_ESP_IDF response->addHeader("Connection", "close"); request->send(response); }