第三方蓝牙设备接入方案1. 简介1.1 支持第三方设备的芯片型号2. 操作流程2.1. 添加设备2.2. 第三方设备开锁2.3. 第三方设备闭锁2.4. 查询锁状态3. 通讯协议3.1. 通讯格式3.2. 第三方设备和锁之间的通讯密钥3.3. 广播数据3.4. 通讯命令3.4.1. 第三方蓝牙设备和门锁通讯命令3.4.1.1. 添加设备3.4.1.2. 获取临时令牌3.4.1.3. 开锁3.4.1.4. 闭锁3.4.1.5. 查询锁状态3.5. 错误码表3.6. 附录3.6.1. CRC值计算方法3.6.2 添加第三方设备示例4.参考代码
随着通通锁方案的锁的大量出货,有越来越多的第三方设备需要控制我们方案的锁,如果第三方设备有安卓或者苹果系统,可以用我们提供的SDK来支持,但也有不少设备不具有操作系统,需要我们开放部分协议进行控制,本方案就是为了满足这种使用场景而设计,让门锁可以被蓝牙模块(无操作系统)来控制开锁或者闭锁,查询锁状态。
支持第三方设备添加、调整蓝牙广播时间的芯片型号如下,请联系锁厂购买相应芯片型号的锁,或进行固件版本号的推送升级:
534-15-1,534-16-1,503-18-1 ,8534-3-1,8534-1-1,8503-2-1
添加设备时,需要App、锁、第三方蓝牙设备三方通讯,并且第三方蓝牙设备需要支持接收蓝牙广播数据,具体流程如下:
锁状态可以直接在锁的正常广播数据中获取,下面是广播的数据例子:
在类型为0xFF的厂商自定义数据中,有门锁的状态信息,具体格式如下:
注意:锁状态也可以通过下面的命令查询。
| 字段名称 | 字节数 | 备注 |
|---|---|---|
| 同步头 | 2 | 0x7F 0x5A |
| 固定数据1 | 7 | 0x05 0x03 0x00 0x00 0x01 0x00 0x01 |
| 命令码 | 1 | 第三方设备发给门锁时,填充命令码;门锁返回时,固定为0x54 |
| 固定数据2 | 1 | 0xB0 |
| 参数长度 | 1 | |
| 参数 | N | 参数长度字段指出的字节个数 |
| CRC校验 | 1 | 前面所有字段的CRC校验值 |
| 固定数据 | 2 | 0x0D 0x0A |
同步头:2个字节,固定为0x7F 0x5A
固定数据1:7个字节,固定为0x05 0x03 0x00 0x00 0x01 0x00 0x01
命令码:1个字节,具体看下面的命令
固定数据2:1个字节,固定为0xB0
数据长度:1个字节,后面数据字段的字节个数
数据:n个字节,具体由数据长度字段的值指出字节个数,数据字段的内容,需要通过AES算法进行加解密,算法见附件。
CRC校验:1个字节,同步头(0x7F 0x5A)开始到本字段之前的所有数据的CRC校验值,算法见附件。
数据包举例:7F5A0503000001000188B010C18C99218D9912CB9D36CE659678D95CDC0D0A
固定的AES key: 0x87,0x12,0x35,0xAE,0x45,0x23,0xC9,0xE3,0x3F,0x67,0x34,0x32,0xBD,0xF9,0xA2,0xC9
添加设备过程,采用上面的固定AES key,其他过程,采用添加过程中生成的密钥。
锁接收到App允许添加设备的命令后,会进行蓝牙广播,广播的UUID为0x1911,广播的厂商自定义数据如下(其中状态字段为0x01):
| 字节序号 | 数据 | 备注 |
|---|---|---|
| 1 | 0x06 | 固定数据 |
| 2 | 0x01 | 固定数据 |
| 3 | 0xXX | 状态0x01-允许添加设备0x02-添加设备结束 |
| 4-9 | 0xXXXXXXXXXXXX | 锁的蓝牙地址,低在前,高在后 |
添加第三方设备结束后,广播的状态字段变为0x02。
注意:第三方蓝牙设备可以搜索UUID为0x1911,厂商自定义数据前三个字节为0x06、0x01、0x01的蓝牙设备进行添加设备动作。
命令码:0x88
子命令码:
| 子命令码 | 子命令描述 |
|---|---|
| 0x01 | 添加设备 |
| 0x02 | 获取临时令牌 |
| 0x03 | 开锁 |
| 0x04 | 闭锁 |
| 0x05 | 查询锁状态 |
A. 请求参数
| 字段名称 | 字节数 | 备注 |
|---|---|---|
| 子命令码 | 1 | 固定数据0x01 |
| 第三方设备蓝牙地址 | 6 | 低在前、高在后的字节顺序 |
B. 应答参数
| 字段名称 | 字节数 | 备注 |
|---|---|---|
| 命令码 | 1 | 0x88 |
| 子命令码 | 1 | 0x01 |
| 门锁电量百分比 | 1 | 0~100 |
| 操作结果 | 1 | 0x00 - 成功其他见错误码表 |
| 永久令牌 | 4 | 4字节整数,Big endian |
| AES Key | 16 |
A. 请求参数
| 字段名称 | 字节数 | 备注 |
|---|---|---|
| 子命令码 | 1 | 0x02 |
| 第三方设备蓝牙地址 | 6 | Little Endian |
B. 应答参数
| 字段名称 | 字节数 | 备注 |
|---|---|---|
| 命令码 | 1 | 0x88 |
| 子命令码 | 1 | 0x02 |
| 门锁电量百分比 | 1 | 0~100 |
| 临时令牌 | 4 | 4字节整数,Big endian |
A. 请求参数
| 字段名称 | 字节数 | 备注 |
|---|---|---|
| 子命令码 | 1 | 0x03 |
| 开锁令牌 | 4 | 永久令牌+临时令牌的和,Big endian |
B. 应答参数
| 字段名称 | 字节数 | 备注 |
|---|---|---|
| 命令码 | 1 | 0x88 |
| 子命令码 | 1 | 0x03 |
| 门锁电量百分比 | 1 | 0~100 |
| 操作结果 | 1 | 0x00 - 成功其他见错误码表 |
A. 请求参数
| 字段名称 | 字节数 | 备注 |
|---|---|---|
| 子命令码 | 1 | 0x04 |
| 闭锁令牌 | 4 | 永久令牌+临时令牌的和,Big endian |
B. 应答参数
| 字段名称 | 字节数 | 备注 |
|---|---|---|
| 命令码 | 1 | 0x88 |
| 子命令码 | 1 | 0x04 |
| 门锁电量百分比 | 1 | 0~100 |
| 操作结果 | 1 | 0x00 - 成功其他见错误码表 |
A. 请求参数
| 字段名称 | 字节数 | 备注 |
|---|---|---|
| 子命令码 | 1 | 0x05 |
B. 应答参数
| 字段名称 | 字节数 | 备注 |
|---|---|---|
| 命令码 | 1 | 0x88 |
| 子命令码 | 1 | 0x05 |
| 门锁电量百分比 | 1 | 0~100 |
| 操作结果 | 1 | 0x00 - 成功其他见错误码表 |
| 锁状态 | 1 | 0x00 - 闭锁0x01 - 开锁0x02 - 未知 |
注意:锁状态,也可以通过锁的广播数据获取
| 错误码 | 描述 |
|---|---|
| 0x0E | 已过期 |
| 0x11 | 未到有效期 |
| 0x13 | 未知错误 |
| 0x1C | 门锁已冻结 |
| 0x1E | 门已反锁 |
| 0x02 | 令牌错误 |
//================
//8位CRC速查表
//================
xxxxxxxxxx371unsigned char const CRC_TABLE[256] =23{450x00,0x5E,0xBC,0xE2,0x61,0x3F,0xDD,0x83,0xC2,0x9C,0x7E,0x20,0xA3,0xFD,0x1F,0x41,670x9D,0xC3,0x21,0x7F,0xFC,0xA2,0x40,0x1E,0x5F,0x01,0xE3,0xBD,0x3E,0x60,0x82,0xDC,890x23,0x07,0x9F,0xC1,0x42,0x1C,0xFE,0xA0,0xE1,0xBF,0x5D,0x03,0x80,0xDE,0x3C,0x62,10110xBE,0xE0,0x02,0x5C,0xDF,0x81,0x63,0x3D,0x7C,0x22,0xC0,0x9E,0x1D,0x43,0xA1,0xFF,12130x46,0x18,0xFA,0xA4,0x27,0x79,0x9B,0xC5,0x84,0xDA,0x38,0x66,0xE5,0xBB,0x59,0x07,14150xDB,0x85,0x67,0x39,0xBA,0xE4,0x06,0x58,0x19,0x47,0xA5,0xFB,0x78,0x26,0xC4,0x9A,16170x65,0x3B,0xD9,0x87,0x04,0x5A,0xB8,0xE6,0xA7,0xF9,0x1B,0x45,0xC6,0x98,0x7A,0x24,18190xF8,0xA6,0x44,0x1A,0x99,0xC7,0x25,0x7B,0x3A,0x64,0x86,0xD8,0x5B,0x05,0xE7,0xB9,20210x8C,0xD2,0x30,0x6E,0xED,0xB3,0x51,0x0F,0x4E,0x10,0xF2,0xAC,0x2F,0x71,0x93,0xCD,22230x11,0x4F,0xAD,0xF3,0x70,0x2E,0xCC,0x92,0xD3,0x8D,0x6F,0x31,0xB2,0xEC,0x0E,0x50,24250xAF,0xF1,0x13,0x4D,0xCE,0x90,0x72,0x2C,0x6D,0x33,0xD1,0x8F,0x0C,0x52,0xB0,0xEE,26270x32,0x6C,0x8E,0xD0,0x53,0x0D,0xEF,0xB1,0xF0,0xAE,0x4C,0x12,0x91,0xCF,0x2D,0x73,28290xCA,0x94,0x76,0x28,0xAB,0xF5,0x17,0x49,0x08,0x56,0xB4,0xEA,0x69,0x37,0xD5,0x8B,30310x57,0x09,0xEB,0xB5,0x36,0x68,0x8A,0xD4,0x95,0xCB,0x29,0x77,0xF4,0xAA,0x48,0x16,32330xE9,0xB7,0x55,0x0B,0x88,0xD6,0x34,0x6A,0x2B,0x75,0x97,0xC9,0x4A,0x14,0xF6,0xA8,34350x74,0x2A,0xC8,0x96,0x15,0x4B,0xA9,0xF7,0xB6,0xE8,0x0A,0x54,0xD7,0x89,0x6B,0x353637};
/*
* 描述:
* 使用快速查表法计算位的CRC结果
* 参数:
* pData 需要计算CRC的数组
* nDataCount 需要计算CRC的数组字节个数
* 返回值:
* CRC值
*/
xxxxxxxxxx121int CalcCRC(LPBYTE pData, int nDataCount)2{3unsigned char CRC_result = 0;45while(nDataCount--)6{7CRC_result ^= *pData++;8CRC_result = CRC_TABLE[CRC_result];9}10return CRC_result;11}12
*第三方设备数据:
第三方设备mac地址: 00-a1-26-66-bf-01
固定的AES key:0x87,0x12,0x35,0xAE,0x45,0x23,0xC9,0xE3,0x3F,0x67,0x34,0x32,0xBD,0xF9,0xA2,0xC9
加密前参数:0x01,0x00,0xA1,0x26,0x66,0xBF,0x01
加密后参数:0xC1 0x8C 0x99 0x21 0x8D 0x99 0x12 0xCB 0x9D 0x36 0xCE 0x65 0x96 0x78 0xD9 0x5C
CRC校验值:0xDC
完整数据包:7F5A0503000001000188B010C18C99218D9912CB9D36CE659678D95CDC0D0A
*锁回复数据:
-7f-5a-05-03-00-00-01-00-01-54-b0-20-4a-6c-86-90-bd-43-29-c8-e1-8c-75-95-2c-4b-34-10-e8-ec-b9-81-8c-cc-f8-ad-4e-e1-e9-77-8b-89-af-45-f0-0d-0a-
解密后参数:
-88-01-3d-00-1c-de-1a-d0-cb-c2-25-4f-29-6e-a8-ab-71-5f-7a-a9-a5-3f-93-f6-
第三方设备控制锁参考代码:Demo