#include "NetworkManager.h" // SSID and password are now configured via Config class void NetworkManager::scanWifi() { if (!isScanning) { isScanning = true; Serial.println("[WiFi] Starting WiFi scan..."); // Start async WiFi scan WiFi.scanNetworksAsync([this](int networksFound) { Serial.printf("[WiFi] Scan completed, found %d networks\n", networksFound); this->processAccessPoints(); this->isScanning = false; }, true); } else { Serial.println("[WiFi] Scan already in progress..."); } } void NetworkManager::processAccessPoints() { int numNetworks = WiFi.scanComplete(); if (numNetworks <= 0) { Serial.println("[WiFi] No networks found or scan not complete"); return; } // Clear existing access points accessPoints.clear(); // Process each network found for (int i = 0; i < numNetworks; i++) { AccessPoint ap; ap.ssid = WiFi.SSID(i); ap.rssi = WiFi.RSSI(i); ap.encryptionType = WiFi.encryptionType(i); ap.channel = WiFi.channel(i); ap.isHidden = ap.ssid.length() == 0; // Copy BSSID uint8_t* newBssid = new uint8_t[6]; memcpy(newBssid, WiFi.BSSID(i), 6); ap.bssid = newBssid; accessPoints.push_back(ap); Serial.printf("[WiFi] Found network %d: %s, Ch: %d, RSSI: %d\n", i + 1, ap.ssid.c_str(), ap.channel, ap.rssi); } // Free the memory used by the scan WiFi.scanDelete(); } std::vector NetworkManager::getAccessPoints() const { return accessPoints; } NetworkManager::NetworkManager(NodeContext& ctx) : ctx(ctx) {} void NetworkManager::setWiFiConfig(const String& ssid, const String& password, uint32_t connect_timeout_ms, uint32_t retry_delay_ms) { ctx.config.wifi_ssid = ssid; ctx.config.wifi_password = password; ctx.config.wifi_connect_timeout_ms = connect_timeout_ms; ctx.config.wifi_retry_delay_ms = retry_delay_ms; } void NetworkManager::setHostnameFromMac() { uint8_t mac[6]; WiFi.macAddress(mac); char buf[32]; sprintf(buf, "esp-%02X%02X%02X%02X%02X%02X", mac[0], mac[1], mac[2], mac[3], mac[4], mac[5]); WiFi.hostname(buf); ctx.hostname = String(buf); } void NetworkManager::setupWiFi() { WiFi.mode(WIFI_STA); WiFi.begin(ctx.config.wifi_ssid.c_str(), ctx.config.wifi_password.c_str()); Serial.println("[WiFi] Connecting to AP..."); unsigned long startAttemptTime = millis(); while (WiFi.status() != WL_CONNECTED && millis() - startAttemptTime < ctx.config.wifi_connect_timeout_ms) { delay(ctx.config.wifi_retry_delay_ms); Serial.print("."); } if (WiFi.status() == WL_CONNECTED) { Serial.println(); Serial.print("[WiFi] Connected to AP, IP: "); Serial.println(WiFi.localIP()); } else { Serial.println(); Serial.println("[WiFi] Failed to connect to AP. Creating AP..."); WiFi.mode(WIFI_AP); WiFi.softAP(ctx.config.wifi_ssid.c_str(), ctx.config.wifi_password.c_str()); Serial.print("[WiFi] AP created, IP: "); Serial.println(WiFi.softAPIP()); } setHostnameFromMac(); ctx.udp->begin(ctx.config.udp_port); ctx.localIP = WiFi.localIP(); ctx.hostname = WiFi.hostname(); Serial.print("[WiFi] Hostname set to: "); Serial.println(ctx.hostname); Serial.printf("[WiFi] UDP listening on port %d\n", ctx.config.udp_port); // Populate self NodeInfo ctx.self.hostname = ctx.hostname; if (WiFi.isConnected()) { ctx.self.ip = WiFi.localIP(); } else { ctx.self.ip = WiFi.softAPIP(); } ctx.self.lastSeen = millis(); ctx.self.status = NodeInfo::ACTIVE; ctx.self.labels["hostname"] = ctx.hostname; // Ensure member list has an entry for this node auto &memberList = *ctx.memberList; auto existing = memberList.find(ctx.hostname); if (existing == memberList.end()) { memberList[ctx.hostname] = ctx.self; } else { existing->second = ctx.self; } // Notify listeners that the node is (re)discovered ctx.fire("node_discovered", &ctx.self); }