如何知道最近的iBeacon



我有一个代码来知道哪个信标最接近,但当信标的精度为-1.00000时,我遇到了问题,应用程序会取第二个。

因此,有一种海盗会寻找最近的灯塔,寻找其他灯塔,并将最近的灯塔与周围的灯塔进行比较。然后,当我知道哪一个是最接近的信标时,我会向用户显示它的视图,但当其他信标离ipad更近时,视图就很近,并且会显示视图。

我在两台iPad上使用iOS 7.1和7.0.4,第一台是iPad3,第二台是iPad Mini Retina。

这里有代码:

    - (void)locationManager:(CLLocationManager *)manager didStartMonitoringForRegion:(CLRegion *)region {
    [self.locationManager startRangingBeaconsInRegion:self.beaconRegion];
}
- (void)initRegion {
    NSUUID *uuid = [[NSUUID alloc] initWithUUIDString:@"00000000-0000-0000-0000-000000000002"];
    self.beaconRegion = [[CLBeaconRegion alloc] initWithProximityUUID:uuid identifier:@"com.devfright.myRegion"];
    [self.locationManager startMonitoringForRegion:self.beaconRegion];
}
- (void)locationManager:(CLLocationManager *)manager didEnterRegion:(CLRegion *)region {
    NSLog(@"Beacon Found");
    [self.locationManager startRangingBeaconsInRegion:self.beaconRegion];
}
-(void)locationManager:(CLLocationManager *)manager didExitRegion:(CLRegion *)region {
    NSLog(@"Left Region");
    [self.locationManager stopRangingBeaconsInRegion:self.beaconRegion];
}
-(void)locationManager:(CLLocationManager *)manager didRangeBeacons:(NSArray *)beacons inRegion:(CLBeaconRegion *)region {
    CLBeacon *beacon = [[CLBeacon alloc] init];
    CLBeacon *closestBeacon = [[CLBeacon alloc] init];
    closestBeacon = [beacons lastObject];
    //Search for the closest and show the view
    for (int i=0; i<beacons.count; i++) {
        beacon = beacons[i];
        if (beacon.accuracy < closestBeacon.accuracy && beacon.accuracy != -1.000000 && beacon.minor != closestBeacon.minor && beacon.proximity != CLProximityFar) {
            closestBeacon = beacons[i];
            //NSString *closeAccuracy = closestBeacon.minor.stringValue;
        }
        NSLog(@"nActualBeacon:%@nAccuracy:%f", beacon.minor.stringValue,beacon.accuracy);
        NSLog(@"nCloserBeacon: %@nAccuracy:%f", closestBeacon.minor.stringValue, closestBeacon.accuracy);
    }
    NSLog(@"nClosestBeacon: %@", closestBeacon.minor.stringValue);
    if (viewShown == NO) {
        if ([closestBeacon.minor.stringValue  isEqual: @"1"]) {
            actualSection = 1;
            [self immediateDetection];
        }else if ([closestBeacon.minor.stringValue  isEqual: @"2"]){
            actualSection = 2;
            [self immediateDetection];
        }else if ([closestBeacon.minor.stringValue  isEqual: @"3"]){
            actualSection = 3;
            [self immediateDetection];
        }else if ([closestBeacon.minor.stringValue  isEqual: @"4"]){
            actualSection = 4;
            [self immediateDetection];
        }else if ([closestBeacon.minor.stringValue  isEqual: @"5"]){
            actualSection = 5;
            [self immediateDetection];
        }else if ([closestBeacon.minor.stringValue  isEqual: @"6"]){
            actualSection = 6;
            [self immediateDetection];
            NSLog(@"6");
        }else if ([closestBeacon.minor.stringValue  isEqual: @"7"]){
            actualSection = 7;
            [self immediateDetection];
            NSLog(@"7");
        }else if ([closestBeacon.minor.stringValue  isEqual: @"8"]){
            actualSection = 8;
            [self immediateDetection];
            NSLog(@"8");
        }else if ([closestBeacon.minor.stringValue  isEqual: @"9"]){
            actualSection = 9;
            [self immediateDetection];
            NSLog(@"9");
        }else if ([closestBeacon.minor.stringValue  isEqual: @"10"]){
            actualSection = 10;
            [self immediateDetection];
            NSLog(@"10");
        }else if ([closestBeacon.minor.stringValue  isEqual: @"11"]){
            actualSection = 11;
            [self immediateDetection];
            NSLog(@"11");
        }else if ([closestBeacon.minor.stringValue  isEqual: @"30"]){
            actualSection = 30;
            [self immediateDetection];
        }
    } else if (viewShown == YES) {
        if (closestBeacon.minor.integerValue != actualSection) {
            //Alarm: Beacon 11
//            if (closestBeacon.minor.integerValue != 11 || closestBeacon.minor.integerValue != 10) {
                [self dismissViewControllerAnimated:NO completion:nil];
                //actualSection = 0;
                viewShown = NO;
//            }
        }
    }
}
- (void)immediateDetection
{
    viewShown = YES;
    if (self.presentedViewController)
    {
        return;
    }
    if (actualSection == 1) {
        SectionViewController *sectionView = [[SectionViewController alloc] init];
        sectionView.section = 1;
        [self presentViewController:sectionView animated:NO completion:nil];
        sectionView.lbl_name.text = self.lbl_name.text;
    }else if (actualSection == 2){
        SectionViewController *sectionView = [[SectionViewController alloc] init];
        sectionView.section = 2;
        [self presentViewController:sectionView animated:NO completion:nil];
        sectionView.lbl_name.text = self.lbl_name.text;
    }else if (actualSection == 3){
        SectionViewController *sectionView = [[SectionViewController alloc] init];
        sectionView.section = 3;
        [self presentViewController:sectionView animated:NO completion:nil];
        sectionView.lbl_name.text = self.lbl_name.text;
    }else if (actualSection == 4){
        SectionViewController *sectionView = [[SectionViewController alloc] init];
        sectionView.section = 4;
        [self presentViewController:sectionView animated:NO completion:nil];
        sectionView.lbl_name.text = self.lbl_name.text;
    }else if (actualSection == 5){
        SectionViewController *sectionView = [[SectionViewController alloc] init];
        sectionView.section = 5;
        [self presentViewController:sectionView animated:NO completion:nil];
        sectionView.lbl_name.text = self.lbl_name.text;
    }else if (actualSection == 6){
        SectionViewController *sectionView = [[SectionViewController alloc] init];
        sectionView.section = 6;
        [self presentViewController:sectionView animated:NO completion:nil];
        sectionView.lbl_name.text = self.lbl_name.text;
    }else if (actualSection == 7){
        SectionViewController *sectionView = [[SectionViewController alloc] init];
        sectionView.section = 7;
        [self presentViewController:sectionView animated:NO completion:nil];
        sectionView.lbl_name.text = self.lbl_name.text;
    }else if (actualSection == 8){
        SectionViewController *sectionView = [[SectionViewController alloc] init];
        sectionView.section = 8;
        [self presentViewController:sectionView animated:NO completion:nil];
        sectionView.lbl_name.text = self.lbl_name.text;
    }else if (actualSection == 9){
        SectionViewController *sectionView = [[SectionViewController alloc] init];
        sectionView.section = 9;
        [self presentViewController:sectionView animated:NO completion:nil];
        sectionView.lbl_name.text = self.lbl_name.text;
    }else if (actualSection == 10){
        ThiefAlarmViewController *thiefAlarmView = [[ThiefAlarmViewController alloc] init];
        [self presentViewController:thiefAlarmView animated:NO completion:nil];
    }else if (actualSection == 11){
        ThiefAlarmViewController *thiefAlarmView = [[ThiefAlarmViewController alloc] init];
        [self presentViewController:thiefAlarmView animated:NO completion:nil];
    }else if (actualSection == 30){
        SectionViewController *sectionView = [[SectionViewController alloc] init];
        sectionView.section = 30;
        [self presentViewController:sectionView animated:NO completion:nil];
        sectionView.lbl_name.text = self.lbl_name.text;
    }
}

