Обновление списка сервисов CentralManagers для периферийного устройства

У меня проблема с Core Bluetooth под iOS. Я программирую программу обновления OTA и сталкиваюсь со странной проблемой. Когда я переключаю устройство в режим OTAU, оно отключается и рекламирует разные службы под одним и тем же UUID устройства, проблема в том, что когда я пытаюсь найти службы с вновь подключенного устройства, мне предоставляется старый список служб, которые больше недействительны. Важной частью проблемы является то, что значение CBPeripheral.name является исходным именем устройства, но в рекламном словаре, возвращенном didDiscoverPeripheral, это правильное, новое имя.

- (void)centralManager:(CBCentralManager *)central didDiscoverPeripheral:(CBPeripheral *)peripheral advertisementData:(NSDictionary *)advertisementData RSSI:(NSNumber *)RSSI
{
for (id key in advertisementData) {
    NSLog(@"key: %@, value: %@ \n", key, [advertisementData objectForKey:key]);
}
NSLog(@"Discovered peripheral with identifer: %@, state: %d, name: %@, services: %@",
      [peripheral identifier],
      [peripheral state],
      [peripheral name],
      [peripheral services]);

if (!self.peripherals)
    self.peripherals = [[NSMutableArray alloc] initWithObjects:peripheral,nil];
else
{
    for(int i = 0; i < self.peripherals.count; i++)
    {
        CBPeripheral *p = [self.peripherals objectAtIndex:i];

        if ((p.identifier == NULL) || (peripheral.identifier == NULL))
            continue;

        if ([self UUIDSAreEqual:p.identifier UUID2:peripheral.identifier])
        {
            [self.peripherals replaceObjectAtIndex:i withObject:peripheral];
            NSLog(@"Duplicate UUID found updating...");
            return;
        }
    }
    peripheral.delegate = self;
    [self.peripherals addObject:peripheral];

    NSLog(@"New UUID, adding");
    }
}

Вот что я вижу в ответ:

  key: kCBAdvDataChannel, value: 38 
  key: kCBAdvDataLocalName, value: Xxxx1000_boot 
  key: kCBAdvDataIsConnectable, value: 1 
  Discovered peripheral with identifer: <__NSConcreteUUID 0x156787d0> 9E7A4F82-29F2-08EF-F6A5-9ADCC0790B7F, state: 0, name: Xxxx1000, services: (null)

часто при следующем чистом запуске программы будет отображаться наоборот с Xxxx_boot для имени периферийного устройства и Xxxx для рекламируемого имени (реклама всегда правильная).

Я не знаю, как очистить информацию о периферийных устройствах, сохраненную в CBCentralManager, я даже пытался создать новый экземпляр CentralManager, но, похоже, ничего не работает. Любые идеи?


person Chris Howell    schedule 24.07.2014    source источник
comment
Чтобы надежно обнаружить службы периферийного устройства, вы должны подключиться к нему и вызвать discoverServices. Прямая проверка рекламных данных ненадежна.   -  person Paulw11    schedule 25.07.2014
comment
На самом деле, я открываю услуги. Похоже, моя проблема заключается в том, что мое устройство не отправляло правильную характеристику изменения службы, поэтому, когда я запрашивал службы после того, как устройство переключилось на загрузчик, я все равно возвращал старый список служб. Судя по всему, в iOS нет возможности очистить сохраненный список сервисов. Он обновит свой список только в том случае, если получит характеристику Service Changed.   -  person Chris Howell    schedule 27.08.2014


Ответы (1)


Реклама на самом деле просто намек. Он может содержать практически все, от вашего «размера обуви» до размещенных сервисов. Просто взгляните на профиль iBeacon. Вы никогда не должны полагаться исключительно на эти данные, и Core Bluetooth не будет использовать эту информацию каким-либо другим образом.

Имя периферийного устройства загружается из соответствующей характеристики периферийного устройства. Как только оно будет прочитано iOS, оно будет использовано в свойстве CBPeripheral.name, а объявленное имя будет просто проигнорировано. При повторном подключении имя будет обновлено автоматически.

В заключение,

  1. не судите перед подключением, реклама может врать и Core Bluetooth использует ее осторожно
  2. всегда обнаруживайте услуги после подключения
  3. обратите внимание на peripheralDidUpdateName: обратный вызов
person allprog    schedule 28.07.2014
comment
вау. ты отвечаешь на вопросы в такое время ‹3 - person Etan; 28.07.2014
comment
Похоже, моя проблема связана с тем, что мое устройство не отправляет характеристику Service Changed. В отличие от большинства других платформ, iOS, по-видимому, не позволяет стирать свою базу данных служб и характеристик, сохраненных для конкретного устройства, и не выполняет автоматическое повторное сканирование, если не получено сообщение об изменении службы. Таким образом, обнаружение служб просто возвращает тот же список, который был получен при первом подключении устройства. - person Chris Howell; 27.08.2014
comment
Это еще одна возможность. Это правда, что кеш нельзя сделать недействительным программно. Но странно, что CB требует, чтобы устройство отправляло сервис измененным. Кажется нетривиальным решить на периферийной стороне, должно ли это уведомление быть отправлено для определенного центра или нет, поэтому на практике, вероятно, неразумно так сильно опираться на это уведомление. Может быть стоит сообщить об ошибке. Будем надеяться, что вы сможете исправить прошивку. - person allprog; 28.08.2014