소스 검색

fix: restore /stats Wi-Fi signal quality and refresh web panel screenshots

Jared Dohrman 3 달 전
부모
커밋
785f5c2fd3

BIN
docs/_assets/repeater_web_panel_app.png


BIN
docs/_assets/repeater_web_panel_overview.png


BIN
docs/_assets/repeater_web_panel_stats.png


+ 42 - 42
docs/boards.md

@@ -86,48 +86,48 @@ If you are deciding between otherwise similar boards, these target-level setting
 
 This table includes all repeater MQTT targets currently defined in `variants/eastmesh_mqtt/platformio.ini`.
 
-| Target                   | MCU     | RAM    | PSRAM | Flash | LoRa   | Display         | GPS | SD |
-| ------------------------ | ------- | ------ | ----- | ----- | ------ | --------------- | --- | -- |
-| Ebyte_EoRa-S3            | ESP32S3 | 512 KB | 2 MB  | 4 MB  | SX1262 | OLED (SSD1306)  |     |    |
-| Generic_E22_sx1262       | ESP32   | 520 KB | No    | 4 MB  | SX1262 | None            |     |    |
-| Generic_E22_sx1268       | ESP32   | 520 KB | No    | 4 MB  | SX1268 | None            |     |    |
-| Heltec_ct62              | ESP32C3 | 400 KB | No    | 4 MB  | SX1262 | None            |     |    |
-| Heltec_E213              | ESP32S3 | 512 KB | 8 MB  | 16 MB | SX1262 | E-paper (2.13") |     |    |
-| Heltec_E290              | ESP32S3 | 512 KB | 8 MB  | 16 MB | SX1262 | E-paper (2.9")  |     |    |
-| Heltec_T190              | ESP32S3 | 512 KB | 8 MB  | 16 MB | SX1262 | TFT (ST7789)    |     |    |
-| heltec_tracker_v2        | ESP32S3 | 512 KB | No    | 8 MB  | SX1262 | TFT (ST7735)    | ✅  |    |
-| Heltec_v2                | ESP32   | 520 KB | No    | 8 MB  | SX1276 | OLED (SSD1306)  |     |    |
-| Heltec_v3                | ESP32S3 | 512 KB | No    | 8 MB  | SX1262 | OLED (SSD1306)  | ✅  |    |
-| heltec_v4                | ESP32S3 | 512 KB | 2 MB  | 16 MB | SX1262 | OLED (SSD1306)  | ✅  |    |
-| heltec_v4_tft            | ESP32S3 | 512 KB | 2 MB  | 16 MB | SX1262 | TFT (ST7789)    | ✅  |    |
-| Heltec_Wireless_Paper    | ESP32S3 | 512 KB | No    | 8 MB  | SX1262 | E-paper (2.13") |     |    |
-| Heltec_Wireless_Tracker  | ESP32S3 | 512 KB | No    | 8 MB  | SX1262 | TFT (ST7735)    | ✅  |    |
-| Heltec_WSL3              | ESP32S3 | 512 KB | No    | 8 MB  | SX1262 | None            | ✅  |    |
-| LilyGo_T3S3_sx1262       | ESP32S3 | 512 KB | 2 MB  | 4 MB  | SX1262 | OLED (SSD1306)  |     | 🧪 |
-| LilyGo_T3S3_sx1276       | ESP32S3 | 512 KB | 2 MB  | 4 MB  | SX1276 | OLED (SSD1306)  |     | 🧪 |
-| LilyGo_TBeam_1W          | ESP32S3 | 512 KB | 8 MB  | 16 MB | SX1262 | OLED (SH1106)   | ✅  | ✅ |
-| LilyGo_TDeck             | ESP32S3 | 512 KB | No    | 16 MB | SX1262 | TFT (ST7789)    | ✅  | 🧪 |
-| LilyGo_Tlora_C6          | ESP32C6 | 512 KB | No    | 4 MB  | SX1262 | None            |     |    |
-| LilyGo_TLora_V2_1_1_6    | ESP32   | 520 KB | No    | 4 MB  | SX1276 | OLED (SSD1306)  | ✅  |    |
-| M5Stack_Unit_C6L         | ESP32C6 | 512 KB | No    | 4 MB  | SX1262 | None            | ✅  |    |
-| Meshadventurer_sx1262    | ESP32   | 520 KB | No    | 4 MB  | SX1262 | OLED (SSD1306)  | ✅  |    |
-| Meshadventurer_sx1268    | ESP32   | 520 KB | No    | 4 MB  | SX1268 | OLED (SSD1306)  | ✅  |    |
-| Meshimi                  | ESP32C6 | 512 KB | No    | 4 MB  | SX1262 | None            |     |    |
-| nibble_screen_connect    | ESP32S3 | 512 KB | No    | 4 MB  | SX1262 | OLED (SSD1306)  |     |    |
-| RAK_3112                 | ESP32S3 | 512 KB | No    | 8 MB  | SX1262 | None            | ✅  |    |
-| Station_G2               | ESP32S3 | 512 KB | 8 MB  | 16 MB | SX1262 | OLED (SH1106)   | ✅  |    |
-| Station_G2_logging       | ESP32S3 | 512 KB | 8 MB  | 16 MB | SX1262 | OLED (SH1106)   | ✅  |    |
-| T_Beam_S3_Supreme_SX1262 | ESP32S3 | 512 KB | 8 MB  | 8 MB  | SX1262 | OLED (SH1106)   | ✅  | ✅ |
-| Tbeam_SX1262             | ESP32   | 520 KB | No    | 4 MB  | SX1262 | OLED (SSD1306)  | ✅  |    |
-| Tbeam_SX1276             | ESP32   | 520 KB | No    | 4 MB  | SX1276 | OLED (SSD1306)  | ✅  |    |
-| Tenstar_C3_sx1262        | ESP32C3 | 400 KB | No    | 4 MB  | SX1262 | None            |     |    |
-| Tenstar_C3_sx1268        | ESP32C3 | 400 KB | No    | 4 MB  | SX1268 | None            |     |    |
-| ThinkNode_M2             | ESP32S3 | 512 KB | No    | 4 MB  | SX1262 | OLED (SH1106)   |     |    |
-| ThinkNode_M5             | ESP32S3 | 512 KB | No    | 4 MB  | SX1262 | E-paper (GxEPD) | ✅  |    |
-| WHY2025_badge            | ESP32C6 | 512 KB | No    | 4 MB  | SX1262 | None            |     |    |
-| Xiao_C3                  | ESP32C3 | 400 KB | No    | 4 MB  | SX1262 | None            | ✅  |    |
-| Xiao_C6                  | ESP32C6 | 512 KB | No    | 4 MB  | SX1262 | None            |     |    |
-| Xiao_S3_WIO              | ESP32S3 | 512 KB | No    | 8 MB  | SX1262 | None            | ✅  |    |
+| Target                   | MCU     | RAM    | PSRAM | Flash | LoRa   | Display         | GPS | SD  |
+| ------------------------ | ------- | ------ | ----- | ----- | ------ | --------------- | --- | --- |
+| Ebyte_EoRa-S3            | ESP32S3 | 512 KB | 2 MB  | 4 MB  | SX1262 | OLED (SSD1306)  |     |     |
+| Generic_E22_sx1262       | ESP32   | 520 KB | No    | 4 MB  | SX1262 | None            |     |     |
+| Generic_E22_sx1268       | ESP32   | 520 KB | No    | 4 MB  | SX1268 | None            |     |     |
+| Heltec_ct62              | ESP32C3 | 400 KB | No    | 4 MB  | SX1262 | None            |     |     |
+| Heltec_E213              | ESP32S3 | 512 KB | 8 MB  | 16 MB | SX1262 | E-paper (2.13") |     |     |
+| Heltec_E290              | ESP32S3 | 512 KB | 8 MB  | 16 MB | SX1262 | E-paper (2.9")  |     |     |
+| Heltec_T190              | ESP32S3 | 512 KB | 8 MB  | 16 MB | SX1262 | TFT (ST7789)    |     |     |
+| heltec_tracker_v2        | ESP32S3 | 512 KB | No    | 8 MB  | SX1262 | TFT (ST7735)    | ✅  |     |
+| Heltec_v2                | ESP32   | 520 KB | No    | 8 MB  | SX1276 | OLED (SSD1306)  |     |     |
+| Heltec_v3                | ESP32S3 | 512 KB | No    | 8 MB  | SX1262 | OLED (SSD1306)  | ✅  |     |
+| heltec_v4                | ESP32S3 | 512 KB | 2 MB  | 16 MB | SX1262 | OLED (SSD1306)  | ✅  |     |
+| heltec_v4_tft            | ESP32S3 | 512 KB | 2 MB  | 16 MB | SX1262 | TFT (ST7789)    | ✅  |     |
+| Heltec_Wireless_Paper    | ESP32S3 | 512 KB | No    | 8 MB  | SX1262 | E-paper (2.13") |     |     |
+| Heltec_Wireless_Tracker  | ESP32S3 | 512 KB | No    | 8 MB  | SX1262 | TFT (ST7735)    | ✅  |     |
+| Heltec_WSL3              | ESP32S3 | 512 KB | No    | 8 MB  | SX1262 | None            | ✅  |     |
+| LilyGo_T3S3_sx1262       | ESP32S3 | 512 KB | 2 MB  | 4 MB  | SX1262 | OLED (SSD1306)  |     | 🧪  |
+| LilyGo_T3S3_sx1276       | ESP32S3 | 512 KB | 2 MB  | 4 MB  | SX1276 | OLED (SSD1306)  |     | 🧪  |
+| LilyGo_TBeam_1W          | ESP32S3 | 512 KB | 8 MB  | 16 MB | SX1262 | OLED (SH1106)   | ✅  | ✅  |
+| LilyGo_TDeck             | ESP32S3 | 512 KB | No    | 16 MB | SX1262 | TFT (ST7789)    | ✅  | 🧪  |
+| LilyGo_Tlora_C6          | ESP32C6 | 512 KB | No    | 4 MB  | SX1262 | None            |     |     |
+| LilyGo_TLora_V2_1_1_6    | ESP32   | 520 KB | No    | 4 MB  | SX1276 | OLED (SSD1306)  | ✅  |     |
+| M5Stack_Unit_C6L         | ESP32C6 | 512 KB | No    | 4 MB  | SX1262 | None            | ✅  |     |
+| Meshadventurer_sx1262    | ESP32   | 520 KB | No    | 4 MB  | SX1262 | OLED (SSD1306)  | ✅  |     |
+| Meshadventurer_sx1268    | ESP32   | 520 KB | No    | 4 MB  | SX1268 | OLED (SSD1306)  | ✅  |     |
+| Meshimi                  | ESP32C6 | 512 KB | No    | 4 MB  | SX1262 | None            |     |     |
+| nibble_screen_connect    | ESP32S3 | 512 KB | No    | 4 MB  | SX1262 | OLED (SSD1306)  |     |     |
+| RAK_3112                 | ESP32S3 | 512 KB | No    | 8 MB  | SX1262 | None            | ✅  |     |
+| Station_G2               | ESP32S3 | 512 KB | 8 MB  | 16 MB | SX1262 | OLED (SH1106)   | ✅  |     |
+| Station_G2_logging       | ESP32S3 | 512 KB | 8 MB  | 16 MB | SX1262 | OLED (SH1106)   | ✅  |     |
+| T_Beam_S3_Supreme_SX1262 | ESP32S3 | 512 KB | 8 MB  | 8 MB  | SX1262 | OLED (SH1106)   | ✅  | ✅  |
+| Tbeam_SX1262             | ESP32   | 520 KB | No    | 4 MB  | SX1262 | OLED (SSD1306)  | ✅  |     |
+| Tbeam_SX1276             | ESP32   | 520 KB | No    | 4 MB  | SX1276 | OLED (SSD1306)  | ✅  |     |
+| Tenstar_C3_sx1262        | ESP32C3 | 400 KB | No    | 4 MB  | SX1262 | None            |     |     |
+| Tenstar_C3_sx1268        | ESP32C3 | 400 KB | No    | 4 MB  | SX1268 | None            |     |     |
+| ThinkNode_M2             | ESP32S3 | 512 KB | No    | 4 MB  | SX1262 | OLED (SH1106)   |     |     |
+| ThinkNode_M5             | ESP32S3 | 512 KB | No    | 4 MB  | SX1262 | E-paper (GxEPD) | ✅  |     |
+| WHY2025_badge            | ESP32C6 | 512 KB | No    | 4 MB  | SX1262 | None            |     |     |
+| Xiao_C3                  | ESP32C3 | 400 KB | No    | 4 MB  | SX1262 | None            | ✅  |     |
+| Xiao_C6                  | ESP32C6 | 512 KB | No    | 4 MB  | SX1262 | None            |     |     |
+| Xiao_S3_WIO              | ESP32S3 | 512 KB | No    | 8 MB  | SX1262 | None            | ✅  |     |
 
 Note: all current `repeater_mqtt` boards support the local web panel except `Xiao_C3`, where it is disabled to preserve limited board resources.
 

+ 8 - 2
docs/web-panel.md

@@ -26,9 +26,15 @@ Operational guidance:
 
 ## Screenshot Overview
 
-The layout below reflects the current panel structure for the repeater web UI.
+The screenshots below show the current split between the lighter `/app` admin page and the dedicated `/stats` status page.
 
-![Repeater web panel overview](./_assets/repeater_web_panel_overview.png)
+### `/app`
+
+![Repeater web panel `/app` overview](./_assets/repeater_web_panel_app.png)
+
+### `/stats`
+
+![Repeater web panel `/stats` overview](./_assets/repeater_web_panel_stats.png)
 
 ## Requirements
 

+ 66 - 1
examples/simple_repeater/MyMesh.cpp

@@ -2132,35 +2132,96 @@ bool MyMesh::formatWebStatsSummaryJson(char* reply, size_t reply_size) {
 #else
   char wifi_ssid[48];
   char wifi_status[20];
+  char wifi_state[24];
   char wifi_ip[20];
+  char wifi_signal[16];
   char wifi_powersave[12];
   escapeJsonString(network.getWifiSSID()[0] ? network.getWifiSSID() : "-", wifi_ssid, sizeof(wifi_ssid));
   escapeJsonString(network.getWifiPowerSave(), wifi_powersave, sizeof(wifi_powersave));
   int wifi_rssi = 0;
+  int wifi_quality = 0;
+  int wifi_code = 0;
 
 #if defined(ESP32)
   if (network.getWifiSSID()[0] == 0) {
     strncpy(wifi_status, "unconfigured", sizeof(wifi_status) - 1);
     wifi_status[sizeof(wifi_status) - 1] = 0;
+    strncpy(wifi_state, "unconfigured", sizeof(wifi_state) - 1);
+    wifi_state[sizeof(wifi_state) - 1] = 0;
     strncpy(wifi_ip, "--", sizeof(wifi_ip) - 1);
     wifi_ip[sizeof(wifi_ip) - 1] = 0;
+    strncpy(wifi_signal, "--", sizeof(wifi_signal) - 1);
+    wifi_signal[sizeof(wifi_signal) - 1] = 0;
   } else if (network.isWifiConnected()) {
     strncpy(wifi_status, "connected", sizeof(wifi_status) - 1);
     wifi_status[sizeof(wifi_status) - 1] = 0;
+    strncpy(wifi_state, "connected", sizeof(wifi_state) - 1);
+    wifi_state[sizeof(wifi_state) - 1] = 0;
     String ip = WiFi.localIP().toString();
     escapeJsonString(ip.c_str(), wifi_ip, sizeof(wifi_ip));
     wifi_rssi = WiFi.RSSI();
+    wifi_code = static_cast<int>(WiFi.status());
+    if (wifi_rssi <= -100) {
+      wifi_quality = 0;
+      strncpy(wifi_signal, "poor", sizeof(wifi_signal) - 1);
+    } else if (wifi_rssi >= -50) {
+      wifi_quality = 100;
+      strncpy(wifi_signal, "excellent", sizeof(wifi_signal) - 1);
+    } else {
+      wifi_quality = 2 * (wifi_rssi + 100);
+      if (wifi_rssi >= -60) {
+        strncpy(wifi_signal, "excellent", sizeof(wifi_signal) - 1);
+      } else if (wifi_rssi >= -67) {
+        strncpy(wifi_signal, "good", sizeof(wifi_signal) - 1);
+      } else if (wifi_rssi >= -75) {
+        strncpy(wifi_signal, "fair", sizeof(wifi_signal) - 1);
+      } else {
+        strncpy(wifi_signal, "poor", sizeof(wifi_signal) - 1);
+      }
+    }
+    wifi_signal[sizeof(wifi_signal) - 1] = 0;
   } else {
     strncpy(wifi_status, "connecting", sizeof(wifi_status) - 1);
     wifi_status[sizeof(wifi_status) - 1] = 0;
+    wifi_code = static_cast<int>(WiFi.status());
+    switch (WiFi.status()) {
+      case WL_IDLE_STATUS:
+        strncpy(wifi_state, "idle", sizeof(wifi_state) - 1);
+        break;
+      case WL_NO_SSID_AVAIL:
+        strncpy(wifi_state, "no_ssid", sizeof(wifi_state) - 1);
+        break;
+      case WL_SCAN_COMPLETED:
+        strncpy(wifi_state, "scan_completed", sizeof(wifi_state) - 1);
+        break;
+      case WL_CONNECT_FAILED:
+        strncpy(wifi_state, "connect_failed", sizeof(wifi_state) - 1);
+        break;
+      case WL_CONNECTION_LOST:
+        strncpy(wifi_state, "connection_lost", sizeof(wifi_state) - 1);
+        break;
+      case WL_DISCONNECTED:
+        strncpy(wifi_state, "disconnected", sizeof(wifi_state) - 1);
+        break;
+      default:
+        strncpy(wifi_state, "unknown", sizeof(wifi_state) - 1);
+        break;
+    }
+    wifi_state[sizeof(wifi_state) - 1] = 0;
     strncpy(wifi_ip, "--", sizeof(wifi_ip) - 1);
     wifi_ip[sizeof(wifi_ip) - 1] = 0;
+    strncpy(wifi_signal, "--", sizeof(wifi_signal) - 1);
+    wifi_signal[sizeof(wifi_signal) - 1] = 0;
   }
 #else
   strncpy(wifi_status, "unsupported", sizeof(wifi_status) - 1);
   wifi_status[sizeof(wifi_status) - 1] = 0;
+  strncpy(wifi_state, "unsupported", sizeof(wifi_state) - 1);
+  wifi_state[sizeof(wifi_state) - 1] = 0;
   strncpy(wifi_ip, "--", sizeof(wifi_ip) - 1);
   wifi_ip[sizeof(wifi_ip) - 1] = 0;
+  strncpy(wifi_signal, "--", sizeof(wifi_signal) - 1);
+  wifi_signal[sizeof(wifi_signal) - 1] = 0;
 #endif
 
   const int battery_pct = board.getBatteryPercent();
@@ -2189,7 +2250,7 @@ bool MyMesh::formatWebStatsSummaryJson(char* reply, size_t reply_size) {
                      "\"packets\":{\"recv\":%u,\"sent\":%u,\"flood_tx\":%u,\"direct_tx\":%u,\"flood_rx\":%u,\"direct_rx\":%u,"
                      "\"recv_errors\":%u,\"direct_dups\":%u,\"flood_dups\":%u,\"neighbors\":%u},"
                      "\"memory\":{\"heap_free\":%u,\"heap_min\":%u,\"heap_max\":%u,\"psram_free\":%u,\"psram_min\":%u,\"psram_max\":%u},"
-                     "\"wifi\":{\"ssid\":\"%s\",\"status\":\"%s\",\"connected\":%s,\"ip\":\"%s\",\"rssi\":%d,\"powersave\":\"%s\"},"
+                     "\"wifi\":{\"ssid\":\"%s\",\"status\":\"%s\",\"connected\":%s,\"state\":\"%s\",\"code\":%d,\"ip\":\"%s\",\"rssi\":%d,\"quality\":%d,\"signal\":\"%s\",\"powersave\":\"%s\"},"
                      "\"services\":{\"mqtt_connected\":%s,\"web_enabled\":%s,\"web_panel_up\":%s,\"web_auth\":\"%s\","
                      "\"archive_available\":%s}",
                      (_stats_history.isEnabled() && _stats_history.isRecentHistoryAvailable()) ? "true" : "false",
@@ -2241,8 +2302,12 @@ bool MyMesh::formatWebStatsSummaryJson(char* reply, size_t reply_size) {
                      wifi_ssid,
                      wifi_status,
                      network.isWifiConnected() ? "true" : "false",
+                     wifi_state,
+                     wifi_code,
                      wifi_ip,
                      wifi_rssi,
+                     wifi_quality,
+                     wifi_signal,
                      wifi_powersave,
                      mqtt_connected ? "true" : "false",
                      web.isWebEnabled() ? "true" : "false",