BLE蓝牙协议包之Service Changed & Attribute Cache

979 阅读8分钟

Attribute caching 和 Service Changed

属性缓存

属性缓存是一种优化,它允许客户端一次发现服务器使用的属性信息(例如属性句柄),并在重新连接时使用相同的属性信息而无需重新发现。如果客户端未缓存属性信息,则它必须在每次重新连接时重新发现属性信息。通过缓存,可以节省时间,并且无需在客户端和服务器之间交换大量数据包。客户端应缓存的属性信息是所有服务器属性的属性句柄和GATT服务特征值。 服务器使用的属性句柄不应随时间变化。这意味着,一旦客户端发现属性句柄,就不应更改该属性的属性句柄。

在某些情况下,可能由于服务器恢复出厂设置或执行固件升级过程,导致服务器更改了用于服务的属性句柄。仅当可以在服务器上添加,修改或删除服务时,才需要在服务器上执行以下操作。如果在设备的使用寿命期间不能更改服务器上基于GATT的服务,则服务器上不应该存在服务更改特征,并且在对该服务器进行初始服务发现之后,客户端无需执行服务发现。

蓝牙核心规格5.1版本定义了一种属性缓存(attribute caching) 策略,旨在让客户端在没有任何更改时能够跳过服务发现。

此前核心规则规定了未建立信任关系(即未关联)的客户端和服务器每次连接时都需要执行服务发现。使用ATT服务更改(Service Changed)指示来单次尝试向客户端通知属性表已更改。

Q: trusted relationship 指的什么呢?

A: 远程设备被标记为信任设备的过程。包括保存密钥过程(用来之后的授权),以及密钥不可用时候的配对过程.

从5.1版本开始有两个新特性:数据库哈希(Database Hash)和客户端支持特性(Client Supported Features)。如果客户端支持新的数据库哈希特性,那么与服务器未建立信任关系的客户端如今 也可在连接过程中缓存属性表。

Q: 怎么样知道设备是5.1+ 还是以下版本的呢?

A:

Read Remote Version Information

  • Status(1 Octet):0x00表示success;0x01-0xFF表示失败
  • Connection_Handle(2 Octet):HCI_Read_Remote_Version_Information command中使用的Connection_Handle,这个Connection_Handle表示一个ACL连接
  • Version(1 Octet):表示BR/EDR或者LE Controller的版本信息
  • Manufacturer_Name(2 Octet):表示remote controller的制造商
  • Subversion(2 Octet):远端设备的LMP次版本号

LMP Version LinkManager Spec

  • LMP 0: Bluetooth 1.0b
  • LMP 1: Bluetooth 1.1
  • LMP 2: Bluetooth 1.2
  • LMP 3: Bluetooth 2.0
  • LMP 4: Bluetooth 2.1
  • LMP 5: Bluetooth 3.0
  • LMP 6: Bluetooth 4.0
  • LMP 7: Bluetooth 4.1
  • LMP 8: Bluetooth 4.2
  • LMP 9: Bluetooth 5.0

Mac mini关于本机-> 系统报告-> 蓝牙核心规范:5.0 (0x9)


【拓展】怎么样知道当前手机的macaddress呢?


BLE 4.x ~ 5.0 的Attribute caching的情况如下:

未配对情况下:

第一次去连接设备时.

设备断开连接,再次连接时: 并没有再次去读取ATT属性列表. (按照Core文档描述,此处有争议,实际情况按照上述步骤情况有所不同.)

按照目前的情况,和第一次连接上发现服务确实有区别。只有一处未发现成功ATT Request发起了,但是之前已经发现完毕的服务和特征,并没有再次出现ATT Request.

第二个测试设备第一次去连接:

第二个测试设备断开蓝牙连接,再次连接时: 发现又重新读取了一遍ATT属性列表.

注意看: 第二个测试设备 比 第一个测试设备 多了一个Service Changed特征.

小结: 如果服务器支持Service Changed特征,则没有信任关系的客户端必须在每个连接上执行服务发现。


配对情况下: 没有去重新读取ATT属性列表 (已连接). 未连接的已配对设备,还是需要继续读取ATT属性列表.

【拓展】配对情况下,会生成LTK 密钥的加密通信.

image.png

【拓展】设备是否支持加密相关功能特性怎么看?


Q: 【拓展】我们怎么去识别其他厂商特定的设备呢?

A: 查看 16-bit UUID Numbers Document 官方文档

