跳至主要內容

Mqtt协议设备接入

fastbee2024年9月27日大约 11 分钟

一、接入步骤

提示

  • 参考的ESP8266硬件SDK源码 https://gitee.com/kerwincui/fastbee/tree/master/sdk/
  • 如果设备的Mqtt消息格式是固定的,可以通过规则引擎进行转发,适配到平台
    • 系统自带netty-mqtt: 支持主题和内容转发
    • 使用emqx中间件: 支持内容转发,主题可以通过emqx自带的规则引擎转发
  1. 设备认证

    • 加密认证(推荐)
    • 简单认证
  2. 设备交互

    • 发布物模型、设备信息、时钟同步相关Mqtt主题
    • 订阅物模型、设备升级、时钟同步相关Mqtt主题
  3. 设备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 = fastbee

# 密码
password = mqtt密码 & 过期时间
password = mqtt密码 & 过期时间 & 设备授权码 (产品启用设备授权时格式)

账号配置信息示例:

clientId = "E&D68329VL588&2&1"
userName = "fastbee"
password = "/W2A/4MK+9cEGBhyBDgr2K5c62DAjAK4m0b5pvwxX6FFMzI3h1pUmaDY3BH1P2mI"

2. 简单认证

产品详情中获取Mqtt账号和Mqtt密码,建议测试环境使用。Mqtt客户端ID格式类似加密认证,其中E改为S。

# 客户端Id等于 认证类型 + 设备编号 + 产品编号 + 用户ID
clientId = S & deviceNumber & productId & userId

# 用户名
userName = fastbee

# 密码
password = mqtt密码
password = mqtt密码 & 设备授权码 (产品启用设备授权时格式)

账号配置信息示例:

# 客户端Id等于 认证类型 + 设备编号 + 产品编号 + 用户ID
clientId = "S&D68329VL588&2&1"
userName = "fastbee"
password = "PHYFED93WSFF1DAS"
password = "PHYFED93WSFF1DAS&ADBFCC8934864B26B55658C66F562AC5" (产品启用设备授权时格式)

3. 设备获取当前时间

获取当前时间,可以调用系统的NTP时间接口,接口请求时发送设备当前运行毫秒数,返回设备发送时间、服务端接收时间、服务端发送时间。然后获取设备当前运行毫秒数,作为设备接收间。最后用公式计算出设备当前的时间,时间必须以毫秒为单位。在线时间戳工具

# deviceSendTime值为设备当前运行的毫秒数
http://localhost:8080/iot/tool/ntp?deviceSendTime=35768

# 计算时间
设备当前时间 = (服务端接收时间 + 服务端发送时间 + 设备接收时间 - 设备发送时间) / 2

4. AES加密说明

采用AES的CBC加密模式,偏移量固定为 wumei-smart-open 16位,输出为Base64,加密使用的密码为产品密钥。测试可以使用:在线加解密工具

加密模式CBC
pkcs5padding
:  128
wumei-smart-open
base64

对应系统的产品秘钥
加密内容mqtt密码 & expireTime & 授权码(可选)



三、设备交互

{productId} 代表产品ID, {deviceNum} 代表设备编号。通过web端获取产品ID和设备编号,如果使用自动添加设备,设备编号可以使用唯一编码或者使用设备MAC地址,设备认证成功后会在后端自动添加一个对应的设备实体。

1. 订阅主题

主题描述
/{productId}/{deviceNum}/function/get订阅平台指令
/{productId}/{deviceNum}/info/get订阅设备信息(订阅到该主题就发布设备信息)
/{productId}/{deviceNum}/monitor/get订阅实时监测信号(根据监测次数和间隔,然后发布监测数据)
/{productId}/{deviceNum}/ntp/get订阅时钟同步(可选,用于同步设备的当前时间)
/{deviceNum}/http/upgrade/setHTTPS方式订阅OTA升级(新)
/{deviceNum}/fetch/upgrade/set二进制包方式订阅OTA升级(新)
/{productId}/{deviceNum}/ota/get订阅设备升级(旧)
/{productId}/{deviceNum}/property/get2.x弃用 订阅属性(服务端发布,设备订阅)
/{productId}/{deviceNum}/property-online/get2.x弃用 订阅属性(在线模式,用户端发布,设备订阅)
/{productId}/{deviceNum}/function-online/get2.x弃用 订阅功能(在线模式,用户端发布,设备订阅)

2. 发布主题

