BLE 设备提供的数据称为Characteristics。这些数据包是专门形成的、紧密封装的字节数组,它们对特定服务的特定值进行编码。您可以在蓝牙官方网站上查看Services。在这里,您将找到已定义(权威)的 GATT 服务和所属特征。
例如,您有一台 BLE 自行车码表,它会报告速度和踏频。您在列表中查找Cycling Speed and Cadence 项目。此条目包含服务的 UUID (0x1816) 和指向包含特征的数据表的链接。现在,如果您转到 Service Characteristics 表,您会发现几个条目。您需要速度和节奏,因此您将打开 CSC Measurement(条目的 Type 字段),将您带到特性的数据表。在这里,您将看到 Value Fields 表,该表定义了可以从特征中读取的特定值。
这是一般的蓝牙 LE 部分,现在回到 Android。请注意,您必须查找这些字段才能从特征中获取值。我只是假设您已经具有要从中获取数据的特征。这是一个检索车轮和曲柄转数(如果有)的快速示例。
BluetoothGattCharacteristic characteristic = ... ;
int offset = 0; // we define the offset that is to be used when reading the next field
// FORMAT_* values are constants in BluetoothGattCharacteristic
// these represent the values you can find in the "Value Fields" table in the "Format" column
int flags = characteristic.getIntValue(FORMAT_UINT8, offset);
offset += 1; // UINT8 = 8 bits = 1 byte
// we have to check the flags' 0th bit to see if C1 field exists
if ((flags & 1) != 0) {
int cumulativeWheelRevolutions = characteristic.getIntValue(FORMAT_UINT32, offset);
offset += 4; // UINT32 = 32 bits = 4 bytes
int lastWheelEventTime = characteristic.getIntValue(FORMAT_UINT16, offset);
offset += 2; // UINT16 = 16 bits = 2 bytes
}
// we have to check the flags' 1st bit to see if C2 field exists
if ((flags & 2) != 0) {
int cumulativeCrankRevolutions = characteristic.getIntValue(FORMAT_UINT16, offset);
offset += 2;
int lastCrankEventTime = characteristic.getIntValue(FORMAT_UINT16, offset);
offset += 2;
}
flags 字段需要检查特定位,因为设备可能不会报告每种类型的数据,例如它不计算车轮转数。所选特征的工作表始终包含有关此字段的相关信息(如果存在)。
还值得注意的是,文档是这样说的
CSC 测量特性(CSC 是指骑行速度和踏频)是一种包含标志字段的可变长度结构,并且根据标志字段的内容,可能包含一个或多个附加字段 [...]
这就是为什么您不能假设在 7 个字节(8 + 32 + 16 位;分别为 1 + 4 + 2 个字节)偏移量处可以找到累积曲柄转数值,并且偏移量应该在您沿着田野前进时被计算在内。
这是一个从 BLE 设备读取 Cycling Speed 和 Cadence 值的示例。您必须为您希望在应用程序中支持的每个设备(或者更确切地说是服务)查找这些可用字段和值。如果设备是特殊设备且无法在此 GATT 目录中找到,则需要查阅设备手册、SDK 或供应商以获取更多信息。