peterhinch / micropython-mqtt

A 'resilient' asynchronous MQTT driver. Recovers from WiFi and broker outages.
MIT License
550 stars 117 forks source link

wifi_connect() times out for ESP8266 but not for ESP32 #34

Closed goatchurchprime closed 2 years ago

goatchurchprime commented 4 years ago

After reporting Issue #29, I began to depend on wifi_connect() to timeout when there is no access point.

Unfortunately this doesn't work on the ESP32.

The problem is around line 512 of mqtt_as.py where it hangs on

while s.status() == network.STAT_CONNECTING:
        await asyncio.sleep(1)

The problem is that, while the ESP8266 gives up after 10 seconds and reports (s.status() == network.STAT_NO_AP_FOUND), the ESP32 never gives up and returns a different state. Therefore we are getting inconsistent behavior.

I've broken out the problematic code here so the behavior can be tested in isolation:

>>> import network, time
>>> w = network.WLAN()
[junk omitted]
>>> w.active(1)
>>> w.connect("BV6000", "password")
>>> time.sleep(300)   # give it five minutes!
... [lots of the following message]
I (108937) wifi: STA_DISCONNECTED, reason:201
no AP found
>>> w.status(), network.STAT_CONNECTING 
1000, 1001

Looking through the special cases in the code, I see that if the library thinks it has esp32_LoBo then it times out after 10 seconds, so I can get that feature by doing the following:

import mqtt_as
mqtt_as.LOBO = True
kevinkk525 commented 4 years ago

This is not good.. You could report it to micropython mabye there are some possibilities left in the firmware.

However I wouldn't change mqtt_as to enfore LOBO port becuse of the differences. It would be better to implement a similar workaround used for the esp8266 in line 487-492 https://github.com/peterhinch/micropython-mqtt/blob/ff6b5aa3121de1ea9ca6436f535f0817105cfadd/mqtt_as/mqtt_as.py#L487 although the situation on esp8266 for this workaround is different.

goatchurchprime commented 4 years ago

Posted into micropython repo, as you can see. The LOBO hack is temporarily safe; the only difference in the code is that it does produce a timeout.