CLBeacons的地理围栏

时间:2014-08-11 13:28:18

标签: ios cllocationmanager ibeacon

我正在尝试为CLbeacons建立地理围栏,如下所示: 一个&GT;任何能够检测到精度<= 2.5米距离的信标。

现在,当我将信标放置在大约7米的距离时,两者都会被检测到。更令人震惊的是,信标的准确度有时会达到15.70米(通过运行Airlocate应用程序检查),这种情况随机发生,从而无法构建地理围栏。

我尝试应用自定义公式计算信标距离double accuracy = (0.89976) * pow(ratio,7.7095) + 0.111; double ratio = rssi*1.0/txPower;,但由于未提供CLbeacons的txPower,因此该函数依赖于我提供静态值为txPower。

任何人都可以指导如何构建这些CLBeacons的地理围栏吗?

1 个答案:

答案 0 :(得分:0)

你是正确的,因为信标的准确度值可以在短时间内大幅波动。我处理这个问题的方式(我们有类似的需要确定何时将设备返回到基本位置)是两种方法的组合:首先,我们调整iBeacons的功能以降低它们以便执行didDetermineState:委托调用进入和离开信标的范围不会被多次调用。其次,我的iBeacon模型跟踪范围内任何信标的准确性并将其平均化。这样,有人走在设备和信标之间,或者用户以特定的方式转动设备,不会导致精度值的巨大波动,从而弄乱你的逻辑。

我不相信Apple希望开发人员将iBeacons用作室内地理位置。它的地理围栏方面是简单地调整发射功率,以便您可以获得设备何时可以检测到信号的通知。可以使用准确度,但它是如此不准确,应谨慎使用。

有一位开发人员声称开发了一种使用iBeacons进行室内定位的算法,但我没有使用它。此外,如果可以达到任何精度水平,我觉得Apple会将它用于室内定位功能,但事实并非如此。

以下是我使用的一些代码:

这是我的自定义MyBeacon类:

@interface MyBeacon()

    @property NSMutableDictionary *accuracyHistory;

@end


@implementation MyBeacon


- (id) init
{
    self = [super init];
    if (self!=nil) {
        self.accuracyHistory = [[NSMutableDictionary alloc] init];
    }
    return self;
}

- (void) addAccuracyValue:(CGFloat)rangeValue forDate:(NSDate *)rangeDateTime
{

    [self removeOldRangeHistoryItems];
    [self.accuracyHistory setObject:[NSNumber numberWithFloat:rangeValue] forKey:rangeDateTime];

}

- (double) getBeaconAverageAccuracy
{
    [self removeOldRangeHistoryItems];
    if( self.accuracyHistory.count == 0 )
    {
        return -1;
    }

    CGFloat sumRangeVals = 0.0;
    int numRangeVals = 0;

    for(NSDate *accuracyDateTime in self.accuracyHistory) {

        NSNumber *curValue = [self.accuracyHistory objectForKey:accuracyDateTime];

        if( [curValue floatValue] >= 0.0 )
        {
            sumRangeVals += [curValue floatValue];
            numRangeVals++;
        }
        else // let's toy with giving unknown readings a value of 30.
        {
            sumRangeVals += 30;
            numRangeVals++;

        }

    }

    CGFloat averageRangeVal = sumRangeVals / numRangeVals;

    return averageRangeVal;
}

- (void) removeOldRangeHistoryItems
{
    NSMutableArray *keysToDelete = [[NSMutableArray alloc] init];
    for(NSDate *accuracyDateTime in self.accuracyHistory) {

        // remove anything older than 10 seconds.
        if( [accuracyDateTime timeIntervalSinceNow] < -10.0 )
        {
            [keysToDelete addObject:accuracyDateTime];
        }
    }

    for( NSDate *key in keysToDelete )
    {
        [self.accuracyHistory removeObjectForKey:key];
    }
}

@end