【问题标题】:How to detect ibeacon device without knowing UUID in iOS?如何在不知道 iOS 中的 UUID 的情况下检测 ibeacon 设备?
【发布时间】:2016-09-06 22:34:01
【问题描述】:

我想开发一个在不知道 uuid 的情况下检测大量信标设备的应用程序。但是我找不到这样做的方法。我必须在代码中定义 uuid。

我开发了一个适用于已知设备的 POC。

我的视图控制器代码:

-(void)setUpview
{
     // Regardless of whether the device is a transmitter or receiver, we need a beacon region.
    NSUUID * uid = [[NSUUID alloc] initWithUUIDString:@"78CDC73D-D678-4B35-A88A-C2E09E5B963F"];//[UIDevice currentDevice].identifierForVendor;
    treasureId = @"com.eden.treasure";
    self.beaconRegion = [[CLBeaconRegion alloc] initWithProximityUUID:uid identifier:treasureId];

    // Location manager.
    self.locationManager = [[CLLocationManager alloc] init];
    self.locationManager.delegate = self;

    if([self.locationManager respondsToSelector:@selector(requestAlwaysAuthorization)]) {
        [self.locationManager requestAlwaysAuthorization];
    }

    [self.locationManager startMonitoringForRegion:self.beaconRegion];
    [self.locationManager startRangingBeaconsInRegion:self.beaconRegion];
    [self locationManager:self.locationManager didStartMonitoringForRegion:self.beaconRegion];

    [self.beaconRegion setNotifyEntryStateOnDisplay:YES];
    [self.beaconRegion setNotifyOnEntry:YES];
    [self.beaconRegion setNotifyOnExit:YES];

//    self.peripheralManager = [[CBPeripheralManager alloc] initWithDelegate:self queue:nil];
    if ([UIDevice currentDevice].userInterfaceIdiom==UIUserInterfaceIdiomPad || [[[UIDevice currentDevice] model] isEqualToString:@"iPad Simulator"])
    {
        [self configureTransmitter];
    }
    else {
        [self configureReceiver];
    }
}


-(void)configureTransmitter
{
    // The received signal strength indicator (RSSI) value (measured in decibels) for the device. This value represents the measured strength of the beacon from one meter away and is used during ranging. Specify nil to use the default value for the device.
    NSNumber * power = [NSNumber numberWithInt:-63];
    self.peripheralData = [self.beaconRegion peripheralDataWithMeasuredPower:power];
    // Get the global dispatch queue.
    dispatch_queue_t queue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0);
    // Create a peripheral manager.
    self.peripheralManager = [[CBPeripheralManager alloc] initWithDelegate:self queue:queue];
}

-(void)configureReceiver {
    // Location manager.
    self.locationManager = [[CLLocationManager alloc] init];
    self.locationManager.delegate = self;
    [self.locationManager requestAlwaysAuthorization];
    [self.locationManager startMonitoringForRegion:self.beaconRegion];
    [self.locationManager startRangingBeaconsInRegion:self.beaconRegion];
}
#pragma mark - CBPeripheralManagerDelegate methods

-(void)peripheralManagerDidUpdateState:(CBPeripheralManager *)peripheral
{
    // The peripheral is now active, this means the bluetooth adapter is all good so we can start advertising.
    if (peripheral.state == CBPeripheralManagerStatePoweredOn)
    {
        [self.peripheralManager startAdvertising:self.peripheralData];
    }
    else if (peripheral.state == CBPeripheralManagerStatePoweredOff)
    {
        NSLog(@"Powered Off");
        [self.peripheralManager stopAdvertising];
    }  
}
-(void)locationManager:(CLLocationManager *)manager didDetermineState:(CLRegionState)state forRegion:(CLRegion *)region
{
    if(state == CLRegionStateInside)
    {
        NSLog(@"%@",[NSString stringWithFormat:@"You are inside region %@", region.identifier]);
    }
    else if(state == CLRegionStateOutside)
    {
        NSLog(@"%@",[NSString stringWithFormat:@"You are outside region %@", region.identifier]);
    }
    else
    {
        return;
    }
}

