MQTT主题设计最佳实践

MQTT是为受限设备设计的广泛采用的轻量级消息传递协议。 MQTT参与者会收到通过MQTT主题组织的信息。 MQTT主题充当发布者和订阅者之间的匹配机制。从概念上讲,MQTT主题(Topic)的行为类似于通知的通道。

使用MQTT时的首要考虑因素之一是MQTT主题的设计策略。 MQTT主题必须平衡当前的设备通信,云端操作和将来的设备功能。因此,设计一个理想的MQTT主题结构可能会具有挑战性,该主题尽可能小的采用特权通讯,并且足够灵活扩展。

本文档为您提供MQTT主题设计最佳实践和指南。它概述了一组常用的MQTT主题结构,可以实现这些结构以解决各种设备消息模式,以及几个示例设计模式。

参考:Designing MQTT Topics for AWS IoT Core

MQTT通讯模式

IoT应用程序支持多种通信场景,例如设备到设备,设备到云,云到设备,设备到/来自用户。 虽然范围模式可能有很大的不同,但大多数MQTT通讯模型源自三种MQTT模式:点对点,广播和扇入。

点对点

点对点通信模式是如何进行通信的基本组成部分之一。设备通常在MQTT中发送和接收消息。 两个“物”用同一个MQTT主题(Topic)作为交流渠道。 接收事件的“物”订阅MQTT主题。 发送消息的“物”发布到同一个已知的MQTT主题。 这种方法在智能家居场景中很常见,用户收到有关家中物的更新。 在以下示例中,机械臂发布出一个主题,APP上订阅接收。

MQTT主题设计最佳实践 1
图:1对1的点对点通讯示例

点对点通信不限于一对一通信。 点对点还用于一对多通信,其中单个发布者可以通过不同的主题,发往不同的各个订阅者。这个这种方法在管理员发送针对性的通知方案中很常见。例如,维修服务器用点对点通信的模式,遍历一系列设备来发布消息。

MQTT主题设计最佳实践 2
图-1对多的点对点通讯示例

广播

广播模式用于一对多消息传递。 广播模式向大量设备发送相同的消息。 在广播中,多个设备订阅相同的MQTT主题。发件人将消息发布到该共享主题。 广播模式的典型用法是根据类型或设备组发送通知:例如,基于设备当前地理位置气象站发送广播消息,其中设备按位置分组。

下图描述了一个示例,其中广播模式发送了一个有关所有公交车都订阅的天气主题的消息。 基于车辆的当前位置,它可以忽略或响应消息。

MQTT主题设计最佳实践 3
图:1对多的广播通讯示例

扇入

扇入模式是多对一通信模式,可以认为是广播模式的逆向。 多个设备在共享主题上发布,只有一个订阅者。 在扇入模式时,因为发布者都使用相似但独特的MQTT主题,订阅者可以利用通配符功能来控制接收范围。扇入模式通常用于远程监控IoT应用中的信息聚合。

在以下示例中,每个终端设备都发布到包含特定组标识符的MQTT主题。IOT规则引擎,会使用通配符订阅来接收消息并将其路由。 具体来说,多个机械臂会用扇入模式发出消息,消息中会带有建筑物标记(楼号1234)。管理系统会针对这个楼号,处理消息。

MQTT主题设计最佳实践 4
图:多对1的扇入模式

当设备使用MQTT通过云进行通信时,请避免对单个订阅终端设备使用扇入模式,因为单个设备MQTT连接会有限制。 相反,请使用扇入模式来路由较大批量设备的消息,通过IoT规则引擎将消息发送到IoT应用程序。 对于大规模扇入场景,请将规则引擎与通配符订阅模式和规则引擎操作结合使用。

通讯工作流

三种常见的通信工作流程是设备到设备,设备到云,以及云到设备。 每个工作流都确定MQTT主题的顺序。 对于设备到设备,MQTT主题应包含消息的发送者或接收者的标识符。 对于设备到云,MQTT消息应包括有关目标应用程序的信息。 目标应用程序使用有关设备其它元数据来扩展MQTT消息。 最后,对于云到设备的通信,MQTT消息应包含会话信息,用于确认关键消息接收到位。

MQTT设计最佳实践

