I am using the following code in attempt to connect to Azure IoT Hub. It uses SAS, therefore no security certificates are needed. I am successfully connecting to Azure IoT Hub using the same M2MQTT library in C# but this code fails with:
Failed to connect.Connection refused, not authorized. Error Code= 5
I tried any possible combos of security parameters but at no avail. The SAS token is generated by DeviceExplorer.
#! /usr/bin/python3.5
import serial
import time
import datetime
import os
import socket
import ssl
import logging
import paho.mqtt.client as mqtt
import sys
print(sys.executable)
def on_disconnect(client, userdata, rc):
if rc==0:
print("client disconnected OK")
client.connected_flag=False
def on_connect(client, userdata, flags, rc):
if rc==0:
print("Connected OK")
mqtt.Client.connected_flag=True
mqtt.Client.bad_connection_params=False
else:
mqtt.Client.bad_connection_params=True
if rc==1:
print("Failed to connect. Connection refused, unacceptable
protocol version. Error Code=", rc)
elif rc==2:
print("Failed to connect.Connection refused, identifier
rejected. Error Code=", rc)
elif rc==3:
print("Failed to connect.Connection refused, server unavailable. Error Code=", rc)
elif rc==4:
print("Failed to connect.Connection refused, bad user name or password. Error Code=", rc)
elif rc==5:
print("Failed to connect.Connection refused, not authorized. Error Code=", rc)
def on_publish(client, userdata, mid):
if rc==0:
print("Data published OK: ", userdata)
else:
print("Failed to publish data. MessageID=", mid)
pass
broker="myIoTHubName.azure-devices.net"
port=8883
DeviceID="MasterTag"
DeviceKey="myDeviceKey"
IoTHubName="myIoTHubName"
SasToken="SharedAccessSignature sr=myIoTHubName.azure-devices.net&sig=..."
# Create client object
# 4 stands for MQTTv311
rpiclient = mqtt.Client("PahoClient-on-RPi-Gateway2", clean_session=True, userdata=None, protocol=4, transport="tcp")
usernameFormat="{}{}{}"
username=usernameFormat.format(IoTHubName, ".azure-devices.net/", DeviceID)
password=SasToken
rpiclient.username_pw_set(username, password)
rpiclient.tls_set(tls_version=ssl.PROTOCOL_TLSv1_2)
rpiclient.tls_insecure_set(True)
# connection flag indicates that connection was made or not
mqtt.Client.connected_flag = False
# connection parameters are incorrect: ip address, port, authentication, etc
mqtt.Client.bad_connection_params=False
#assign function to callback
rpiclient.on_connect = on_connect
#assign function to callback
rpiclient.on_publish = on_publish
# bind the disconnect callback
rpiclient.on_disconnect = on_disconnect
rpiclient.loop_start()
rpiclient.will_set("dwm/position", "Client PahoClient-on-RPi2 had unexpectedly disconnected", 1, True)
try:
print("Connecting to MQTT broker ",broker)
# Connect to the MQTT Broker
rpiclient.connect(broker, port)
time.sleep(1)
# Wait in a loop until we are connected
print("mqtt.Client.connected_flag={},
mqtt.Client.bad_connection_params={}".format(mqtt.Client.connected_flag, mqtt.Client.bad_connection_params))
while mqtt.Client.connected_flag == False and mqtt.Client.bad_connection_params == False:
print("Waiting for connection...");
time.sleep(1)
if mqtt.Client.bad_connection_params == True:
rpiclient.loop_stop()
sys.exit()
except Exception as ex:
print("Connection to MQTT Broker failed: ", ex)
rpiclient.loop_stop()
# Disconnect MQTT Client
rpiclient.disconnect()
Any advice is appreciated.
the following is a working example of the simulated device1 connected to the Azure IoT Hub using a paho.Mqtt client library:
from paho.mqtt import client as mqtt
import time
import ssl
def on_subscribe(client, userdata, mid, granted_qos):
print('Subscribed for m' + str(mid))
def on_connect(client, userdata, flags, rc):
print("Connected with result code "+str(rc))
def on_message(client, userdata, message):
print("Received message '" + str(message.payload) + "' on topic '" + message.topic + "' with QoS " + str(message.qos))
def on_log(client, userdata, level, buf):
print("log: ",buf)
device_id = "device1"
iot_hub_name = "myIoTHub"
sas_token = "SharedAccessSignature sr=myIoTHub.azure-devices.net%2Fdevices%2Fdevice1&sig=****&se=1586926815"
client = mqtt.Client(client_id=device_id, protocol=mqtt.MQTTv311, clean_session=False)
client.on_log = on_log
client.tls_set_context(context=None)
# Set up client credentials
username = "{}.azure-devices.net/{}/api-version=2018-06-30".format(iot_hub_name, device_id)
client.username_pw_set(username=username, password=sas_token)
# Connect to the Azure IoT Hub
client.on_connect = on_connect
client.connect(iot_hub_name+".azure-devices.net", port=8883)
# Publish
client.publish("devices/{device_id}/messages/events/".format(device_id=device_id), payload="{}", qos=0, retain=False)
# Subscribing on the topic ,
client.on_message = on_message
client.on_subscribe = on_subscribe
client.subscribe("devices/{device_id}/messages/devicebound/#".format(device_id=device_id))
client.subscribe("$iothub/twin/PATCH/properties/desired/#")
client.subscribe("$iothub/methods/POST/#")
client.loop_forever()
Update:
The sas_token for the specific device can be generated using the Device Explorer tool, see the following screen snippet:
and the output log should be looked like the following screen snippet:
When you use MQTT to connect the Azure IoT Hub directly, you need to connect over TLS/SSL. In order to establish a TLS connection, you may need to download and reference the DigiCert Baltimore Root Certificate, and then set the certificate for the TLS/SSL connection. Please see the document Communicate with your IoT hub using the MQTT protocol.
client.tls_set(ca_certs=path_to_root_cert, certfile=None, keyfile=None,
cert_reqs=ssl.CERT_REQUIRED, tls_version=ssl.PROTOCOL_TLSv1, ciphers=None)
client.tls_insecure_set(False)
Related
python code
import time
broker = "test.mosquitto.org"
port=8884
conn_flag= False
def on_connect(client, userdata, flags, rc):
global conn_flag
conn_flag=True
print("connected",conn_flag)
conn_flag=True
def on_log(client, userdata, level, buf):
print("buffer", buf)
def on_disconnect(client, userdata, rc):
print("client disconnected ok")
client1= paho.Client("control")
client1.on_log=on_log
client1.tls_set('C:\etc\mosquitto\certs\mosquitto.org.crt')
client1.on_connect = on_connect
client1.on_disconnect = on_disconnect
client1.connect(broker,port)
while not conn_flag:
time.sleep(1)
print("waiting", conn_flag)
client1.loop()
time.sleep(3)
print("publishing")
client1.publish("house/bulb", "Test")
time.sleep(2)
client1.loop()
time.sleep(2)
client1.disconnect()
I am using the mosquitto.org.crt (PEM format) file gave by test.mosquitto.org, currently can't get to connect on port 8884, conn_flag is always false what should I do?
As per http://test.mosquitto.org the ports are:
8883 : MQTT, encrypted, unauthenticated
8884 : MQTT, encrypted, client certificate required
In your code client1.tls_set('C:\etc\mosquitto\certs\mosquitto.org.crt') you are setting the ca_cert - the params being:
tls_set(ca_certs=None, certfile=None, keyfile=None, cert_reqs=ssl.CERT_REQUIRED, tls_version=ssl.PROTOCOL_TLS, ciphers=None)
This would be sufficient to connect to port 8883 (and your code connects to that port successfully for me). A connection to port 8883 will be encrypted and the client can confirm the identify of the server; however the client does not have to provide a client certificate (to identify itself).
To connect to port 8884 you have to provide a client certificate (used to authenticate the client) - i.e. the certfile and keyfile arguments. An appropriate certificate can be requested here.
It's my first time trying to connect to a mqtt broker and it's not really going great. I've been trying to get data from the broker but am unable to figure out how to connect. I've been handed a username, password, port and encrypted port aswell as "Topics. When trying to connect the "client.connect"-line responds with "0". I changed the username and password and I still get the same result so there is something wrong with my configuration. Any help would be much appreciated!
I'm running python 3.6.5
import paho.mqtt.client as mqtt
import time
username="temp"
password="temp"
# The callback for when the client receives a CONNACK response from the server.
def on_connect(client, userdata, flags, rc):
print("Connected with result code "+str(rc))
# Subscribing in on_connect() means that if we lose the connection and
# reconnect then subscriptions will be renewed.
client.subscribe("extapi/data/esm")
# The callback for when a PUBLISH message is received from the server.
def on_message(client, userdata, msg):
print(msg.topic+" "+str(msg.payload))
client = mqtt.Client()
client.on_connect = on_connect
client.on_message = on_message
client.username_pw_set(username, password)
client.connect("example.io", 1883, 60)
My client is unable to receive message payload from the MQTT server. I had set mosquitto on my PC to act as both the server and publisher and execute the following command:
mosquitto_pub -h 192.168.1.2 -t topic/test -m "testing" -i simulator -d
Subscribing myself works and payload is received.
However, my client which is using paho mqtt only received successful connection without the payload message. So i have the following code here:
def on_connect(client, userdata, flags, rc):
print("connection ok")
client.subscribe("topic/test")
def on_message(client, userdata, msg):
print("Message received! " + str(msg.payload))
if msg.payload == "testing":
print("Message received")
# Do something
...
def main():
#MQTT
broker = "192.168.1.2" #broker ip
client = mqtt.Client("simulator")
client.on_connect = on_connect
client.on_message = on_message
client.connect(broker, 1883, 60)
client.loop_start()
while(1):
...
So it did managed to print "connection ok", but not "Messaged received! ..."
You are using the same client-id (simulator) with mosquitto_pub and in your python. As per the spec:
If the ClientId represents a Client already connected to the Server then the Server MUST disconnect the existing Client
So what is happening is:
Python client connects and subscribes.
mosquitto_pub connects, broker disconnects python client.
mosquitto_pub publishes the message (but as nothing is subscribed the QOS 0 message will be dropped by the broker).
Python client reconnects and subscribes again.
Try using a different client-id with mosquitto_pub (your code works fine when I test it in that way - added a time.sleep(1) in the while(1)).
I cant get mqtt messages from pythonscript on Node Red and cant recieve mqtt messages from Node Red.
this is my code:
import time
import sys
sys.path.append('C:\\Users\\user\\Python\\pyproj\\project1\\Lib\\site-packages\\paho_mqtt-1.6.1-py3.10.egg')
import paho.mqtt.client as mqtt
userdata = "Leer"
client_name = "Pythonscript"
broker_address="000.000.000.000"
port = 1234
topic = "a topic"
subtopic = "fromNodeRed"
def on_log(client, userdata, level, buf):
print(" client: ",client)
print(" userdata: ",userdata)
print(" level: ",level)
print(" buf: ",buf)
def on_connect(client, userdate, flags, rc):#, message):
if rc==0:
print("connected OK ")
print("Subscribing to topic ",subtopic)#topic)
client.subscribe(subtopic)
else:
print("Bad Connection Returned code=",rc)
def on_message(client,userdate,msg):
topic=msg.topic
m_decode=str(msg.payload.decode("utf-8","ignore"))
print("message recieved",m_decode)
print("Publishing message to topic ",topic)
client.publish(topic, "python mqqt message")
def on_disconnect(client, userdate, flags, rc=0):
print("Disconnected result code "+str(rc))
print("creating new instance ",client_name)
client =mqtt.Client(client_name)
client.on_connect=on_connect
client.on_disconnect=on_disconnect
client.on_log=on_log
client.on_message=on_message
print("connecting to broker ",broker_address+" :"+str(port))
client.connect(broker_address,port,60)
client.loop_start()
print("Publishing message to topic ",topic)
client.publish(topic, "python mqqt message")
time.sleep(4)
client.loop_stop()
client.disconnect()
I changed some data for protection.
Here is the console output:
I checked the topics, the IP, the Port. Everything seems to be ok.
What do i miss?
I used the portnumber from Node Red instead of the mqtt broker.
After that, I recieved and published messages.
import paho.mqtt.publish as publish
import paho.mqtt.client as mqtt
USERNAME = "admin-user"
PASSWORD = "admin-user#12345"
AUTH = {"username":USERNAME, "password":PASSWORD}
HOSTNAME = "ssl://b-c7d1ea8g-f777-4c71-23a3-2d73088fdb64-1.mq.us-west-2.amazonaws.com"
PORT = 8883
TOPICNAME = "paho/test/single"
PAYLOAD = "Hope Stackoverflow Help Me Resolve This Issue!"
publish.single(TOPICNAME, payload=PAYLOAD, hostname=HOSTNAME, port=PORT, auth=AUTH, protocol=mqtt.MQTTv311, transport="tcp", client_id="", keepalive=60, will=None) # This won't work
# publish.single(TOPICNAME, payload=PAYLOAD, hostname="localhost") # This works!
print('published message payload = ', PAYLOAD)
I am able to connect to AmazonMQ with Java eclipse Paho client, but not able to do same the in Python. It gives me an error "gaierror: [Errno -2] Name or service not known".
The above python code works fine with a locally hosted ActiveMQ MQTT broker and also in stand alone server where I have hosted ActiveMQ MQTT broker. But the same is not working with AmazonMQ broker.
This issue is already mentioned in the issue tracker of Github Paho, but still there is no solution that will help.
You need to remove the "ssl://" from your host variable, and set a ssl context in order to connect to Amazon-MQ with paho.
context = ssl.create_default_context()
client.tls_set_context(context=context)
Here is a working version of the example posted on your github issue.
import paho.mqtt.client as mqttClient
import time
import ssl
context = ssl.create_default_context()
Connected = False
broker_address= "b-xxxxxx-acbf-xxxx-xxxx-xxxxx-1.mq.us-east-1.amazonaws.com" # No ssl://
port = 8883
user = "xxxxxx"
password = "xxxxx"
def on_connect(client, userdata, flags, rc):
if rc == 0:
print("Connected to broker")
global Connected #Use global variable
Connected = True #Signal connection
client.subscribe("test/data")
else:
print("Connection failed")
def on_message(client, userdata, msg):
print(msg.topic+" "+str(msg.payload))
client = mqttClient.Client("Test") #create new instance
client.username_pw_set(user, password=password) #set username and password
client.on_connect=on_connect
client.on_message=on_message
client.tls_set_context(context=context)
client.connect(broker_address, port=port)
client.loop_start()
while Connected != True:
time.sleep(0.1)
client.publish("test/data", "This is my test msg 123.")
time.sleep(10)