Не удалось распознать маяк с помощью CBPeripheral в iOS

Отредактировано: удален код iBeacon. Так как нет проблем с кодом iBeacon.

-> Как только мы распознаем наши маяки, мы должны связаться с первым маяком, используя BLE. Мы используем фреймворк Bleno на Respberry PI.

//Передача моего сервисного UUID

[bluetoothManager scanForPeripheralsWithServices:@[@"87fa7df2-748c-4093-8e73-b93ee73543b4"] options:scanOptions];

Проблема в том, что если мы передаем UUID моей службы (проверено с помощью приложения Light Blue), я не получаю никаких результатов. Вместо этого, если мы передаем «ноль», я, по крайней мере, могу распознать свое устройство.

Итак, есть ли какой-либо общий способ распознать наше устройство Bluetooth из кода iOS. Поскольку CBPeripheral возвращает ограниченные свойства.

‹CBPeripheral: 0x1700ff700, идентификатор = 7915DCF8-AF2E-4AF2-B5FC-A5EEA10D3812, имя = raspberrypi, состояние = подключено›

Я попытался изменить имя своего устройства Bluetooth, используя приведенную ниже команду, используя структуру BLENO.

sudo BLENO_DEVICE_NAME="SOME_NAME_86" узел iBeacon.js

Иногда я могу прочитать имя. Но не всегда. Поэтому ищу альтернативное решение.

Вот мой код:

@реализация ViewController

- (void)viewDidLoad {
    [super viewDidLoad];
    // Do any additional setup after loading the view, typically from a nib.    
    _centralManager = [[CBCentralManager alloc] initWithDelegate:self queue:nil];
    _data = [[NSMutableData alloc] init];
}


- (void)centralManagerDidUpdateState:(CBCentralManager *)central {    
    switch (central.state) {            
        case CBManagerStatePoweredOn:
[_centralManager scanForPeripheralsWithServices:@[[CBUUID 
UUIDWithString:@"87FA7DF2-748C-4093-8E73-B93EE73543B4"]] options:@{CBCentralManagerScanOptionAllowDuplicatesKey : @YES}];                break;            
        default:            break;
    }
}


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

    if (_discoveredPeripheral != peripheral) {
        _discoveredPeripheral = peripheral;
        [_centralManager connectPeripheral:peripheral options:nil];
        [_centralManager stopScan];
    }
}

- (void)centralManager:(CBCentralManager *)central didFailToConnectPeripheral:(CBPeripheral *)peripheral error:(NSError *)error {
    NSLog(@"Failed to connect");
    [self cleanup];
}

- (void)cleanup {

    // See if we are subscribed to a characteristic on the peripheral
    if (_discoveredPeripheral.services != nil) {
        for (CBService *service in _discoveredPeripheral.services) {
            if (service.characteristics != nil) {
                for (CBCharacteristic *characteristic in service.characteristics) {
                    if ([characteristic.UUID isEqual:[CBUUID UUIDWithString:TRANSFER_CHARACTERISTIC_UUID]]) {
                        if (characteristic.isNotifying) {
                            [_discoveredPeripheral setNotifyValue:NO forCharacteristic:characteristic];
                            return;
                        }
                    }
                }
            }
        }
    }

    [_centralManager cancelPeripheralConnection:_discoveredPeripheral];
}


- (void)centralManager:(CBCentralManager *)central didConnectPeripheral:(CBPeripheral *)peripheral {
    NSLog(@"Connected");

    [_centralManager stopScan];
    NSLog(@"Scanning stopped");

    [_data setLength:0];

    peripheral.delegate = self;    
    [peripheral discoverServices:@[[CBUUID UUIDWithString:@"87FA7DF2-748C-4093-8E73-B93EE73543B4"]]];
}


- (void)peripheral:(CBPeripheral *)peripheral didDiscoverServices:(NSError *)error {
    if (error) {
        [self cleanup];
        return;
    }

    for (CBService *service in peripheral.services) {
        [peripheral discoverCharacteristics:@[[CBUUID UUIDWithString:TRANSFER_CHARACTERISTIC_UUID]] forService:service];
    }
    // Discover other characteristics
}

