【问题标题】:CLBeacon does not get detected未检测到 CLBeacon
【发布时间】:2014-05-29 10:31:46
【问题描述】:

我正在尝试了解 CLBeacons 的工作原理。我之前使用过 CBPeripherals,它实际上是 BLE 设备的核心蓝牙框架实现。

我做了以下步骤:

  1. 使用 CBPeripheralManager 检测我周围的信标,(以获取每个信标的单独标识符)。
  2. 使用了要在 UITableView 上显示的数据
  3. 在选择 Tableview 时,我将 CBPeripheral 对象本身传递给另一个我有 CLLocationManager 的类。在这里,我使用 CBPeripheral 对象的邻近 UUID 和该区域中的 startToRangeBeacons 定义 CLBeaconRegion。

没有出现任何信标。

令人惊讶的是,当我使用 [NSUUID alloc] initWithUUIDString:@"E2C56DB5-DFFB-48D2-B060-D0F5A71096E0"] 作为 uuid(我从 AirLocate 项目中收集)时,出现了多个信标。

根据我阅读的文档,邻近 UUID 是信标的标识符。那么为什么我使用传递的标识符时它不起作用,为什么我使用定义的标识符时它起作用?

代码---- 1.第一屏

#import "TiBViewController.h"
#import "DEASensorTag.h"
#import "TiBScanTableViewCell.h"
#import "TiBLocateViewController.h"

@interface TiBViewController ()

@property (nonatomic,strong) NSTimer *timer_check;
@end

@implementation TiBViewController

- (void)viewDidLoad
{
    [super viewDidLoad];

}
-(void)viewWillAppear:(BOOL)animated
{
    [super viewWillAppear:YES];

}
-(void)viewDidAppear:(BOOL)animated
{
    [super viewDidAppear:YES];

    [self performSelector:@selector(initialise) withObject:self afterDelay:2.0];
}
-(void)initialise
{
    DEACentralManager *centralManager = [DEACentralManager initSharedServiceWithDelegate:self];
    if (centralManager.isScanning == NO)
    {
        [centralManager startScan];
        centralManager.isScanning=YES;
        [[UIApplication sharedApplication] setNetworkActivityIndicatorVisible:YES];
    }

    if(self.timer_check==nil)
    {
        self.timer_check = [NSTimer timerWithTimeInterval:20
                                                   target:self
                                                 selector:@selector(timer_function)
                                                 userInfo:nil
                                                  repeats:YES];

        NSRunLoop *runner = [NSRunLoop currentRunLoop];
        [runner addTimer:self.timer_check forMode: NSDefaultRunLoopMode];
    }
    [self.timer_check fire];
}

- (void)centralManagerDidUpdateState:(CBCentralManager *)central
{
    switch (central.state)
    {
        case CBCentralManagerStatePoweredOn:
            break;
        case CBCentralManagerStatePoweredOff:
            break;
        case CBCentralManagerStateUnsupported:
        {
            UIAlertView *alert = [[UIAlertView alloc] initWithTitle:@"Error"
                                                            message:@"Device is Supported"
                                                           delegate:nil
                                                  cancelButtonTitle:@"Dismiss"
                                                  otherButtonTitles:nil];

            [alert show];
            break;
        }
        case CBCentralManagerStateResetting:
        {

            break;
        }
        case CBCentralManagerStateUnauthorized:
            break;

        case CBCentralManagerStateUnknown:
            break;

        default:
            break;
    }
}
- (void)centralManager:(CBCentralManager *)central didConnectPeripheral:(CBPeripheral *)peripheral
{
    DEACentralManager *centralManager = [DEACentralManager sharedService];
    YMSCBPeripheral *yp = [centralManager findPeripheral:peripheral];
    yp.delegate = self;

    [yp readRSSI];

    for (TiBScanTableViewCell *cell in [self.peripheralsTableView visibleCells])
    {
        if (cell.yperipheral == yp)
        {
           [cell updateDisplay];
            break;
        }
    }
}



- (void)centralManager:(CBCentralManager *)central didDisconnectPeripheral:(CBPeripheral *)peripheral error:(NSError *)error
{
    for (TiBScanTableViewCell *cell in [self.peripheralsTableView visibleCells])
    {
        [cell updateDisplay];
    }
}

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

    DEACentralManager *centralManager = [DEACentralManager sharedService];

    YMSCBPeripheral *yp = [centralManager findPeripheral:peripheral];
    if (yp.isRenderedInViewCell == NO)
    {
        yp.isRenderedInViewCell = YES;

        [self.peripheralsTableView reloadData];
    }

    if (centralManager.isScanning)
    {
//        if(advertisementData!=nil)
//        {
//            NSLog(@" ad is %@",advertisementData);
//        }

       for (TiBScanTableViewCell *cell in [self.peripheralsTableView visibleCells])
        {
          if (cell.yperipheral.cbPeripheral == peripheral)
            {
              if (peripheral.state == CBPeripheralStateDisconnected)
                {
                    cell.rssiLabel.text = [NSString stringWithFormat:@"%ld dB", (long)[RSSI integerValue]];

                    cell.distanceLabel.text = [NSString stringWithFormat:@" distance : %0.3fm",[self calculateAccuracyWithRSSI:[RSSI doubleValue]]];
                }
                else
                {
                    continue;
                }
            }
        }
    }
}


- (void)centralManager:(CBCentralManager *)central didRetrievePeripherals:(NSArray *)peripherals {
    DEACentralManager *centralManager = [DEACentralManager sharedService];

    for (CBPeripheral *peripheral in peripherals)
    {
        YMSCBPeripheral *yp = [centralManager findPeripheral:peripheral];
        if (yp)
        {
            yp.delegate = self;
        }
    }

    [self.peripheralsTableView reloadData];

}

- (void)centralManager:(CBCentralManager *)central didRetrieveConnectedPeripherals:(NSArray *)peripherals
{
    DEACentralManager *centralManager = [DEACentralManager sharedService];

    for (CBPeripheral *peripheral in peripherals)
    {
        YMSCBPeripheral *yp = [centralManager findPeripheral:peripheral];
        if (yp)
        {
            yp.delegate = self;
        }
    }

    [self.peripheralsTableView reloadData];
}

#pragma mark - CBPeripheralDelegate Methods

- (void)performUpdateRSSI:(NSArray *)args
{
    CBPeripheral *peripheral = args[0];

    [peripheral readRSSI];
}

- (void)peripheralDidUpdateRSSI:(CBPeripheral *)peripheral error:(NSError *)error {

    if (error)
    {
        NSLog(@"ERROR: readRSSI failed, retrying. %@", error.description);

        if (peripheral.state == CBPeripheralStateConnected)
        {
            NSArray *args = @[peripheral];
            [self performSelector:@selector(performUpdateRSSI:) withObject:args afterDelay:2.0];
        }

        return;
    }

    [self placeRSSI:peripheral];

    DEACentralManager *centralManager = [DEACentralManager sharedService];
    YMSCBPeripheral *yp = [centralManager findPeripheral:peripheral];

    NSArray *args = @[peripheral];
    [self performSelector:@selector(performUpdateRSSI:) withObject:args afterDelay:yp.rssiPingPeriod];
}

-(void)placeRSSI:(CBPeripheral *)per
{
    for (TiBScanTableViewCell *cell in [self.peripheralsTableView visibleCells])
    {
        if (cell.yperipheral)
        {
            if (cell.yperipheral.isConnected)
            {
                if (cell.yperipheral.cbPeripheral == per)
                {
                    cell.rssiLabel.text = [NSString stringWithFormat:@"%@", per.RSSI];
                    cell.distanceLabel.text = [NSString stringWithFormat:@" distance : %0.3fm",[self calculateAccuracyWithRSSI:[per.RSSI doubleValue]]];
                    break;
                }
            }
        }
    }
}

