以下内容是我在初识蓝牙时收集整理的一些资料,以供有需要的同学们。如果有不对的地方还望指出,因为有很多是看别人博客里讲解的,如果有侵权望告知,会即时删除。

1 蓝牙广播

BLE协议栈采用了分层结构,其中有一层称为GAP(Generic Access Profile),该层负责设备间的广播,搜寻以及连接。搜寻过程涉及广播设备和扫描设备。BLE蓝牙广播,按照蓝牙spec,每一个广播事件包含三个广播包,即分别在37/38/39三个通道上同时广播相同的信息。

蓝牙广播数据包的主要格式:一个广播包是由若干个广播单元AD Structure构成的。每个广播单元的组成是:第一个字节是长度值 length,表示接下来的 length个字节是数据部分;数据部分的第一个字节表示数据的类型AD Type,决定了AD Data的数据代表的是什么以及怎么解析,广播数据最长31字节。

android蓝牙ble广播 蓝牙音频广播_网络

1.1 AD Type说明

见《Generic Access Profile.pdf》,可从官网下载。

1.2 Beacon帧格式

1.2.1 beacon广播报文类型

一般使用ADV_NONCONN_IND(不可连接的非定向广播)作为Beacon包的“广播报文类型”,有两种AD Type可以被用作自定义beacon帧,分别是0xFF和0x16。0x2B 为MESH beacon的AD Type。0xFF表示厂商自定义数据,厂商数据字段的数据域前2字节为公司识别码。由蓝牙SIG组织分配给各公司,指示后续数据的解码方式。
使用0xFF作为beacon的公司有苹果公司的ibeacon,Radius Network的AltBeacon。
使用0x16作为beacon的公司有谷歌公司的Eddystone,xiaomi的mibeacon。
例如小米mibeacon的AD Stucture: AD Length + Type(0x16)+ 16bit Service Data UUID(0xFE95,小米申请的UUID)+ Frame Control(2字节) + Product ID(2字节) + Frame Counter (1字节)+ …
注:各大公司申请的UUID见附件:《16-bit UUID Numbers Document.pdf》,其中百度(0xFDC2,0xFDC3),小米(0xFDAB,0xFDAA,0xFE95),alibaba(0xFE3C),nordic(0xFE59,0xFE58)

1.2.2 苹果ibeacon AD Structure

android蓝牙ble广播 蓝牙音频广播_网络_02

1.2.2.1 ibeacon数据协议分析Frame: 62 bytes

Nordic BLE Sniffer
04: Board
37 00: 0x0037(55),表示length of payload
02: Protocol version
68 14: 0x1468(5224),表示Packet counter
06: Packer ID
0a: length of packet(包含自身)
01: Flags
26: Channel 38
53: RSSI
00 00: Event counter 0
3c 6f 00 00 : Delta time
Bluetooth Low Energy Link Layer
Access Address: d6 be 89 8e(0x8e89bed6)
Packet Header: 20 24
20 表示PDU Type
ADV_IND:可连接无定向广播
ADV_DIRECT_IND可连接定向广播
ADV_NONCONN_IND:不可连接无定向广播
SCAN_REQ: 扫描请求(从机接收扫描包)
SCAN_RSP:扫描回应(从机发送扫描回应包)
CONNECT_REQ:连接请求
ADV_SCAN_IND:可扫描无定向广播
24 表示length 36(不包含自身)
Adverting Address(大端): ff ff b1 22 8e b0 (0xb08e22b1ffff)
Adverting Data: 后面数据
Flags:02 01 06
02 length
01 AD Type:Flags
06 详见右图
Manufacturer Specific:
1a: length 26
ff: AD Type:《Manufacturer Specific Data》
4c 00:0x004C 代表苹果公司
0x02 代表proximity beacon
0x15 表示接下来有21个字节的数据
9-24 表示16字节uuid
25-26 表示major的值
27-28 表示minor的值
29 TX Powerer

1.2.3 Radius Network的AltBeacon AD Structure

android蓝牙ble广播 蓝牙音频广播_数据_03


0x0118 代表Radius Network

0x8EAC Beacon Code

9-24 Beacon ID org.uint

25-28 Beacon ID(remainder)

29 TX Powerer

1.2.4 谷歌公司的Eddystone AD Structure

一般采用AD Type 0x16,还定义了0x00,0x10,0x20

例: 小米mibeacon的AD Structure

android蓝牙ble广播 蓝牙音频广播_网络_04


3 代表数据长度

4 AD Type 0x16

5-6 16bit Service Data UUID 如小米公司0xFE95

7-8 Frame Control(2字节)

9-10 Product ID(2字节)

11 Frame Counter (1字节)

……

1.3 凯普勒ADV广播实例说明

android蓝牙ble广播 蓝牙音频广播_android蓝牙ble广播_05


