Сбой Bluetooth при использовании updateValue:forCharacteristic: onSubscribedCentrals в OS X

#ios #objective-c #macos #bluetooth #bluetooth-lowenergy

#iOS #objective-c #macos #bluetooth #bluetooth -низкое энергопотребление

Вопрос:

Я написал приложение для iOS, в котором устройство iOS является одновременно как центральным, так и периферийным устройством, и несколько устройств могут обмениваться данными. Я попытался перенести периферийную часть приложения в OS X. Проблема в том, что как только я пытаюсь передать данные с периферийного устройства OS X на iOS central через updateValue:forCharacteristic:onSubscribedCentrals , BTLE в OS X практически полностью выходит из строя.

Это означает:

1) компьютер OS X больше не воспринимается ни одним устройством iOS

2) диспетчер периферийных устройств больше ничего не делает — обратные вызовы не вызываются, ничего

3) Когда я перезапускаю приложение в OS X, peripheral manager никогда не меняет свое состояние на PoweredOn или любое другое состояние

4) Единственный способ заставить BTLE снова работать в OS X после этого — перезагрузка или использование sudo killall blued

Точно такой же код отлично работает на iOS, я понятия не имею, что происходит. В принципе, я делаю это:

 - (instancetype)init {
    self = [super init];
    dispatch_queue_t peripheralQueue = dispatch_queue_create("connichiwaperipheralqueue", DISPATCH_QUEUE_SERIAL);
    self.peripheralManager = [[CBPeripheralManager alloc] initWithDelegate:self queue:peripheralQueue];
    return self;
}

- (void)peripheralManagerDidUpdateState:(CBPeripheralManager *)peripheralManager {
    if (peripheralManager.state == CBCentralManagerStatePoweredOn) {
        [self.peripheralManager addService:self.advertisedService];
        [self.peripheralManager startAdvertising:@{ CBAdvertisementDataServiceUUIDsKey : @[[CBUUID UUIDWithString:BLUETOOTH_SERVICE_UUID]] }];
    }
}

- (void)peripheralManager:(CBPeripheralManager *)peripheral central:(CBCentral *)central didSubscribeToCharacteristic:(CBCharacteristic *)characteristic {
    if (characteristic == self.advertisedInitialCharacteristic) {
        [self _sendInitialToCentral:central];
    }
}

- (void)_sendInitialToCentral:(CBCentral *)central {   
    NSDictionary *sendDictionary = @{ /* some dictionary, but i've also tried with a short, simple string */ };
    NSData *initialData = [NSJSONSerialization dataWithJSONObject:sendDictionary options:NSJSONWritingPrettyPrinted error:nil];
    BOOL didSend = [self.peripheralManager updateValue:initialData forCharacteristic:self.advertisedInitialCharacteristic onSubscribedCentrals:@[central]];
}
  

, тогда как self.advertisedService это служба, которая содержит self.advertisedInitialCharacteristic и BLUETOOTH_SERVICE_UUID является идентификатором пользовательского интерфейса, который ищет устройство iOS.

Когда это выполняется, устройство iOS подключается к компьютеру OS X, обнаруживает службу, обнаруживает характеристику, а затем выполняется компьютер OS X _sendInitialToCentral: . Здесь, didSend становится true , но после этого BTLE в основном перестает что-либо делать на компьютере, и новое значение никогда не поступает на устройство iOS.

Есть идеи? Я делаю что-то не так? Я не вижу здесь проблемы. Работает OS X 10.9.3

Обновить

Просто хотел добавить, что я только что протестировал это на другом компьютере, и происходило то же самое.

Обновление 2

Найдена причина: Причина этой проблемы в том, что я передаю CBCentral в updateValue:forCharacteristic:onSubscribedCentrals: . Если я изменю последний параметр на nil , данные будут отправлены. Проблема в том, что мне нужно отправить данные в определенный центр, я не хочу их транслировать. У кого-нибудь есть идеи, что здесь происходит и как это исправить?

Комментарии:

1. Что находится в вашем словаре отправки? Я отмечаю, что вы говорите, что пробовали короткую строку, но насколько короткую? BLE ограничен 20 байтами за передачу

2. На самом деле, именно поэтому я попробовал это — на iOS, кажется, возможно отправить более 20 байт (не уверен, почему, но это работает). Но даже если я попробую использовать строку из одного символа (или пустую строку, если на то пошло), то то же самое произойдет в OS X. И самое странное, что это updateValue:forCharacteristic:onSubscribedCentrals возвращается true , так что, я думаю, это не должно быть проблемой с данными?

3. Да, кажется, что maximumUpdateValueLength свойство в CBCentral указывает, сколько байтов может быть записано с данными после этого усечения. Получаете ли вы что-нибудь в журналах OSX от blued?

4. Хорошая мысль. При запуске приложения я получаю blued[59087]: ****** properties = 0x10, permissions = 0x1, write? 0, w/o res? 0 сообщение, которое, похоже, соответствует рекламируемой характеристике. Однако при отправке данных ничего не регистрируется. Через некоторое время я получаю другое сообщение, но я не уверен на 100%, связано ли это: kernel[0]: **** [IOBluetoothHostControllerUSBTransport][SuspendDevice] -- Suspend -- suspendDeviceCallResult = 0x0000 (kIOReturnSuccess) -- 0x6000 ****

5. обнаружена проблема, смотрите мою правку

Ответ №1:

Просто чтобы ответить на это: похоже, это была ошибка в Mavericks. Эта проблема (и многие другие с BTLE) были полностью решены в Yosemite.

В Mavericks, похоже, что BTLE работает только при переходе nil к последнему параметру updateValue:forCharacteristic:onSubscribedCentrals .