一,Bluetooth Low Energy协议基本组成
蓝牙系统核心架构可分为三个方面:
BLE Application和BLE Host 属于应用层API
HCI(Host Controller Interface)为中间层
BLE Controller为底层蓝牙芯片
其中在HOST层有的两个比较核心的协议:ATT、GATT
1,ATT(Attribute Protocol)
该协议将数据以属性(Attribute)的方式抽象出来,用UUID定义不同的属性,并提供一下方法以供远端设备读取、修改这些属性的值。
每个属性又由三个元素组成:
- 一个16bits的Handle
- 一个16bits/32bits/64bits的UUID
- 确定长度的属性值
需要注意的是,Handle是用于识别唯一属性的数字,而非UUID,因为一个BLE设备中可能有多个属性拥有同一个UUID,UUID由更上层的GATT定义。
UUID用于确定属性中存放的值所对应的服务,其中主要包括一下几种:
- Service UUID
- Characteristic UUID
- Profile UUID
- Vendor-Specified UUID
和属性相关的读写权限保存于属性值中,但它也由更上层的GATT定义,ATT本身并不关心。
ATT本身有两个角色,即C/S架构,其中Server存储属性,Client什么也不存,Client主动发起请求读写Server端数据,Server端被动相应。但当Server端的属性发生变化时,也可以主动通知Client。
2,GATT(Generic Attribute Profile)
GATT将ATT中的不同属性组合在一起,形成有意义的服务。
纵向来看,GATT Profile包含一个或多个GATT Services,每个GATT Service又包含一个或多个GATT Characteristics。
(1)GATT Profile
Profile实际上并不存在于BLE外设上,而是由Bluetooth SIG或者外设设计者预先定义的Service的集合。比如说Heart Rate Profile就定义了Heart Rate Service和Device Information Service。
(2)GATT Service
GATT Service的基础是UUID值为0x2800的属性,所有紧接着跟在其后边的UUID定义的属性都同属于一个服务,直到另一个0x2800出现。
比如说,一个设备中有三个服务,其布局如下:
UUID为0x2800的属性定义了Primary服务,0x2801定义了Secondary服务,0x2802定义了Include,0x2803定义了属性(Characteristic)。每个属性不需要知道自己属于哪个服务,GATT根据0x2800作为标记区分不同的属性属于哪个服务。可以通过服务来确定Handle值的范围,比如说Service B的Handle就确定在0x0150~0x02ff之间。这样一来Client就可以找到所有服务而不需要知道服务的具体意义。
(3)GATT Service Characteristics
每个服务有几个特征,每个特征其中存储了有用的值以及相关权限。特征中至少有两种属性:
- Characteristic Declaration Attribute:定义了此特征的数据位置
- Characteristic Data Attribute:存放了特征本身的数据
比如说一个温度计,它的特征可以包括只读的温度值和可读写的时间戳:
其中主特征的UUID为0x2803,在它的Value值中又定义了不同特征的UUID。如图所示,通过UUID为0x2803的主特征的Value值中的UUID,可以找到UUID为0x2A2B的temperature的特征值,也可以找到UUID为0x2A08的date/time的特征值。
特征值的真正格式是由UUID决定的,因此如果客户端知道如何解释UUID为0x0A28的特征值,就能从包含这个特征的任何服务中读取它的日期和时间值。
- Characteristic Descriptors(可选)
这些属性用来扩展在Characteristic Declaration Attribute中的数据。一般的Descriptor属性包括如下几种:
-
Extended Properties
- Contains additional declaration property bits
-
Characteristic User Description
- Contains a user-readable description for the characteristic in which it is placed (i.e. "Temperature in the Living Room").
-
Client Characteristic Configuration Descriptor (CCCD)
- A switch, enabling/disabling server-initiated updates.
其它协议
3,GAP(Generic Access Profile)
它负责控制蓝牙设备的广播和连接行为,可通过Advertising Data Payload或者Scan Response Payload来进行广播,它们长度都为31bytes。不同之处在于前者为Peripheral设备自己定时发出,后者为接受到Central设备的请求后的响应内容。
4,SM(Security Manager)
通过使用一种密钥分发的方式来实现蓝牙设备之间通讯的加密与解密。当连接建立之后,双方通过某种方式协商出共同使用的密钥,后续传播的数据就要通过这个密钥使用加密算法来加密。
5,L2CAP(Logic Link Control and Adaptation Protocol)
L2CAP中文名为逻辑链路控制和适配协议,它将上层协议(ATT/SM)与下层的协议连接起来,因为ATT与SM层的协议实现和数据格式完全不同,所以说L2CAP的功能是实现了协议复用。L2CAP中定义了一种抽象概念,名为信道,表示两个设备的某个协议层之间的通道。每个信道分配一个2字节的CID(Channel ID),对于BLE协议而言共有三种信道ID:
- 0x0004 – 属性协议
- 0x0005 – 低功耗信令信道
- 0x0006 – 安全管理协议
其中ATT都是通过CID为0x0004的Attribute Protocol来传递数据的。我们关心的上层协议的内容也主要体现于此。
6,Link Layer
直接与Physical Layer进行交互,其中内容包括Channel,Packets,设备之间Discovery和Connection。
(1)Channel分为Advertising Channel和Data Channel两种,BLE一共使用40个Channel。
(2)在Link Layer种设备有不同的状态,以及不同的角色。在Link Layer所称的Master对应于GAP的Central、GATT的Client,而Slave对应于GAP的Peripheral、GATT的Server。下图是Unicast Connection中的设备连接过程:
(3)Packet Types
BLE包种的Protocal Data Unit(PDU)共分为两种:
Advertising Channel PDU:
它的Header共定义了7种不同类型的PDU,每种数据包都有不同的格式和功能:
-
Advertising PDUs
- ADV_IND, ADV_DIRECT_IND, ADV_NONCONN_IND, ADV_SCAN_IND
-
Scanning PDUs
- SCAN_REQ, SCAN_RSP
-
Initiating PDUs
- CONNECT_REQ
Data Channel PDU:
二,wireshark抓取数据包分析
使用View Tool Hollong BLE Sniffer嗅探手机和蓝牙显示屏之间的通信,并在wireshark上查看数据包具体内容。
我们连接的设备在最下边一行,名字为PRSN-306083,MAC为AC:9A:22:30:60:83。
抓到的数据包主要有一下几种:
1,ADV_IND 广播
属于Link Layer层,长度为37 bytes。
- Access Adress:0-3 bytes,用于确定通信频道
- Packet Header:4-5 bytes,定义了PDU Type为ADV_IND
- Advertising Adress:6-11 bytes,是发送广播的设备的MAC地址
- Advertising Data:12-33 bytes
- Flags:12-14 bytes
-
- Device Name:15-27 bytes
- Manufacturer Specific:28-33 bytes
- CRC:34-36 bytes
2,SCAN_REQ 扫描
长度为21 bytes,由Master发出,也属于Link Layer层
包括Access Address,Packet Header,Scanning Address,Advertising Address。
3,SCAN_RSP 扫描回复
长度为33bytes,Slave接收到SCAN_REQ之后广播回复消息
除了Access Address,Packet Header,Advertising Address之外,还包含了一个UUID
4,CONNECT_REQ 连接请求
前四个部分为Access Address,Packet Header,Initator Address,Adevrtising Address
在接下来的Link Layer Data中重新定义了Access Address,以及一些其它连接相关参数
5,Connection Parameter Update Request/Response 跟新连接参数
属于L2CAP层协议,
可以看到此时Access Adress已经变为373a2a690610,这里L2CAP使用了CID为0x0005的通道,为低功耗信令通道。
6,GATT Primary Service Declaration 声明服务
在L2CAP层,CID为0x0004,代表ATT属性协议。
在GATT数据包中包括了Opcode,Starting Handle,Ending Handle,还使用UUID 0x2800定义了Primary服务(Service)。
在回复的数据包中,定义了3个属性组(Attribute List),这些属性都是手机自定义的,每个属性里边包含有自己的Handle的起始和结束位置以及UUID。
我们可以收集到我们的蓝牙设备返回的一系列Service,通过Linux系统下的工具Gatttool也可以获得,我们的设备一共有5个Services。其中前四个为Bluetooth SIG预先设定的,最后一个提供的是自定义的Service。
7,GATT Include Declaration
一般在跟在Primary Service Declaraion之后,询问一定handle范围(在一个Service)内的Characteristic,但是我抓到的包每次Server都回复的是error。
在网上查到:
GATT profile attributes defined by SIG, they are Primary Service(0x2800), Secondary Service(0x2801), Include(0x2802), and Characteristic(0x2803).
8,GATT Characteristic Declaration 声明特征
用来声明特征值的读写权限,存放value的handle,对应的UUID。
由前边的Service可以判断出,handle范围在0x002a~0x0036之间的为设备自定义的一些特征,可以提供某些自定义功能。比如说后边抓包发现Write Command是通过改变handle为0x002c中存放的value实现的。通过向0x002c/0x002f的handle发送命令,可以实现控制蓝牙显示屏的内容以及动作。
9,Find Information 查找信息
查找某些handle的UUID
handle | UUID |
0x000f | Client Characteristic Configuration (0x2902) |
0x0026 | Client Characteristic Configuration (0x2902) |
0x0027 | Characteristic User Description (0x2901) |
0X002d | Characteristic User Description (0x2901) |
0x0030 | Characteristic User Description (0x2901) |
0x0033 | Characteristic User Description (0x2901) |
0x0036 | Client Characteristic Configuration (0x2902) |
10,Write Request
像handle为0x0036请求。
11,Write Command
像Handle 0x002c写入value。
最终我们可以画出整个属性表的结构:
Handle | UUID | Type Of Attribute | Attribute Permission | Attribute Value |
0x0001 | 00002800-0000-1000-8000-00805f9b34fb | Service Declaration | Read Only | UUID: 0x1800 Generic Access Profile |
0x0002 | 00002803-0000-1000-8000-00805f9b34fb | Charactristic Declaration | 0x0a | Value Handle(0x0003) UUID(0x2a00) |
0x0003 | 00002a00-0000-1000-8000-00805f9b34fb | Device Name | 由上定义 | |
0x0004 | 00002803-0000-1000-8000-00805f9b34fb | Charactristic Declaration | 0x02 | Value Handle(0x0005) UUID(0x2a01) |
0x0005 | 00002a01-0000-1000-8000-00805f9b34fb | Appearance | 由上定义 | |
0x0006 | 00002803-0000-1000-8000-00805f9b34fb | Charactristic Declaration | 0x0a | Value Handle(0x0007) UUID(0x2a02) |
0x0007 | 00002a02-0000-1000-8000-00805f9b34fb | Peripheral Privacy Flag | 由上定义 | |
0x0008 | 00002803-0000-1000-8000-00805f9b34fb | Charactristic Declaration | 0x02 | Value Handle(0x0009) UUID(0x2a04) |
0x0009 | 00002a04-0000-1000-8000-00805f9b34fb | Peripheral Preffered Connection Parameters | 由上定义 | |
0x000a | 00002803-0000-1000-8000-00805f9b34fb | Charactristic Declaration | 0x0e | Value Handle(0x000b) UUID(0x2a03) |
0x000b | 00002a03-0000-1000-8000-00805f9b34fb | Reconnection Address | 由上定义 | |
0x000c | 00002800-0000-1000-8000-00805f9b34fb | Service Declaration | Read Only | UUID: 0x1801 Generic Attribute Profile |
0x000d | 00002803-0000-1000-8000-00805f9b34fb | Charactristic Declaration | ||
0x000e | 00002a05-0000-1000-8000-00805f9b34fb | |||
0x000f | 00002902-0000-1000-8000-00805f9b34fb | |||
0x0010 | 00002800-0000-1000-8000-00805f9b34fb | Service Declaration | Read Only | UUID: 0x180a Device Information |
0x0011 | 00002803-0000-1000-8000-00805f9b34fb | Charactristic Declaration | ||
0x0012 | 00002a29-0000-1000-8000-00805f9b34fb | |||
0x0013 | 00002803-0000-1000-8000-00805f9b34fb | Charactristic Declaration | ||
0x0014 | 00002a24-0000-1000-8000-00805f9b34fb | |||
0x0015 | 00002803-0000-1000-8000-00805f9b34fb | Charactristic Declaration | ||
0x0016 | 00002a25-0000-1000-8000-00805f9b34fb | |||
0x0017 | 00002803-0000-1000-8000-00805f9b34fb | Charactristic Declaration | ||
0x0018 | 00002a27-0000-1000-8000-00805f9b34fb | |||
0x0019 | 00002803-0000-1000-8000-00805f9b34fb | Charactristic Declaration | ||
0x001a | 00002a26-0000-1000-8000-00805f9b34fb | |||
0x001b | 00002803-0000-1000-8000-00805f9b34fb | Charactristic Declaration | ||
0x001c | 00002a28-0000-1000-8000-00805f9b34fb | |||
0x001d | 00002803-0000-1000-8000-00805f9b34fb | Charactristic Declaration | ||
0x001e | 00002a23-0000-1000-8000-00805f9b34fb | |||
0x001f | 00002803-0000-1000-8000-00805f9b34fb | Charactristic Declaration | ||
0x0020 | 00002a2a-0000-1000-8000-00805f9b34fb | |||
0x0021 | 00002803-0000-1000-8000-00805f9b34fb | Charactristic Declaration | ||
0x0022 | 00002a50-0000-1000-8000-00805f9b34fb | |||
0x0023 | 00002800-0000-1000-8000-00805f9b34fb | Service Declaration | Read Only | UUID: 0xfee8 Quintic Corp. |
0x0024 | 00002803-0000-1000-8000-00805f9b34fb | Charactristic Declaration | ||
0x0025 | 003784cf-f7e3-55b4-6c4c-9fd140100a16 | |||
0x0026 | 00002902-0000-1000-8000-00805f9b34fb | |||
0x0027 | 00002901-0000-1000-8000-00805f9b34fb | |||
0x0028 | 00002803-0000-1000-8000-00805f9b34fb | Charactristic Declaration | ||
0x0029 | 013784cf-f7e3-55b4-6c4c-9fd140100a16 | |||
0x002a | 00002800-0000-1000-8000-00805f9b34fb | Service Declaration | Read Only | UUID: 0xfee9 (自定义) |
0x002b | 00002803-0000-1000-8000-00805f9b34fb | Charactristic Declaration | ||
0x002c | d44bc439-abfd-45a2-b575-925416129600 | |||
0x002d | 00002901-0000-1000-8000-00805f9b34fb | |||
0x002e | 00002803-0000-1000-8000-00805f9b34fb | Charactristic Declaration | ||
0x002f | d44bc439-abfd-45a2-b575-92541612960a | |||
0x0030 | 00002901-0000-1000-8000-00805f9b34fb | |||
0x0031 | 00002803-0000-1000-8000-00805f9b34fb | Charactristic Declaration | ||
0x0032 | d44bc439-abfd-45a2-b575-92541612960b | |||
0x0033 | 00002901-0000-1000-8000-00805f9b34fb | |||
0x0034 | 00002803-0000-1000-8000-00805f9b34fb | Charactristic Declaration | ||
0x0035 | d44bc439-abfd-45a2-b575-925416129601 | |||
0x0036 | 00002902-0000-1000-8000-00805f9b34fb |
这是我在processon上将整个通讯抓包过程绘制成的流程图,可以更加清楚地了解BLE协议的细节。
https://www.processon.com/view/link/5bb06eb3e4b0d4d65c1d9d77