From 1bc30fbf2a7cc73868c7a41697b5011fff682e1d Mon Sep 17 00:00:00 2001 From: Brendan O'Leary Date: Mon, 15 Dec 2025 22:13:17 -0500 Subject: [PATCH] Fix issue with failed connections --- src/WifiCredentialStore.cpp | 4 ++ src/screens/OnScreenKeyboard.cpp | 2 +- src/screens/WifiScreen.cpp | 111 ++++++++++++++++++++++++++++--- src/screens/WifiScreen.h | 7 +- 4 files changed, 112 insertions(+), 12 deletions(-) diff --git a/src/WifiCredentialStore.cpp b/src/WifiCredentialStore.cpp index b0b26c2..f15fefe 100644 --- a/src/WifiCredentialStore.cpp +++ b/src/WifiCredentialStore.cpp @@ -22,6 +22,7 @@ constexpr uint8_t OBFUSCATION_KEY[] = {0x43, 0x72, 0x6F, 0x73, 0x73, constexpr size_t KEY_LENGTH = sizeof(OBFUSCATION_KEY); void WifiCredentialStore::obfuscate(std::string& data) const { + Serial.printf("[%lu] [WCS] Obfuscating/deobfuscating %zu bytes\n", millis(), data.size()); for (size_t i = 0; i < data.size(); i++) { data[i] ^= OBFUSCATION_KEY[i % KEY_LENGTH]; } @@ -45,6 +46,7 @@ bool WifiCredentialStore::saveToFile() const { for (const auto& cred : credentials) { // Write SSID (plaintext - not sensitive) serialization::writeString(file, cred.ssid); + Serial.printf("[%lu] [WCS] Saving SSID: %s, password length: %zu\n", millis(), cred.ssid.c_str(), cred.password.size()); // Write password (obfuscated) std::string obfuscatedPwd = cred.password; @@ -92,7 +94,9 @@ bool WifiCredentialStore::loadFromFile() { // Read and deobfuscate password serialization::readString(file, cred.password); + Serial.printf("[%lu] [WCS] Loaded SSID: %s, obfuscated password length: %zu\n", millis(), cred.ssid.c_str(), cred.password.size()); obfuscate(cred.password); // XOR is symmetric, so same function deobfuscates + Serial.printf("[%lu] [WCS] After deobfuscation, password length: %zu\n", millis(), cred.password.size()); credentials.push_back(cred); } diff --git a/src/screens/OnScreenKeyboard.cpp b/src/screens/OnScreenKeyboard.cpp index 9671fdf..ba5c1e0 100644 --- a/src/screens/OnScreenKeyboard.cpp +++ b/src/screens/OnScreenKeyboard.cpp @@ -217,7 +217,7 @@ void OnScreenKeyboard::render(int startY) const { int keyboardStartY = inputY + 25; const int keyWidth = 18; const int keyHeight = 18; - const int keySpacing = 1; + const int keySpacing = 3; const char* const* layout = shiftActive ? keyboardShift : keyboard; diff --git a/src/screens/WifiScreen.cpp b/src/screens/WifiScreen.cpp index 4e9d47e..1700c02 100644 --- a/src/screens/WifiScreen.cpp +++ b/src/screens/WifiScreen.cpp @@ -28,6 +28,7 @@ void WifiScreen::onEnter() { enteredPassword.clear(); usedSavedPassword = false; savePromptSelection = 0; + forgetPromptSelection = 0; keyboard.reset(); // Trigger first update to show scanning message @@ -135,6 +136,7 @@ void WifiScreen::selectNetwork(int index) { // Use saved password - connect directly enteredPassword = savedCred->password; usedSavedPassword = true; + Serial.printf("[%lu] [WiFi] Using saved password for %s, length: %zu\n", millis(), selectedSSID.c_str(), enteredPassword.size()); attemptConnection(); return; } @@ -289,18 +291,66 @@ void WifiScreen::handleInput() { return; } - // Handle connected/failed states - if (state == WifiScreenState::CONNECTED || state == WifiScreenState::CONNECTION_FAILED) { - if (inputManager.wasPressed(InputManager::BTN_BACK) || + // Handle forget prompt state (connection failed with saved credentials) + if (state == WifiScreenState::FORGET_PROMPT) { + if (inputManager.wasPressed(InputManager::BTN_LEFT) || + inputManager.wasPressed(InputManager::BTN_UP)) { + if (forgetPromptSelection > 0) { + forgetPromptSelection--; + updateRequired = true; + } + } else if (inputManager.wasPressed(InputManager::BTN_RIGHT) || + inputManager.wasPressed(InputManager::BTN_DOWN)) { + if (forgetPromptSelection < 1) { + forgetPromptSelection++; + updateRequired = true; + } + } else if (inputManager.wasPressed(InputManager::BTN_CONFIRM)) { + if (forgetPromptSelection == 0) { + // User chose "Yes" - forget the network + WIFI_STORE.removeCredential(selectedSSID); + // Update the network list to reflect the change + for (auto& network : networks) { + if (network.ssid == selectedSSID) { + network.hasSavedPassword = false; + break; + } + } + } + // Go back to network list + state = WifiScreenState::NETWORK_LIST; + updateRequired = true; + } else if (inputManager.wasPressed(InputManager::BTN_BACK)) { + // Skip forgetting, go back to network list + state = WifiScreenState::NETWORK_LIST; + updateRequired = true; + } + return; + } + + // Handle connected state + if (state == WifiScreenState::CONNECTED) { + if (inputManager.wasPressed(InputManager::BTN_BACK) || inputManager.wasPressed(InputManager::BTN_CONFIRM)) { - if (state == WifiScreenState::CONNECTION_FAILED) { + // Exit screen on success + onGoBack(); + return; + } + } + + // Handle connection failed state + if (state == WifiScreenState::CONNECTION_FAILED) { + if (inputManager.wasPressed(InputManager::BTN_BACK) || + inputManager.wasPressed(InputManager::BTN_CONFIRM)) { + // If we used saved credentials, offer to forget the network + if (usedSavedPassword) { + state = WifiScreenState::FORGET_PROMPT; + forgetPromptSelection = 0; // Default to "Yes" + } else { // Go back to network list on failure state = WifiScreenState::NETWORK_LIST; - updateRequired = true; - } else { - // Exit screen on success - onGoBack(); } + updateRequired = true; return; } } @@ -389,6 +439,9 @@ void WifiScreen::render() const { case WifiScreenState::CONNECTION_FAILED: renderConnectionFailed(); break; + case WifiScreenState::FORGET_PROMPT: + renderForgetPrompt(); + break; } renderer.displayBuffer(); @@ -578,5 +631,45 @@ void WifiScreen::renderConnectionFailed() const { renderer.drawCenteredText(READER_FONT_ID, top - 20, "Connection Failed", true, BOLD); renderer.drawCenteredText(UI_FONT_ID, top + 20, connectionError.c_str(), true, REGULAR); - renderer.drawCenteredText(SMALL_FONT_ID, pageHeight - 30, "Press any button to go back", true, REGULAR); + renderer.drawCenteredText(SMALL_FONT_ID, pageHeight - 30, "Press any button to continue", true, REGULAR); +} + +void WifiScreen::renderForgetPrompt() const { + const auto pageWidth = GfxRenderer::getScreenWidth(); + const auto pageHeight = GfxRenderer::getScreenHeight(); + const auto height = renderer.getLineHeight(UI_FONT_ID); + const auto top = (pageHeight - height * 3) / 2; + + renderer.drawCenteredText(READER_FONT_ID, top - 40, "Forget Network?", true, BOLD); + + std::string ssidInfo = "Network: " + selectedSSID; + if (ssidInfo.length() > 28) { + ssidInfo = ssidInfo.substr(0, 25) + "..."; + } + renderer.drawCenteredText(UI_FONT_ID, top, ssidInfo.c_str(), true, REGULAR); + + renderer.drawCenteredText(UI_FONT_ID, top + 40, "Remove saved password?", true, REGULAR); + + // Draw Yes/No buttons + const int buttonY = top + 80; + const int buttonWidth = 60; + const int buttonSpacing = 30; + const int totalWidth = buttonWidth * 2 + buttonSpacing; + const int startX = (pageWidth - totalWidth) / 2; + + // Draw "Yes" button + if (forgetPromptSelection == 0) { + renderer.drawText(UI_FONT_ID, startX, buttonY, "[Yes]"); + } else { + renderer.drawText(UI_FONT_ID, startX + 4, buttonY, "Yes"); + } + + // Draw "No" button + if (forgetPromptSelection == 1) { + renderer.drawText(UI_FONT_ID, startX + buttonWidth + buttonSpacing, buttonY, "[No]"); + } else { + renderer.drawText(UI_FONT_ID, startX + buttonWidth + buttonSpacing + 4, buttonY, "No"); + } + + renderer.drawCenteredText(SMALL_FONT_ID, pageHeight - 30, "LEFT/RIGHT: Select | OK: Confirm", true, REGULAR); } diff --git a/src/screens/WifiScreen.h b/src/screens/WifiScreen.h index 935ba51..1f1be3f 100644 --- a/src/screens/WifiScreen.h +++ b/src/screens/WifiScreen.h @@ -28,7 +28,8 @@ enum class WifiScreenState { CONNECTING, // Attempting to connect CONNECTED, // Successfully connected, showing IP SAVE_PROMPT, // Asking user if they want to save the password - CONNECTION_FAILED // Connection failed + CONNECTION_FAILED, // Connection failed + FORGET_PROMPT // Asking user if they want to forget the network }; class WifiScreen final : public Screen { @@ -57,8 +58,9 @@ class WifiScreen final : public Screen { // Whether network was connected using a saved password (skip save prompt) bool usedSavedPassword = false; - // Save prompt selection (0 = Yes, 1 = No) + // Save/forget prompt selection (0 = Yes, 1 = No) int savePromptSelection = 0; + int forgetPromptSelection = 0; // Connection timeout static constexpr unsigned long CONNECTION_TIMEOUT_MS = 15000; @@ -73,6 +75,7 @@ class WifiScreen final : public Screen { void renderConnected() const; void renderSavePrompt() const; void renderConnectionFailed() const; + void renderForgetPrompt() const; void startWifiScan(); void processWifiScanResults();