BLE: Read Long Characteristics Value using Android

2019-05-23 14:44发布

问题:

With a normal Characteristics Read only the MTU Size (20bytes) of data will be read. My customer will offer a characteristics with a larger size (about 100bytes).

I saw that BLE offers a "Long Read" feature which reads until the size of the characteristics is reached. (https://bluegiga.zendesk.com/entries/25053373--REFERENCE-BLE-master-slave-GATT-client-server-and-data-RX-TX-basics)

attclient_read_long command - Starts a procedure where the client first sends normal read request to the server, and if the server returns an attribute value with a length equal to the BLE MTU (22 bytes), then the client continues to send "read long" requests until rest of the attribute is read. This only applies if you are reading attributes that are longer than 22 bytes. It is often simpler to construct your GATT server such that there are no long attributes, for simplicity. Note that the BLE protocol still requires that data is packetized into max. 22-byte chunks, so using "read long" does not save transmission time.

But how can I use this feature in Android? The BluetoothGatt class only offers a simple "Read()" - same for iOS.

Increasing the MTU is not possible since we need to support devices with AP Level < 21 (increaseMTU was introduced at API 21)

回答1:

I can confirm for iOS that a read operation as per standard will occur first. Then if the server returns a completely filled PDU, the iOS device will then continue to perform the blob read operation. Tested with iPhone 7 running iOS 11.2.x

You do NOT need to call the peripheral.readValue(characteristic) multiple times for long attributes. CoreBluetooth does all of this under the covers.

Refer to the Bluetooth Spec Core v5.0, specifically Vol 3, Part F. "Long Attribute Values".

Experiment to prove above.

I have an Android Thing acting as the server that I'm making return the maximum length with my iPhone during a read operation. iOS and my RPI3 exchange a MTU of 185. So the read response is (MTU - 1) 184 bytes long. The server (RPI) then receives a new read request with an offset of 184, which you can then return more data. This is continued until the offset is > 512, or the last read response returns less than the MTU - 1 length.

Based upon the fact that the BluetoothGattServer supports long attributes, I'd assume the BluetoothGatt object does as well. Since there is no way via the API to set the offset to be read, I'd assume you can invoke read just once.