2014-09-19 3 views
13

Я пишу приложение iOS для связи с устройством BLE. Устройство может изменять имена между соединениями (не во время соединения BLE), но iOS отказывается изменять имя устройства.Неверное имя периферийного устройства BLE с iOS

Например: я могу подключиться к устройству, когда его имя - SadName. Я отключу его, выключу приложение и т. Д. И изменив имя устройства на HappyName. Но, когда я просматриваю устройства, iOS по-прежнему показывает периферийное имя как SadName.

Если отладить приложение и посмотреть на:

(void)centralManager:(CBCentralManager *)central didDiscoverPeripheral:(CBPeripheral *)peripheral advertisementData:(NSDictionary *)advertisementData RSSI:(NSNumber *)RSSI 

значение peripheral.name является SadName, так что я не думаю, что это то, что я интерпретирую неправильно в коде. Следует отметить, что при сканировании устройств, мой код:

[self.CM scanForPeripheralsWithServices:nil options:0]; // Start scanning 

Я предполагаю, что это просто потому, что устройства UUID это же так прошивкой тянет его из кэшированных списка устройств, но я хочу переопределите это.

Мысли? Извините, я новичок в iOS. Cheers - MSchmidtbauer

+0

Спасибо за ответы всем. У вас, ребята, было много замечательных моментов, и я смог найти способ, который хорошо работал, удаляя рекламные данные. Ура! ~ MSchmidtbauer – MSchmidtbauer

ответ

21

API-интерфейс CoreBluetooth для iOS SDK не дает возможности принудительно обновить периферийное имя.

В настоящее время невозможно использовать имя периферийного устройства в iOS при изменении имени устройства в BLEdevice.

компании Apple предлагает сканировать для конкретного устройства, указав список объектов CBUUID (содержащих один или несколько UUID, услуг), которые вы передаете scanForPeripheralsWithServices:

NSArray *services = @[[CBUUID UUIDWithString: @"2456e1b9-26e2-8f83-e744-f34f01e9d701"] ]; // change to your service UUID! 
NSDictionary *dictionary = [NSDictionary dictionaryWithObject:[NSNumber numberWithInt:1] forKey:CBCentralManagerScanOptionAllowDuplicatesKey]; 

[self.manager scanForPeripheralsWithServices:services options:dictionary]; 

Это уменьшает количество вызовов didDiscoverPeripheral. Не просто передавайте nil на scanForPeripheralsWithServices. Он также позволяет вашему приложению сканировать периферию в фоновом режиме.

Если вы ищете способ передачи динамической информации, доступной до установления соединения, вы можете использовать Рекламные или сканирующие данные ответа. Периферийное устройство может быть настроено для вещания записей под названием Локальное имя и Данные изготовителя. Эти данные в доступна: didDiscoverPeripheral:

- (void)centralManager:   (CBCentralManager *)central 
didDiscoverPeripheral: (CBPeripheral *)peripheral 
    advertisementData:  (NSDictionary *)advertisementData 
        RSSI:   (NSNumber *)RSSI { 
NSString *localName = [advertisementData objectForKey:CBAdvertisementDataLocalNameKey]; 
NSData *manufacturerData = [advertisementData objectForKey:CBAdvertisementDataManufacturerDataKey]; 
NSLog(@"Local: name: %@", localName); 
NSLog(@"Manufact. Data: %@", [manufacturerData description]); 
} 

Локальное имя является NSString, поэтому писать только печатаемые символы на BLE устройства в этой сфере. Данные изготовителя - это NSData, это может содержать любое значение байта, поэтому вы можете даже иметь двоичные данные здесь.

В зависимости от используемого устройства BLE длина локального имени и конкретных данных производителя ограничена.

На моем устройстве BLE я могу отправить идентификатор UUID с 128 битами и 8-значное локальное имя с данными рекламы. Специфические данные производителя входят в данные ответа сканирования и могут составлять 29 байтов.

Хорошо, что использовать данные Adv./Scan Response, это может быть изменено на этом устройстве BLE без цикла питания.

Предложение:

  1. Используйте UUID службы для фильтрации при сканировании
  2. Используйте Рекламу/сканирование данных отклика для дальнейшей фильтрации (UUID должен быть частью рекламной информации я опустил его в приведенном выше описании!)
  3. Забудьте о peripheral.name до тех пор, пока не детерминированной обновления доступны
+0

Я отредактировал сообщение, надеюсь, что теперь это больше ответ, чем раньше. – Abrow

5

Ваш угадывая правильно.
Это из-за core-blutetoothкэш.

В целом изменение имени/услуг/характеристик на устройствах BLE «не поддерживается». Все эти параметры кэшируются.

Есть два способа решения этого:

  • рестарта Bluetooth адаптер, так что Bluetooth кэш очищается (я боюсь, что нет никакого способа сделать это программно, но я могу ошибаться)
  • ваш BLE устройство реализует GATT служба Изменено характеристика: читать об этом here
    Том 3, часть G, 2.5.2 и Том 3, часть G, 7.1.

В качестве альтернативы можно проверить данные рекламы вашего устройства BLE. Он может иметь свойство name, которое должно обновляться каждый раз, когда устройство BLE является рекламными данными (рекламные данные не получают кэширование).

0

Протокол CBPeripheralDelegate содержит метод ...

- (void)peripheralDidUpdateName:(CBPeripheral *)peripheral NS_AVAILABLE(NA, 6_0); 

... который для этой цели.

+0

К сожалению, этот метод вызывается только тогда, когда iOS решает, что имя изменилось, и убедить его в том, что это сложно. – Clyde

0

Edit - просто понял, что вторая часть принятого ответа выше, имеет такое же решение :-(я должен более внимательно прочитать я оставлю этот ответ здесь в любом случае, так как она включает в себя RoboVM код

I.. нашли изменение этой проблемы.Создание характеристики измененного сервиса GATT не работало и не читало имя устройства непосредственно из атрибута Device Name 2A00, поскольку iOS скрывает службу Generic Access. Однако если периферийное устройство включает в себя его локальное имя в рекламный пакет, он доступен из словаря рекламных данных, предоставленного на scan result с использованием ключа поиска CBAdvertisementDataLocalNameKey. Я копирую его в свою оболочку устройства BLE и использую его вместо имени, доступного из CBPeripheral. Ниже приведенный код в Java для RoboVM. Эквивалент OBJC или Swift является простым.

@Override 
    public void didDiscoverPeripheral(CBCentralManager cbCentralManager, CBPeripheral cbPeripheral, CBAdvertisementData cbAdvertisementData, NSNumber rssi) { 
     NSData manufacturerData = cbAdvertisementData.getManufacturerData(); 
     byte[] data = null; 
     if(manufacturerData != null) 
      data = manufacturerData.getBytes(); 
     IosBleDevice bleDevice = new IosBleDevice(cbPeripheral); 
     String name = cbAdvertisementData.getLocalName(); 
     if(name != null && !name.equals(cbPeripheral.getName())) { 
      CJLog.logMsg("Set local name to %s (was %s)", name, cbPeripheral.getName()); 
      bleDevice.setName(name); 
     } 
     deviceList.put(bleDevice.getAddress(), bleDevice); 
     if(!iosBlueMaxService.getSubscriber().isDisposed()) { 
      BleScanResult bleScanResult = new IosBleScanResult(bleDevice, 
       cbAdvertisementData.isConnectable(), 
       data); 
      bleScanResult.setRssi(rssi.intValue()); 
      iosBlueMaxService.getSubscriber().onNext(bleScanResult); 
     } 
    } 
+0

В Objective c как получить имя периферийного устройства. –

Смежные вопросы