CoreBluetooth не обнаруживает монитор слуха, если сначала подключено другое приложение
Я хочу, чтобы мои пользователи могли отслеживать их пульс с помощью моего приложения. Поэтому я использую CBCentralManager
для этого. Все работает нормально, если к датчику сердечного ритма еще не подключено ни одно другое приложение. У меня проблема, если я сначала начну, например, Страву или Эндомондо. Тогда я просто не могу найти больше устройств. С другой стороны, все работает нормально, так что, я думаю, я что-то упустил?
Что я сейчас делаю:
Я создаю свой экземпляр CBCentralManager
вот так
centralManager = CBCentralManager(delegate: self, queue: DispatchQueue.main)
что приведет к срабатыванию метода делегата для соединения
func centralManagerDidUpdateState(_ central: CBCentralManager) {
let heartRateServiceUUID = CBUUID(string: "180D")
let services = [heartRateServiceUUID]
switch central.state {
case .poweredOn:
centralManager.scanForPeripherals(withServices: services, options: nil)
и оттуда на периферии не найдено.
Но опять же, когда я принудительно закрываю другие приложения, такие как Endomondo или Strava, а затем запускаю свое приложение, все работает нормально.
3 ответа
См. Рекомендации по взаимодействию с удаленным периферийным устройством для получения полной информации о том, как подключиться к устройствам, о которых вы уже знаете.
Основная проблема, с которой вы сталкиваетесь, заключается в том, что большинство устройств BLE прекращают рекламу, когда у них есть соединение. Так как они не являются рекламой, вы не можете увидеть их на скане. В этом конкретном случае устройство BLE подключено к iPhone, на котором вы работаете, но это ничего не меняет. Это все еще не реклама.
Чтобы справиться с этим, вы хотите спросить iPhone о подключенных устройствах, которые имеют услугу, которую вы хотите, используя retrieveConnectedPeripherals(withServices:)
, Это очень быстрый синхронный вызов, и вы обычно должны делать это перед вызовом scanForPeripherals(withServices:options:)
,
Есть несколько других шагов, которые вы обычно должны делать. Точный порядок и логика немного зависят от вашей ситуации, но приведенная выше блок-схема показывает вам один подход. В основном это будет выглядеть примерно так:
Вызов
retrievePeripherals(withIdentifiers:)
найти периферийное устройство, для которого вы уже знаете идентификатор. Обратите внимание, что это просто говорит вам, что система знает о периферийных устройствах; это не значит, что он сейчас рядом. призваниеconnect
на этом никогда не получится.Вызов
retrieveConnectedPeripherals(withServices:)
найти периферийное устройство, которое уже подключено к этому iPhone и рекламирует ваш сервис. Вам все еще нужно позвонитьconnect
на это для вашего процесса, но он должен быть успешным.Если все остальное терпит неудачу, тогда звоните
scanForPeripherals(withServices:options:)
,
Хорошо, я только что нашел решение своей главной проблемы. Так что любой, кто может иметь такую же проблему:
- Как только вы подключитесь к устройству, помните, что это UUID
- Если вы хотите подключиться к нему, вам не нужно сканировать, просто используйте
centralManager.retrievePeripherals(withIdentifiers: [the id's of the devices you know])
- Это вернет вам список
CBPeripherals
и вы просто подключаетесь к ним, как после поиска.
Единственное, чего я до сих пор не знаю: даже когда я удаляю Endomondo, сначала запускаю мое приложение, они все равно могут обнаружить мой монитор сердечного ритма... И я полагаю, даже если они помнят UUID, он будет в UserDefaults
я полагаю, что они не могут восстановить соединение, используя centralManager.retrievePeripherals(...)
, Так что я все еще хотел бы знать, что мне нужно изменить, чтобы это работало...
Обновление. Похоже, что чипсет BLE4.0 поддерживал только одно соединение, поэтому, когда центральный менеджер подключился к устройству BLE4.0, он прекратил рекламу и установил подключенный уровень.
В чипсете BLE4.1 добавлена поддержка многоцелевого соединения. Возможно, что датчик сердечного ритма использует более новую технику BLE, которая поддерживает более одного соединения. https://e2e.ti.com/blogs_/b/connecting_wirelessly/archive/2016/11/30/bluetooth-low-energy-multi-role-demystified
До сих пор неясно, почему ваше приложение не подключается, если подключены другие приложения. Можете ли вы опубликовать весь свой код?
Мой старый ответ:"Базовые Bluetooth и Bluetooth Low Energy могут обрабатывать только одно соединение для каждого периферийного устройства, что означает, что если ваше приложение (CBCentralManager) устанавливает соединение с периферийным устройством (UUID), оно устанавливает уровень сообщений между центральным и периферийным устройствами, так что другие приложения не может помешать подключению к этому периферийному устройству, если вы не отключите первое приложение. Так работает Bluetooth Low Energy."
Руководства и примеры Apple: https://developer.apple.com/library/content/documentation/NetworkingInternetWeb/Conceptual/CoreBluetooth_concepts/AboutCoreBluetooth/Introduction.html
Apple Core Bluetooth API: https://developer.apple.com/reference/corebluetooth