Nano Hash - криптовалюты, майнинг, программирование

Обратный вызов центрального диспетчера CoreBluetooth сделал DiscoverPeripheral дважды

Я сканирую свое периферийное устройство следующим образом:

NSDictionary *scanOptions = [NSDictionary dictionaryWithObject:[NSNumber numberWithBool:NO] 
                                                            forKey:CBCentralManagerScanOptionAllowDuplicatesKey];
        // Scan for peripherals with given UUID
        [cm scanForPeripheralsWithServices:[NSArray arrayWithObject:HeliController.serviceUUID] options:scanOptions]

Нет проблем, я нахожу периферийное устройство и могу к нему подключиться. Как видите, я даю CBCentralManagerScanOptionAllowDuplicatesKey с bool NO, чтобы не допускать более одного периферийного устройства, но иногда didDiscoverPeripheralcallback срабатывает дважды.

- (void) centralManager:(CBCentralManager *)central 
  didDiscoverPeripheral:(CBPeripheral *)peripheral 
  advertisementData:(NSDictionary *)advertisementData 
               RSSI:(NSNumber *)RSSI 
{        
if(!discovered){
    discovered = YES;
    NSLog(@"Discovered");

    [cm stopScan];

    [scanButton setTitle:@"Connect" forState:UIControlStateNormal];
}
else if(discovered){
    discovered = YES
    NSLog(@"Already discovered");
}
}

Несколько раз я получаю

Discovered
Already discovered

как вывод в моей консоли, и в большинстве случаев отображается только Discoveredmessage.

