Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to set time for scanning interval for iBeacon on iOS?

I'm developing an app with iBeacon support. Basically, I have a single view that updates its content according to the nearest beacon, and to scan beacons, I use no framework (just the CoreLocation from Apple), even though I use Estimote Beacons.

The problem is that my application doesn't detect the beacons instantaneously, I have to wait about 5 seconds in front of a beacon in order to get the content updated, while the Estimote app detects the beacons within 1-2 seconds. My Estimote beacons are configured to advertise every 960 ms.

How is that possible ? Can I set a time interval to scan for beacons ? How to improve my app to update the view faster ?

Here is the code I use to initialize the location manager and to update the view :

// ViewController.h =================
@property (strong, nonatomic) CLLocationManager *locationManager;

// ViewController.m =================
-(void)initBeaconMonitor {
    NSUUID *estimoteUUID = [[NSUUID alloc] initWithUUIDString:estimoteBeaconUUID];
    _region = [[CLBeaconRegion alloc] initWithProximityUUID:estimoteUUID major:estimoteBeaconMajor identifier:beaconRegionIdentifier];

    self.locationManager = [[CLLocationManager alloc] init];
    // For iOS 8
    if([self.locationManager respondsToSelector:@selector(requestAlwaysAuthorization)]) {
        [self.locationManager requestAlwaysAuthorization];
    }

    self.locationManager.delegate = self;
    self.locationManager.pausesLocationUpdatesAutomatically = NO;

    [self.locationManager startMonitoringForRegion:_region];
    [self.locationManager startRangingBeaconsInRegion:_region];
    [self.locationManager startUpdatingLocation];
}

-(void)locationManager:(CLLocationManager *)manager didRangeBeacons:
(NSArray *)beacons inRegion:(CLBeaconRegion *)region {

    if(beacons.count > 0) {
        CLBeacon *nearestBeacon = beacons.firstObject;

        if(nearestBeacon == _lastBeacon) {
            return;
        }

        _lastBeacon = [nearestBeacon copy];

        switch(nearestBeacon.proximity) {
            case CLProximityFar:
                break;
            case CLProximityNear:
                [self updateViewWithBeacon:nearestBeacon];
                break;
            case CLProximityImmediate:
                [self updateViewWithBeacon:nearestBeacon];
                break;
            case CLProximityUnknown:
                return;
        }
    }
}
like image 542
Mohamed Amine Avatar asked Apr 17 '15 09:04

Mohamed Amine


1 Answers

You cannot change the beacon scanning interval on iOS. When ranging in the foreground, iOS will constantly scan for beacons so this is not what is causing delays.

The problem is that the app logic will only update the UI once CoreLocation determines the beacon is in Near/Immediate proximity and the beacon is closest according to the sorted position in the beacons array. Both the sorting and the value of the proximity field are based on CoreLocation's distance estimate to the beacon (the accuracy field), and this is based on a 20 second running average of the signal strength between the mobile device and the beacon. It is this 20 second running average that is causing the delays you mention, because the distance estimate updates slowly and does not reach a steady state until the mobile device has been in the same place relative to all beacons for 20 seconds. Unfortunately, this 20 seconds is fixed and not configurable.

For faster responsiveness, you can stop using the accuracy field and sorted order of the beacon within the array. A few alternatives:

  1. Change your logic to not be based on distance at all, perhaps based on timing and what beacons have been seen before.

  2. Switch to using the rssi field as a proxy for distance. This field is averaged over only 1s, but be aware that it has as lot if variability due to radio noise. Less negative values for this field indicate closer beacons. Increasing the beacon transmission frequency as @heypiotr suggests in his answer will help give more stable RSSI numbers.

  3. Manually calculate your own running average of RSSI over a shorter time interval (2-5 secs) for a better tradeoff between rapid updates in distance estimation and stability.

You can read more about how iBeacon ranging works here:

http://developer.radiusnetworks.com/2014/12/04/fundamentals-of-beacon-ranging.html

like image 196
davidgyoung Avatar answered Sep 21 '22 12:09

davidgyoung