广播结构解析

一个完整的BLE广播数据包最长可以有37个字节,其中前6个字节固定用于设备MAC地址,剩下的31个字节才是我们可以自由配置的广播数据区域。这31个字节会被划分为若干个广播数据结构体(AD Structure)。

输入图片说明

每个结构体都包含三个关键部分:

  1. 长度字段(1字节):指明当前结构体的总字节数
  2. 类型字段(1字节):定义这个结构体承载的数据类型
  3. 数据内容(N字节):实际要广播的信息

这里有个容易混淆的地方需要注意:长度字段的值 = 类型字段(1字节) + 数据内容(N字节)的总和。比如一个长度为0x04的结构体,意味着后面跟着1字节类型和3字节数据内容。

输入图片说明

示例1:基础结构
0x04,0x09,0x41,0x42,0x43,0x03,0x19,0x80,0x01
  • 第一个结构体:
    • 长度0x04 → 类型0x09 + 数据"ABC"(0x41,0x42,0x43)
  • 第二个结构体:
    • 长度0x03 → 类型0x19 + 数据0x80,0x01

输入图片说明

虽然规范允许使用最多31个字节,但这个示例只用了9个字节。系统会自动用0x00填充剩余空间,凑足31个字节。

输入图片说明

示例2:复杂结构分析
0x05 0x09 0x31 0x32 0x33 0x34 0x02 0x0A 0x08 0x06 0xFF 0x41 0x50 0x50 0x4C 0x45
  • 第一个结构体:
    • 长度0x04 → 类型0x09 + 数据"1234"(0x31 0x32 0x33 0x34)
  • 第二个结构体:
    • 长度0x02 → 类型0x0A + 数据0x08
  • 第三个结构体:
    • 长度0x06 → 类型0xFF + 数据"APPLE"(0x41 0x50 0x50 0x4C 0x45)

广播类型解析

理解广播数据的关键在于掌握各种广播类型的含义。就像我们阅读文章需要认识单词一样,解析广播数据必须熟悉不同类型的编码规则。

常见广播类型速查表

广播数据中,类型字段就像数据的"身份证",告诉我们这段内容代表什么信息。以下是工程师最常遇到的几种类型:

类型值 实际含义 典型应用场景
0x01 设备标识 区分设备类型
0x02 16位UUID 标识标准服务
0x07 128位UUID 自定义服务标识
0x08 缩略设备名称 简化显示的设备名
0x09 完整设备名称 完整的设备名称
0x0A 发射功率 用于距离估算
0x19 设备外观 显示设备图标类型
0xFF 厂商自定义数据 设备特有功能

掌握这些类型定义后,你就能像读说明书一样解读广播数据了。下次看到一长串十六进制数时,不妨先找类型字段,再对照这个表格,很快就能理解其中的含义。

实战解析示例

用之前的广播数据来练习解析技巧:

0x05 0x09 0x31 0x32 0x33 0x34
0x02 0x0A 0x08
0x06 0xFF 0x41 0x50 0x50 0x4C 0x45
  1. 设备名称(类型0x09)
    • 数据:0x31 0x32 0x33 0x34
    • 解析:UTF-8编码的"1234"
    • 作用:这是设备的完整名称,手机扫描时会显示这个名称
  2. 发射功率(类型0x0A)
    • 数据:0x08
    • 解析:转换为十进制是+8dBm
    • 作用:告知接收方设备的信号强度基准值
  3. 厂商数据(类型0xFF)
    • 数据:0x41 0x50 0x50 0x4C 0x45
    • 解析:ASCII码对应"APPLE"
    • 特别说明:这类数据的解释权完全归厂商所有,不同厂商的编码规则可能完全不同
注意事项

在实际开发中,有几点特别需要注意:

  • 类型0x08和0x09都是设备名称,区别在于前者是缩写版本(最长8字节),后者是完整版本
  • 发射功率值是有符号数,0x08表示+8dBm,而0xF8则表示-8dBm
  • 厂商自定义数据是最灵活的部分,开发时建议查阅具体设备的通信协议文档

设备标识定义

Type为0x01 表示的是设备标识,告知扫描设备(如手机)如何处理广播源设备,避免无效连接尝试。其含义如下:

比特位 名称 技术含义
bit0 LE Limited Discoverable 设备仅在有限时间内可被发现(如配对模式)
bit1 LE General Discoverable 设备始终可被发现
bit2 BR/EDR Not Supported 关键位:1=不支持经典蓝牙
bit3 Simultaneous LE & BR/EDR (Controller) 1=设备射频层支持双模(基带能力)
bit4 Simultaneous LE & BR/EDR (Host) 1=设备协议栈支持双模(软件能力)
bit5-7 Reserved 保留

实验

笔者使用ESP32开发板和MicroPython进行BLE广播实验,搭配nRF Connect手机APP作为扫描工具。

核心API

gap_advertise()是MicroPython中控制BLE广播的核心方法,主要参数说明:

  • interval_us:广播间隔(微秒),实际会取625us的整数倍
  • adv_data:广播数据包内容,支持bytes/bytearray/str类型
  • resp_data:扫描响应数据(可选)
  • connectable:是否允许连接(默认可连接)

特别要注意的是:

  1. 传入None作为间隔参数会停止广播
  2. 如果不指定adv_data,会沿用上次设置的数据
  3. 要清空广播数据需要显式传递空bytes(b''

实验代码解析

示例代码实现了最基本的不可连接广播。测试设备只支持LE(低功耗蓝牙),不支持BR/EDR(经典蓝牙),一般都将设备设为处于普通发现模式,所以我们只设置Bit1和Bit2,即0x06(b00000110)。

from time import sleep_ms
import ubluetooth   # 导入BLE功能模块

ble = ubluetooth.BLE()  # 创建BLE设备
ble.active(True)  # 打开BLE

# 设置BLE广播数据
adv_data = b'\x02\x01\x06\x0C\x09micropython'
ble.gap_advertise(100, adv_data=adv_data)

# 打印广播数据包
print("开始广播")
print("广播数据包:", ' '.join(f'{byte:02x}' for byte in adv_data))

try:
    while True:
        sleep_ms(1000)  # 保持广播,间隔1秒
except KeyboardInterrupt:
    ble.gap_advertise(None)  # 停止广播
    print("停止广播")

主广播数据:

02 01 06 0c 09 6d 69 63 72 6f 70 79 74 68 6f 6e这串十六进制其实包含两个重要信息块:

  1. 设备标志(3字节)
    • 02 → 后面数据块长度:2字节
    • 01 → 数据类型:设备标志位(Flags)
    • 06 → 标志值:00000110(二进制)
      • Bit1和Bit2被置1 → 表示"通用可发现模式"
      • 其他位都是0 → 不支持经典蓝牙(BR/EDR),只支持低功耗(LE)
  2. 设备名称(13字节)
    • 0C → 后面数据块长度:12字节
    • 09 → 数据类型:完整设备名称(Complete Local Name)
    • 6d 69 63 72 6f 70 79 74 68 6f 6e → 这是"micropython"的ASCII编码
      (m-i-c-r-o-p-y-t-h-o-n)

实验结果验证

使用nRF Connect扫描时,可以搜索到广播的设备名为micropython。广播的数据也都正常解析

输入图片说明

Logo

智能硬件社区聚焦AI智能硬件技术生态,汇聚嵌入式AI、物联网硬件开发者,打造交流分享平台,同步全国赛事资讯、开展 OPC 核心人才招募,助力技术落地与开发者成长。

更多推荐