Python MQTT connection to Azure Iot Hub - python

I want to connect to Azure Iot Hub, with Python MQTT.
An username and SAS token is required by Iot Hub. This is my code:
import paho.mqtt.client as mqtt
def on_connect(client, userdata, flags, rc):
print("Connected with result code "+str(rc))
client.subscribe("$SYS/#")
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("myHub.azure-devices.net/device1", "mySASToken")
client.connect("myHub.azure-devices.net", 1883, 60)
client.loop_forever()
But after running for a while, this exception is thrown:
TimeoutError: [WinError 10060] A connection attempt failed because the connected party did not properly respond after a period of time, or established connection failed because connected host has failed to respond
Does somebody know why I can't connect to the Iot Hub?

There is now an official Python SDK to connect devices to Azure IoT Hub:
https://github.com/Azure/azure-iot-sdks/tree/master/python/device
This sample demonstrates how to connect using the MQTT protocol.
Basically, here's how it works:
create a device client and specifies MQTT for the protocol
set the callback that will be called when a message is received
use send_event_async to send messages to your Azure IoT Hub instance.
from iothub_client import *
def send_confirmation_callback(message, result, userContext):
print "Confirmation[%d] received for message with result = %s" % (userContext, result)
def receive_message_callback(message, counter):
buffer = message.get_bytearray()
size = len(buffer)
print "Received Message"
print " Data: <<<%s>>> & Size=%d" % (buffer[:size], size)
return IoTHubMessageDispositionResult.ACCEPTED
iotHubClient = IoTHubClient(connectionString, IoTHubTransportProvider.MQTT)
iotHubClient.set_message_callback(receive_message_callback, 0)
iotHubClient.send_event_async(message, send_confirmation_callback, 0)

As #FarukCelik said, there was no Azure IoT SDK for Python.
However, per my experience, I think there are four practicable ways using the existing SDK for Azure IoTHub in Python.
Using Azure IoT SDK for C to extending Python, you can try to refer to https://docs.python.org/2/extending/extending.html to implement it.
Using Azure IoT SDK for Java as Jython package imported, you can try to refer to http://www.jython.org/jythonbook/en/1.0/JythonAndJavaIntegration.html to know how to do it.
The similar to the second way, integrating IronPython with Azure IoT SDK for C#/.Net, please refer to http://ironpython.net/documentation/dotnet/.
The Azure IoT SDK for NodeJS support MQTT via the same Eclipse project Paho for JavaScript Client, so I think you can try to refer to the source code of Azure NodeJS IoT SDK on GitHub to know how to correctly using paho Python client for Azure IoTHub.
Meanwhile, there is a unoffical Python library for Azure IoTHub Device on GitHub https://github.com/bechynsky/AzureIoTDeviceClientPY. That you can concern about this project repository, but it's still on the deveploment stage by now.
Hope it helps. Best Regards.

Here is how to use paho (mosquitto) to connect to the Azure IoT Hub over standard MQTT:
from paho.mqtt import client as mqtt
def on_connect(client, userdata, flags, rc):
print "Connected with result code: %s" % rc
client.subscribe("devices/<YOUR DEVICE ID>/messages/devicebound/#")
def on_disconnect(client, userdata, rc):
print "Disconnected with result code: %s" % rc
def on_message(client, userdata, msg):
print " - ".join((msg.topic, str(msg.payload)))
# Do this only if you want to send a reply message every time you receive one
client.publish("devices/<YOUR DEVICE ID>/messages/events", "REPLY", qos=1)
def on_publish(client, userdata, mid):
print "Sent message"
client = mqtt.Client(cleint_id=<YOUR DEVICE ID>, protocol=mqtt.MQTTv311)
client.on_connect = on_connect
client.on_disconnect = on_disconnect
client.on_message = on_message
client.on_publish = on_publish
client.username_pw_set(username="<YOUR NAMESPACE>.azure-devices.net/<YOUR DEVICE ID>",
password="<YOUR SHARED ACCESS SIGNATURE FOR THE DEVICE>")
client.tls_insecure_set(True) # You can also set the proper certificate using client.tls_set()
client.connect("<YOUR NAMESPACE>.azure-devices.net", port=8883)
client.loop_forever()

Referring to https://azure.microsoft.com/en-gb/documentation/articles/iot-hub-sdks-summary/ Azure IoT SDK does not contain Pyhon "yet". This is already raised by other customers in https://feedback.azure.com/forums/321918-azure-iot . (Direct link : https://feedback.azure.com/forums/321918-azure-iot/suggestions/10522101-add-python-client-sdk).

Related

Trying to use mosquitto broker with TLS using paho python

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.

