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:), Это очень быстрый синхронный вызов, и вы обычно должны делать это перед вызовом scan​For​Peripherals(with​Services:​options:​),

Есть несколько других шагов, которые вы обычно должны делать. Точный порядок и логика немного зависят от вашей ситуации, но приведенная выше блок-схема показывает вам один подход. В основном это будет выглядеть примерно так:

  • Вызов retrieve​Peripherals(with​Identifiers:​) найти периферийное устройство, для которого вы уже знаете идентификатор. Обратите внимание, что это просто говорит вам, что система знает о периферийных устройствах; это не значит, что он сейчас рядом. призвание connect на этом никогда не получится.

  • Вызов retrieveConnectedPeripherals(withServices:) найти периферийное устройство, которое уже подключено к этому iPhone и рекламирует ваш сервис. Вам все еще нужно позвонить connect на это для вашего процесса, но он должен быть успешным.

  • Если все остальное терпит неудачу, тогда звоните scan​For​Peripherals(with​Services:​options:​),

Хорошо, я только что нашел решение своей главной проблемы. Так что любой, кто может иметь такую ​​же проблему:

  1. Как только вы подключитесь к устройству, помните, что это UUID
  2. Если вы хотите подключиться к нему, вам не нужно сканировать, просто используйте centralManager.retrievePeripherals(withIdentifiers: [the id's of the devices you know])
  3. Это вернет вам список 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

Другие вопросы по тегам