MQTT-SN 全名为 MQTT for Sensor Networks,其目标是为非 TCP/IP 协议栈的嵌入式设备(如 Zigbee、Bluetooth)提供应用层通信标准。MQTT-SN 是一个专为 WSN(Wireless Sensor Networks)网络设计的 Publish/Subscribe 的消息传输协议。
大规模分布式物联网 MQTT 消息服务器 EMQX 除了完整支持 MQTT 协议外,还可以通过网关处理所有非 MQTT 协议的连接、认证和消息收发,并为其提供统一的用户层接口。本文将介绍如何在 EMQX 中接入 MQTT-SN 协议设备,并通过认证及授权保障设备接入安全。
MQTT-SN 的优点是什么?
- 与 MQTT 协议兼容: MQTT-SN 通信模型完全与 MQTT 相对应,例如发布、订阅、保留会话、遗嘱消息等。统一的模型有利于降低端到端的设计复杂度。
- 轻量: 为了应对 WSN 网络中有限的传输带宽,协议设计非常精简。例如 PUBLISH 消息中的主题名称被一个短的、两字节长的 Topic ID 取代。
- 支持休眠: MQTT-SN 协议新增了休眠逻辑,来应对低功耗的场景。例如设备进入到休眠后,所有发给它们的消息都会被缓存在服务器,并在唤醒后传递给它们。
MQTT-SN 常见的部署结构
MQTT-SN Architecture
- Client 和 Gateway 部署在同一个局域网中(例如 Zigbee)通过 MQTT-SN 协议进行通信,并且 Gateway 通过以太网和 MQTT 协议将数据上报到云端的 MQTT Broker。
- MQTT Broker 与 MQTT-SN Gateway 集成在一起,都部署在云端。Client 通过 UDP 和 MQTT-SN 直接与云端的 MQTT-SN 网关进行通信。
- 第三种部署方式与第一种类似,不同的是使用 MQTT-SN 协议与云端的 MQTT-SN 网关进行交互。
相对比而言:
- 第一种方案是最为典型的 MQTT-SN 部署方案,该方案非常适用于终端无公网通信需求且需要部署网关来统一管理的场景,例如典型的智能家居场景。
- 第二种方案常见于终端设备都部署在室外,它们通过移动网络例如(NB-IoT) 直接与云端直连,中间无法部署网关来处理设备请求。
- 第三种部署比较少见,它仅是方案 1、2 的一种折中。仅在服务端仅能提供 MQTT-SN 接入服务时会用到。
因此,MQTT-SN 主要应用于具有短距离、带宽受限、低功耗等特点的应用场景,例如智慧城市、智能家具、水电气表等。
使用 EMQX 接入 MQTT-SN 协议
EMQX 的 MQTT-SN 网关基于 MQTT-SN 1.2 版本实现。MQTT-SN 网关作为一个组件集成在 EMQX,可以允许将其部署在边缘或云端来实现上文提到的第一和第二种部署结构。
启用 MQTT-SN 网关
在 EMQX 5.0 中,可以通过 Dashboard、HTTP-API 或配置文件来启用 MQTT-SN 网关。
例如,开启并配置监听 UDP 1884 端口的 MQTT-SN 网关:
gateway.mqttsn {
mountpoint = "mqttsn/"
listeners.udp.default {
bind = 1884
max_connections = 10240000
max_conn_rate = 1000
}
}
客户端测试
使用 C 语言编写的 MQTT-SN 客户端,来测试发布订阅,例如:
Client ID mqttsn1
连接并订阅主题 t/a
,
$ ./mqtt-sn-sub -i mqttsn1 -t t/a -p 1884 -d
使用 Client ID 为 mqttsn2
登录到 MQTT-SN 网关,并对 t/a
主题发布消息 Hi, This is mqttsn2
:
$ ./mqtt-sn-pub -i mqttsn2 -p 1884 -t t/a -m 'Hi, This is mqttsn2' -d
最终,能在 mqtt-sn-sub
端接收到该消息:
更多高级功能配置
配置客户端接入认证
由于 MQTT-SN v1.2 协议的连接报文只定义了 Client ID,没有 Username 和 Password 。所以 MQTT-SN 网关目前仅支持 HTTP Server 认证
例如,通过配置文件,为 MQTT-SN 网关添加一个 HTTP 认证:
gateway.mqttsn {
authentication {
enable = true
backend = "http"
mechanism = "password_based"
method = "post"
connect_timeout = "5s"
enable_pipelining = 100
url = "<http://127.0.0.1:8080">
headers {
"content-type" = "application/json"
}
body {
clientid = "${clientid}"
}
pool_size = 8
request_timeout = "5s"
ssl.enable = false
}
}
在该认证方式中,将 Client ID 传递给 HTTP 服务,由 HTTP 服务来决定该客户端是否有接入系统的权限。
配置发布订阅权限
在 EMQX 5.0 中,所有主题的发布订阅权限都在授权(Authorization)中统一配置。例如,允许所有人发布订阅 mqttsn/
开头的主题:
在 Dashboard 中配置主题发布订阅权限
获取上下线事件
MQTT-SN 网关会将所有设备的上下线事件发布到两个专用的主题:
- 上线事件主题:
$SYS/brokers/<node>/gateway/mqtt-sn/clients/<clientid>/connected
- 下线事件主题:
$SYS/brokers/<node>/gateway/mqtt-sn/clients/<clientid>/disconnected
例如,一条上线事件消息内容为:
{
"clientid": "abc",
"username": "undefined",
"ts": 1660285421750,
"sockport": 1884,
"protocol": "mqtt-sn",
"proto_ver": "1.2",
"proto_name": "MQTT-SN",
"keepalive": 10,
"ipaddress": "127.0.0.1",
"expiry_interval": 7200000,
"connected_at": 1660285421750,
"clean_start": false
}
当然,也可以通过规则引擎中的 $event/client_connected
和 $event/client_disconnected
事件来获取 MQTT-SN 网关的上下线事件,具体可以参考:Event topic available for FROM clause
引用
[1] OASIS Open: MQTT-SN spec v1.2
[3] EMQX 5.0 MQTT-SN Gateway introduction
[4] OASIS Open: MQTT-SN v2.0-wd17.docx
版权声明: 本文为 EMQ 原创,转载请注明出处。原文链接:https://www.emqx.com/zh/blog/connecting-mqtt-sn-devices-using-emqx