09 08 69 53 65 6e 73 6f 72 20 表示设备名称为: 69 53 65 6e 73 6f 72 20(iSensor□)

09 ff 00 db 97 46 42 02 25 21 厂商自定义数据: 00 db 97 46 表示设备ID(4Bytes), 42 02 25表示数据部分(3Bytes),21表示校验和(1Byte)。

2 蓝牙概念

低功耗蓝牙中则有一个主设备(Central)和从设备(Peripheral,也叫外围设备)的概念。主设备作为发现方,扫描发现外围设备,从设备则作为被发现方,发出广播,以供发现。总体流程大致为:发现设备->配对/绑定设备->建立连接->数据通信,与传统蓝牙除了配对/绑定这个环节一样,其它三个环节都是不同。
注:各种叫法对应
Observer —> Master —> Central --> Client
Advertiser —> slaver —>Perpheral -->Server
在蓝牙设备中,存在着物理地址,我们也叫作蓝牙的MAC地址,这个地址是唯一的,就像网络上的IP地址。同时还存在着一个叫做UUID的东西,理解为是IP地址中的端口号。正如知道了IP地址和端口号,就知道怎么链接到目标网络服务器位置,知道了蓝牙设备的MAC地址和UUID也就能够确定到具体是哪一台蓝牙设备了,这两者合起来就是蓝牙的唯一身份标识。

2.1 基本概念

2.1.1 名词

Generic Access Profile (GAP) 通用访问配置文件
GAP是应用层能够直接访问BLE协议栈的最底层,包括管理广播和连接事件的有关参数。GAP的服务包括设备发现,连接方式,安全,认证,关联模型和服务发现等。
Generic Attribute Profile (GATT)通用属性配置文件
GATT层是传输真正数据所在的层,定义两个两类角色:服务器和客户端。通过BLE连接,读写属性类小数据的Profile通用规范,现在所有的BLE应用Profile都是基于GATT的。
Attribute Protocol (ATT) 属性协议
GATT是基于ATT Protocol的。ATT针对BLE设备做了专门的优化,具体就是在传输过程中使用尽量少的数据。每个属性都有一个唯一的UUID,属性将以characteristics and services的形式传输。
Characteristic(特性):
Characteristic可以理解为一个数据类型,它包括一个value和0至多个对此value的描述(Descriptor)。
Descriptor(描述):
对Characteristic的描述,例如范围、计量单位等。
Service (服务):
Characteristic的集合。例如一个service叫做“Heart Rate Monitor”,它可能包含多个Characteristics,其中可能包含一个叫做“heart rate measurement"的Characteristic。

2.1.2 什么是UUID

UUID 含义是通用唯一识别码 (Universally Unique Identifier),这是一个软件建构的标准。UUID 是指在一台机器上生成的数字,它保证对在同一时空中的所有机器都是唯一的。通常平台会提供生成的 API。
在"GATT 层”中规范定义的所有属性都有一个 UUID 值,UUID 是全球唯一的 128位的号码,它用来识别不同的特性。

2.1.2.1 蓝牙技术联盟UUID

蓝牙核心规范制定了两种不同的UUID,一种是基本的UUID,一种是代替基本UUID的16位UUID,所有的蓝牙技术联盟定义UUID公用的一个基本的UUID(0x0000xxxx-0000-1000-8000-00805F9B34FB), 为了进一步简化基本 UUID,每一个蓝牙技术联盟定义的属性有一个唯一的 16 位 UUID以代替上面的基本 UUID 的x’部分。例如,心率测量特性使用 0X2A37 作为它的 16 位UUID,因此它完整的 128 位 UUID 为: 0x00002A37-0000-1000-8000-00805F9B34FB。虽然蓝牙技术联盟使用相同的基本 UUID,但是 16 位的 UUID 足够唯一地识别蓝牙技术联盟所定义的各种属性。蓝牙技术联盟所用的基本 UUID 不能用于任何定制的属性、服务和特性。对于定制的属性,必须使用另外完整的 128 位 UUID。

2.1.2.2 厂商特定的UUID

根据蓝牙技术联盟定义 UUID 类似的方式定义 UUID: 先增加一个特定的基本 UUID,再定义一个 16 位的 UUID (类似于一个别名),再加载在基本 UUID 之上。这种采用为所有的定制属性定义一个共用的基本 UUID 的方式使得应用变为更加简单,至少在同一服务中更是如此。
蓝牙核心规范没有任何规则或是建议如何对加入基本 UUID 的 16 位UUID 进行分配因此你可以按照你的意图来任意分配。
注:可使用nRFgo Studio 软件生成一个128位基础UUID

2.1.3 GATT的规范层次

一个 GATT 服务器通过一个称为属性表的表格组织数据,这些数据就是用于真正发送的数据。

2.1.3.1 属性

