I have a temperature sensor connected to raspberry via MQTT on ESP32 controller, it display correctly temperature in Arduino IDE serial monitor also in Home Assistant webpage.
I am trying to get it display on Raspberry Pi console with a python 3 script. it display the value but add charachteres --> b' 22.71'
I tried to strip characters or display values from specific position without success. I need to have only temperature value for export it.
the script is
import paho.mqtt.client as mqtt
def on_connect(client, userdata, rc, *extra_params):
client.subscribe("ha/temperature")
def on_message(client, userdata, msg):
if msg.topic == 'ha/temperature':
print(msg.payload)
client = mqtt.Client("test")
client.on_connect = on_connect
client.on_message = on_message
client.username_pw_set(username="username",password="password")
client.connect("192.168.0.100", 1883, 60)
client.loop_forever()
the result is:
pi#raspberrypi:~ $ sudo python3 BasicMQTT.py
b' 22.71'
b' 22.71'
b' 22.71'
b' 22.71'
how it can be strip "b" "'" and space characters from output?
thanks in advance
This is because with python3 the paho library is returning a byte array not the string representation of the byte array for the payload.
You can fix changing the on_message callback as follows:
def on_message(client, userdata, msg):
if msg.topic == 'ha/temperature':
print(msg.payload.decode("utf-8") )
Related
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"))
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'):
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.
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()
I'm trying to send a jpg image using MQTT mosquitto broker(pub and sub) in Raspberry Pi2.
This is my python code pub.py(modified)
import paho.mqtt.client as mqtt
def on_publish(mosq, userdata, mid):
mosq.disconnect()
client = mqtt.Client()
client.connect("test.mosquitto.org", 1883, 60)
client.on_publish = on_publish
f=open("b.jpg", "rb") #3.7kiB in same folder
fileContent = f.read()
byteArr = bytearray(fileContent)
client.publish("image",byteArr,0)
client.loop_forever()
and it's sub.py(modified)
import paho.mqtt.client as mqtt
def on_connect(client, userdata, rc):
print("Connect" + str(rc))
client.subscribe("image")
def on_message(client, userdata, msg):
print "Topic : ", msg.topic
f = open("/tmp/output.jpg", "w") #there is a output.jpg which is different
f.write(msg.payload)
f.close()
client = mqtt.Client()
client.on_connect = on_connect
client.on_message = on_message
client.connect("test.mosquitto.org", 1883, 60)
client.loop_forever()
My python verson is 2.7.9.
After I solved some error, It seems to work but It doesn't.
When I implement the sub.py, It connects successfully so I implement the pub.py in other terminal.
However, There isn't any reaction without connect message which is "Connect with result code 0"
There is no error message so I don't know what my mistake is.
Tested Code:
Requirements:
Install Mosquitto Broker
Install paho.mqtt package.
pub.py
import paho.mqtt.publish as publish
MQTT_SERVER = "xxx.xxx.xxx.xxx" #Write Server IP Address
MQTT_PATH = "Image"
f=open("image_test.jpg", "rb") #3.7kiB in same folder
fileContent = f.read()
byteArr = bytearray(fileContent)
publish.single(MQTT_PATH, byteArr, hostname=MQTT_SERVER)
One small modification, file permission is write byte instead of write mode.
sub.py
import paho.mqtt.client as mqtt
MQTT_SERVER = "localhost"
MQTT_PATH = "Image"
# 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(MQTT_PATH)
# The callback for when a PUBLISH message is received from the server.
def on_message(client, userdata, msg):
# more callbacks, etc
# Create a file with write byte permission
f = open('output.jpg', "wb")
f.write(msg.payload)
print("Image Received")
f.close()
client = mqtt.Client()
client.on_connect = on_connect
client.on_message = on_message
client.connect(MQTT_SERVER, 1883, 60)
# Blocking call that processes network traffic, dispatches callbacks and
# handles reconnecting.
# Other loop*() functions are available that give a threaded interface and a
# manual interface.
client.loop_forever()
Expected Output:
Able to transfer the Image from Raspberry Pi to server machine.
In sub.py you have 2 on_public functions which should be renamed on_connect and on_publish respectively.
In pub.py you need to actually set the on_publish method on the client so it will be called once the publish has been completed.
...
client.connect("test.mosquitto.org", 1883, 60)
client.on_publish = on_public
...
Also as #ralight pointed out in his answer to your previous question, you should change client.loop(5) to client.loop_forever() it will still exit once the message has been sent because of the mosq.disconnect()
In your sub.py you need a callback which handles incoming messages for your subscription. The standard callback for that is on_message.
Just rename in your sub.y on_publish(client, userdata, msg) to on_message(client, userdata, msg)and assign client.on_message = on_message.