В настоящее время у меня есть программа 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"
). Но мой вопрос: как я также публиковать и подписываться на сообщения на моей Малиновой Пи (в моем первом коде, который я опубликовал)? Поскольку я публикую сообщения в бесконечном цикле на моем ноутбуке, мне также понадобится бесконечный цикл для подписки на тот же (или другой раздел), чтобы получать сообщения. Как вы запускаете сразу две из этих петель? Мне нужны два разных потока?
Спасибо.
Как предложил Сергей, вы можете использовать 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
Просто поставьте свой код из subscribing script
в subscribing script
publishing script
до этого, while True:
и замените loop_forever()
на loop_start()
. Используйте loop_stop()
когда вы запускаете скрипт перед GPIO.cleanup()
.
Самый простой способ - запустить еще один процесс 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-секундным сном).