В моем периферийном делегате я сначала обнаруживаю службы, которые затем вызывают [peripheral discoverCharacteristics, и всегда происходит обратный вызов:

- (void) peripheral:(CBPeripheral *)peripheral didDiscoverCharacteristicsForService:(CBService *)service error:(NSError *)error{

NSLog(@"Did discover characteristic for service %@", [service.peripheral UUID]);

for(CBCharacteristic *c in [service characteristics]){
    // We never get here when peripheral is discovered twice
    if([[c UUID] isEqual:myCharacteristicUUID]){

        NSLog(@"Found characteristic");

        self.throttleCharacteristic = c;

    }
}

Когда didDiscoverPeripheral встречается дважды, service становится nil в этом методе, даже если peripheral нет (UUID, имя по-прежнему правильное).

Перезагрузка телефона или сброс настроек сети временно устраняет проблему.

Мне очень нужно это исправить! Спасибо


  • Какой параметр устройства вы указали? 19.07.2012
  • false для CBCentralManagerScanOptionAllowDuplicatesKey 20.07.2012
  • Я предполагаю, что он вызывается дважды, когда уровень сигнала плохой. 21.07.2012
  • Я опробую эту теорию в понедельник, но по моему опыту, если это произошло один раз, я не смогу заставить ее работать снова, пока не перезагрузлю телефон. 21.07.2012
  • К силе сигнала это не имеет никакого отношения. 23.07.2012

Ответы:


1

Устройства могут возвращать дополнительные данные во время рекламы. Они могут поступать отдельными пакетами в разное время. В этом случае didDiscoverPeripheral вызывается сначала, когда устройство изначально видно, а затем снова, когда для него становится доступной дополнительная информация.

CBCentralManagerScanOptionAllowDuplicatesKey отличается. Он сообщает CoreBluetooth, хотите ли вы получать повторяющиеся результаты, когда устройство снова объявляет о себе. Это не предотвращает несколько вызовов didDiscoverPeripheral для одной и той же последовательности обнаружения; это предотвращает повторные последовательности обнаружения.

Источник: http://lists.apple.com/archives/bluetooth-dev/2012/Apr/msg00047.html (представитель Apple на bluetooth-dev).

30.07.2012
  • @Wilhelmsen: Что нужно решить? Просто отследите UUID, которые вы уже видели. 31.07.2012
  • Я попробовал ответ @Mike, разве он не отслеживает UUID? Я новичок в этом, поэтому, если у вас есть какие-либо дополнительные подсказки о том, как программно добиться этого, я был бы очень признателен! В любом случае большое спасибо за информацию 01.08.2012
  • didDiscoverPeripheral возвращает объекты CBPeripheral. Каждый из этих объектов имеет атрибут UUID, который можно использовать для отслеживания первого и второго случаев обратного вызова для одного и того же периферийного объекта. 02.08.2012
  • Эти дополнительные данные называются откликом сканирования, и периферийное устройство отправляет эти дополнительные данные только тогда, когда центральное устройство запрашивает их. В этом случае CoreBluetooth автоматически запрашивает его для каждого обнаруженного устройства. 13.03.2015
  • Я искал это, но я не уверен в этом. Как проверить, был ли второй раз, когда мы сделали DiscoverPeripheral, для дополнительных данных? В моем случае рекламные данные совпадают. 24.01.2017

  • 2

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

    В своем коде Apple избегает таких дубликатов:

    NSMutableArray *peripherals = [self mutableArrayValueForKey:@"thermometers"];
    if( ![self.thermometers containsObject:peripheral] )
        [peripherals addObject:peripheral];
    

    Если устройство уже существует в массиве, оно не добавляется во второй раз.

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

    20.07.2012
  • Благодарю вас! должно ли это войти в мой метод didDiscoverPeripheral? 21.07.2012
  • Да, во всяком случае, именно так это сделала Apple. См. developer.apple.com/library/mac/#samplecode/HealthThermometer/ для получения полного исходного кода. 22.07.2012
  • Я действительно думаю, что это решило это. Я не смог воспроизвести это каким-либо образом: D Я опубликую ответ на свой вопрос, чтобы уточнить. Большое тебе спасибо 24.07.2012
  • Я был неправ, это работало какое-то время, а потом снова дерьмо 24.07.2012
  • Я думаю, что параметр, который вы упомянули, должен делать то, что вы сказали. Можете поделиться кодом, что вы задаете параметр? 26.07.2012
  • установка CBCentralManagerScanOptionAllowDuplicatesKey показывает вопрос 26.07.2012
  • обновление: вместо перезагрузки телефона я также могу сбросить настройки сети, работает точно так же 30.07.2012
  • Это неправильно. Различные периферийные устройства никогда не будут иметь одинаковый UUID; если есть четыре термометра, есть четыре UUID. Параметр CBCentralManagerScanOptionAllowDuplicatesKey позволяет возвращать одно и то же устройство несколько раз, поэтому вы будете получать обратный вызов didDiscoverPeripheral снова и снова, пока устройство рекламируется, а вы не подключились к нему. Установка его в NO (по умолчанию) означает, что вы хотите видеть его только в первый раз. 31.07.2012
  • Существует разница между периферийным UUID и сервисным UUID. ScanForPeripheralsWithServices:options: использует UUID службы, который (предположительно) будет дублироваться на нескольких устройствах, предоставляющих одну и ту же информацию, таких как термометры. UUID для самого устройства, который не используется в этом вызове, представляет собой другую проблему. Я предполагаю, но точно не знаю, что они уникальны. В оригинальном посте этот момент четко не отражен. 31.07.2012
  • didDiscoverPeripheral вызывается дважды, потому что ваш рекламный пакет больше 31 байта (максимум на пакет), а остальные данные необходимо отправить. Я полагаю, вы настраиваете службу с помощью CBAdvertisementDataServiceUUIDsKey, а также имя устройства через CBAdvertisementDataLocalNameKey? Или, возможно, одно из других рекламных значений, которые вы можете отправить. 25.09.2012
  • @afrederick, рекламный пакет не может быть больше, чем можно отправить в одном пакете. didDiscoverPeripheral вызывается снова для доставки данных scan response, которые CoreBluetooth запрашивает после получения первого рекламного пакета. 13.03.2015
  • Но этот CBCentralManagerScanOptionAllowDuplicatesKey игнорируется при фоновом сканировании. Как я буду подключаться к этим 4 термометрам в фоновом режиме, потому что они будут объединены в один и рекламироваться iOS как один пакет? @Майк 23.09.2018
  • Новые материалы

    Кластеризация: более глубокий взгляд
    Кластеризация — это метод обучения без учителя, в котором мы пытаемся найти группы в наборе данных на основе некоторых известных или неизвестных свойств, которые могут существовать. Независимо от..

    Как написать эффективное резюме
    Предложения по дизайну и макету, чтобы представить себя профессионально Вам не позвонили на собеседование после того, как вы несколько раз подали заявку на работу своей мечты? У вас может..

    Частный метод Python: улучшение инкапсуляции и безопасности
    Введение Python — универсальный и мощный язык программирования, известный своей простотой и удобством использования. Одной из ключевых особенностей, отличающих Python от других языков, является..

    Как я автоматизирую тестирование с помощью Jest
    Шутка для победы, когда дело касается автоматизации тестирования Одной очень важной частью разработки программного обеспечения является автоматизация тестирования, поскольку она создает..

    Работа с векторными символическими архитектурами, часть 4 (искусственный интеллект)
    Hyperseed: неконтролируемое обучение с векторными символическими архитектурами (arXiv) Автор: Евгений Осипов , Сачин Кахавала , Диланта Хапутантри , Тимал Кемпития , Дасвин Де Сильва ,..

    Понимание расстояния Вассерштейна: мощная метрика в машинном обучении
    В обширной области машинного обучения часто возникает необходимость сравнивать и измерять различия между распределениями вероятностей. Традиционные метрики расстояния, такие как евклидово..

    Обеспечение масштабируемости LLM: облачный анализ с помощью AWS Fargate и Copilot
    В динамичной области искусственного интеллекта все большее распространение получают модели больших языков (LLM). Они жизненно важны для различных приложений, таких как интеллектуальные..