iOS Bluetooth с низким энергопотреблением ANCS: "3 удара, и все готово"
У нас есть периферийное устройство BLE, которое подписывается на ANCS. Он также содержит несколько пользовательских сервисов, к которым подключается наше приложение.
Из-за ANCS подключение к периферийному устройству (xxx) должно быть сделано в приложении "Настройки". Таким образом, у нас нет никаких средств из приложения для инициирования соединения BLE. Это также обеспечивает чистоту UseEx и уменьшает "угловые случаи".
Идея заключается в том, что пользователь подключается в приложении "Настройки". Затем, если периферийное устройство выходит за пределы диапазона, iOS автоматически переподключится, как только вернется в диапазон.
Однако клиент обнаружил, что часто периферийное устройство не будет переподключаться после, скажем, выхода из комнаты.
Мы можем надежно воспроизвести это, только поместив периферийное устройство BLE в металлическую коробку на расстоянии примерно 15 метров от iPhone. Открывая и закрывая корпус с нужной скоростью, мы можем вызвать серию неудачных запросов на соединение ANCS в течение примерно 10 секунд.
Вот некоторые журналы консоли устройства, показывающие первое неудачное соединение из-за потери сигнала.
Mar 18 16:38:05 afes-iPhone BTLEServer[107] <Notice>: (Note ) Central "xxx" is now subscribed to characteristic "ANCS Data Source"
Mar 18 16:38:07 afes-iPhone BTServer[68] <Error>: Core Connection timed out to device "xxxxxxx"
Mar 18 16:38:07 afes-iPhone BTLEServer[107] <Notice>: (Note ) Peripheral "xxx" is now disconnected: Error Domain=CBErrorDomain Code=6 "The connection has timed out unexpectedly." UserInfo=0x14528470 {NSLocalizedDescription=The connection has timed out unexpectedly.}
Mar 18 16:38:07 afes-iPhone BTLEServer[107] <Notice>: (Note ) Connecting peripheral "xxx"...
Mar 18 16:38:07 afes-iPhone BTLEServer[107] <Notice>: (Note ) Central "xxx" is now unsubscribed from characteristic "ANCS Notification Source"
Mar 18 16:38:07 afes-iPhone BTLEServer[107] <Notice>: (Note ) Central "xxx" is now unsubscribed from characteristic "ANCS Data Source"
Mar 18 16:38:08 afes-iPhone BTLEServer[107] <Notice>: (Note ) Peripheral "xxx" is now connected
Mar 18 16:38:08 afes-iPhone Preferences[164] <Warning>: (Warn ) CoreBluetooth: API MISUSE: <CBPeripheral: 0x14da8170, identifier = xxxxxx, name = xxx, state = disconnected> can only accept commands while in the connected state
....
Mar 18 16:38:09 afes-iPhone BTServer[68] <Error>: Core Connection timed out to device "xxxxxxxxx"
Mar 18 16:38:09 afes-iPhone BTLEServer[107] <Notice>: (Note ) Peripheral "xxx" is now disconnected: Error Domain=CBErrorDomain Code=6 "The connection has timed out unexpectedly." UserInfo=0x1453daf0 {NSLocalizedDescription=The connection has timed out unexpectedly.}
Mar 18 16:38:09 afes-iPhone BTLEServer[107] <Notice>: (Note ) Connecting peripheral "xxx"...
Mar 18 16:38:09 afes-iPhone BTLEServer[107] <Notice>: (Note ) Peripheral "xxx" did not use any built-in service, strike #1
...
И если мы продолжим только правильное открытие и закрытие нашего металлического ящика, мы можем выполнить одно и то же "API MISUSE" три раза подряд.
В результате появляются следующие сообщения:
Mar 18 16:38:12 afes-iPhone BTLEServer[107] <Notice>: (Note ) Peripheral "xxx" did not use any built-in service, strike #2
...
Mar 18 16:38:16 afes-iPhone BTLEServer[107] <Notice>: (Note ) Peripheral "xxx" did not use any built-in service, strike #3
...
Кажется, это алгоритм "три удара, и вы вышли", который затем помещает периферийные устройства в "серый список". Время должно быть в пределах примерно 11 секунд. Мы не можем замедлить наши допросы, или мы идем против 30-секундного обмена ключами с перерывами в паре.
Этот серый список означает, что iOS больше не будет разрешать повторное подключение этого периферийного устройства к ANCS без открытия пользователем настроек и подключения к нему вручную.
Это означает, что CBCentralManager - retrieveConnectedPeripheralsWithServices: метод не будет извлекать периферийное устройство, поскольку оно больше не подключено.
Нам пришлось добавить обходной путь, посредством которого мы теперь сохраняем UDID любых ранее увиденных периферийных устройств, а затем при обратном вызове didDisconnectPeripheral, который мы повторно подключаем, используя - retrievePeripheralsWithIdentifiers:
Однако, чтобы поддерживать непрерывность соединения ANCS, нам также пришлось добавить центральный режим Bluetooth UIBackground в Info.plist, чтобы переподключение производилось после получения didDisconnectPeripheral с приложением в фоновом режиме. Конечно, если приложение выгружено, то без сохранения и восстановления состояния соединение ANCS снова будет разорвано.
Для правильной оценки мы также используем сторожевой таймер для периодической проверки состояния соединения, когда на переднем плане.
Мы можем воспроизвести эффект только с трудом, наш клиент, кажется, может видеть его очень часто, это правда, что ненадежность соединения вероятна для устройств BLE.
Мы могли бы сделать наше приложение намного более энергоэффективным и разрабатывать его с гораздо меньшими усилиями, если бы ANCS обрабатывался более надежно в iOS.
Используемые устройства - iPhone 4S и iPhone 6 на iOS 8.1 и 8.2.
Вопрос: кто-нибудь еще видел такое поведение с ANCS?