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

广播模式

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

广播包有两种:广播包(Advertising Data)和响应包(Scan Response),其中广播包是每个设备必须广播的,而响应包是可选的。数据包的格式如下图所示(图片来自官方 Spec):每个包都是 31 字节,数据包中分为有效数据(significant)和无效数据(non-significant)两部分。

  • 有效数据部分:包含若干个广播数据单元,称为 AD Structure。如图中所示,AD Structure 的组成是:第一个字节是长度值 Len,表示接下来的 Len 个字节是数据部分。数据部分的第一个字节表示数据的类型 AD Type,剩下的 Len - 1 个字节是真正的数据 AD data。其中 AD type 非常关键,决定了 AD Data 的数据代表的是什么和怎么解析,这个在后面会详细讲;
  • 无效数据部分:因为广播包的长度必须是 31 个 byte,如果有效数据部分不到 31 自己,剩下的就用 0 补全。这部分的数据是无效的,解释的时候,忽略即可。

广播数据格式

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

  • Flags: TYPE = 0x01。这个数据用来标识设备 LE 物理连接的功能。DATA 是 0 到多个字节的 Flag 值,每个 bit 上用 0 或者 1 来表示是否为 True。如果有任何一个 bit 不为 0,并且广播包是可连接的,就必须包含此数据。各 bit 的定义如下:

    • bit 0: LE 有限发现模式
    • bit 1: LE 普通发现模式
    • bit 2: 不支持 BR/EDR
    • bit 3: 对 Same Device Capable(Controller) 同时支持 BLE 和 BR/EDR
    • bit 4: 对 Same Device Capable(Host) 同时支持 BLE 和 BR/EDR
    • bit 5..7: 预留
  • Service UUID: 广播数据中一般都会把设备支持的 GATT Service 广播出来,用来告诉外面本设备所支持的 Service。有三种类型的 UUID:16 bit, 32bit, 128 bit。广播中,每种类型类型有有两个类别:完整和非完整的。这样就共有 6 种 AD Type。

    • 非完整的 16 bit UUID 列表: TYPE = 0x02;
    • 完整的 16 bit UUID 列表: TYPE = 0x03;
    • 非完整的 32 bit UUID 列表: TYPE = 0x04;
    • 完整的 32 bit UUID 列表: TYPE = 0x05;
    • 非完整的 128 bit UUID 列表: TYPE = 0x06;
    • 完整的 128 bit UUID 列表: TYPE = 0x07;
  • Local Name: 设备名字,DATA 是名字的字符串。Local Name 可以是设备的全名,也可以是设备名字的缩写,其中缩写必须是全名的前面的若干字符。

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

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

    • bit 0: OOB Flag,0 表示没有 OOB 数据,1 表示有
    • bit 1: 支持 LE
    • bit 2: 对 Same Device Capable(Host) 同时支持 BLE 和 BR/EDR
    • bit 3: 地址类型,0 表示公开地址,1 表示随机地址
  • 外设(Slave)连接间隔范围:TYPE = 0x12。数据中定义了 Slave 最大和最小连接间隔,数据包含 4 个字节:

    • 前 2 字节:定义最小连接间隔,取值范围:0x0006 ~ 0x0C80,而 0xFFFF 表示未定义;
    • 后 2 字节:定义最大连接间隔,同上,不过需要保证最大连接间隔大于或者等于最小连接间隔。
  • 服务搜寻:外围设备可以要请中心设备提供相应的 Service。其数据定义和前面的 Service UUID 类似:

    • 16 bit UUID 列表: TYPE = 0x14
    • 32 bit UUID 列表: TYPE = 0x??
    • 128 bit UUID 列表: TYPE = 0x15
  • Service Data: Service 对应的数据。

    • 16 bit UUID Service: TYPE = 0x16, 前 2 字节是 UUID,后面是 Service 的数据;
    • 32 bit UUID Service: TYPE = 0x??, 前 4 字节是 UUID,后面是 Service 的数据;
    • 128 bit UUID Service: TYPE = 0x??, 前 16 字节是 UUID,后面是 Service 的数据;
  • 公开目标地址:TYPE = 0x17,表示希望这个广播包被指定的目标设备处理,此设备绑定了公开地址,DATA 是目标地址列表,每个地址 6 字节。

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

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

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

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

广播数据解析

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

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);

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

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

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("%08x-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("%08x-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;
}

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

参考资料:

  1. 蓝牙官方文档
  2. GAP Advertising and Scan Response Data format
  3. Parsing BLE Advertisement packets

https://race604.com/ble-advertising/

