-
Notifications
You must be signed in to change notification settings - Fork 75
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
wrong connection error messages from connect_AP method #189
Comments
The ESP32SPI library sends the command to connect to the NINA firmware, and handles any errors here:
In the ESP32SPI library, code (1) is No SSID, code (4) is Connection failed, (3) is Connected - these seem to match NINA / Arduino codes: The NINA firmware command handler calls the Arduino function Pretty much everything at that level or above is just passing along commands and returning responses. The actual connect logic is in the Arduino WiFi component included in the NINA firmware: I'm not sure which aspects of the |
I am familiar with that block of code. I reproduced a variation of it as part of the testing that went into the original post. Note though that the 'handling' that does is only after the 10 second timeout. It looks at the final status.
Analysis:
The important difference in that is that the bad password case detects a status change to 6 (WL_DISCONNECTED) 13.104 seconds after the passphrase is set, AND the following case where the ssid does not exist goes to status 1 (WL_NO_SSID_AVAIL) when setting the passphrase. It takes more than 10 seconds for an attempt to connect using a bad passphrase to timeout and disconnect (on the esp32 side). Analysing the pattern of status changes, WL_NO_SSID_AVAIL is NEVER a final status for a connection attempt. That status means that some operation is still pending. With the longer timeout, which prevents interaction with the failed (still failing) previous connection attempt, setting the passphrase always results in a status of 1 (WL_NO_SSID_AVAIL). The actual result status is whatever that changes to, whenever it changes. The case for the AP not being in range can be sped up significantly by watching for that status change, instead of waiting for the timeout. In the existing structure, timing out (with a status of 1) actually means that an attempt is still in progress. Assessment: Looking over the patterns from those tests, here is a naive, shell for a connect_AP replacement that handles those cases. It is likely not sufficient as is, since I do not know enough about what other conditions might be encountered. Simply adding WL_CONNECTION_LOST to the unable to connect case might cover it. def fixed_connect_AP(self, ssid:str, password:str, timeout_s:int=10) -> int: # pylint:disable=invalid-name
"""alternate structure"""
# converting bytes to bytes does not change anything. No need to test before forcing.
if self.status == wl_const.WL_NO_SSID_AVAIL:
print('Could be a previous operation still in progress. Handle it')
# send spi command to abort operation? and wait for 'better' status?
raise ConnectionError("Operation pending: aborting connection to ssid", ssid)
if isinstance(ssid, str):
ssid = bytes(ssid, "utf-8")
if password:
if isinstance(password, str):
password = bytes(password, "utf-8")
self.wifi_set_passphrase(ssid, password)
else:
self.wifi_set_network(ssid)
stat = self.status
if stat != wl_const.WL_NO_SSID_AVAIL:
print('Something strange: status should be "NO_SSID_AVAIL" immediately after '
'setting credentials')
raise OSError(f'{stat:02X} status detected setting WiFi Credentials. ' +
f'Expecting only {wl_const.WL_NO_SSID_AVAIL:02X}')
times = time.monotonic()
while (time.monotonic() - times) < timeout_s: # wait until have result or timeout
stat = self.status
if stat != wl_const.WL_NO_SSID_AVAIL:
# the state has changed, we have some sort of result
break
time.sleep(0.05)
if stat == wl_const.WL_CONNECTED:
return stat
if stat == wl_const.WL_NO_SSID_AVAIL:
# possible bad password, weak signal, something else causing slow response
raise ConnectionError("Timeout attempting to connect to ssid", ssid)
if stat == wl_const.WL_DISCONNECTED:
raise ConnectionError("Unable to connect to ssid", ssid)
if stat == wl_const.WL_CONNECT_FAILED:
raise ConnectionError("Unable to locate ssid", ssid)
raise OSError(f"Unknown error {stat:02X}") Using that version in my test code, with a 20 seoncd timout gives:
With a 10 second timeout:
With a 10 second timeout and increasing the sleep time between connection attempts to 5 seconds:
|
ESP_SPIcontrol.connect_AP is not reporting connection failures correctly for the actual failure causes. Testing is pointing to a possible failure or limitation in the NINA fw. The problem could also be the way, and which, commands are being sent to the fw.
Observed:
When specifying an SSID that exists, but using the wrong password, connect_AP reports 'No such ssid'.
When specifying an SSID that does not exist, connect_AP reports 'Failed to connect to ssid'
Expected:
The reverse.
To demonstrate, I took a copy of the simple_test.py example, cut it down, modified it, and added to it. As part of that, I created a subclass of ESP_SPIcontrol to add a testing version of connect_AP. That version monitors and reports the status changes more closely, but raises the same exceptions. The result is below, along with the output I get. In that, I noticed that the status never goes back to idle.
The text was updated successfully, but these errors were encountered: