Публикация и подписка в обе стороны с использованием MQTT Python

1

В настоящее время у меня есть программа Python, написанная на малине Pi 3, чтобы читать данные о влажности и температуре и публиковать эти данные в теме. Затем я могу получить эти данные с помощью своего ноутбука. Вот мой код для чтения данных датчиков и публикации его в теме из моей малины Pi:

import RPi.GPIO as GPIO
import time
import json
import Adafruit_DHT as dht
import math
import paho.mqtt.publish as publish
import paho.mqtt.client as mqtt
# Creating the JSON Objects

dht22 = {}
arduino = {}
dht22Temp = []
dht22Hum = []
arduinoLED = []


dht22['temperature'] = dht22Temp
dht22['humidity'] = dht22Hum
dht22['sensor'] = 'DHT22'

arduino['blink'] = arduinoLED
arduino['actuator'] = 'arduinoLED'  

# Timing constants
E_PULSE = 0.0005
E_DELAY = 0.0005

def main():
  # Main program block
  while True:

    h, t = dht.read_retry(dht.DHT22, 17) //Reading humidity and temp data from GPIO17
    t = round(t,2)
    h = round(h,2)

    if t > 25: 
      if len(arduinoLED) == 3:
        arduinoLED.pop(0)
        arduinoLED.append("true")
      else: 
        arduinoLED.append("true")
    else:
      if len(arduinoLED) == 3:
        arduinoLED.pop(0)
        arduinoLED.append("false")
      else: 
        arduinoLED.append("false")
    if len(dht22Temp) == 3:
      dht22Temp.pop(0)
      dht22Temp.append(t)
    else: 
      dht22Temp.append(t)
    if len(dht22Hum) == 3:
      dht22Hum.pop(0)
      dht22Hum.append(h)
    else: 
      dht22Hum.append(h)
    # lm35dzTemp.append(tempc) 


    # Publishing sensor information by JSON converting object to a string
    publish.single("topic/sensorTemperature", json.dumps(dht22), hostname = "test.mosquitto.org")
    publish.single("topic/sensorTemperature", json.dumps(arduino), hostname = "test.mosquitto.org")

    # Printing JSON objects
    print(dht22)
    print(arduino)
    time.sleep(2)

if __name__ == '__main__':

  try:
    main()
  except KeyboardInterrupt:
    pass
  finally:

    GPIO.cleanup()

Вот мой код для подписки и получения данных с моего ноутбука:

import paho.mqtt.client as mqtt
import json

# This is the Subscriber
def on_connect(client, userdata, flags, rc):
    print("Connected with result code " + str(rc))
    client.subscribe("topic/sensorTemperature")


def on_message(client, userdata, msg):
    print(json.loads(msg.payload)) #converting the string back to a JSON object

client = mqtt.Client()

client.on_connect = on_connect
client.on_message = on_message

client.connect("test.mosquitto.org", 1883, 60)

client.loop_forever()

То, что я хочу сделать, теперь опубликовать что-то с моего ноутбука (возможно, в том же коде, что и подписчик, или в отдельном файле, который просто опубликует сообщение в той же теме - "topic/sensorTemperature"). Но мой вопрос: как я также публиковать и подписываться на сообщения на моей Малиновой Пи (в моем первом коде, который я опубликовал)? Поскольку я публикую сообщения в бесконечном цикле на моем ноутбуке, мне также понадобится бесконечный цикл для подписки на тот же (или другой раздел), чтобы получать сообщения. Как вы запускаете сразу две из этих петель? Мне нужны два разных потока?

Спасибо.

Теги:
mqtt

3 ответа

1
Лучший ответ

Как предложил Сергей, вы можете использовать loop_start для создания отдельного потока для приема сообщений.

Вот как ваша основная функция будет выглядеть так:

def main():
    # Create a new client for receiving messages
    client = mqtt.Client()
    client.on_connect = on_connect
    client.on_message = on_message
    client.subscribe(topic)
    client.connect(mqttserver)
    client.loop_start()
    while True:
        #code for publishing
        pass
1

Просто поставьте свой код из subscribing script в subscribing script publishing script до этого, while True: и замените loop_forever() на loop_start(). Используйте loop_stop() когда вы запускаете скрипт перед GPIO.cleanup().

1

Самый простой способ - запустить еще один процесс Python (аналогично вашему сценарию для ноутбука) на Малине параллельно, обрабатывая сообщения, полученные от ноутбука.

Но если вы хотите реализовать все в одном скрипте, вы можете расширить свой второй фрагмент кода (обработка сообщений) с помощью реализации первого фрагмента (данные датчиков публикации).

Конечно, вы не можете использовать loop_forever() в этом случае. Когда вы вызываете loop_forever(), он никогда не вернется, пока клиент не вызовет disconnect(), поэтому вы не можете обрабатывать полученные сообщения (основной поток заблокирован). Клиент Paho также имеет подпрограммы loop() и loop_start()/loop_stop() для управления сетевым циклом. Посмотрите на них:

1) Функция loop() может принимать таймаут в качестве аргумента. Он будет блокироваться до тех пор, пока не поступит новое сообщение или не исчезнет время. В первом случае - заготовку обрабатывать полученное сообщение и вычислять время до следующего опубликования. Повторите это время как параметр для цикла(). Во втором случае просто опубликуйте данные и вызовите loop() со временем до следующего опубликования (2 секунды в вашем примере).

2) loop_start()/loop_stop() запускает и останавливает фоновый поток, выполняющий работу по отправке и получению (и обработке) данных для вас. Создайте клиент, зарегистрируйте обратный вызов on_message(), подключитесь/подписайтесь и вызовите loop_start(), чтобы запустить этот поток. Основной поток бесплатно для вас сейчас - используйте его с логикой первого фрагмента (цикл с 2-секундным сном).

Ещё вопросы

Сообщество Overcoder
Наверх
Меню