2. MQTT协议核心概念

在农业物联网中,传感器节点往往部署在温室、大田、畜禽舍等分散位置,控制器和执行器又分布在另一侧,如果采用“点对点直连”的方式,每增加一个设备就要新增一条连接,系统很快会变得难以维护。MQTT 用一套轻量的发布/订阅机制解决了这个问题:设备不直接找对方,而是把消息交给 Broker(消息代理),由 Broker 按主题把消息分发给关心的订阅者。理解发布/订阅模型、主题与通配符、QoS、保留消息、会话与遗嘱消息这六个核心概念,是后续搭建农业数据通道和远程控制链路的基础。

发布/订阅模型:设备之间解耦

发布/订阅模型中有三类角色:发布者(Publisher)、订阅者(Subscriber)和代理(Broker)。以温室场景为例,土壤湿度传感器作为发布者,把测量值发布到主题 farm/greenhouse01/soil/moisture;灌溉控制器作为订阅者,提前向 Broker 订阅该主题;Broker 收到消息后,把消息转发给所有匹配的订阅者。发布者不需要知道谁在订阅,订阅者也不需要知道数据来自哪台设备,双方只通过主题这一“地址”建立联系。

这种解耦带来三个实际好处:一是新增一个手机端监控应用时,只需让它订阅相同主题,无需改动传感器固件;二是某个订阅者离线不会阻塞发布者,发布者照常上报;三是可以一对多分发,同一份湿度数据既能送给灌溉控制器,也能送给云端存储和报警服务。需要注意的是,MQTT 的发布/订阅是异步的,发布者发出消息后并不等待订阅者处理完成,因此对控制类指令要结合 QoS 和业务确认机制来保证可靠性。

主题与通配符:给农业数据编址

主题(Topic)是用斜杠分隔的层级字符串,类似文件路径,但不需要预先创建。建议按“场区/棚室/设备类型/测点”的层级设计,例如:

farm/greenhouse01/soil/moisture
farm/greenhouse01/climate/temperature
farm/greenhouse01/irrigation/valve01/cmd
farm/barn02/environment/co2

订阅时可以使用两种通配符。单层通配符 + 匹配一个层级,例如 farm/+/soil/moisture 可匹配 greenhouse01、greenhouse02 等所有棚室的土壤湿度;多层通配符 # 匹配剩余所有层级,且只能出现在主题末尾,例如 farm/greenhouse01/# 可接收该棚室下全部数据。通配符只能用于订阅,发布消息时主题中不允许出现 + 和 #。

设计主题时有几条经验:层级从大到小、语义稳定,避免把易变的时间戳或随机数放进主题;控制指令与遥测数据分开,例如遥测用 .../telemetry、指令用 .../cmd;不要用 # 订阅整个 farm/# 作为长期方案,设备规模变大后 Broker 和客户端的压力都会明显上升。另外,以 $ 开头的主题(如 $SYS/)是 Broker 系统主题,普通业务主题不要占用。

QoS 等级:按业务选可靠性

MQTT 定义了三个服务质量等级,权衡的是“消息能否到达”和“开销大小”:

QoS语义典型交互农业场景建议
0最多一次,可能丢失发布即发送,不确认高频环境数据、允许偶发丢点的曲线采集
1至少一次,可能重复PUBLISH / PUBACK土壤湿度上报、一般状态量,需做幂等处理
2恰好一次,开销最大四次握手计费、阀门开关等不容重复执行的指令

实际选择时,QoS 由发布和订阅两端共同决定,最终生效的是两者中较低的一级。例如传感器以 QoS 1 发布,订阅端以 QoS 0 订阅,则消息按 QoS 0 投递。对灌溉阀门这类执行指令,更稳妥的做法是使用 QoS 1 并在应用层携带指令序号,控制器收到后回执,重复序号直接丢弃,从而在“至少一次”的基础上实现业务幂等,而不是一味追求 QoS 2 带来的握手开销。

保留消息:让新订阅者立刻拿到最新状态

发布者发布消息时若设置 retain 标志,Broker 会为该主题保存最后一条保留消息。之后任何新订阅该主题的客户端,都会立即收到这条消息。农业场景中,这非常适合表达“当前状态”:阀门当前是开还是关、补光灯当前亮度、棚室当前温度。手机应用刚上线时,不必等待下一次上报就能显示最新值。

