BLE低功耗蓝牙的广播内容

BLE广播的原理

BLE的设备可以发出广播信号,其信号占用的通道是37,38,39通道


image.png

设备可以选择广播在其中的任何一个,两个或全部三个通道


image.png

其广播包的格式为
image.png

BLE4.0-BLE4.2支持的最大广播payload包长是31字节;BLE5.0增加了扩展模式,以数据通道发送额外的数据,使得广播支持的最大payload包长是254字节。

广播内容和扫描内容

除了广播的31字节以外,还支持在扫描回复内容中包含最多31字节的数据。
这两者的区别是:广播的内容会持续定期发送,不管有没有接收者;而扫描回复内容只有在主机发送扫描命令后,设备才会在扫描回复中携带此内容
以下是一个典型的广播-扫描-回复过程。

image.png

一般来讲,在上层软件中,会将广播内容和扫描回复内容统一处理成设备的广播信息,并从中提取出相关字段。

广播字段的定义

广播内容和扫描回复内容的格式定义是通用的。都是长度+数据的方式,其中数据又分成类型+实际数据,如下图

image.png

在蓝牙官方协议中定义了各种类型的含义。
常用的有:格式定义字段(Flags), UUID字段,设备名称字段,厂商自定义字段等
这些字段中,除了格式定义字段是必须存在,且需要放在广播内容中,其他字段都是可选的,并且位置并不重要,放在广播内容或扫描回复内容中都可以,效果基本相同。

格式定义字段

格式定义字段(Flags)是一个字节的配置字段,是唯一一个必须包含的字段,用于指示设备是否可以被搜到、是否支持传统蓝牙,是否支持可被连接等。

UUID字段

UUID是一种唯一代号,一般每个service会对应一个UUID,一个设备可以有多个UUID。


image.png

一个完整的UUID是128bit,也可以以32bit或16bit缩写的方式表示。
通过此字段,可以选择将全部或部分UUID广播出来。

名称字段

名称字段(Local Name)决定了设备在手机中搜索出来的名字

注意,虽然安卓使用上述字段,iPhone可能不使用此字段,而使用ATT协议中的名称字段作为设备名称显示出来

厂商自定义字段

厂商自定义字段(Manufacturer Specific Data)是我们可以自己定义其内容的字段。其中也预定义了一些厂商,在Bluetooth官方网站可以查到,这些都是交了会员费的成员。
如果我们自己用,也可以完全自定义內容

一些第三方软件,例如微信,并不支持获取所有字段的内容,但是一般都会支持显示厂商自定义信息。所以需要传输一些自定义信息时,使用厂商自定义字段是比较合适的。

其他字段

其他字段可以参考蓝牙标准,或者其他网站说明。

长度限制

注意:广播和扫描字段内容均不能超过31字节,并且要特别注意每个字段中的Length要与Data匹配,否则可能会造成某些手机能搜到广播某些搜不到的奇怪现象。

CC264x中设置和修改蓝牙广播内容

初始化设置

CC264x中,广播内容和扫描回复内容要分别设置。
定义两个数组缓冲

// Advertisement data, 最多31字节
uint8_t advData[] =
{
  0x02
  ,GAP_ADTYPE_FLAGS
  ,GAP_ADTYPE_FLAGS_BREDR_NOT_SUPPORTED | GAP_ADTYPE_FLAGS_GENERAL
...
}
uint8_t scanResData[] =
{
...
}

使用GapAdv_loadByHandle()函数加载缓冲内容

GapAdv_loadByHandle(advHandle, GAP_ADV_DATA_TYPE_ADV, sizeof(advData), advData);
GapAdv_loadByHandle(advHandle, GAP_ADV_DATA_TYPE_ADV, sizeof(scanResData), scanResData);

之后调用GapAdv_enable()打开广播即可

修改内容

如果在广播已经开启后,要修改广播内容,有两种方法
方法一:使用GapAdv_prepareLoadByHandle()和GapAdv_loadByHandle()方法

// 更改前的准备,GAP_ADV_FREE_OPTION_DONT_FREE指示不释放原内容。对广播和扫描同时生效。
GapAdv_prepareLoadByHandle(advHandle, GAP_ADV_FREE_OPTION_DONT_FREE)
// 修改缓冲内容
advData[..] = ...
scanResData[..] = ...
...
// 重新装载缓冲
GapAdv_loadByHandle(advHandle, GAP_ADV_DATA_TYPE_ADV, sizeof(advData), advData);
GapAdv_loadByHandle(advHandle, GAP_ADV_DATA_TYPE_ADV, sizeof(scanResData), scanResData);

方法二:使用GapAdv_prepareLoadByBuffer() 和 GapAdv_LoadByBuffer()方法

// 更改前的准备,FALSE指示不释放原内容。对指定缓冲生效。
GapAdv_prepareLoadByBuffer(advData, FALSE)
// 修改缓冲内容
advData[..] = ...
...
// 重新装载缓冲
GapAdv_loadByBuffer(sizeof(advData), advData);

注意:对于某些SDK(例如CC13x2_26x2 SDK 3.20.00.68, 3.40.00.02),有已知BUG,方法二只能用于更新广播,而不能用于更新扫描数据。

参考文章

https://blog.csdn.net/slimmm/article/details/100583655
https://blog.csdn.net/zzfenglin/article/details/56064808
https://www.novelbits.io/bluetooth-low-energy-advertisements-part-1/
https://www.novelbits.io/bluetooth-low-energy-advertisements-part-2/
https://stackoverflow.com/questions/40250621/does-the-ble-spec-allow-for-manufacturer-ad-type-in-both-advertising-data-and-sc
https://stackoverflow.com/questions/33535404/whats-the-maximum-length-of-a-ble-manufacturer-specific-data-ad
https://e2e.ti.com/support/wireless-connectivity/bluetooth-group/bluetooth/f/bluetooth-forum/845470/cc2642r-updating-scan-response-data-via-gapadv_loadbybuffer

你可能感兴趣的:(BLE低功耗蓝牙的广播内容)