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
Repeatable OSError: Wifi Internal Error in sta_if.connect
Port, board and/or hardware
ESP32-C3 and S3
MicroPython version
MicroPython v1.25.0 on 2025-04-15; ESP32C3 module with ESP32C3
Reproduction
Power-cycle the board and run the following code (in my case, in Thonny):
import network, time
sta_if = network.WLAN(network.WLAN.IF_STA)
sta_if.active(True)
print('foo')
sta_if.connect("no-such-network", "password")
time.sleep(5)
print('bar')
sta_if.connect("no-such-network", "password")
time.sleep(5)
print('baz')
Expected behaviour
No response
Observed behaviour
foo
bar
Traceback (most recent call last):
File "<stdin>", line 10, in <module>
OSError: Wifi Internal Error
(where line 10 is the second connect)
I get similar results when the first connect() is a real network with the wrong password, the second connect() is the same wrong network/password as the first, or the second connect() is a real network with the right password.
In fact, the sleep()s don't seem to be required either.
Additional Information
Power-cycling the board before running the test may be required for reproducibility.
Bug also manifests in the latest preview ESP32_GENERIC_C3-20250709-v1.26.0-preview.364.gdf05caea6.bin
and ESP32_GENERIC_S3-SPIRAM_OCT-20250709-v1.26.0-preview.364.gdf05caea6.bin
Unfortunately I don't have other boards to test with right now.
Code of Conduct
Yes, I agree