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
- `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.
- `set web on|off`
- `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
- 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` suspends the local repeater web panel until reboot so the OTA HTTP listener can take over port `80`
## Companion WiFi Rescue Commands
+2 -1
Просмотреть файл
@@ -277,7 +277,8 @@ On mobile:
1. Press `Start OTA`.
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
+6
Просмотреть файл
@@ -1973,6 +1973,12 @@ void MyMesh::clearStats() {
((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) {
if (region_load_active) {
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 formatPacketStatsReply(char *reply, size_t reply_size) override;
void formatMemoryReply(char *reply, size_t reply_size) override;
void prepareForOTAStart() override;
void startRegionsLoad() override;
bool saveRegions() 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");
}
} else if (memcmp(command, "start ota", 9) == 0) {
_callbacks->prepareForOTAStart();
if (!_board->startOTAUpdate(_prefs->node_name, reply)) {
strcpy(reply, "Error");
}
+3
Просмотреть файл
@@ -92,6 +92,9 @@ public:
virtual void saveIdentity(const mesh::LocalIdentity& new_id) = 0;
virtual void clearStats() = 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() {
// no op by default
+18 -3
Просмотреть файл
@@ -4,7 +4,7 @@
#include <WiFi.h>
#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);
}
@@ -19,6 +19,13 @@ void WebService::end() {
#endif
}
void WebService::suspendForOTA() {
#if defined(ESP_PLATFORM) && WITH_WEB_PANEL
_suspended_for_ota = true;
_panel.stop();
#endif
}
void WebService::loop() {
#if defined(ESP_PLATFORM) && WITH_WEB_PANEL
ensureWebServer();
@@ -39,9 +46,12 @@ bool WebService::savePrefs() {
bool WebService::setWebEnabled(bool enabled) {
_prefs.web_enabled = enabled ? 1 : 0;
if (!enabled) {
_suspended_for_ota = false;
}
bool ok = savePrefs();
#if defined(ESP_PLATFORM) && WITH_WEB_PANEL
if (_prefs.web_enabled != 0) {
if (_prefs.web_enabled != 0 && !_suspended_for_ota) {
ensureWebServer();
} else {
_panel.stop();
@@ -62,6 +72,11 @@ void WebService::formatWebStatusReply(char* reply, size_t reply_size) const {
return;
}
if (_suspended_for_ota) {
snprintf(reply, reply_size, "> web:suspended ota");
return;
}
if (!_panel.isRunning() || _network == nullptr || !_network->isWifiConnected()) {
snprintf(reply, reply_size, "> web:down");
return;
@@ -76,7 +91,7 @@ void WebService::formatWebStatusReply(char* reply, size_t reply_size) const {
#if defined(ESP_PLATFORM) && WITH_WEB_PANEL
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();
return;
}
+2
Просмотреть файл
@@ -14,6 +14,7 @@ public:
void begin(FILESYSTEM* fs);
void end();
void loop();
void suspendForOTA();
void setCommandRunner(WebPanelCommandRunner* runner);
void setNetworkStateProvider(NetworkStateProvider* network) { _network = network; }
@@ -38,4 +39,5 @@ private:
WebPanelCommandRunner* _runner;
NetworkStateProvider* _network;
WebPanelServer _panel;
bool _suspended_for_ota;
};