feat: wifiscan
This commit is contained in:
@@ -1,8 +1,29 @@
|
||||
#include "NetworkManager.h"
|
||||
#include "TaskManager.h"
|
||||
|
||||
// SSID and password are now configured via Config class
|
||||
|
||||
NetworkManager::NetworkManager(NodeContext& ctx) : ctx(ctx) {}
|
||||
const char* const NetworkManager::WIFI_SCAN_MONITOR_TASK = "wifi_scan_monitor";
|
||||
|
||||
NetworkManager::NetworkManager(NodeContext& ctx) : ctx(ctx), wifiScanInProgress(false), wifiScanStartTime(0) {
|
||||
// Register scan process callback
|
||||
ctx.on("wifi/scan/process", [this](void* data) {
|
||||
int networksFound = reinterpret_cast<intptr_t>(data);
|
||||
this->processScanResults(networksFound);
|
||||
});
|
||||
}
|
||||
|
||||
void NetworkManager::initTasks() {
|
||||
if (!ctx.taskManager) {
|
||||
Serial.println("[WiFi] Error: TaskManager not initialized");
|
||||
return;
|
||||
}
|
||||
|
||||
// Register task to check scan status every 100ms (initially disabled)
|
||||
ctx.taskManager->registerTask(WIFI_SCAN_MONITOR_TASK, 100, [this]() {
|
||||
this->updateWiFiScan();
|
||||
}, false); // false = disabled by default
|
||||
}
|
||||
|
||||
void NetworkManager::setHostnameFromMac() {
|
||||
uint8_t mac[6];
|
||||
@@ -65,3 +86,133 @@ void NetworkManager::setupWiFi() {
|
||||
// Notify listeners that the node is (re)discovered
|
||||
ctx.fire("node_discovered", &ctx.self);
|
||||
}
|
||||
|
||||
void NetworkManager::startWiFiScan() {
|
||||
if (wifiScanInProgress) {
|
||||
Serial.println("[WiFi] Scan already in progress");
|
||||
return;
|
||||
}
|
||||
|
||||
// Check if we're in AP mode only
|
||||
if (WiFi.getMode() == WIFI_AP) {
|
||||
// Enable STA mode while keeping AP mode
|
||||
WiFi.mode(WIFI_AP_STA);
|
||||
delay(100); // Give some time for mode change
|
||||
}
|
||||
|
||||
// Ensure we have STA mode enabled
|
||||
if (WiFi.getMode() != WIFI_STA && WiFi.getMode() != WIFI_AP_STA) {
|
||||
Serial.println("[WiFi] Error: Cannot scan without STA mode enabled");
|
||||
ctx.fire("wifi/scan/error", nullptr);
|
||||
return;
|
||||
}
|
||||
|
||||
Serial.println("[WiFi] Starting WiFi scan...");
|
||||
wifiScanInProgress = true;
|
||||
wifiScanStartTime = millis();
|
||||
|
||||
// Enable the monitoring task if TaskManager is available
|
||||
if (ctx.taskManager) {
|
||||
ctx.taskManager->enableTask(WIFI_SCAN_MONITOR_TASK);
|
||||
}
|
||||
|
||||
// Clear previous results safely
|
||||
if (ctx.wifiAccessPoints) {
|
||||
ctx.wifiAccessPoints->clear();
|
||||
}
|
||||
|
||||
// Disable interrupts briefly during scan start
|
||||
noInterrupts();
|
||||
// Start the scan
|
||||
WiFi.scanNetworksAsync([this](int networksFound) {
|
||||
// Schedule callback in main loop
|
||||
ctx.fire("wifi/scan/process", reinterpret_cast<void*>(networksFound));
|
||||
}, true); // Show hidden networks
|
||||
interrupts();
|
||||
}
|
||||
|
||||
void NetworkManager::updateWiFiScan() {
|
||||
if (!wifiScanInProgress) {
|
||||
return;
|
||||
}
|
||||
|
||||
// Check for timeout
|
||||
if (millis() - wifiScanStartTime > WIFI_SCAN_TIMEOUT_MS) {
|
||||
Serial.println("[WiFi] WiFi scan timeout");
|
||||
wifiScanInProgress = false;
|
||||
if (ctx.taskManager) {
|
||||
ctx.taskManager->disableTask(WIFI_SCAN_MONITOR_TASK);
|
||||
}
|
||||
ctx.fire("wifi/scan/timeout", nullptr);
|
||||
}
|
||||
}
|
||||
|
||||
void NetworkManager::processScanResults(int networksFound) {
|
||||
// This is called from the main loop context via the event system
|
||||
if (!wifiScanInProgress) {
|
||||
return; // Ignore if we're not expecting results
|
||||
}
|
||||
|
||||
wifiScanInProgress = false;
|
||||
// Disable the monitoring task if TaskManager is available
|
||||
if (ctx.taskManager) {
|
||||
ctx.taskManager->disableTask(WIFI_SCAN_MONITOR_TASK);
|
||||
}
|
||||
|
||||
Serial.printf("[WiFi] Processing scan results, found %d networks\n", networksFound);
|
||||
|
||||
// Create a temporary vector to hold new results
|
||||
std::vector<WiFiAccessPoint> newAccessPoints;
|
||||
|
||||
if (networksFound > 0) {
|
||||
newAccessPoints.reserve(networksFound); // Pre-allocate space
|
||||
|
||||
// Process each found network
|
||||
for (int i = 0; i < networksFound; i++) {
|
||||
WiFiAccessPoint ap;
|
||||
ap.ssid = WiFi.SSID(i);
|
||||
ap.rssi = WiFi.RSSI(i);
|
||||
ap.encryption = WiFi.encryptionType(i);
|
||||
ap.channel = WiFi.channel(i);
|
||||
ap.isHidden = WiFi.isHidden(i);
|
||||
|
||||
// Copy BSSID - with null check and bounds protection
|
||||
uint8_t* bssid = WiFi.BSSID(i);
|
||||
ap.bssid = nullptr; // Initialize to null first
|
||||
if (bssid != nullptr) {
|
||||
ap.bssid = new (std::nothrow) uint8_t[6]; // Use nothrow to prevent exceptions
|
||||
if (ap.bssid != nullptr) {
|
||||
memcpy(ap.bssid, bssid, 6);
|
||||
}
|
||||
}
|
||||
|
||||
newAccessPoints.push_back(ap);
|
||||
|
||||
Serial.printf("[WiFi] %d: %s (RSSI: %d, Ch: %d, Enc: %d)\n",
|
||||
i, ap.ssid.c_str(), ap.rssi, ap.channel, ap.encryption);
|
||||
}
|
||||
}
|
||||
|
||||
// Free the scan results from WiFi to prevent memory leaks
|
||||
WiFi.scanDelete();
|
||||
|
||||
// Safely swap the new results with the stored results
|
||||
if (ctx.wifiAccessPoints) {
|
||||
ctx.wifiAccessPoints->swap(newAccessPoints);
|
||||
// Fire the scan complete event with a copy of the pointer
|
||||
auto accessPoints = ctx.wifiAccessPoints;
|
||||
ctx.fire("wifi/scan/complete", accessPoints);
|
||||
} else {
|
||||
Serial.println("[WiFi] Error: wifiAccessPoints is null");
|
||||
ctx.fire("wifi/scan/error", nullptr);
|
||||
}
|
||||
}
|
||||
|
||||
void NetworkManager::onWiFiScanComplete(int networksFound) {
|
||||
// Internal callback that schedules processing in the main loop
|
||||
ctx.fire("wifi/scan/process", reinterpret_cast<void*>(networksFound));
|
||||
}
|
||||
|
||||
bool NetworkManager::isWiFiScanning() const {
|
||||
return wifiScanInProgress;
|
||||
}
|
||||
|
||||
@@ -1,8 +1,11 @@
|
||||
#include "NodeContext.h"
|
||||
#include "TaskManager.h"
|
||||
|
||||
NodeContext::NodeContext() {
|
||||
udp = new WiFiUDP();
|
||||
memberList = new std::map<String, NodeInfo>();
|
||||
wifiAccessPoints = new std::vector<WiFiAccessPoint>();
|
||||
taskManager = nullptr; // Will be set by TaskManager constructor
|
||||
hostname = "";
|
||||
self.hostname = "";
|
||||
self.ip = IPAddress();
|
||||
@@ -19,6 +22,7 @@ NodeContext::NodeContext(std::initializer_list<std::pair<String, String>> initia
|
||||
NodeContext::~NodeContext() {
|
||||
delete udp;
|
||||
delete memberList;
|
||||
delete wifiAccessPoints;
|
||||
}
|
||||
|
||||
void NodeContext::on(const std::string& event, EventCallback cb) {
|
||||
|
||||
Reference in New Issue
Block a user