基于 BLE 5.1 协议 Core Spec。
目录
2.2.1、Common Extended Advertising Payload Format
啰嗦几句
广播(Advertising),之所谓称之为广播,最初的含义(BLE 4.2)是为了让其他设备发现自己的存在,也就是告诉空中的其他设备:“我在这里啊~~,这是我的地址 0xAABBCCDDEEFF ”(BD Address 我瞎写的),其他的处于 Scanning 状态的设备,就能够发现广播者了。
不过呢,BLE 5.0 上对传统的广播进行了升华,赋予了它新的使命。接下来我们就来探讨这些东西。(5.0 上传说中的 X8 的 Data)
就像现在流行的垃圾分类一样,垃圾分为干垃圾,湿垃圾,可回收垃圾,不可回收垃圾。^_^
广播(后面称为 ADV 或者 Adv)也分为,可连接/不可连接 ADV,可扫描/不可扫描 ADV,定向/不定向 ADV,等以及他们的各种组合。(唐僧给悟空啰嗦这些,肯定要被活活 K 死)。好了,现在不管那么多,咱们先来介绍各种 ADV 包的格式以及用法(请看官耐心)。
根据不同 BLE 的版本,ADV 分为两类:
Legacy ADV:BLE 4.2 版本的 ADV
Extend ADV: BLE 5.x 版本的 ADV
好了,这里先有一个概念,这两者之前的关系,待后面详细细说。
1、ADV 广播包组成
广播包的组成呢,也遵循上一节讲的数据包的基本组成方式(BLE(3)—— 空口数据包组成),只不过 AA 变为了特定值(0x8E89BED6),PDU 赋予了它新的生命:
广播的 PDU 组成主要由 Header 和 Payload 构成:
Header 由 16bits 构成,Payload 长度为 1~255 字节。
我们一步一步来,先看看 Header 域。
1.1、ADV PDU Header
Header 包含的内容比较丰富:
1、PDU Type:标识这种 ADV 是什么类型的 ADV(后面详细介绍)
2、RFU : Reserved For Further 暂时不用,为后续预留
3、ChSel:如果本机支持跳频(Hopping)算法 #2,这设置成为 1
4、TxAdd:如果为 0 代表 ADV 是 public 类型的 Address,否则为 1,是 random 类型的 Address
5、RxAdd:如果为 0 代表期望的对端地址类型为 public,否则为1,代表期望对端的 Target Address 为 random(在指向性广播中使用,因为指向性广播,携带了对端地址,其他类型广播,这个 bit 没用)
6、Length:代表了后面的 Payload 的长度,以直接为单位,因为是 8bits,所以最大的长度为 255 个字节
好了,这里就剩下 PDU Type 没用详细介绍了,在介绍这个之前呢,需要给大家插播一条 BLE4.2 Vs BLE 5.x,这样理解这个玩意会更加容易。
---------------------------------------------------- 插播内容开始 ---------------------------------------------------
在 BLE 4.2 时代,所有的 ADV 都在 37、38、39上进行发送和接收交互,这里我们称 37、38、39 为 Primary Advertising Physical Channel 并且呢,ADV 携带的数据最大是 31 个字节。
到了 BLE 5.0 时代,SIG 说,ADV 你们几爷子也可以在其他频道上搞事情了,好了,这个时候,SIG 对 ADV 进行了扩展,Core Spec 管这些新来的 ADV 大爷叫做 Extended ADV,也就是扩展广播(名字简单粗暴吧)。扩展广播是怎么个扩展法子呢?就是在 Primary Advertising Physical Channel 上,还是会发一个叫 EXT_ADV 的包,这个包呢,携带了一些信息,信息中包含了下一个和他关联的包的所在地(Secondary Advertising Physical Channel),这个所在地,就不是 37、38、39了,而是其他的 37 个通道中的一个,具体是哪个,由这个 EXT_ADV 的包来决定。
---------------------------------------------------- 插播内容结束 ---------------------------------------------------
好了,这里主要插播的目的是引出,Extended ADV 的概念和 Secondary Advertising Physical Channel 的概念。OK,我们继续包格式的分析之旅。
1.1.1、ADV PDU Header PDU Type
Alright,下图表示了 PDU Type 不同,所对应的包的不同,以及他们的 Physical Channel,甚至于支持的 PHYs:
我觉得已经非常清楚了(可能是我已经知道了后面的内容的缘故),如果觉得不清楚呢,没事,看完 ADV 的所有分析后,在回头来看这个表,客官您一定会觉得豁然开朗。
2、ADV 的各种 PDU
还记得文章开始卖的关子么,这里,把 ADV 的 PDU 介绍分为两个阶段,一个是 Legcay ADV ,另一个是 Extended ADV。
这里细聊 PDU 中的 Payload,各种 Payload 构成了丰富多彩的 PDU,进而构成了不同的包:
2.1、Legacy ADV PDUs
远古时代,就已经支持个一些种类的 ADV PDUs,咱们称之为,Legcay ADV:
• ADV_IND
• ADV_DIRECT_IND
• ADV_NONCONN_IND
• ADV_SCAN_IND
接下来一个一个分析呗。
2.1.1、ADV_IND
这个比较经典和常用的 ADV PDU 了,它代表了咱们发出去的这个 ADV 包,是一个可连接的,并且可扫描的广播包。什么是可连接呢?意思是,我发出去这个包,别人想连接我,OK,没问题。可扫描指的是,有人处于 Scanning 状态,收到我的这个 ADV_IND 后,对端发起 SCAN_REQ,咱们回复他 SCAN_RSP。
ADV_IND 的 包体为:
AdvA:本机地址 48bits
AdvData:携带的数据 0 - 31 字节
2.1.2、ADV_DIRECT_IND
顾名思义,咱们可以知道这种类型的数据包,是可连接的并且带指向性的(不可扫描),什么叫指向性呢,也就是,我指着对端的鼻子说,我这个包是专门给你准备的(来连接我啊)。所以这个包携带了本机地址和指着的那个地址。同时不允许携带数据:
AdvA:本机地址 48bits
TargetA:对端地址 48bit
2.1.3、ADV_NONCONN_IND
这种类型的 ADV PDU,属于不可连接,不可扫描,不定向的 ADV 包,包含了本机地址和数据(类似于,在空中散布谣言类型)
AdvA:本机地址 48bits
AdvData:携带的数据 0 - 31 字节
2.1.4、ADV_SCAN_IND
这种类型的 ADV PDU 是只能扫描的不定向的,不连接的 ADV
AdvA:本机地址 48bits
AdvData:携带的数据 0 - 31 字节
2.2、Extended ADV PDUs
前面知道,Legacy ADV 是通过每一个都有一个不同的 PDU Type 来进行区分的,可以看到,之前那个表里面,Extended ADV 很多都是同一个 PDU Type,这个咋个区分呢?
这个我们要从引入 Extended ADV 的源头说起。
Extended ADV PDUs 有一个叫 Common Extended Advertising Payload Format 的东东,它代表了所有的 Extended ADV PDUs 的格式包含:
• ADV_EXT_IND
• AUX_ADV_IND
• AUX_SCAN_RSP
• AUX_SYNC_IND
• AUX_CHAIN_IND
• AUX_CONNECT_RSP
2.2.1、Common Extended Advertising Payload Format
这个是针对 Extended 的 Common 结构描述。是啥意思呢,也就是,BLE 5.x 扩展的广播信道系列的包,遵从这个格式:
Extended Header Length:代表了后面的那个Extended Header 域的长度,这个 Extended Header 域是变长的
AdvMode:2 个 bits,代表了不同 ADV 的模式,包含是否可连接,是否和扫描以及它们的组合
Extended Header:Header 域,包含很多内容,马上呈现
AdvData:携带的数据,这个携带的数据长度是动态的。计算方法是:用上一级的 PDU Header 的长度减去这个 Extended Header 的长度(Extended Header Length 代表的),在减去 1 个字节(Extended Header Length + AdvMode = 8 bits)
2.2.1.1 AdvMode
AdvMode 使用 2 个 bits 表示,表达了这个包是否可被连接,是否能够被扫描:
2.2.1.2 Extended Header
这个域是一个可变长度,它的结构稍微复杂,为:
其中:Extended Header Flags 由 1 个 Byte 构成,它代表了后面的域是否存在:
Extended Header Flags
可变,就可变在,如果对应的 bit 为 1,则代表后续的数据包,对应的域是存在在,否则,如果为 0,则代表对应的域不存在。打个比方:如果这个 Extended Header Flags 为 00000011'b,则代表,后面的 AdvA 和 TargetA 是有货的,其他几个域不包含在这个 Payload 里面。
AdvA 和 TargetA,都是 48bits 的,这里代表的含义肯定大家都猜到了,代表了本机地址和对端地址。这里不再介绍。
CETInfo 用于 AoA/AoD 以后再说。
AdvDataInfo 字段要说一下:
这里的 AdvDataInfo 分为了 Advertising Data ID 和 Advertising Set ID:
Advertising Data ID:一个广播,可能发送不同的数据(比如周期性广播,并不是每次都发送的同样的数据),那么为了让对端知道当前的数据是个啥(或者说是第几包数据),那么就要对数据进行编号咯,所以就有这个玩意啦。
Advertising Set ID:一个蓝牙,只有一个地址,但是可以开启多个广播,本机肯定知道当前使用的那个广播(用 Handle 区分),但是其他空中的设备不知道呀,所以呢,这个 SID 就用于别人区分同一个设备发送的多个广播啦,所以也就叫广播集。
AuxPtr 字段也要啰嗦一下:
前面说过(后面会详细讲,看完在来看这个,立马茅塞顿开),Extended Adv 的行为是,首先在 Primary Advertising Physical Channel 上发送一个 Extended ADV,然后再 Secondary Advertising Physical Channel 上在发送一些具体的信息,所以呢,这个 AuxPtr 的含义,就是描述在 Secondary Advertising Physical Channel 的信息。
打个比方,对方 Scanning 的时候,在 Primary Advertising Physical Channel 上收到了你的 Extended ADV,为了更好的知道你的情况,它需要继续在 Secondary Advertising Physical Channel 上继续收包,那么既然是 Secondary Advertising Physical Channel,咱们就需要在 Primary 上写给别人说:“你,要在哪个频道上去准备收包(Channel Index),什么时候去收包(Offset Unites and AUX Offset),在哪个 PHY 上去收(AUX PHY)”
OK,明白了吧:
Channel Index:描述了需要在哪个 Secondary Advertising Physical Channel 上去接收 AUX 包
Offset Units:Offset 的单位
AUX Offset:收包的时间点是距离现在时间多少个 Offset Units
AUX PHY:使用哪个 PHY 来收包(1M/2M/Coded)
CA:代表了Clock 的精度
所以:
Offset Units:
AUX PHY:
CA:
为了容错,允许发送 AUX 包的时候呢,有一定的偏差,但是偏差需要控制在一个 Offset Unit,所以呢,在空口上看到的样子是:
好了,我们回到 Extended Header,SyncInfo 字段呢,用于描述周期性广播,后面详细讲解,这里知道有他就行了。
TxPower 字段用于描述 Tx 的 Power(相当于没说),也就是发送的能量。
ACAD 这个我只知道用于代表小的 ADV 数据,在 BLE 5.0 没用到,BLE 5.1 还没有对这个玩意的用法完全研究透彻,以后看到在补上吧。
好了,终于把通用的 Extended ADV 格式描述完了,累死了。下面就看看他的具体用法吧,首先看 ADV_EXT_IND 这个玩意。
2.2.2、ADV_EXT_IND
这个包是爷,为什么是爷呢?因为所有的扩展广播,都要经过他把关!
他发送在 Primary Advertising Physical Channel 上,目的是为了引出后续的 Secondary Advertising Physical Channel 包。这个的解释是,绝大多数的扩展广播包,都是以 ADV_EXT_IND(Primary) + AUX_ADV_IND(Secondary) 的形式来组织的,扫描端想要知道这个扩展广播的含义,则,必须要收到 ADV_EXT_IND 后,接着去收 AUX_ADV_IND,然后完成数据解析,才知道这个到底是个啥。
广播分为可连接,可扫描,不可连接,不可扫描的组合,以及是否带数据,依据这个的话,BLE Core Spec 将 ADV_EXT_IND 的组成分为了几类:
是不是想吐了,是的,第一眼我看到,也是想打人!这个表格的 X,O,M,C,的含义如下:
好,我们来分析一个,接下来的由大家自行分析:
最常见的,就是可连接,不定向的包了:
这里如果你想发送这个包,则需要:
1、AdvMode 设置成为 01'b
2、ADV_EXT_IND 包中不含 AdvA
3、ADV_EXT_IND 包中不含 TargetA
4、ADV_EXT_IND 包中不含 CTEInfo
5、ADV_EXT_IND 包中一定要有 ADI
6、ADV_EXT_IND 包中一定要有 AuxPtr
7、ADV_EXT_IND 包中不含 SyncInfo
8、ADV_EXT_IND 包中可选含 Tx Power (1M 可选,Coded PHY 以后支持)
9、ADV_EXT_IND 包中不含 ACDA
10、ADV_EXT_IND 包中不含 AdvData
有的朋友肯定会问:“啊,你发送一个可连接的扩展广播,咋个都不带地址信息啊”,非常好,因为这种可连接的包的组织形式是:
ADV_EXT_IND(Primary) + AUX_ADV_IND(Secondary)
看到了么,在 ADV_EXT_IND 强制了 AuxPtr,也就是一定要有 AUX_ADV_IND 这个,地址信息被放在这个里面了。
OK,其他的就不一一讲解了,套路是一样的。
2.2.3、AUX_ADV_IND
这个和上一个是好基友,经常勾肩搭背,成对出现,一起表征了扩展广播,废话不多说,套路一样:
看到没,这里的 Connectable Undirected 的 AdvA 是强制的(M),而 TargetA是没有的,因为他是不指向性的包,所以没有 TargetA,对应了指向性的扩展广播,TargetA 就是强制的 (M)。
所以呢?觉得多数的扩展广播,上面两个包都能够表示了。
2.2.4、AUX_SYNC_IND
这个包比较特殊,专门用于周期性广播,当建立起周期性广播后,会按照周期发送这个包:
这里有一点要注意一下,周期性广播包,只能是非连接,不能扫描的,也就是说,对端只需要安安静静的听我发的东西就好了,别给我回复,因为,反正我也不会回复你。
2.2.5、AUX_CHAIN_IND
按照前面的说明,ADV 数据最多发送 251 个,那如果我想发更多的数据咋办?好勒,Chain 包送上!
如果发数据的时候(一个 251 Bytes 装不下),这时候,在空口上会继续发送 Chain 包,你可以把它理解成为锁链,或者链表。
注意到了么,AUX_ADV_IND 的某些类型,和 AUX_SYNC_IND 类型的 AuxPtr 为 可选(O),意思是,后面还可以跟东西,跟的这个东西,咱们就管他叫 Chain 包,AuxPtr 向指针一样,指向了下一个关联的包。
也就是说,一个 ADV_EXT_IND 跟一个 AUX_ADV_IND,再有数据发,那么后面跟的就是 AUX_CHAIN_IND 了。那么如果跟一个 AUX_CHAIN_IND 不够咋办,当然是这个 AUX_CHAIN_IND 后面继续跟 AUX_CHAIN_IND(AuxPtr 可选).........当然也不可能无限 AUX_CHAIN_IND,这个和具体的 BLE CORE IP 的硬件资源是紧密联系的(工程实现章节分析)。
举个例子,Chain 包在空口上可能的情况之一:
---- 【ADV_EXT_IND】 ---- 【ADV_EXT_IND】---- 【ADV_EXT_IND】
----------------------------------------------------------------------------------- 【AUX_ADV_IND】
---------------------------------------------------------------------------------------------------------------------【AUX_CHAIN_IND】
3、结尾
所以,SIG 宣称的 X8 Data 指的啥意思?并不是传统链路传送可以传送什么8倍数据,而是以前 ADV 最大 31 字节,现在扩展广播后,支持了 254,差不多 8 倍,这个体现在广播上了。
BLE 5.0 以后,引入了扩展广播,的确是把广播搞得复杂许多,使得广播不光光是空中吆喝的角色了,也起到了能够承载一部分数据传送的作用。