5

我正在使用 python-mosquitto 订阅支持文件类型上传的 MQTT 代理。从命令行上的 Mosquitto 使用 -f 标志时,我可以很好地使用它。但是,我不知道如何使用 client.publish(topic, payload) 在我的 python 脚本中指定要发布的文件。

TypeError: payload must be a string, bytearray, int, float or None.当我尝试向它抛出一些奇怪的东西时,Python mosquitto 给了我错误。我已经在本地目录中存储了一个文件,我想将其指定为发布的有效负载。

我对 MQTT 有经验,但我的 python 很生锈,我假设我需要在这里做某种类型的文件流功能,但不知道该怎么做。

我想在这里指定图像:mqttc.publish("/v3/device/file", NEED_TO_SPECIFY_HERE)

我尝试通过以下方式打开图像:

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

但这没有用,也没有mqttc.publish("/v3/device/file", bytearray(open('/tmp/test.png', 'r').read()))

client.publish 不会引发错误,但代理没有正确接收文件。有任何想法吗?

谢谢!!

4

2 回答 2

12

发布必须立即成为整个文件,因此您需要读入整个文件并一次性发布。

以下代码有效

#!/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)

并且可以收到

#!/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)
于 2013-10-22T07:37:25.907 回答
6

值得注意的是,这是 Python 2 和 Python 3 之间可能存在差异的领域之一。

Python 2file.read()返回 astr而 Python 3 是bytes. mosquitto.publish()处理这两种类型,所以在这种情况下你应该没问题,但这是需要注意的。

我在下面的@hardillb 代码中添加了我认为的一些小改进。请不要接受我的回答而不是他的回答,因为他最初写了它并先到了那里!我会编辑他的答案,但我认为看到差异很有用。

#!/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()
于 2013-10-22T09:11:10.913 回答