蓝牙通信接口

蓝牙通信接口

概述

本文主要包含包含了蓝牙功能的前端设备的广播,扫描应答,GATT 服务等蓝牙通信接口

BeacoNice 广播包

蓝牙应用程序使用主动扫描模式下,当设备收到扫描请求包之后会立即回复一个扫描应答包

蓝牙设备通过扫描应答包来传输设备名称,设备类型,固件版本号,电池电量等基本信息.

扫描应答包中必须包含制造商数据内容,并通过其 Company ID,Department ID 和 Product ID 属性的值来判断是否是 BeacoNice 蓝牙设备.

扫描应答包数据结构

No. Name Size Sample Note
1 AD Size 1 0x0E 这个 AD 的大小,14 个字节
5 AD Type 1 0xFF AD_TYPE_MANUFACTURER_SPECIFIC_DATA
3 Company ID 2 0x0D06 TDK Corporation: 0x060D
4 Department ID 1 0x11 部门 ID,总是为 0x11
5 Product ID 1 0x02 产品类型 ID,0x02: Sensor & DTU
6 Firmware Version 2 0x0A0B 固件版本,0x0A0B = v10.11
7 Battery Level 1 0x0B 电池电量,0x00-0x64,0xFF 表示没有电池
8 Device ID 6 - 设备 ID,如: 0x0080980287d6,即蓝牙 MAC 地址
9 AD Size 1 0x02 这个 AD 的长度,2 个字节
10 AD Type 1 0x0A ADV_TYPE_TX_POWER_LEVEL
11 Tx Power Value 1 0xC0 无线发射功率,0xEC = -20dBm
12 AD Size 1 0x0A 设备名结构体长度 (最长 11 个字节)
13 AD type 1 0x09 ADV_TYPE_COMPLETE_LOCAL_NAME
14 Name Data 10 - 设备名称,如: BN5001ABCD

AD

蓝牙广播包 PDU 主要由一到多个 AD 组成,每个 AD 的结构如下:

  • AD Size,1 个字节,这个 AD 的长度,不包括 AD Size 本身
  • AD Type,1 个字节,这个 AD 的类型
  • AD Data,0 到多个字节,这个 AD 的内容

扫描应答包主要包含了如下 3 个 AD:

  • 无线发射功率 AD
  • 设备名称 AD
  • 制造商数据 AD

它们的具体描述如下:

无线发射功率 AD

这个 AD (ADV_TYPE_TX_POWER_LEVEL) 包含了设备的无线发射功率.

使用一个字节有符号整数来表示无线发射功率,单位为 dBm.

可以表示的范围为 -20 dBm ~ 100 dBm,除此外的值不被蓝牙规范接受.

这个 AD 是可选的.

设备名称 AD

这个 AD (ADV_TYPE_COMPLETE_LOCAL_NAME) 包含了设备的名称.

内容为 UTF-8 字符串,可以在应用程序或配置工具里显示,方便用户识别.

当没有指定设备名时,将使用默认的设备名,默认设备名生成规则为:

  • 型号名 + MAC 地址最后两个字节的 16 进制字符串.
  • 总体长度不能超过 10 个字节
  • 例如 BN1004ABCD

这个 AD 是必需的.

制造商数据 AD

这个 AD (AD_TYPE_MANUFACTURER_SPECIFIC_DATA) 包含了和设备制造商有关的信息.

BeacoNice 使用制造商数据来传递 Beacon 的一些基本属性.

  • Company ID - 厂商 ID,2 个字节,由 SIG 分配,TDK 为 0x060D
  • Frame Type - 数据帧类型,1 个字节,由公司分配
  • Product ID - 产品类型 ID,1 个字节,由公司分配
  • Firmware Version - 固件版本,2 个字节,高字节为主版本号,低字节为次版本号
  • Battery Level - 1 个字节,电池剩余电量百分比
  • Beacon ID - 可选,设备 ID,6 个字节,即设备的蓝牙 MAC 地址

产品类型 ID:

BeacoNice 使用一个字节来表示产品类型,下面是具体的值分别代表的产品类型:

Product ID Product Name Description
0x00 Reserve 保留将来使用
0x01 Battery Beacon 普通 Beacon
0x02 Sensor 传感器和数据采集器
0x07 Thermometer 蓝牙基础体温计
0x03 Solar Beacon 光能 Beacon
0x04-0x06 Asset Tag 资产定位标签
0x08-0xFF Reserve 保留将来使用

固件版本:

BeacoNice 使用两个字节无符号整数来表示固件版本

  • 高字节: 主版本号,0 ~ 255
  • 底字节: 次版本号,0 ~ 255

电池电量:

