在 BLE 中使用读取 Blob 请求时可能的最大偏移量是多少?

What is the Maximum offset possible while working with Read Blob Request in BLE?

我是 BLE 新手,正在尝试了解读取 Blob 请求的偏移量。当ATT_MTU为23字节时,偏移量增加了22..从0,22,44.... 512.if我将MTU更新为517(接近512),那么这个偏移量有多远?只到 512 或 0,512,1024...? 另外,这是否可能:如果它进一步增加,每次迭代可以传输 512 字节的数据,这意味着更多的数据传输。 请有人帮助我。

来自蓝牙核心规范 v5.3,第 3 卷,F 部分 (ATT):

第 3.2.9 节长属性值:

The longest attribute that can be sent in a single packet is (ATT_MTU-1) octets in size. At a minimum, the Attribute Opcode is included in an Attribute PDU. An attribute value may be defined to be larger than (ATT_MTU-1) octets in size. These attributes are called long attributes.

To read the entire value of an attributes larger than (ATT_MTU-1) octets, the ATT_READ_BLOB_REQ PDU is used. It is possible to read the first (ATT_MTU-1) octets of a long attribute value using the ATT_READ_REQ PDU.

...

The maximum length of an attribute value shall be 512 octets.

第 3.4.4.5 节 ATT_READ_BLOB_REQ:

If the value offset of the Read Blob Request is greater than the length of the attribute value, an ATT_ERROR_RSP PDU shall be sent with the Error Code parameter set to Invalid Offset (0x07).

来自第 3 卷 G 部分 (GATT):

第 4.8.3 节读取长特征值

This sub-procedure is used to read a Characteristic Value from a server when the client knows the Characteristic Value Handle and the length of the Characteristic Value is longer than can be sent in a single ATT_READ_RSP PDU.

The ATT_READ_REQ and ATT_READ_BLOB_REQ PDUs are used to perform this sub-procedure. The Attribute Handle shall be set to the Characteristic Value Handle of the Characteristic Value to be read. To read the complete Characteristic Value an ATT_READ_REQ PDU should be used for the first part of the value and ATT_READ_BLOB_REQ PDUs shall used for the rest. The Value Offset parameter of each ATT_READ_BLOB_REQ PDU shall be set to the offset of the next octet within the Characteristic Value that has yet to be read. The ATT_READ_BLOB_REQ PDU is repeated until the ATT_READ_BLOB_RSP PDU’s Part Attribute Value parameter is shorter than (ATT_MTU – 1).

For each ATT_READ_BLOB_REQ PDU a ATT_READ_BLOB_RSP PDU is received with a portion of the Characteristic Value contained in the Part Attribute Value parameter.

所以思路是GATT服务器在characteristic里面放一个值,最多只允许512字节。然后每当GATT客户端要读取这个值(最多512字节)时,如果ATT_MTU最多为513,它可以使用ATT_READ_REQ一次性读取整个值。当 ATT_MTU 较小以至于完整值不适合 ATT_READ_RSP 时,客户端必须发出多个 ATT_READ_BLOB_REQs,并为每个请求增加偏移量。当返回值小于 ATT_READ_BLOB_RSP 中可以容纳的最大大小时,它会终止。请注意,当 MTU >= 513 时通常不使用 ATT_READ_BLOB_REQ,因为始终可以使用正常的 ATT_READ_REQ.

读取所有可能的属性值

由于最大属性值大小为 512,包含偏移量 > 512 的 ATT_READ_BLOB_REQ 应始终导致具有错误“无效偏移量”的响应(假设其他条件通过,例如句柄存在并且该属性首先是可读的等等)。

GATT 不是为传输大于 512 字节的数据而设计的。如果您需要这样做,您有一些选择:

  1. 改用通知。拆分数据并发送多个通知。应用程序程序员必须以某种方式定义一种方法来正确地从多个通知中重建完整的值。为了触发GATT服务器开始发送值,应用程序员可以设计GATT服务器,让客户端首先使用写特性操作写入一些指令,当收到这个操作时,服务器开始发送通知。

  2. 使用多次读取。首先将数据分成多个块。 GATT 服务器首先将前 512 个字节放入特征值中。每当它检测到 GATT 客户端已读取前 512 个字节时,它会将接下来的 512 个字节放入特征值中,以便客户端可以读取下一个块。此选项的吞吐量低于使用通知,因此没有太多理由使用此选项而不是使用通知。

  3. 使用 L2CAP CoC 而不是使用 GATT。与 GATT 相比,L2CAP CoC 专为大数据传输而设计。 Android 从 Android 10 及更高版本开始支持此功能。