BLE 广播数据解析



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

广播模式

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

广播包有两种: 广播包 (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() {
    @Override
    public 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 对象,用来保存解析后的数据。这里只是解析了我关心的数据,你也可以根据前面的说明,解析更多的内容。

http://www.tuicool.com/articles/3EZjYvv

参考资料:

<think>好的,我现在需要详细回答用户关于BLE广播数据结构的组成和格式的问题。首先,我需要回顾自己之前学过的蓝牙低功耗(BLE)相关知识,尤其是广播包的结构。根据用户提供的引用内容,特别是引用[2]和引用[3],里面提到了广播包的类型和数据结构的限制。 用户的问题核心是BLE广播数据结构的格式和组成,所以我需要分步骤解释。首先,广播包的基本结构,包括各个字段的长度和用途。例如,每个广播包由多个AD Structure组成,每个AD Structure包含长度、类型和具体数据。这部分需要详细说明每个字段的含义,比如长度字段占1字节,类型字段也是1字节,后面的数据部分长度可变。 然后,我需要列举常见的广播数据类型,比如Flags、设备名称、服务UUID、制造商数据等,并给出每个类型的例子,例如Type 0x01对应Flags,数据部分可能包含BR/EDR不支持、同时支持普通和低功耗模式等信息。这里需要参考引用[2]中的广告类型说明。 接下来,广播数据有31字节的限制,这一点在引用[1]和引用[3]中都有提到,虽然某些扩展模式可能更长,但通常基础广播模式下是31字节。这里需要强调数据长度的限制以及如何合理利用空间,如使用压缩或高效编码,如引用[1]中的注意事项部分。 此外,广播包和扫描响应数据的区别也需要说明。广播包是设备主动发送的,而扫描响应数据是在扫描请求后回复的,两者结构相同,但用途不同,总长度可能达到62字节(31+31)。引用[1]提到扩展广播模式可能有更大的数据长度,但基础模式是31字节。 然后,我需要举一个实际的广播数据示例,帮助用户更好地理解结构。例如,分解一个包含Flags、设备名称和制造商数据广播包,每个AD Structure的具体字节分配。 最后,根据用户的要求生成相关问题,可能需要涉及数据结构优化、类型字段作用、数据长度限制的影响等,确保问题与主题相关,并参考提供的引用内容中的知识点。 需要检查是否符合系统级指令,比如所有数学表达式是否正确使用$...$,是否有独立公式(但这个问题可能不需要),中文回答是否正确,引用标识是否在适当的位置添加。例如,在提到数据长度限制时,引用[1]和引用[3]的相关部分需要标注。 可能需要注意的细节:确保每个AD Structure的格式正确,类型字段的常见值对应的正确含义,以及数据长度的计算方式(长度字段本身占1字节,类型1字节,数据部分n字节,总长度n+2)。同时,需要指出广播信道只有三个,无法跳频,这点在引用[3]中有提到,可能影响数据可靠性和功耗,但用户主要问的是数据结构,这部分可能作为补充说明。 总结回答结构:先总述广播数据结构的组成,然后分点详细讲解每个部分,再讨论数据长度限制及优化,举例说明,最后相关问题和引用标注。</think>### BLE广播数据结构的组成与格式 BLE广播数据结构由多个**广告数据结构(AD Structure)**组成,每个AD Structure包含三个部分:**长度(Length)**、**类型(Type)**和**数据(Data)**。其格式如下: $$ \begin{array}{|c|c|c|} \hline \text{长度 (1字节)} & \text{类型 (1字节)} & \text{数据 (n字节)} \\ \hline \end{array} $$ 其中,`长度`字段表示**类型+数据**的总字节数,即数据部分的实际长度为`长度-1`[^2]。 --- #### 1. 常见广播数据类型 以下为几种常见的Type类型及其含义(部分示例): - **0x01 (Flags)**:指示设备能力,如是否支持BR/EDR、低功耗模式等。例如:`0x06`表示“仅BLE,不支持传统蓝牙,且可被发现”[^2]。 - **0x08/0x09 (设备名称)**:完整或缩短的设备名称。例如:`0x08`对应完整名称如“Device_A”。 - **0x03/0x16 (服务UUID)**:完整UUID或部分UUID列表。例如:心率服务UUID为`0x180D`。 - **0xFF (制造商数据)**:自定义数据,通常包含厂商ID和自定义字段。例如:苹果的iBeacon数据[^2]。 --- #### 2. 广播数据长度限制 - **基础广播模式**:单个广播包(Advertising Data)最大为**31字节**,若同时启用扫描响应数据(Scan Response),则总长度可达**62字节**(31+31)[^1]。 - **扩展广播模式**:支持更长的数据(如1650字节),但需设备支持BLE 5.0及以上规范[^1]。 --- #### 3. 广播包示例 假设某广播包内容如下(十六进制): ``` 02 01 06 0A 09 44 65 76 69 63 65 5F 42 05 FF 4C 00 10 20 ``` 解析如下: - **02 01 06**:长度2,类型0x01(Flags),数据0x06(表示BLE仅限、可被发现)。 - **0A 09 44...5F42**:长度10,类型0x09(完整设备名),数据为ASCII码“Device_B”。 - **05 FF 4C...20**:长度5,类型0xFF(厂商数据),厂商ID为0x004C(苹果),后续为自定义数据。 --- #### 4. 数据设计的注意事项 - **空间优化**:需在有限长度内优先传输关键信息(如服务UUID),必要时压缩数据或分多次广播[^1]。 - **功耗与频率**:数据过长可能导致广播间隔增加,影响扫描端功耗和响应速度[^3]。 - **兼容性**:需根据BLE版本选择广播模式,例如扩展广播需双方设备支持BLE 5.0[^1]。 ---
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值