一般最佳做法

有几种最佳实践适用于任何消息模式,而与设备如何发布或接收消息无关。本节阐明设计主题结构时,一些总体最佳实践供参考与实施。

确保MQTT主题级别仅使用小写字母,数字和减号。

由于MQTT主题区分大小写,因此在设计MQTT主题时使用一组标准的命名约定非常重要。因此,客户在创建每个主题级别时应当只能使用小写字母,数字和破折号。客户应避免使用驼峰式命名,并且要使用难以调试的字符(例如空格)。

确保MQTT主题级别的结构遵循通用到特定的模式。

随着主题从左到右流动,主题级别从通用到特定。

例如,一个空调系统(名为hvac719)与名为hv100的IoT平台相关联,位于建筑物bld1518的地下室(basement)。主题结构以以通用组(在这种情况下为IoT平台的名称)开头,以最具体的身份(物的名称)结尾。本示例创建以下主题级别的结构:

v100/bld1518/basement/havc719
通用---->具体

MQTT主题中包括完整的相关的路由信息​​。

相关路由信息包括但不限于:IoT应用程序标识符,设备可能属于的组,例如安装位置以及IoT设备的唯一标识。延续上一示例,MQTT主题hv100 / bld1518 / basement / hvac719包含所有相关的路由信息​​。基于在此MQTT主题上,您可以设计一个系统,该系统使用标识符hv100捕获与整个应用程序相关的任何数据,但还可以针对不同的感兴趣区域来订阅消息,例如建筑物位置。

给您的MQTT主题加上前缀,以区分数据主题和命令主题。

确保命令和数据消息之间的MQTT主题不重叠。可以保留第一个主题层级来表示数据,还是命令主题。设备命令,针对发出命令的回应,被动检测数据应当明确区分。例如, IoT设备数字孪生来跟踪设备状态,并使用另外一个数据主题获取远程遥测出的被动数据。

将推荐的MQTT主题结构文档化,并推荐为运营实践的一部分。

该文档应包括可用于发布,订阅或接收数据的所有主题,以及数据的预期生产者和消费者。查看文档以确保其满足IoT平台限制,内部安全要求以及接入应用程序。

使用AWS IoT物名称作为MQTT客户端ID,用为设备连接。

连接到IoT时,MQTT通常需要唯一的客户端ID。应当使用每个设备的唯一“物名称”作为MQTT客户端ID。通过将客户端ID与事物名称匹配,您可以更轻松地将IoT日志等信息与设备关联。

在设备用于发布或订阅其数据的所有MQTT主题中都包括设备的名称。

要跟踪发往特定设备的消息,请将“物名称”作为该设备发布或发送到特定设备的MQTT消息的一部分。事物名称应显示在MQTT主题中。

将附加的情境信息,加入到在MQTT消息中

该情境信息包括但不限于:会话标识符,请求者标识符,日志记录信息或设备希望在其上接收响应的返回主题。虽然MQTT 3.1.1规范不需要特定的有效负载属性,我们建议您在MQTT有效负载内部包括相关的跟踪信息。

通过创建包括会话标识符和成功/错误代码等字段的标准结构,您可以更轻松地分析设备行为的趋势。标准化通信模式还可以增强整个IoT团队之间设备用例的共享性。

避免使用会导致单个设备出现大量扇入的MQTT通讯模式。

设备的一些连接行动为导致平台触发流程限制,例如单个MQTT连接上的最大发布数。不要允许单个设备订阅点接收多个设备发布到的共享主题。通过避免这种模式,您更有可能避免达到单个连接设备限制,尤其是每秒每个连接的吞吐量限制。

切勿允许设备使用#订阅所有主题,而只能在IoT规则中使用多级通配符订阅。

通过使用多级通配符,当您无意中将可能不适用于该特定设备的新主题添加到层次结构中时,可能会产生意想不到的后果。相反,保留将多级通配符用作IoT规则引擎的一部分,并将单级通配符(+)用于设备订阅

远程监测最佳实践

远程监测是只读的数据,由设备传输出并聚集在云中。远程监测遵循设备到云模式以及扇入模式进行通信。远程监测不需要从MQTT代理返回确认消息,而可以选择设置更高的服务质量(QoS)级别。因为远程监测是一项被动活动,MQTT主题不能应当主动工作流(例如命令)的任何MQTT主题重叠。远程监测的主题支持代表其它设备发布的其它代理设备,例如边缘网关,组网中枢……