主题描述
/{productId}/{deviceNum}/property/post发布数据 (实时显示,属性/功能和监测数据,可定时上报监测数据)
/{productId}/{deviceNum}/info/post发布设备信息
/{productId}/{deviceNum}/event/post发布事件
/{productId}/{deviceNum}/monitor/post发布实时监测数据(仅用于实时监测图表显示,不会存储)
/{productId}/{deviceNum}/ntp/post发布时钟同步(可选)
/{deviceNum}/http/upgrade/replyHTTPS方式回复OTA升级(新)
/{deviceNum}/fetch/upgrade/reply二进制包方式回复OTA升级(新)
/{productId}/{deviceNum}/upgrade/reply回复OTA升级(旧)
/{productId}/{deviceNum}/function/post2.x弃用 发布功能 (实时显示)

3. 数据格式

设备和系统交互使用JSON格式

# 描述订阅到设备信息后发布设备信息解决设备状态同步问题
# 设备消息内容为空
# 描述:1.设备上电后发布设备信息; 2.设备接收到设备信息指令后发布设备信息
# rssi             设备信号信号极好[-550],信号好[-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": 2, 
     "longitude": 0,
     "latitude": 0,
     "summary": {
 	    "name": "FastBee",
 	    "chip": "ESP8266",
 	    "author": "kerwincui",
 	    "deliveryTime": "2023-06-06",
 	    "activeTime": "2022-10-01"
     }
 }

# 描述订阅到实时监测消息根据数量和间隔发布实时监测数据
# count      数量
# interval   间隔毫秒为单位

{
    "count": 60,
    "interval": 1000
}
# 描述根据订阅到的实时监测消息发布指定数量和间隔的监测数据
# id       标识符实时监测是物模型中的属性产品详情中查看标识符对应id值
# value    设备采集的值只能是整数或者小数以字符串类型传递
# remark   可为空或者使用设备当前时间

[{
    "id": "temperature",
    "value": "27.43",
    "remark": ""
}, {
    "id": "humidity",
    "value": "32.18",
    "remark": ""
}]

# 描述属性功能事件都属于物模型Json定义是一样的例如都订阅到消息打开开关设备的处理都是把开关打开
# id      标识符产品详情中查看物模型对应物模型的标识符
# value对应物模型中定义以字符串类型传递
# remark  平台中告警场景联动和定时下发的指令有备注信息

[{
    "id": "gear",
    "value": "1",
    "remark": "设备定时"
},{
    "id": "switch",
    "value": "0",
    "remark": "场景联动触发"
}]

# 描述属性功能事件都属于物模型Json定义是一样的`value` 的值如果是布尔类型值为"0"或者"1"代表打开/关闭枚举类型对应枚举项的键值(例如 "1"代表中速档位);数组类型是以英文逗号分隔的字符串
# id      标识符产品详情中查看物模型对应物模型的标识符
# value对应物模型中定义以字符串类型传递
# remark  可以直接使用订阅到的备注信息设备日志信息中查看到该备注

[{
    "id": "gear",
    "value": "1",
    "remark": "档位设置成功"
}, {
    "id": "switch",
    "value": "0",
    "remark": "开关已关闭"
}]

相关物模型说明

  • 所有物模型的Id(标识符)都是唯一的,尽量不要使用特殊字符,以字母和数字为主。
  • 对象类型物模型下面子模型Id(标识符)格式:parentId_childId,对象数组类型同样,子模型Id增加父级的Id以下划线分隔,例如:
# 父级物模型Id:power
# 子级物模型Id:power_light
  • 数组类型(包括对象数组类型)的物模型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": ""
    }]

# 描述可选发布时钟同步消息服务端订阅到后下发时钟同步消息
# deviceSendTime 设备发送时间

{
    "deviceSendTime": "1592361428000"
}
# 描述可选订阅到时钟同步消息计算当前时间 = (服务端接收时间 + 服务端发送时间 + 设备接收时间 - 设备发送时间) / 2
# deviceSendTime  设备发送时间
# serverRecvTime  服务端接收时间
# serverSendTime  服务端发送时间

{
    "deviceSendTime": "1592361428000",
    "serverSendTime": "1592366463548",
    "serverRecvTime": "1592366463548"
}

# 描述订阅到设备升级消息后根据固件下载地址Http请求下载固件并升级
# version       版本号可用于匹配固件版本
# downloadUrl   固件下载地址

  {
    "taskId": 26,
    "url": "/profile/iot/1/2024-0824-001954.bin",
    "version": 1.2,
    "status": 1
  }



四、设备配网(可选,仅限Wifi类设备)

提示

  • 设备采用AP配网,配网时,设备开启热点,并提供web服务。移动端通过设备提供的web服务来传递配置信息。
  • 设备端热点的地址设置为:192.168.4.1
  • 可以参考项目SDK

1. 检测设备接口

设备端提供检测接口,移动端通过该接口实现发现设备功能,适用于单设备配网。

# 请求方法Get
# 接口地址http://192.168.4.1/status
# 参数
# 返回信息HTTP状态码200 表示检测到设备

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