Files
Crosspoint/src/activities/network/WifiSelectionActivity.h
T
Zach Nelson 3a1e9f3023 refactor: Dedupe wifi scan in-place without std::map (#2262)
## Summary

`std::map` heap-allocates each node. Avoid using it for wifi SSID
dedupe, and instead just dedupe in-place with the existing `networks`
vector. Removed dead `ipAddress` member in `WifiNetworkInfo` struct.

---

### AI Usage

Did you use AI tools to help write this code? _**PARTIALLY**_
2026-06-07 08:27:20 -04:00

110 lines
3.6 KiB
C++

#pragma once
#include <cstdint>
#include <functional>
#include <memory>
#include <string>
#include <vector>
#include "activities/Activity.h"
#include "util/ButtonNavigator.h"
struct Rect;
struct ThemeMetrics;
// 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 {
AUTO_CONNECTING, // Trying to connect to the last known network
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 Activity {
ButtonNavigator buttonNavigator;
WifiSelectionState state = WifiSelectionState::SCANNING;
size_t selectedNetworkIndex = 0;
std::vector<WifiNetworkInfo> networks;
// 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;
// Cached MAC address string for display
std::string cachedMacAddress;
// Whether network was connected using a saved password (skip save prompt)
bool usedSavedPassword = false;
// Whether to attempt auto-connect on entry
const bool allowAutoConnect;
// Whether we are attempting to auto-connect
bool autoConnecting = 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;
void renderNetworkList(const Rect* screen, const ThemeMetrics* metrics) const;
void renderPasswordEntry(const Rect* screen, const ThemeMetrics* metrics) const;
void renderConnecting(const Rect* screen, const ThemeMetrics* metrics) const;
void renderConnected(const Rect* screen, const ThemeMetrics* metrics) const;
void renderSavePrompt(const Rect* screen, const ThemeMetrics* metrics) const;
void renderConnectionFailed(const Rect* screen, const ThemeMetrics* metrics) const;
void renderForgetPrompt(const Rect* screen, const ThemeMetrics* metrics) const;
void startWifiScan();
void processWifiScanResults();
void selectNetwork(int index);
void attemptConnection();
void checkConnectionStatus();
std::string getSignalStrengthIndicator(int32_t rssi) const;
void onComplete(bool connected);
public:
explicit WifiSelectionActivity(GfxRenderer& renderer, MappedInputManager& mappedInput, bool autoConnect = true)
: Activity("WifiSelection", renderer, mappedInput), allowAutoConnect(autoConnect) {}
void onEnter() override;
void onExit() override;
void loop() override;
void render(RenderLock&&) override;
};