#pragma once #include #include #include #include #include #include #include #include #include "activities/ActivityWithSubactivity.h" // Structure to hold WiFi network information struct WifiNetworkInfo { std::string ssid; int32_t rssi; bool isEncrypted; bool hasSavedPassword; // Whether we have saved credentials for this network }; // WiFi selection states enum class WifiSelectionState { SCANNING, // Scanning for networks NETWORK_LIST, // Displaying available networks PASSWORD_ENTRY, // Entering password for selected network CONNECTING, // Attempting to connect CONNECTED, // Successfully connected SAVE_PROMPT, // Asking user if they want to save the password CONNECTION_FAILED, // Connection failed FORGET_PROMPT // Asking user if they want to forget the network }; /** * WifiSelectionActivity is responsible for scanning WiFi APs and connecting to them. * It will: * - Enter scanning mode on entry * - List available WiFi networks * - Allow selection and launch KeyboardEntryActivity for password if needed * - Save the password if requested * - Call onComplete callback when connected or cancelled * * The onComplete callback receives true if connected successfully, false if cancelled. */ class WifiSelectionActivity final : public ActivityWithSubactivity { TaskHandle_t displayTaskHandle = nullptr; SemaphoreHandle_t renderingMutex = nullptr; bool updateRequired = false; WifiSelectionState state = WifiSelectionState::SCANNING; int selectedNetworkIndex = 0; std::vector networks; const std::function onComplete; // Selected network for connection std::string selectedSSID; bool selectedRequiresPassword = false; // Connection result std::string connectedIP; std::string connectionError; // Password to potentially save (from keyboard or saved credentials) std::string enteredPassword; // Whether network was connected using a saved password (skip save prompt) bool usedSavedPassword = false; // Save/forget prompt selection (0 = Yes, 1 = No) int savePromptSelection = 0; int forgetPromptSelection = 0; // Connection timeout static constexpr unsigned long CONNECTION_TIMEOUT_MS = 15000; unsigned long connectionStartTime = 0; static void taskTrampoline(void* param); [[noreturn]] void displayTaskLoop(); void render() const; void renderNetworkList() const; void renderPasswordEntry() const; void renderConnecting() const; void renderConnected() const; void renderSavePrompt() const; void renderConnectionFailed() const; void renderForgetPrompt() const; void startWifiScan(); void processWifiScanResults(); void selectNetwork(int index); void attemptConnection(); void checkConnectionStatus(); std::string getSignalStrengthIndicator(int32_t rssi) const; public: explicit WifiSelectionActivity(GfxRenderer& renderer, MappedInputManager& mappedInput, const std::function& onComplete) : ActivityWithSubactivity("WifiSelection", renderer, mappedInput), onComplete(onComplete) {} void onEnter() override; void onExit() override; void loop() override; // Get the IP address after successful connection const std::string& getConnectedIP() const { return connectedIP; } };