Connection is established, but unable to retrieve message payload on paho mqtt client

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)).

Mqtt broker is disconnecting frequently even though it has a unique client id

Hi I have a mqtt broker up and running. I am connecting to it from python using paho-mqtt.
Code
def on_connect(client, userdata, flags, rc):
if rc==0:
print("connected OK Returned code=",rc)
else:
print("Bad connection Returned code=",rc)
print("Subscribing to topic","data/#")
client.subscribe("data/#")
def on_disconnect(client, userdata, rc):
print("Client Got Disconnected")
if rc != 0:
print('Unexpected MQTT disconnection. Will auto-reconnect')
else:
print('rc value:' + str(rc))
broker_address="ip"
port = 'port'
print("creating new instance")
client = mqtt.Client(clean_session=True) #create new instance
client.on_connect = on_connect
client.on_message = on_message #attach function to callback
client.on_disconnect = on_disconnect
print("connecting to broker")
client.connect(broker_address, port=port,) #connect to broker
client.loop_forever() #stop the loop
I am using the same code in multiple scripts ,connecting to broker and subscribing to a topic. The frequency of disconnection was less when there were 5-6 scripts. I have around 12-13 scripts connecting to the broker and frequency of disconnects has increased significantly. Is there some thing wrong with the connection in the scripts or its about the broker. Can someone help me with this?
My guess though is your broker does not like the fact that the Python client defaults to a null clientid. As per the spec it should treat this as an indication it must assign a unique id to your client, but it may be implementing the spec improperly?
Please try passing a randomly generated / unique client id in your connect(), as this will guarantee your clients are all unique, rather than all having the same id which for your broker means it's kicking out any connected client when a new one with the same id tries to connect.

MQTT Client not receiving messages

I'm using the following code from MQTT Paho project to subscribe to messages from my mqtt broker. I tested the connection using mosquitto_sub and I receive the messages there. However, when I run the following code it doesn't receive any messages and no output is printed. I checked the topic and host.
import paho.mqtt.client as mqtt
# The callback for when the client receives a CONNACK response from the server.
def on_connect(client, userdata, 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("test")
# 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.connect("localhost", 1883, 60)
client.loop_forever()
The following error is logged by the broker:
Invalid protocol "MQTT" in CONNECT from ::1.
Socket read error on client (null), disconnecting.
EDIT Thanks to #hardillb for pointing out the outdated MQTT version.
Everything worked after I did the following:
sudo apt-get purge mosquitto
sudo apt-add-repository ppa:mosquitto-dev/mosquitto-ppa
sudo apt-get update
sudo apt-get install mosquitto
This is most likely because you are using an old version of mosquitto and the python is expecting a newer build that supports MQTT 3.1.1
Try changing the code as shown:
import paho.mqtt.client as mqtt
# The callback for when the client receives a CONNACK response from the server.
def on_connect(client, userdata, 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("test")
# The callback for when a PUBLISH message is received from the server.
def on_message(client, userdata, msg):
print(msg.topic+" "+str(msg.payload))
# Change made HERE
client = mqtt.Client(protocol=MQTTv31)
client.on_connect = on_connect
client.on_message = on_message
client.connect("localhost", 1883, 60)
client.loop_forever()
You should also upgrade your broker as soon as possible, that version is incredibly out of date and has a number of known issues, the current version is 1.4.10

Can't connect to Mosquitto server using paho.mqtt.client although mosquitto_pub works fine

I have a remote server running mosquitto. I can connect to this server and exchange messages using mosquitto_pub and mosquitto_sub. If i try the same using some python with paho.mqtt.client I get no connection. My script keeps running but the on_connection hook is never called.. The same scripts however work flawlessly with my local mosquitto server.
What could possibly be the reason for the connection problems? How can I get some more feedback on what's happening? Any suggestions?
EDIT: I added a minimal code example
import paho.mqtt.client as mqtt
def on_connect(client, userdata, flags, rc):
print("Yeeha")
client.subscribe("botgrid/init", qos=2)
def on_message(client, userdata, msg):
print(msg.payload)
client = mqtt.Client()
client.on_connect = on_connect
client.on_message = on_message
client.connect("localhost")
print("Waiting for connection...")
client.loop_forever()
EDIT 2: While playing around, I noted that replacing "localhost" with "test.mosquitto.org" resulted in OSError: [Errno 101] Network is unreachable although I have no problems connecting to it via mosquitto_sub
Does this code produce the same problem? This is probably the equivalent to the code at the point that it is failing.
import socket
sock = socket.create_connection(("test.mosquitto.org", 1883))

Categories

Resources