Files
crosspoint-reader/src/activities/network/WifiSelectionActivity.h
2025-12-22 00:48:16 +11:00

105 lines
3.4 KiB
C++

#pragma once
#include <freertos/FreeRTOS.h>
#include <freertos/semphr.h>
#include <freertos/task.h>
#include <cstdint>
#include <functional>
#include <memory>
#include <string>
#include <vector>
#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<WifiNetworkInfo> networks;
const std::function<void(bool connected)> 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, InputManager& inputManager,
const std::function<void(bool connected)>& onComplete)
: ActivityWithSubactivity("WifiSelection", renderer, inputManager), 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; }
};