eg. 0xFED4 Apple, Inc. 0xFED3 Apple, Inc. 0xFED2 Apple, Inc. 0xFED1 Apple, Inc. 0xFED0 Apple, Inc. 0xFECF Apple, Inc.


Service changed

如果基于GATT的服务列表和服务定义在设备的使用寿命内无法更改,则该特征将不存在,否则该特征将存在。如果服务器上存在“服务已更改”特征,则服务器上的“特征值指示”支持是强制性的。

服务器应发送ATT_HANDLE_VALUE_IND PDU,其中包含受影响的属性句柄的范围,这些属性句柄在客户端的属性缓存中应视为无效。 起始属性句柄应为包含更改的服务定义的起始属性句柄,终止属性句柄应为包含更改的服务定义的最后属性句柄。 指示中的值由两个16位属性句柄组成,两个属性值句柄级联以指示受影响的属性句柄范围。

**注意:**服务器可以将受影响的属性句柄范围设置为0x0001到0xFFFF,以指示客户端重新发现服务器上的整个属性句柄集。


Q: NotificationIndication 的区别.

A: 如果在连接参数相同的情况下(主要指connection interval),并且APP处理得当,那肯定是Notification快,因为indication要等回复才能发下一个包。


5.1+ 新特性

  1. Generic Attribute 添加两个新特征 ( Database Hash and Client Supported Features )
  2. 添加新的GATT错误代码 GATT error code ( database out-of-sync )

Q: 怎么样才能知道当前手机是否是5.1 + 呢? A:

Read Local Version Information - HCI Version: 0x09 (Core Spec v 5.0)

HCI Version: 0x09 (Core Spec v 5.0) HCI Revision: 0x03EA LMP Version: 0x09 Manufacturer Name: 0x000F (Broadcom) LMP Subversion: 0x420E

如果服务器支持Service Changed特征,则不具有受信任关系的支持缓存的客户端必须执行服务发现或通过读取每个连接上的 Database Hash 特征来检测服务更改。


Robust Caching 鲁棒性缓存

如果服务器上同时存在 Database Hash 和 Service Changed 特征,则服务器应支持 Robust Caching 功能。

客户端会处于变更感知(change-aware)状态或变更无感知(change-unaware)状态。该规格列出了 转换到适当状态的精确规则,以及每种状态下的行为方式。 特别值得注意的是,如果服务器认为客户端属性表缓存与服务器不同步,则可能会返回这一新的“数据库 不同步(Database Out Of Sync)”ATT错误响应(ATT_ERROR_RSP)。当服务器处于变更无感知状态时,服务器将忽略从客 户端接收到的所有ATT指令。许多事件可将客户端状态转换为变更感知,包括服务器接收ATT确认到先前 已发送的服务更改指示,或服务器已通过“数据库不同步(Database Out Of Sync)”错误向客户端发出 通知,而后又从客户端接收一些其他ATT PDU。从客户端的角度来看,如果它转换到变更无感知,将不会 使用其属性缓存,并将其视为无效。在客户端的属性缓存和服务器再次同步之前,它将继续被视为无效。

每当服务器更新数据库定义时,所有连接的客户端都不会感知更改。 当未更改感知的已连接客户端读取数据库哈希特征,然后服务器从该客户端接收到另一个ATT请求时,该客户端便会感知更改。

发生以下任何一种情况时,未感知更改的已连接客户端将变为可感知更改: 客户收到并确认“服务已更改”特征的“处理值指示”。 服务器向客户端发送错误代码为“数据库不同步”的响应,然后服务器从客户端收到另一个ATT请求。


change-aware state


Database Out Of Sync


Database Hash

数据库哈希特性存储一个128位的值,该值是根据数据库结构计算得出的AES-CMAC哈希。数据库结构的任何更改都将导致不同的哈希值。一次发现数据库后,客户端应存储该值。下次,当客户端连接到服务器时,它仅应 检查数据库哈希 是否已更改。如果没有,可以安全地假定数据库结构不变,并且高速缓存的属性句柄仍然有效。如果已更改,则客户端需要重新发现GATT数据库。

拓展: 客户端如今能够推断出它所连接的设备与先前连接的设备为同类型,且其属性表已在客户端缓存。如果来自相连设备的数据库哈希和与客户端属性缓存关联的数据库哈希相同,且其他详细信息(例如设备 制造商)也相同,则客户端可断定不需要为相连的设备执行服务发现,因为从另一台设备获得的属性缓存 已经包含了等效数据。