这里只讨论蓝牙BLE广播
这部分可以看蓝牙标准Core Specification V5.3的卷3 Host part C。当然广播参数那一块和“控制器”层有关,只需要了解广播参数的含义和设置方法就行,控制器的细节不太容易理解。
主要目标
- 广播参数(广播间隔、TX 功率、信道和使用的 PHY)。
- 广播类型(可连接与不可连接、可扫描与不可扫描等)。
- 蓝牙 LE 地址类型(公共、随机、静态、可解析等)。
- 在蓝牙 LE 广播和 UUID 中包含数据。
广播的作用
LE设备周期性的宣布自己存在,以让别人能连接自己。这里的周期性就是“广播间隔”
发起广播端的参数
广播间隔:发送广播包的间隔。范围为20ms至10.24s,步长为0.625ms。
广播间隔越小,广播数据包发送的频率就越高,因此功耗也就越大。因此,这里需要权衡功耗与扫描仪接收广播商的广播数据包的速度(通常称为可发现性)。为了避免数据包冲突,每个广播数据包之前都会添加 0-10 毫秒的随机延迟。这可确保具有相同广播间隔的设备不会一直发生广播数据包冲突。
广播信道:无线通信都会有通信的无线信道。蓝牙 LE 设备通过 40 个不同的频道进行通信。这些频道分为三个主要广播频道和 37 个次要广播频道。
接收广播端的参数
和广播间隔类似,在接收端(如手机)也会有一个时间叫“扫描间隔”和“扫描窗口”。
扫描间隔:设备扫描广播数据包的间隔。
扫描窗口:设备在每个扫描间隔内扫描数据包所用的时间。
两者范围均为 2.5 毫秒至 10.24 秒,步长为 0.625 毫秒。
从上图可以看出,广播会在37,38,39三个广播信道上传输,因此接受也会依次在3个信道上不停地切换,并接收广播。
上图中,绿色表示37信道,浅蓝色表示38信道,深蓝色表示39信道。
广播的请求
如果想了解设备的更多信息(如更多的服务UUID、扩展的设备名称、制造商数据等),那么就需要进行广播数据请求。正式的术语叫“扫描请求”和“扫描响应”
具体流程:
- 外围设备(如手表),发出广播数据包,让中央设备(如手机)能扫描到广播包。
- 中央设备发送“扫描请求”。
- 外围设备回应“扫描响应”。这里就可以附加更多的信息返回给设备。
扫描请求:中央设备向外围设备发送的消息,用于请求广播包中不存在的附加信息。
扫描响应:作为对扫描请求的响应而发送的消息,包含附加用户数据。
这个过程的作用
- 从上面可以看到,扫描请求和响应,可以作为未连接前,两个设备之间单向通信的一种方式。
- 因为广播包的长度有限,不能放入太多数据,可以用扫描响应来给出更多的设备信息。
广播的类型
外围设备可以通过多种不同的方式进行广播。
作用
有时候需要告诉别人,我这个设备,是不让别人连接的(如Becan设备),中央设备看到类型后,就不会去发起广播请求了。
广播类型的广播包的Header里面。
广播包类型
1. 可扫描和可连接 ( ADV_IND):这是最常见的广告类型。允许别人扫描请求。并且有响应,然后建立连接。
2. 定向可连接(ADV_DIRECT_IND):不接受扫描请求,但是特定中央设备可以快速连接的的广播。一个很好的例子是蓝牙鼠标与 PC 失去连接并且只想重新连接。在这种情况下,无需接受扫描请求,发送定向广播包以缩短连接过程会更快。
3. 不可连接且可扫描(ADV_SCAN_IND):可以有扫描请求,但是不允许建立连接。
4. 不可连接且不可扫描 ( ADV_NONCONN_IND):不能请求,也不能连接
连接、扫描、定向的含义
可连接与不可连接:确定中央设备是否可以连接到外围设备。
可扫描与不可扫描:确定外围设备是否接受来自中央设备的扫描请求。
定向与非定向:确定广播数据包是否针对特定中央设备。
蓝牙地址
和以太网,wifi的MAC地址的概念类似。蓝牙也有自己的“MAC”地址,就叫“蓝牙地址”
- 每个蓝牙 LE 设备都由一个唯一的 48 位地址标识。
- 蓝牙地址分为公共地址和随机地址。根据随机地址是否变化,随机地址又可分为静态地址或私有地址。此外,私有地址可以是可解析的,也可以是不可解析的。
下边对不同地址地址类型,详细展开:
公共地址
需要在 IEEE 注册机构注册,并且对于该设备而言是全球唯一的,并且无法删除。获取此类地址需要付费。并不是每个设备都会有这个地址,需要看厂家是否有为设备购买公共地址。
地址结构:
高24位:公司标识符(Organizationally Unique Identifier, OUI),由IEEE分配给设备制造商。
低24位:由设备制造商分配,唯一标识每个设备。
随机地址
随机地址更为常用,因为它不需要向 IEEE 注册,并且可以由用户手动配置。它既可以在设备内编程,也可以在运行时创建。随机地址又可以进一步细分为:随机静态地址(Random static address)或随机私有地址(Random private address)。
备注:随机私有地址根据可否解析,可分为“可解析私有地址”和“不可解析私有地址”。
因此随机地址一共有3种:静态随机地址,可解析的随机私有地址
静态随机地址
在设备的整个生命周期内固定不变。它可以在启动时更改,但不能在运行时更改。
地址结构:
高2位固定为11,表示这是一个静态随机地址。
剩余46位由设备在启动时随机生成,并在设备重启之前保持不变。
格式示例:11XXXXXX:YYYYYYYY:YYYYYYYY:YYYYYYYY
可解析的随机私有地址
因为目标侦听器拥有一个预共享密钥,每次地址发生变化时,他们都可以使用该密钥找出新地址。预共享密钥是身份解析密钥 (IRK),用于生成和解析随机地址。
地址结构:
高2位固定为01,表示这是一个可解析的私有地址。
剩余46位由设备通过一个密钥生成,中心设备可以通过身份解析键(Identity Resolving Key, IRK)解析出设备身份。
格式示例:01XXXXXX:YYYYYYYY:YYYYYYYY:YYYYYYYY
不可解析的随机私有地址
不可解析的私有地址无法被其他设备解析,仅用于防止跟踪。这种地址不常用。
地址结构:
高2位固定为00,表示这是一个不可解析的私有地址。
剩余46位随机生成,不能被解析出设备的身份。
格式示例:00XXXXXX:YYYYYYYY:YYYYYYYY:YYYYYYYY
总之,记住蓝牙地址一共有4种类型:公共地址:、随机静态地址、可解析随机私有地址、不可解析的随机私有地址。
广播包的帧格式
如上是广播包的格式,其中preamble,access address,CRC都是协议栈自动计算和填充的。下面继续看看Advertisement PDU里面有啥。
Advertisement PDU
Header头部,
PDU type:广播类型
RFU:保留
ChSel:通信channel的算法。就是通信时是怎么在通道之间跳转的。
TxAdd(Tx 地址):0 或 1,取决于发射器地址是公共的还是随机的。
RxAdd(Rx 地址):0 或 1,取决于接收地址是公开的还是随机的。
长度:有效载荷的长度。从这里可以看出广播包的有效载荷最大长度为256字节。
Payload
AdvA:广播设备的蓝牙地址
AdvData:广播数据
AdvData:广播数据
广播数据的内容,根据广播的类型决定。上文有讲广播的类型有4种。其中有定向广播(ADV_DIRECT_IND)比较特别。后面单独拿出来。剩余3种数据结构都一样。如下
广播数据里面可以分成很多段:AD0,AD1…ADn。每一段都有固定的格式,如上图浅蓝色部分。
为什么要分段?为了节省数据包的空间,一个段就代表一个有效数据。
如下示例
如果想在广播包里展示如上的信息。我们通常会这么写
- Complete list of 16-bit Service UUlDs:0x180D.0x180F,0x180A
- Complete Local Name: Zephyr HeartrateSensor
如上简单直观,但是会发现标题行已经占据了很大的篇幅,要知道蓝牙的广播包能存放的有效数据长度就几十个字节。为了解决这个问题。蓝牙标准预先定义好了广播数据类型(在Generic Access Profile.pdf定义)。并用数字表示,比如Complete Local Name:用数字0x09表示,Complete list of 16-bit Service UUlDs用数字0x03代替。这样,只需要2个字节,就可以表示需要三四十个字节的标题。
下图似乎蓝牙广播是,实际传输的广播包原始数据Raw data。Details是具体解析出来的分段数据。
zephyr的广播数据类型(AD Type),定义在这个头文件里面。
https://docs.nordicsemi.com/bundle/ncs-latest/page/zephyr/connectivity/bluetooth/api/gap.html#c.BT_DATA_FLAGS
综上所述:
要看到广播数据包的内容,需要做如下动作
- 先提取出整个ADV data
- 根据AD length,分离出第一个AD0,同样的剥离出AD1,ADn
- 根据AD type得知后面数据是什么数据。
蓝牙BLE的实例程序
这部分另外开文章展开。