Android Beacon Library - Some beacons aren't being detected in each scan, even though the position is the same

119 Views Asked by At

I have 10 beacons to be detected by the library, they are placed randomly across a 10 meter radius.

In each scan, I only get 3-4 beacons to be detected, and in the following scan (with the same exact phone position) 2 or 3 of those disappear and I end up with only 1 update.

In the first scan:

D/Beacon: 3 :RSSI:-79 Distance: 3,66 
D/Beacon: 1 :RSSI:-73 Distance: 4,22
D/Beacon: 2 :RSSI:-77 Distance: 2,66
D/Beacon: 4 :RSSI:-85 Distance: 3,26 

Then in the following scan:

D/Beacon: 1 :RSSI:-82 Distance: 3,55 
D/Beacon: 2 :RSSI:-72 Distance: 2,58

And next:

D/Beacon: 6 :RSSI:-73 Distance: 3,11
D/Beacon: 2 :RSSI:-73 Distance: 2,52

Is there any specific reason behind this, and if so, is there a way to solve it or minimize these events?

For example, would specifying the UUID for the region to scan help this cause?

1

There are 1 best solutions below

0
davidgyoung On

It seems your beacons are often not detected in during the ranging cycle. This typically happens because they are not advertising frequently enough. When a beacon does not appear in the list, that is the Android Beacon Library's way of telling you that the beacon was not detected since the last ranging callback.

It's easy to add smoothing logic if you want to keep treating them as visible despite the fact that they haven't been detected in awhile. Here's a class that does exactly that, retaining them for a minimum of 10 seconds before it will drop them off the detected list:

import org.altbeacon.beacon.Beacon
import java.util.ArrayList

/*
 * This class is used to smooth out the beacon ranging data to prevent periodic dropouts.  By
 * default, it will retain beacons in the list if detected in the past 10 secconds, but you can 
 * adjust this with the smoothingWindowMillis property.
 * 
 * To use this class, simply add it to your project and call a line like below wherever you get 
 * an update of ranged beacons (in an observer or in didRangeBeacons):
 * 
 *  val smoothedBeacons = BeaconRangingSmoother.shared.add(beacons).visibleBeacons
 */
class BeaconRangingSmoother {
    private var beacons: ArrayList<Beacon> = ArrayList<Beacon>()
    var smoothingWindowMillis: Long = 10000
    var visibleBeacons: List<Beacon> = ArrayList<Beacon>()
        get() {
            var visible = ArrayList<Beacon>()
            for (beacon in beacons) {
                if (System.currentTimeMillis() - beacon.lastCycleDetectionTimestamp < smoothingWindowMillis) {
                    visible.add(beacon)
                }
            }
            return visible
        }
    fun add(detectedBeacons: Collection<Beacon>): BeaconRangingSmoother {
        for (beacon in detectedBeacons) {
            beacon.lastCycleDetectionTimestamp = System.currentTimeMillis()
            beacons.add(beacon)
        }
        return this
    }    
    companion object {
        val TAG = "BeaconRangingSmoother"
        val shared = BeaconRangingSmoother()
    }
}

To use this class, place the following line wherever you get beacon ranging updates:

val smoothedBeacons = BeaconRangingSmoother.shared.add(beacons).visibleBeacons

The above will convert the list beacons with dropouts (beacons) to one without dropouts (smoothedBeacons).