Подтвердить что ты не робот

Неправильное имя периферийного устройства BLE с iOS

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

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

Если я отлаживаю приложение и смотрю:

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

значение inner.name - это SadName, поэтому я не думаю, что это то, что я неправильно интерпретирую в коде. Я должен упомянуть, что когда я просматриваю устройства, мой код:

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

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

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

4b9b3361

Ответ 1

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​​strong > , это может содержать любое значение байта, поэтому вы можете даже иметь двоичные данные здесь.

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

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

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

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

  • Использовать UUID службы для фильтрации при сканировании (UUID должен быть частью рекламных данных! Я опустил его в приведенном выше описании)
  • Используйте данные объявления/сканирования для дальнейшей фильтрации
  • Забудьте о имени периферии, если нет детерминированного обновления.

Ответ 2

Ваше предположение верно.
Это из-за кеша core-blutetooth .

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

Существует два способа решения этого вопроса:

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

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

Ответ 3

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

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

..., который сделан для этой цели.

Ответ 4

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

Я нашел решение этой проблемы. Добавление измененной характеристики GATT Service не работало и не читало имя устройства непосредственно из атрибута Device Name 2A00, поскольку iOS скрывает службу Generic Access. Однако, если периферийное устройство включает его локальное имя в рекламный пакет, оно доступно из словаря рекламных данных, предоставленного на результат сканирования, используя извлечение key 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);
        }
    }