BeacoNice 使用一个字节无符号整数来表示电池电量百分比

  • 0x00~0x64 表示 0% ~ 100% 的电量
  • 0xFF 表示没有电池

信标 ID:

BeacoNice 使用六个字节来表示信标的 ID (即蓝牙 MAC 地址)

因为在 iOS 等设备中不允许读取蓝牙设备的 MAC 地址,所以这个字段对 iOS 等应用很有用

这个属性是可选的,如果不包含则制造商数据 AD 长度为 8.

Sensor 广播包数据包结构

Sensor 广播用来对外发送设备内置的传感器测量得到的数据

主要组成内容如下:

  • Beacon ID
  • 传感器类型
  • 传感器测量值

因为不同的设备包含的传感器不一样,所以不同于其他广播包,这个广播的具体内容和长度是可变的

可以同时包含多个传感器测量值,但是最大不要超过 22 个字节 (整个广播包不要超过 31 个字节)

数据包格式如下:

No. Name Size Sample Note
1 AD Size 1 0x02 这个结构体的长度,2 个字节
2 AD Type 1 0x01 AD_TYPE_FLAGS
3 Flags Value 1 0x06 Flags value
4 AD Size 1 0x0E 这个结构体的长度,最多 27 个字节
5 AD Type 1 0xFF AD_TYPE_MANUFACTURER_SPECIFIC_DATA
6 Company ID 2 0x0D06 TDK Corporation: 0x060D
7 Department ID 1 0x11 部门 ID,总是为 0x11
8 Product ID 1 0x02 产品类型 ID,0x02: Sensor
9 Sensor Data N - 传感器数据内容,最多 22 个字节

注意 Sensor Data 总共不能超过 22 个字节.

Sensor Data 的格式如下:

No. Name Size Sample Note
1 Data Type 1 - 传感器的类型
2 Data Value N - 测量的值,长度由类型决定
N - - - 更多传感器数据

例如下面是一个包含了温湿和大气压传感器的设备的广播内容:

No. Name Size Sample Note
1 AD Size 1 0x02 这个结构体的长度,2 个字节
2 AD Type 1 0x01 AD_TYPE_FLAGS
3 Flags Value 1 0x06 Flags value
4 AD Size 1 0x0E 这个结构体的长度,最多 27 个字节
5 AD Type 1 0xFF AD_TYPE_MANUFACTURER_SPECIFIC_DATA
6 Company ID 2 0x0D06 TDK Corporation: 0x060D
7 Department ID 1 0x11 部门 ID,总是为 0x11
8 Product ID 1 0x02 产品类型 ID,0x02: Sensor
9 Data Type 1 0x01 温度
10 Data Value 2 0x1980 0x1980 = 0x19 + 0x80 / 0x100 = 25 + 128 / 256 = 25.5 度
11 Data Type 1 0x03 湿度
12 Data Value 1 0x50 0x50 = 80 = 80%
13 Data Type 1 0x04 压力
14 Data Value 3 0x018A16 0x018a16 = 100886 = 1008.86Hpa

常用传感器类型

Name ID Size Sample Note
Beacon ID 0x00 6 0x112233AABBCC 设备的 MAC 地址
Battery 0x01 2 0x6000 电池电压,1 mV/bit,Big Endian
Temperature 0x02 2 0x1980 摄氏温度,第一字节: 整数位,第二字节: 小数位。 0x1980 = 0x19 + 0x80 / 256 = 25 + 128 / 256 = 25.5 度
Humidity 0x03 1 0x50 相对湿度,0x00-0x64,如 0x50 = 80 = 80%
Atmosphere 0x04 3 0x018A16 大气压,0~167 * 1000Hpa,0x018a16 = 100886 = 1008.86Hpa,Big Endian
Alarm 0x05 1 0x01 告警状态, 1 表示告警, 0 表示正常
Open 0x06 1 0x01 打开/关闭状态, 1 表示打开,0 表示关闭
ch2o 0x10 2 0x1000 无符号整数,单位为 ug/m3
co 0x11 2 0x1000 无符号整数,单位为 ug/m3
co2 0x12 2 0x1000 无符号整数,单位为 ug/m3
h2s 0x13 2 0x1000 无符号整数,单位为 ug/m3
nh3 0x14 2 0x1000 无符号整数,单位为 ug/m3
no2 0x15 2 0x1000 无符号整数,单位为 ug/m3
o3 0x16 2 0x1000 无符号整数,单位为 ug/m3
so2 0x17 2 0x1000 无符号整数,单位为 ug/m3
pm10 0x20 2 0x1000 无符号整数,单位为 ug/m3
pm25 0x21 2 0x1000 无符号整数,单位为 ug/m3
- 0x22-0xFE - - 保留将来使用
Sensor Type 0xFF 1 0x01 传感器类型

