/// © MiroZ 2024 #include "Wifi.h" #include "errors.h" #include "Settings.h" #include #include #include "utilities.h" #include "app_config.h" #include #include "esp_phy_init.h" #include "esp_ota_ops.h" static const char *TAG = "Wifi"; #define IGNORE_SSID_MINS 20 using namespace std::placeholders; const char* Wifi::FALLBACK_NETWORKS[] = {"CBX_IoT", "welltest"}; const char* Wifi::FALLBACK_PASSWORDS[] = {"69696969", "well1234"}; const int Wifi::NUM_FALLBACK_NETWORKS = 2; bool Wifi::shouldPerformBootupCalibration() { uint32_t reset_reason = esp_reset_reason(); ESP_LOGI(TAG, "Checking if bootup calibration needed, reset reason: %d", reset_reason); // Always calibrate after these conditions: bool should_calibrate = false; // 1. After OTA update const esp_partition_t* running_partition = esp_ota_get_running_partition(); const esp_partition_t* boot_partition = esp_ota_get_boot_partition(); if (running_partition != boot_partition) { ESP_LOGW(TAG, "Bootup calibration: Running from different partition (OTA update detected)"); should_calibrate = true; } // 2. After power-related resets that might affect calibration if(reset_reason == ESP_RST_BROWNOUT) { ESP_LOGW(TAG, "Bootup calibration: Brown-out reset detected"); should_calibrate = true; } // 3. After watchdog resets (system instability) if(reset_reason == ESP_RST_TASK_WDT || reset_reason == ESP_RST_WDT) { ESP_LOGW(TAG, "Bootup calibration: Watchdog reset detected"); should_calibrate = true; } // 4. After panic/exception resets if(reset_reason == ESP_RST_PANIC) { ESP_LOGW(TAG, "Bootup calibration: Panic reset detected"); should_calibrate = true; } // 5. First boot after firmware flash (power-on reset) if(reset_reason == ESP_RST_POWERON) { ESP_LOGI(TAG, "Bootup calibration: Power-on reset (fresh boot or firmware flash)"); should_calibrate = true; } // 6. Check if automatic calibration occurred (failed to load RF data) // This would require checking a flag set during phy_init // For now, we'll assume if we got this far, we might need it return should_calibrate; } void Wifi::performBootupCalibration() { if(m_bootup_calibration_done) { ESP_LOGD(TAG, "Bootup calibration already performed"); return; } ESP_LOGW(TAG, "Performing WiFi calibration after boot-up..."); // Ensure WiFi is off before calibration WiFi.mode(WIFI_OFF); delay(1000); // Clear any existing calibration data to force fresh calibration esp_phy_erase_cal_data_in_nvs(); ESP_LOGI(TAG, "Cleared existing PHY calibration data"); // Initialize WiFi with fresh calibration WiFi.mode(WIFI_STA); delay(2000); // Give time for calibration to complete // Turn off WiFi again to save power until actually needed WiFi.mode(WIFI_OFF); delay(500); m_bootup_calibration_done = true; ESP_LOGW(TAG, "Bootup WiFi calibration completed"); } Wifi::Wifi() { esp_log_level_set("wifi", ESP_LOG_WARN); esp_log_level_set("wifi_init", ESP_LOG_INFO); // Add WiFi configuration here if(shouldPerformBootupCalibration()) { performBootupCalibration(); } esp_wifi_set_country_code("US", true); // Or your country code //WiFi.setSleep(false); // Disable power saving if BT is enabled, do not do this! WiFi.onEvent(std::bind(&Wifi::wifi_event, this, _1, _2)); #ifdef USE_TIMER esp_timer_create_args_t timer; timer.arg = this; timer.callback = &timerCallback; timer.dispatch_method = ESP_TIMER_TASK; timer.skip_unhandled_events = true; timer.name = "wifi countdown timer"; ESP_ERROR_CHECK(esp_timer_create(&timer, &m_timer)); ESP_ERROR_CHECK(esp_timer_start_periodic(m_timer, 60000000)); // 1 min #endif } #ifdef USE_TIMER void Wifi::timerCallback(void* arg) { for(int n = 0; n < SETTINGS_NUM_WIFI_ENTRIES; n++) { if(((Wifi*)arg)->m_ignored[n] > 0) ((Wifi*)arg)->m_ignored[n]--; } } #endif void Wifi::wifi_event(arduino_event_id_t event, arduino_event_info_t info) { ESP_LOGI(TAG, "event: %s (%d)", WiFi.eventName(event), (int)event); if(event == ARDUINO_EVENT_WIFI_STA_DISCONNECTED) { wifi_err_reason_t reason = (wifi_err_reason_t)info.wifi_sta_disconnected.reason; ESP_LOGI(TAG, "reason: %s, rssi: %d", WiFi.disconnectReasonName(reason), WiFi.RSSI()); ESP_LOGI(TAG, "Local IP: %s", WiFi.localIP().toString().c_str()); } if(event == ARDUINO_EVENT_WIFI_STA_CONNECTED) { ESP_LOGI(TAG, "Connected - RSSI: %d, Channel: %d", WiFi.RSSI(), WiFi.channel()); } } void Wifi::task() { while(true) { // Check if we're in provisioning mode and handle timeout if(m_wifi_status == WIFI_STATUS::PROVISIONING) { if(isProvisioningTimedOut()) { ESP_LOGW(TAG, "Provisioning timeout reached, stopping AP mode"); stopProvisioning(); m_wifi_status = WIFI_STATUS::NOT_CONNECTED; m_provision_timeout = true; } delay(1000); // Check every second during provisioning continue; } // Check pause flag FIRST (but not during provisioning) while(m_pause && m_wifi_status != WIFI_STATUS::PROVISIONING) { delay(100); } if(!WiFi.isConnected()) { m_wifi_status = WIFI_STATUS::PENDING; m_wifi_status = startConnecting(); delay(500); } delay(15000); } } void Wifi::startProvisioning() { m_wifi_status = WIFI_STATUS::PROVISIONING; m_provision_start_time = millis(); m_provision_timeout = false; ESP_LOGI(TAG, "Starting provisioning mode for %lu minutes", PROVISION_TIMEOUT_MS / 60000); } void Wifi::stopProvisioning() { m_wifi_status = WIFI_STATUS::NOT_CONNECTED; m_provision_start_time = 0; WiFi.mode(WIFI_STA); // Stop AP mode } bool Wifi::isProvisioningTimedOut() { if(m_provision_start_time == 0) return false; return (millis() - m_provision_start_time) > PROVISION_TIMEOUT_MS; } void Wifi::resetProvisioningTimer() { m_provision_start_time = millis(); m_provision_timeout = false; } void Wifi::pause(bool pause) { m_pause = pause; } bool Wifi::shouldRecalibrateRadio(int failed_ssid_index) { // Check cooldown period unsigned long current_time = millis(); bool cooldown_ok = (m_last_recalibration_time == 0) || (current_time - m_last_recalibration_time >= RECALIBRATION_COOLDOWN_MS); if(!cooldown_ok) { unsigned long time_remaining = RECALIBRATION_COOLDOWN_MS - (current_time - m_last_recalibration_time); ESP_LOGD(TAG, "Recalibration skipped - cooldown period active (%lu ms remaining)", time_remaining); return false; } // Check if we have credentials for this index if(failed_ssid_index < 0 || failed_ssid_index >= SETTINGS.wifi.num) { ESP_LOGD(TAG, "Recalibration skipped - no valid credentials"); return false; } // Check if the SSID is visible (network is up) const char* target_ssid = SETTINGS.wifi.entry[failed_ssid_index].ssid; if(!isSSIDVisible(target_ssid)) { ESP_LOGD(TAG, "Recalibration skipped - SSID '%s' not visible", target_ssid); return false; } ESP_LOGW(TAG, "Radio recalibration needed - connection failed but SSID '%s' is visible", target_ssid); ESP_LOGI(TAG, "Current time: %lu, Last recalibration: %lu", current_time, m_last_recalibration_time); return true; } bool Wifi::isSSIDVisible(const char* ssid) { ESP_LOGI(TAG, "=== Starting SSID visibility scan for '%s' ===", ssid); wl_status_t status = WiFi.status(); ESP_LOGI(TAG, "Current WiFi status before scan: %d", status); // Force WiFi into clean state - more aggressive approach WiFi.disconnect(true); // true = also forget credentials temporarily delay(500); WiFi.mode(WIFI_OFF); // Completely turn off WiFi delay(500); WiFi.mode(WIFI_STA); // Turn back on in station mode delay(1000); // Longer delay for complete initialization ESP_LOGI(TAG, "Calling WiFi.scanNetworks(false, false, false, 0)..."); int num_networks = WiFi.scanNetworks(false, false, false, 0); ESP_LOGI(TAG, "=== Scan completed, found %d networks ===", num_networks); for(int n = 0; n < num_networks; n++) { if(strcmp(WiFi.SSID(n).c_str(), ssid) == 0) { ESP_LOGI(TAG, "SSID '%s' found with RSSI %d dBm", ssid, WiFi.RSSI(n)); return true; } } ESP_LOGI(TAG, "SSID '%s' not found in scan results", ssid); return false; } void Wifi::performRadioRecalibration() { ESP_LOGW(TAG, "Performing WiFi radio recalibration..."); // Disconnect and stop WiFi WiFi.disconnect(); WiFi.mode(WIFI_OFF); delay(1000); // Erase calibration data to force fresh calibration esp_phy_erase_cal_data_in_nvs(); // Record recalibration time m_last_recalibration_time = millis(); ESP_LOGW(TAG, "Radio recalibration completed - WiFi will reinitialize on next connection attempt"); // Brief delay to let the radio settle delay(3000); } /// @brief Connect to provisioned wifi /// @param index index of wifi in settings /// @return WIFI_STATUS::CONNECTED/NOT_CONENCTED connected // Modified connectTo method with smart recalibration Wifi::WIFI_STATUS Wifi::connectTo(int index) { IPAddress local_IP(0, 0, 0, 0); IPAddress gateway(0, 0, 0, 0); IPAddress subnet(SETTINGS.wifi.subnet_mask); IPAddress primaryDNS(SETTINGS.wifi.dns_primary); IPAddress secondaryDNS(SETTINGS.wifi.dns_secondary); ESP_LOGI(TAG, "Connecting to %s...", SETTINGS.wifi.entry[index].ssid); delay(1000); // set hostname uint8_t mac[6]; WiFi.macAddress(mac); char buffer[32]; sprintf(buffer, "wellhub-tag%02x%02x%02x", mac[3], mac[4], mac[5]); WiFi.hostname(buffer); WiFi.mode(WIFI_STA); WiFi.config(local_IP, gateway, subnet, primaryDNS, secondaryDNS); WiFi.begin(SETTINGS.wifi.entry[index].ssid, SETTINGS.wifi.entry[index].pwd); int status = WiFi.waitForConnectResult(10000); if(status == WL_CONNECTED) { ESP_LOGI(TAG, "Connected"); return WIFI_STATUS::CONNECTED; } delay(1000); WiFi.disconnect(); ESP_LOGW(TAG, "Failed to connect, status: %d", status); // Check if we should recalibrate the radio if(shouldRecalibrateRadio(index)) { performRadioRecalibration(); // Try connecting one more time after recalibration ESP_LOGI(TAG, "Retrying connection after recalibration..."); delay(3000); // Give radio time to reinitialize WiFi.mode(WIFI_STA); WiFi.config(local_IP, gateway, subnet, primaryDNS, secondaryDNS); WiFi.begin(SETTINGS.wifi.entry[index].ssid, SETTINGS.wifi.entry[index].pwd); status = WiFi.waitForConnectResult(10000); if(status == WL_CONNECTED) { ESP_LOGI(TAG, "Connected after recalibration!"); return WIFI_STATUS::CONNECTED; } else { ESP_LOGW(TAG, "Still failed after recalibration, status: %d", status); WiFi.disconnect(); } } return WIFI_STATUS::NOT_CONNECTED; } int Wifi::start() { if(m_task == nullptr) { uint8_t mac[8]; esp_read_mac(mac, ESP_MAC_WIFI_STA); ESP_LOGW(TAG, "Starting wifi, mac: %02x:%02x:%02x:%02x:%02x:%02x ...", mac[0], mac[1], mac[2], mac[3], mac[4], mac[5]); m_task = TaskMgr::getInstance().createTask(std::bind(&Wifi::task, this), WIFI_TASK_NAME, WIFI_TASK_STACK_SIZE, WIFI_TASK_PRIORITY, WIFI_TASK_CORE); } return 0; } Wifi::WIFI_STATUS Wifi::waitForConnection() { Wifi::WIFI_STATUS st; while((st = status()) == Wifi::WIFI_STATUS::PENDING) delay(500); return st; } /// @brief Connect to default fallback wifi network /// @return WIFI_STATUS::CONNECTED/NOT_CONNECTED // Also modify startConnecting to handle recalibration for fallback network Wifi::WIFI_STATUS Wifi::connectToDefault() { // Try each fallback network in sequence using class members for(int i = 0; i < NUM_FALLBACK_NETWORKS; i++) { ESP_LOGI(TAG, "Trying fallback network %d: %s...", i + 1, FALLBACK_NETWORKS[i]); WIFI_STATUS status = connectToFallbackNetwork(FALLBACK_NETWORKS[i], FALLBACK_PASSWORDS[i]); if(status == WIFI_STATUS::CONNECTED) { ESP_LOGI(TAG, "Connected to fallback network %s", FALLBACK_NETWORKS[i]); return WIFI_STATUS::CONNECTED; } } ESP_LOGW(TAG, "All %d fallback networks failed", NUM_FALLBACK_NETWORKS); return WIFI_STATUS::NOT_CONNECTED; } // New helper method to connect to a specific fallback network Wifi::WIFI_STATUS Wifi::connectToFallbackNetwork(const char* ssid, const char* password) { IPAddress local_IP(0, 0, 0, 0); IPAddress gateway(0, 0, 0, 0); IPAddress subnet(SETTINGS.wifi.subnet_mask); IPAddress primaryDNS(SETTINGS.wifi.dns_primary); IPAddress secondaryDNS(SETTINGS.wifi.dns_secondary); ESP_LOGI(TAG, "Connecting to fallback network %s...", ssid); delay(1000); // set hostname uint8_t mac[6]; WiFi.macAddress(mac); char buffer[32]; sprintf(buffer, "wellhub-tag%02x%02x%02x", mac[3], mac[4], mac[5]); WiFi.hostname(buffer); WiFi.mode(WIFI_STA); WiFi.config(local_IP, gateway, subnet, primaryDNS, secondaryDNS); WiFi.begin(ssid, password); int status = WiFi.waitForConnectResult(10000); if(status == WL_CONNECTED) { ESP_LOGI(TAG, "Connected to fallback network %s", ssid); return WIFI_STATUS::CONNECTED; } delay(1000); WiFi.disconnect(); ESP_LOGW(TAG, "Failed to connect to fallback network %s, status: %d", ssid, status); return WIFI_STATUS::NOT_CONNECTED; } /// @brief Connects to wifi. Returns immediately if already connected. /// @return WH_OK | WH_ERR_WIFI_NOT_PROVISIONED // Modified startConnecting method to handle dual fallback with recalibration // Modified startConnecting method - no hardcoded networks Wifi::WIFI_STATUS Wifi::startConnecting() { ESP_LOGW(TAG, "===== START CONNECTING ====="); // Diagnostic logging of saved networks ESP_LOGW(TAG, "Provisioned networks: %d", SETTINGS.wifi.num); for(int i = 0; i < SETTINGS.wifi.num; i++) { ESP_LOGW(TAG, "[%d] SSID: '%s'", i, SETTINGS.wifi.entry[i].ssid); } if(::WiFi.isConnected()) { ESP_LOGW(TAG, "Already connected"); return WIFI_STATUS::CONNECTED; } // Try provisioned networks first if any exist if(SETTINGS.wifi.num > 0) { // Single network provisioned - try multiple times if(SETTINGS.wifi.num == 1) { ESP_LOGW(TAG, "Single network provisioned, checking visibility first..."); SETTINGS.wifi.selected = 0; // Check if the network is visible before attempting connections if(isSSIDVisible(SETTINGS.wifi.entry[0].ssid)) { ESP_LOGW(TAG, "Network '%s' is visible, attempting connection...", SETTINGS.wifi.entry[0].ssid); for(int n = 0; n < 7; n++) { ESP_LOGW(TAG, "Connection attempt %d/7 to '%s'", n+1, SETTINGS.wifi.entry[0].ssid); if(connectTo(SETTINGS.wifi.selected) == WIFI_STATUS::CONNECTED) { ESP_LOGW(TAG, "Successfully connected on attempt %d", n+1); return WIFI_STATUS::CONNECTED; } ::WiFi.disconnect(); delay(1000); } ESP_LOGW(TAG, "Failed to connect to visible network after 7 attempts"); } else { ESP_LOGW(TAG, "Network '%s' not found in scan - skipping connection attempts", SETTINGS.wifi.entry[0].ssid); } ESP_LOGW(TAG, "Single provisioned network unavailable or failed"); } else { // Multiple networks provisioned - ALWAYS scan first to get current visibility/RSSI ESP_LOGW(TAG, "Multiple networks provisioned, scanning for currently available networks..."); memset(m_ignored, 0, SETTINGS_NUM_WIFI_ENTRIES); // Force a fresh scan to get current network conditions ESP_LOGW(TAG, "Performing fresh scan to find best available network..."); int ssid_ix = scan(); if(ssid_ix >= 0) { ESP_LOGW(TAG, "Found available network with best RSSI: '%s'", SETTINGS.wifi.entry[ssid_ix].ssid); if(connectTo(ssid_ix) == WIFI_STATUS::CONNECTED) { SETTINGS.wifi.selected = ssid_ix; ESP_LOGW(TAG, "Connected to best available network"); return WIFI_STATUS::CONNECTED; } // First choice failed - mark as ignored and try others ESP_LOGW(TAG, "Best RSSI network failed, trying other available networks..."); m_ignored[ssid_ix] = IGNORE_SSID_MINS; // Keep trying other networks found in the scan do { ssid_ix = scan(); if(ssid_ix >= 0) { ESP_LOGW(TAG, "Trying next best available network: '%s'", SETTINGS.wifi.entry[ssid_ix].ssid); if(connectTo(ssid_ix) == WIFI_STATUS::CONNECTED) { SETTINGS.wifi.selected = ssid_ix; ESP_LOGW(TAG, "Connected to network '%s'", SETTINGS.wifi.entry[ssid_ix].ssid); return WIFI_STATUS::CONNECTED; } else { m_ignored[ssid_ix] = IGNORE_SSID_MINS; } } else { ESP_LOGW(TAG, "No more available networks found in scan"); break; } } while(true); // All scanned networks failed - try a brute force approach on all stored networks ESP_LOGW(TAG, "Scan-based selection failed, trying brute force on all stored networks..."); memset(m_ignored, 0, SETTINGS_NUM_WIFI_ENTRIES); // Clear ignore list for(int cycle = 0; cycle < 3; cycle++) { ESP_LOGW(TAG, "Brute force cycle %d/3", cycle+1); for(int n = 0; n < SETTINGS.wifi.num; n++) { // Check if network is actually visible before trying to connect ESP_LOGW(TAG, "Checking visibility of stored network '%s'...", SETTINGS.wifi.entry[n].ssid); if(isSSIDVisible(SETTINGS.wifi.entry[n].ssid)) { ESP_LOGW(TAG, "Network '%s' is visible, attempting connection...", SETTINGS.wifi.entry[n].ssid); if(connectTo(n) == WIFI_STATUS::CONNECTED) { SETTINGS.wifi.selected = n; ESP_LOGW(TAG, "Connected to '%s' in brute force mode", SETTINGS.wifi.entry[n].ssid); return WIFI_STATUS::CONNECTED; } } else { ESP_LOGW(TAG, "Network '%s' not visible, skipping", SETTINGS.wifi.entry[n].ssid); } } } } else { // No provisioned networks found in scan - try visibility check on all stored networks ESP_LOGW(TAG, "No provisioned networks found in scan, checking individual visibility..."); for(int n = 0; n < SETTINGS.wifi.num; n++) { ESP_LOGW(TAG, "Checking if stored network '%s' is available...", SETTINGS.wifi.entry[n].ssid); if(isSSIDVisible(SETTINGS.wifi.entry[n].ssid)) { ESP_LOGW(TAG, "Found available stored network '%s', attempting connection...", SETTINGS.wifi.entry[n].ssid); if(connectTo(n) == WIFI_STATUS::CONNECTED) { SETTINGS.wifi.selected = n; ESP_LOGW(TAG, "Connected to stored network '%s'", SETTINGS.wifi.entry[n].ssid); return WIFI_STATUS::CONNECTED; } } else { ESP_LOGW(TAG, "Stored network '%s' not currently available", SETTINGS.wifi.entry[n].ssid); } } } ESP_LOGW(TAG, "Failed to connect to any provisioned networks"); } } else { ESP_LOGW(TAG, "No networks provisioned"); } // Fallback: Try fallback WiFi networks ESP_LOGW(TAG, "===== ATTEMPTING FALLBACK CONNECTIONS ====="); WIFI_STATUS fallback_status = connectToDefault(); if(fallback_status == WIFI_STATUS::CONNECTED) { ESP_LOGW(TAG, "Successfully connected to fallback network"); return WIFI_STATUS::CONNECTED; } // Check if we should recalibrate for any visible fallback network ESP_LOGW(TAG, "All fallback connections failed, checking if recalibration needed..."); // Check if any fallback network is visible bool any_network_visible = false; const char* visible_network = nullptr; for(int i = 0; i < NUM_FALLBACK_NETWORKS; i++) { ESP_LOGW(TAG, "Checking visibility of fallback network '%s'...", FALLBACK_NETWORKS[i]); if(isSSIDVisible(FALLBACK_NETWORKS[i])) { any_network_visible = true; visible_network = FALLBACK_NETWORKS[i]; ESP_LOGW(TAG, "Fallback network '%s' is VISIBLE", FALLBACK_NETWORKS[i]); break; } else { ESP_LOGW(TAG, "Fallback network '%s' is NOT visible", FALLBACK_NETWORKS[i]); } } if(any_network_visible) { unsigned long current_time = millis(); // Allow recalibration if never done or cooldown expired bool cooldown_ok = (m_last_recalibration_time == 0) || (current_time - m_last_recalibration_time >= RECALIBRATION_COOLDOWN_MS); if(cooldown_ok) { ESP_LOGW(TAG, "*** RECALIBRATION TRIGGERED ***"); ESP_LOGW(TAG, "Network '%s' visible but connection failed", visible_network); ESP_LOGW(TAG, "Current time: %lu ms, Last recalibration: %lu ms ago", current_time, m_last_recalibration_time ? (current_time - m_last_recalibration_time) : 0); performRadioRecalibration(); // Retry all fallback networks after recalibration ESP_LOGW(TAG, "===== RETRYING AFTER RECALIBRATION ====="); fallback_status = connectToDefault(); if(fallback_status == WIFI_STATUS::CONNECTED) { ESP_LOGW(TAG, "*** SUCCESS *** Connected after recalibration!"); return WIFI_STATUS::CONNECTED; } else { ESP_LOGE(TAG, "*** FAILURE *** Still cannot connect after recalibration"); // Try provisioned networks one more time after recalibration if(SETTINGS.wifi.num > 0) { ESP_LOGW(TAG, "Final attempt on provisioned networks after recalibration..."); for(int i = 0; i < SETTINGS.wifi.num; i++) { if(connectTo(i) == WIFI_STATUS::CONNECTED) { ESP_LOGW(TAG, "Connected to provisioned network after recalibration!"); return WIFI_STATUS::CONNECTED; } } } } } else { unsigned long time_remaining = RECALIBRATION_COOLDOWN_MS - (current_time - m_last_recalibration_time); ESP_LOGW(TAG, "Recalibration SKIPPED - cooldown active"); ESP_LOGW(TAG, "Time remaining: %lu ms (%lu seconds)", time_remaining, time_remaining / 1000); } } else { ESP_LOGE(TAG, "No fallback networks visible - all networks may be down"); } ESP_LOGE(TAG, "===== CONNECTION FAILED ====="); ESP_LOGE(TAG, "Cannot connect to any network (provisioned or fallback)"); //dumpSystemDiagnostics("CONNECTION_FAILED_FINAL"); return WIFI_STATUS::NOT_PROVISIONED; } /// @brief Scans all visible ssid's and picks known ssid with highest rssi that is not ignored. /// @return wifi index in Settings int Wifi::scan() { ESP_LOGI(TAG, "Scanning wifi networks..."); int num_networks = WiFi.scanNetworks(false, false, false, 0); ESP_LOGI(TAG, "found %d networks", num_networks); int rssi = -500; int selected_index = -1; // crossref scanned and saved networks for(int n = 0; n < num_networks; n++) { for(int p = 0; p < SETTINGS.wifi.num; p++) { if(strcmp(SETTINGS.wifi.entry[p].ssid, WiFi.SSID(n).c_str()) == 0) { // found saved network ESP_LOGI(TAG, "Found provisioned network '%s' with RSSI %d dBm", SETTINGS.wifi.entry[p].ssid, WiFi.RSSI(n)); if(WiFi.RSSI(n) > rssi && m_ignored[p] == 0) { rssi = WiFi.RSSI(n); selected_index = p; } } } } if(selected_index >= 0) ESP_LOGI(TAG, "Chosen network '%s'", SETTINGS.wifi.entry[selected_index].ssid); else ESP_LOGI(TAG, "No suitable networks found at this time"); return selected_index; }