BLE Legacy 广播【广播内容】
1、Legacy Advertising 最核心的 4 个 HCI Command
Legacy BLE 广播配置主要就是这 4 个命令:
| HCI Command | Opcode | 作用 |
|---|---|---|
LE Set Advertising Parameters |
0x2006 |
设置广播参数 |
LE Set Advertising Data |
0x2008 |
设置 Advertising Data |
LE Set Scan Response Data |
0x2009 |
设置 Scan Response Data |
LE Set Advertising Enable |
0x200A |
开启 / 关闭广播 |
可以先把它理解成:
LE Set Advertising Parameters
决定怎么广播LE Set Advertising Data
决定广播包里面放什么内容LE Set Scan Response Data
决定收到 Scan Request 后回复什么内容LE Set Advertising Enable
决定是否开始广播
在我上一篇博客《BLE 广播 rawBytes 解析说明》提到的rawBytes其实就是Advertising Data和Scan Response Data,为了连贯性所以本篇博客先把LE Set Advertising Data和LE Set Scan Response Data理解清楚。
2、LE Set Advertising Data
Part E Host Controller Interface Functional SpecificationThis Part describes the functional specification for the Host Controller interface (HCI). The HCI provides a uniform command interface to a Controller.
https://www.bluetooth.com/wp-content/uploads/Files/Specification/HTML/Core-61/out/en/host-controller-interface/host-controller-interface-functional-specification.html#UUID-7b83376f-e321-e7ce-3bf1-2af187798be4
这张图就是 Legacy Advertising 的 HCI 命令:HCI_LE_Set_Advertising_Data。它对应前面说的“把 rawBytes 配置进广播包”。
核心可以这样理解:
HCI_LE_Set_Advertising_Data
作用:设置 Legacy 广播包里的 Advertising Data
最大长度:31 字节
数据格式:Vol 3, Part C, Section 11 定义的 AD Structure
2.1 这个命令设置的就是 Advertising Data
截图里这句话很关键:
This command is used to set the data used in advertising packets that have a data field.
意思是:
这个命令用于设置广播包中的 data field,也就是 Legacy 广播里的 Advertising Data。
对于 App 开发来说,可以把它理解成:
这个命令设置的内容 ≈ 扫描端看到的 rawBytes 里面的 Advertising Data 部分
也就是这种结构:
Length | AD Type | AD Data
Length | AD Type | AD Data
Length | AD Type | AD Data
...
2.2 Advertising_Data_Length 是有效数据长度
截图里:
Advertising_Data_Length
Size: 1 octet
Value: 0x00 to 0x1F
The number of significant octets in the Advertising_Data.
重点是:
0x1F = 31
所以:
Advertising_Data_Length 最大就是 31 字节
它表示 Advertising_Data 里面有多少个有效字节。
比如你要设置:
02 01 06
03 03 0F 18
08 09 44 65 76 69 63 65 31
总长度是:
3 + 4 + 9 = 16 字节
那么:
Advertising_Data_Length = 0x10
因为:
0x10 = 16
2.3 Advertising_Data 固定是 31 octets
截图里:
Advertising_Data
Size: 31 octets
31 octets of advertising data formatted as defined in Vol 3 Part C, Section 11.
意思是:
这个 HCI 命令里的 Advertising_Data 参数固定给了 31 字节空间。
但是并不是说这 31 字节都一定有效。真正有效多少,看前面的:
Advertising_Data_Length
例如有效数据只有 16 字节,那么命令里面还是会带一个 31 字节数组:
Advertising_Data_Length = 0x10
Advertising_Data[31] =
02 01 06
03 03 0F 18
08 09 44 65 76 69 63 65 31
00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
前 16 字节是有效数据,后面的 00 是补齐。
所以如果看到 rawBytes 后面有很多 00,就可以和这里对应上:
HCI 命令字段固定有 31 字节空间
但有效广播数据长度由 Advertising_Data_Length 决定
2.4 significant part 是什么意思?
截图里还有一句:
Only the significant part of the Advertising_Data should be transmitted in the advertising packets.
这里的 significant part 就是有效部分。
也就是说:
只有 Advertising_Data_Length 指定的那部分数据,才应该真正放进广播包发送出去。
例如:
Advertising_Data_Length = 0x07
Advertising_Data[31] =
02 01 06 03 03 0F 18 00 00 00 ...
那么真正广播出去的 Advertising Data 应该只有:
02 01 06 03 03 0F 18
后面的 00 00 00... 不属于有效广播内容。
2.5 如果广播已经开启,再设置 Advertising Data 会怎样?
截图里这段也很重要:
If advertising is currently enabled, the Controller shall use the new data in subsequent advertising events.
If an advertising event is in progress when this command is issued, the Controller may use the old or new data for that event.
意思是:
如果广播已经开启,此时再发 HCI_LE_Set_Advertising_Data,Controller 后续的广播事件会使用新的广播数据。
但是如果刚好有一个广播事件正在进行中,那么那个事件可能使用旧数据,也可能使用新数据。
所以实际工程里更稳妥的做法通常是:
1. 关闭广播
2. 设置 Advertising Data
3. 再开启广播
也就是:
LE Set Advertising Enable = 0x00
LE Set Advertising Data
LE Set Advertising Enable = 0x01
不过规范也允许在广播开启时更新数据,只是当前那个正在进行的 advertising event 不保证一定立即使用新数据。
这点和多 Beacon 轮播有关。
如果模块内部做多 Beacon 轮播,它可能就是周期性更新 Advertising Data。某个广播事件用旧数据还是新数据,底层有一定时序差异。
2.6 默认值是什么意思?
截图里:
The default Advertising_Data_Length shall be zero
and the default Advertising_Data shall be 31 all-zero octets.
意思是默认情况下:
Advertising_Data_Length = 0
Advertising_Data = 31 个 0
也就是:
默认没有有效 Advertising Data
不是说默认广播 31 个 00,而是有效长度为 0。
2.7 Return Parameters 只有 Status
这个命令返回参数只有:
Status
如果:
Status = 0x00
表示:
HCI_LE_Set_Advertising_Data command succeeded
如果:
Status = 0x01 ~ 0xFF
表示命令失败,具体错误码要查 Controller Error Codes。
所以这个命令只是告诉你:
广播数据是否设置成功
它不会返回当前广播数据,也不会帮你解析 AD Structure。
2.8 Event generated:Command Complete
截图最后说:
When the HCI_LE_Set_Advertising_Data command has completed,
an HCI_Command_Complete event shall be generated.
意思是:
Host 发出这个 HCI Command 后,Controller 执行完成,会返回一个:
HCI_Command_Complete Event
里面带上 Status。
所以 HCI 层交互大概是:
Host -> Controller:
HCI_LE_Set_Advertising_Data
Controller -> Host:
HCI_Command_Complete Event
Status = 0x00 / error code
以上内容总结如下:
LE Set Advertising Data 命令用于设置 Legacy 广播包中的 Advertising Data。
Advertising_Data_Length 表示有效数据长度,最大 0x1F,也就是 31 字节。
Advertising_Data 是固定 31 字节数组,里面的数据必须按 AD Structure 格式组织:
Length | AD Type | AD Data。
只有 Advertising_Data_Length 指定的有效部分会被放进广播包发送。
3、LE Set Scan Response Datahttps://www.bluetooth.com/wp-content/uploads/Files/Specification/HTML/Core-61/out/en/host-controller-interface/host-controller-interface-functional-specification.html#UUID-7f9e3a5b-fa09-5292-b64e-1a5304b6a255
https://www.bluetooth.com/wp-content/uploads/Files/Specification/HTML/Core-61/out/en/host-controller-interface/host-controller-interface-functional-specification.html#UUID-7f9e3a5b-fa09-5292-b64e-1a5304b6a255
这个命令和上一条 LE Set Advertising Data 是一对的。区别是:
LE Set Advertising Data
设置主动广播包里的 Advertising Data
LE Set Scan Response Data
设置收到 SCAN_REQ 后回复的 Scan Response Data
也就是说,这张图讲的是 Legacy BLE 扫描响应数据的配置命令。
3.1 这个命令设置的是什么?
命令名:
HCI_LE_Set_Scan_Response_Data
OCF:
0x0009
完整理解:
Host 通过这个 HCI Command,把 Scan Response Data 配置到 Controller 里。
当 Controller 后续收到 Scanner 发来的 SCAN_REQ 时,就可以回复 SCAN_RSP。
SCAN_RSP 里面携带的就是这里配置的 Scan_Response_Data。
也就是说:
LE Set Scan Response Data
↓
配置 Scan_Response_Data
↓
外设收到 SCAN_REQ
↓
回复 SCAN_RSP
↓
手机扫描端可能拿到这部分数据
3.2 Scan_Response_Data_Length
截图里这个字段:
Scan_Response_Data_Length
Size: 1 octet
Value: 0x00 to 0x1F
意思是:
Scan Response Data 的有效数据长度,范围 0 到 31 字节。
因为:
0x1F = 31
所以 Legacy BLE 下:
Scan Response Data 最大也是 31 字节
和 Advertising Data 一样。
例如你配置扫描响应数据:
08 09 44 65 76 69 63 65 31
这表示:
08 = Length
09 = AD Type,Complete Local Name
44 65 76 69 63 65 31 = Device1
总长度是 9 字节,所以:
Scan_Response_Data_Length = 0x09
3.3 Scan_Response_Data 固定 31 字节
截图里写:
Scan_Response_Data
Size: 31 octets
意思是 HCI 命令参数里固定提供一个 31 字节数组。
但真正有效的字节数由:
Scan_Response_Data_Length
决定。
例如:
Scan_Response_Data_Length = 0x09
Scan_Response_Data[31] =
08 09 44 65 76 69 63 65 31
00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
前面 9 字节有效,后面的 00 是补齐,不是有效扫描响应内容。
3.4 Scan Response Data 里面仍然是 AD Structure
截图里提到:
formatted as defined in Vol 3 Part C, Section 11
意思是它的格式和 Advertising Data 一样,仍然是:
Length | AD Type | AD Data
所以 Scan Response Data 不是另一套格式。
例如:
08 09 44 65 76 69 63 65 31
解析为:
08 = Length,后面有 8 字节
09 = AD Type,Complete Local Name
44 65 76 69 63 65 31 = AD Data,字符串 Device1
再比如:
05 FF 34 12 01 02
解析为:
05 = Length
FF = Manufacturer Specific Data
34 12 = Company ID,小端序,0x1234
01 02 = 厂商自定义数据
所以不管是 Advertising Data 还是 Scan Response Data,本质都使用同一套 AD Structure。
3.5 和 LE Set Advertising Data 的区别
这两个命令非常像:
| 命令 | 设置的数据 | 最大长度 | 什么时候发送 |
|---|---|---|---|
LE Set Advertising Data |
Advertising Data | 31 字节 | 外设主动广播时发送 |
LE Set Scan Response Data |
Scan Response Data | 31 字节 | 外设收到 SCAN_REQ 后回复 |
也就是说:
Advertising Data 是外设主动发的。
Scan Response Data 是别人问了之后才回复的。
Legacy BLE 里常见的配置方式是:
Advertising Data:
Flags
Service UUID
Manufacturer Data
Scan Response Data:
Complete Local Name
因为设备名称比较占空间,放到广播包里可能不够,所以很多设备会把完整名称放到扫描响应包里。
3.6 不是所有广播都会用到 Scan Response Data
这个很关键。
你配置了 Scan_Response_Data,并不代表它一定会被发出去。
它需要几个条件:
1. 广播类型必须是 scannable
2. 扫描设备必须处于 Active Scanning
3. 扫描设备实际发送了 SCAN_REQ
4. 外设 Controller 收到 SCAN_REQ
5. 外设回复 SCAN_RSP
例如:
| Advertising Type | Link Layer PDU | 是否可扫描 | 是否会用到 Scan Response Data |
|---|---|---|---|
0x00 |
ADV_IND |
是 | 可能 |
0x02 |
ADV_SCAN_IND |
是 | 可能 |
0x03 |
ADV_NONCONN_IND |
否 | 不会 |
所以如果你把广播类型设置成:
ADV_NONCONN_IND
即使你配置了 Scan Response Data,正常情况下手机也不会发 SCAN_REQ,模块也不会回复 SCAN_RSP。
3.7 如果广播已经开启,再修改 Scan Response Data 会怎样?
截图里这段和上一条命令一样:
If advertising is currently enabled, the Controller shall use the new data in subsequent advertising events.
If an advertising event is in progress when this command is issued, the Controller may use the old or new data for that event.
意思是:
如果广播已经开启,再设置新的 Scan Response Data,那么 Controller 后续的 advertising events 会使用新数据。
但是如果刚好某个 advertising event 正在进行中,这个事件可能使用旧数据,也可能使用新数据。
所以工程上更稳妥的配置流程仍然是:
1. 关闭广播
2. 设置 Advertising Parameters
3. 设置 Advertising Data
4. 设置 Scan Response Data
5. 开启广播
也就是:
LE Set Advertising Enable = 0x00
LE Set Advertising Parameters
LE Set Advertising Data
LE Set Scan Response Data
LE Set Advertising Enable = 0x01
3.8 默认值
截图里写:
The default Scan_Response_Data_Length shall be zero
and the default Scan_Response_Data shall be 31 all-zero octets.
意思是默认情况下:
Scan_Response_Data_Length = 0
Scan_Response_Data = 31 个 0
也就是:
默认没有有效的 Scan Response Data
不是说默认会扫描响应 31 个 00。
有效长度为 0,就表示没有有效扫描响应数据。
3.9 App 层看到它时是什么样?
这个命令配置的是底层 SCAN_RSP 里的数据。
但是到了 iOS / Android App 层,一般不会明确告诉你:
这个字段来自 Advertising Data
这个字段来自 Scan Response Data
系统可能会把两部分整理到扫描结果里。
例如底层配置:
Advertising Data:
02 01 06
03 03 0F 18
Scan Response Data:
08 09 44 65 76 69 63 65 31
App 层可能看到:
Flags: 0x06
Service UUID: 0x180F
Local Name: Device1
但是 App 通常不能可靠判断:
Device1 是从 Advertising Data 来的,还是从 Scan Response Data 来的。
3.10 总结
这张图说明的是:
LE Set Scan Response Data 命令用于设置 Legacy BLE 的 Scan Response Data。
Scan_Response_Data_Length 表示有效数据长度,最大 31 字节。
Scan_Response_Data 是固定 31 字节数组,内容格式仍然是 AD Structure:
Length | AD Type | AD Data。
这部分数据只有在广播类型可扫描,并且扫描设备发送 SCAN_REQ 后,才会通过 SCAN_RSP 发出去。
可以把它和上一条命令放在一起记:
LE Set Advertising Data:
设置主动广播出去的 31 字节 Advertising Data。
LE Set Scan Response Data:
设置被主动扫描时回复的 31 字节 Scan Response Data。
更多推荐

所有评论(0)