MQTT遥测主题语法

以下示例和部分提供了遥测的MQTT主题结构:

dt / <应用程序> / <情境> / <物名称> / <dt-type>
  • dt:设置引用消息类型的前缀。
    对于远程监控主题,我们固定dt用作数据的缩写。所有遥测主题都为应用程序使用此顶级前缀。(对于命令类,固定以cmd开头)
  • 应用程序:标识与设备关联的整体物联网应用名。
    常用的应用程序属性包括设备硬件版本或云应用程序的内部标识符,该标识符是消息的主要接收点。
  • 情境:有关设备正在发布的消息的单层或多层情境数据。
    情境信息与在设备供应期间设置的信息有关。例如,工厂中的情境信息可以包括设施中设备的当前位置名。情境信息的另一个示例是MQTT主题中的组ID(group-id)。 group-id表示何时多个有相同属性的设备,例如购买一包智能灯泡来控制房间的照明。 group-id使众多设备作为一个单元进行管理。
  • 物名称:标识哪个设备正在发送远程监测消息。
  • dt-type(可选):将消息与设备的特定子组件或边缘网关的任何下游设备相关联。复杂的设备通常具有多个具有特定任务的子组件,例如传感器,执行器或单片系统(SOC)。 dt类型允许您将特定设备的每个子组件与单个MQTT主题相关联。例如,用于测量车辆地理位置、方向的子组件。该子组件将具有dt类型的geo值,以将其地理位置消息与汽车的其他组件(例如加速度计)区分开来。

案例1:MQTT远程监测主题示例

本节是一个示例,建筑物中多个占用传感器(Occupancy Sensor)的远程监控房间的占用情况。 占用传感器与IOT网关通信。 然后,网关将有关MQTT主题的所有传感器指标传递到云上。此用例专注于远程监测,不需要命令与响应主题。

此方案假定以下详细信息:

  • 占用传感器的ID为occupancy-1和occupancy-2
  • 建筑物称为 building-fresco
  • 每个占用传感器安放在建筑building-fresco 中的地面或房间中。
  • 网关标识为:gateway-1
  • 当前的楼宇自动化系统关联到项目:acme

从占用传感器到边缘层IOT网关

每个占用传感器以每分钟一次的频率,以及每当有人进入或离开房间时都会发布一次占用读数。 由于占用传感器与设备的状态不完全相关,而是指房间的状态,传感器会在远程监控主题上发布房间状态。有效的消息负载包括:时间戳,占用率以及如果房间空置时用于关灯的倒计时。 占用传感器使用MQTT主题,其中包括有关建筑物及其相关项目中传感器位置的情境信息。边缘层IOT网关会接收所有占用传感器数据。

MQTT主题设计最佳实践 5
图-边缘层传感器发布信息到IOT网关

从边缘层网关到云上

在此示例中,边缘层网关的主要作用是聚合来自多个占用传感器的数据,然后将数据发送到AWS IoT 云。 由于边缘层网关是本地通向云桥梁,因此边缘层网关将元数据添加到每个传感器读数中。

边缘层网关将建筑物信息添加到每条消息中,以5分钟为增量显示建筑物的整体使用情况。 边缘层网关还通过添加适当的应用程序标识符acme来扩展MQTT主题。

MQTT主题设计最佳实践 6
图-边缘网关聚合传感信息,增加补充后,发到云端

案例2:MQTT命令示例

对于智能门锁的应用,用户必须能够向门锁提交一个指令,触发后,为经批准的访客发放临时钥匙。临时钥匙由授权用户的TTL、代码组成。创建临时密钥的能力允许另一个人在指定时间内打开锁。例如主人在上班,有亲戚前来访问时。
这个场景假设以下细节。

  • 屋主人的移动设备ID为Mobile-1。
  • 授信的访客的移动设备ID为Mobile-2。
  • 智能锁是作为家中其他锁组的一部分。该锁组有一个上下文的groupId,其中示例中的锁groupId=group-3。
  • 前门的智能锁的lockid=lock-1。
  • 智能锁硬件的系列号为series100。该SN号是该产品版本的唯一标识符。

