Переглянути джерело

fix: suspend web panel for OTA

Jared Dohrman 3 місяців тому
батько
коміт
2ad3b134f2

+ 2 - 1
docs/custom-cli.md

@@ -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
docs/web-panel.md

@@ -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 - 0
examples/simple_repeater/MyMesh.cpp

@@ -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 - 0
examples/simple_repeater/MyMesh.h

@@ -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 - 0
src/helpers/CommonCLI.cpp

@@ -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 - 0
src/helpers/CommonCLI.h

@@ -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
src/helpers/web/WebService.cpp

@@ -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 - 0
src/helpers/web/WebService.h

@@ -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;
 };