如何从蓝牙 LE 设备获取数据
Posted
技术标签:
【中文标题】如何从蓝牙 LE 设备获取数据【英文标题】:How do you get data from a Bluetooth LE device 【发布时间】:2017-08-14 14:38:09 【问题描述】:我有一个支持蓝牙 LE 的蓝牙条码扫描器,我正在尝试在扫描时从中获取条码信息。
我可以很好地连接到它 onServicesDiscovered
在我的 BluetoothGattCallback
中被调用,但我不知道从那里做什么。
使用经典蓝牙连接,您会从BluetoothSocket
获得InputStream
,您只需等待read()
为您提供数据,但我不确定它如何与蓝牙 LE 一起使用。我尝试循环检查BluetoothGattCharacteristic
的属性,如果它是读取属性,我调用gatt.readCharacteristic(characteristic);
但这只会给我无用的信息,甚至在我尝试扫描某些东西之前。
那么如何从扫描仪中获取条码数据呢?
这是我的扫描仪https://www.zebra.com/us/en/support-downloads/scanners/ultra-rugged-scanners/li3608-li3678.html
【问题讨论】:
你试过Scanner SDK for android吗?我知道您的问题标题要求读取通用 BLE 数据,但您似乎特别对条形码扫描仪感兴趣,因此这个 SDK 似乎是一个很好的起点,而不是读取原始数据。 是的,我知道 SDK 可以工作,但我需要支持的不仅仅是这个扫描仪,这就是我想推出自己的蓝牙逻辑的原因 那么你到底对哪一部分有问题呢?如何从特征中获取有意义的值? 是的,无论从 LE 设备如何获取值 【参考方案1】: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 或供应商以获取更多信息。
【讨论】:
好的,所以我需要知道我正在寻找的具体特征,然后mGatt.setCharacteristicNotification(characteristic,true);
告诉设备我想知道什么时候它会发生变化。然后我在 onCharacteristicChanged` 中得到一个回调,这就是你上面的代码出现的地方?描述符在这个过程中有什么部分?
告诉堆栈您希望通过特性更改获得通知是一回事,但您还必须告诉服务器(远程设备)您希望它向您发送通知/指示和这就是描述符出现的地方。请查看Receiving GATT Notifications 了解更多信息。示例 CLIENT_CHARACTERISTIC_CONFIG
描述符的 UUID (0x2902
)(以及其他)可以在 BT website 找到。以上是关于如何从蓝牙 LE 设备获取数据的主要内容,如果未能解决你的问题,请参考以下文章
通过 disassemble manucaftures 库从蓝牙 le scale 获取重量数据