문제

I am using python-mosquitto to subscribe to my MQTT broker which support file type uploads. I can use it just fine using the -f flag when going from Mosquitto on the command line. However, I can't figure out how to use the client.publish(topic, payload) to specify a file to publish when doing it from within my python script.

Python mosquitto gives me the error TypeError: payload must be a string, bytearray, int, float or None. when I try to throw something weird at it. I have a file stored in local directory already which I want to specify as the payload of the publish.

I'm experienced with MQTT but my python is very rusty, I am assuming I need to do some type of file stream function here, but not sure how to do it.

I want to specify the image here: mqttc.publish("/v3/device/file", NEED_TO_SPECIFY_HERE)

I have tried opening the image by doing:

    f = open("/home/pi/mosq/imagecap/imagefile.jpg", "rb")
    imagebin = f.read()
    mqttc.publish("/v3/device/file", imagebin)

But that didn't work and neither did mqttc.publish("/v3/device/file", bytearray(open('/tmp/test.png', 'r').read()))

The client.publish doesnt throw an error with those, but the file is not received properly by the broker. Any ideas?

Thanks!!

도움이 되었습니까?

해결책 2

It's worth noting that this is one of the areas that can have differences between Python 2 and Python 3.

Python 2 file.read() returns a str whereas Python 3 is bytes. mosquitto.publish() handles both types so you should be ok in that case, but it is something to be aware of.

I've added what I consider some minor improvements to @hardillb 's code below. Please don't accept my answer in preference to his because he wrote it originally and got there first! I would have edited his answer, but I think it's useful to see the difference.

#!/usr/bin/python

import mosquitto

def on_publish(mosq, userdata, mid):
  # Disconnect after our message has been sent.
  mosq.disconnect()

# Specifying a client id here could lead to collisions if you have multiple
# clients sending. Either generate a random id, or use:
#client = mosquitto.Mosquitto()
client = mosquitto.Mosquitto("image-send")
client.on_publish = on_publish
client.connect("127.0.0.1")

f = open("data")
imagestring = f.read()
byteArray = bytes(imagestring)
client.publish("photo", byteArray ,0)
# If the image is large, just calling publish() won't guarantee that all 
# of the message is sent. You should call one of the mosquitto.loop*()
# functions to ensure that happens. loop_forever() does this for you in a
# blocking call. It will automatically reconnect if disconnected by accident
# and will return after we call disconnect() above.
client.loop_forever()

다른 팁

The publish has to be the whole file at once, so you will need to read the whole file in and publish it in one go.

The following code works

#!/usr/bin/python

import mosquitto

client = mosquitto.Mosquitto("image-send")
client.connect("127.0.0.1")

f = open("data")
imagestring = f.read()
byteArray = bytes(imagestring)
client.publish("photo", byteArray ,0)

And can be received with

#!/usr/bin/python

import time
import mosquitto

def on_message(mosq, obj, msg):
  with open('iris.jpg', 'wb') as fd:
    fd.write(msg.payload)


client = mosquitto.Mosquitto("image-rec")
client.connect("127.0.0.1")
client.subscribe("photo",0)
client.on_message = on_message

while True:
   client.loop(15)
   time.sleep(2)
라이센스 : CC-BY-SA ~와 함께 속성
제휴하지 않습니다 StackOverflow
scroll top