MQTT简介

  1. MQTT全称为消息队列遥测传输(英语:Message Queuing Telemetry Transport),是ISO 标准(ISO/IEC PRF 20922)下基于发布 (Publish)/订阅 (Subscribe)范式的消息协议,工作在 TCP/IP协议族上。
  2. MQTT最大优点在于,可以用极少的数据和有限的带宽,为连接远程设备提供实时可靠的消息服务。作为一种低开销、低带宽占用的即时通讯协议,使其在物联网、小型设备、移动应用等方面有较广泛的应用。
  3. MQTT 协议定义了两种网络实体:消息代理(message broker)与客户端(client)。其中,消息代理用于接收来自客户端的消息并转发至目标客户端,也被称为MQTT服务器。MQTT 客户端可以是任何运行有 MQTT 库并通过网络连接至消息代理的设备,例如微型控制器或大型服务器。
  4. MQTT 协议中,消息的传输是通过主题(topic)管理的,消息的发布者和订阅者均为客户端(client)。消息由主题(Topic)和负载(payload)两部分组成。当某个客户端有需要分发的数据时,会向连接的消息代理(MQTT服务器)发送指定主题的携带有负载的消息。服务器收到消息后,会向订阅此主题的客户端分发此消息。发布者不需要配置订阅者的相关信息和具体位置;同样,订阅者也不需要配置发布者的相关信息和具体位置。

AirIot平台MQTT驱动配置说明

  1. 在系统模型管理界面中选择要配置的模型,右侧选项卡选择设备配置,在设备驱动一栏选择MQTT客户端。无无该选项时,点击右侧的驱动市场按钮在线安装驱动。

image.png

  1. 配置驱动参数

(1)MQTT服务器:填写要连接的mqtt服务器的地址。格式为

tcp://服务器IP或域名:服务器端口 例如:tcp://127.0.0.1:1883

(2)用户名、密码:填写MQTT服务器的用户名和密码。
(3)订阅消息主题:填写该模型要订阅的消息主题,可使用通配符#和+。

Topic是个utf-8编码的字符串,可由多个’/‘分割开。 +:为单级通配符,如:check/+/baseline #:为多级通配符,必须放在topic的最后,前一个字符必须是’/‘ 建议Topic中不要包含空格符。

(4)通讯监控参数:平台通用配置,当某个资产数据点中的最新上数时间距离当前时间超过此参数时,平台判定资产掉线。
(5)自定义脚本:由于mqtt协议中未规定具体的消息内容格式,因此需要用户编写自定义脚本,用于解析消息和组装要发送的消息内容。

使用示例

由于MQTT协议通过主题区分不同种类的消息,因此在使用时,不同的主题需要建立不同的模型,下边以网关常用的MQTT格式为例,介绍脚本的编写方法。

消息格式

  1. 数据采集网关发布的主题的为 box/网关唯一编号/data
  2. 假设网关唯一编号为8位,例:box/abcd1234/data
  3. 消息内容:{"data":{"d1":100},"time":1644290863000}
  4. 网关订阅的主题为 box/网关唯一编号/command
  5. 消息内容:{"d1":200}

脚本

脚本语言采用的是JavaScript,一部分为固定格式:

  1. // 解析接收数据
  2. // 该服务器和主题收到的消息会调用此方法进行解析,消息主题是方法参数topic,消息内容是方法参数package.
  3. // topic类型为字符串,考虑到部分设备的消息内容为二进制数据,package类型为字节数组.
  4. ParseHandle = function (topic, package) {
  5. // 解析数据
  6. let id = "abcd1234" //id是资产编号,平台通过id判断数据和资产的对应关系,必需
  7. let values = {"d1":100} // values是一个对象,key为数据点标识,值就是采集的具体数值,必需
  8. let time = 1644290863000 // 数据点采集时间,UNIX毫秒时间戳,没有time时,默认采用服务器时间
  9. return [ //可返回多个对象,对应多个资产
  10. { id, values,time } //返回的对象中的key的名字必须为id,values,time
  11. ]
  12. }
  13. // 构建发送数据
  14. CommandHandle = function (topic, id, op) {
  15. // 构建发送数据
  16. let sendTopic = ""
  17. let sendData = {"d1":200}
  18. return { sendTopic, sendData }} //返回的对象中的key的名字必须为sendTopic,sendData
  19. }

脚本示例:

  1. // 解析接收数据
  2. // 消息内容:{"data":{"d1":100},"time":1644290863000}
  3. ParseHandle = function (topic, package) {
  4. let id = topic.substring(4, 12) // 从主题中截取资产编号
  5. let msg = JSON.parse(package.toString()) // 将消息从字节数组转为json对象
  6. let values = msg.data // 该消息内容的格式恰好符合平台的要求格式
  7. let time = msg.time // 毫秒时间戳
  8. return [
  9. { id, values,time }
  10. ]
  11. }
  12. // 构建发送数据
  13. // 主题: box/abcd1234/command
  14. // 内容: {"d1":200}
  15. CommandHandle = function (topic, id, op) {
  16. let sendTopic = `box/${id}/command`
  17. let sendData = `{"${op.tag}":${op.value}}`
  18. return { sendTopic, sendData }
  19. }