首页 文章

CLBeacon未被检测到

提问于
浏览
0

我想了解CLBeacons的工作原理 . 我之前曾使用过CBPeripherals,它实际上是BLE设备的核心蓝牙框架实现 .

我做的是以下步骤:

  • 使用CBPeripheralManager来检测我周围的信标,(获取每个信标的个人标识符) .

  • 使用要在UITableView上显示的数据

  • 在选择Tableview时,我将CBPeripheral对象本身传递给另一个我有CLLocationManager的类 . 在这里,我使用CBPeripheral对象的邻近UUID和该区域中的startToRangeBeacons定义CLBeaconRegion .

没有信标出现 .

出人意料的是,当我使用[NSUUID页头] 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
  • 第二个屏幕

#import“TiBLocateViewController.h”@import CoreLocation;

@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

1 回答

  • 1

    虽然iBeacons使用蓝牙低功耗,但它们并未与iOS中的Core-Bluetooth库一起使用 . 它们通过Core Location处理 .

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

    iBeacon UUID与蓝牙MAC地址不同 - 它更像是“供应商ID” . 给定供应商或所有者的所有信标都将具有相同的UUID - 例如Acme Dept商店将为自己分配一个UUID并将其分配给所有信标,而Big Bank Corp将分配一个不同的信标并将其分配给他们 . 然后,他们可以使用主要和次要来指示不同的位置 . 例如,百货商店可能有主要=商店号码和次要=部门号码(鞋子= 1,食物= 2等等) . 银行专业可能是分支机构,而辅修专业可能是分支机构(1 =出纳员,2 = ATM,3 =后台) .

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

    如果要扫描信标区域,则必须至少指定UUID . 您还可以选择指定主要和次要 . 当检测到与您正在扫描的信标区域匹配的信标时,您将收到通知(取决于您已激活的模式,输入/退出区域或didRangeBeacon) .

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

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

相关问题