如果BLE服务包含GATT客户端表示兴趣的多个通知特征,那么BLE协议是否对GATT客户端收到更新值的订单有很大的保证?另外,对GATT客户端将新接收的数据提供到应用程序的顺序是否有任何协议级别的要求?
例如:说该应用程序在“安静”期间的连接事件之间快速连续的连续性更改Gatt服务器中两个单独特征的值。在下一个连接事件中,假设Gatt服务器有足够的时间和带宽,可以将两个更新的特征值全部传输到Gatt客户端。
BLE协议是否要求GATT服务器以应用程序更改的顺序传输新变化的值?
此外,BLE协议是否要求GATT客户端将这些新变化值的顺序保留到应用程序中?
我认为所有支持Bluetooth 5.0的BLE堆栈,但是很高兴知道此类版本是否已经改变了以前的版本。协议标准本身的任何特定引用将非常有帮助!
上述所有这些问题的答案也许令人惊讶的是“不适用”。当您阅读该标准时,软件库/sdk/api 实现由一个人编写的 GATT“核心”部分,然后由另一个人利用该库/sdk/api 编写单独的应用程序的整个概念根本不存在。蓝牙标准只是一个协议标准,即规定了两个设备如何相互通信的要求,而不是应用程序内部如何构造和实现的要求。请参阅蓝牙核心规范(当前版本为 5.4)中 GATT 章节第 2.1 节的协议栈图:
如您所见,GATT是“应用程序”配置文件,ATT是您的应用程序所说的协议。如果您有一个内部管理队列的软件库,请派遣命令/通知到正确的线程等,以使您的工作更容易,那么这不是蓝牙标准的一部分,并且在此库中的任何愚蠢的设计错误都限制了协议的使用。 /最终应用程序开发人员的个人资料应该被视为“缺失功能”,而不是协议漏洞。
然而,在某些情况下,该标准会建议一些允许的实施细节。在 ATT 章节中,您可以阅读“在非增强型 ATT 承载上,收到但由于缓冲区溢出而无法处理的通知应被丢弃。因此,这些 PDU 必须被视为不可靠”。
为了回答这个问题,我将做出与标准相同的假设,即应用程序可以直接访问将 GATT 通知作为 ATT 数据包发送到下层 (L2CAP),并且 GATT 客户端直接接收 ATT 通知与从下层 (L2CAP) 接收的顺序相同。
在通知方面,ATT 协议和 GATT 配置文件标准都没有提及任何有关有序交付的内容。相反,在推理有序交付时,通常会考虑底层协议。
在蓝牙4.0-5.1中,仅存在“Unenhanced ATT bearer”,它是按顺序传递数据的固定L2CAP通道。因此,您至少可以在协议级别上期待有序交付。例如,HID 配置文件或多或少假定有序交付。否则,击键顺序可能会不正确。
在蓝牙 5.2 中,引入了“增强型 ATT 承载”,以允许多个并发 ATT 事务(每个通信通道一个),这旨在加快同一设备上运行的多个“应用程序”与同一远程设备进行通信的情况。请注意,一次只能执行一个读请求或写请求,并且必须在收到前一个请求或写请求的响应后发送下一个请求。如果两个设备都支持此功能,并且您已向同一设备打开多个 ATT 承载,则如果通知通过单独的 ATT 承载发送,则您不能假定通知将传递到另一台设备的任何特定顺序,因为它们有自己的流量控制。因此,如果您需要有序交付,只需对这些通知使用相同的 ATT 承载即可。
实际上,据我所知,所有实现 GATT 的软件库都不会重新排序属于同一特征的通知。例如,在 Android 上,Binder 机制用作蓝牙守护程序和每个应用程序之间的 IPC 层。此处,在收到特定 BluetoothGatt 对象的通知时调用的回调将不会再次调用,直到同一 BluetoothGatt 对象的先前方法调用返回。
然而,在 Windows 上,我上次检查时,每次开始监听通知时,都会启动一个新线程,每当收到通知时,您的事件处理程序就会在该线程上运行。由于在监听通知时只能指定监听一个特征,因此如果有两个特征,则需要设置两个单独的监听器,因此将启动两个线程,每个线程处理每个特征。对于两个线程,不可能同步传送通知的顺序,因为两个线程可以在两个不同的 CPU 核心上同时运行。在我看来,这是限制使用的“愚蠢”设计错误之一。
因此,作为建议,如果您需要保证通知按照发出的顺序传递和处理,请使用一个特征,通常应该没问题。