一个属性包含句柄、UUID、值,句柄是属性在 GATT 表中的索引,在一个设备中每一个属性的句柄都是唯一的。UUID 包含属性表中数据类型的信息,它是理解属性表中的值的每一个字节的意义的关键信息。在一个 GATT 表中可能有许多属性,这些属性能可能有相同的 UUID。

2.1.3.2 特性

一个特性至少包含 2 个属性:一个属性用于声明,一个属性用于存放特性的值。
所有通过 GATT 服务传输的数据必须映射成一系列的特性,可以把特性中的这些数据看成是一个个捆绑起来的数据,每个特性就是一个自我包容而独立的数据点。例如,如果几块数据总是一起变化,那么我们可以把它们集中在一个特性里。

2.1.3.3 描述符

任何在特性中的属性不是定义为属性值就是为描述符。描述符是一个额外的属性以提供更多特性的信息,它提供一个人类可识别的特性描述的实例。
然而,有一个特别的描述符值得特别地提起: 客户端特性配置描述符(ClientCharacteristic Configuration Descriptor,CCCD),这个描述符是给任何支持通知或指示功能的特性额外增加的。在 CCCD 中写入“1”使能通知功能,写入“2”使能指示功能,写入“0”同时禁止通知和指示功能。
在 S132 SoftDevice 协议栈中,对任何使能了通知功能或是指示功能的特性,协议栈将自动加入这个类型的描述符。

2.1.3.4 服务

一个服务包含一个或多个特性,这些特性是逻辑上相关的集合体。
GATT 服务一般包含几块具有相关的功能,比如特定传感器的读取和设置,人机接口的输入输出。组织具有相关的特性到服务中既实用又有效,因为它使得逻辑上和用户数据上的边界变得更加清晰,同时它也有助于不同应用程序间代码的重用。GATT 基于蓝牙技术联盟SIG)官方而设计,SIG 建议根据它们的规范设计自己的 profile。

2.1.3.5 profile(数据配置文件)

一个 profile 文件可以包含一个或者多个服务,一个 profile 文件包含需要的服务的信息或者为对等设备如何交互的配置文件的选项信息。设备的 GAP 和 GATT 的角色都可能在数据的交换过程中改变,因此,这个文件应该包含广播的种类、所使用的连接间隔、所需的安全等级等信息。
需要注意的是一个 profile 中的属性表不能包含另一个属性表。

2.1.4 GATT 属性表解读

对照ESP32《gatt_server_service_table》例程

2.1.4.1 属性表的创建

本例程创建了一个属性表,包含8个属性分别为IDX_SVC(服务或者服务声明),IDX_CHAR_A(特性A声明),IDX_CHAR_VAL_A(特性A值),IDX_CHAR_CFG_A(客户端特性配置描述符),IDX_CHAR_B(特性B声明),IDX_CHAR_VAL_B(特性B值),DX_CHAR_C(特性C声明),IDX_CHAR_VAL_C(特性C值)。

2.1.4.2 属性解读

本例程创建的属性类型为esp_gatts_attr_db_t 包含esp_attr_control_t和esp_attr_desc_t两类型,其中esp_attr_desc_t又包含uuid_length, uuid_p, permission, Max_length, length, length, value_p,在创建属性表时,我们需要对各属性进行赋初值。

android蓝牙ble广播 蓝牙音频广播_网络_06


android蓝牙ble广播 蓝牙音频广播_网络_07


android蓝牙ble广播 蓝牙音频广播_属性表_08

2.4.1.3 根据上述2.1.4.2 对各属性参数解读

  1. 服务或服务声明属性
    其uuid_lengh为2,uuid_p为primaryServiceUUID,这是蓝牙联盟SIG中定义的,permissions为 read,只允许去读到这个server的UUID,但是不能去改写这个UUID。max_length和length用户自定义,value则为用户定义的service UUID。
  2. Characteristic或称Characteristic Declaration属性
    其uuid_lengh为2,uuid_p为character declaration uuid,这是蓝牙联盟SIG中定义的,permissions为 read,只允许去读到这个Characteristic,但是不能去改写这个UUID。max_length和length为用户自定义,value为对应Characteristic Value的读写权限。
  3. Characteristic Value
    其uuid_lengh为用户自定义Characteristic uuid的长度,可用16位或128位的长度,uuid_p为用户自定义的的Characteristic uuid值,特征值跟在特征声明后面,permissions为 Characteristic Value的权限属性, max_length为value值的最大长度,length为初始值的长度,value为对应的初始值。
  4. Client Characteristic Configuration Descripto(客户端特性配置描述符)
    其uuid_lengh为2,uuid_p为character_client_config_uuid,这是蓝牙联盟SIG中定义的,permissions为 read & write.
  5. Characteristic Description
    其uuid_lengh为2,uuid_p为character_description_uuid,这是蓝牙联盟SIG中定义的,permissions为 read & write, max_length为value值的最大长度,length为初始值的长度,value为对应的初始值。