Mqtt设备接入
# 一、接入步骤
:::
设备认证
- 加密认证(推荐)
- 简单认证
设备交互
- 发布物模型、设备信息、时钟同步相关Mqtt主题
- 订阅物模型、设备升级、时钟同步相关Mqtt主题
设备AP配网(可选,仅限Wifi类设备)
- 设备检测接口
- 设备配置接口
# 二、设备认证
提示
- 认证类型:S=简单认证,E=加密认证
- 产品启用设备授权码后,授权码不能为空
- 用户ID就是登陆用户的ID,使用不同用户ID,设备归属于不同用户。可以统一使用admin账号1,后面通过配网或者扫码关联设备分配给不同用户。
- 设备编号有两种方式获取:1.使用系统新建设备时,生成的设备编号;2.系统未新建设备,硬件端生成一个唯一编号作为设备编号,认证后系统会自动注册一个设备实体(设备比较多时,推荐这种方式)
# 1. 加密认证
产品详情中获取产品编号、Mqtt账号、Mqtt密码和产品秘钥,密码通过产品秘钥进行AES加密,传递到后端;后端通过产品秘钥解密进行认证;连接Mqtt消息服务器需要提供唯一的客户端ID、用户名和密码,具体格式如下:
# 客户端Id等于 认证类型 + 设备编号 + 产品编号 + 用户ID
clientId = E & deviceNumber & productId & userId
# 用户名
userName = yanfan-smart
# 密码
password = mqtt密码 & 过期时间
password = mqtt密码 & 过期时间 & 设备授权码 (产品启用设备授权时格式)
2
3
4
5
6
7
8
9
10
- 客户端ID等于 认证类型 + 设备编号 + 产品编号 + 用户ID,用
&
符号连接,中间无空格; - 用户名直接输入Mqtt账号
- 密码等于 Mqtt密码 + 密码过期时间 + 设备授权码(可选),然后进行AES加密。为了安全,密码过期时间应该在24小时以内,采用时间戳格式,精确到毫秒。
账号配置信息示例:
clientId = "E&D68329VL588&2&1"
userName = "yanfan-smart"
password = "/W2A/4MK+9cEGBhyBDgr2K5c62DAjAK4m0b5pvwxX6FFMzI3h1pUmaDY3BH1P2mI"
2
3
# 2. 简单认证
产品详情中获取Mqtt账号和Mqtt密码,建议测试环境使用。Mqtt客户端ID格式类似加密认证,其中E改为S。
# 客户端Id等于 认证类型 + 设备编号 + 产品编号 + 用户ID
clientId = S & deviceNumber & productId & userId
# 用户名
userName = yanfan-smart
# 密码
password = mqtt密码
password = mqtt密码 & 设备授权码 (产品启用设备授权时格式)
2
3
4
5
6
7
8
9
账号配置信息示例:
# 客户端Id等于 认证类型 + 设备编号 + 产品编号 + 用户ID
clientId = "S&D68329VL588&2&1"
userName = "yanfan-smart"
password = "PHYFED93WSFF1DAS"
password = "PHYFED93WSFF1DAS&ADBFCC8934864B26B55658C66F562AC5" (产品启用设备授权时格式)
2
3
4
5
# 3. 设备获取当前时间
获取当前时间,可以调用系统的NTP时间接口,接口请求时发送设备当前运行毫秒数,返回设备发送时间、服务端接收时间、服务端发送时间。然后获取设备当前运行毫秒数,作为设备接收间。最后用公式计算出设备当前的时间,时间必须以毫秒为单位。在线时间戳工具
# deviceSendTime值为设备当前运行的毫秒数
http://localhost:8080/iot/tool/ntp?deviceSendTime=35768
# 计算时间
设备当前时间 = (服务端接收时间 + 服务端发送时间 + 设备接收时间 - 设备发送时间) / 2
2
3
4
5
# 4. AES加密说明
采用AES的CBC加密模式,偏移量固定为 yanfan-smart-open
16位,输出为Base64,加密使用的密码为产品密钥。测试可以使用:在线加解密工具
加密模式: CBC
填 充: pkcs5padding
数 据 块: 128位
偏 移 量: yanfan-smart-open
输 出: base64
密 码: 对应系统的产品秘钥
加密内容: mqtt密码 & expireTime & 授权码(可选)
2
3
4
5
6
7
8
# 三、设备交互
{productId}
代表产品ID, {deviceNum}
代表设备编号。通过web端获取产品ID和设备编号,如果使用自动添加设备,设备编号可以使用唯一编码或者使用设备MAC地址,设备认证成功后会在后端自动添加一个对应的设备实体。
# 1. 订阅主题
)
主题 | 描述 |
---|---|
/{productId}/{deviceNum}/function/get | 订阅平台指令 |
/{productId}/{deviceNum}/info/get | 订阅设备信息(订阅到该主题就发布设备信息) |
/{productId}/{deviceNum}/ota/get | 订阅设备升级(旧) |
/{productId}/{deviceNum}/upgrade/get | 订阅OTA升级(新) |
/{productId}/{deviceNum}/monitor/get | 订阅实时监测信号(根据监测次数和间隔,然后发布监测数据) |
/{productId}/{deviceNum}/ntp/get | 订阅时钟同步(可选,用于同步设备的当前时间) |
/{productId}/{deviceNum}/property/get | 2.x弃用 订阅属性(服务端发布,设备订阅) |
/{productId}/{deviceNum}/property-online/get | 2.x弃用 订阅属性(在线模式,用户端发布,设备订阅) |
/{productId}/{deviceNum}/function-online/get | 2.x弃用 订阅功能(在线模式,用户端发布,设备订阅) |
# 2. 发布主题
发布OTA升级(新)
主题 | 描述 |
---|---|
/{productId}/{deviceNum}/property/post | 发布数据 (实时显示,属性/功能和监测数据,可定时上报监测数据) |
/{productId}/{deviceNum}/info/post | 发布设备信息 |
/{productId}/{deviceNum}/event/post | 发布事件 |
/{productId}/{deviceNum}/monitor/post | 发布实时监测数据(仅用于实时监测图表显示,不会存储) |
/{productId}/{deviceNum}/ntp/post | 发布时钟同步(可选) |
/{productId}/{deviceNum}/upgrade/reply | 回复OTA升级(新) |
/{productId}/{deviceNum}/function/post | 2.x弃用 发布功能 (实时显示) |
# 3.自定义主题和clientId
- 默认是使用初始主题 /{productId}/{deviceNum}/property/post(发布)、/{productId}/{deviceNum}/function/get(订阅)、S & deviceNumber & productId & userId(clientId)
# 4. 数据格式
设备和系统交互使用JSON格式
订阅设备信息,对应主题:
/info/get
# 描述:订阅到设备信息后,发布设备信息,解决设备状态同步问题 # 设备消息内容为空
1
2发布设备信息,对应主题:
/info/post
# 描述:1.设备上电后发布设备信息; 2.设备接收到设备信息指令后发布设备信息 # rssi 设备信号(信号极好[-55— 0],信号好[-70— -55],信号一般[-85— -70],信号差[-100— -85]) # status 设备状态,固定为3,表示在线 # firmwareVersion 固件版本 # userId 用户的ID,可设置为用户ID为1(管理员),配网时会分配设备给具体的用户。 # longitude 可选,经度,使用设备定位时需要上传 # latitude 可选,纬度,使用设备定位时需要上传 # summary 可选,摘要,设备的配置信息等,json格式,对象可自定义 { "rssi": -43, "firmwareVersion": 1.2, "status": 3, "userId": 1, "longitude": 0, "latitude": 0, "summary": { "name": "延凡科技", "chip": "ESP8266", "author": "kerwincui", "deliveryTime": "2023-06-06", "activeTime": "2022-10-01" } }
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
订阅实时监测,对应主题:
/monitor/get
# 描述:订阅到实时监测消息,根据数量和间隔发布实时监测数据 # count 数量 # interval 间隔,毫秒为单位 { "count": 60, "interval": 1000 }
1
2
3
4
5
6
7
8发布实时监测,对应主题:
/monitor/post
# 描述:根据订阅到的实时监测消息,发布指定数量和间隔的监测数据 # id 标识符,实时监测是物模型中的属性,产品详情中查看标识符,对应id值 # value 设备采集的值,只能是整数或者小数,以字符串类型传递 # remark 可为空或者使用设备当前时间 [{ "id": "temperature", "value": "27.43", "remark": "" }, { "id": "humidity", "value": "32.18", "remark": "" }]
1
2
3
4
5
6
7
8
9
10
11
12
13
14
订阅平台指令,对应主题:
/function/get
# 描述:属性、功能、事件都属于物模型,Json定义是一样的。例如都订阅到消息打开开关,设备的处理都是把开关打开。 # id 标识符,产品详情中查看物模型,对应物模型的标识符 # value 值,对应物模型中定义,以字符串类型传递 # remark 平台中告警、场景联动和定时下发的指令有备注信息 [{ "id": "gear", "value": "1", "remark": "设备定时" },{ "id": "switch", "value": "0", "remark": "场景联动触发" }]
1
2
3
4
5
6
7
8
9
10
11
12
13
14发布数据和事件,对应主题:
/property/post
、/event/post
# 描述:属性、功能、事件都属于物模型,Json定义是一样的。`value` 的值如果是布尔类型,值为"0"或者"1",代表打开/关闭;枚举类型对应枚举项的键值(例如 "1",代表中速档位);数组类型是以英文逗号分隔的字符串。 # id 标识符,产品详情中查看物模型,对应物模型的标识符 # value 值,对应物模型中定义,以字符串类型传递 # remark 可以直接使用订阅到的备注信息,设备日志信息中查看到该备注 [{ "id": "gear", "value": "1", "remark": "档位设置成功" }, { "id": "switch", "value": "0", "remark": "开关已关闭" }]
1
2
3
4
5
6
7
8
9
10
11
12
13
14
相关物模型说明
- 所有物模型的Id(标识符)都是唯一的,尽量不要使用特殊字符,以字母和数字为主。
- 对象类型物模型下面子模型Id(标识符)格式:parentId_childId,对象数组类型同样,子模型Id增加父级的Id以下划线分隔,例如:
# 父级物模型Id:power
# 子级物模型Id:power_light
2
- 数组类型(包括对象数组类型)的物模型Id(标识符)只有一个,物模型值为数组(以英文逗号分隔的字符串存储),例如
98,100,50
字符串。所以上报数组类型的属性/功能/事件,相对特殊,Id(标识符)必须以array_索引
开头,索引是两位数,例如:# 普通数组格式 `array_00_RGB` # 对象数组格式 `array_00_power_switch` # 索引00代表数组中第一个元素,02 / 03 ... 98 / 99 以此类推,数组长度不能超过100 [{ "id": "array_01_power_switch", // array_01作为前缀,表示数组中的第二个元素 "value": "1", "remark": "" }]
1
2
3
4
5
6
7
8
发布时钟同步,对应主题:
/ntp/post
# 描述:可选,发布时钟同步消息,服务端订阅到后下发时钟同步消息 # deviceSendTime 设备发送时间 { "deviceSendTime": "1592361428000" }
1
2
3
4
5
6订阅时钟同步,对应主题:
/ntp/get
# 描述:可选,订阅到时钟同步消息,计算当前时间 = (服务端接收时间 + 服务端发送时间 + 设备接收时间 - 设备发送时间) / 2
# deviceSendTime 设备发送时间
# serverRecvTime 服务端接收时间
# serverSendTime 服务端发送时间
{
"deviceSendTime": "1592361428000",
"serverSendTime": "1592366463548",
"serverRecvTime": "1592366463548"
}
2
3
4
5
6
7
8
9
10
- 订阅OTA升级,对应主题:
/ota/get
# 描述:订阅到设备升级消息后,根据固件下载地址,Http请求下载固件并升级
# version 版本号,可用于匹配固件版本
# downloadUrl 固件下载地址
{
"version": 1.1,
"downloadUrl": "https://iot.yanfankeji.com/prod-api/profile/iot/6/2022-0616-140539.bin"
}
2
3
4
5
6
7
8
# 5. 举例
- 连接设备
- 查找连接参数
- 使用mqttx代替设备连接iot平台设备
- 使用发布主题
- 使用预定主题
# 四、设备配网(可选,仅限Wifi类设备)
提示
- 设备采用AP配网,配网时,设备开启热点,并提供web服务。移动端通过设备提供的web服务来传递配置信息。
- 设备端热点的地址设置为:192.168.4.1
# 1. 检测设备接口
设备端提供检测接口,移动端通过该接口实现发现设备功能,适用于单设备配网。
# 请求方法:Get
# 接口地址:http://192.168.4.1/status
# 参数:无
# 返回信息:HTTP状态码200 表示检测到设备
2
3
4
# 2. 配置接口
设备端提供配置接口来获取信息,移动端发送配置信息,参数采用Url方式传递,其中SSID、password、userId是必传参数。
# 请求方法:Post
# 接口地址:http://192.168.4.1/config
# 参数如下:
SSID # Wifi的名称
password # Wifi的密码
userId # 用户编号/ID
deviceNum # 可选,设备编号
authCode # 可选,授权码
extra # 可选,补充信息
# 返回信息:HTTP状态码200 表示配网成功;HTTP状态码500 表示配网失败;
# 请求URL例子,设备通过该Url获取参数,保存到设备中
http://192.168.4.1/config?SSID=mywifi&password=mywifipassword&userId=1
http://192.168.4.1/config?SSID=mywifi&password=mywifipassword&userId=1&deviceNum=D68329VL588&authCode=6688&extra=open
2
3
4
5
6
7
8
9
10
11
12
13
14
15