Added WIFI auto-tune for EMP prevention
This commit is contained in:
parent
682ffb4fee
commit
cf8ddebcc6
123
main/App.cpp
123
main/App.cpp
@ -46,43 +46,57 @@ void App::init()
|
||||
|
||||
m_led = new Led(LED_PIN);
|
||||
m_wifi = new Wifi();
|
||||
|
||||
m_commandProcessor = new CommandProcessor(*this);
|
||||
|
||||
m_ble_service = new BleService(*this);
|
||||
m_ble_service->start();
|
||||
|
||||
bool needs_provision = true;
|
||||
bool first_attempt = true;
|
||||
bool connected = false;
|
||||
|
||||
#if 0
|
||||
#if 0
|
||||
ESP_LOGI(TAG, "Scanning wifi networks...");
|
||||
|
||||
int num_networks = WiFi.scanNetworks(false, false, false, 0);
|
||||
|
||||
for(int n = 0; n < num_networks; n++)
|
||||
{
|
||||
ESP_LOGI(TAG, "%s, %d", WiFi.SSID(n).c_str(), WiFi.RSSI(n));
|
||||
}
|
||||
#endif
|
||||
#endif
|
||||
|
||||
if(SETTINGS.wifi.num > 0)
|
||||
// Main connection/provisioning cycle
|
||||
while(!connected)
|
||||
{
|
||||
// try connecting
|
||||
m_led->setColor(0, 255, 0);
|
||||
needs_provision = true;
|
||||
|
||||
// Try WiFi connections (provisioned networks + fallback)
|
||||
if(SETTINGS.wifi.num > 0 || !first_attempt)
|
||||
{
|
||||
if(!first_attempt)
|
||||
{
|
||||
ESP_LOGI(TAG, "Retrying WiFi connections after provisioning timeout...");
|
||||
m_wifi->pause(false); // Resume WiFi task
|
||||
}
|
||||
else
|
||||
{
|
||||
ESP_LOGI(TAG, "Trying provisioned networks...");
|
||||
m_wifi->start();
|
||||
}
|
||||
|
||||
m_led->setColor(0, 255, 0);
|
||||
Wifi::WIFI_STATUS wifi_status = m_wifi->waitForConnection();
|
||||
ESP_LOGI(TAG, "WiFi final status: %d", (int)wifi_status);
|
||||
|
||||
if(wifi_status == Wifi::WIFI_STATUS::CONNECTED)
|
||||
{
|
||||
ESP_LOGI(TAG, "Connected to WiFi successfully");
|
||||
|
||||
// Sync time
|
||||
ESP_LOGI(TAG, "Getting local time...");
|
||||
struct tm timeinfo;
|
||||
|
||||
int tries = 5;
|
||||
while (tries--)
|
||||
{
|
||||
configTime(0, 0, "pool.ntp.org"); // needed?
|
||||
|
||||
configTime(0, 0, "pool.ntp.org");
|
||||
if(getLocalTime(&timeinfo))
|
||||
{
|
||||
ESP_LOGI(TAG, "pool.ntp.org ok");
|
||||
@ -93,45 +107,15 @@ void App::init()
|
||||
}
|
||||
|
||||
needs_provision = false;
|
||||
connected = true;
|
||||
}
|
||||
else
|
||||
{
|
||||
ESP_LOGI(TAG, "Provisioned networks failed, trying fallback...");
|
||||
// Don't pause yet - let it try the fallback
|
||||
// The modified startConnecting() will attempt CBX_IoT fallback
|
||||
// Wait a bit more for the fallback attempt
|
||||
delay(5000);
|
||||
wifi_status = m_wifi->status();
|
||||
|
||||
if(wifi_status == Wifi::WIFI_STATUS::CONNECTED)
|
||||
{
|
||||
ESP_LOGI(TAG, "Connected via fallback network");
|
||||
ESP_LOGI(TAG, "Getting local time...");
|
||||
struct tm timeinfo;
|
||||
|
||||
int tries = 5;
|
||||
while (tries--)
|
||||
{
|
||||
configTime(0, 0, "pool.ntp.org"); // needed?
|
||||
|
||||
if(getLocalTime(&timeinfo))
|
||||
{
|
||||
ESP_LOGI(TAG, "pool.ntp.org ok");
|
||||
break;
|
||||
}
|
||||
else
|
||||
ESP_LOGE(TAG, "pool.ntp.org Failed");
|
||||
}
|
||||
needs_provision = false;
|
||||
}
|
||||
else
|
||||
{
|
||||
ESP_LOGI(TAG, "Fallback also failed, entering provisioning mode");
|
||||
ESP_LOGI(TAG, "All WiFi connections failed, will enter provisioning mode");
|
||||
m_wifi->pause(true);
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
else if(first_attempt)
|
||||
{
|
||||
// No provisioned networks - try fallback directly
|
||||
ESP_LOGI(TAG, "No provisioned networks, trying fallback...");
|
||||
@ -142,14 +126,14 @@ void App::init()
|
||||
if(wifi_status == Wifi::WIFI_STATUS::CONNECTED)
|
||||
{
|
||||
ESP_LOGI(TAG, "Connected to fallback network");
|
||||
|
||||
// Sync time
|
||||
ESP_LOGI(TAG, "Getting local time...");
|
||||
struct tm timeinfo;
|
||||
|
||||
int tries = 5;
|
||||
while (tries--)
|
||||
{
|
||||
configTime(0, 0, "pool.ntp.org"); // needed?
|
||||
|
||||
configTime(0, 0, "pool.ntp.org");
|
||||
if(getLocalTime(&timeinfo))
|
||||
{
|
||||
ESP_LOGI(TAG, "pool.ntp.org ok");
|
||||
@ -158,21 +142,60 @@ void App::init()
|
||||
else
|
||||
ESP_LOGE(TAG, "pool.ntp.org Failed");
|
||||
}
|
||||
|
||||
needs_provision = false;
|
||||
connected = true;
|
||||
}
|
||||
else
|
||||
{
|
||||
ESP_LOGI(TAG, "Fallback failed, entering provisioning mode");
|
||||
ESP_LOGI(TAG, "Fallback connection failed");
|
||||
m_wifi->pause(true);
|
||||
}
|
||||
}
|
||||
if(needs_provision)
|
||||
|
||||
// Enter provisioning mode if needed
|
||||
if(needs_provision && !connected)
|
||||
{
|
||||
ESP_LOGI(TAG, "Entering provisioning mode for 10 minutes...");
|
||||
m_led->setPulse(0, 0, 255);
|
||||
|
||||
// Start provisioning mode in WiFi
|
||||
m_wifi->startProvisioning();
|
||||
|
||||
// Start the provision server
|
||||
ProvisionSoftAP provision(80);
|
||||
provision.start();
|
||||
|
||||
// Wait for either successful provisioning or timeout
|
||||
ESP_LOGI(TAG, "Waiting for provisioning (10 minute timeout)...");
|
||||
while(m_wifi->status() == Wifi::WIFI_STATUS::PROVISIONING)
|
||||
{
|
||||
if(m_wifi->isProvisioningTimedOut())
|
||||
{
|
||||
ESP_LOGW(TAG, "Provisioning timeout reached (10 minutes)");
|
||||
break;
|
||||
}
|
||||
|
||||
// You could add logic here to check if new credentials were received
|
||||
// and attempt immediate connection if so
|
||||
|
||||
delay(1000);
|
||||
}
|
||||
|
||||
// Stop provisioning
|
||||
ESP_LOGI(TAG, "Stopping provisioning mode...");
|
||||
// provision.stop(); // Add this method to ProvisionSoftAP if available
|
||||
m_wifi->stopProvisioning();
|
||||
|
||||
ESP_LOGI(TAG, "Provisioning period ended, will retry connections in 5 seconds...");
|
||||
delay(5000);
|
||||
}
|
||||
|
||||
first_attempt = false;
|
||||
}
|
||||
|
||||
ESP_LOGI(TAG, "WiFi connection established, continuing with app initialization...");
|
||||
|
||||
otaCheck();
|
||||
|
||||
// m_led->setPulse(255, 0, 255);
|
||||
|
||||
217
main/Wifi.cpp
217
main/Wifi.cpp
@ -9,6 +9,7 @@
|
||||
#include "app_config.h"
|
||||
|
||||
#include <esp_wifi.h>
|
||||
#include "esp_phy_init.h"
|
||||
|
||||
static const char *TAG = "Wifi";
|
||||
#define IGNORE_SSID_MINS 20
|
||||
@ -20,6 +21,9 @@ Wifi::Wifi()
|
||||
{
|
||||
esp_log_level_set("wifi", ESP_LOG_WARN);
|
||||
esp_log_level_set("wifi_init", ESP_LOG_INFO);
|
||||
// Add WiFi configuration here
|
||||
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
|
||||
@ -52,7 +56,12 @@ void Wifi::wifi_event(arduino_event_id_t event, arduino_event_info_t info)
|
||||
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", WiFi.disconnectReasonName(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());
|
||||
}
|
||||
}
|
||||
|
||||
@ -60,30 +69,150 @@ 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);
|
||||
|
||||
while(m_pause)
|
||||
{
|
||||
delay(100);
|
||||
}
|
||||
}
|
||||
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, "Scanning for SSID '%s' visibility...", ssid);
|
||||
|
||||
int num_networks = WiFi.scanNetworks(false, false, false, 500);
|
||||
ESP_LOGI(TAG, "Found %d networks during visibility check", 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(2000);
|
||||
}
|
||||
|
||||
|
||||
/// @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);
|
||||
@ -116,9 +245,36 @@ Wifi::WIFI_STATUS Wifi::connectTo(int index)
|
||||
}
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
@ -147,6 +303,7 @@ Wifi::WIFI_STATUS Wifi::waitForConnection()
|
||||
|
||||
/// @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()
|
||||
{
|
||||
const char* default_ssid = "CBX_IoT";
|
||||
@ -184,6 +341,7 @@ Wifi::WIFI_STATUS Wifi::connectToDefault()
|
||||
delay(1000);
|
||||
WiFi.disconnect();
|
||||
ESP_LOGW(TAG, "Failed to connect to default network, status: %d", status);
|
||||
|
||||
return WIFI_STATUS::NOT_CONNECTED;
|
||||
}
|
||||
|
||||
@ -275,6 +433,51 @@ Wifi::WIFI_STATUS Wifi::startConnecting()
|
||||
return WIFI_STATUS::CONNECTED;
|
||||
}
|
||||
|
||||
// Check if we should recalibrate for the fallback network
|
||||
ESP_LOGW(TAG, "Fallback connection failed, checking if recalibration needed...");
|
||||
|
||||
const char* default_ssid = "CBX_IoT";
|
||||
if(isSSIDVisible(default_ssid))
|
||||
{
|
||||
unsigned long current_time = millis();
|
||||
|
||||
// Allow recalibration if:
|
||||
// 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) ||
|
||||
(current_time - m_last_recalibration_time >= RECALIBRATION_COOLDOWN_MS);
|
||||
|
||||
if(cooldown_ok)
|
||||
{
|
||||
ESP_LOGW(TAG, "Fallback network '%s' visible but connection failed - performing recalibration", default_ssid);
|
||||
ESP_LOGI(TAG, "Current time: %lu, Last recalibration: %lu", current_time, m_last_recalibration_time);
|
||||
|
||||
performRadioRecalibration();
|
||||
|
||||
// Retry fallback connection after recalibration
|
||||
ESP_LOGI(TAG, "Retrying fallback connection after recalibration...");
|
||||
fallback_status = connectToDefault();
|
||||
if(fallback_status == WIFI_STATUS::CONNECTED)
|
||||
{
|
||||
ESP_LOGI(TAG, "Successfully connected to fallback after recalibration!");
|
||||
return WIFI_STATUS::CONNECTED;
|
||||
}
|
||||
else
|
||||
{
|
||||
ESP_LOGW(TAG, "Fallback still failed after recalibration");
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
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);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
ESP_LOGI(TAG, "Fallback network not visible - network may be down");
|
||||
}
|
||||
|
||||
ESP_LOGE(TAG, "Cannot connect to any network including default fallback");
|
||||
return WIFI_STATUS::NOT_PROVISIONED;
|
||||
}
|
||||
|
||||
16
main/Wifi.h
16
main/Wifi.h
@ -18,7 +18,8 @@ public:
|
||||
NOT_CONNECTED,
|
||||
PENDING,
|
||||
NOT_PROVISIONED,
|
||||
CONNECTED
|
||||
CONNECTED,
|
||||
PROVISIONING
|
||||
} WIFI_STATUS;
|
||||
|
||||
protected:
|
||||
@ -40,9 +41,16 @@ protected:
|
||||
|
||||
public:
|
||||
Wifi();
|
||||
void startProvisioning();
|
||||
void stopProvisioning();
|
||||
bool isProvisioningTimedOut();
|
||||
void resetProvisioningTimer();
|
||||
|
||||
protected:
|
||||
void wifi_event(arduino_event_id_t event, arduino_event_info_t info);
|
||||
unsigned long m_provision_start_time = 0;
|
||||
static const unsigned long PROVISION_TIMEOUT_MS = 600000; // 10 minutes
|
||||
bool m_provision_timeout = false;
|
||||
|
||||
public:
|
||||
int start();
|
||||
@ -53,6 +61,12 @@ public:
|
||||
|
||||
private:
|
||||
WIFI_STATUS connectToDefault();
|
||||
unsigned long m_last_recalibration_time = 0;
|
||||
static const unsigned long RECALIBRATION_COOLDOWN_MS = 3600000; // 1 hour
|
||||
|
||||
bool shouldRecalibrateRadio(int failed_ssid_index);
|
||||
void performRadioRecalibration();
|
||||
bool isSSIDVisible(const char* ssid);
|
||||
};
|
||||
|
||||
#endif /* __WIFI_H__ */
|
||||
Loading…
x
Reference in New Issue
Block a user