Description
During the development, it is nice to have an option to have control over starting and stopping the code. For this, I'm using the webrepl that at least allows me to issue exec(open('my_main.py').read())
and press CRTL-C to stop it. At least, because using select.poll()
I can also send something into the running code from the STDIN.
The connect()
mqtt_as call makes an issue with STDIN. Let's consider the following example code that is started using exec(open(...).read())
:
from configuration import Configuration
from mqtt_as import MQTTClient
from mqtt_as import config as mqttconfig
import asyncio
TOPIC = "test/foo"
async def main(client):
try:
await client.connect()
except OSError:
print("Connection failed.")
return
n = 0
while True:
await asyncio.sleep(5)
print("publish", n)
await client.publish(TOPIC, f"counter: {n}")
n += 1
mqttconfig["server'] = Configuration.MQTT_SERVER
mqttconfig["user"] = Configuration.MQTT_USERNAME
mqttconfig["password"] = Configuration.MQTT_PASSWORD
mqttconfig["ssid"] = Configuration.WIFI_SSID
mqttconfig["wifi_pw"] = Configuration.WIFI_PASSWORD
mqttconfig["port"] = 1883
mqttconfig["queue_len"] = 1
MQTTClient.DEBUG = True
client = MQTTClient(mqttconfig)
try:
asyncio.run(main(client))
except KeyboardInterrupt:
print("interrupt")
finally:
client.disconnect()
asyncio.new_event_loop()
I expect, that after CTRL-C key press, an "interrupt" would appear on the output and program finish. Unfortunately, it doesn't happen - there is no reaction and only a hard reset is available.
After some digging I've found that the problem is with the async def _handle_msg(self)
method:
async def _handle_msg(self):
try:
while self.isconnected():
async with self.lock:
await self.wait_msg() # Immediate return if no message
await asyncio.sleep_ms(0) # Let other tasks get lock
except OSError:
pass
self._reconnect() # Broker or WiFi fail.
(lines 844-853 of mqtt_as/__init__.py
). Making the non-zero sleep_ms makes things work as expected. Tested on ESP32-S3 and ESP32-C3.
I'm not sure why zero sleep prevents handling STDIN. I have some theorems in my mind, but I don't feel strong enough in async world to share with them. If anyone has a good understanding of the cause, please let me know.
It looks like the small delay (20ms) was replaced with zero last year. The potential solution is to make the delay configurable with some default value (like zero, what is at this moment).
Please, express your thoughts.