- (void)peripheral:(CBPeripheral *)peripheral didUpdateValueForCharacteristic:(CBCharacteristic *)characteristic error:(NSError *)error {
    if (error) {
        NSLog(@"Error");
        return;
    }

    NSString *stringFromData = [[NSString alloc] initWithData:characteristic.value encoding:NSUTF8StringEncoding];

    if ([stringFromData isEqualToString:@"EOM"]) {        
        [peripheral setNotifyValue:NO forCharacteristic:characteristic];        
        [_centralManager cancelPeripheralConnection:peripheral];
    }

    [_data appendData:characteristic.value];
}

@конец

Проблема в том, что у меня есть два устройства Bluetooth рядом, рекламирующие один и тот же идентификатор службы. Исходя из сценария, я должен подключиться только к одному устройству и прочитать его характеристики.


person Praveen    schedule 28.02.2017    source источник
comment
Вы не можете связать UUID маяка с периферийным устройством BLE. Вам нужно использовать CoreBluetooth, чтобы обнаружить ваши рекламные периферийные устройства и таким образом подключиться к ним. Идентификатор, который CoreBluetooth предоставляет вашему приложению, связан с MAC-адресом устройства, но не является MAC-адресом устройства. UUID маяка не связан с MAC или идентификатором CoreBluetooth.   -  person Paulw11    schedule 01.03.2017
comment
Спасибо Павел за комментарий. Я тоже попробовал iBeacnon UUID. Во всяком случае, это правильно. В том же коде я также добавил свой сервисный UUID (уникальный для моего устройства) в методе scanPeripheral. Но он не нашел мои устройства с синим зубом с этим сервисным UUID. Я не мог продолжить, не распознав свое устройство с синим зубом.   -  person Praveen    schedule 01.03.2017
comment
Как только вы обнаружите устройство, рекламирующее вашу услугу, вам необходимо подключиться и прочитать значение некоторой характеристики, чтобы идентифицировать его. Вы не можете определить конкретное устройство только по рекламе сервиса   -  person Paulw11    schedule 01.03.2017
comment
Я попытался подключиться к службе своего устройства, используя UUID службы в методе scanForPeripherals. [BluetoothManager scanForPeripheralsWithServices: @[87FA7DF2-748C-4093-8E73-B93EE7354666] параметры: ноль]; Поскольку мое устройство активно, я все еще не могу найти блютуз.   -  person Praveen    schedule 02.03.2017
comment
Ваше устройство рекламирует этот сервис? Начните с приложения LightBlue из магазина приложений и убедитесь, что оно видит ваше устройство и этот сервис.   -  person Paulw11    schedule 02.03.2017
comment
Да... Я вижу сервисный UUID в голубом приложении. Но если в моем коде указать тот же сервисный UUID, он не работает. Не уверен.. что-то пошло не так.   -  person Praveen    schedule 02.03.2017
comment
Можете ли вы отредактировать свой вопрос, чтобы показать свой код?   -  person Paulw11    schedule 02.03.2017
comment
Да... Отредактировал вопрос с образцом кода.   -  person Praveen    schedule 02.03.2017


Ответы (3)


Если вы пытаетесь обнаружить iBeacon и связаться с ним из iOS, вы, скорее всего, захотите использовать Core Location, а не Core Bluetooth...

Посмотрите здесь: https://developer.apple.com/reference/corelocation?language=objc

Редактировать: я не запускал этот код, но после быстрого просмотра кода он выглядит как достойный пример сканирования и обнаружения iBeacons: https://github.com/ThomasJay/Locate

person DonMag    schedule 28.02.2017
comment
Спасибо ДонМаг за комментарий. Но я могу распознать свой iBeacon, используя уникальный идентификатор. Я использую Core Location для этого. Проблема в том, что как только мы распознали Raspberry PI (устройство Bluetooth), я попытался подключиться с использованием базовой платформы Bluetooth. Я использую метод ScanPeripheral для повторного сканирования ближайших устройств Bluetooth. На этом этапе я не могу распознать свое устройство с синим зубом, используя свой уникальный сервисный UUID. - person Praveen; 01.03.2017
comment
Ах - имеет смысл. Я так понимаю, у вас есть несколько устройств в этом районе? Итак, вы используете iBeacon, чтобы, возможно, обнаружить ближайший, а затем вам нужно подключиться к нему? - person DonMag; 01.03.2017
comment
Да... Верно... В Android мы можем подключиться к периферийному устройству Bluetooth, передав сервисный UUID. Но в iOS это не работает. - person Praveen; 02.03.2017
comment
Хммм... У вас есть контроль над конфигурациями устройств среды/BLE? Если да, можете ли вы дать каждому свой собственный UUID службы? Или вы можете использовать значения BLE RSSI для определения близости? - person DonMag; 02.03.2017
comment
Да. У меня есть контроль над конфигурациями BLE. Для этих сценариев я пробовал только одно устройство с синим зубом (Respberry PI), предоставляя уникальный сервисный UUID. Вот код вызова метода с сервисным UUID. [_centralManager scanForPeripheralsWithServices:@[@87FA7DF2-748C-4093-8E73-B93EE73543B4] параметры: ноль]; - person Praveen; 02.03.2017