当我知道最接近的iBeacon时,我会显示它的视图,但当它的准确度为-1.00000,与其他应用程序相比,应用程序会选择第二个,因为第一个的准确度=-1.00000。

希望有人能帮助我,因为我不知道该怎么办,也许这是iBeacon的问题,但我认为这个问题有解决方案。

谢谢。

locationManager:didRangeBeacons:inRegion:将按接近顺序返回信标列表。也就是说,列表中的第一个信标将离您最近。

然而,这个规则有一个例外:如果任何信标的接近度为未知,那么它们将位于列表的顶部(因为它们的准确度为-1)。为此,只需过滤掉任何未知信标,然后选择列表中的第一个:

beacons = [beacons filteredArrayUsingPredicate:[NSPredicate predicateWithFormat:@"proximity != %d", CLProximityUnknown]];
CLBeacon *nearestBeacon = [beacons firstObject];

首先:将locationManager:didRangeBeacons:inRegion:的长else/if替换为:

if (([closestBeacon.minor intValue] > 0 && [closestBeacon.minor intValue] <= 11) || [closestBeacon.minor intValue] == 30)
{
    actualSection = [closestBeacon.minor intValue]; 
    [self immediateDetection];
}

immediateDetection中的长else/if替换为:

if ((actualSection > 0 && actualSection < 10 || actualSection == 30)
{
    SectionViewController *sectionView = [[SectionViewController alloc] init];
    sectionView.section = actualSection;
    [self presentViewController:sectionView animated:NO completion:nil];
    sectionView.lbl_name.text = self.lbl_name.text;
}
else if (actualSection == 10 || actualSection == 11)
{
    ThiefAlarmViewController *thiefAlarmView = [[ThiefAlarmViewController alloc] init];
    [self presentViewController:thiefAlarmView animated:NO completion:nil];
}
else
{
}

这将为您节省大量代码。

对于您的问题,您可以这样做:

    NSPredicate *predicateIrrelevantBeacons = [NSPredicate predicateWithFormat:@"(self.accuracy != -1) AND ((self.proximity != %d) OR (self.proximity != %d))", CLProximityFar,CLProximityUnknown];
NSArray *relevantsBeacons = [beacons filteredArrayUsingPredicate: predicateIrrelevantBeacons];
    NSPredicate *predicateMin = [NSPredicate predicateWithFormat:@"self.accuracy == %@.@min.accuracy", relevantsBeacons];
    CLBeacon *closestBeacon = nil;
    NSArray *closestArray = [[relevantsBeacons filteredArrayUsingPredicate:predicateMin];
    if ([closestArray count] > 0)
        closestBeacon = [closestArray objectAtIndex:0];
   if (closestBeacon)
   { //Do your thing }
   else
   {//No relevant close beacon}

除了过滤掉-1的接近值外,您还必须考虑某些iBeacon定期不会出现在对didRangeBeacons: inRegion的回调中的情况。这可能是由于无线电干扰,尤其是对于不经常发送广告的电池供电信标。

要解决这个问题,你需要保留你自己的最近看到的信标列表,并跟踪过去几秒钟内看到的任何信标。如果其中一个信标的接近度为-1,您可以不将其放在列表中,或者如果不存在,则重复使用上一个已知的非-1接近度值。

您需要考虑的另一个因素是,接近度值会反弹很多。你可能需要在你的算法中添加一些滞后逻辑,这样哪个信标最接近就不会每秒来回跳动。具体的操作方式取决于您的用例。

相关内容

  • 没有找到相关文章

最新更新