Description
Platform
- Hardware: Wemos D1 mini
- Core Version: 2.6.3 (3d128e5)
Problem Description
The docs for WiFi.status() state
Function returns one of the following connection statuses:
WL_CONNECTED after successful connection is established
WL_NO_SSID_AVAIL in case configured SSID cannot be reached
WL_CONNECT_FAILED if password is incorrect
WL_IDLE_STATUS when Wi-Fi is in process of changing between statuses
WL_DISCONNECTED if module is not configured in station mode
The code just does a mapping from the return values of wifi_station_get_connect_status()
to Arduino constants:
wl_status_t ESP8266WiFiSTAClass::status() {
station_status_t status = wifi_station_get_connect_status();
switch(status) {
case STATION_GOT_IP:
return WL_CONNECTED;
case STATION_NO_AP_FOUND:
return WL_NO_SSID_AVAIL;
case STATION_CONNECT_FAIL:
case STATION_WRONG_PASSWORD:
return WL_CONNECT_FAILED;
case STATION_IDLE:
return WL_IDLE_STATUS;
default:
return WL_DISCONNECTED;
}
}
IMHO the documentation and the code have the following issues:
WL_NO_SSID_AVAIL
andWL_CONNECT_FAILED
From what I experienced, both states only happen with setAutoReconnect(true)
. That's mostly an issue with the underlying esp8266 sdk, but I think the docs should at least state the fact. Also, looking at the code suggests that a wrong password isn't the only possible cause though I don't know under which circumstances wifi_station_get_connect_status()
would return STATION_CONNECT_FAIL
.
WL_IDLE_STATUS
andWL_DISCONNECTED
I think the two status values are mixed up. The implementation should probably reflect the semantics of the original Arduino library, quoted below:
WL_IDLE_STATUS
: it is a temporary status assigned whenWiFi.begin()
is called and remains active until the number of attempts expires (resulting inWL_CONNECT_FAILED
) or a connection is established (resulting inWL_CONNECTED
);WL_DISCONNECTED
: assigned when disconnected from a network;
But as it is implemented now, it's excatly the other way round: WL_IDLE_STATUS
is reported before and after WiFi.begin()
resp. WiFi.disconnect()
are called and WL_DISCONNECTED
in the time between the two calls before a connection has been made:
Demo sketch
Output:
Status before WiFi.begin(): WL_IDLE_STATUS
Status while connecting: WL_DISCONNECTED
Status after connecting: WL_CONNECTED
Status after WiFi.disconnect(): WL_IDLE_STATUS
#include <ESP8266WiFi.h>
#define SSID "xxx"
#define PW "xxx"
const char *wiFiStatus() {
switch (WiFi.status()) {
case WL_IDLE_STATUS:
return "WL_IDLE_STATUS";
case WL_CONNECTED:
return "WL_CONNECTED";
case WL_DISCONNECTED:
return "WL_DISCONNECTED";
default:
return "Unhandled value";
}
}
void setup() {
Serial.begin(115200);
WiFi.persistent(false);
WiFi.setAutoConnect(false);
WiFi.disconnect();
Serial.printf("Status before WiFi.begin(): %s\n", wiFiStatus());
WiFi.begin(SSID, PW);
while (WiFi.status() != WL_CONNECTED) {
Serial.printf("Status while connecting: %s\n", wiFiStatus());
delay(5000);
}
Serial.printf("Status after connecting: %s\n", wiFiStatus());
WiFi.disconnect();
Serial.printf("Status after WiFi.disconnect(): %s\n", wiFiStatus());
}
void loop() {}
I'd be happy to prepare a PR, but I'd like to discuss the prefered solution first:
-
The obvious fix would be to swap the two symbols in the switch statement, but that would break backwards compatibilty with programs that rely on the current behaviour.
-
At very least the docs should be updated: I have the impression that for
WL_IDLE_STATUS
andWL_DISCONNECTED
they try to represent what the implementation would be if it matched the definition of the original library, so if 1. isn't an option, then the annotations for these two values should be swapped. -
The longer term goal should imho be to fix WiFi.status() to better represent the current state of the connection. That would include making
WL_NO_SSID_AVAIL
andWL_CONNECT_FAILED
work withsetAutoReconnect(false)
and maybe add the currently unsupported stateWL_CONNECTION_LOST
. i won't promise anything :), but would such a PR be considered given that it would break backwards compatibility even more?