-(void)locationManager:(CLLocationManager *)manager didRangeBeacons:(NSArray *)beacons inRegion:(CLBeaconRegion *)region
{
    if ([beacons count] == 0)
        return;

    NSString * message;
    UIColor * bgColor;
    CLBeacon * beacon = [beacons firstObject];

    switch (beacon.proximity) {
        case CLProximityUnknown:
            message = [NSString stringWithFormat:@"ProximityUnknown -- %ld", (long)beacon.proximity];
            bgColor = [UIColor blueColor];
            break;
        case CLProximityFar:
            message = [NSString stringWithFormat:@"ProximityFar -- %ld", (long)beacon.proximity];
            bgColor = [UIColor colorWithRed:.0f green:.0f blue:230.0f alpha:1.0f];
            break;
        case CLProximityNear:
            message = [NSString stringWithFormat:@"ProximityNear -- %ld", (long)beacon.proximity];
            bgColor = [UIColor orangeColor];
            break;
        case CLProximityImmediate:
        default:
            message = [NSString stringWithFormat:@"ProximityImmediate -- %ld", (long)beacon.proximity];
            bgColor = [UIColor redColor];
            break;
    }
    if (beacon.proximity != self.previousProximity)
    {
        [lblStatus setText:message];
        [self.view setBackgroundColor:bgColor];
        self.previousProximity = beacon.proximity;  
    }  
}

那么有什么方法可以在不知道 uuid 的情况下检测 iBeacon 吗?

注意:使用与check This link 广播信号(虚拟信标)相同功能的示例应用程序。

任何帮助将不胜感激。

【问题讨论】:

  • 你应该做不到。如果它是真正的 iBeacon(而不是经典 BLE 设备和 iBeacon 之间的混合体)。 iOS 应该自动翻译 BLE 广播消息并让它仅可用于 CLBeacon 的东西。如果它是有时会广播经典 BLE 内容的混合,您可以使用 CBPeripheralManager 找到它,并获取 UUID 以扫描 CLBeacon。主要问题是 iOS 只提供高级 API 而不是低级 API,而对于 Android,它们(可以)解析自己的消息,然后扫描并采取行动响应任何他们想要的。
  • 您需要知道您要查找的 UUID。您无法扫描所有 UUID

标签: ios objective-c iphone ibeacon core-bluetooth


【解决方案1】:

iOS 中没有公共 API 可以在至少知道信标的 ProximityUUID 的情况下检测信标。这是设计使然——Apple 只希望您能够看到自己的信标,这意味着知道 ProximityUUID。

也就是说,操作系统当然知道如何查看任何信标,并且您可能会使用私有 API 来执行此操作。请理解,您不能使用私有 API 为 App Store 开发应用程序,因为 Apple 不会批准使用此类代码。您可以使用私有 API 制作实用程序以供您自己的 iOS 设备使用,但私有 API 可能会因任何 iOS 升级而停止工作

根据这些注意事项,使用CoreLocation 可以定义一个通配符CLBeaconRegion,该通配符可用于使用私有API 查找任何信标。 See here 一种方法。

【讨论】:

  • 你是对的,我们已经使用上面的示例进行了测试,它显示了正确的结果,包括具有不同 UUID 的 iBeacons/虚拟 iBeacon。但由于它是私有 API,这对实际开发没有用处。任何方式感谢您的信息。欣赏。
  • 大家好,我是新手,所以我对 iBeacon 与 iOS 的集成有一些疑问。是否可以在没有 MinorID 的情况下跟踪那些 iBeacons(而我们只有 MajorID)?如果这是可能的,它在代码中看起来如何?以及如何跟踪不同位置或区域的那些?
  • 是的,这是可能的。您只需在区域定义中保留次要 null 即可做到这一点。
  • 我编写了那个应用程序,它预编程了十几个 UUID,这些 UUID 是流行的信标制造商的默认设置。所以它适用于许多但不是所有的信标,除非你配置额外的 UUID。
  • 每个信标制造商通常会生成自己的 UUID,然后按照惯例,在默认设置下使用该 UUID 作为所有信标的标准。您可以通过 (a) 阅读他们的文档或 (b) 购买他们的一个信标并查看它传输的 UUID,了解每个信标制造商默认使用哪些 UUID。
