Android API 无法获取蓝牙 BLE Attribute Handle 值

更新日期: 2022-12-07 阅读次数: 630 字数: 488 分类: Android

最近写了一个 Android APP 用于快速配置蓝牙网关(已上架 Google Play),但是基本功能完成后, 发现无法获取指定特性 (characteristic) / 描述符 (descriptor) 的 handle 值。

handle 存在的意义

Handle 的全称是 Attribute Handle。

在用 Android API 实现这个 BLE 扫描 APP 的过程中,我发现无论是服务,还是特性、描述符其 UUID 都是可能重复的。 举个例子,如果一个蓝牙设备包含两个电池模块,则存在两个相同服务的 UUID 是合理的。

那么用 UUID 来标识一个服务/特性/描述符就不合理了。

所以,Attribute Handle 就是这个唯一标识。

/**
 * @brief ESP_GATTS_WRITE_EVT
 */
struct gatts_write_evt_param {
	uint16_t conn_id;		/*!< Connection id */
	uint32_t trans_id;		/*!< Transfer id */
	esp_bd_addr_t bda;	/*!< The bluetooth device address which been written */
	uint16_t handle;		/*!< The attribute handle */
	uint16_t offset;		/*!< Offset of the value, if the value is too long */
	bool need_rsp;		/*!< The write operation need to do response */
	bool is_prep;			/*!< This write operation is prepare write */
	uint16_t len;			/*!< The write attribute value length */
	uint8_t *value;			/*!< The write attribute value */
} write;			/*!< Gatt server callback param of ESP_GATTS_WRITE_EVT */

为何 Android API 不提供 Handle 获取接口

Android Stack 将 Handle 做了一层封装,对应用层不可见,也就无法获取到 Handle。

但是,你去看 Android 文档:

  • GATT Service getInstanceId: https://developer.android.com/reference/android/bluetooth/BluetoothGattService#getInstanceId()
  • GATT Characteristic getInstanceId: https://developer.android.com/reference/android/bluetooth/BluetoothGattCharacteristic#getInstanceId()

If a remote device offers multiple services with the same UUID (ex. multiple battery services for different batteries), the instance ID is used to distuinguish services.

Android 的实现是用 instance id 加 UUID 作为服务/特性的唯一标识。而没有直接采用 Handle。 这也是为何无法通过 Android API 获取到 handle 值的原因。

https://e2e.ti.com/support/wireless-connectivity/bluetooth-group/bluetooth/f/bluetooth-forum/299434/addressing-characteristics-by-handle-with-android

The Android BLE developers chose to use UUID as the characteristic identifier in GATT API's; handles are not directly exposed to applications. Internally, Android maps UUID's to handles and uses handles to access characteristics, but apps have no need to know the handle.

Windows API

Windows 则提供了 AttributeHandle 接口获取 Handle 值。

https://learn.microsoft.com/en-us/uwp/api/windows.devices.bluetooth.genericattributeprofile.gattcharacteristic.attributehandle?view=winrt-22621#windows-devices-bluetooth-genericattributeprofile-gattcharacteristic-attributehandle

public ushort AttributeHandle { get; }

感觉得用 Windows WinForm / WPF 重写一遍这个工具了。

参考

  • https://www.esp32.com/viewtopic.php?t=830
  • https://e2e.ti.com/support/wireless-connectivity/bluetooth-group/bluetooth/f/bluetooth-forum/299434/addressing-characteristics-by-handle-with-android
  • https://github.com/hbldh/bleak/issues/888

tags: 蓝牙

爱评论不评论