扫二维码与项目经理沟通
我们在微信上24小时期待你的声音
解答本文疑问/技术咨询/运营咨询/技术建议/互联网交流
目录
创新互联建站主营潜江网站建设的网络公司,主营网站建设方案,重庆APP开发公司,潜江h5小程序开发搭建,潜江网站营销推广欢迎潜江等地区企业咨询前言:
4.2版本广播:
5.0版本广播:
实现原理:
格式定义:
广播事件类型:
扩展广播:
周期广播:
广播集:
HCI接口定义:
4.2版本:
5.0版本:
周期广播:
疑问与解答:
BLE 5.0的扩展广播特性,网上的资料很少,我觉得写一点关于扩展广播的内容是有意义的。蓝牙BLE的4.2版本及其之前版本,有一个很大的限制,就是广播数据的payload太小了,只有31个字节。原因是广播物理信道(37,38,39)只有三个,并且大家都在使用,因此无法像数据信道那样,修改信道上传输的数据包的大小来解决问题(数据信道有一个好处,就是有37个信道,可以跳频,大家彼此冲突的几率小,但是广播信道没有这个条件)。
为了解决广播数据payload小的这个问题,蓝牙BLE在5.0版本中,新增了扩展广播的特性,包含了广播集,周期广播等概念,了解扩展广播实现机制后,我们可以明显的感受到一个信息:“5.0扩展广播的实现是在模仿GATT连接的实现”。
4.2版本广播:我们首先回顾一下4.2版本的广播定义,4.2的蓝牙广播根据PDU Type来区分,一共有7种类型,这7种类型的广播都是在37,38,39三个无线信道上收发的。
图1
将4.2的蓝牙广播分为2组,这样更方便记忆:
1组:ADV_IND,ADV_DIRECT_IND,ADV_NONCONN_IND,ADV_SCAN_IND
这四个广播从名字上来区分,它们更容易理解为的广播概念(ADV),它们根据是否可以处理连接请求和扫描请求两个维度分为四种,如图2。
图2
2组:CONNECT_REQ,SCAN_REQ,SCAN_RSP,这三个类型的广播,是带有一定功能性的,之所以将它们也划分到广播类型中,是因为它们也是在广播信道上收发的,蓝牙4.2版本的BLE将在BLE广播信道上发送的PDU,都分类为广播数据。蓝牙BLE4.2版本的链路层的广播PDU的格式汇总如图3,本文主要介绍扩展广播,因此此部分内容一张图带过。
图3
其中需要说明的2点:
1.广播PDU的access address是固定的,它的值为0x8E89BED6。
2.Link Layer packet format中的PDU大值是39(2字节header,37字节Payload)。
5.0版本广播:5.0版本协议发布之后,新增广播类型的叫做extend adv,而将4.2以及之前版本的广播叫做legacy adv,5.0版本协议中在4.2的7种广播类型基础上,又新增了8种广播类型的PDU,如图4。
图4
实现原理:4.2版本的蓝牙规范中,提到过它的广播通道只有 37,38,39 这三个,剩余的37个信道都是数据信道,数据信道用于发送连接的数据,payload比广播信道的数据要长(从Link Layer packet format来看,可以发送257个字节PDU)。在5.0的广播信道定义中,将37,38,39三个信道定义为Primary Advertising,可以叫做主广播信道,将剩余37个信道叫做Secondary Advertising,Secondary Advertising也可以用来发送广播数据,可以叫做辅助广播信道或者第二广播信道,说白了就是使用4.2的数据信道作为辅助广播信道,用来发送广播数据,将单包广播数据的payload提升到和“连接ACL数据payload”一样,辅助广播信道上发送和接收的包,也叫做辅助包(auxiliary packet)。这就是5.0扩展广播的核心思想,“将广播数据用数据信道来传输”。
将广播数据用数据信道来传输,确实可以提升单包数据的payload,但是也需要解决一个核心问题,对端设备无法同时在40个信道上扫描广播包,扫描端设备必须要确定广播设备在什么时候使用了哪个数据信道来传输广播数据,这个核心问题在BLE的GATT连接通信上也是存在的(它的解决方式是跳频,跳频的策略是在“建立连接时由两端设备同步Channel Map和hop”的基础上来实现,然后就可以按照双方已知的规则进行跳频通信)。另外一个核心问题是如何向下兼容4.2版本的广播实现。
5.0新增的8个广播类型,7个是工作在Secondary Advertising上的,都是AUX_***命名的广播,AUX是Auxiliary(辅助)的缩写,只有一个ADV_EXT_IND是工作在Primary Advertising上。
格式定义:图4的表格中,PDU Type为0011b的SCAN_REQ和AUX_SCAN_REQ,这两个广播消息的PDU Type是相同的,并且PDU的Payload格式也是相同的,那么蓝牙BLE是如何区分这两个消息的不同呢,后来一想它们是工作在不同的信道上的,SCAN_REQ工作在37,38,39三个信道,AUX_SCAN_REQ工作在0~36信道,如果一个PDU Type为0011b的广播消息出现在Primary Advertising上,那么他就是SCAN_REQ,如果出现在Secondary Advertising上,那么他就是AUX_SCAN_REQ消息。CONNECT_IND和AUX_CONNECT_REQ消息也是靠着同样的逻辑进行区分的。
剩下6种广播类型,其中5个工作在Secondary Advertising上,是AUX_SCAN_RESP,AUX_ADV_IND,AUX_SYNC_IND,AUX_CHAIN_IND和AUX_CONNECT_RSP,另外1个工作在Primary Advertising上,叫做ADV_EXT_IND,这6种广播的payload格式均符合Common Extended Advertising Payload Format格式,如图5所示,该图中的Payload部分只列出了扩展广播相关的新增的数据格式,兼容4.2版本的legacy部分没有列出(可以参考图3中的Payload)。
图5
Common Extended Advertising Payload Format格式详解:
下面详细介绍一下这几种新增的广播包的格式:
图6
从图6可知,ADV_EXT_IND里面是不带AdvData和ACAD,说明它本身不包含最终的广播数据。另外with auxiliary packet的广播类型,一定要包含ADI和AuxPtr字段,ADI标识本广播属于哪个广播集合(SID),广播数据的ID(DID)是多少。AuxPtr会告诉扫描设备,它的辅助包的广播数据在什么时间点出现在哪个辅助信道上。他的第一个辅助包的格式是AUX_ADV_IND。
图7
ADI是强制存在的字段,并且要求和指向它的ADV_EXT_IND中的ADI是相同的,这样子才可以表示这两个广播是关联的,它们协作起来发送同一个payload比较大的广播数据。如果数据广播的payload比较短,一个AUX_ADV_IND就可以发送完成,则它的AuxPtr可以没有,如果广播数据没有发完,则它的AuxPtr字段指向下一个辅助包,它可以是AUX_CHAIN_IND。如果是周期广播的话,那么它的SyncInfo字段指向下一个AUX_SYNC_IND(周期广播)。
图8
图9
图10
图11
扩展广播的spec中,经常会出现上级包(superior PDU),辅助包(auxiliary PDU)的概念,我们可以把扩展广播理解为一个单向链表,表头是工作在Primary Advertising上的ADV_EXT_IND PDU(其中AUX_SCAN*和AUX_CONNECT*除外),它里面的AuxPtr指向了下一个工作在Secondary Advretising上的AUX_ADV_IND PDU,如果有更多的数据的话,它里面的AuxPtr还会指向下一个AUX_CHAIN_IND PDU,依次向后,可能会存在n个AUX_CHAIN_IND PDU,直到数据结束,最后一个AUX_CHAIN_IND的AuxPtr字段为空,AuxPtr就像是链表里面的next节点指针。
扩展广播 PDU | 上级包 (superior PDU) | 辅助包 (auxiliary PDU) |
ADV_EXT_IND | - | AUX_ADV_IND |
AUX_ADV_IND | ADV_EXT_IND | AUX_CHAIN_IND PDU AUX_SYNC_IND PDU |
AUX_SYNC_IND | AUX_ADV_IND | AUX_CHAIN_IND |
AUX_CHAIN_IND | AUX_ADV_IND AUX_SYNC_IND AUX_CHAIN_IND | AUX_CHAIN_IND |
AUX_SCAN_REQ | - | - |
AUX_SCAN_RSP | - | AUX_CHAIN_IND |
AUX_CONNECT_REQ | - | - |
AUX_CONNECT_RSP | - | - |
表1
广播事件类型:图12中,描述了5.0版本支持的广播事件类型,兼容4.2的legacy的PDU Type我用红色框标注了,从该图中我们可以看到扩展广播是无法发送Connectable and Scannable Undirected Event的,只有legacy的广播可以发送此类型的广播事件。而Scannable Undirected Event广播,legacy和扩展广播都可以发送。
图12
扩展广播:这部分内容比较多,我们只选取其中几个广播事件类型:
#1 ADV_EXT_IND(Primary Advertising 37,38,39)
#2 AUX_ADV_IND(Secondary Advertising)
#3 AUX_CHAIN_IND(Secondary Advertising)
#4 AUX_CHAIN_IND(Secondary Advertising)
......
#n AUX_CHAIN_IND(Secondary Advertising)
其中#2~#n处于不同的Secondary信道,由上级包中的AuxPtr指定。
图13
图14
图15
定向和非定向的区别,主要在于TargetA是否存在,关于时序部分相差无几,因此可扫描,可连接,不可扫描不可连接,分别找了1个例子来举例广播事件,其中的没有提到的内容还很多,
图16
限制:
周期广播是5.0扩展广播的一个功能,他用来周期的发送广播数据,同时它的数据是可以变化的,为什么不用非周期广播来发送呢(非周期广播也可以更改数据,也可以一直处于广播状态),我的理解是为了低功耗和更好的同步性,因为非周期广播的最小间隔是Adv Interval(20ms)+ delay(0~10ms),因为delay的不确定性,扫描者需要打开更多的扫描窗口来接收到需要的广播数据,同时它的同步性没有那么好,但是周期广播没有0~10ms的delay,并且使用跳频技术,因此扫描者可以更小的打开scan窗口,从而降低功耗,获得更好的同步性,周期广播有点类似于单向GATT传输,一对多的GATT连接。当周期广播被启动后,the periodic advertising interval不能被更改。从图8中,我们可以获取到周期广播只能用来发送不可扫描不可连接的广播事件。同时AUX_SYNC_IND如果无法承载全部的AdvData,可以在他后面通过AuxPtr指向下一个AUX_CHAIN_IND PDU。周期广播的AdvInterval为7.5 ms ~ 81.91875 s。
周期广播事件的广播顺序应该是:
#1:ADV_EXT_IND(Primary Advertising)
#2:AUX_ADV_IND(Secondary Advertising,他的SyncInfo字段不为空,类似于legacy的CONNECT_IND,包含着跳频所需的ChannelMap)
#3:AUX_SYNC_IND(如果AdvData超过单包大限制,需要跟着若干个AUX_CHAIN_IND PDU,这个PDU有点类似于GATT的ACL连接包,注意他的SyncInfo字段为空)
#4:AUX_SYNC_IND()
#5:AUX_SYNC_IND()
......
图17
AUX_ADV_IND PDU的SyncInfo field中的Event Counter字段,是这么定义的,每发一次AUX_SYNC_IND PDU,它就会+1,这个起初让我很疑惑它是干什么用的,因为Event Counter本身并不出现在AUX_SYNC_IND PDU中,但是它却会随着每次发送一次AUX_SYNC_IND PDU,它就+1。后来看到了下面这段定义才恍然大悟,原来这个值是用来计算跳频频谱的,发起AUX_ADV_IND的周期广播发起者,和扫描者,都需要实时计算这个Event Counter,为了可以获取下一次接收周期广播的跳频后的信道号。
图18
周期广播传输的AdvData是Host下发的,链路层使用AUX_SYNC_IND PDUs和他的辅助包来发送数据,如果Host不再更新数据的话,链路层会一直重复上次的数据,周期广播会一直发送,直到Host下发了停止周期广播的HCI Command。
图19
图19对我理解周期广播的概念造成了很大的困惑,困惑的点在于第二个AUX_SYNC_IND为什么是由ADV_EXT_IND和AUX_ADV_IND引过来的,周期广播嘛,按理说应该没有他们才对呀,想了很久才想明白,其实第二个ADV_EXT_IND和AUX_ADV_IND是不需要的,没有它,也可以继续发送周期广播,它存在的意义是为了让那些没有收到第一次ADV_EXT_IND和AUX_ADV_IND的扫描设备,也可以与当前的周期广播同步。但是对于第一次就收到了ADV_EXT_IND和AUX_ADV_IND的扫描设备来说,是没有什么意义的。扫描者不会尝试去同步一个已经同步的周期广播。
换个角度说,第一次的ADV_EXT_IND和AUX_ADV_IND确定了AUX_SYNC_IND的广播时序和跳频信道,第二次的ADV_EXT_IND和AUX_ADV_IND是为了让其他扫描设备也可以同步上AUX_SYNC_IND PDU,它不会更改AUX_SYNC_IND的广播时序和跳频信道。之前谈到过,周期广播的实现机制类似于GATT连接,但GATT的单次连接是一对一的,但是周期广播是希望可以很多扫描者都可以同步获取广播上的数据的,因此它会发送多次ADV_EXT_IND和AUX_ADV_IND来保证后面接入的扫描者,也可以同步得获取数据,因此也需要Event Counter这个东西,和前面的内容也严丝合缝的解释清楚了。这里面还涉及一个周期广播Interva和广播Interval的概念,第一次的ADV_EXT_IND,AUX_ADV_IND和第二次的ADV_EXT_IND,AUX_ADV_IND的间隔是广播Interval,AUX_SYNC_IND之间的间隔是周期广播的Interval。
广播集的是扩展广播中的一个概念,它通过设置SID和DID,使得蓝牙芯片可以插空的“同时”发送多个不同类型的广播,比如可以“同时”发送可连接广播和不可连接广播,这样的功能对于Host的协议栈代码实现和Controller的实现有很大的帮助,Controller受限于硬件资源,支持的广播集的数量有限,这个需要在实际使用时,询问芯片原厂。
在4.2版本的蓝牙协议中,如果想要发送两个不同类型的广播数据的话,只能在Host层排队发送,发送完第一个类型的广播之后,再发送第二个类型的广播。但是5.0的广播集的概念,Host可以不用排队发送,他们只要设置为不同的广播集,Controller会插空的同时发送两个类型的广播,“插空”的意思是在发送广播集1的空闲的AdvInterval之间发送广播集2。
HCI接口定义:以上内容大致解释了蓝牙5.0的扩展广播的原理和内容,实际使用上还是通过HCI Command和HCI Event来实现的,因此我们下面介绍一下扩展广播的HCI。
4.2版本:广播相关:
扫描相关:
广播上报:
新增的5.0广播相关的HCI Command:
扫描相关:
广播上报:
周期广播的原理已经介绍过了,通过分析hci的调用方式,我们可以更加理解它的实现机制。我们分为两部分来解释,分为扫描部分和发送部分。扫描部分又分为获取周期广播SID,同步周期广播,获取周期广播的数据。
扫描部分:
LE Extended Advertising Report Event里面有一个字段叫做Periodic_Advertising_Interval[i],除了表示周期广播Interval之外,还可以表示这个广播集SID[i]代表着的是一个周期广播。
然后上层业务就可以根据需要,选择是否监听这个周期广播,如果需要监听的话,调用LE Periodic Advertising Create Sync Command,来通知Controller和这个周期广播建立同步关系。同步成功之后,会上报LE Periodic Advertising Sync Established Event事件,表示成功与对方的周期广播建立了同步关系,该Event中的Advertising_SID和Sync_Handle,表明了所同步的周期广播的SID和对应的handle,后面Host就可以通过Sync_Handle来操作这个同步接收的任务。
扫描到的周期广播的数据是通过LE Periodic Advertising Report Event进行上报的(并不是通过LE Extended Advertising Report Event),该Event里面包括了Sync_Handle来表示数据来自哪个周期广播。LE Periodic Advertising Sync Lost Event用来通知Host,与对方的周期广播已经同步失败了(timeout的时间内没有收到任何AUX_SYNC_IND)。
我推测,如果Host不调用Periodic Advertising Create Sync Command的话,Controller虽然可以知道有周期广播存在,但是不会按照周期广播的ChannelMap去解析它的AUX_SYNC_IND的包,只解析道AUX_ADV_IND,知道它指向一个周期广播就可以了,这样子也节省了扫描的资源,如果每个周期广播,Controller都去跟随扫描的话,那么Controller的扫描效率会大打折扣。
创建周期广播(发送部分):
关于HCI的接口这里面要再重提一下兼容性的问题,5.0版本的蓝牙协议定义了2套HCI的接口,这两套接口是可以同时存在的,一套是4.2的HCI Command,一套是5.0的新增的HCI Command,但这两套接口,Host不应该搅合起来用,也就说要不你就都用4.2的旧HCI Command,要不你就都用5.0的新HCI Command,LE Set Extended Scan Parameters Command和LE Set Advertise Enable Command这样的搭配使用是不被允许的。
疑问与解答:问题1:蓝牙5.0版本的Controller,是否可以与4.2版本的Host兼容。
回答:可以,5.0版本的Controller应该同时实现4.2版本和5.0版本的HCI Command。与4.2版本的Host一起使用时,使用4.2版本的HCI就可以了,但是这样就浪费了Controller的5.0的能力。
问题2 :蓝牙4.2版本的controller,是否可以与5.0版本的host兼容。
回答:理论上可以,但需要Host实现的很复杂,需要Host支持两套HCI Command,并且更难的是,要根据不同的Controller版本调整程序的实现架构,所以一般可以不用兼容,更好的方案是直接一个宏定义控制,或者有不同的分支版本来控制两套代码。Host可以使用发送Read Local Version Information Command来读取Controller的版本,从而选择不同的HCI Command和代码架构。
问题3:蓝牙5.0版本的controller + host芯片方案,是否可以与对端4.2版本的设备兼容。
回答:当然是可以的,5.0也可以收发4.2的广播包,并且比4.2更高效。
问题4:蓝牙5.0版本的controller + host芯片方案,是否可以指定发送legacy广播或者extend 广播。
回答:当然是可以的,可以配置发送legacy广播,还是extend广播,还是周期广播,可以设置PDU Type。
问题5:官方SIG Mesh Profile,是否支持通过蓝牙5.0版本协议,发送大payload的扩展广播。
回答:Mesh Profile虽然是在5.0协议发布之后才发布的,但是它为了更好的兼容性,加上本身就没有那么大的控制需求,所以从设计的角度,就没有考虑使用扩展广播发送大payload的数据包,至少1.0版本是如此,即将release的1.1版本也没有使用到扩展广播。
问题6:官方SIG Mesh Profile与蓝牙5.0版本协议的关系。
回答:这个问题可以从两个角度来看:从协议设计的角度来讲,可以说没有什么关系(1.0版本和1.1版本来看),mesh协议设计之初,就考虑到了要兼容4.2版本的蓝牙协议(广播消息有效的payload只有31个字节),因此我们现在看到的mesh协议才是现在这个样子,mesh协议为什么需要设计IV Update的过程,为什么不在每一包mesh消息数据都带着完整的4字节IV Index或者简单的增加seq number的字节数,一切的一切,都是为了兼容4.2版本的蓝牙协议。如果当时考虑到了使用5.0的扩展广播上实现SIG Mesh协议,就不应该设计IV Update的机制。因此可以得出一个结论,从SIG Mesh release出来的协议来看,到目前为止,它没有想过放弃4.2版本蓝牙,也没有考虑使用扩展广播来发送Mesh消息,也没有考虑过通过Mesh协议发送长包(目前1.0版本协议,和即将release的1.1版本协议,没有涉及到使用扩展广播发送Mesh协议,但据说2.0版本的Mesh协议会涉及一部分扩展广播的功能,但是只要它不放弃4.2,那么也仅仅是某些功能使用5.0的扩展广播)。如果有需求希望通过5.0的扩展广播发送长包,我建议在5.0的基础上,重新设计一套私有的Mesh协议;从HOST的代码实现的角度来看,蓝牙5.0和Mesh协议还是有关系的,因为5.0不仅支持大payload的扩展广播,也支持多广播(也就是多广播集),多广播这个特性,可以很大程度的简化Host的mesh协议相关的实现,Host可以同发送SNB和Mesh控制消息,并且可以很方便的设置发包个数和发包的Duration。
你是否还在寻找稳定的海外服务器提供商?创新互联www.cdcxhl.cn海外机房具备T级流量清洗系统配攻击溯源,准确流量调度确保服务器高可用性,企业级服务器适合批量采购,新人活动首月15元起,快前往官网查看详情吧
我们在微信上24小时期待你的声音
解答本文疑问/技术咨询/运营咨询/技术建议/互联网交流