【解决方案2】:

您需要使用CoreBluetooth 库来扫描设备。从已发现设备列表中找到您的 iBeacon 后,您将查询 iBeacon 的服务和特征以找到 UUID。我是这样做的:

import CoreBluetooth
import CoreLocation

extension Data {

    public var hexString: String {
        var str = ""
        enumerateBytes { (buffer, index, stop) in
            for byte in buffer {
                str.append(String(format: "%02X", byte))
            }
        }
        return str
    }
}

class viewController: UIViewController, CLLocationManagerDelegate, CBCentralManagerDelegate, CGPeripheralDelegate {

    var locationManager: CLLocationManager = CLLocationManager()
    var myBeaconRegion: CLBeaconRegion!
    var centralManager: CBCentralManager!
    var discoveredPeripheral: CBPeripheral?

    override viewDidLoad() {

        centralManager = CBCentralManager(delegate: self, queue: nil)
    }

    func centralManagerDidUpdateState(_ central: CBCentralManager) {

        if central.state != .poweredOn {
            return
        }

        centralManager.scanForPeripherals(withServices: nil, options: [CBCentralManagerScanOptionAllowDuplicateKeys: true])
    }

    func centralManager(_ central: CBCentralManager, didDiscover peripheral: CBPeripheral, advertisementData: [String: Any], rssi RSSI: NSNumber) {

        if (RSSI.intValue > -15 || RSSI.intValue < -35) {
            return // With those RSSI values, probably not an iBeacon.
        }

        if peripheral != discoveredPeripheral {
            discoveredPeripheral = peripheral // Need to retain a reference to connect to the beacon.
            centralManager.connect(peripheral, options: nil)
            central.stopScan() // No need to scan anymore, we found it.
        }
    }

    func centralManager(_ central: CBCentralManager, didConnect peripheral: CBPeripheral) {

        peripheral.discoverServices(nil)
    }

    func centralManager(_ central: CBCentralManager, didDisconnectPeripheral peripheral: CBPeripheral, error: Error?) {

        discoveredPeripheral = nil
    }

    func peripheral(_ peripheral: CBPeripheral, didDiscoverServices error: Error?) {

        guard error == nil else {
            return
        }

        if let services = peripheral.services {
            for service in services {
                peripheral.discoverCharacteristics(nil, for: service)
            }
        }
    }

    func peripheral(_ peripheral: CBPeripheral, didDiscoverCharacteristicsFor service: CBService, error: Error?) {

        guard error == nil else {
            return
        }

        if let characteristics = service.characteristics {
            for characteristic in characteristics {
                if characteristic.uuid.uuidString == "2B24" { // UUID
                    peripheral.readValue(for: characteristic)
                }
            }
        }
    }

    func peripheral(_ peripheral: CBPeripheral, didUpdateValueFor characteristic: CBCharacteristic, error: Error?) {

        guard error == nil else {
            return;
        }

        if value = characteristic.value {
            // value will be a Data object with bits that represent the UUID you're looking for.
            print("Found beacon UUID: \(value.hexString)")
            // This is where you can start the CLBeaconRegion and start monitoring it, or just get the value you need.
        }
    }

【讨论】:

  • 我尝试了您的代码。由于“str.append(String(format: "%02X", byte))”,此代码正在更改标识符的值...请验证一次十六进制转换。 .
【解决方案3】:

我也在寻找同样的东西,我在这个例子中得到了答案 enter link description here

这是搜索所有没有 UUID 的 iBeacons

【讨论】:

    猜你喜欢
    • 2018-09-29
    • 1970-01-01
    • 2017-06-27
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多