Fix issue with failed connections

This commit is contained in:
Brendan O'Leary 2025-12-15 22:13:17 -05:00
parent 596e6fad0b
commit 1bc30fbf2a
4 changed files with 112 additions and 12 deletions

View File

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

View File

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

View File

@ -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) {
// 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);
}

View File

@ -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();