IoT-For-Beginners 的 MQTT 消息发布后订阅端收不到,如何排查 Topic 与 QoS 配置
2026/9/15 17:33:41 网站建设 项目流程

IoT-For-Beginners 的 MQTT 消息发布后订阅端收不到,如何排查 Topic 与 QoS 配置

【免费下载链接】IoT-For-Beginners12 Weeks, 24 Lessons, IoT for All!项目地址: https://gitcode.com/GitHub_Trending/io/IoT-For-Beginners

在 IoT-For-Beginners 课程的第 4 课(Connect your device to the Internet)中,夜灯示例会把 Wio Terminal 或 Raspberry Pi(也可以是用 CounterFit 搭建的虚拟设备)接入公共 MQTT 测试 brokertest.mosquitto.org:设备把光敏读数发布到<ID>/telemetry主题,本地运行的 Python 服务端代码订阅该主题,再向<ID>/commands主题发布 LED 开关命令,设备订阅这个命令主题。如果你看到设备端已经打印出 "Sending telemetry"、服务端却一条 "Message received" 都没有(或者反向:命令发出去设备没反应),问题通常出在 Topic 或 QoS 配置上。本文按项目 TROUBLESHOOTING.md 中 "MQTT messages not received" 一节的排查项,结合 第 4 课主文档 给出的示例代码与验证输出,给出一条可核对的排查路径。

先确认两端真的连上了 broker

排查 Topic 和 QoS 之前,先确认发布方和订阅方都已经和 broker 建立连接,否则消息根本没有进入 broker。

  • Wio Terminal:上传代码后打开 PlatformIO 的 Serial Monitor,确认出现以下输出(文档示例):

    Connecting to WiFi.. Connected! Attempting MQTT connection...connected
  • Raspberry Pi / 虚拟设备:运行app.py后终端应打印MQTT connected!(文档示例)。

如果连接这一步就失败,按 TROUBLESHOOTING.md "MQTT connection fails" 一节逐项检查:broker 地址是否正确、端口(1883 为未加密,8883 为 TLS)、需要用户名/密码时凭据是否正确、TLS 证书是否有效可信、防火墙是否放行了端口。课程示例中 Wio Terminal 用client.setServer(BROKER.c_str(), 1883)连接test.mosquitto.org的 1883 端口,服务端app.pymqtt_client.connect('test.mosquitto.org')连接。

检查一:发布方与订阅方的 Topic 是否完全一致

TROUBLESHOOTING.md 对该问题的第一条建议是:Verify subscriber topic matches publisher topic exactly——订阅方订阅的 Topic 必须与发布方发布的 Topic 逐字符一致。

课程代码里两端的 Topic 都基于同一个唯一 ID 拼出来:

Wio Terminal 的config.h(见 wio-terminal-mqtt.md 与 wio-terminal-telemetry.md):

const string CLIENT_TELEMETRY_TOPIC = ID + "/telemetry"; const string SERVER_COMMAND_TOPIC = ID + "/commands";

服务端app.py(见 README.md "Write the server code" 一节):

id = '<ID>' client_telemetry_topic = id + '/telemetry' server_command_topic = id + '/commands'

<ID>是读者必须提供的值:课程要求替换成一个唯一 ID,并明确警告服务端代码里的id必须与设备端使用的 ID 相同,"or the server code won't subscribe or publish to the right topic"。因为test.mosquitto.org是公共 broker,被许多使用者(包括其他正在上这门课的人)共用,使用唯一 ID 和唯一 Topic 是为了避免与别人冲突。Pi / 虚拟设备端的代码同样是client_telemetry_topic = id + '/telemetry'server_command_topic = id + '/commands'(见 single-board-computer-telemetry.md 与 single-board-computer-commands.md),两端写法必须一致。

对照方法:把设备端config.h中的ID与服务端app.py中的id逐字符比对,再核对拼出来的 Topic 是否为<ID>/telemetry<ID>/commands。任何一边多一个前导斜杠、大小写不同或 ID 不同,消息都会发到另一个 Topic 上,订阅方自然收不到。