生成智能锁密码申请的命令

家的主人首先向锁发布一个命令,请求为授信的访客创建一个临时访问代码。命令有内容包括房主的移动设备的标识、用于跟踪当前会话而随机生成的标识符(sessionid)、一个包含命令类型的动作字段(action)和一个主题字段(topic)。智能锁使用主题字段中的主题来发布它对房主的响应。

MQTT主题设计最佳实践 7
图-移动用户发送命令来获取临时密码

如果屋主要求使用临时锁,但需要响应到达家中所有的门锁,可以将主题字段改为发送到一组设备。

智能锁的指令处理

智能锁接收来自MQTT主题的命令。通过利用应用中一致命令命名模式,智能锁可以确保只接收其特定命令主题上的命令。这种主题设计模式使锁可以在其标识符后使用单级MQTT通配符(+)进行所有命令订阅。随着物联网应用增加新的命令类型,单级通配符命令是向后兼容的。

MQTT主题设计最佳实践 8
图-IOT网关发送命令到智能锁

在接收到MQTT有效消息后,智能锁会对命令进行解析,以确定动作类型。在这种情况下,该命令与凭证有关。设备还提取了客户端ID、会话ID和响应的主题。因为一个家庭可以有多个授权的房主,所以客户端ID确定哪个房主发出了申请。在这个例子中,动作字段包括凭证申请类型、生成密码、临时密钥的关联用户。最后,设备获取到主题中的响应(response)字段,并以此做出回应。

MQTT主题设计最佳实践 9
图-智能锁对IOT网关进行回应

将命令反馈传送至移动客户端

业主的移动客户端会订阅智能锁组中所有命令响应。只要移动客户端接收到成功的命令响应,临时密码(code)以及授权信息可以在设备上进行处理,并同时存储在云中。之后,授权访客可以使用临时密码以及额外的安全凭证,如换取OAuth凭证,将临时代码应用到智能锁上。

在这个工作流程中,应用程序为单个设备使用了一个命令主题。然而,如果要对一组多个设备进行申请,也是类似的。例如锁定家中所有的门。

MQTT主题设计最佳实践 10
图-从IOT云接收消息到移动端

案例3:IOT数字孪生设备

在这个例子中,管理员正在向风力发电机发送一个命令,改变叶片角度,以适应即将到来的风向变化。案例中,管理员利用AWS IoT Shadow(数字孪生对象)作为向设备发出命令的主要机制。

这个场景假设了以下细节。

  • 风力发电机作为一个物名称为:turbine8000。
  • 管理员正在利用一个内部应用程序,有使用具有临时IAM权限,范围为turbine8000。
  • 管理员的会话标识符为session-admin100。

向风机的设备孪生发送命令

管理员使用为 turbine8000 预留的 MQTT 主题向 IoT 数字孪生发布消息。命令包括设置设备的期望状态。为了跟踪,管理员还在申请中嵌入一个会话标识符作为clientToken。

MQTT主题设计最佳实践 11
图-向风机设备数字孪生(Device Shadow)发送命令

风机上的命令处理

使用数字孪生时,终端设备负责订阅几个不同的 MQTT 主题,以接收来通知。至少要确保设备订阅 update/delta , update/rejected , get/accepted , 和 get/rejected 的预留主题以接收成功和不成功的申请。

MQTT主题设计最佳实践 12
图-在风机上进行命令处理

在本例中,风力涡轮机在 update/delta时收到一条消息,该消息表明状态与预期状态不同。在处理该命令之前, wind turbine检查clientToken字段以确定请求的发送者。然后它检查元数据中的时间戳字段。对于某些用例,命令应该只在给定的时间段内被视为有效)。一旦确认,风机将调整其叶片角度,并使用更新主题发布带有新报告状态的响应。

向反馈管理员的命令响应

为了让管理员接收报告状态变化的更新,管理员UI订阅update/accepted和update/rejected主题。一旦风机将其更新的状态发布到物联网数字孪生上,管理员就会在update/accepted的主题上收到更新r的确认消息。

MQTT主题设计最佳实践 13
图-风机发布更新