fix: suspend web panel for OTA

Cette révision appartient à :
Jared Dohrman
2026-04-21 18:19:33 +10:00
Parent 0ad50e5bd0
révision 2ad3b134f2
8 fichiers modifiés avec 35 ajouts et 5 suppressions
+2 -1
Voir le fichier
@@ -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
Voir le fichier
@@ -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
Voir le fichier
@@ -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
Voir le fichier
@@ -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
Voir le fichier
@@ -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
Voir le fichier
@@ -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
Voir le fichier
@@ -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
Voir le fichier
@@ -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;
}; };