如何在 CBPeripheralManager 处于活动状态时提高 CBCentralManager 的性能
How to improve performance of CBCentralManager while CBPeripheralManager is active
我们创建了一个 iOS 应用程序,它实现了 CBCentralManager 以连接到我们创建的以 10Hz 传输数据的设备。数据快速通过并显示非常重要,因此我们围绕此建立了严格的延迟检查,如果遗漏了太多点,或者如果本地时钟检测到传入值变慢,我们将出错并断开连接。
客户要求我们实施第二个 iOS 应用程序来观察第一个应用程序。我们在原来的应用程序中实现了一个 CBPeripheralManager,它可以广告,可以连接,并且会定期将其数据发布到一些传出特征。
我们发现我们似乎无法将观察者 iOS 应用程序连接到原始 iOS 应用程序(即,原始 iOS 应用程序同时具有 CBCentral 连接到设备和 CBPeripheral 与观察者应用程序的连接同时处于活动状态),而不会触发我们对来自设备的传入数据的延迟检查。
我已经尝试了所有我能想到的,我为CBPeripheralManager和CBCentralManager使用了单独的队列,如下:
q = dispatch_get_global_queue(QOS_CLASS_UTILITY, 0);
ptr_CBPeriphMgr = [[CBPeripheralManager alloc] initWithDelegate:self queue:q];
此外,
- 我记录并标记了所有内容,验证了 none 我的代码花费的时间太长
- 我将几乎所有代码都移出了 BLE 处理程序,使它们 非常 轻便且不阻塞,
- 我尝试了低优先级的单独队列(如上所示的示例)
- 我已经尝试将我的 CBPeripheralManager 数据速率减慢到涓涓细流,每秒更新几次
- 我曾尝试在建立 CBPeripheralManager 连接后暂停延迟检查三秒钟(这非常不理想),但问题似乎是随机出现的,而不仅仅是在连接之后。
似乎无论我尝试什么,外围和中央连接都处于活动状态 4-5 分钟后(我们有一个循环,其中第二个 App 每五秒重复连接和断开连接,以挑战设备连接)我从设备到中央的传入值更新速度减慢到大约 1/4 或 1/5 速度,或者它们停止整整一秒,然后几乎同时出现三到四个更新——这两个都触发了我们的延迟检查。这就像一些队列被填满并且性能停滞不前,但正如我上面提到的,我认为我正在使用单独的队列。
我无计可施...有没有人想过如何在 iOS 应用程序中优先考虑我的核心功能而不是我的外围功能,或者以某种方式提高性能以防止这种情况发生一个问题并使我的应用程序响应来自设备的 10Hz 更新,即使在被观察为外围设备时也是如此?
(编辑声明我们是 connecting/disconnecting 重复的第二个应用程序......也许我在断开连接后没有正确清理,垃圾堆积起来并搞砸了 BLE?这可以解释为什么无论第二次连接上的数据更新频率如何,问题似乎都会在 4-5 分钟后出现。)
这里有一些建议:
- 尝试使用
QOS_CLASS_USER_INITIATED
或更高版本而不是 QOS_CLASS_UTILITY
创建队列。
- 确保在不需要扫描外围设备时调用
-[CBCentralManager stopScan]
,并且在不需要为传入连接做准备时调用 -[CBPeripheralManager stopAdvertising]
(可能在连接时) .
- 调用
-[CBPeripheralManager setDesiredConnectionLatency:forCentral:]
预留更多资源。
但是,如果您可以针对 iOS 11+,我建议使用 L2CAP 通道来减少延迟并提高速度。虽然没有很好地记录 CoreBluetooth 的 L2CAP 支持,但这里有一个 list of the available APIs.
我们创建了一个 iOS 应用程序,它实现了 CBCentralManager 以连接到我们创建的以 10Hz 传输数据的设备。数据快速通过并显示非常重要,因此我们围绕此建立了严格的延迟检查,如果遗漏了太多点,或者如果本地时钟检测到传入值变慢,我们将出错并断开连接。
客户要求我们实施第二个 iOS 应用程序来观察第一个应用程序。我们在原来的应用程序中实现了一个 CBPeripheralManager,它可以广告,可以连接,并且会定期将其数据发布到一些传出特征。
我们发现我们似乎无法将观察者 iOS 应用程序连接到原始 iOS 应用程序(即,原始 iOS 应用程序同时具有 CBCentral 连接到设备和 CBPeripheral 与观察者应用程序的连接同时处于活动状态),而不会触发我们对来自设备的传入数据的延迟检查。
我已经尝试了所有我能想到的,我为CBPeripheralManager和CBCentralManager使用了单独的队列,如下:
q = dispatch_get_global_queue(QOS_CLASS_UTILITY, 0);
ptr_CBPeriphMgr = [[CBPeripheralManager alloc] initWithDelegate:self queue:q];
此外,
- 我记录并标记了所有内容,验证了 none 我的代码花费的时间太长
- 我将几乎所有代码都移出了 BLE 处理程序,使它们 非常 轻便且不阻塞,
- 我尝试了低优先级的单独队列(如上所示的示例)
- 我已经尝试将我的 CBPeripheralManager 数据速率减慢到涓涓细流,每秒更新几次
- 我曾尝试在建立 CBPeripheralManager 连接后暂停延迟检查三秒钟(这非常不理想),但问题似乎是随机出现的,而不仅仅是在连接之后。
似乎无论我尝试什么,外围和中央连接都处于活动状态 4-5 分钟后(我们有一个循环,其中第二个 App 每五秒重复连接和断开连接,以挑战设备连接)我从设备到中央的传入值更新速度减慢到大约 1/4 或 1/5 速度,或者它们停止整整一秒,然后几乎同时出现三到四个更新——这两个都触发了我们的延迟检查。这就像一些队列被填满并且性能停滞不前,但正如我上面提到的,我认为我正在使用单独的队列。
我无计可施...有没有人想过如何在 iOS 应用程序中优先考虑我的核心功能而不是我的外围功能,或者以某种方式提高性能以防止这种情况发生一个问题并使我的应用程序响应来自设备的 10Hz 更新,即使在被观察为外围设备时也是如此?
(编辑声明我们是 connecting/disconnecting 重复的第二个应用程序......也许我在断开连接后没有正确清理,垃圾堆积起来并搞砸了 BLE?这可以解释为什么无论第二次连接上的数据更新频率如何,问题似乎都会在 4-5 分钟后出现。)
这里有一些建议:
- 尝试使用
QOS_CLASS_USER_INITIATED
或更高版本而不是QOS_CLASS_UTILITY
创建队列。 - 确保在不需要扫描外围设备时调用
-[CBCentralManager stopScan]
,并且在不需要为传入连接做准备时调用-[CBPeripheralManager stopAdvertising]
(可能在连接时) . - 调用
-[CBPeripheralManager setDesiredConnectionLatency:forCentral:]
预留更多资源。
但是,如果您可以针对 iOS 11+,我建议使用 L2CAP 通道来减少延迟并提高速度。虽然没有很好地记录 CoreBluetooth 的 L2CAP 支持,但这里有一个 list of the available APIs.