This is definitely a bug, feel free to propose a patch.
umqtt.simple's check_msg triggers OSError -1 with TLS servers
Please consider this code:
import utime
from umqtt.simple import MQTTClient
mqtt = MQTTClient("test_mqtt_client_id", "test.mosquitto.org",
port=8883, keepalive=30, ssl=True)
def on_topic_updated(topic, msg):
print((topic, msg))
mqtt.set_callback(on_topic_updated)
mqtt.connect()
mqtt.subscribe(b"Topic/For/Sylvain")
while True:
print("Checking msg...")
mqtt.check_msg()
utime.sleep(1)
It systematically gives the same output (and I can reproduce it with another broker e.g. AWS IoT)
$ /usr/local/Cellar/micropython/1.11/bin/micropython main.py
Checking msg...
Checking msg...
Traceback (most recent call last):
File "main.py", line 15, in <module>
File "/Users/sylvain/.micropython/lib/umqtt/simple.py", line 204, in check_msg
File "/Users/sylvain/.micropython/lib/umqtt/simple.py", line 173, in wait_msg
OSError: -1
What's strange is that if I use port 1883 and ssl=False (i.e. no encryption), the same code works.
I reproduced this issue on my Mac (MicroPython 1.11) and on my ESP8266 board (MicroPython 1.12).
Looping over mqtt.wait_msg() works like a charm, so I suspect switching back and forth a TLS socket from blocking to non-blocking generates such error.
umqtt.simple: multiple subscribe() need check_msg()
Example script:
import time
from umqtt.simple import MQTTClient
def sub_cb(topic, msg):
print((topic, msg))
def main(server="localhost"):
c = MQTTClient("umqtt_client", server)
c.set_callback(sub_cb)
c.connect()
c.subscribe(b"foo_topic")
#time.sleep_ms(100)
#c.check_msg()
c.subscribe(b"bar_topic")
while True:
c.wait_msg()
c.disconnect()
Running with mosquitto MQTT broker seems to work fine with:
$ mosquitto_pub -t "foo_topic" -m "1"
$ mosquitto_pub -t "bar_topic" -m "1"
$ mosquitto_pub -t "bar_topic" -m "3"
However, having a retained message,
$ mosquitto_pub -t "foo_topic" -m "1" -r
the start of the script fails with:
Traceback (most recent call last):
File "example_sub_multi.py", line 21, in <module>
File "example_sub_multi.py", line 14, in main
File "/home/frederik/Downloads/micropython-lib/umqtt.simple/umqtt/simple.py", line 104, in subscribe
AssertionError:
Having a look in the code shows that subscribe() is expecting the
answer of the second subscribe (0x90), but since the message of the
first subscribe arrived, the AssertionError is thrown. So,
uncommenting sleep_ms() and check_msg() results in a working
script.
@pfalcon: This is a bug or by intention?
Solved with #89
Same here (ESP8266 and MicroPython 1.12). When change SSL to noSSL connection, works fine.
I too have this issue using a ublox modem and AWS over TLS. Are there any workarounds?
Same problem, in ESP32 it works perfectly but in ESP8266 it doesn't.
there seems to be some kind of problem when the ssl socket is set to nonblocking and it occasionally returns b"" which results in the OSError(-1). Ignoring it did not help. to work around the problem I created a poll object after the ssl_wrap and in check_msg() I check the poll object instead of mucking around with setblocking(True/False).
YMMV / workaround / not an optimal solution, but it works for me
simple.py
and comment out the #self.sock.setblocking(True) in get_msg()
According to my test, the problem does not occur because of SSL. The problem is because the server's waiting time is over according to the keepalive=??? My solution is to add a timer that PINGs the server before the keepalive time expires. This solves the problem. Here is a sample code to solve the problem: