Paho mqtt client not working properly - python

I'm new to MQTT and raspberry pi! I'm running a client script and I simply publish a message using another script. I'm using my own Mosquitto broker.
Client:
import paho.mqtt.client as mqtt
def on_connect(client, userdata, flags, rc):
print("Connected with result code "+str(rc))
client.subscribe("Example/test")
client.subscribe("Example/topic")
def on_message(client, userdata, msg):
print(msg.topic+" "+str(msg.payload))
if msg.payload == "Hello":
print("Received message #1, do something")
if msg.payload == "World":
print("Received message #2, do something else")
client = mqtt.Client()
client.on_connect = on_connect
client.on_message = on_message
client.connect("192.168.1.4", 1883)
client.loop_forever()
Publisher:
import paho.mqtt.publish as publish
publish.single("Example/test", "Hello", hostname="192.168.1.4")
publish.single("Example/topic", "World", hostname="192.168.1.4")
print("OK")
That's where things seem weird and those things happen.
1.When I run both the client and the publisher using the python3 command the if statements are skipped and only topic + payload are printed
2.When I run the client using python command and publisher using both python3 and python command everything works fine!
3.When I do all the above, while running the client on virtualenv again the if statements are ignored, in all occasions!
I would like to know if there is a compatibility reason for this to happen, or anything wrong in the code as I must run something more complicated like that on virtualenv!
UPDATE: I found a solution that works fine !
In the client code in the if statement I used
if msg.payload == b"Hello":
and
if msg.payload == b"World":
As far as I know it must have been due to a variable type thing and they didn't match.

I found a solution that works fine !
In the client code in the if statement I used
if msg.payload == b"Hello":
and
if msg.payload == b"World":
As far as I know it must have been due to a variable type thing and they didn't match.

stumbled upon this post while trying Paho mqtt client -
It may be good to note how characters & bytes are treated in Python, as explained in detail in this post.
So, above snippet could also be written as,
if (msg.payload.decode() == 'Hello'):

Related

Python/paho MQTT - not receiving messages

I am new to using MQTT and I would like to run two Python programs simultaneously: one to publish messages to a topic and the other to print out the messages as they are published to the topic. However, the callback function to print out the message isn't working for me.
These are the two programs I have:
Publish messages:
import paho.mqtt.client as mqtt
def on_connect(client, userdata, flags, rc):
print("Connected! Result code: " + str(rc))
client = mqtt.Client(client_id="clientID")
client.on_connect = on_connect
client.username_pw_set(username="username", password="password")
client.loop_start()
client.connect("node02.myqtthub.com", 1883)
while True:
client.publish("my/topic", "test")
Subscribe to and print messages:
import paho.mqtt.client as mqtt
def on_message(client, userdata, msg):
print(msg.payload.decode())
def on_connect(client, userdata, flags, rc):
print("Connected! Result code: " + str(rc))
client.subscribe("my/topic")
client = mqtt.Client(client_id="clientID")
client.on_connect = on_connect
client.on_message = on_message
client.username_pw_set(username="username", password="password")
client.connect("node02.myqtthub.com", 1883)
client.loop_forever()
Could someone help me fix this issue?
Both programs are using client_id="clientID"; the mqtt spec states
If the ClientId represents a Client already connected to the Server then the Server MUST disconnect the existing Client [MQTT-3.1.4-2].
So whichever app connects second will cause the first to be disconnected. To fix this change the client id in one of the apps.
Note: This is a comment on something obviously wrong. When asking a question please state what you see happening (any output, errors, what you have tried etc) because there may be another problem.

Python2 vs Python3 - parsing JSON

I try to read MQTT messages using Python. For debugging purposes, I reduced the program at the minimum.
import paho.mqtt.client as mqtt
import json
def on_connect(client, userdata, flags, rc):
print("Connected with code " + str(rc))
client.subscribe("temperature")
def on_message(client, userdata, message):
if message.topic == "temperature":
print("New message received")
dhtreadings_json = json.loads(message.payload)
temperature = dhtreadings_json['temperature']
print(temperature)
mqttc = mqtt.Client()
mqttc.username_pw_set("user","password")
mqttc.on_connect = on_connect
mqttc.on_message = on_message
mqttc.connect("192.168.1.133",1883,60)
mqttc.loop_forever()
Under Python 2, everything works fine:
Under Python3, I got the connection established message and I am informed that a new message was received and this is all. More than this no other output after:
Environment: Latest version of Raspbian on Raspberry Pi 3B+
As suggested, I replaced to print ("New message received", message.payload).
The message.payload is the same in Python2 and Python3.
Python2:
Python3:
Thank you!
This will be because with Python3 the message.payload is a byte array and with Python2 it's a string. (this can be seen in the images you posted because the Python3 strings are proceeded with b'...)
The change is to move closer to the MQTT spec which treats all MQTT payloads as just a collection bytes and also not making any assumptions about what character set should be used to covert the payload to a string.
The following should work with Python3 (assuming the initial json is utf-8 encoded)
dhtreadings_json = json.loads(message.payload.decode("utf-8"))

How to exit mqtt forever_loop?

I created a program to receive data, recently.
And I want to break the loop When I receive a specific data.
For example, if I receive "1" to another machine, then my system will regard it
as an illegal number, then it will break the loop to stop receiving data.
Here is my code in the below, and you can also see client.loop_stop() in my code. But it not works.
I have also tried sys.exit() in my code.
Although it works in this case, it is not suitable to be utilized in other situation.
So I am wondering about how to break the loop of the client, I don't want to close the whole system by sys.exit().
import paho.mqtt.client as mqtt
# This is the Subscriber
a=""
def on_connect(client, userdata, flags, rc):
print("Connected with result code "+str(rc))
client.subscribe("hello")
def on_message(client, userdata, msg):
info=msg.payload.decode()
print info
if str(info)=='1':
print "OK"
client.loop_stop()
client = mqtt.Client()
client.connect("myIp",1883,60)
client.on_connect = on_connect
client.on_message = on_message
client.loop_forever()
In order to stop loop_forever, you must use client.disconnect, not loop_stop.

OpenCV (in C++) to MQTT broker

My goal is to publish from OpenCV (C++) a JSON stream of (x, y) coordinates to an MQTT broker. I'm confused as to a good way to transmit the JSON data to MQTT from OpenCV.
I currently have an MQTT broker that manages a JSON message queue between a Python publisher script on Computer 1 and a Javascript client script on Computer 2. I have Computer 3 running OpenCV and need to send many small JSON blobs of (x, y) coordinates in near real-time to the MQTT broker.
I initially considered continuously writing coordinates from OpenCV to a local text file, which is then continuously read by a Python MQTT publisher script that runs in parallel. However, there are issues around file locking and it seems that writing to disk is unnecessary.
Ideally, I'm hoping for the stream of coordinates to stay in memory and published to the MQTT broker often, say every 10ms. I'm struggling to find a way to use stdin/stdout to work between the OpenCV code and a Python publisher script.
Your guidance is appreciated. Thank you.
Not certain what parts you are missing, but you basically want:
#include "mqtt.h"
...
// Start up
mqtt_broker_handle_t *broker = mqtt_connect(client_name, ip_addr, port);
...
...
// Update broker
mqtt_publish(broker, topic, msg, QoS1);
You mentioned a python script for a publisher.
Here is the publisher:
#!/usr/bin/env python3
import paho.mqtt.client as mqtt
# This is the Publisher
client = mqtt.Client()
client.connect("localhost",1883,60)
client.publish("topic/test", "Hello world!", qos=0, retain=False)
client.disconnect()
Here is a subscriber:
#!/usr/bin/env python3
import paho.mqtt.client as mqtt
# This is the Subscriber
def on_connect(client, userdata, flags, rc):
print("Connected with result code "+str(rc))
client.subscribe("topic/test")
def on_message(client, userdata, msg):
if msg.payload.decode() == "Hello world!":
print("Yes!")
client.disconnect()
client = mqtt.Client()
client.connect("localhost",1883,60)
client.on_connect = on_connect
client.on_message = on_message
client.loop_forever()

Python Paho/MQTT : Detecting Connect error

In short, I have a Paho/MQTT sample set that works fine, but I'm having trouble detecting errors. Specifically, I'm not getting an on_connect callback and when an invalid UserID/Pswd combination is given, it fails silently.
In fact, by every indication, it all worked fine!
What am I doing wrong?
(snip)
def on_connect(client, userdata, flags, rc):
print("Connected with flags [%s] rtn code [%d]"% (flags, rc) )
def on_disconnect(client, userdata, rc):
print("disconnected with rtn code [%d]"% (rc) )
def on_publish(client, userdata, msgID):
print("Published with MsgID [%d]"% (msgID) )
mqttc = mqtt.Client()
mqttc.on_connect = on_connect
mqttc.on_disconnect = on_disconnect
mqttc.on_publish = on_publish
mqttc.username_pw_set(Q_USER, Q_PSWD)
rc=mqttc.connect(Q_BROKER, Q_PORT)
print "Return="+str(rc)
mqttc.loop_start()
rc=mqttc.publish(Q_TOPIC, "Hello, World!")
print "Return="+str(rc)
mqttc.disconnect()
mqttc.loop_stop()
Output when UserID or Pswd is deliberately wrong:
Return=0
Published with MsgID [1]
Return=(0, 1)
disconnected with rtn code [0]
Turns out that it was a few different issues.
First, Connect returns without truly being connected. Adding a wait loop with a Sleep until the Connect callback is received is crucial. Only the callback tells you the Connect succeeded or failed.
Second, once I saw the return code, I saw mine was failing on Protocol Version Mismatch. The Mosquitto version my Pi was pulling down was REALLY old. Found a post that pointed my system to a newer version. Solved the version mismatch problem.
Third, adding the "loop_start()" before Connect does not work. The intuitive place is not the right place.
Fourth, one needs to add Sleep() calls before Disconnect, or you will not see all the Callbacks.
Bottom line, while the docs show how to use the APIs, they don't show you how to write a robust program for production use.
I'm still still looking for ways to know when all in-flight publish calls have cleared, rather than using a blind Sleep call, but my original issue is resolved.
When you send mqtt CONNECT packet, you should receive CONNACK response. This response contains the following codes
0 - success, connection accepted
1 - connection refused, bad protocol
2 - refused, client-id error
3 - refused, service unavailable
4 - refused, bad username or password
5 - refused, not authorized
As you can see, your response should be 4. But it is zero. It might be that you broker doesn't check credentials so your connect message is accepted. Client looks fine.
Try to put the publish into a while loop like this
while True:
mqttc.loop()
rc=mqttc.publish(Q_TOPIC, "Hello, World!")
print("Return=" + str(rc))
if sth:
break
mqttc.disconnect()
In this way, the callback function may be executed before the program ends.

Categories

Resources