diff --git a/src/helpers/web/WebPanelServer.cpp b/src/helpers/web/WebPanelServer.cpp index eef42357..8a19dab7 100644 --- a/src/helpers/web/WebPanelServer.cpp +++ b/src/helpers/web/WebPanelServer.cpp @@ -2511,7 +2511,10 @@ const char kWebPanelAppHtml[] PROGMEM = R"HTML( }; document.getElementById("otaBtn").onclick = async () => { if (confirm("Start OTA mode now?")) { - await runCommand("start ota"); + const result = await runCommand("start ota"); + if (result && result.ok) { + window.open(window.location.origin + "/update", "_blank"); + } } }; const AUTO_REFRESH_INTERVAL = 60; @@ -2620,7 +2623,7 @@ const char kWebPanelAppHtml[] PROGMEM = R"HTML( } // namespace WebPanelServer::WebPanelServer() - : _runner(nullptr), _server(nullptr), _redirect_server(nullptr), _token{0}, _last_activity_ms(0), _route_context{this} { + : _runner(nullptr), _server(nullptr), _redirect_server(nullptr), _token{0}, _last_activity_ms(0), _route_context{this}, _ota_started(false) { } void WebPanelServer::setCommandRunner(WebPanelCommandRunner* runner) { @@ -2669,12 +2672,14 @@ bool WebPanelServer::start() { httpd_uri_t login_uri = {.uri = "/login", .method = HTTP_POST, .handler = &WebPanelServer::handleLogin, .user_ctx = &_route_context}; httpd_uri_t command_uri = {.uri = "/api/command", .method = HTTP_POST, .handler = &WebPanelServer::handleCommand, .user_ctx = &_route_context}; httpd_uri_t stats_uri = {.uri = "/api/stats", .method = HTTP_GET, .handler = &WebPanelServer::handleStats, .user_ctx = &_route_context}; + httpd_uri_t update = {.uri = "/update", .method = HTTP_GET, .handler = &WebPanelServer::handleOtaRedirect, .user_ctx = &_route_context}; httpd_register_uri_handler(_server, &index_uri); httpd_register_uri_handler(_server, &app_uri); httpd_register_uri_handler(_server, &stats_page_uri); httpd_register_uri_handler(_server, &login_uri); httpd_register_uri_handler(_server, &command_uri); httpd_register_uri_handler(_server, &stats_uri); + httpd_register_uri_handler(_server, &update); httpd_config_t redirect_config = HTTPD_DEFAULT_CONFIG(); redirect_config.server_port = 80; @@ -2745,6 +2750,10 @@ void WebPanelServer::lockSession() { _last_activity_ms = 0; } +void WebPanelServer::notifyOtaStarted() { + _ota_started = true; +} + esp_err_t WebPanelServer::handleIndex(httpd_req_t* req) { auto* ctx = static_cast(req->user_ctx); if (ctx == nullptr || ctx->self == nullptr) { @@ -2794,6 +2803,34 @@ esp_err_t WebPanelServer::handleStatsPage(httpd_req_t* req) { return sendProgmem(req, kWebPanelAppHtml); } +esp_err_t WebPanelServer::handleOtaRedirect(httpd_req_t* req) { + auto* ctx = static_cast(req->user_ctx); + if (ctx == nullptr || ctx->self == nullptr) { + return httpd_resp_send_500(req); + } + if (!ctx->self->_ota_started) { + httpd_resp_send_err(req, HTTPD_404_NOT_FOUND, "OTA not started"); + return ESP_OK; + } + + char host[64] = {}; + if (httpd_req_get_hdr_value_str(req, "Host", host, sizeof(host)) == ESP_OK && host[0] != '\0') { + char* colon = strchr(host, ':'); + if (colon != nullptr) *colon = '\0'; + } else { + strncpy(host, WiFi.localIP().toString().c_str(), sizeof(host) - 1); + host[sizeof(host) - 1] = '\0'; + } + char location[80]; + snprintf(location, sizeof(location), "http://%s/update", host); + + httpd_resp_set_status(req, "302 Found"); + httpd_resp_set_hdr(req, "Location", location); + httpd_resp_set_hdr(req, "Cache-Control", "no-store"); + httpd_resp_set_hdr(req, "Connection", "close"); + return httpd_resp_send(req, "", 0); +} + esp_err_t WebPanelServer::handleLogin(httpd_req_t* req) { auto* ctx = static_cast(req->user_ctx); if (ctx == nullptr || ctx->self == nullptr || ctx->self->_runner == nullptr) { @@ -2984,4 +3021,7 @@ bool WebPanelServer::shouldAutoLock(unsigned long) const { void WebPanelServer::lockSession() { } +void WebPanelServer::notifyOtaStarted() { +} + #endif diff --git a/src/helpers/web/WebPanelServer.h b/src/helpers/web/WebPanelServer.h index 7c76ed08..c34e5bc9 100644 --- a/src/helpers/web/WebPanelServer.h +++ b/src/helpers/web/WebPanelServer.h @@ -46,6 +46,7 @@ public: bool hasSessionToken() const; bool shouldAutoLock(unsigned long now_ms) const; void lockSession(); + void notifyOtaStarted(); private: #if defined(ESP_PLATFORM) && WITH_WEB_PANEL @@ -59,6 +60,7 @@ private: char _token[33]; unsigned long _last_activity_ms; RouteContext _route_context; + bool _ota_started; static esp_err_t handleIndex(httpd_req_t* req); static esp_err_t handleHttpRedirect(httpd_req_t* req); @@ -67,6 +69,7 @@ private: static esp_err_t handleLogin(httpd_req_t* req); static esp_err_t handleCommand(httpd_req_t* req); static esp_err_t handleStats(httpd_req_t* req); + static esp_err_t handleOtaRedirect(httpd_req_t* req); bool readRequestBody(httpd_req_t* req, char* buffer, size_t buffer_size) const; void refreshToken(); diff --git a/src/helpers/web/WebService.cpp b/src/helpers/web/WebService.cpp index 7a664a30..2975fd0c 100644 --- a/src/helpers/web/WebService.cpp +++ b/src/helpers/web/WebService.cpp @@ -30,6 +30,7 @@ void WebService::prepareForOTAStart() { #if defined(ESP_PLATFORM) && WITH_WEB_PANEL _suspended_for_ota = true; _panel.stopRedirectServer(); + _panel.notifyOtaStarted(); #endif }