BLE模式和配置文件(原文)
本文档探讨了BLE如何工作,特别是如何将两种BLE模式(连接和广告)用于不同的目的。
外围设备和中央设备vs服务器和客户端
当我们通过BLE连接设备时,我们将它们视为外设(从设备)设备或中央(主设备)设备。 蓝牙标准建立了该区分方式以匹配设备上可用的资源:
- 主设备/中央
通常将具有更多的计算资源和可用能量 - 例如计算机或平板电脑。
- 从设备/外设
一个mbed设备 - 将在计算资源和能源两个方面受限制。
目前,mbed的BLE_API支持创建外设。 我们计划尽快将其扩展到中央设备。
BLE使用两个附加术语来描述连接实体 - 服务器和客户端:
- 服务器
该设备具有希望共享的信息,且对于BLE而言通常是外设(如mbed板子)。
- 客户端
需要信息和服务的设备,且对于BLE而言通常是中央设备 - 例如电话。
在讨论信息交流时,我们使用术语服务器和客户端 。 我们使用中央和外设来表示BLE连接的起点和目标。 中央作为客户端连接,外围设备作为服务器并不罕见。
mbed板是服务器或外设;手机是客户端和中央设备“)
启动连接
中央启动,控制和结束连接 - 外设不能强制中央执行(扫描BLE设备,查看其信息,连接等)。 中央还决定询问外围设备的频度。 然而,外设可以向中央推荐一些东西。 有关这些决定的更多信息,请参阅连接参数部分 。
广告和连接模式
BLE使用的两种模式是:
- 广告模式
外设会发出该区域任何设备可以接收到的信息。 这是中央设备如何知道周围有外围设备的方式。
- 连接模式
外设和中央设备建立一对一的对话。 这就是他们如何交换复杂的信息的方式。
中央设备必须知道外围设备存在才能与之连接。 因此,外设将使用BLE 广告模式发布其存在。 在这种模式下,设备使用通用访问配置文件 (GAP)以稳定的速率发送一些信息 —— 一个广告。 这个广告是其他设备,像你的手机,接收到的。 它告诉他们附近有一个BLE设备存在,以及该设备是否愿意与他们交谈。
广告模式数据包大小非常有限。 GAP广播的一般数据包格式如下图所示:
每个BLE包可以包含最多47个字节(这不是很多),我们不能使用它们的全部:
为了自己的目的,BLE协议栈需要8个字节(1 + 4 + 3)。
因此,广告分组数据单元(PDU)最多具有39个字节。 但是BLE栈再次需要一些开销,占用8个字节(2 + 6)。
-
PDU的广告数据字段剩下31个字节,分为广告数据(AD)结构。 然后:
GAP广播必须包含告诉设备有关我们发送的广告类型的标志。 标志结构总共使用三个部分(一个用于数据长度,一个用于数据类型,一个用于数据本身)。 我们需要前两个字节(数据长度和类型指示)的原因是帮助解析器来使用我们的标志信息正常工作。 我们还剩下28个字节。
现在我们终于用自己的数据结构发送自己的数据了 - 但是它也需要一个长度和类型的指示(总共两个字节),所以我们只剩下26个字节。
所有这些意味着我们只有26B用于通过GAP发送的数据。
如果您想查看AD的示例,请参阅自定义GAP广告部分中的扩展说明。
对于许多应用,广告可能是需要的一切。 这可能是:
- 外围设备只想周期性地广播可以适应广告的少量信息。
- 无论身份验证如何,这些数据都可用于范围内的任何中央设备。
但是,有时候,您需要提供比单向数据传输更多的信息或更复杂的交互。 为此,您需要在BLE设备和用户的手机,平板电脑或计算机之间设置“对话”。该会话基于连接模式 ,其描述了仅两个设备之间的关系:BLE外围设备和中央设备。
目前,广告和连接模式还不能共存。 这是因为BLE外围设备一次只能连接到一个中央设备(如移动电话)。 连接建立的时刻,BLE外设将停止广告。 在这一点上,没有其他中央设备能够连接到它,因为如果它不广告,他们不能发现该设备在那里。 只有在第一个连接终止并且BLE外围设备再次开始广告之后,才能建立新的连接。
注意:最新的蓝牙标准允许广告并行连接,这将在2015年底之前成为mbed的BLE_API的一部分。
服务和配置文件(GATT)
为了使上述通信的功耗较低,BLE规范在连接模式下交换数据的方式施加了特定的结构。 它依赖于BLE外设维护客户端可以访问的状态变量数据库(如电池电量,温度和时间)的能力。 我们可以根据功能将状态变量分组到服务中。 例如,心率服务是状态变量的集合,包括心率测量和身体传感器位置。 这些状态变量的技术术语是“特征(Characteristics)”。 为了互操作性,每个特征(Characteristics)也包含了值类型的描述。 这样客户端就可以解释这个值,即使它们没有被特别编程来识别它。
服务,特征及其配套属性是连接方式的基本实体。 服务使用通用属性配置文件(Generic Attribute Profile,GATT)根据特征来组织信息。 我们将在下面更详细地探索特征。
我们将服务捆绑到一个配置文件中 。 例如,心率配置文件(Heart Rate Profile)包括两个服务 - 心率和设备信息(Heart Rate and Device Information),血压配置文件(Blood Pressure Profile)包括血压和设备信息(Blood Pressure and Device Information)服务。
BLE已经有一段时间了,所以它有一些标准的服务,你可以进入。 回到我们的心率监测器的例子,心率服务是完善的,易于使用。 它可以从BLE心率监测器读取信息并将其发送到应用程序。 你会在稍后的编码示例中看到。
在开始研究项目之前,值得看看是否已经有可以完成所需功能的服务了; 它会节省大量的编码和测试时间。 您可以在这里找到可用的配置文件和服务列表。
特征和相互作用
服务将数据分解为特征 。 每个特征映射到单个数据点:它告诉你一件事,只有一件事。 例如, 设备信息服务具有以下特征:
- 制造商名称
- 型号
- 序列号
- 硬件版本
- 固件版本
- 软件版本
- 系统ID
- IEEE 11073-20601监管认证资料清单(regulatory certification data list)
这些特征中的每一个应该只包含其标签所包含的信息。 他们一起揭示设备的制造商信息,并组成一个完整的设备信息服务。 此服务本身捆绑在不同的配置文件中。
在mbed上创建一个特征非常简单,因为BLE_API为涉及服务定义的实体提供C++抽象。 例如,这里我们创建一个简单的特征,通知客户一个按钮的状态(按下/释放):
//button initial state
bool buttonPressed = false;
//read-only characteristic of type boolean,
//accepting the buttonState’s UUID and initial value
ReadOnlyGattCharacteristic buttonState(BUTTON_STATE_CHARACTERISTIC_UUID,
&buttonPressed);
有关mbed的特征创建的完整展示,请参阅我们的输入服务模板 。
特征完全由其声明,值和描述符定义:
声明包含有关特征的数据,例如其通用唯一标识符(UUID)。
值是特征的“有趣”部分:它是包含您正在查看和响应的数据的值。
** 描述符**不是强制性的; 您可以使用它来提供有关特征的更多信息或控制其行为。 例如,在使用通知时使用描述符。
特征可以是静态的(如设备的制造商名称)或动态的。 如果一个特征是动态的,当设备有新的信息时,您的设备可以为它生成一个新的值。 例如,在心率服务中, 当前心率是定期获得新值的特征。
以下是创建读/写特征(可以接收新值并显示其当前值的特征)的示例:
bool initialValueForLEDCharacteristic = false;
ReadWriteGattCharacteristic ledState(LED_STATE_CHARACTERISTIC_UUID,
&initialValueForLEDCharacteristic);
有关在mbed上创建读/写特征的信息,请参阅我们的执行器服务模板 。
一些特征是双向实体。 这意味着服务器(BLE外设)可以自己更新,也可以从客户端(手机)接收新的值。 这种双向流量使BLE具有交互性:用户向一个或多个特征发送新值,并且设备响应这些新值。 例如,当UriBeacon设备打开时,它进入临时配置模式(configuration mode) ,让我们有机会更新其特征的值(包含稍后公布的数据)。
对于每个特征,服务定义说明客户端是否有权写入该特征。 这是在外设上设置GATT服务器时完成的。 在我们的示例中, 配置模式(configuration mode)指出广告信息是可读/写的, 广告模式表示它是只读的。 因此,根据设备的模式,相同的特征可以具有两种不同的权限。
UUID
每个服务和特征都需要一个普遍唯一的标识符(UUID),它们在声明中列出(如上所述)。 对于BLE官方实体,UUID为16位,BLE站点上提供了完整的列表,以获取服务和特性 。 对于您自己创建的服务和特征,您将需要128位UUID; 您可以在UTI网站上生成。
有关UUID分配的更多信息,请参见我们的服务创建示例 。
配置文件,服务和特征的总结
因此,配置文件的完整拆分是:一个或多个服务,每个服务包含零个或多个特征,每个特征具有零个或多个描述符: