2016-05-03 54 views
3

MQTT問題:蟒蛇MQTT腳本來發送和接收消息

嗨,我試圖建立多樹莓派之間的MQTT網絡(從2開始)。 我有一個覆蓋有熱敏電阻傳感器的樹莓派(RPi-A)MQTT客戶端,以及一個作爲我的網絡集線器的覆盆子(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() 
+0

是你看到什麼實際的錯誤?代碼看起來是正確的(RPI-A在循環之前不需要任何MQTT客戶端代碼,因爲您使用的是'publish.single'),並且RPI-B代碼乍看之下看起來不錯。 – hardillb

+0

@hardillb感謝您的回覆,我希望RPi-A接收來自RPi-B的mqtt消息以及發送它們,所以我想我需要客戶端mqtt代碼。我本身沒有出現錯誤,但是RPi-B似乎沒有發送消息來響應RPi-A。 –

+0

對不起,錯過了那一點。提供的答案 – hardillb

回答

5

最簡單的方法是開始於一個單獨的線程在網絡環使用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) 
+0

超級的東西,工作的一種享受:)非常感謝你。
我應該甚至在RPi-B上使用client.loop_forever(),還是應該用client.loop_start()替換它? –

+0

保持原樣,因爲該用例是正確的 – hardillb