今天系统地总结一下蓝牙的广播。通常我们看到的蓝牙广播,似乎只广播了一个蓝牙名称,因为我们在手机上进行蓝牙搜索时发现只能看到名字。然而事实并非如此,如果我们用nrf Connect扫描的话,就会发现,单单广播包中就可以包含众多信息。
这是我在周围发现的一个设备,可以看到这个设备的广播中还是包含了很多信息的,显而易见的,它的广播名称是ESP32, 然后还有它的MAC地址为:5C:E5:0C:D0:7F:7A,以及当前的RSSI,-69dBm。其次,这里还有很多其他信息,例如它的设备类型是单模的LE设备,也就是低功耗蓝牙,其内核版本是4.1。然后它的公司是Xiaomi,所以这应该是我家里的空调插座,因为ESP32是wifi+ble,我家只有这个设备是用wifi连接网络,然后还可以作为蓝牙mesh的网关。
这是我扫描到的另一个设备,从设备名字上看不出是个什么东西来,但是上面图片显示了一个鼠标呢,所以这其实是一个HID设备,广播信息中包含了它的服务UUID:0x1812,这就是一个标准的HID设备的描述。我们点击图中的RAW可以看到原始数据,软件很友好的给出了广播包的组织格式
从这里,我们至少知道,整个广播包的长度为61个字节(这是我认真数的),根据下面表格也可以计算出来Len = 2+26+8+17+3 + 5 = 61。认真看的朋友一定发现了,最后为什么要加一个5呢?这是因为广播包的特殊组织形式导致的,它首先用一个字节来表示本条数据帧后面数据的长度,然后再用一个字节来表示本条数据帧的类型Type,后面的Value则表示真正的数据,数据总数 + Type就正好是最开始的长度LEN。所以,一共5条数据帧,我们要把存储LEN的5个字节加上,这样才是广播包数据的总长度。我们来像剥洋葱一样剥一下蓝牙的广播数据吧。
广播报文结构
一个完整的BLE广播报文由四部分组成,分别是前导码,接入地址,协议数据单元和CRC校验码,一个广播包的实际最大数据长度为47个字节。
- 前导码:用来同步时序,就好像我们做串口通信的时候总是弄个0x55,0xAA开始,这里也不例外,在广播报文里,这个前导码被规定为0xAA。接入地址:长度为4个字节,广播报文的接入地址被定义为:0x8E89BED6。协议数据单元:包含了两个字节的报头和0~37个字节的payload。CRC校验码:长度为3个字节。
剥一层下来,我们看广播报文PDU
图中可以看到,他实际包含了 2个自己的报头Header和最长37个字节的payload,我们先看Header的内容。
- PDU Type:PDU类型,标识广播报文的类型,包括是广播还是扫描,能否连接等等,后面有个表格。RFU:保留TxAdd:发送地址类型,标识广播地址是共有地址还是随机地址RxAdd:接收地址类型,广播只发送,因此不使用Length:标识后面payload的长度,0 ~ 37字节,使用 6 bits (64)表示刚刚好。
接下来,我们看Payload部分是怎么组织的,到这里就剩下0 ~ 37字节了。这个payload字段中还包含两部分,一部分是6个字节的AdvA部分,剩余部分才是我们的AdvData。所以我们经常说广播报文最大长度是31个字节,就是这么来的。
广播报文:长度域包含6个比特,有效值的范围是6~37。
数据报文:长度域包含5个比特,有效值的范围是0~31。
广播报文和和数据报文的长度域有所不同,主要原因是:广播报文除了最多31个字节的数据之外,还必须要包含6个字节的广播设备地址。6+31=37,所以需要6比特的长度域。
公有地址:这个就是我们常说的MAC地址,跟我们电脑的网卡的那个格式是一样的。
- 随机地址:为了防止设备被跟踪,广播地址可以是随机的。这里的随机地址又分为静态设备地址、私有设备地址和不可解释私有地址,哈哈,关于蓝牙的广播地址
- AdvA:广播设备地址,分为公共地址和随机地址。
这里解释一下公有地址和随机地址的区别:
AdvData:广播数据,包含多个广播的Structure,这里翻译成结构吧,就是开头我们讲的那个结构。
这里顺带记录一下,蓝牙的CRC计算报头,长度和payload的,其多项式为:
广播结构的定义
上图可以非常清晰的看到广播数据包的组织结构,其中所谓的无效部分就是我们广播内容比较少,没有用到的部分。蓝牙官网有很详细的手册 Specifications | Bluetooth® Technology Website关于AD type的定义在这个文档里 Assigned_Numbers.pdf 这里面除了标准定义好的一些类型,比如0x09是完整的设备名称,0x0A是发射功率等级等等,还有一些厂商可以自己定的空间,也就是AD type:0xFF
我们可以利用这个字段来自定义自己的产品信息,这样就可以让我们的APP在扫描到我的设备时,即使不连接也能知道我是哪个具体型号,或者子型号或者更多可以想象的操作。我基本上使用这个属性来识别公司各类产品的类别,这样我们的APP在扫描的时候就能看到产品的图片,非常的利于辨认。
广播包和响应包
BLE中有两种角色,分别是Central和Peripheral,以前叫做主机从机,现在叫做中心设备和外围设备。中心设备可以主动连接外围设备,外围设备可以发送广播被中心设备扫描到,广播中就包含了很多外围设备的自身信息。在真正连接之前,外围设备其实有两次机会可以向中心设备上报信息,第一次肯定是正常的广播,这也是每个外围设备必须要具备的能力。至于响应包,外围设备是可以选择的,其实可以理解为对中心设备扫描的回复,至于搭不搭话茬,就看自己了。
如果我们再加上响应包的31个字节,那么我们在未连接之前可以向主机展示的信息最多为62字节了。回到我们开头扫描的那个hid设备,他就是有响应包的,直接发送了61个自己的数据。
关于广播的内容,先记录这些。