Better handling of fallback wifi networks
This commit is contained in:
parent
cf8ddebcc6
commit
0b2fb3feea
44
.vscode/c_cpp_properties.json
vendored
44
.vscode/c_cpp_properties.json
vendored
@ -1,23 +1,23 @@
|
|||||||
{
|
{
|
||||||
"configurations": [
|
"configurations": [
|
||||||
{
|
{
|
||||||
"name": "ESP-IDF",
|
"name": "ESP-IDF",
|
||||||
"cStandard": "c11",
|
"cStandard": "c11",
|
||||||
"cppStandard": "c++17",
|
"cppStandard": "c++17",
|
||||||
"compileCommands": "${workspaceFolder}/build/compile_commands.json",
|
"compileCommands": "${workspaceFolder}/build/compile_commands.json",
|
||||||
"includePath": [
|
"includePath": [
|
||||||
"~/esp/esp-idf/components/**",
|
"~/esp/esp-idf/components/**",
|
||||||
"~/esp/esp-idf/components/arduino/libraries/**",
|
"~/esp/esp-idf/components/arduino/libraries/**",
|
||||||
"${workspaceFolder}/**"
|
"${workspaceFolder}/**"
|
||||||
],
|
],
|
||||||
"browse": {
|
"browse": {
|
||||||
"path": [
|
"path": [
|
||||||
"~/esp/esp-idf/components",
|
"~/esp/esp-idf/components",
|
||||||
"${workspaceFolder}"
|
"${workspaceFolder}"
|
||||||
],
|
],
|
||||||
"limitSymbolsToIncludedHeaders": false
|
"limitSymbolsToIncludedHeaders": false
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"version": 4
|
"version": 4
|
||||||
}
|
}
|
||||||
158
.vscode/settings.json
vendored
158
.vscode/settings.json
vendored
@ -1,79 +1,79 @@
|
|||||||
{
|
{
|
||||||
"files.associations": {
|
"files.associations": {
|
||||||
"*.ipp": "cpp",
|
"*.ipp": "cpp",
|
||||||
"*.tcc": "cpp",
|
"*.tcc": "cpp",
|
||||||
"fstream": "cpp",
|
"fstream": "cpp",
|
||||||
"array": "cpp",
|
"array": "cpp",
|
||||||
"string": "cpp",
|
"string": "cpp",
|
||||||
"string_view": "cpp",
|
"string_view": "cpp",
|
||||||
"regex": "cpp",
|
"regex": "cpp",
|
||||||
"bitset": "cpp",
|
"bitset": "cpp",
|
||||||
"memory": "cpp",
|
"memory": "cpp",
|
||||||
"random": "cpp",
|
"random": "cpp",
|
||||||
"future": "cpp",
|
"future": "cpp",
|
||||||
"optional": "cpp",
|
"optional": "cpp",
|
||||||
"new": "cpp",
|
"new": "cpp",
|
||||||
"condition_variable": "cpp",
|
"condition_variable": "cpp",
|
||||||
"algorithm": "cpp",
|
"algorithm": "cpp",
|
||||||
"streambuf": "cpp",
|
"streambuf": "cpp",
|
||||||
"numeric": "cpp",
|
"numeric": "cpp",
|
||||||
"functional": "cpp",
|
"functional": "cpp",
|
||||||
"deque": "cpp",
|
"deque": "cpp",
|
||||||
"list": "cpp",
|
"list": "cpp",
|
||||||
"vector": "cpp",
|
"vector": "cpp",
|
||||||
"unordered_map": "cpp",
|
"unordered_map": "cpp",
|
||||||
"istream": "cpp",
|
"istream": "cpp",
|
||||||
"ostream": "cpp",
|
"ostream": "cpp",
|
||||||
"sstream": "cpp",
|
"sstream": "cpp",
|
||||||
"unordered_set": "cpp",
|
"unordered_set": "cpp",
|
||||||
"system_error": "cpp",
|
"system_error": "cpp",
|
||||||
"atomic": "cpp",
|
"atomic": "cpp",
|
||||||
"strstream": "cpp",
|
"strstream": "cpp",
|
||||||
"cctype": "cpp",
|
"cctype": "cpp",
|
||||||
"chrono": "cpp",
|
"chrono": "cpp",
|
||||||
"clocale": "cpp",
|
"clocale": "cpp",
|
||||||
"cmath": "cpp",
|
"cmath": "cpp",
|
||||||
"codecvt": "cpp",
|
"codecvt": "cpp",
|
||||||
"csignal": "cpp",
|
"csignal": "cpp",
|
||||||
"cstdarg": "cpp",
|
"cstdarg": "cpp",
|
||||||
"cstddef": "cpp",
|
"cstddef": "cpp",
|
||||||
"cstdint": "cpp",
|
"cstdint": "cpp",
|
||||||
"cstdio": "cpp",
|
"cstdio": "cpp",
|
||||||
"cstdlib": "cpp",
|
"cstdlib": "cpp",
|
||||||
"cstring": "cpp",
|
"cstring": "cpp",
|
||||||
"ctime": "cpp",
|
"ctime": "cpp",
|
||||||
"cwchar": "cpp",
|
"cwchar": "cpp",
|
||||||
"cwctype": "cpp",
|
"cwctype": "cpp",
|
||||||
"exception": "cpp",
|
"exception": "cpp",
|
||||||
"iterator": "cpp",
|
"iterator": "cpp",
|
||||||
"map": "cpp",
|
"map": "cpp",
|
||||||
"memory_resource": "cpp",
|
"memory_resource": "cpp",
|
||||||
"ratio": "cpp",
|
"ratio": "cpp",
|
||||||
"set": "cpp",
|
"set": "cpp",
|
||||||
"tuple": "cpp",
|
"tuple": "cpp",
|
||||||
"type_traits": "cpp",
|
"type_traits": "cpp",
|
||||||
"utility": "cpp",
|
"utility": "cpp",
|
||||||
"initializer_list": "cpp",
|
"initializer_list": "cpp",
|
||||||
"iomanip": "cpp",
|
"iomanip": "cpp",
|
||||||
"iosfwd": "cpp",
|
"iosfwd": "cpp",
|
||||||
"iostream": "cpp",
|
"iostream": "cpp",
|
||||||
"limits": "cpp",
|
"limits": "cpp",
|
||||||
"mutex": "cpp",
|
"mutex": "cpp",
|
||||||
"stdexcept": "cpp",
|
"stdexcept": "cpp",
|
||||||
"thread": "cpp",
|
"thread": "cpp",
|
||||||
"cinttypes": "cpp",
|
"cinttypes": "cpp",
|
||||||
"typeinfo": "cpp",
|
"typeinfo": "cpp",
|
||||||
"bit": "cpp",
|
"bit": "cpp",
|
||||||
"compare": "cpp",
|
"compare": "cpp",
|
||||||
"concepts": "cpp",
|
"concepts": "cpp",
|
||||||
"netfwd": "cpp",
|
"netfwd": "cpp",
|
||||||
"numbers": "cpp",
|
"numbers": "cpp",
|
||||||
"semaphore": "cpp",
|
"semaphore": "cpp",
|
||||||
"stop_token": "cpp",
|
"stop_token": "cpp",
|
||||||
"*.inc": "cpp"
|
"*.inc": "cpp"
|
||||||
},
|
},
|
||||||
|
|
||||||
"cmake.configureOnOpen": false,
|
"cmake.configureOnOpen": false,
|
||||||
"C_Cpp.dimInactiveRegions": true,
|
"C_Cpp.dimInactiveRegions": true,
|
||||||
"editor.autoIndent": "full",
|
"editor.autoIndent": "full",
|
||||||
}
|
}
|
||||||
|
|||||||
@ -44,6 +44,9 @@ void App::init()
|
|||||||
ESP_LOGI(TAG, "mqtt_id: %s, wifi mac: %02x:%02x:%02x:%02x:%02x:%02x well_id: %u, group_id: %u", SETTINGS.mqtt.device_id,
|
ESP_LOGI(TAG, "mqtt_id: %s, wifi mac: %02x:%02x:%02x:%02x:%02x:%02x well_id: %u, group_id: %u", SETTINGS.mqtt.device_id,
|
||||||
mac[0], mac[1], mac[2], mac[3], mac[4], mac[5], SETTINGS.device.tata_id, SETTINGS.device.group_id);
|
mac[0], mac[1], mac[2], mac[3], mac[4], mac[5], SETTINGS.device.tata_id, SETTINGS.device.group_id);
|
||||||
|
|
||||||
|
ESP_LOGW(TAG, "Ver:1.00");
|
||||||
|
|
||||||
|
|
||||||
m_led = new Led(LED_PIN);
|
m_led = new Led(LED_PIN);
|
||||||
m_wifi = new Wifi();
|
m_wifi = new Wifi();
|
||||||
m_commandProcessor = new CommandProcessor(*this);
|
m_commandProcessor = new CommandProcessor(*this);
|
||||||
|
|||||||
459
main/Wifi.cpp
459
main/Wifi.cpp
@ -10,18 +10,102 @@
|
|||||||
|
|
||||||
#include <esp_wifi.h>
|
#include <esp_wifi.h>
|
||||||
#include "esp_phy_init.h"
|
#include "esp_phy_init.h"
|
||||||
|
#include "esp_ota_ops.h"
|
||||||
|
|
||||||
static const char *TAG = "Wifi";
|
static const char *TAG = "Wifi";
|
||||||
#define IGNORE_SSID_MINS 20
|
#define IGNORE_SSID_MINS 20
|
||||||
|
|
||||||
using namespace std::placeholders;
|
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()
|
Wifi::Wifi()
|
||||||
{
|
{
|
||||||
esp_log_level_set("wifi", ESP_LOG_WARN);
|
esp_log_level_set("wifi", ESP_LOG_WARN);
|
||||||
esp_log_level_set("wifi_init", ESP_LOG_INFO);
|
esp_log_level_set("wifi_init", ESP_LOG_INFO);
|
||||||
// Add WiFi configuration here
|
// Add WiFi configuration here
|
||||||
|
if(shouldPerformBootupCalibration()) {
|
||||||
|
performBootupCalibration();
|
||||||
|
}
|
||||||
esp_wifi_set_country_code("US", true); // Or your country code
|
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.setSleep(false); // Disable power saving if BT is enabled, do not do this!
|
||||||
|
|
||||||
@ -169,11 +253,24 @@ bool Wifi::shouldRecalibrateRadio(int failed_ssid_index)
|
|||||||
|
|
||||||
bool Wifi::isSSIDVisible(const char* ssid)
|
bool Wifi::isSSIDVisible(const char* ssid)
|
||||||
{
|
{
|
||||||
ESP_LOGI(TAG, "Scanning for SSID '%s' visibility...", ssid);
|
ESP_LOGI(TAG, "=== Starting SSID visibility scan for '%s' ===", ssid);
|
||||||
|
|
||||||
int num_networks = WiFi.scanNetworks(false, false, false, 500);
|
wl_status_t status = WiFi.status();
|
||||||
ESP_LOGI(TAG, "Found %d networks during visibility check", num_networks);
|
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++)
|
for(int n = 0; n < num_networks; n++)
|
||||||
{
|
{
|
||||||
if(strcmp(WiFi.SSID(n).c_str(), ssid) == 0)
|
if(strcmp(WiFi.SSID(n).c_str(), ssid) == 0)
|
||||||
@ -205,7 +302,7 @@ void Wifi::performRadioRecalibration()
|
|||||||
ESP_LOGW(TAG, "Radio recalibration completed - WiFi will reinitialize on next connection attempt");
|
ESP_LOGW(TAG, "Radio recalibration completed - WiFi will reinitialize on next connection attempt");
|
||||||
|
|
||||||
// Brief delay to let the radio settle
|
// Brief delay to let the radio settle
|
||||||
delay(2000);
|
delay(3000);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -306,16 +403,33 @@ Wifi::WIFI_STATUS Wifi::waitForConnection()
|
|||||||
// Also modify startConnecting to handle recalibration for fallback network
|
// Also modify startConnecting to handle recalibration for fallback network
|
||||||
Wifi::WIFI_STATUS Wifi::connectToDefault()
|
Wifi::WIFI_STATUS Wifi::connectToDefault()
|
||||||
{
|
{
|
||||||
const char* default_ssid = "CBX_IoT";
|
// Try each fallback network in sequence using class members
|
||||||
const char* default_password = "69696969";
|
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 local_IP(0, 0, 0, 0);
|
||||||
IPAddress gateway(0, 0, 0, 0);
|
IPAddress gateway(0, 0, 0, 0);
|
||||||
IPAddress subnet(SETTINGS.wifi.subnet_mask);
|
IPAddress subnet(SETTINGS.wifi.subnet_mask);
|
||||||
IPAddress primaryDNS(SETTINGS.wifi.dns_primary);
|
IPAddress primaryDNS(SETTINGS.wifi.dns_primary);
|
||||||
IPAddress secondaryDNS(SETTINGS.wifi.dns_secondary);
|
IPAddress secondaryDNS(SETTINGS.wifi.dns_secondary);
|
||||||
|
|
||||||
ESP_LOGI(TAG, "Connecting to default network %s...", default_ssid);
|
ESP_LOGI(TAG, "Connecting to fallback network %s...", ssid);
|
||||||
|
|
||||||
delay(1000);
|
delay(1000);
|
||||||
|
|
||||||
@ -329,156 +443,285 @@ Wifi::WIFI_STATUS Wifi::connectToDefault()
|
|||||||
WiFi.mode(WIFI_STA);
|
WiFi.mode(WIFI_STA);
|
||||||
WiFi.config(local_IP, gateway, subnet, primaryDNS, secondaryDNS);
|
WiFi.config(local_IP, gateway, subnet, primaryDNS, secondaryDNS);
|
||||||
|
|
||||||
WiFi.begin(default_ssid, default_password);
|
WiFi.begin(ssid, password);
|
||||||
int status = WiFi.waitForConnectResult(10000);
|
int status = WiFi.waitForConnectResult(10000);
|
||||||
|
|
||||||
if(status == WL_CONNECTED)
|
if(status == WL_CONNECTED)
|
||||||
{
|
{
|
||||||
ESP_LOGI(TAG, "Connected to default network");
|
ESP_LOGI(TAG, "Connected to fallback network %s", ssid);
|
||||||
return WIFI_STATUS::CONNECTED;
|
return WIFI_STATUS::CONNECTED;
|
||||||
}
|
}
|
||||||
|
|
||||||
delay(1000);
|
delay(1000);
|
||||||
WiFi.disconnect();
|
WiFi.disconnect();
|
||||||
ESP_LOGW(TAG, "Failed to connect to default network, status: %d", status);
|
ESP_LOGW(TAG, "Failed to connect to fallback network %s, status: %d", ssid, status);
|
||||||
|
|
||||||
return WIFI_STATUS::NOT_CONNECTED;
|
return WIFI_STATUS::NOT_CONNECTED;
|
||||||
}
|
}
|
||||||
|
|
||||||
/// @brief Connects to wifi. Returns immediately if already connected.
|
/// @brief Connects to wifi. Returns immediately if already connected.
|
||||||
/// @return WH_OK | WH_ERR_WIFI_NOT_PROVISIONED
|
/// @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()
|
Wifi::WIFI_STATUS Wifi::startConnecting()
|
||||||
{
|
{
|
||||||
if(WiFi.isConnected())
|
ESP_LOGW(TAG, "===== START CONNECTING =====");
|
||||||
return WIFI_STATUS::CONNECTED;
|
|
||||||
|
// Diagnostic logging of saved networks
|
||||||
// Try provisioned networks first if any exist
|
ESP_LOGW(TAG, "Provisioned networks: %d", SETTINGS.wifi.num);
|
||||||
if(SETTINGS.wifi.num > 0)
|
for(int i = 0; i < SETTINGS.wifi.num; i++) {
|
||||||
{
|
ESP_LOGW(TAG, "[%d] SSID: '%s'", i, SETTINGS.wifi.entry[i].ssid);
|
||||||
// if only one network is provisioned
|
}
|
||||||
if(SETTINGS.wifi.num == 1)
|
|
||||||
{
|
if(::WiFi.isConnected()) {
|
||||||
SETTINGS.wifi.selected = 0;
|
ESP_LOGW(TAG, "Already connected");
|
||||||
for(int n = 0; n < 7; n++)
|
|
||||||
{
|
|
||||||
if(connectTo(SETTINGS.wifi.selected) == WIFI_STATUS::CONNECTED)
|
|
||||||
return WIFI_STATUS::CONNECTED;
|
|
||||||
|
|
||||||
WiFi.disconnect();
|
|
||||||
}
|
|
||||||
|
|
||||||
ESP_LOGW(TAG, "Failed to connect to provisioned network");
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
// multiple networks are provisioned. Use either specific network or scan for highest rssi
|
|
||||||
memset(m_ignored, 0, SETTINGS_NUM_WIFI_ENTRIES);
|
|
||||||
int ssid_ix = SETTINGS.wifi.selected;
|
|
||||||
|
|
||||||
if(SETTINGS.wifi.always_scan_before_connect || SETTINGS.wifi.selected >= SETTINGS.wifi.num)
|
|
||||||
ssid_ix = scan();
|
|
||||||
|
|
||||||
if(ssid_ix >= 0)
|
|
||||||
{
|
|
||||||
if(connectTo(ssid_ix) == WIFI_STATUS::CONNECTED)
|
|
||||||
{
|
|
||||||
SETTINGS.wifi.selected = ssid_ix;
|
|
||||||
return WIFI_STATUS::CONNECTED;
|
|
||||||
}
|
|
||||||
|
|
||||||
// didn't work. go through them all giving priority to one with highest rssi
|
|
||||||
m_ignored[ssid_ix] = IGNORE_SSID_MINS;
|
|
||||||
|
|
||||||
do
|
|
||||||
{
|
|
||||||
ssid_ix = scan();
|
|
||||||
if(ssid_ix >= 0)
|
|
||||||
{
|
|
||||||
if(connectTo(ssid_ix) == WIFI_STATUS::CONNECTED)
|
|
||||||
return WIFI_STATUS::CONNECTED;
|
|
||||||
else
|
|
||||||
m_ignored[ssid_ix] = IGNORE_SSID_MINS;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
break;
|
|
||||||
|
|
||||||
} while(true);
|
|
||||||
|
|
||||||
// that failed too, try them all again round-robin
|
|
||||||
for(int m = 0; m < 3; m++)
|
|
||||||
{
|
|
||||||
for(int n = 0; n < SETTINGS.wifi.num; n++)
|
|
||||||
{
|
|
||||||
if(connectTo(n) == WIFI_STATUS::CONNECTED)
|
|
||||||
return WIFI_STATUS::CONNECTED;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
ESP_LOGW(TAG, "Failed to connect to any provisioned networks");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
ESP_LOGW(TAG, "No networks provisioned");
|
|
||||||
}
|
|
||||||
|
|
||||||
// Fallback: Try default WiFi network CBX_IoT
|
|
||||||
ESP_LOGI(TAG, "Attempting fallback connection to default network CBX_IoT...");
|
|
||||||
|
|
||||||
WIFI_STATUS fallback_status = connectToDefault();
|
|
||||||
if(fallback_status == WIFI_STATUS::CONNECTED)
|
|
||||||
{
|
|
||||||
ESP_LOGI(TAG, "Successfully connected to default network");
|
|
||||||
return WIFI_STATUS::CONNECTED;
|
return WIFI_STATUS::CONNECTED;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Check if we should recalibrate for the fallback network
|
// Try provisioned networks first if any exist
|
||||||
ESP_LOGW(TAG, "Fallback connection failed, checking if recalibration needed...");
|
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 =====");
|
||||||
|
|
||||||
const char* default_ssid = "CBX_IoT";
|
WIFI_STATUS fallback_status = connectToDefault();
|
||||||
if(isSSIDVisible(default_ssid))
|
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();
|
unsigned long current_time = millis();
|
||||||
|
|
||||||
// Allow recalibration if:
|
// Allow recalibration if never done or cooldown expired
|
||||||
// 1. Never recalibrated before (m_last_recalibration_time == 0)
|
|
||||||
// 2. Or enough time has passed since last recalibration
|
|
||||||
bool cooldown_ok = (m_last_recalibration_time == 0) ||
|
bool cooldown_ok = (m_last_recalibration_time == 0) ||
|
||||||
(current_time - m_last_recalibration_time >= RECALIBRATION_COOLDOWN_MS);
|
(current_time - m_last_recalibration_time >= RECALIBRATION_COOLDOWN_MS);
|
||||||
|
|
||||||
if(cooldown_ok)
|
if(cooldown_ok)
|
||||||
{
|
{
|
||||||
ESP_LOGW(TAG, "Fallback network '%s' visible but connection failed - performing recalibration", default_ssid);
|
ESP_LOGW(TAG, "*** RECALIBRATION TRIGGERED ***");
|
||||||
ESP_LOGI(TAG, "Current time: %lu, Last recalibration: %lu", current_time, m_last_recalibration_time);
|
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();
|
performRadioRecalibration();
|
||||||
|
|
||||||
// Retry fallback connection after recalibration
|
// Retry all fallback networks after recalibration
|
||||||
ESP_LOGI(TAG, "Retrying fallback connection after recalibration...");
|
ESP_LOGW(TAG, "===== RETRYING AFTER RECALIBRATION =====");
|
||||||
fallback_status = connectToDefault();
|
fallback_status = connectToDefault();
|
||||||
if(fallback_status == WIFI_STATUS::CONNECTED)
|
if(fallback_status == WIFI_STATUS::CONNECTED)
|
||||||
{
|
{
|
||||||
ESP_LOGI(TAG, "Successfully connected to fallback after recalibration!");
|
ESP_LOGW(TAG, "*** SUCCESS *** Connected after recalibration!");
|
||||||
return WIFI_STATUS::CONNECTED;
|
return WIFI_STATUS::CONNECTED;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
ESP_LOGW(TAG, "Fallback still failed after recalibration");
|
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
|
else
|
||||||
{
|
{
|
||||||
unsigned long time_remaining = RECALIBRATION_COOLDOWN_MS - (current_time - m_last_recalibration_time);
|
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);
|
ESP_LOGW(TAG, "Recalibration SKIPPED - cooldown active");
|
||||||
|
ESP_LOGW(TAG, "Time remaining: %lu ms (%lu seconds)",
|
||||||
|
time_remaining, time_remaining / 1000);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
ESP_LOGI(TAG, "Fallback network not visible - network may be down");
|
ESP_LOGE(TAG, "No fallback networks visible - all networks may be down");
|
||||||
}
|
}
|
||||||
|
|
||||||
ESP_LOGE(TAG, "Cannot connect to any network including default fallback");
|
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;
|
return WIFI_STATUS::NOT_PROVISIONED;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -488,7 +731,7 @@ int Wifi::scan()
|
|||||||
{
|
{
|
||||||
ESP_LOGI(TAG, "Scanning wifi networks...");
|
ESP_LOGI(TAG, "Scanning wifi networks...");
|
||||||
|
|
||||||
int num_networks = WiFi.scanNetworks(false, false, false, 500);
|
int num_networks = WiFi.scanNetworks(false, false, false, 0);
|
||||||
ESP_LOGI(TAG, "found %d networks", num_networks);
|
ESP_LOGI(TAG, "found %d networks", num_networks);
|
||||||
|
|
||||||
int rssi = -500;
|
int rssi = -500;
|
||||||
|
|||||||
12
main/Wifi.h
12
main/Wifi.h
@ -45,6 +45,8 @@ public:
|
|||||||
void stopProvisioning();
|
void stopProvisioning();
|
||||||
bool isProvisioningTimedOut();
|
bool isProvisioningTimedOut();
|
||||||
void resetProvisioningTimer();
|
void resetProvisioningTimer();
|
||||||
|
void performBootupCalibration();
|
||||||
|
bool shouldPerformBootupCalibration();
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
void wifi_event(arduino_event_id_t event, arduino_event_info_t info);
|
void wifi_event(arduino_event_id_t event, arduino_event_info_t info);
|
||||||
@ -60,10 +62,16 @@ public:
|
|||||||
WIFI_STATUS waitForConnection();
|
WIFI_STATUS waitForConnection();
|
||||||
|
|
||||||
private:
|
private:
|
||||||
WIFI_STATUS connectToDefault();
|
// Single source of truth for fallback networks
|
||||||
|
static const char* FALLBACK_NETWORKS[];
|
||||||
|
static const char* FALLBACK_PASSWORDS[];
|
||||||
|
static const int NUM_FALLBACK_NETWORKS;
|
||||||
|
|
||||||
|
WIFI_STATUS connectToDefault();
|
||||||
|
WIFI_STATUS connectToFallbackNetwork(const char* ssid, const char* password);
|
||||||
unsigned long m_last_recalibration_time = 0;
|
unsigned long m_last_recalibration_time = 0;
|
||||||
static const unsigned long RECALIBRATION_COOLDOWN_MS = 3600000; // 1 hour
|
static const unsigned long RECALIBRATION_COOLDOWN_MS = 3600000; // 1 hour
|
||||||
|
bool m_bootup_calibration_done = false;
|
||||||
bool shouldRecalibrateRadio(int failed_ssid_index);
|
bool shouldRecalibrateRadio(int failed_ssid_index);
|
||||||
void performRadioRecalibration();
|
void performRadioRecalibration();
|
||||||
bool isSSIDVisible(const char* ssid);
|
bool isSSIDVisible(const char* ssid);
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user