WiFiManager: WiFi config does not persist after multiple failed connection attempts
Hi Guys,
Firstly, I’m a big fan of this library, thanks @tzapu and @kentaylor
I’m currently running the @kentaylor version of the manager, but I believe this issue is relevant for @tzapu version too.
I’ve found that the WiFi config does not persist across multiple restarts. That is, WiFi.SSID() returns nothing after a couple of failed connection attempts/timeouts and hence gets into a state where it will never connect to the last known WiFi and needs to be manually reconfigured. Note that this can also be observed by looking at the output from WiFi.printDiag(Serial); and turning off the AP you are trying to connect to, restart x2.
I have tried a few things to get this going in a simple way such as calling WiFi.persistent(true); and ensuring WiFi.disconnect(true); (which clears settings) is not run, but none of these things seem to have any effect.
So, in my efforts to get this going, I’ve essentially implemented my own SSID and Password persist code and thought I’d share.
The code below are extracts from my working code to show just essential functions.
Firstly I modified the WiFiManager function startConfigPortal to allow the caller to optionally specify a Station SSID and Password to be used only if the timeout is reached (does not run if normal connect occurs).
WiFiManager.h:
boolean startConfigPortal(char const *apName, char const *apPassword = NULL, char const *stnSSIDDefault = NULL, char const *stnPasswordDefault = NULL);
And added this into startConfigPortal just where it drops out from the while loop.
WiFiManager.cpp
if (_configPortalTimeout) {
DEBUG_WM(F("Timout... try saved credentials.") );
// using user-provided _ssid, _pass in place of system-stored ssid and pass
if (connectWifi(stnSSIDDefault, stnPasswordDefault) != WL_CONNECTED) {
DEBUG_WM(F("Failed to connect.") );
WiFi.mode(WIFI_AP); // Dual mode becomes flaky if not connected to a WiFi network.
// I think this might be because too much of the processor is being utilised
//trying to connect to the network.
} else {
//notify that configuration has changed and any optional parameters should be saved
if (_savecallback != NULL) {
//todo: check if any custom parameters actually exist, and check if they really changed maybe
_savecallback();
}
//break;
}
}
Then, I added the following to my module (but maybe this could be encapsulated in the WiFiManager?
#includes ...
#define EEPROM_size 512 // EEPROM map for persisting strings (need null termination, so 20 char string = 21 bytes)
#define EEPROM_PROGRAMMED1 0
#define EEPROM_PROGRAMMED2 EEPROM_PROGRAMMED1 + 1
#define EEPROM_WIFISSID_start EEPROM_PROGRAMMED2 + 1
#define EEPROM_WIFISSID_len 33
#define EEPROM_WIFISSID_end EEPROM_WIFISSID_start + EEPROM_WIFISSID_len
#define EEPROM_WIFIPW_start EEPROM_WIFISSID_end + 1
#define EEPROM_WIFIPW_len 33
#define EEPROM_WIFIPW_end EEPROM_WIFIPW_start + EEPROM_WIFIPW_len
char EEPROM_WIFISSID[EEPROM_WIFISSID_len] = ""; // Data structure to hold the stuff persisted in EEPROM
String s_EEPROM_WIFISSID = "";
String s_Current_WIFISSID = "";
char EEPROM_WIFIPW[EEPROM_WIFIPW_len] = ""; // Data structure to hold the stuff persisted in EEPROM
String s_EEPROM_WIFIPW = "";
String s_Current_WIFIPW = "";
void setup() {
readEEPROM();
getWIFIConfig();
WiFiManager wifiManager;
wifiManager.startConfigPortal(APName.c_str(), APPassword.c_str(), s_EEPROM_WIFISSID.c_str(), s_EEPROM_WIFIPW.c_str() );
}
void getWIFIConfig() {
struct station_config conf;
wifi_station_get_config(&conf);
const char * ssidcstr = reinterpret_cast<const char*>(conf.ssid);
s_Current_WIFISSID = String(ssidcstr);
const char * passphrasecstr = reinterpret_cast<const char*>(conf.password);
s_Current_WIFIPW = String(passphrasecstr);
Serial.print("getWIFIConfig: ssid: [");
Serial.print(s_Current_WIFISSID);
Serial.print("] password: [");
Serial.print(s_Current_WIFIPW);
Serial.println("]");
if (s_Current_WIFISSID != "") {
Serial.println("wifiConnectionManagerKT: pre-connection check Found SSID in last wifi config, save to EEPROM...");
strlcpy(EEPROM_WIFISSID, s_Current_WIFISSID.c_str(), sizeof (EEPROM_WIFISSID) );
strlcpy(EEPROM_WIFIPW, s_Current_WIFIPW.c_str(), sizeof (EEPROM_WIFIPW) );
Serial.println("wifiConnectionManagerKT: pre-connection check Save_System_EEPROM...");
Save_System_EEPROM();
//Load_System_EEPROM(); // TESTING
} else if (s_EEPROM_WIFISSID != "") {
Serial.println("wifiConnectionManagerKT: pre-connection check found values in EEPROM but not in last WIFI config??? Try to set WiFi config from EEPROM...");
//WiFi.begin(s_EEPROM_WIFISSID.c_str(), s_EEPROM_WIFIPW.c_str() );
//WiFi.printDiag(Serial); //Remove this line if you do not want to see WiFi password printed
} else {
Serial.println("wifiConnectionManagerKT: no WIFI config found in either last config or EEPROM.");
}
}
bool Is_System_EEPROM_programmed() {
return ( (EEPROM.read(EEPROM_PROGRAMMED1) == 42) && (EEPROM.read(EEPROM_PROGRAMMED2) == 24) );
}
void Load_System_EEPROM() {
if ( (EEPROM.read(EEPROM_PROGRAMMED1) == 42) && (EEPROM.read(EEPROM_PROGRAMMED2) == 24) ) {
EEPROM_load_string( (byte *) EEPROM_WIFISSID, EEPROM_WIFISSID_start, EEPROM_WIFISSID_end);
EEPROM_load_string( (byte *) EEPROM_WIFIPW, EEPROM_WIFIPW_start, EEPROM_WIFIPW_end);
s_EEPROM_WIFISSID = String(EEPROM_WIFISSID);
Serial.print("Load_System_EEPROM: s_EEPROM_WIFISSID: ");
Serial.println(s_EEPROM_WIFISSID);
s_EEPROM_WIFIPW = String(EEPROM_WIFIPW);
Serial.print("Load_System_EEPROM: s_EEPROM_WIFIPW: ");
Serial.println(s_EEPROM_WIFIPW);
}
}
void Save_System_EEPROM() {
EEPROM_save_string( (byte *) EEPROM_WIFISSID, EEPROM_WIFISSID_start, EEPROM_WIFISSID_end);
EEPROM_save_string( (byte *) EEPROM_WIFIPW, EEPROM_WIFIPW_start, EEPROM_WIFIPW_end);
EEPROM.write(EEPROM_PROGRAMMED1, 42); // easy but hack way to see if EEPROM was initialized, must be a smarter approach
EEPROM.write(EEPROM_PROGRAMMED2, 24); // 42 24 - thanks Douglas Adams!
EEPROM.commit();
s_EEPROM_WIFISSID = String(EEPROM_WIFISSID);
Serial.print("Load_System_EEPROM: s_EEPROM_WIFISSID: ");
Serial.println(s_EEPROM_WIFISSID);
s_EEPROM_WIFIPW = String(EEPROM_WIFIPW);
Serial.print("Load_System_EEPROM: s_EEPROM_WIFIPW: ");
Serial.println(s_EEPROM_WIFIPW);
}
void EEPROM_load_string(byte string[], int str_start, int str_end) {
int i;
for (i = str_start; i < str_end; i++) {
string[i - str_start] = EEPROM.read(i);
}
}
void EEPROM_save_string(byte string[], int str_start, int str_end) {
int i;
for (i = str_start; i < str_end; i++) {
EEPROM.write(i, string[i - str_start]);
}
}
void readEEPROM() {
EEPROM.begin(EEPROM_size); //needed by the ESP lib - specify the size of EEPROM space accessible
Serial.println("readEEPROM: start...");
if (Is_System_EEPROM_programmed() ) {
Serial.println("readEEPROM: Is_System_EEPROM_programmed: YES");
Serial.println("readEEPROM: Load_System_EEPROM...");
Load_System_EEPROM();
} else {
Serial.println("readEEPROM: Is_System_EEPROM_programmed: NO");
Serial.println("readEEPROM: Save_System_EEPROM with nothing...");
Save_System_EEPROM();
}
}
About this issue
- Original URL
- State: open
- Created 8 years ago
- Comments: 47
sigh, what a damn waste of time, scannetworks calls disconnect! I thought I added debug there but I must have reverted it. Well there you go.
kens branch is unstable for me, my esp fails to connect after every boot, then flash gets wiped. There is something going on with memory, i think it has something to do with doing the scannetworks while the esp is connecting. I can reproduce with his branch, no idea why he is doing a WiFi.scanNetworks(); on constructor.
I have a feeling there is something wrong with that code, or there is another memory overflow, cause as soon as I put his branch on my board it went to crap. exceptions all over the place. Gonna try erasing flash and doing some memory dumps
I still cannot narrow down, wtf is causing it to not connect, and what is subsequently wiping config.
are you guys settings timeouts on configportal ?
wifiManager.setConfigPortalTimeout(60);
If you don’t the default it to wait for config indefinitely on connect failure.
Also consider increasing
setConnectTimeout
value also