【问题标题】:Not able to recognize the beacon using CBPeripheral in iOS无法在 iOS 中使用 CBPeripheral 识别信标
【发布时间】:2017-07-20 01:35:26
【问题描述】:

编辑: 删除了 iBeacon 代码。因为 iBeacon 代码没有问题。

-> 一旦我们识别出我们的信标,我们就必须使用 BLE 与第一个信标进行通信。我们在 Respberry PI 上使用了 Bleno 框架。

//传递我的服务UUID

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

问题是,如果我们通过我的服务 UUID(使用 Light Blue App 验证),我不会得到任何结果。相反,如果我们传递“nil”,我至少能够识别我的设备。

那么,是否有任何通用方法可以从 iOS 代码中识别我们的蓝牙设备。由于 CBPeripheral 返回有限的属性。

我尝试使用以下命令使用 BLENO 框架更改我的蓝牙设备名称。

sudo BLENO_DEVICE_NAME="SOME_NAME_86" 节点 iBeacon.js

有时,我能读懂这个名字。但并非所有时候。所以我正在寻找替代解决方案。

这是我的代码:

@implementation 视图控制器

- (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];
}

@结束

问题是,我有两个蓝牙设备并排,广告相同的服务 ID。根据场景,我应该只连接一台设备并读取它们的特征。

【问题讨论】:

  • 您不能将信标 UUID 与 BLE 外围设备相关联。您需要使用 CoreBluetooth 来发现您的广告外围设备并以这种方式连接到它们。 CoreBluetooth 向您的应用提供的标识符设备 MAC 相关,但不是设备 MAC。 Beacon UUID 与 MAC 或 CoreBluetooth 标识符无关
  • 感谢保罗的评论。我也尝试了 iBeacnon UUID。无论如何,这是正确的。在同一代码中,我还在 scanPeripheral 方法中添加了我的服务 UUID(对我的设备唯一)。但它没有找到具有该服务 UUID 的我的蓝牙设备。如果不识别我的蓝牙设备,我无法继续。
  • 一旦您检测到设备宣传您的服务,您需要连接并读取某些特征的值来识别它。您无法仅从服务广告中识别特定设备
  • 我尝试在 scanForPeripherals 方法中使用 Service UUID 连接到我的设备服务。 [bluetoothManager scanForPeripheralsWithServices:@[87FA7DF2-748C-4093-8E73-B93EE7354666] 选项:无];由于我的设备处于活动状态,仍然无法找到蓝牙。
  • 您的设备是否在宣传该服务?从应用商店中的 LightBlue 应用开始,确保它可以看到您的设备和该服务。

标签: ios objective-c bluetooth cbperipheral cbcentralmanager


【解决方案1】:

如果您尝试从 iOS 检测 iBeacon 并与之通信,您很可能希望使用 Core Location,而不是 Core Bluetooth...

看这里:https://developer.apple.com/reference/corelocation?language=objc

编辑:我还没有运行此代码,但在快速浏览代码后,它看起来像是扫描和检测 iBeacons 的一个不错的示例:https://github.com/ThomasJay/Locate

【讨论】:

  • 感谢 DonMag 的评论。但我能够使用唯一标识符识别我的 iBeacon。我为此使用核心位置。问题是,一旦我们识别出 Raspberry PI(蓝牙设备),我就尝试使用 Core Bluetooth 框架进行连接。我正在使用 ScanPeripheral 方法再次扫描附近的蓝牙设备。在这一步中,我无法使用我唯一的服务 UUID 识别我的蓝牙设备。
  • 啊 - 有道理。我认为您在该地区有多个设备?因此,您正在使用 iBeacon 来“检测最近的”,然后您需要连接到它?
  • 是的...那是正确的...在 Android 中,我们可以通过传递服务 UUID 连接到蓝牙外围设备。但在 iOS 中,它不起作用。
  • 嗯...您可以控制环境/BLE 设备配置吗?如果是这样,你能给每个人一个自己的服务 UUID 吗?或者,您可以使用 BLE RSSI 值来确定接近度吗?
  • 是的。我可以控制 BLE 配置。对于这种情况,我通过提供唯一的服务 UUID 仅在一个蓝牙设备 (Respberry PI) 上进行了尝试。这是带有服务 UUID 的方法调用代码。 [_centralManager scanForPeripheralsWithServices:@[@"87FA7DF2-748C-4093-8E73-B93EE73543B4"] 选项:nil];
【解决方案2】:

您发送给scanForPeripheralsWithServices 的数组是CBUUID 对象数组,而不是字符串数组。你需要:

[_centralManager scanForPeripheralsWithServices:@[[CBUUID UUIDWithString:@"87FA7DF2-748C-4093-8E73-B93EE73543B4"]] options:nil];

【讨论】:

  • 顺便说一句,像这样的问题是你应该认真考虑迁移到 Swift 的原因; Swift 会在编译时捕捉到这一点
  • 是的..我已经尝试过两种方式。 [_centralManager scanForPeripheralsWithServices:@[[CBUUID UUIDWithString:@"87FA7DF2-748C-4093-8E73-B93EE73543B4"]] options:nil];
  • 仔细检查你的服务UUID;将其与 LightBlue 从广告数据包中发现的服务进行比较。外围设备上可用的服务与宣传的服务之间存在差异。也尝试将nil 代替CBUU​​ID 的数组;这将发现所有广告外围设备,然后您可以看到您的 Pi 正在广告哪些服务
  • 我在浅蓝色应用程序中仔细检查了服务 UUID。好像没有错。连接后,我能够打印服务 UUID。我在 ScanForPeripherals 方法中传递“nil”。 [_centralManager scanForPeripheralsWithServices:nil options:scanOptions];这里我是 pass,discoverServices 方法中的服务 UUID。有时它正在工作。但并非所有时候。 [_discoveredPeripheral discoverServices:@[[CBUUID UUIDWithString:TRANSFER_SERVICE_UUID]]];
  • 您似乎尚未配置外围设备来宣传您的服务。广告数据中包含什么服务 uuid;你可以在didDiscoverPeripheral查字典。
【解决方案3】:

偶然发现这个,这似乎过时了,但由于我处于类似的情况(并且花了一天左右的时间来解决这个问题)决定我会为将来阅读这篇文章的任何人回答这个问题。您很可能正在运行服务,但您没有广播它们的可用性。这样一来,您的服务只有在与设备配对后才可见。

要对此进行测试,请使用 nil 值扫描服务并打印 centralManager:didDiscoverPeripheral:advertisementData:RSSI: 中可用的 advData 数组的内容。如果您的服务 UUID 在该字典中不可用(在键 CBAdvertisementDataServiceUUIDsKey 下),iOS 设备无法在不配对的情况下知道该服务可用。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2016-04-18
    • 1970-01-01
    • 1970-01-01
    • 2014-08-29
    • 1970-01-01
    • 2020-02-25
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多