Closed JayPalm closed 1 year ago
resp[3]
is the MQTT connect return code. A value of 0 means connection accepted. Unfortunately the broker is rejecting your connection.
[EDIT]
My previous response was wrong. A value of 5 means "0x05 Connection Refused, not authorized" (from MQTT spec para 3.2.2.3 Connect Return code). I think you may need to create an account.
I have pushed an update improving the error reporting. README section 7 now explains these error codes.
Thanks for the reply and explanation. Any idea why a config (server, user, password) would work with the mqtt.simple module in micropython-lib but not here? The response of "Not Authorized" suggests an issue with user/password to me, but I've checked and double checked that they work with other clients.
Thanks for your help.
I can replicate this problem. I created an account with HiveMQTT and ran their Paho/Python3 example successfully. Attempts to connect with mqtt_as
produce the response code 5.
You report success using mqtt.simple
: I can't replicate this - I get response code 5. Please could you post your successful script (feel free to redact password and username).
I think this is the key to a solution because my ._connect
method is based on that in mqtt.simple
.
You are not the first to struggle with HiveMQTT: see https://github.com/peterhinch/micropython-mqtt/issues/94.
You are not the first to struggle with HiveMQTT: see #94.
I'm using a pico w to send json data to nodered via that server and, afaik, I don't get any errors. I also use nodered to send control signals to the pico. Nodered is installed on my Rpi 3+ at home but, accessible via internet.
# Define configuration
config['server'] = 'broker.mqttdashboard.com' # Change to suit
config['ssid'] = wifimgr.get_profiles()[0] # using a modified wifimgr.py to get my wifi credentials
config['wifi_pw'] = wifimgr.get_profiles()[1]
config['user'] = 'my_user_name'
config['password'] = 'my_pass'
config['subs_cb'] = sub_cb
config['wifi_coro'] = wifi_han
config['will'] = (pub_topic, 'Goodbye cruel world!', False, 0)
config['connect_coro'] = conn_han
config['keepalive'] = 120
# Set up client. Enable optional debug statements.
MQTTClient.DEBUG = False
client = MQTTClient(config)
# asyncio.create_task(temp_sensor())
try:
asyncio.run(main(client))
finally: # Prevent LmacRxBlk:1 errors.
client.close()
green_led(True) # led section modified
asyncio.new_event_loop()
mqtt_as: VERSION = (0, 7, 0)
I suspect I didn't make myself clear. I understood that you had achieved success with mqtt.simple()
. I found it failed so I wanted to see your working script that used mqtt.simple()
. Mine is
from simple import MQTTClient # simple.py is in the Pico root directory
import do_connect # My connection script
do_connect.do_connect()
def main():
c = MQTTClient("",
server='106b0a678db04a00be920085ef5f84f3.s2.eu.hivemq.cloud',
user="pythoncoder",
password="my_password",
ssl=True
)
c.connect() # FAILS with code 5
c.publish(b"foo_topic", b"hello")
c.disconnect()
main()
If you have a similar script that works, hopefully we'll be on the way to a solution.
At the moment I'm baffled by this. HiveMQ uses V5 of the MQTT protocol but their Paho example works if you specify V3.1.1. The connect string from simple.py
and mqtt_as.py
is correct for V3.1.1. So both should work, but in my testing neither do.
If you have a similar script that works, hopefully we'll be on the way to a solution.
This' what I tried:
import network
from utime import sleep
from umachine import reset
ssid = "my_ssid"
password = "my_pass"
def wifiConnect():
print('-- Connecting...')
wifi = network.WLAN(network.STA_IF)
wifi.active(True)
if wifi.isconnected():
wifi.disconnect()
wifi.connect(ssid, password)
wifi.ifconfig(('192.168.1.99', '255.255.255.0', '192.168.1.1', '8.8.8.8'))
sleep(2)
cnt = 0
while not wifi.isconnected():
print('Re_Connecting...')
sleep(2)
cnt += 1
if cnt == 10:
t = '** Reset ESP **'
print(t)
sleep(5)
reset()
print('Wifi connected')
print(wifi.ifconfig())
sleep(5)
return True
print(wifiConnect())
from simple import MQTTClient # simple.py is in the Pico root directory
# could not find it so I used this one: https://github.com/micropython/micropython-lib/blob/master/micropython/umqtt.simple/umqtt/simple.py
def main():
c = MQTTClient("",
server='broker.mqttdashboard.com',
user='username',
password='user_pass',
ssl=True
)
c.connect() # FAILS with code 5
c.publish(b"foo_topic", b"hello")
c.disconnect()
main()
and this' what I got:
>>> %Run -c $EDITOR_CONTENT
-- Connecting...
Re_Connecting...
Wifi connected
('192.168.1.99', '255.255.255.0', '192.168.1.1', '8.8.8.8')
True
>>>
from mqttx app:
Topic: foo_topicQoS: 0 hello 2023-01-03 15:48:19:264
edit1: That's if the simple.py lib I used is correct. edit2: The only difference I see is the name of the server.
We are both using the same simple.py
. The fact that we have different connect scripts is irrelevant. In both cases we have an established connection. So:
edit2: The only difference I see is the name of the server.
Agreed.
I don't know what is broker.mqttdashboard.com
. As far as I can see, to access HiveMQ you need to use the URL they supply you with. Yours will be something similar to 106b0a678db04a00be920085ef5f84f3.s2.eu.hivemq.cloud
. Perhaps you could try the "simple" script with that URL.
With their URL I can access HiveMQ with mosquitto and with Paho/Python but not with simple.py
.
As a general point, if simple.py
does not work, mqtt_as
won't either because their connect methods are very similar. So I suggest we work on getting simple.py
working as it's easier to debug being, er, simple :) Conversely, if we can connect with simple.py
then I'm confident of being able to fix any problem with mqtt_as
.
Ok. If you click on the "broker" link you mentioned above, it redirects to a dashboard which is the one I'm using. If you click on "106b0a678db04a00be920085ef5f84f3.s2.eu.hivemq.cloud" it goes nowhere. and I guess this' the reason the code fails:
>>> %Run -c $EDITOR_CONTENT
-- Connecting...
Re_Connecting...
Wifi connected
('192.168.1.99', '255.255.255.0', '192.168.1.1', '8.8.8.8')
True
Traceback (most recent call last):
File "<stdin>", line 50, in <module>
File "<stdin>", line 46, in main
File "simple.py", line 110, in connect
MQTTException: 5
>>>
Each HiveMQ user gets their own URL so the specific 106b0a678db04a00be920085ef5f84f3.s2.eu.hivemq.cloud
URL will only work with my username and password.
EUREKA.
The key is that the server name must be broker.mqttdashboard.com
. Then both simple.py
and mqtt_as
work.
This is quite obscure as all the examples they post use the long cryptic URL. @ebolisa To satisfy my curiosity, where did you find the name broker.mqttdashboard.com
?
To satisfy my curiosity, where did you find the name
broker.mqttdashboard.com
?
Clicking on that link you're directed to their web. Click on X or "Cancel" on the popup window. The login settings are on the right side of the page. Cheers.
I'm still puzzled by the two URL's. With mosquitto_sub
I can only connect to the long hex URL, yet the Python solutions can only connect to broker.mqttdashboard.com
. The two are separate. My async test script regularly publishes but if I subscribe with mosquitto_sub I get nothing. So my prime debugging tools mosquitto_pub
and mosquitto_sub
are useless.
Tomorrow I'll verify that two async clients can talk to each other, but surely they will...
Tomorrow I'll verify that two async clients can talk to each other, but surely they will...
I cannot help you much there Peter. I'm not a programmer but a retired bio-med engineer who just cannot stay away from electronics. Have a wonderful year!
@peterhinch I guess I misspoke regarding the mqtt.simple example config, it is slightly different. See here for what needs to be added to the client config to get it working, basically this:
config["ssl_params"] = {
"server_hostname": "<broker_address>"
}
However, adding this to the config for mqtt_as hasn't yielded success for me yet.
Putting together a script, will post shortly.
Update: this gist is working for me, feel free to run it with my broker and credentials.
I am having success with this now: gist.
I added the ssl_param
dict as above. I'm not sure why it wasn't working before.
Thank you. I was beginning to think I was going to have to search for a bug in both clients.
I now have this working with mqtt_as
, testing with mosquitto_pub
and mosquitto_sub
. For reference here is my config:
# Credentials
broker = '106b0a678db04a00be920085ef5f84f3.s2.eu.hivemq.cloud'
config['user'] = 'my username'
config['password'] = 'my password'
# Define configuration
config['will'] = (TOPIC, 'Goodbye cruel world!', False, 0)
config['keepalive'] = 120
config["queue_len"] = 1 # Use event interface with default queue
config['server'] = broker
config['ssl'] = True
config['ssl_params'] = {"server_hostname": broker} # magic
I have added these notes to the docs.
No problem, and thanks for the info/help, @peterhinch! Would you accept a PR that showed or noted this "magic" addition in the TLS examples, and perhaps in the readme?
I'm always open to suggestions, but please check out my latest version of the readme as I updated it late yesterday.
I'd rather not change the code of the TLS samples as these have been tested, but code comments would be welcome.
Does anyone know why this works?
config['ssl_params'] = {"server_hostname": broker}
I had discounted TLS problems because the server responded to connect with a correctly formatted CONNACK
packet (albeit showing failure). This implies that encryption and decryption was working correctly in both directions. Yet the server_hostname
key is evidently necessary.
Any guidance or doc references on this dict would be much appreciated.
I am trying to connect to a free broker from HiveMQ. Everything works fine when I use the following config on a public test broker (from eclipse)
However, when I switch the server, user, and password to the appropriate values for my HiveMQ broker, I receive the "BAD CONNACK" error.
This exact config (server, port, user, pass, etc) work successfully in other clients, including the simple umqtt included in micropython-lib.
It appears to be caused by this clause in the
_connect
method:This is the value of
resp
when connecting to Eclipse (working config):bytearray(b' \x02\x00\x00')
This is the value of
resp
when connecting to HiveMQ (not working):bytearray(b' \x02\x00\x05')
I've been trying figure out what that 4th byte in the response means, beyond indicating that the authentication was unsuccessful.