Как я могу опубликовать файл с помощью Mosquitto на Python?

Я использую python-mosquitto для подписки на моего брокера MQTT, который поддерживает загрузку типов файлов. Я могу использовать его с флагом -f при переходе из Mosquitto в командную строку. Однако я не могу понять, как использовать client.publish (тема, полезная нагрузка), чтобы указать файл для публикации, когда это делается из моего скрипта python.

Python mosquitto выдает ошибку TypeError: payload must be a string, bytearray, int, float or None., когда я пытаюсь бросить в него что-то странное. У меня уже есть файл, хранящийся в локальном каталоге, который я хочу указать в качестве полезной нагрузки публикации.

У меня есть опыт работы с MQTT, но мой питон очень ржавый, я предполагаю, что мне нужно сделать здесь какой-то тип функции потока файлов, но не знаю, как это сделать.

Я хочу указать здесь изображение: 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 не вызывает ошибок, но файл не получен брокером должным образом. Любые идеи?

Спасибо!!


person calumb    schedule 22.10.2013    source источник


Ответы (2)


Стоит отметить, что это одна из областей, в которых могут быть различия между Python 2 и Python 3.

Python 2 file.read() возвращает str, тогда как 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()
person ralight    schedule 22.10.2013
comment
Оба ответа сработали, оказалось, что это было отсутствие client.loop_forever() в моем коде, и широкий спектр преобразований byteArray работал хорошо. Для меня было странно, что я смог опубликовать текст типа hello world без необходимости в цикле навсегда, но при создании файла (около 70 КБ) он нуждался в loop_forever(). Спасибо за вашу помощь! - person calumb; 24.10.2013

Публикация должна быть всего файла сразу, поэтому вам нужно будет прочитать весь файл и опубликовать его за один раз.

Следующий код работает

#!/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)
person hardillb    schedule 22.10.2013