#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
.