检查二:Topic 通配符写法是否正确

TROUBLESHOOTING.md 建议检查通配符是否用对:+匹配单级,#匹配多级(Check topic wildcards are used correctly (+for single level,#for multi-level))。

第 4 课主文档用一个例子说明 Topic 层级:温度消息发到/telemetry/temperature,湿度消息发到/telemetry/humidity,云端应用订阅上一层级就能同时收到两种消息。如果你的订阅端依赖通配符而不是完整 Topic 名,按上述+/#的定义核对层级数:订阅层数写错,broker 就不会把消息路由到这个客户端。

检查三:QoS 级别

第 4 课主文档定义了 QoS(quality of service,决定消息被接收的保证程度)的三级语义:

  • At most once:消息只发一次,客户端和 broker 不做额外的确认(fire and forget);
  • At least once:发送方多次重发,直到收到确认(acknowledged delivery);
  • Exactly once:发送方与接收方通过两级握手确保只收到一份(assured delivery)。

TROUBLESHOOTING.md 对 "消息发布后收不到" 给出的第二条建议是:Try QoS 1 or 2 instead of 0——当前级别下消息丢失时,改用 QoS 1 或 2 再试。注意课程的示例代码(Wio 端client.publish(...)、Pi 端mqtt_client.publish(client_telemetry_topic, telemetry)、订阅端mqtt_client.subscribe(...))都没有显式传 QoS 参数,所以调整 QoS 时需要在你自己代码的 publish/subscribe 调用里改,改完重新运行并重复下文的验证步骤。

检查四:连接时序与 retained 消息

剩下两个与 Topic、QoS 相关的常见原因是时序和消息保留,TROUBLESHOOTING.md 分别给出对应建议:

  • Connection timing:Ensure subscriber connects before messages are published——先让订阅方连上 broker 并订阅,再让发布方发消息。课程文档也明确:服务端app.py必须先处于运行状态,设备端发来的消息才能被收到;并且 MQTT 虽然名字里有 "Queueing",但实际并不支持消息队列——客户端断开期间发布的消息,在重连后不会补投(除已通过 QoS 流程开始处理的消息外)。所以验证顺序应是:先启动服务端订阅者,再启动设备端发布者。
  • Retained messages:发布方可以设置 retain 标志让 broker 保留该主题的最后一条消息(Check retained messages: Publisher can set retain flag to keep last message)。broker 会把这条消息发给之后才订阅该主题的客户端。如果你期望的是"后订阅的客户端也能拿到最近一次的值",检查发布端有没有按预期设置 retained 标志。

验证:怎样确认已经修好

按 README.md 中的验证方式,在激活的虚拟环境里运行服务端:

python app.py

然后调整物理设备或 CounterFit 虚拟设备检测到的光强。服务端终端应打印收到的遥测消息,文档示例输出如下(数值为示例,实际读数会不同):

(.venv) ➜ nightlight-server python app.py Message received: {'light': 0} Message received: {'light': 400}

反向链路(命令下行)的验证:调整光强后,设备端 Serial Monitor 会打印Message received:及命令 JSON 内容,LED 随命令点亮或熄灭,即说明<ID>/commands主题上的订阅正常。

TROUBLESHOOTING.md 还给出一个独立于课程代码的验证工具:用 MQTT Explorer 或mosquitto_pub/mosquitto_sub直接向 broker 发布/订阅,用来区分"broker 与网络没问题、问题出在自己代码的 Topic/QoS 上"的情况。

限制说明

  • test.mosquitto.org是公共测试 broker,课程文档明确提示它不安全:任何人可能正在监听你发布的内容,不要用它传输需要保密的数据。
  • 由于 broker 公共且多人共用,设备端与服务端的<ID>必须使用同一个唯一值;ID 不一致时两端会落在不同的 Topic 上,这正是本场景最常见的一类收不到消息的原因。

【免费下载链接】IoT-For-Beginners12 Weeks, 24 Lessons, IoT for All!项目地址: https://gitcode.com/GitHub_Trending/io/IoT-For-Beginners

创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询