proper state machine

This commit is contained in:
J. Nick Koston 2025-06-29 19:31:01 -05:00
parent 8e00fedc67
commit 59bcbe7fef
No known key found for this signature in database
2 changed files with 20 additions and 14 deletions

View File

@ -119,8 +119,7 @@ void OTARequestHandler::handleUpload(AsyncWebServerRequest *request, const Strin
// ESP-IDF implementation
if (index == 0) {
this->ota_init_(filename.c_str());
this->ota_started_ = false;
this->ota_success_ = false;
this->ota_state_ = OTAState::IDLE;
// Create OTA backend
auto backend = ota::make_ota_backend();
@ -129,15 +128,16 @@ void OTARequestHandler::handleUpload(AsyncWebServerRequest *request, const Strin
auto result = backend->begin(0);
if (result != ota::OTA_RESPONSE_OK) {
ESP_LOGE(TAG, "OTA begin failed: %d", result);
this->ota_state_ = OTAState::FAILED;
return;
}
// Store the backend pointer
this->ota_backend_ = backend.release();
this->ota_started_ = true;
this->ota_state_ = OTAState::STARTED;
}
if (!this->ota_started_ || !this->ota_backend_) {
if (this->ota_state_ != OTAState::STARTED && this->ota_state_ != OTAState::IN_PROGRESS) {
// Begin failed or was aborted
return;
}
@ -145,6 +145,7 @@ void OTARequestHandler::handleUpload(AsyncWebServerRequest *request, const Strin
// Write data
if (len > 0) {
auto *backend = static_cast<ota::OTABackend *>(this->ota_backend_);
this->ota_state_ = OTAState::IN_PROGRESS;
auto result = backend->write(data, len);
if (result != ota::OTA_RESPONSE_OK) {
@ -152,8 +153,7 @@ void OTARequestHandler::handleUpload(AsyncWebServerRequest *request, const Strin
backend->abort();
delete backend;
this->ota_backend_ = nullptr;
this->ota_started_ = false;
this->ota_success_ = false;
this->ota_state_ = OTAState::FAILED;
return;
}
@ -165,15 +165,14 @@ void OTARequestHandler::handleUpload(AsyncWebServerRequest *request, const Strin
auto *backend = static_cast<ota::OTABackend *>(this->ota_backend_);
auto result = backend->end();
if (result == ota::OTA_RESPONSE_OK) {
this->ota_success_ = true;
this->ota_state_ = OTAState::SUCCESS;
this->schedule_ota_reboot_();
} else {
ESP_LOGE(TAG, "OTA end failed: %d", result);
this->ota_success_ = false;
this->ota_state_ = OTAState::FAILED;
}
delete backend;
this->ota_backend_ = nullptr;
this->ota_started_ = false;
}
#endif // USE_ESP_IDF
#endif // USE_WEBSERVER_OTA
@ -195,7 +194,7 @@ void OTARequestHandler::handleRequest(AsyncWebServerRequest *request) {
#ifdef USE_ESP_IDF
// For ESP-IDF, we use direct send() instead of beginResponse()
// to ensure the response is sent immediately before the reboot.
request->send(200, "text/plain", this->ota_success_ ? "Update Successful!" : "Update Failed!");
request->send(200, "text/plain", this->ota_state_ == OTAState::SUCCESS ? "Update Successful!" : "Update Failed!");
return;
#endif // USE_ESP_IDF
response->addHeader("Connection", "close");

View File

@ -130,8 +130,7 @@ class OTARequestHandler : public AsyncWebHandler {
OTARequestHandler(WebServerBase *parent) : parent_(parent) {
#if defined(USE_ESP_IDF) && defined(USE_WEBSERVER_OTA)
this->ota_backend_ = nullptr;
this->ota_started_ = false;
this->ota_success_ = false;
this->ota_state_ = OTAState::IDLE;
#endif
}
void handleRequest(AsyncWebServerRequest *request) override;
@ -157,9 +156,17 @@ class OTARequestHandler : public AsyncWebHandler {
private:
#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};
bool ota_started_{false};
bool ota_success_{false};
OTAState ota_state_{OTAState::IDLE};
#endif
};