将MQTT主题和消息放入数组中

0 投票
2 回答
6358 浏览
提问于 2025-04-18 00:01

我对Python完全是个新手,对MQTT的了解也非常基础。

我想写一个Python脚本,订阅一个通配符主题,然后建立一个这个通配符下的主题列表。我知道MQTT协议本身不支持这个功能,所以我得通过Python来实现。我在想把主题和消息放在一个数组里。

我有以下这些主题:

/weather/current/temperature

/weather/current/humidity

/weather/current/pressure

/weather/current/time

在我的Python脚本中,我订阅的是 /weather/current/#。

比如,我想象中的数组可能是这样的:

[/weather/current/temperature,message]

[/weather/current/humidity,message]

[/weather/current/pressure,message]

[/weather/current/time,message]

我的脚本基本上是一个标准的例子,我尝试了几种方法来实现这个功能,但都没有成功。我觉得我最大的问题是对on_message这个函数的理解不够。这个函数是针对所有主题执行一次,还是每个主题执行一次呢?

def on_connect(mqttc, obj, rc):
    print("rc: "+str(rc))

def on_message(mqttc, obj, msg,):
    # print(msg.topic+" "+str(msg.payload))
    payload = str(msg.payload)
    print(msg.topic+" Payload -> "+payload)

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

def on_subscribe(mqttc, obj, mid, granted_qos):
    print("Subscribed: "+str(mid)+" "+str(granted_qos))

def on_log(mqttc, obj, level, string):
    print(string)

try:
    mqttc = mqtt.Client("Python-MQTT-Sub")

    mqttc = mqtt.Client()
    mqttc.on_message = on_message
    mqttc.on_connect = on_connect
    mqttc.on_publish = on_publish
    mqttc.on_subscribe = on_subscribe
    # Uncomment to enable debug messages
    #mqttc.on_log = on_log
    mqttc.connect("localhost", 1883, 60)
    mqttc.subscribe("/weather/current/#", 0)

    mqttc.loop_forever()

except KeyboardInterrupt:
    print("\ninterrupt received, exiting...")

2 个回答

2

on_message 是在收到来自消息代理的消息时被调用的。这些消息可以是你订阅的任何主题的内容,比如说 /weather/current 及其以上的主题。虽然你只用了一次订阅,但每条消息都是独立的事件。

还有一个小建议 - 通常不建议把客户端 ID 写死在代码里,除非你把 clean session 设置为 false。如果客户端 ID 重复,你会被从消息代理断开连接。要么自己生成一个独特的 ID,要么在调用 Client() 时不指定客户端 ID,这样系统会自动生成一个随机的 ID。

最后一点 - 除非有特别的原因,否则其实没有必要在主题前加斜杠。前面的斜杠会增加一个额外的层级,第一层是一个空字符串。这可能和你预想的有些不同,所以在某些情况下会让人感到困惑。

3

正如@ralight上面所说,on_message是在收到消息时被调用的(这条消息可能是保留消息,也可能不是)。为了说明这一点,我稍微修改了你的代码,添加了一个叫topic_names的数组,这个数组会随着消息的到来而被填充。

import paho.mqtt.client as mqtt 

topic_names = []

def on_message(mqttc, obj, msg,):
    # print(msg.topic + " " + str(msg.payload))
    payload = str(msg.payload)
    print(msg.topic + " Payload -> " + payload)

    topic_names.append(msg.topic)

try:
    mqttc = mqtt.Client()
    mqttc.on_message = on_message

    mqttc.connect("localhost", 1883, 60)
    mqttc.subscribe("weather/current/#", 0)

    mqttc.loop_forever()

except KeyboardInterrupt:
    print "Received topics:"
    for topic in topic_names:
        print topic

运行这个程序并向它发布两条消息后,会显示

weather/current/temp Payload -> Fair
weather/current/humidity Payload -> 10
^C
weather/current/temp
weather/current/humidity

撰写回答