Массив, который вы отправляете scanForPeripheralsWithServices, представляет собой массив объектов CBUUID, а не массив строк. Тебе нужно:

[_centralManager scanForPeripheralsWithServices:@[[CBUUID UUIDWithString:@"87FA7DF2-748C-4093-8E73-B93EE73543B4"]] options:nil];
person Paulw11    schedule 02.03.2017
comment
Кроме того, подобные проблемы — вот почему вам следует серьезно подумать о переходе на Swift; Swift поймал бы это во время компиляции - person Paulw11; 02.03.2017
comment
Да .. Я пробовал в обоих направлениях. [_centralManager scanForPeripheralsWithServices:@[[CBUUID UUIDWithString:@87FA7DF2-748C-4093-8E73-B93EE73543B4]] параметры: ноль]; - person Praveen; 02.03.2017
comment
Внимательно проверьте свой сервисный UUID; Сравните это с сервисами, которые LightBlue обнаруживает из рекламного пакета. Существует разница между сервисом, доступным на периферийном устройстве, и сервисом, который рекламируется. Также попробуйте nil вместо массива CBUUID; который обнаружит все рекламные периферийные устройства, а затем вы сможете увидеть, какие услуги рекламирует ваш Pi - person Paulw11; 02.03.2017
comment
Я дважды проверил сервисный UUID в голубом приложении. Вроде не ошибся. Я смог распечатать UUID службы после подключения. Я передаю ноль в методе ScanForPeripherals. [_centralManager scanForPeripheralsWithServices:nil options:scanOptions]; Вот я и прошел, сервисный UUID в методе DiscoverServices. Иногда это работает. Но не всегда. [_discoveredPeripheral discoveryServices:@[[CBUUID UUIDWithString:TRANSFER_SERVICE_UUID]]]; - person Praveen; 02.03.2017
comment
Похоже, вы не настроили периферийное устройство для рекламы своего сервиса. UUID какого сервиса входит в рекламные данные; вы можете проверить словарь в didDiscoverPeripheral. - person Paulw11; 02.03.2017
comment
Если есть несколько устройств, мой код некоторое время подключает другие устройства, кроме моего устройства. Есть ли способ остановить сканирование, как только мы получим наше устройство. Если да, то по какому признаку мы можем распознать наше устройство. -- Спасибо - person Praveen; 02.03.2017
comment
Вот почему вам нужно иметь возможность сканировать устройства, рекламирующие конкретную услугу, а не ноль; как только ваше устройство правильно рекламируется, вы можете сканировать эту услугу. - person Paulw11; 02.03.2017
comment
Я попытался просканировать периферийные устройства, используя свой сервисный UUID. Но мой код не может найти периферийные устройства. Вот почему я сдал ноль. После того, как я получил некоторые периферийные устройства, я пытаюсь подключиться и обнаружить службы через подключенное периферийное устройство. Но непоследовательно. Я что-то пропустил здесь. [_discoveredPeripheral discoveryServices:@[[CBUUID UUIDWithString:TRANSFER_SERVICE_UUID]]]; - person Praveen; 03.03.2017

Наткнулся на это случайно, и это кажется устаревшим, но, поскольку я был в похожей ситуации (и потратил день или около того, чтобы понять это), решил, что отвечу на это всем, кто будет читать это в будущем. Скорее всего у вас запущены сервисы, но вы не вещаете об их доступности. Таким образом, ваши услуги будут видны только после сопряжения с устройством.

Чтобы проверить это, выполните сканирование со значением nil для служб и распечатайте содержимое массива advData, доступного в centralManager:didDiscoverPeripheral:advertisementData:RSSI:. Если UUID вашей службы недоступен в этом словаре (под ключом CBAdvertisementDataServiceUUIDsKey), устройство iOS не сможет узнать, что служба доступна без сопряжения.

person Raimundas Sakalauskas    schedule 07.04.2020