WiFiManager
WiFiManager copied to clipboard
for repair get error : No Credentials are Saved, skipping connect on esp32
when i connect to ap after restart get No Credentials are Saved, skipping connect error but with this commit repair this. and with CMakeLists.txt and component.mk file can use this component in arduino as esp-idf component in component folder
Whats the issue and or change here?
Does this add a wifi init check in wifi ssid to make sure its not garbage?
I wont merge it with the whitespace and formatting changes, feel free to fix the PR
Does this add a wifi init check in wifi ssid to make sure its not garbage?
after connect to ap after restart when run blow code :
esp_wifi_get_config(WIFI_IF_STA, &conf);
return ESP_ERR_WIFI_NOT_INIT
for me. and return No Credentials are Saved, skipping connect
. and Cannot connect to previously set AP.
other file (CMakeLists.txt and component.mk) is used went arduino as esp-idf component in ESP-IDF
Basic Infos
Hardware
WiFimanager Branch/Release: master
hash 7bdcfd
Esp8266/Esp32: ESP32 Hardware: ESP32 Devkit v1 Core Version: 2.04
Problem description
The debug output shows No Credentials are Saved, skipping connect
on ESP32:
WiFi connect...
SSID: ⸮⸮?
*wm:[1] AutoConnect
*wm:[1] No Credentials are Saved, skipping connect
*wm:[2] enableConfigPortal: FALSE, skipping
Failed. Retry in 10s...
When WiFi mode is not in WIFI_MODE_STA
, the following code in WiFiManager.cpp
function WiFi_SSID()
returns garbage (not null terminated string). In this case the message No Credentials are Saved, skipping connect
is printed:
wifi_config_t conf;
int err = esp_wifi_get_config(WIFI_IF_STA, &conf);
The returned error esp_wifi_get_config()
is currently not handled in WiFi_SSID()
.
This can happen when the AP portal was started and changes to WIFI_MODE_STA
mode at next reboot. As a result, it cannot connect to WiFi.
The suggested solution is to make sure that the ESP32 is in WIFI_MODE_STA
before reading the SSID, for example in autoconnect()
. Current workaround for the user is to use WiFi calls to connect to WiFi and not autoconnect()
.
Note: Forcing WiFi mode to WIFI_MODE_STA
in function WiFi_SSID()
in this pull request is not correct as the user can decide to use a different mode.
Testcase
Add the following testcode to a sketch to print incorrect SSID reads:
void wifiPrintStatus()
{
Serial.print(F("WiFi mode: "));
switch (WiFi.getMode()) {
case WIFI_MODE_STA:
Serial.println(F("STA"));
break;
case WIFI_MODE_AP:
Serial.println(F("AP"));
break;
case WIFI_MODE_APSTA:
Serial.println(F("APSTA"));
break;
default:
Serial.println(F("ERROR"));
}
Serial.print(F("WiFi status: "));
if (WiFi.status() == WL_CONNECTED) {
Serial.println(F("WiFi connected"));
Serial.print(F("Local IP: "));
Serial.println(WiFi.localIP());
} else {
Serial.println(F("WiFi not connected"));
}
// SSID returned string contains garbage when not in `WIFI_MODE_STA`. In this case cannot connect to WiFi via autoConnect().
wifi_config_t conf;
Serial.print(F("esp_wifi_get_config(): "));
// https://docs.espressif.com/projects/esp-idf/en/latest/esp32/api-reference/network/esp_wifi.html
Serial.println(esp_wifi_get_config(WIFI_IF_STA, &conf)); // 0 on success, else error
Serial.print(F("SSID: "));
Serial.println(String(reinterpret_cast<const char*>(conf.sta.ssid)));
}
Settings in IDE
Module: NodeMCU-32S
Additional libraries:
Sketch testcase
#include <EEPROM.h>
#include <WiFiManager.h> // https://github.com/tzapu/WiFiManager master 7bdcfd
#define LED_PIN LED_BUILTIN
#define WM_TITLE "WiFiManager"
#define WM_AP_NAME "ESP32AP"
#define WM_AP_PASSWORD "changeme"
#define WM_CONNECT_TIMEOUT 20
#define WM_AUTO_CP false
#define WM_DEBUG true
#define EEPROM_SIZE 512
#define DOUBLE_RESET_TIME_SEC 3
#define DOUBLE_RESET_EEPROM_ADDRESS 0x0100
#define DOUBLE_RESET_DETECT_FLAG_SET 0xD0D01234
#define DOUBLE_RESET_DETECT_FLAG_CLEAR 0xD0D04321
bool saveConfig = false;
bool saveParams = false;
bool doubleResetCheck = true;
bool isDoubleReset()
{
uint32_t value;
EEPROM.get(DOUBLE_RESET_EEPROM_ADDRESS, value);
Serial.print(F("Read double reset flag: "));
if (value == DOUBLE_RESET_DETECT_FLAG_SET) {
Serial.println(F("SET"));
return true;
} else if (value == DOUBLE_RESET_DETECT_FLAG_CLEAR) {
Serial.println(F("CLEAR"));
return false;
} else {
Serial.println(F("INVALID"));
return false;
}
}
void doubleResetWrite(uint32_t value)
{
uint32_t oldValue;
EEPROM.get(DOUBLE_RESET_EEPROM_ADDRESS, oldValue);
if (oldValue != value) {
Serial.print(F("Write double reset flag: "));
if (value == DOUBLE_RESET_DETECT_FLAG_SET) {
Serial.println(F("SET"));
} else if (value == DOUBLE_RESET_DETECT_FLAG_CLEAR) {
Serial.println(F("CLEAR"));
doubleResetCheck = false;
} else {
Serial.println(F("INVALID"));
return;
}
EEPROM.put(DOUBLE_RESET_EEPROM_ADDRESS, value);
EEPROM.commit();
}
}
void doubleResetLoop()
{
if (doubleResetCheck && (millis() > (DOUBLE_RESET_TIME_SEC * 1000))) {
// Clear flag
doubleResetWrite(DOUBLE_RESET_DETECT_FLAG_CLEAR);
}
}
void espRestart()
{
Serial.println(F("Restarting..."));
delay(2000);
ESP.restart();
delay(5000);
}
void saveConfigCallback ()
{
Serial.println("saveConfigCallback()");
saveConfig = true;
}
void saveParamsCallback()
{
Serial.println(F("saveParamsCallback()"));
// Save parameters when exiting config portal
saveParams = true;
}
void startWiFiConfigPortal()
{
WiFiManager wm;
// Start WiFi config portal
Serial.println(F("Starting config portal (AP)..."));
// Set debug
wm.setDebugOutput(WM_DEBUG);
// Set title config protal
wm.setTitle(WM_TITLE);
// Set config save callback
//wm.setSaveConfigCallback(saveConfigCallback);
// Set param save callback
wm.setSaveParamsCallback(saveParamsCallback);
// Always save parameters, even when WiFi connect failed
wm.setBreakAfterConfig(true);
// Automatically connect using saved credentials,
// if connection fails, it starts an access point with the specified name ( "AutoConnectAP"),
// if empty will auto generate SSID, if password is blank it will be anonymous AP (wm.autoConnect())
// then goes into a blocking loop awaiting configuration and will return success result
// Ignore false return value when aborting config portal
(void)wm.startConfigPortal(WM_AP_NAME, WM_AP_PASSWORD);
}
void wifiConnect()
{
wifi_config_t conf;
WiFiManager wm;
// Connect to WiFi
Serial.print(F("WiFi connect..."));
// Force station mode
//WiFi.mode(WIFI_STA);
esp_wifi_get_config(WIFI_IF_STA, &conf);
Serial.print("config wifiConnect() before autoConnect(): ");
Serial.println(String(reinterpret_cast<const char*>(conf.sta.ssid)));
// Set debug output
wm.setDebugOutput(WM_DEBUG);
// Disable auto start config portal on WiFi connect failure
wm.setEnableConfigPortal(WM_AUTO_CP);
// Set connect timeout
wm.setConnectTimeout(WM_CONNECT_TIMEOUT);
// Connect to WiFi access point
while (!wm.autoConnect()) {
Serial.println(F("Failed. Retry in 10s..."));
delay(10000);
Serial.print(F("WiFi connect..."));
}
esp_wifi_get_config(WIFI_IF_STA, &conf);
Serial.print("config wifiConnect() after autoConnect(): ");
Serial.println(String(reinterpret_cast<const char*>(conf.sta.ssid)));
// WiFi connected
Serial.print(F("Connected\nlocal IP: "));
Serial.println(WiFi.localIP());
}
void wifiDisconnect()
{
WiFi.mode(WIFI_OFF);
}
void setup()
{
// Initialize LED
pinMode(LED_PIN, OUTPUT);
digitalWrite(LED_PIN, HIGH);
// Initialize serial
Serial.begin(115200);
Serial.println(F("\nErriez double reset example"));
// Initialize EEPROM
if (!EEPROM.begin(EEPROM_SIZE)) {
Serial.println("EEPROM init error");
espRestart();
}
// Detect double reset
if (isDoubleReset()) {
// Clear double reset flag
doubleResetWrite(DOUBLE_RESET_DETECT_FLAG_CLEAR);
// Start AP config
startWiFiConfigPortal();
// Restart ESP
espRestart();
}
// Set double reset flag
doubleResetWrite(DOUBLE_RESET_DETECT_FLAG_SET);
// Connect to WiFi
wifiConnect();
digitalWrite(LED_PIN, LOW);
}
void loop()
{
doubleResetLoop();
if (WiFi.status() == WL_CONNECTED) {
Serial.println(F("WiFi connected"));
} else {
Serial.println(F("WiFi not connected"));
}
digitalWrite(LED_PIN, HIGH);
delay(2000);
digitalWrite(LED_PIN, LOW);
delay(2000);
}
Does anyone know why the WiFi mode is forced to WIFI_OFF
in autoConnect()
for ESP32 when a hostname is set? This is the root cause of the problem: https://github.com/tzapu/WiFiManager/blob/7bdcfd501eb18d6c48be37f8608de775e44a90ae/WiFiManager.cpp#L288
It does not make sense to call WiFi.mode(WIFI_STA);
before autoConnect()
as the WiFi is always disabled in autoConnect()
and not restored to STA mode. Reading SSID will fail.
Disabling WiFi also slows down the WiFi connection speed compared with:
void wifiConnectFast()
{
// Test case by using `WiFi` is faster than wm.autoConnect() as it disables WiFi first.
Serial.println(F("Connecting to WiFi"));
WiFi.mode(WIFI_STA);
WiFi.persistent(true);
WiFi.begin();
while (WiFi.status() != WL_CONNECTED) {
delay(100);
}
Serial.println(WiFi.localIP());
}
Bug in: https://github.com/tzapu/WiFiManager/blob/7bdcfd501eb18d6c48be37f8608de775e44a90ae/WiFiManager.cpp#L285
Function setHostname()
is not called (no hostname configured in STA mode) and always disables WiFi in autoConnect()
as the String hostname if statement is incorrect:
Testcase:
void setup()
{
// Initialize serial
Serial.begin(115200);
Serial.println(F("\nErriez String example"));
// Create string object
String _hostname;
// Print hostname (which is empty)
Serial.println(F("Hostname: ");
Serial.println(_hostname);
// Perform incorrect comparison
if (_hostname) {
// Always true
Serial.println("true");
} else {
Serial.println("false");
}
Bugfix:
-if (_hostname) {
+if (!_hostname.isEmpty()) {
or:
-if (_hostname) {
+if (_hostname != "") {
@tablatronix https://github.com/tzapu/WiFiManager/commit/94bb90322bf85de2c9ec592858f20643161bc11f
Issue #1490 with pull request #1491 replaces this PR.
Sorry I haven't fixed this yet, I discover major bugs in esp32 while working on this and after the hostname fix that sidetracked me
I removed this check entirely, it was intended to speed up connections, until I find a better way to init wifi It will remain off. and the method to check wont work.
I am adding a passive check using events for init checking then will look into startup speed