上面只列出了已知的产品包含的传感器类型,将来可以继续扩展,暂时最多可以定义 255 种传感器类型.

传感器类型

ID 类型
0x00 无指定类型传感器
0x01 温度传感器
0x02 气象站
0x03 气体传感器
0x04 烟雾报警器
0x05 门窗传感器
0x06 水浸传感器

通用访问 (GAP) 服务

TYPE NOTE
Name Generic Access
Service UUID 0x1800

设备名

TYPE NOTE
Characteristic UUID 0x2A00
Name Device Name
Properties READ
Value 表示设备的名称,UTF-8 字符串

常见产品名称:

  • BN2001: Asset Tag
  • BN2002: Asset Tag
  • BN1002: Beacon
  • BN1003: Solar Beacon
  • BN1004: Solar Beacon
  • BN1005: Temperature Sensor
  • BL1001: ESL
  • BN5001: Motor Sensor
  • BN5003: Temperature Sensor
  • BN5005: Alarm Detector
  • DT01: DTU

外观

TYPE NOTE
Characteristic UUID 0x2A01
Name Appearance
Properties READ
Value 外观特性,16 位的值,默认为 0x0000

这个特征值为枚举类型,在编号分配文件中定义. 用来列举设备的外观样式,如颜色等.

外围设备首选连接参数

TYPE NOTE
Characteristic UUID 0x2A04
Name Slave Preferred Connection Parameters
Properties READ
Value -

具体请参考 GAP 服务相关规范.

通用属性 (GATT) 服务

TYPE NOTE
Name Generic Attribute
Service UUID 0x1801

服务改变

TYPE NOTE
Characteristic UUID 0x2A05
Name Service Changed
Properties INDICATE

一旦服务端的 GATT 属性分布有变(增加了或者移除了一些信息),服务就可以通过这个特征值的 indication 来通知应用程序.

具体请参考 GATT 服务相关规范.

设备信息服务

所有产品都必须实现这个服务,用来提供关于这个设备的基本信息.

TYPE NOTE
Name Device Information
Service UUID 0x180A

制造商名称字符串

TYPE NOTE
Characteristic UUID 0x2A29
Name Manufacturer Name String
Properties READ
Value 总是为 TDK Corporation

型号编码字符串

TYPE NOTE
Characteristic UUID 0x2A24
Name Model Number String
Properties READ
Value BN5001

固件版本字符串

TYPE NOTE
Characteristic UUID 0x2A26
Name Firmware Revision String
Properties READ
Value 3.2,分别表示主,次版本号

硬件版本字符串

TYPE NOTE
Characteristic UUID 0x2A27
Name Hardware Revision String
Properties READ
Value 1.0,分别表示主,次版本号

电池服务

只有带电池的产品可选实现这个服务.

TYPE NOTE
Name Battery Service
Service UUID 0x180F

电池电量

TYPE NOTE
Characteristic UUID 0x2A19
Name Battery Level
Properties READ
Value 0 到 100,表示 0% 到 100% 的电量

虚拟串口服务

只有蓝牙传感器可选实现这个服务.

TYPE NOTE
Name UART Service
Service UUID 6E400001-B5A3-F393-E0A9-E50E-24DCCA9E

接收端

TYPE NOTE
Characteristic UUID 0x0002
Name RX
Lock Requirement 当为解锁状态时可写
Properties READ,NOTIFY

发送端

TYPE NOTE
Characteristic UUID 0x0003
Name TX
Lock Requirement 当为解锁状态时可读
Properties WRITE

配置服务

TYPE NOTE
Name Configuration Service
Service UUID A3C87600-8ED3-4BDF-8A39-A01BEBEDE295

在没有明确说明的情况下,写入和读取的数据都是用 big-endian 的字节数组来定义的。

设备能力

TYPE NOTE
Characteristic UUID a3c87501-8ed3-4bdf-8a39-a01bebede295
Name Capabilities
Lock Requirement 当为解锁状态时可读,永远不可写
Properties READ

属性:

// byte array (read)

{
    version_byte,
    product_byte,
    data[N],
    supported_radio_tx_power[0] ... supported_radio_tx_power[N-1]
}

长度: >= 7 bytes

描述:

返回一个如下编码的数组:

  • version_byte: 8-bit 版本号, 当前版本号为 0x00.
  • product_byte: 8-bit 产品号, 当前版本号为 0x00.
  • data 数据内容,具体内容和设备版本相关
  • supported_radio_tx_power: 一个可变长度的数组,表示支持的无线发射功率值. 注意必须按从低到高排列.

返回值:

  • Read Not Permitted: 当试图读锁定状态的 Beacon 时.
  • Write Not Permitted: 当任何时间试图写入时.

锁定状态

