蓝牙介绍

官网:https://www.bluetooth.com/zh-cn/

wiki:蓝牙 - 维基百科,自由的百科全书

分为经典蓝牙和低功耗蓝牙(BLE),前者支持传统的点对点通信,比如无线耳机,无线打印机等,后者支持低功耗,支持更多的拓扑结构,比如蓝牙广播,mesh等。BLE除了数据传输,还支持设备定位,比如蓝牙beacon技术。(参考链接:https://www.bluetooth.com/zh-cn/learn-about-bluetooth/tech-overview/

蓝牙规范:https://www.bluetooth.com/zh-cn/specifications/specs/

蓝牙协议栈


参考链接:

  1. https://docs.espressif.com/projects/esp-idf/zh_CN/stable/esp32/api-guides/ble/overview.html
  2. https://www.espressif.com/sites/default/files/documentation/esp32_bluetooth_architecture_cn.pdf

ESP-BluedroidESP-NimBLE 两个主机,其主要区别如下:

  • 虽然两者都支持低功耗蓝牙,但 ESP-NimBLE 需要的堆和 flash 空间更少。

  • ESP-Bluedroid 支持经典蓝牙和低功耗蓝牙,而 ESP-NimBLE 仅支持低功耗蓝牙。

从整体结构上,蓝⽛可分为控制器 (Controller)主机 (Host) 两⼤部分:控制器包括了PHY、 Baseband、 Link Controller、 Link Manager、 Device Manager、 HCI 等模块,⽤于硬件接⼝管理、链路管理等等;主机则包括了 L2CAP、 SMP、 SDP、 ATT、 GATT、 GAP 以及各种规范,构建了向应⽤层提供接⼝的基础,⽅便应⽤层对蓝⽛系统的访问。主机可以与控制器运⾏在同⼀个宿主上,也可以分布在不同的宿主上。 

控制器提供蓝牙能力,比如射频,PHY,链路控制等,主机提供软件能力,比如蓝牙协议栈实现,两者通过总线解耦,方便将蓝牙能力拓展到不同的主机上。

GAP规范

Generic Access Profile,通用访问规范。

参考链接:https://www.bluetooth.com/specifications/specs/core-specification-5-0/

下载V5.0的pdf文档后,GAP规范的章节在Vol 3 → Part C。

GAP规范的用于定义以下内容:

  1. 角色分类。
  2. 发现模式和发现过程。 
  3. 连接模式和连接过程。
  4. 安全相关的模式和过程。

GAP定义了以下几种角色:

  1. 广播者(Broadcaster)
  2. 观察者(Observer)
  3. 外围设备(Peripheral)
  4. 中心设备(Central)

典型的可扫描、可连接蓝牙设备建立连接的过程如下:

有些设备只需要发送即可,比如Apple Beacon,有些设备只需要接收即可,比如BLE Sniffer,不同的设备对应不同的角色。比如Apple Beacon对应广播者,BLE Sniffer对应观察者。一些低功耗的蓝牙传感器,比如心律监测计,是外围设备,而负责接收的设备,比如手机,则是中心设备。

对于外围设备和中心设备,在连接建立后,需要区分Slave Role和Master Role。

GATT规范

Generic Attribute Profile,通用属性规范。

GATT区分客户端和服务端,客户端通过command, request, confirmation向服务端发送消息,服务端通过resonpse, notification, indication向客户端返回数据。

数据存储在服务端,通过Profile来表示,其格式如下:

Profile包含一个或多个Service,每个Service包含一个Service Declaration(服务声明,用于说明这个服务是干啥的),Service Include(服务引用,引用了其他哪些服务),以及多个特征值,每个特征值表示一个有效数据。

UUID用于表示当前服务的类型,这些类型是预分配好的,基本上所有的知名服务,比如血压计,心律计,定时器等,都有对应好的UUID,具体的UUID可以查看蓝牙规范文档,参考链接:https://www.bluetooth.com/specifications/assigned-numbers/

 

Include表示包含了哪些其他服务及对应的UUID。


特征值结构,首先是特征声明,包含特征的属性,句柄,UUID。


接下来是值的声明。


接下来是可选的补充信息。


所有的属性数据都遵循以下格式:

ATT负责存储数据,GATT为ATT赋予类型属性,根据类型属性就可以对ATT的格式和内容进行解析。

GATT不仅使用ATT来存储和发送数据,还使用ATT来发送命令。

GATT服务端工作流程

  1. 初始化:初始化蓝牙控制器→ 使能蓝牙控制器→ 使能蓝牙协议栈。
  2. 注册GATT callback:gatts_event_handler,注册GATT回调事件。
  3. 注册GAP callback:gap_event_handler,注册GAP回调事件。
  4. 注册GATT APP ID:APP ID用于协议栈区分不同的profile。
  5. 设置MTU:参考Core spec V5.0,搜索MTU。
  6. 处理各种回调事件,包括GAP的回调事件和GATT的回调事件。

GAP事件包括以下几种:

  1. 广播数据设置成功。
  2. 开始广播成功,此时可以用BLE调试助手搜索到对应的广播热点。
  3. 停止广播成功。
  4. 更新连接参数事件。

GATT事件包括以下几种:

  1. GATTS注册事件,表示注册GATT APP ID成功,此时可以拿到这个profile的句柄。
  2. 调用profile的回调函数,继续处理GATT事件,比如特征值读写事件。

GATT服务端广播流程

下载V5.0的pdf文档后,GAP规范的章节在Vol 6 → Part D → 3 Advertising State。

以非定向广播为例,其广播流程如下:


接收端负责扫描广播信息,以第4小节中的被动扫描为例,其流程如下:


客户端也可以进行主动扫描,其流程如下:


GATT服务端广播流程:

  1. 注册GATT APP ID,触发注册APP ID成功事件,此时可以设置GAP广播数据,以及广播扫描应答数据。
  2. 触发GAP广播数据设置完成事件和广播扫描应用数据设置成功事件。
  3. 检测到广播数据设置成功后,使能GAP广播。
  4. 触发GAP开始广播成功事件,表示已经开始广播了。
  5. 主动停止广播,触发停止广播成功事件。

GATT广播数据解析

参考Core spec V5.0,Vol3 → Part C → 11小节。

 

关于AD Type,在上面的Assigned Numbers文档有描述,在Common Data Types章节,以下是一个广播数据示例。

以第一行0x02, 0x01, 0x06为例,0x02表示后面的数据长度为2,0x01表示这是一个标志数据,后面的0x06可以参考Core spec的补充文档查找其含义。

关于device name,广播数据中的device name是用于显示在扫描后的local name中的,而在程序中设置的name是用于在BLE调试助手上显示的。比如XM的所有蓝牙配网设备用BLE调试助手搜索出来的名字都是XM,但由于每个设备广播数据中的device name都不一样,所以在APP上还是可以区分出设备类型。

关于广播数据的长度,可参考Core spec V5.0,Vol6 → Part B → 2.3.1小节。广播数据区分legacy pdu和extended pdu,对应传统蓝牙(4.0, 4.2)和蓝牙5.0(2.3.4小节)。蓝牙5.0通过fragmentation技术,可以发送最大1650字节的广播数据。在设备广播参数时可以指定广播类型,从而决定广播数据包长度。

GATT客户端工作流程

GATT服务端读数据处理

GATT客户端读数据处理

GATT服务端写数据处理





























  • 无标签