BLE 广播数据解析相关推荐

  1. Android的BLE广播数据包介绍和解析---BLE--Android系列, 蓝牙技术BLE

    目录 一.引言 二.广播的类型 三.广播数据格式 四.广播数据解析 五.总结 一.引言 理解和分析这个数据包结构(这里面也涉及广播间隔时间的设置,设备广播数据间隔设置长了,会影响设备被发现的效率:设置 ...

  2. 蓝牙广播数据包_一分钟读懂低功耗蓝牙(BLE)广播数据包

    一分钟读懂低功耗蓝牙(BLE)广播数据包 低功耗蓝牙 => BLE (Bluetooth Low Energy) 1. 怎样抓取BLE广播数据包 * 硬件:一个BLE设备(具有广播功能): 一台 ...

  3. 蓝牙4.0 BLE 广播包解析

    本文转自:蓝牙4.0BLE抓包(二) – 广播包解析 - 强光手电 - 博客园 感谢原创作者! SleepingBug评论:这篇文档写的相当好,受教了,多谢了! 所有图片水印均是CSDN自动标上的,并 ...

  4. 51822模拟ble广播-理论

    http://blog.chinaunix.net/uid/28852942/cid-219646-list-1.html 这讲教程介绍如何使用51822的radio部分来模拟实现ble广播功能,并使 ...

  5. 蓝牙广播数据包_蓝牙BLE数据包格式汇总

    以蓝牙4.0为例说明: BLE包格式有:广播包.扫描包.初始化连接包.链路层控制包(LL层数据包).逻辑链路控制和自适应协议数据包(即L2CAP数据包)等: 其中广播包又分为:定向广播包和非定向广播包 ...

  6. CC2541解析广播数据及扫描响应

    广播数据(advertData)和扫描响应(scanRspData) 在典型的蓝牙BLE(Bluetooth Low Energy )系统中,从机设备广播数据让所有主机设备知道它是一个可连接的设备.接 ...

  7. 【IoT】BLE 广播的基础数据定义:广播名字类型和设备类型标志

    BLE 实际广播 AD 数据区满足 LTV 格式,下面介绍的类型就是指数据 LTV 中的 T 字段. 1.广播名字类型 广播中的 name_type 字段: typedef enum {BLE_ADV ...

  8. 【BLE】广播数据包结构讲解,五颗蓝牙芯片对比

    [广播数据包结构讲解] 广播数据包的讲解网上可参考的也挺多,讲解了整个数据包的每个字节每个位的功能描述,非常详细. 今天我们换个方式,按照代码编写的方式,只要是被SDK封装的部分都不做考虑,例如报头. ...

  9. 蓝牙4.0BLE抓包(二) – 广播包解析

    转自: http://www.cnblogs.com/aikm/p/5022502.html 版权声明:本文为博主原创文章,转载请注明作者和出处.    作者:强光手电[艾克姆科技-无线事业部] 在使 ...

最新文章

  1. Android 内容观察者 ContentObserver 类
  2. zabbix server、zabbix agent、zabbix proxy 配置文件详解
  3. 傅里叶卷积实现「万物隐身」,这个神器可试玩
  4. 宇宙和你,本质上其实只是个八维数字?
  5. 技术分享:浅谈Service Mesh在瓜子的实践
  6. Windows下Caffe-SSD编译
  7. Windows Server 2016 Hyper-v 嵌套虚拟化技术
  8. linux cmake 安装mysql5.5.11_以及更高版本_linux cmake 安装mysql5.5.11,以及更高版本
  9. 【转】由投影重建图像:滤波反投影、FDK、TFDK三维重建算法理论基础
  10. php jquery mysql,使用PHP / MySQL搜索并使用jQuery动态更新
  11. 基于CUDA的GPU优化建议
  12. [.NET领域驱动设计实战系列]专题十:DDD扩展内容:全面剖析CQRS模式实现
  13. matlab中3乘4魔方阵,小代码3 魔方矩阵
  14. 记一次闲置电视盒子乐视C1S折腾entware
  15. QT控件 之(TreeView)实现右键菜单栏功能,双击事件能实现区分不同的节点的点击效果
  16. word文档动态插入水印,45度角,位于文档中央,可插入中文(附jar包和licence文件))
  17. 阿尔伯塔计算机硕士要求,阿尔伯塔大学计算机硕士专业介绍
  18. 如何彻底关闭Win10自动更新,Win10永久关闭自动更新的方法
  19. EDM营销解读[转载]
  20. 感谢各位博友的关注和支持!

热门文章

  1. oracle常用函数之STDDEV、STDDEV_POP、STDDEV_SAMP区别
  2. STM32驱动Marvell 88W8686 WiFi模块代码说明(20180129版)
  3. 线性代数之 矩阵求导(3)标量、向量求导的快速记忆
  4. 关于计算机故障排除的文章 三(转)
  5. 【升华网络】为你介绍淘宝
  6. 大话设计模式12.25-2.19(过年十五天没有更~偷个懒)
  7. APISIX 助力中东社交软件,实现本地化部署
  8. 喝“饮料”后财物被偷 菲2华人起诉“迷魂党”成员
  9. 国外html5转app store,H5唤醒移动端APP,或跳转到App Store和应用宝
  10. Philips飞利浦 Sonicare E系列电动牙刷替换刷头