Make Indicator WiFi display authoritative
This commit is contained in:
1 parent
b562af845a
commit
bf2d4e4b93
5 files changed
+86
-3
No files matched your search
@@ -1,5 +1,6 @@
|
||||
#pragma once
|
||||
|
||||
#include <stddef.h>
|
||||
#include <stdint.h>
|
||||
|
||||
#ifndef UI_WIFI_SETUP_HOME_PAGE
|
||||
@@ -49,6 +50,20 @@ bool isCompanionWiFiEnabled();
|
||||
// live. Unlike localIP(), the driver record is cleared on a real disconnect.
|
||||
bool isCompanionWiFiConnected();
|
||||
|
||||
enum class CompanionWiFiDisplayState : uint8_t {
|
||||
NotRendered,
|
||||
Setup,
|
||||
Off,
|
||||
Ready,
|
||||
Connecting,
|
||||
};
|
||||
|
||||
// Record the branch that was actually drawn. This is exposed through the
|
||||
// read-only `get display.wifi` terminal diagnostic so a headless test host can
|
||||
// distinguish network state from a stale or incorrect LCD frame.
|
||||
void noteCompanionWiFiDisplayState(CompanionWiFiDisplayState state);
|
||||
void formatCompanionWiFiDisplayStatus(char* reply, size_t reply_size);
|
||||
|
||||
// Reload saved credentials after a text-terminal update. The reconnect is
|
||||
// deferred so the command reply can leave USB/TCP before WiFi is restarted.
|
||||
void scheduleCompanionWiFiCredentialReload();
|
||||
|
||||
@@ -2294,6 +2294,11 @@ bool MyMesh::handleLocalControlCommand(const char* command, char* reply,
|
||||
#endif
|
||||
|
||||
#if defined(ESP32) && defined(WIFI_SSID)
|
||||
if (strcmp(command, "get display.wifi") == 0) {
|
||||
formatCompanionWiFiDisplayStatus(reply, reply_size);
|
||||
return true;
|
||||
}
|
||||
|
||||
#if defined(COMPANION_EXCLUSIVE_WIFI_BLE)
|
||||
if (strcmp(command, "get companion.transport") == 0) {
|
||||
snprintf(reply, reply_size, "%s",
|
||||
|
||||
@@ -822,6 +822,9 @@ void halt() {
|
||||
static unsigned long companion_wifi_credential_reload_at = 0;
|
||||
static bool companion_wifi_power_save_loaded = false;
|
||||
static uint8_t companion_wifi_power_save = mesh::wifi::kDefaultPowerSave;
|
||||
static CompanionWiFiDisplayState companion_wifi_display_state =
|
||||
CompanionWiFiDisplayState::NotRendered;
|
||||
static uint32_t companion_wifi_display_frames = 0;
|
||||
|
||||
#if defined(COMPANION_EXCLUSIVE_WIFI_BLE)
|
||||
static CompanionTransportMode companion_transport_boot_mode =
|
||||
@@ -1145,12 +1148,40 @@ void halt() {
|
||||
}
|
||||
|
||||
bool isCompanionWiFiConnected() {
|
||||
if (!companion_wifi_requested || !companion_wifi_active) return false;
|
||||
// The display describes the station link, not the lifecycle of the
|
||||
// Companion TCP services. A valid station association remains the source
|
||||
// of truth even if service bookkeeping is delayed or being recovered.
|
||||
if (!companion_wifi_requested) return false;
|
||||
if (WiFi.status() == WL_CONNECTED) return true;
|
||||
wifi_ap_record_t access_point = {};
|
||||
return esp_wifi_sta_get_ap_info(&access_point) == ESP_OK;
|
||||
}
|
||||
|
||||
void noteCompanionWiFiDisplayState(CompanionWiFiDisplayState state) {
|
||||
companion_wifi_display_state = state;
|
||||
companion_wifi_display_frames++;
|
||||
}
|
||||
|
||||
void formatCompanionWiFiDisplayStatus(char* reply, size_t reply_size) {
|
||||
if (reply == nullptr || reply_size == 0) return;
|
||||
static const char* const names[] = {
|
||||
"not-rendered", "setup", "off", "ready", "connecting",
|
||||
};
|
||||
uint8_t state = static_cast<uint8_t>(companion_wifi_display_state);
|
||||
if (state >= sizeof(names) / sizeof(names[0])) state = 0;
|
||||
wifi_ap_record_t access_point = {};
|
||||
const bool idf_associated =
|
||||
esp_wifi_sta_get_ap_info(&access_point) == ESP_OK;
|
||||
snprintf(reply, reply_size,
|
||||
"> state=%s, frames=%lu, requested=%u, services=%u, "
|
||||
"wl=%d, idf=%u, IP=%s",
|
||||
names[state], (unsigned long)companion_wifi_display_frames,
|
||||
companion_wifi_requested ? 1U : 0U,
|
||||
companion_wifi_active ? 1U : 0U, (int)WiFi.status(),
|
||||
idf_associated ? 1U : 0U,
|
||||
WiFi.localIP().toString().c_str());
|
||||
}
|
||||
|
||||
bool toggleCompanionWiFi() {
|
||||
#if defined(COMPANION_EXCLUSIVE_WIFI_BLE)
|
||||
const CompanionTransportMode current = getCompanionTransportMode();
|
||||
|
||||
@@ -123,6 +123,26 @@ static void drawCompanionWiFiSetupPage(DisplayDriver& display) {
|
||||
char setup_ip[16] = {0};
|
||||
const bool setup_active = WebConfigServer::getSetupInfo(
|
||||
setup_ssid, sizeof(setup_ssid), setup_ip, sizeof(setup_ip));
|
||||
const bool wifi_enabled = isCompanionWiFiEnabled();
|
||||
const bool wifi_connected = isCompanionWiFiConnected();
|
||||
const CompanionWiFiDisplayState state = setup_active
|
||||
? CompanionWiFiDisplayState::Setup
|
||||
: !wifi_enabled
|
||||
? CompanionWiFiDisplayState::Off
|
||||
: wifi_connected
|
||||
? CompanionWiFiDisplayState::Ready
|
||||
: CompanionWiFiDisplayState::Connecting;
|
||||
static CompanionWiFiDisplayState previous_state =
|
||||
CompanionWiFiDisplayState::NotRendered;
|
||||
|
||||
// Frame hashing normally suppresses identical LCD transfers. Explicitly
|
||||
// invalidate that cache on a network-state transition so a retained
|
||||
// CONNECTING frame can never survive a READY render.
|
||||
if (state != previous_state) {
|
||||
display.clear();
|
||||
previous_state = state;
|
||||
}
|
||||
noteCompanionWiFiDisplayState(state);
|
||||
|
||||
// Keep the setup content below the shared title bar and page dots. Compact
|
||||
// text makes its physical size identical on the 480 canvas and the
|
||||
@@ -155,14 +175,14 @@ static void drawCompanionWiFiSetupPage(DisplayDriver& display) {
|
||||
display.drawTextCentered(display.width() / 2, 70, "QR UNAVAILABLE");
|
||||
display.setColor(UIColor::secondary_txt);
|
||||
display.drawTextCentered(display.width() / 2, 100, setup_ip);
|
||||
} else if (!isCompanionWiFiEnabled()) {
|
||||
} else if (!wifi_enabled) {
|
||||
display.setTextSize(3);
|
||||
display.drawTextCentered(display.width() / 2, 45, "WIFI OFF");
|
||||
display.setTextSize(2);
|
||||
display.setColor(UIColor::secondary_txt);
|
||||
display.drawTextCentered(display.width() / 2, 90, "SELECT WIFI");
|
||||
display.drawTextCentered(display.width() / 2, 112, "THEN REBOOT");
|
||||
} else if (isCompanionWiFiConnected()) {
|
||||
} else if (wifi_connected) {
|
||||
display.setTextSize(2);
|
||||
display.drawTextCentered(display.width() / 2, 25, "WIFI READY");
|
||||
const String ssid = WiFi.SSID();
|
||||
|
||||
@@ -178,6 +178,18 @@ int main() {
|
||||
self.assertIn("wifi_setup_active && !_wifi_setup_was_active", ui)
|
||||
self.assertIn("isCompanionWiFiConnected()", page)
|
||||
self.assertIn("wifi_connected != _wifi_was_connected", ui)
|
||||
self.assertIn("CompanionWiFiDisplayState::Ready", page)
|
||||
self.assertIn("display.clear()", page)
|
||||
self.assertIn("noteCompanionWiFiDisplayState(state)", page)
|
||||
|
||||
main = (ROOT / "examples/companion_radio/main.cpp").read_text()
|
||||
helper = main[main.index("bool isCompanionWiFiConnected()"):
|
||||
main.index("bool toggleCompanionWiFi()")]
|
||||
self.assertNotIn("!companion_wifi_active", helper)
|
||||
self.assertIn("esp_wifi_sta_get_ap_info", helper)
|
||||
|
||||
mesh = (ROOT / "examples/companion_radio/MyMesh.cpp").read_text()
|
||||
self.assertIn('strcmp(command, "get display.wifi")', mesh)
|
||||
self.assertIn("_task->gotoHomeScreen();", ui)
|
||||
|
||||
main = MAIN.read_text(encoding="utf-8")
|
||||
|
||||
Reference in new issue
Block a user