This commit is contained in:
J. Nick Koston 2025-06-29 21:55:13 -05:00
parent 6968772a31
commit 22cb59b88c
No known key found for this signature in database
2 changed files with 21 additions and 40 deletions

View File

@ -117,43 +117,37 @@ void OTARequestHandler::handleUpload(AsyncWebServerRequest *request, const Strin
#ifdef USE_ESP_IDF #ifdef USE_ESP_IDF
// ESP-IDF implementation // ESP-IDF implementation
if (index == 0) { auto *backend = static_cast<ota::OTABackend *>(this->ota_backend_);
if (index == 0 && !backend) {
// Only initialize once when backend doesn't exist
this->ota_init_(filename.c_str()); this->ota_init_(filename.c_str());
this->ota_state_ = OTAState::IDLE; this->ota_success_ = false; // Reset success flag
// Create OTA backend // Create and begin OTA
auto backend = ota::make_ota_backend(); auto new_backend = ota::make_ota_backend();
auto result = new_backend->begin(0);
// Begin OTA with unknown size
auto result = backend->begin(0);
if (result != ota::OTA_RESPONSE_OK) { if (result != ota::OTA_RESPONSE_OK) {
ESP_LOGE(TAG, "OTA begin failed: %d", result); ESP_LOGE(TAG, "OTA begin failed: %d", result);
this->ota_state_ = OTAState::FAILED;
return; return;
} }
// Store the backend pointer this->ota_backend_ = new_backend.release();
this->ota_backend_ = backend.release(); backend = static_cast<ota::OTABackend *>(this->ota_backend_);
this->ota_state_ = OTAState::STARTED;
} }
if (this->ota_state_ != OTAState::STARTED && this->ota_state_ != OTAState::IN_PROGRESS) { if (!backend) {
// Begin failed or was aborted return; // Begin failed or was aborted
return;
} }
// Write data // Write data if provided
if (len > 0) { if (len > 0) {
auto *backend = static_cast<ota::OTABackend *>(this->ota_backend_);
this->ota_state_ = OTAState::IN_PROGRESS;
auto result = backend->write(data, len); auto result = backend->write(data, len);
if (result != ota::OTA_RESPONSE_OK) { if (result != ota::OTA_RESPONSE_OK) {
ESP_LOGE(TAG, "OTA write failed: %d", result); ESP_LOGE(TAG, "OTA write failed: %d", result);
backend->abort(); backend->abort();
delete backend; delete backend;
this->ota_backend_ = nullptr; this->ota_backend_ = nullptr;
this->ota_state_ = OTAState::FAILED;
return; return;
} }
@ -161,15 +155,14 @@ void OTARequestHandler::handleUpload(AsyncWebServerRequest *request, const Strin
this->report_ota_progress_(request); this->report_ota_progress_(request);
} }
// Finalize if requested
if (final) { if (final) {
auto *backend = static_cast<ota::OTABackend *>(this->ota_backend_);
auto result = backend->end(); auto result = backend->end();
if (result == ota::OTA_RESPONSE_OK) { this->ota_success_ = (result == ota::OTA_RESPONSE_OK);
this->ota_state_ = OTAState::SUCCESS; if (this->ota_success_) {
this->schedule_ota_reboot_(); this->schedule_ota_reboot_();
} else { } else {
ESP_LOGE(TAG, "OTA end failed: %d", result); ESP_LOGE(TAG, "OTA end failed: %d", result);
this->ota_state_ = OTAState::FAILED;
} }
delete backend; delete backend;
this->ota_backend_ = nullptr; this->ota_backend_ = nullptr;
@ -194,7 +187,9 @@ void OTARequestHandler::handleRequest(AsyncWebServerRequest *request) {
#ifdef USE_ESP_IDF #ifdef USE_ESP_IDF
// For ESP-IDF, we use direct send() instead of beginResponse() // For ESP-IDF, we use direct send() instead of beginResponse()
// to ensure the response is sent immediately before the reboot. // to ensure the response is sent immediately before the reboot.
request->send(200, "text/plain", this->ota_state_ == OTAState::SUCCESS ? "Update Successful!" : "Update Failed!"); // If ota_backend_ is nullptr and we got here, the update completed (either success or failure)
// We'll use ota_success_ flag set by handleUpload to determine the result
request->send(200, "text/plain", this->ota_success_ ? "Update Successful!" : "Update Failed!");
return; return;
#endif // USE_ESP_IDF #endif // USE_ESP_IDF
response->addHeader("Connection", "close"); response->addHeader("Connection", "close");

View File

@ -127,12 +127,7 @@ class WebServerBase : public Component {
class OTARequestHandler : public AsyncWebHandler { class OTARequestHandler : public AsyncWebHandler {
public: public:
OTARequestHandler(WebServerBase *parent) : parent_(parent) { OTARequestHandler(WebServerBase *parent) : parent_(parent) {}
#if defined(USE_ESP_IDF) && defined(USE_WEBSERVER_OTA)
this->ota_backend_ = nullptr;
this->ota_state_ = OTAState::IDLE;
#endif
}
void handleRequest(AsyncWebServerRequest *request) override; void handleRequest(AsyncWebServerRequest *request) override;
void handleUpload(AsyncWebServerRequest *request, const String &filename, size_t index, uint8_t *data, size_t len, void handleUpload(AsyncWebServerRequest *request, const String &filename, size_t index, uint8_t *data, size_t len,
bool final) override; bool final) override;
@ -156,17 +151,8 @@ class OTARequestHandler : public AsyncWebHandler {
private: private:
#if defined(USE_ESP_IDF) && defined(USE_WEBSERVER_OTA) #if defined(USE_ESP_IDF) && defined(USE_WEBSERVER_OTA)
// OTA state machine
enum class OTAState : uint8_t{
IDLE = 0, // No OTA in progress
STARTED, // OTA begin() succeeded
IN_PROGRESS, // Writing data
SUCCESS, // OTA end() succeeded
FAILED // OTA failed at any stage
};
void *ota_backend_{nullptr}; void *ota_backend_{nullptr};
OTAState ota_state_{OTAState::IDLE}; bool ota_success_{false};
#endif #endif
}; };