#pragma mark UITableView
- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView
{
    return 1;
}
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
{
    DEACentralManager *centralManager = [DEACentralManager sharedService];
    return centralManager.count;
}
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
    static NSString *CellIdentifier = @"ListCell";

    DEACentralManager *centralManager = [DEACentralManager sharedService];
    YMSCBPeripheral *yp = [centralManager peripheralAtIndex:indexPath.row];

    UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier];

    if (cell == nil)
    {
        cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:CellIdentifier];
    }
    TiBScanTableViewCell *pcell = (TiBScanTableViewCell *)[tableView dequeueReusableCellWithIdentifier:CellIdentifier];
    [pcell configureWithPeripheral:yp];

    yp.isRenderedInViewCell = YES;
    cell = pcell;

    return cell;
}
-(void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
{
    DEACentralManager *centralManager = [DEACentralManager sharedService];
    YMSCBPeripheral *yp = [centralManager peripheralAtIndex:indexPath.row];

    TiBLocateViewController *locate = [self.storyboard instantiateViewControllerWithIdentifier:@"Locate"];
    locate.cbPeripheral=yp.cbPeripheral;
    [self.navigationController pushViewController:locate animated:YES];
}
-(void)timer_function
{
    DEACentralManager *centralManager = [DEACentralManager sharedService];
    for (TiBScanTableViewCell *cell in [self.peripheralsTableView visibleCells])
    {
        NSIndexPath *indexPath = [self.peripheralsTableView indexPathForCell:cell];
        YMSCBPeripheral *yp = [centralManager peripheralAtIndex:indexPath.row];
        [centralManager removePeripheral:yp];
        [self.peripheralsTableView deleteRowsAtIndexPaths:@[indexPath] withRowAnimation:UITableViewRowAnimationAutomatic];
    }
}
-(void)viewWillDisappear:(BOOL)animated
{
    [self.timer_check invalidate];
    self.timer_check = nil;
    [self timer_function];

    DEACentralManager *centralManager = [DEACentralManager sharedService];
    [centralManager stopScan];

    [super viewWillDisappear:YES];
}
- (void)didReceiveMemoryWarning
{
    [super didReceiveMemoryWarning];
}
- (double)calculateAccuracyWithRSSI:(double)rssi
{
    if (rssi == 0) {
        return -1.0;
    }

    double txPower = -70;
    double ratio = rssi*1.0/txPower;
    if (ratio < 1.0) {
        return pow(ratio,10);
    }
    else {
        double accuracy =  (0.89976) * pow(ratio,7.7095) + 0.111;
        return accuracy;
    }
}
@end
  1. 第二个屏幕

    #import "TiBLocateViewController.h" @import 核心位置;

    @interface TiBLocateViewController ()<CLLocationManagerDelegate>
    @property (strong,nonatomic) CLLocationManager *locateManager;
    @end
    
    @implementation TiBLocateViewController
    
    - (id)initWithNibName:(NSString *)nibNameOrNil bundle:(NSBundle *)nibBundleOrNil
    {
        self = [super initWithNibName:nibNameOrNil bundle:nibBundleOrNil];
        if (self) {
            // Custom initialization
        }
        return self;
    }
    
    - (void)viewDidLoad
    {
        [super viewDidLoad];
    
        self.locateManager = [[CLLocationManager alloc]init];
        self.locateManager.delegate=self;
        self.locateManager.desiredAccuracy = kCLLocationAccuracyBest;
    
    }
    
    -(void)viewDidAppear:(BOOL)animated
    {
        [super viewDidAppear:YES];
    
    }
    -(void)locationManager:(CLLocationManager *)manager didChangeAuthorizationStatus:(CLAuthorizationStatus)status
    {
        if ([CLLocationManager authorizationStatus] == kCLAuthorizationStatusAuthorized)
        {
    
            NSUUID *per_uuid = self.cbPeripheral.identifier;
            CLBeaconRegion *beaconRegion = [[CLBeaconRegion alloc]
                                            initWithProximityUUID:per_uuid
                                            identifier:[[NSBundle mainBundle] bundleIdentifier]];
    
            beaconRegion.notifyOnExit=YES;
            beaconRegion.notifyOnEntry=YES;
            beaconRegion.notifyEntryStateOnDisplay=YES;
    
            [manager startMonitoringForRegion:beaconRegion];
            [manager startRangingBeaconsInRegion:beaconRegion];
    
        }
    }
    -(void)locationManager:(CLLocationManager *)manager didStartMonitoringForRegion:(CLRegion *)region
    {
        if ([region isKindOfClass:[CLBeaconRegion class]])
        {
            [manager startRangingBeaconsInRegion:(CLBeaconRegion *)region];
        }
    }
    - (void)locationManager:(CLLocationManager *)manager didEnterRegion:(CLRegion *)region
    {
        if ([region isKindOfClass:[CLBeaconRegion class]])
        {
            [manager startRangingBeaconsInRegion:(CLBeaconRegion *)region];
        }
    }
    -(void)locationManager:(CLLocationManager *)manager didRangeBeacons:(NSArray *)beacons inRegion:(CLBeaconRegion *)region
    {
       for (CLBeacon *beacon in beacons)
       {
           NSLog(@" beacon %@",beacon);
       }
    }
    -(void)locationManager:(CLLocationManager *)manager didFailWithError:(NSError *)error
    {
        NSLog(@" error is %@",error.localizedDescription);
    }
    - (void)locationManager:(CLLocationManager *)manager didExitRegion:(CLRegion *)region
    {
        if ([region isKindOfClass:[CLBeaconRegion class]])
        {
            [manager stopRangingBeaconsInRegion:(CLBeaconRegion *)region];
        }
    }
    - (void)didReceiveMemoryWarning
    {
        [super didReceiveMemoryWarning];
    }
    -(void)viewWillDisappear:(BOOL)animated
    {
        [super viewWillDisappear:YES];
        [self.locateManager stopMonitoringSignificantLocationChanges];
    }
    /*
    #pragma mark - Navigation
    
    // In a storyboard-based application, you will often want to do a little preparation before navigation
    - (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender
    {
        // Get the new view controller using [segue destinationViewController].
        // Pass the selected object to the new view controller.
    }
    */
    
    @end
    

【问题讨论】:

  • 我试图实现的基本问题是定位 CBperipheral。由于 CB 以外围设备结尾,我想在 CLBeacons 中尝试
  • 你从 CB 获取 uuid 并从 CL 开始测距 .. 听起来不错
  • 用代码编辑过的帖子
  • didChangeAuthorizationStatus 在状态没有改变时不会被调用......如果是......它不应该是:D 不要依赖它
  • 我一开始在 ViewDidAppear 块上遇到了同样的问题,所以我想把它移到其他地方;什么也没发生.....:(

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


【解决方案1】:

虽然 iBeacons 使用蓝牙低功耗,但它们不与 iOS 中的 Core-Bluetooth 库一起使用。它们通过核心位置处理。

信标区域根据三个参数定义 - UUID、主要和次要。

iBeacon UUID 与蓝牙 MAC 地址不同 - 它更像是“供应商 ID”。给定供应商或所有者的所有信标都将具有相同的 UUID - 例如Acme Dept store 将为自己分配一个 UUID 并将其分配给他们所有的信标,而 Big Bank Corp 将分配一个不同的 UUID 并将其分配给他们的信标。然后他们可以使用主要和次要来指示不同的位置。例如,百货公司可能有major=store number 和minor=department number(shoes=1,food=2 等等)。对于银行来说,主要可能是分行,次要可能是分行(1=柜员,2=ATM,3=后台)。

还有一些“众所周知的”UUID 正在使用中——例如,您找到了 AirLocate。 Estimote 也有一个默认情况下他们的信标附带的。

当您想要扫描信标区域时,您必须至少指定 UUID。您还可以选择指定主要和次要。当检测到与您正在扫描的信标区域匹配的信标时,您将收到通知(didEnter/ExitRegion 或 didRangeBeacon,具体取决于您激活的模式)。

一些信标可能额外实现 BLE 外围服务和特性以设置其参数(UUID、主要、次要、传输级别),但这不是 iBeacon 规范的一部分,因此不同的供应商将有不同的方法来执行此操作。要使用这些设置,您将使用 Core-Bluetooth。

因此,总而言之,如果您只是处理 iBeacon 方面的事情,那么您不需要对 Core-Bluetooth 做任何事情。您所需要的只是核心位置。

【讨论】:

  • 解释得很清楚。但是CBPeripheral的UUID表示什么?是不是和CLBeaconRegion的Proximity UUID不一样?
  • IBeacons 使用蓝牙低功耗芯片组,因此它们确实有蓝牙 mac,正如我所说,它们可能会暴露辅助 ble 服务,但出于 iBeacon 的目的,您无需担心
  • 所以,基本上我需要知道是哪家公司生产了我的 iBeacons,然后将其编程为 CLBeaconRegion 的邻近 UUID,对吗?
  • 是的,或者可能有供应商提供的应用程序可用于设置自己的 UUID
  • 好的,一个新问题。那么,有了这个东西,我应该有一个网络服务来识别信标并加载一些检测信息,还是iBeacon本身可以携带信息?
猜你喜欢
  • 2017-01-07
  • 2018-12-11
  • 2019-11-25
  • 2016-03-25
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多