sta_if.status() unreliable
Port, board and/or hardware
esp32 port
MicroPython version
MicroPython v1.25.0 on 2025-04-15; Generic ESP32 module with ESP32
Reproduction
import network, time
from sys import print_exception
REAL_SSID = 'MyNetwork'
REAL_PASS = 'MyPassword'
NETWORKS = (('FakeNetwork1', '12345678'), (REAL_SSID, REAL_PASS), ('FakeNetwork2', '12345678'), ('FakeNetwork3', '12345678'))
STATUS_LOOKUP = {
network.STAT_ASSOC_FAIL: 'ASSOC_FAIL',
network.STAT_BEACON_TIMEOUT: 'BEACON_TIMEOUT',
network.STAT_CONNECTING: 'CONNECTING',
network.STAT_CONNECT_FAIL: 'CONNECT_FAIL',
network.STAT_GOT_IP: 'GOT_IP',
network.STAT_HANDSHAKE_TIMEOUT: 'HANDSHAKE_TIMEOUT',
network.STAT_IDLE: 'IDLE',
network.STAT_NO_AP_FOUND: 'NO_AP_FOUND',
network.STAT_NO_AP_FOUND_IN_AUTHMODE_THRESHOLD: 'NO_AP_FOUND_IN_AUTHMODE_THRESHOLD',
network.STAT_NO_AP_FOUND_IN_RSSI_THRESHOLD: 'NO_AP_FOUND_IN_RSSI_THRESHOLD',
network.STAT_NO_AP_FOUND_W_COMPATIBLE_SECURITY: 'NO_AP_FOUND_W_COMPATIBLE_SECURITY',
network.STAT_WRONG_PASSWORD: 'WRONG_PASSWORD',
}
def print_status_loop(interface, duration):
old_status = None
t0 = time.ticks_ms()
while True:
tt = time.ticks_diff(time.ticks_ms(), t0)
if tt > duration * 1000:
break
status = interface.status()
if old_status != status:
old_status = status
print(tt, STATUS_LOOKUP.get(status, str(status)))
sta_if = network.WLAN(network.STA_IF)
sta_if.active(True)
for network in NETWORKS:
print( '======== disconnect()')
try: sta_if.disconnect()
except Exception as e: print_exception(e)
print_status_loop(sta_if, 5)
print(f'======== connect({network[0]}, ...)')
sta_if.connect(*network)
print_status_loop(sta_if, 5)
Expected behaviour
I would expect the connect() call to reliably initialise the status to something (CONNECTING?)
I would expect the disconnect() call to reliably set the status to something (IDLE?)
Observed behaviour
connect() only works as I expect if the previous connect() call eventually GOT_IP, but not otherwise.
disconnect() almost works as I expect if the previous connect() call eventually GOT_IP, but not otherwise.
======== disconnect()
0 IDLE
======== connect(FakeNetwork1, ...)
0 CONNECTING
2417 NO_AP_FOUND
======== disconnect()
0 NO_AP_FOUND
======== connect(MyNetwork, ...)
0 NO_AP_FOUND
1398 GOT_IP
======== disconnect()
0 GOT_IP
1 IDLE
======== connect(FakeNetwork2, ...)
0 IDLE
2417 NO_AP_FOUND
======== disconnect()
0 NO_AP_FOUND
======== connect(FakeNetwork3, ...)
0 NO_AP_FOUND
Additional Information
I would like to loop through a bunch of pre-configured wifi networks to find one that works (e.g. for a portable device).
Unfortunately if a .connect() call doesn't eventually connect (the usual case in my scenario), then polling .status() becomes unreliable and I have to guess an appropriate timer and wait for .isconnected() for each ssid/pass, significantly slowing down startup if the working network is down the list.
Code of Conduct
Yes, I agree
Implement status() for ESP32 STA_IF Resolves #3913
Implements the default method (no args) which provides the link status for the STA_IF on ESP32 devices.
Implementation is inspired and consistent with ESP8266, success codes are named similarly, as are most error names. Error codes and names for wifi disconnect are otherwise taken (returned directly) from what the ESP-IDF gives us but are defined in the const dictionary where appropriate.
Success codes are number from 1000 upwards so as not to clash with the 8-bit error codes from ESP-IDF.
Tested connection. failure and success on Wemos R32 device, it seems to return as expected.