首页 >> 大全

BLE 广播数据解析

2023-07-30 大全 23 作者:考证青年

从上一篇 GATT 简介中提到过,BLE 设备工作的第一步就是向外广播数据。广播数据中带有设备相关的信息。本文主要说一下 BLE 的广播中的数据的规范以及广播包的解析。

广播模式

BLE 中有两种角色 和 ,也就是中心设备和外围设备。中心设备可以主动连接外围设备,外围设备发送广播或者被中心设备连接。外围通过广播被中心设备发现,广播中带有外围设备自身的相关信息。

广播包有两种:广播包( Data)和响应包(Scan ),其中广播包是每个设备必须广播的,而响应包是可选的。数据包的格式如下图所示(图片来自官方 Spec):

每个包都是 31 字节,数据包中分为有效数据()和无效数据(non-)两部分。

广播数据格式

所有的 AD type 的定义在文档 ​Core 中。 AD Type 包括如下类型:

UUID: 广播数据中一般都会把设备支持的 GATT 广播出来,用来告诉外面本设备所支持的 。有三种类型的 UUID:16 bit, 32bit, 128 bit。广播中,每种类型类型有有两个类别:完整和非完整的。这样就共有 6 种 AD Type。

Local Name: 设备名字,DATA 是名字的字符串。Local Name 可以是设备的全名,也可以是设备名字的缩写,其中缩写必须是全名的前面的若干字符。

TX Power Level: TYPE = 0x0A,表示设备发送广播包的信号强度。DATA 部分是一个字节,表示 -127 到 + 127 dBm。

带外安全管理( Out of Band):TYPE = 0x11。DATA 也是 Flag,每个 bit 表示一个功能:

外设(Slave)连接间隔范围:TYPE = 0x12。数据中定义了 Slave 最大和最小连接间隔,数据包含 4 个字节:

服务搜寻:外围设备可以要请中心设备提供相应的 。其数据定义和前面的 UUID 类似:

Data: 对应的数据。

公开目标地址:TYPE = 0x17,表示希望这个广播包被指定的目标设备处理,此设备绑定了公开地址,DATA 是目标地址列表,每个地址 6 字节。

随机目标地址:TYPE = 0x18,定义和前一个类似,表示希望这个广播包被指定的目标设备处理,此设备绑定了随机地址,DATA 是目标地址列表,每个地址 6 字节。

:TYPE = 0x19,DATA 是表示了设备的外观。

厂商自定义数据: TYPE = 0xFF,厂商自定义的数据中,前两个字节表示厂商 ID,剩下的是厂商自己按照需求添加,里面的数据内容自己定义。

广播数据包__广播数据帧不能穿透什么设备

还有一些其他的数据,我这里就不一一列举了,有需要的可以从这个文档查阅 Core 。

广播数据解析

在 可以使用 来发起扫描。基本用法如下:

BluetoothAdapter.LeScanCallback mLeScanCallback =  new BluetoothAdapter.LeScanCallback() {@Overridepublic void onLeScan(final BluetoothDevice device, int rssi, byte[] scanRecord) {// 解析广播数据
            parseAdvData(scanRecord);}};mBluetoothAdapter = BluetoothAdapter.getDefaultAdapter();  
// 开始扫描设备
mBluetoothAdapter.startLeScan(mLeScanCallback);  
...
// 停止扫描设备
mBluetoothAdapter.stopLeScan(mLeScanCallback);  

当扫描到设备以后,就会回调 (...),这里的参数 就是广播数据,这里同时包含广播数据和扫描相应数据(如果有的话),所以长度一般就是 62 字节。

根据上一节的广播数据格式的说明,可以实现解析广播数据函数 ();,下面的代码实现了解析几个我关心的数据:

public static ParsedAd parseData(byte[] adv_data) {  ParsedAd parsedAd = new ParsedAd();ByteBuffer buffer = ByteBuffer.wrap(adv_data).order(ByteOrder.LITTLE_ENDIAN);while (buffer.remaining() > 2) {byte length = buffer.get();if (length == 0)break;byte type = buffer.get();length -= 1;switch (type) {case 0x01: // Flags
                parsedAd.flags = buffer.get();length--;break;case 0x02: // Partial list of 16-bit UUIDs
            case 0x03: // Complete list of 16-bit UUIDs
            case 0x14: // List of 16-bit Service Solicitation UUIDs
                while (length >= 2) {parsedAd.uuids.add(UUID.fromString(String.format("x-0000-1000-8000-00805f9b34fb", buffer.getShort())));length -= 2;}break;case 0x04: // Partial list of 32 bit service UUIDs
            case 0x05: // Complete list of 32 bit service UUIDs
                while (length >= 4) {parsedAd.uuids.add(UUID.fromString(String.format("x-0000-1000-8000-00805f9b34fb", buffer.getInt())));length -= 4;}break;case 0x06: // Partial list of 128-bit UUIDs
            case 0x07: // Complete list of 128-bit UUIDs
            case 0x15: // List of 128-bit Service Solicitation UUIDs
                while (length >= 16) {long lsb = buffer.getLong();long msb = buffer.getLong();parsedAd.uuids.add(new UUID(msb, lsb));length -= 16;}break;case 0x08: // Short local device name
            case 0x09: // Complete local device name
                byte sb[] = new byte[length];buffer.get(sb, 0, length);length = 0;parsedAd.localName = new String(sb).trim();break;                case (byte) 0xFF: // Manufacturer Specific Data
                parsedAd.manufacturer = buffer.getShort();length -= 2;break;default: // skip
                break;}if (length > 0) {buffer.position(buffer.position() + length);}}return parsedAd;
}

其中 是自定义的简单 Java 对象,用来保存解析后的数据。这里只是解析了我关心的数据,你也可以根据前面的说明,解析更多的内容。

参考资料:

蓝牙官方文档 GAP and Scan Data BLE

关于我们

最火推荐

小编推荐

联系我们


版权声明:本站内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌抄袭侵权/违法违规的内容, 请发送邮件至 88@qq.com 举报,一经查实,本站将立刻删除。备案号:桂ICP备2021009421号
Powered By Z-BlogPHP.
复制成功
微信号:
我知道了