скрипт python mqtt на raspberry pi для отправки и получения сообщений

MQTT вопрос:

Привет, я пытаюсь настроить сеть MQTT между несколькими Raspberry Pis (начиная с двух). У меня есть один Raspberry Pi (RPi-A), клиент MQTT с подключенным термисторным датчиком, и один Raspberry Pi (RPi-B), брокер / клиент MQTT, выступающий в качестве концентратора для моей сети. С помощью скриптов на Python я хотел бы, чтобы температура отправлялась каждые 30 минут с RPi-A через MQTT на датчик / данные темы и принималась RPi-B. Когда RPi-B получает сообщение от RPi-A через датчик / данные темы, я хочу, чтобы он ответил инструкцией через датчик темы / инструкции MQTT для RPi-A. Ниже мой сценарий, пока RPi-A может отправлять сообщения, а RPi-B получать их, но я не могу понять, как RPi-B может ответить.

По сути, я пытаюсь понять, может ли устройство MQTT действовать одновременно как брокер и клиент? И может ли клиент как отправлять, так и получать сообщения, и если да, то как реализовать все вышеперечисленное через python? Я прочитал много блогов, официальных статей MQTT и документации модуля paho (что для меня очень сложно понять), но до сих пор не могу понять этого. Ваша помощь будет очень полезна / оценена.

Код RPi-A (с термисторным датчиком):

from sense_hat import SenseHat
import time
import paho.mqtt.client as mqtt
import paho.mqtt.publish as publish
sense = SenseHat()

Broker = "192.168.1.252"

sub_topic = "sensor/instructions"    # receive messages on this topic

pub_topic = "sensor/data"       # send messages to this topic


############### sensehat inputs ##################

def read_temp():
    t = sense.get_temperature()
    t = round(t)
    return t

def read_humidity():
    h = sense.get_humidity()
    h = round(h)
    return h

def read_pressure():
    p = sense.get_pressure()
    p = round(p)
    return p

def display_sensehat(message):
    sense.show_message(message)
    time.sleep(10)

############### MQTT section ##################

# when connecting to mqtt do this;

def on_connect(client, userdata, flags, rc):
    print("Connected with result code "+str(rc))
    client.subscribe(sub_topic)

# when receiving a mqtt message do this;

def on_message(client, userdata, msg):
    message = str(msg.payload)
    print(msg.topic+" "+message)
    display_sensehat(message)

def publish_mqtt(sensor_data):
    mqttc = mqtt.Client("python_pub")
    mqttc.connect(Broker, 1883)
    mqttc.publish(pub_topic, sensor_data)
    #mqttc.loop(2) //timeout = 2s

def on_publish(mosq, obj, mid):
    print("mid: " + str(mid))


client = mqtt.Client()
client.on_connect = on_connect
client.on_message = on_message
client.connect(Broker, 1883, 60)


while True:
    sensor_data = [read_temp(), read_humidity(), read_pressure()]
    publish.single("monto/solar/sensors", str(sensor_data), hostname = Broker)
    time.sleep(1*60)

Код RPi-B (сетевой концентратор):

import time
import paho.mqtt.client as mqtt
import paho.mqtt.publish as publish

Broker = "192.168.1.252"

sub_topic = "sensor/data"    # receive messages on this topic

pub_topic = "sensor/instructions"               # send messages to this topic


# mqtt section

# when connecting to mqtt do this;

def on_connect(client, userdata, flags, rc):
    print("Connected with result code "+str(rc))
    client.subscribe(sub_topic)

# when receiving a mqtt message do this;

def on_message(client, userdata, msg):
    message = str(msg.payload)
    print(msg.topic+" "+message)
    publish_mqtt(‘got your message’)

# to send a message

def publish_mqtt(sensor_data):
    mqttc = mqtt.Client("monto_hub")
    mqttc.connect(Broker, 1883)
    mqttc.publish(pub_topic, "this is the master speaking")
    #mqttc.loop(2) //timeout = 2s

def on_publish(mosq, obj, mid):
    print("mid: " + str(mid))


client = mqtt.Client()
client.on_connect = on_connect
client.on_message = on_message
client.connect(Broker, 1883, 60)
client.loop_forever()

person Tullio_IRL    schedule 03.05.2016    source источник
comment
Какую фактическую ошибку вы видите? Код выглядит примерно правильно (RPI-A не нуждается в каком-либо клиентском коде MQTT перед циклом, поскольку вы используете publish.single), а код RPI-B на первый взгляд выглядит нормально.   -  person hardillb    schedule 03.05.2016
comment
@hardillb спасибо за ответ, я хочу, чтобы RPi-A получал сообщения mqtt от RPi-B, а также отправлял их, поэтому я подумал, что мне понадобится код client-mqtt. Я не получаю сообщения об ошибке, но похоже, что RPi-B не отправляет сообщения в ответ на RPi-A.   -  person Tullio_IRL    schedule 03.05.2016
comment
Извините, что пропустил этот бит. Предоставлен ответ   -  person hardillb    schedule 03.05.2016


Ответы (1)


Самый простой способ - запустить сетевой цикл в отдельном потоке с помощью функции client.loop_start(), а затем использовать обычный метод client.publish

from sense_hat import SenseHat
import time
import paho.mqtt.client as mqtt
import paho.mqtt.publish as publish
sense = SenseHat()

Broker = "192.168.1.252"

sub_topic = "sensor/instructions"    # receive messages on this topic

pub_topic = "sensor/data"       # send messages to this topic


############### sensehat inputs ##################

def read_temp():
    t = sense.get_temperature()
    t = round(t)
    return t

def read_humidity():
    h = sense.get_humidity()
    h = round(h)
    return h

def read_pressure():
    p = sense.get_pressure()
    p = round(p)
    return p

def display_sensehat(message):
    sense.show_message(message)
    time.sleep(10)

############### MQTT section ##################

# when connecting to mqtt do this;

def on_connect(client, userdata, flags, rc):
    print("Connected with result code "+str(rc))
    client.subscribe(sub_topic)

# when receiving a mqtt message do this;

def on_message(client, userdata, msg):
    message = str(msg.payload)
    print(msg.topic+" "+message)
    display_sensehat(message)

def on_publish(mosq, obj, mid):
    print("mid: " + str(mid))


client = mqtt.Client()
client.on_connect = on_connect
client.on_message = on_message
client.connect(Broker, 1883, 60)
client.loop_start()

while True:
    sensor_data = [read_temp(), read_humidity(), read_pressure()]
    client.publish("monto/solar/sensors", str(sensor_data))
    time.sleep(1*60)
person hardillb    schedule 03.05.2016
comment
Супер материал, который сработал :) Большое спасибо. ‹Br/› Следует ли мне вообще использовать client.loop_forever () на RPi-B или я должен заменить его на client.loop_start ()? - person Tullio_IRL; 03.05.2016
comment
Большое вам спасибо за этот ответ. Это сработало и для меня - person Tia; 27.05.2018