fix: suspend web panel for OTA

Этот коммит содержится в:
Jared Dohrman
2026-04-21 18:19:33 +10:00
родитель 0ad50e5bd0
Коммит 2ad3b134f2
8 изменённых файлов: 35 добавлений и 5 удалений
+2 -1
Просмотреть файл
@@ -68,7 +68,7 @@ Legacy dotted aliases are also accepted:
### Web Panel Controls ### Web Panel Controls
- `get web` - `get web`
- `get web.status`: shows whether the local HTTPS panel is available. - `get web.status`: shows whether the local HTTPS panel is available. After `start ota`, this reports `web:suspended ota` until the repeater reboots.
- `get web.stats.status`: shows whether the dedicated stats page and history subsystem are enabled, whether recent history is active, whether PSRAM-backed history is available, and whether the SD-backed archive is mounted. When enabled, the history capture now covers supported environment telemetry too, not just the original battery/radio series. - `get web.stats.status`: shows whether the dedicated stats page and history subsystem are enabled, whether recent history is active, whether PSRAM-backed history is available, and whether the SD-backed archive is mounted. When enabled, the history capture now covers supported environment telemetry too, not just the original battery/radio series.
- `set web on|off` - `set web on|off`
- `set.web on|off`: enables or disables the local HTTPS panel. - `set.web on|off`: enables or disables the local HTTPS panel.
@@ -123,6 +123,7 @@ Notes:
- the panel still uses the repeater admin password for access - the panel still uses the repeater admin password for access
- commands run with the same care as if you typed them into the repeater CLI directly - 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 - this is intended for local admin use on a trusted network
- `start ota` suspends the local repeater web panel until reboot so the OTA HTTP listener can take over port `80`
## Companion WiFi Rescue Commands ## Companion WiFi Rescue Commands
+2 -1
Просмотреть файл
@@ -277,7 +277,8 @@ On mobile:
1. Press `Start OTA`. 1. Press `Start OTA`.
2. Confirm the action. 2. Confirm the action.
3. Continue with your normal OTA workflow. 3. The local repeater web panel is suspended until reboot so OTA can take over HTTP on port `80`.
4. Continue with your normal OTA workflow.
### Use Historical Stats ### Use Historical Stats
+6
Просмотреть файл
@@ -1973,6 +1973,12 @@ void MyMesh::clearStats() {
((SimpleMeshTables *)getTables())->resetStats(); ((SimpleMeshTables *)getTables())->resetStats();
} }
void MyMesh::prepareForOTAStart() {
#if defined(ESP_PLATFORM) && WITH_WEB_PANEL
web.suspendForOTA();
#endif
}
void MyMesh::handleCommand(uint32_t sender_timestamp, char *command, char *reply) { void MyMesh::handleCommand(uint32_t sender_timestamp, char *command, char *reply) {
if (region_load_active) { if (region_load_active) {
if (StrHelper::isBlank(command)) { // empty/blank line, signal to terminate 'load' operation if (StrHelper::isBlank(command)) { // empty/blank line, signal to terminate 'load' operation
+1
Просмотреть файл
@@ -255,6 +255,7 @@ public:
void formatRadioStatsReply(char *reply, size_t reply_size) override; void formatRadioStatsReply(char *reply, size_t reply_size) override;
void formatPacketStatsReply(char *reply, size_t reply_size) override; void formatPacketStatsReply(char *reply, size_t reply_size) override;
void formatMemoryReply(char *reply, size_t reply_size) override; void formatMemoryReply(char *reply, size_t reply_size) override;
void prepareForOTAStart() override;
void startRegionsLoad() override; void startRegionsLoad() override;
bool saveRegions() override; bool saveRegions() override;
void onDefaultRegionChanged(const RegionEntry* r) override; void onDefaultRegionChanged(const RegionEntry* r) override;
+1
Просмотреть файл
@@ -252,6 +252,7 @@ void CommonCLI::handleCommand(uint32_t sender_timestamp, char* command, char* re
strcpy(reply, "ERR: clock cannot go backwards"); strcpy(reply, "ERR: clock cannot go backwards");
} }
} else if (memcmp(command, "start ota", 9) == 0) { } else if (memcmp(command, "start ota", 9) == 0) {
_callbacks->prepareForOTAStart();
if (!_board->startOTAUpdate(_prefs->node_name, reply)) { if (!_board->startOTAUpdate(_prefs->node_name, reply)) {
strcpy(reply, "Error"); strcpy(reply, "Error");
} }
+3
Просмотреть файл
@@ -92,6 +92,9 @@ public:
virtual void saveIdentity(const mesh::LocalIdentity& new_id) = 0; virtual void saveIdentity(const mesh::LocalIdentity& new_id) = 0;
virtual void clearStats() = 0; virtual void clearStats() = 0;
virtual void applyTempRadioParams(float freq, float bw, uint8_t sf, uint8_t cr, int timeout_mins) = 0; virtual void applyTempRadioParams(float freq, float bw, uint8_t sf, uint8_t cr, int timeout_mins) = 0;
virtual void prepareForOTAStart() {
// no op by default
}
virtual void startRegionsLoad() { virtual void startRegionsLoad() {
// no op by default // no op by default
+18 -3
Просмотреть файл
@@ -4,7 +4,7 @@
#include <WiFi.h> #include <WiFi.h>
#endif #endif
WebService::WebService() : _fs(nullptr), _prefs{}, _runner(nullptr), _network(nullptr) { WebService::WebService() : _fs(nullptr), _prefs{}, _runner(nullptr), _network(nullptr), _suspended_for_ota(false) {
WebPrefsStore::setDefaults(_prefs); WebPrefsStore::setDefaults(_prefs);
} }
@@ -19,6 +19,13 @@ void WebService::end() {
#endif #endif
} }
void WebService::suspendForOTA() {
#if defined(ESP_PLATFORM) && WITH_WEB_PANEL
_suspended_for_ota = true;
_panel.stop();
#endif
}
void WebService::loop() { void WebService::loop() {
#if defined(ESP_PLATFORM) && WITH_WEB_PANEL #if defined(ESP_PLATFORM) && WITH_WEB_PANEL
ensureWebServer(); ensureWebServer();
@@ -39,9 +46,12 @@ bool WebService::savePrefs() {
bool WebService::setWebEnabled(bool enabled) { bool WebService::setWebEnabled(bool enabled) {
_prefs.web_enabled = enabled ? 1 : 0; _prefs.web_enabled = enabled ? 1 : 0;
if (!enabled) {
_suspended_for_ota = false;
}
bool ok = savePrefs(); bool ok = savePrefs();
#if defined(ESP_PLATFORM) && WITH_WEB_PANEL #if defined(ESP_PLATFORM) && WITH_WEB_PANEL
if (_prefs.web_enabled != 0) { if (_prefs.web_enabled != 0 && !_suspended_for_ota) {
ensureWebServer(); ensureWebServer();
} else { } else {
_panel.stop(); _panel.stop();
@@ -62,6 +72,11 @@ void WebService::formatWebStatusReply(char* reply, size_t reply_size) const {
return; return;
} }
if (_suspended_for_ota) {
snprintf(reply, reply_size, "> web:suspended ota");
return;
}
if (!_panel.isRunning() || _network == nullptr || !_network->isWifiConnected()) { if (!_panel.isRunning() || _network == nullptr || !_network->isWifiConnected()) {
snprintf(reply, reply_size, "> web:down"); snprintf(reply, reply_size, "> web:down");
return; return;
@@ -76,7 +91,7 @@ void WebService::formatWebStatusReply(char* reply, size_t reply_size) const {
#if defined(ESP_PLATFORM) && WITH_WEB_PANEL #if defined(ESP_PLATFORM) && WITH_WEB_PANEL
void WebService::ensureWebServer() { void WebService::ensureWebServer() {
if (_runner == nullptr || _prefs.web_enabled == 0 || _network == nullptr || !_network->isWifiConnected()) { if (_suspended_for_ota || _runner == nullptr || _prefs.web_enabled == 0 || _network == nullptr || !_network->isWifiConnected()) {
_panel.stop(); _panel.stop();
return; return;
} }
+2
Просмотреть файл
@@ -14,6 +14,7 @@ public:
void begin(FILESYSTEM* fs); void begin(FILESYSTEM* fs);
void end(); void end();
void loop(); void loop();
void suspendForOTA();
void setCommandRunner(WebPanelCommandRunner* runner); void setCommandRunner(WebPanelCommandRunner* runner);
void setNetworkStateProvider(NetworkStateProvider* network) { _network = network; } void setNetworkStateProvider(NetworkStateProvider* network) { _network = network; }
@@ -38,4 +39,5 @@ private:
WebPanelCommandRunner* _runner; WebPanelCommandRunner* _runner;
NetworkStateProvider* _network; NetworkStateProvider* _network;
WebPanelServer _panel; WebPanelServer _panel;
bool _suspended_for_ota;
}; };