APP设备标准交互协议
文档目标
本文档用于描述智能设备在接入得力云平台过程中如何通过与得力E+APP(以下简称“APP”)交互来实现网络配置、接入验证以及信息读取的流程和标准交互协议。
适用范围
所有支持通过APP进行扫码、配网、接入验证以及数据通信的智能设备可参考本文档,其它设备不在此讨论范围。
基本流程
所有接入得力云平台的设备(包括直接接入或通过APP间接接入两大类设备),都应归属于某一个具体的产品型号。不同的产品型号会针对设备是否接入平台、如何配置网络以及如何与APP进行直连通信进行初始静态参数配置。
在所有操作开始之前,APP首先需要通过扫描设备二维码获取设备的产品型号信息,然后根据产品型号的不同配置参数采取不同的策略完成设备网络配置、接入认证以及绑定激活等流程。
设备通过APP接入得力云平台的整体流程图如下:
主要包括有:
1. 验证设备二维码合法性;
2. 验收设备以及产品型号等配置合法性;
3. 检查设备是否需要APP配置网络,并进入相应网络配置流程;
4. 设备接入认证,包括APP以及云平台设备网关;
5. 设备绑定激活;
设备二维码
标准的设备二维码的格式如下:
https://delicloud.com/d/{设备ID}/activate?product={产品型号}&status={状态}
老的二维码格式也支持,但不建议继续使用:
https://delicloud.com?from={二维码来源}&action={操作}&product={产品型号}&device={设备ID}&status={状态}
其中,各参数说明如下:
参数 | 描述 |
---|---|
from | 必填,二维码来源,对于来自设备的二维码,其固定值为device |
action | 选填,对于绑定激活,可设置固定值为activate |
product | 必填,设备对应的产品型号 |
device | 选填,设备ID。除非有特别原因,否则都应直接将设备ID写入二维码中。如果无法写入,设备应支持其他与APP交互的标准方式提供该信息 |
status | 选填,连接状态。包括: 未联网(-1)、接入平台成功(0)、接入平台失败(1)。该字段仅对直接接入平台设备网关的设备有效 |
对于有屏幕的智能设备,可以根据设备状态实时更新动态二维码信息到屏幕上供APP扫描,对于其他设备,则可以在包装和设备本身上通过印刷提供设备二维码信息。
针对某些特殊情况,比如设备印刷面积有限,需要压缩二维码的内容时,可以生成简化版的二维码,格式如下:QR/{产品型号}
,但该类型设备应支持直接通过与APP通信的方式获取设备ID等更多信息。
设备搜索
对于那些需要与APP进行无线连接的智能设备,例如通过蓝牙或者WIFI热点广播等方式直连的设备,APP需要设备的蓝牙名称或者WIFI热点名称(统称“广播名称”)符合以下规范:
1. 如果APP扫码无法获得设备ID,请命名设备广播名称为: DELI_{产品型号}。例如D2蓝牙考勤机的蓝牙名称可以为DELI_D2;
2. 如果APP扫码可以获得设备ID,请命名设备广播名称为: DELI_{产品型号}_{设备ID后6位},例如打印机型号为PT的设备ID为PT_12345678,则可以设置广播名称为DELI_PT_345678;
对于APP扫码可以获得设备ID的情况,APP会按照规范#2去查找匹配的设备广播名称,否则将通过规范#1进行搜索匹配。
一旦匹配成功,就会自动连接(部分特殊情况可能需要人工参与)并进行设备后续校验通信。
通信格式
对于需要与APP进行数据流通信的设备,除非已约定了数据交换协议,否则推荐采用平台规定的统一的消息报文格式,消息报文结构示例如下:
包头 | 消息指令 | 负载长度 | 负载数据 | 校验位 |
---|---|---|---|---|
0x40444cfa | 0x00 | 0x0004 | 0x68656c64 | 0x6b |
各部分数据说明如下:
参数 | 长度 | 说明 |
---|---|---|
包头 | 4字节 | 固定为0x40444cfa |
消息指令 | 1字节 | 具体的消息指令类型 |
负载长度 | 2字节 | 负载的内容长度N,单位为字节byte |
负载数据 | N字节 | 具体的负载内容,以UTF-8格式编码 |
校验位 | 1字节 | 报文完整性校验值。计算公式为报文内每个byte相加的和取低位字节。按照示例报文计算为:0x40+0x44+0x4c+0xfa+0x00+0x04+0x68+0x65+0x6c+0x64=0x36b, 校验位为0x6b |
后续所有按照该标准通信格式的交互指令均按照此规范格式进行通信。另外,对于某些存在单次发送固定报文长度需求的通信方式(例如蓝牙4.0要求每个包固定20个字节),负载数据可以通过填充0x00字节的方式来适配。
如果通信指令请求出现异常,设备可通过指令0x00向APP响应异常错误信息,响应负载内容如下:
错误代码 | 错误描述 |
---|---|
1个字节 | N-1字节 |
其中,预定义的错误代码有:
错误代码 | 描述 |
---|---|
0x01 | 报文解析出错 |
0x02 | 校验位计算错误 |
0x03 | 不能识别的指令 |
设备信息读取
对于支持与APP进行连接通信的设备,应支持APP通过指令0x01向设备请求设备基本信息,请求负载为空。设备收到该指令后,应返回设备ID和产品型号信息,消息指令不变,负载内容如下:
设备ID长度 | 设备ID | 产品型号长度 | 产品型号 |
---|---|---|---|
1字节 | ... | 1字节 | ... |
设备验证
对于不接入云平台设备网关,直接与APP进行连接通信的设备,APP需要进行设备合法性验证。整个验证流程如下:
1). APP生成随机字符串,并通过指令0x02请求签名校验。举例签名字符串为hello(16进制为0x68656c6c6f),则发送的完整报文内容为:0x40444cfa01000568656c6c6fe4。
2). 设备收到指令,使用该随机签名字符串按照以下计算公式生成一个签名结果并返回APP。同时,一并返回设备ID和产品型号。
sig = CRC32(${产品型号} + "-" + ${随机签名字符串} + "-" + ${产品秘钥})
CRC32校验算法请参考https://baike.baidu.com/item/CRC32/7460858。
返回负载数据内容的格式如下:
签名结果长度 | 签名结果 | 设备ID长度 | 设备ID | 产品型号长度 | 产品型号 |
---|---|---|---|---|---|
1字节 | ... | 1字节 | ... | 1字节 | ... |
3). APP将该设备ID、产品型号、随机签名字符串以及签名结果信息发送给平台进行验证。如果平台按照相同的算法验证结果一致,则证明设备是合法的。
注意,对于接入平台设备网关的设备,由于平台网关会进行设备合法性验证,APP不会调用该指令进行验证。
APP配网
对于需要通过APP进行配网并接入云平台的设备(例如无屏幕的蓝牙Wifi考勤机),一旦搜索成功并建立了连接,则可以通过消息指令0x03将WIFI账户、密码信息传递给设备。
由于明文广播的安全性没有保障,而且如果周围有多台处于配网状态的设备可能造成误配网,因此需要对WIFI广播信息进行加密处理,只有对应产品型号的设备可以解密该配网信息进行网络连接。
配网信息采用XOR加密算法加密wifi密码信息,SID仍采用明文传输。具体加密密码的生成规则如下:
加密密码 = ('DELI@' + 明文WIFI密码) XOR 产品密钥
其中, 产品密钥
为该设备对应产品型号的密钥信息,由平台生成并分配给设备厂商。设备收到该加密信息后,通过产品密钥再次XOR解密出明文密码,如果解密出来的密码以'DELI@'
开头(密码标示),则认为解密成功,设备可去掉该密码标示信息取得明文密码,进行网络连接,否则直接忽略。
需要注意的是,这里的异或算法规则是,用待加密的字符串的每个字节去和产品密钥的每个字节进行异或,产生最终的加密密码字节流。一段Java示例代码如下:
//src = ('DELI@' + 明文WIFI密码)
//key = 产品密钥
byte[] srcBytes = src.getBytes();
byte[] keyBytes = key.getBytes();
for (int i = 0, size = srcBytes.length; i < size; i++) {
for (byte keyByte : keyBytes) {
srcBytes[i] = (byte) (srcBytes[i] ^ keyByte);
}
}
发送数据的负载内容结构如下:
Wifi SID长度 | Wifi SID | Wifi加密密码长度 | Wifi加密密码 |
---|---|---|---|
1字节 | ... | 1字节 | ... |
注意,对于开放的WIFI热点,由于不需要密码认证,请直接将Wifi加密密码长度设置为0,不需要进行密码加密操作。
为了及时获得设备的配网结果,在APP进行设备配网时,如果APP也连接到了Wifi路由器,APP会在端口24333监听UDP广播。设备配网结束后,如果连接路由器成功(不论是否能连接平台),设备应发送UDP广播通知APP配网结果,通知消息指令也是0x03,负载信息包括: 设备ID、产品型号、设备状态、错误消息(可选)。结构如下:
设备ID长度 | 设备ID | 产品型号长度 | 产品型号 | 设备状态码 | 错误消息长度 | 错误代码 | 设备MAC | IP地址 | 子网掩码 | 网关地址 |
---|---|---|---|---|---|---|---|---|---|---|
1字节 | ... | 1字节 | ... | 1字节 | 1字节 | 1字节 | 6字节 | 4字节 | 4字节 | 4字节 |
注意,为了避免局域网内UDP丢包,建议设备配网结束之后至少发送3次以上UDP广播,每次发送间隔时间1 ~ 5s。
除了监听UDP数据包外,APP还会通过轮训平台查询设备接入的状态,整个轮训的周期长度为120s。另外,某些直连APP的通信设备,例如蓝牙设备可直接通过原蓝牙通道将配网结果返回给APP,该类设备可以不用发送UDP广播包。
其中,不同情况下返回的设备状态码不同,包括以下几种情况:
设备状态码 | 状态描述 | 处理建议 |
---|---|---|
-2 | 路由器连接失败 | APP引导重新发起配网流程 |
-1 | 无法访问外部网络 | 提示用户检查路由器设置后再重试 |
0 | 配网成功且接入云平台成功 | 无 |
1 | 配网成功,但接入云平台失败 | 建议用户与售后联系处理 |
如果设备状态码不为0,则表示设备配置网络或连接云平台设备网关出现了故障,设备需要将故障原因通过错误代码反馈给APP。具体的错误代码定义如下:
错误代码 | 设备状态码 | 错误描述 | 提示语建议 |
---|---|---|---|
-6 | -2 | 配网超时 | 网络配置超时,请重试 |
-5 | -2 | 设备不支持连接5G Wifi热点 | 设备不支持5G网络,请切换到2.4G |
-4 | -2 | 其他配网错误 | 网络配置异常,请重试 |
-3 | -2 | Wifi SSID或密码错误 | 重新输入 |
-2 | -1 | 路由器连接成功,但DHCP失败 | IP地址获取异常,请检查路由器DHCP设置 |
-1 | -1 | 无法通过路由器访问外部网络 | 设备连接网络失败,请检查路由器是否支持外网访问 |
1 | -1 | DNS域名解析失败 | DNS解析失败,请检查路由器DNS设置 |
2 | 1 | 无法访问云平台 | 服务器无法访问,请检查网络 |
3 | 1 | 平台访问拒绝,接入认证失败 | 设备认证失败,请与售后联系 |
设备应用交互
在某些具体的业务场景下,如果设备与绑定的H5应用之间需要直接的数据通信交互,可以通过支持APP消息指令0xff来完成。应用和设备具体的业务数据通过报文的负载数据部分来传输,具体负载数据内部的结构可以由设备和应用之间自定义。
包头 | 消息指令 | 负载长度 | 负载数据 | 校验位 |
---|---|---|---|---|
0x40444cfa | 0xff | 0x???? | 设备和应用定义消息 | 0x?? |
其他说明
本文档规定的通信协议和报文格式并非强制性要求,仅作为设备推荐实现方案。如果设备因为自身情况限制,也可以按照其他通信方案实现,APP将通过硬件SDK提供兼容性支持,不过为了完成APP的验证流程,上述基础的功能接口必须实现。