fix: defer ESP32 OTA server startup from web command

This commit is contained in:
Jared Dohrman committed 2026-05-24 17:55:43 +10:00
1 parent 01fd229b21
commit 1fb68263cd
4 files changed
+52 -22

No files matched your search

+1
View File
@@ -182,6 +182,7 @@ Notes:
- commands run with the same care as if you typed them into the repeater CLI directly
- this is intended for local admin use on a trusted network
- `start ota` releases the local HTTP redirect listener on port `80` so the OTA HTTP listener can take over without stopping the rest of the repeater services, regardless of whether the command is run from the web panel, serial CLI, or a remote companion/app CLI session
- `start ota` uses the repeater's existing Wi-Fi address when already connected, or starts the `MeshCore-OTA` access point when Wi-Fi is not connected
- the `/app` Regions shortcut runs the existing MeshCore region commands in sequence: `region put au`, `region put au-STATE`, `region allowf au`, `region allowf au-STATE`, then `region save`
## Companion Wi-Fi Rescue Commands
+5 -2
View File
@@ -340,8 +340,11 @@ On mobile:
1. Press `Start OTA`.
2. Confirm the action.
3. The local HTTP redirect listener on port `80` is released so OTA can take over that port.
4. Continue with your normal OTA workflow.
3. The panel starts OTA, then opens the returned `http://.../update` URL.
4. The local HTTP redirect listener on port `80` is released so OTA can take over that port.
5. Continue with your normal OTA workflow.
If the repeater is already connected to Wi-Fi, OTA uses the existing LAN address. If Wi-Fi is not connected, the repeater starts the `MeshCore-OTA` access point and returns that OTA address instead.
If an older build sends you through a strange redirect after `start ota`, use the web `Start OTA` button to begin the upgrade. This redirect issue is fixed in `observer-eastmesh-v1.3.11`.
+42 -20
View File
@@ -10,6 +10,40 @@
#include <SPIFFS.h>
namespace {
AsyncWebServer* ota_server = nullptr;
char ota_id_buf[60];
char ota_home_buf[90];
volatile bool ota_start_pending = false;
void startOTAServerNow() {
if (ota_server != nullptr) {
delete ota_server;
ota_server = nullptr;
}
ota_server = new AsyncWebServer(80);
ota_server->on("/", HTTP_GET, [](AsyncWebServerRequest *request) {
request->send(200, "text/html", ota_home_buf);
});
ota_server->on("/log", HTTP_GET, [](AsyncWebServerRequest *request) {
request->send(SPIFFS, "/packet_log", "text/plain");
});
AsyncElegantOTA.setID(ota_id_buf);
AsyncElegantOTA.begin(ota_server); // Start ElegantOTA
ota_server->begin();
}
void startOTAServerTask(void*) {
vTaskDelay(pdMS_TO_TICKS(750));
startOTAServerNow();
ota_start_pending = false;
vTaskDelete(nullptr);
}
}
bool ESP32Board::startOTAUpdate(const char* id, char reply[]) {
inhibit_sleep = true; // prevent sleep during OTA
@@ -28,28 +62,16 @@ bool ESP32Board::startOTAUpdate(const char* id, char reply[]) {
sprintf(reply, "Started: http://%s/update", ota_ip.toString().c_str());
MESH_DEBUG_PRINTLN("startOTAUpdate: %s", reply);
static char id_buf[60];
snprintf(id_buf, sizeof(id_buf), "%s (%s)", id, getManufacturerName());
static char home_buf[90];
snprintf(home_buf, sizeof(home_buf), "<H2>Hi! I am a MeshCore Repeater. ID: %s</H2>", id);
snprintf(ota_id_buf, sizeof(ota_id_buf), "%s (%s)", id, getManufacturerName());
snprintf(ota_home_buf, sizeof(ota_home_buf), "<H2>Hi! I am a MeshCore Repeater. ID: %s</H2>", id);
static AsyncWebServer* server = nullptr;
if (server != nullptr) {
delete server;
server = nullptr;
if (!ota_start_pending) {
ota_start_pending = true;
if (xTaskCreate(startOTAServerTask, "ota-start", 4096, nullptr, 1, nullptr) != pdPASS) {
startOTAServerNow();
ota_start_pending = false;
}
}
server = new AsyncWebServer(80);
server->on("/", HTTP_GET, [](AsyncWebServerRequest *request) {
request->send(200, "text/html", home_buf);
});
server->on("/log", HTTP_GET, [](AsyncWebServerRequest *request) {
request->send(SPIFFS, "/packet_log", "text/plain");
});
AsyncElegantOTA.setID(id_buf);
AsyncElegantOTA.begin(server); // Start ElegantOTA
server->begin();
return true;
}
+4
View File
@@ -2678,10 +2678,14 @@ const char kWebPanelAppHtml[] PROGMEM = R"HTML(
};
document.getElementById("otaBtn").onclick = async () => {
if (confirm("Start OTA mode now?")) {
const otaBtn = document.getElementById("otaBtn");
otaBtn.disabled = true;
const result = await runCommand("start ota");
const match = result.text && result.text.match(/https?:\/\/\S+/);
if (result.ok && match) {
window.location.href = match[0];
} else {
otaBtn.disabled = false;
}
}
};