蓝牙“广播数据”通常指 BLE 广播包里的 AdvData / ScanRspData,它不是一整块自由文本,而是由若干 AD Structure(广播数据单元) 拼起来的。
一、整体层次
空口 PDU
├─ 前导 / 接入地址 / MAC 地址 / 头 / CRC(协议栈管)
└─ AdvData(应用层关心的负载)
└─ AD Structure 1
└─ AD Structure 2
└─ ...
- Legacy 广播:AdvData 最多 31 字节,Scan Response 再 31 字节
- Extended Advertising(BLE 5.0+):可通过辅助信道扩到最大 1650 字节
二、AD Structure 格式(核心)
每个单元都是 LTV:
[Length 1B][AD Type 1B][AD Data ...]
- Length:
AD Type + AD Data的字节数(不含 Length 自己) - AD Type:这段数据是什么(由蓝牙 SIG 分配)
- AD Data:具体内容,长度 = Length - 1
例:
02 01 06
- 02:后面有 2 字节
- 01:Flags
- 06:LE General Discoverable + BR/EDR Not Supported
三、常见 AD Type
| AD Type | 含义 | 说明 |
|---|---|---|
| 0x01 | Flags | 是否可发现、是否纯 BLE |
| 0x02 / 0x03 | 16-bit UUID 不完整 / 完整列表 | 设备支持的服务 |
| 0x06 / 0x07 | 128-bit UUID 不完整 / 完整列表 | 自定义服务常用 |
| 0x08 / 0x09 | Shortened / Complete Local Name | 设备名 |
| 0x0A | TX Power Level | 发射功率 dBm,用于测距 |
| 0x16 | Service Data(16-bit UUID) | UUID + 业务数据 |
| 0x19 | Appearance | 设备类型(手表/鼠标/体温计…) |
| 0xFF | Manufacturer Specific Data | 厂商私有协议主战场 |
四、0xFF 厂商自定义数据(最常用)
[AD Type=0xFF][Company ID 2B][厂商私有数据...]
- 前 2 字节:SIG 分配的 Company ID(小端)
- 0x004C = Apple
- 0x0006 = Microsoft
- 0x004D = LG
- 0x0590 / 0x0059 = Nordic(示例)
- 后面完全自定义:传感器值、状态位、固件版本、MAC、帧序号、加密负载等
iBeacon / Eddystone / 微信 AirSync / 华为碰一碰 都建立在 0xFF 或 0x16 上。
五、广播类型(PDU 层面)
| 类型 | 是否可连接 | 是否响应扫描 |
|---|---|---|
| ADV_IND | 可连接 | 可扫描 |
| ADV_NONCONN_IND | 不可连接 | 不可扫描(纯信标) |
| ADV_SCAN_IND | 不可连接 | 可扫描(发 ScanRsp) |
| ADV_DIRECT_IND | 定向可连接 | 否 |
六、手写一个广播包例子
想广播:
- 通用可发现、纯 BLE
- 名字
Sensor01 - 厂商数据:公司 ID=0x1234,payload=
01 64(类型1,电量100)
02 01 06
0B 09 53 65 6E 73 6F 72 30 31
05 FF 34 12 01 64
解析:
02 01 06→ Flags0B 09 ...→ 0x0B=11 字节,0x09=Complete Local Name,Sensor0105 FF 34 12 01 64→ 厂商数据,Company ID=0x1234(34 12 小端),数据=01 64
七、工程上怎么定协议
如果你要做“蓝牙广播传业务数据”,建议:
- 用
0xFF放私有数据 - 前 2 字节 Company ID
- 第 3 字节:协议版本(方便以后改格式)
- 第 4 字节:设备类型 / 消息类型
- 后面:状态码、传感器值、CRC 等
- 多字节整数统一用 小端
- 名字/UUID 放 Scan Response,主广播只放“过滤用的最小信息”
示例:
[FF][CompanyID 2B][ver][type][battery][temp低][temp高][status][crc]