使用保留消息要注意两点:一是每个主题只保留最后一条,历史数据仍需依赖数据库;二是清除保留消息的方法是向同一主题发布一条空载荷的保留消息。对于状态类主题,建议设备在状态变化时发布保留消息,并周期性重发以刷新;对于高频遥测主题,一般不建议开启保留,避免 Broker 为大量主题长期保存数据。

会话与遗嘱消息:断线也要可感知

MQTT 会话(Session)保存的是订阅关系和未确认消息等状态。客户端连接时可以设置 Clean Session(MQTT 5 中为 Clean Start 加会话过期时间)。设为 false 时,Broker 会保留该客户端的订阅,并在其离线期间缓存 QoS 1/2 的消息,待其重连后补发。对于网络不稳定的田间网关,关闭清理会话可以减少重连后重新订阅的麻烦,也能接住离线期间的关键指令;但缓存量要有上限意识,避免长期离线导致消息堆积。

遗嘱消息(Will Message)是客户端在连接时预先登记的一条消息,当 Broker 检测到该客户端异常断开(如网络中断、设备掉电,且未正常发送 DISCONNECT)时,由 Broker 代为发布。农业场景中,可以把遗嘱主题设为 farm/greenhouse01/status/online,载荷为 offline,并设置 retain,这样监控端一旦收到该消息就能立即判断设备失联。与之配合,设备上线后向同一主题发布 online 的保留消息,就形成了一套简单的在线状态机制。

农业 MQTT 发布/订阅核心机制 发布者 土壤湿度传感器 气象站 / 水肥机 QoS 1 · retain 可选 MQTT Broker 主题路由与匹配 保留消息存储 会话缓存 · 遗嘱发布 订阅者 灌溉控制器 手机监控应用 云端数据平台 PUBLISH farm/gh01/soil/moisture 按主题分发 farm/+/soil/moisture 主题层级与通配符 farm / greenhouse01 / soil / moisture 单层 + :farm/+/soil/moisture → 匹配所有棚室土壤湿度 多层 # :farm/greenhouse01/# → 匹配该棚室全部数据(仅订阅可用,且置于末尾) QoS 等级 0 最多一次:高频环境曲线 1 至少一次:湿度上报、状态量 2 恰好一次:阀门开关等关键指令 保留消息 Broker 保存主题最后一条消息 新订阅者立即获得当前状态 空载荷可清除保留消息 会话与遗嘱 持久会话:离线缓存 QoS 1/2 消息 遗嘱:异常断线由 Broker 代发 status/online → offline(retain)

把六个概念串成一条农业链路

以一个温室土壤湿度采集与灌溉联动为例:传感器每 30 秒向 farm/greenhouse01/soil/moisture 发布一次读数,QoS 1,不保留;灌溉控制器订阅 farm/greenhouse01/soil/moisture,当湿度低于设定阈值(示例设为 35%)时,向 farm/greenhouse01/irrigation/valve01/cmd 发布开启指令,QoS 1 并携带指令序号;阀门执行后向 .../valve01/state 发布保留消息,让监控端随时看到当前开关状态。设备连接时登记遗嘱主题 farm/greenhouse01/status/online,载荷 offline 且 retain,上线后发布 online 覆盖。这样,数据上报、指令下发、状态查询和失联告警就都落在同一套主题体系里。

主题命名一旦确定,后续设备固件、云端规则和手机应用都会依赖它,建议在项目初期就形成书面约定,并避免随意改名。通配符订阅范围越大,Broker 的匹配与转发压力越大,生产环境应尽量使用具体主题或有限层级的 +。
QoS 1 允许重复投递,控制类指令必须在应用层做幂等处理,例如携带唯一指令序号并在执行端去重;遗嘱消息只有在客户端异常断开时才会触发,正常发送 DISCONNECT 不会发布遗嘱,调试时不要误判为设备故障。

掌握这六个概念后,再看具体的连接参数、心跳与认证配置,就能理解每一项设置背后的业务含义,而不是机械照抄示例。