TYPE NOTE
Characteristic UUID a3c87506-8ed3-4bdf-8a39-a01bebede295
Name Lock State
Lock Requirement 总是可读,必须在解锁状态下才可以读写

属性:

uint8_t lock_state (read)

byte_array (write) {
    lock_byte,
    encrypted_key[0] ... encrypted_key[15]
}

描述:

读取这个属性时,将读取到一个表示当前锁定状态的字节:

  • 0x00: LOCKED 锁定状态
  • 0x01: UNLOCKED 解锁状态
  • 0x02: UNLOCKED AND AUTOMATIC RELOCK DISABLED

写一个字节来锁定,或者写 17 个字节来切换到一个新的锁定状态:

0x00: 切换到锁定状态,但是不会改变当前密钥 0x00 + key[16]: 切换到锁定状态,但是会改变当前密钥. 0x02: disable the automatic relocking capability of the interface

长度: 1 byte or 17 bytes

  • 建立连接后,5 秒内不解锁将断开连接,防止耗电
  • BEACON 硬件和手机 APP 默认相同的密钥

返回值:

  • Write Not Permitted: 当试图写入一个非法的 Key 来解锁

解锁

TYPE NOTE
Name Unlock
Characteristic UUID a3c87507-8ed3-4bdf-8a39-a01bebede295
Lock Requirement 必须在锁定的状态下才可以读写

属性:

byte_array (read) {
    challenge[0] ... challenge[15]
}

byte_array (write) {
    unlock_token[0] ... unlock_token[15]
}

长度: 16 bytes

描述:

用来解锁 Beacon.

  • 读: 返回一个 128 位的 challenge token,这个码是一次性的,不能重复使用.
  • 写: Beacon 接收一个 128 位的加密值,它能通过这个值来验证应用程序是否知道正确的解锁码.

应用程序首先通过这个 Characteristic 读取到一个 16 个字节的随机码,然后使用 AES-128-ECB.encrypt (key=beacon_lock_code[16],text=challenge[16]) 算法生成一个 16 字节的解锁码.

应用程序将生成的解锁码写到这个 Characteristic,Beacon 将使用同样的算法计算出相应的结果并和这个解锁码比较.

如果两个值是相同的,Beacon 就会被解锁,并设置 Lock state0x01.

返回值:

  • Read Not Permitted: 当试图在未锁定状态下读取.
  • Write Not Permitted: 当试图在未锁定状态下写入.

恢复出厂设置

TYPE NOTE
Name (Advanced) Factory reset
Characteristic UUID a3c8750b-8ed3-4bdf-8a39-a01bebede295
Lock Requirement 必须在解锁后才能写. 且锁定状态必须为 0x01.

属性:

uint8_t reset_boolean (write)

描述:

当写入一个 0x0B 的值后,Beacon 必须恢复到出厂状态. 但是不会恢复解锁码,它还是保留当前的值. 其他用户配置的数据,比如广播的数据内容等都会被清除.

写入其他的值都不会有任何处理.

返回值:

  • Write Not Permitted: 当试图在锁定状态时或者锁定状态不是 0x01 时写入.

批量读写配置参数

TYPE NOTE
Name (Advanced) BeacoNice Configuration
Characteristic UUID a3c87680-8ed3-4bdf-8a39-a01bebede295
Lock Requirement 必须在解锁状态下读写.

属性:

byte array (read/write) {
    size,
    type,
    data[0]...data[N],
    size,
    type,
    data[0]...data[N]
    ...
}

描述:

批量读写配置参数

返回值:

  • Read Not Permitted: 当试图在锁定状态下读取.
  • Write Not Permitted: 当试图在锁定状态下写入.
  • Invalid Attribute Length: 当试图写入一个非法长度的数据.

GATT 错误码

Code Description Notes
0x02 Read Not Permitted 当在 Beacon 处于锁定状态时访问一个需要认证的特征值
0x03 Write Not Permitted 当特征值为只读
0x0d Invalid Attribute Length 当参数超出范围,或者数据长度不同于预期

附录

密码锁策略

  • 设备默认设置为公共密钥,APP 默认内置这个公共密钥
  • 在客户下单时,为客户创建账号,并为客户生成客户密钥,并保存在数据库
  • 将客户密钥写入将出售给客户的 设备中
  • 客户收到 设备 时,下载配置 APP 并登录自己的账号,同时会下载自己的密钥
  • 客户通过自己的密钥可以配置自己购买的 设备,但其他人都无法修改
  • 设备同时内置一个超级管理密钥,以便设备密钥遗忘或维修使用
  • 当客户密钥密码验证不通过时,会验证是否是超级管理密钥,如果都不通过才返回验证失败
  • 使用超级管理密钥解锁后就可以重新设置新的客户密钥等
image-modal