3. 使用通配符订阅多个主题
任务目标
在MQTT中,通配符用于一次订阅多个匹配的主题,避免逐条订阅。本案例使用+(单层通配符)和#(多层通配符)订阅一组主题,并通过发布消息验证匹配规则。
环境准备
需要安装 paho-mqtt 客户端库,并准备一个可用的MQTT Broker(如公共Broker broker.emqx.io:1883)。
pip install paho-mqtt
完整实现代码
import paho.mqtt.client as mqtt
import time
BROKER = "broker.emqx.io"
PORT = 1883
TOPIC_BASE = "demo/wildcard"
# 订阅回调:打印收到的主题和消息
def on_message(client, userdata, msg):
print(f"收到消息: topic={msg.topic}, payload={msg.payload.decode()}")
# 连接回调
def on_connect(client, userdata, flags, rc):
print(f"连接结果: {rc}")
# 使用通配符订阅:
# '+' 匹配 demo/wildcard/ 下的任意一层
# '#' 匹配 demo/wildcard/ 下的所有后续层级
client.subscribe([(f"{TOPIC_BASE}/+/temp", 0), (f"{TOPIC_BASE}/#", 0)])
client = mqtt.Client()
client.on_connect = on_connect
client.on_message = on_message
client.connect(BROKER, PORT, 60)
client.loop_start()
# 等待连接建立
time.sleep(1)
# 发布测试消息,验证匹配规则
test_cases = [
(f"{TOPIC_BASE}/room1/temp", "25.5"), # 应被 + 和 # 匹配
(f"{TOPIC_BASE}/room2/temp", "26.0"), # 应被 + 和 # 匹配
(f"{TOPIC_BASE}/room1/humidity", "60%"), # 仅被 # 匹配(+ 只匹配一层)
(f"{TOPIC_BASE}/floor1/room1/temp", "24.8"), # 仅被 # 匹配(+ 不匹配多层)
]
for topic, payload in test_cases:
client.publish(topic, payload)
time.sleep(0.5)
# 等待消息回调完成
time.sleep(2)
client.loop_stop()
client.disconnect()
运行与验证
直接运行上述Python脚本。观察控制台输出,验证匹配规则:
demo/wildcard/room1/temp和demo/wildcard/room2/temp会被打印两次(分别由+/temp和#两个订阅匹配)。demo/wildcard/room1/humidity和demo/wildcard/floor1/room1/temp只会被打印一次(仅由#匹配)。
通过条件:输出结果与上述预期完全一致,即每条消息至少被打印一次,且前两条消息各出现两次,后两条各出现一次,说明+只匹配单层、#匹配剩余所有层级。
匹配规则说明
+:匹配一个层级。例如demo/wildcard/+/temp可匹配demo/wildcard/任意名/temp,但不能匹配demo/wildcard/a/b/temp。#:匹配多个层级(含零个)。例如demo/wildcard/#可匹配demo/wildcard/下的任意深度主题。- 通配符只能位于主题末尾(
#)或单独占一层(+),不能出现在主题中间(如demo/+/temp合法,但demo/#/temp非法)。