3

I created an android (java) application that uses the altbeacon library (github page) to detect beacons via the Bluetooth module.

The Beacons are configured with Eddystone UID, protocol with an advertising interval of 100ms and transmit power level of strong (10dBm). What I would like to be able to do is to detect the RSSI value of the beacons with a frequency of 10Hz (i.e. 100ms).

I've already prepared a service that implements the altbeacon library, the relevant part are showed below:

mBeaconManager = BeaconManager.getInstanceForApplication(this);

        beaconRegion = new Region("beacon_region", null, null, null);

        // use Eddystone protocol
        mBeaconManager.getBeaconParsers().add(new BeaconParser().
                setBeaconLayout(BeaconParser.EDDYSTONE_UID_LAYOUT));

        mBeaconManager.setAndroidLScanningDisabled(true);
        mBeaconManager.setForegroundScanPeriod(100l); // scan frequency
        mBeaconManager.setForegroundBetweenScanPeriod(0);

and the callback didRangeBeaconsInRegion from which I see the beacons and get the RSSI value is this:

@Override
    public void didRangeBeaconsInRegion(Collection<Beacon> beacons, Region region) {
        Log.i(BeaconDataCollectorService.class.getSimpleName(), String.format("Found %s beacons in range", beacons.size()));
    }

What's my problem? Running the app, I notice that within didRangeBeaconsInRegion, I often don't see all the beacons.

I ran the data collection for a few seconds, creating a csv format of the data obtained, where you can see that I often have 0s (indicating that the beacon was not detected); I put the sharing of this csv on pastebin (https://pastebin.com/zkUZC5R4)

How can I improve the scan frequency by always being able to detect all the beacons?

altbeacon version used:

implementation 'org.altbeacon:android-beacon-library:2.16.3'

Android version: 9

Thanks

Twisha Kotecha
  • 1,082
  • 1
  • 4
  • 18
fabchi
  • 33
  • 3

1 Answers1

2

Unfortunately, the library is not designed to do this, as the ranging APIs are modeled after iOS equivalents which give aggregate detections at fixed intervals as opposed to access to individual packets when they arrive.

The main reason you often get 0 beacons detected with such a short scan period is because the scan is turned on and off every 100ms, and it takes 10ms or so to start and stop. This gives a good probability of missing the detection.

Here's the good news: If the library ever detects two beacon packets in the same scan period then it will stop turning the scan off and your detection rate will improve. But getting it to detect two beacons in 100ms is nearly impossible of your beacon advertises at a nominal 10Hz.

One thing you might try is to start by setting the scan period to 1 second. After you have detected a finite number of your beacons for 10 secs or so, there is a very good chance you will have detected two beacons in one scan cycle and then you can switch to a scan period of 100ms and get a higher detection rate.

You will never get a 100% detection rate for two reasons:

  • Not all beacon packets transmitted are received due to collisions and radio noise. At close range 80-90% is typical.

  • "BLE advertisers do not advertise at regular intervals. They randomize when their packets are sent to avoid collisions. A nominal 10Hz transmitter might have anywhere between 70ms and 140ms between individual packets, so for fixed scan cycles of 100ms sometimes there will be 0, 1 or 2 Packers eligible to be received.

If you really need to get callbacks on every detection, you might try setting up a NonBeaconBleScanCallback in the BeaconManager, then calling BeaconManager.clearBeaconParsers(). This will cause all beacons detections to be sent to that callback immediately when detected. You will then have to construct a new BeaconParser for use inside that callback to decode the beacon from the raw packet. Use beaconParser.parse(...)

davidgyoung
  • 63,876
  • 14
  • 121
  • 204
  • Thanks @davidgyoung. I tried to change after 10s the `mBeaconManager.setForegroundScanPeriod` from `1000ms` to `100ms` but it seems that at runtime you cannot change the scan value. I also tried to set up a scan of `300ms`, where the beacons emitting at `100ms` should have caught them all, but even so I can't detect them – fabchi Feb 20 '20 at 14:17
  • Why do you say "even so I can't detect them?" I thought your problem was that they were intermittently detected at 100ms? Does it really not detect at all at 300ms? Two points: (1) if you cannot detect them at all at 300ms something is wrong. Try using an off-the-shelf beacon detector like BeaconScope (also using this library) and make it says your beacons are doing what you think they are doing. (2) You can force the scan periods to take effect by calling `beaconManager.updateScanPeriods()` – davidgyoung Feb 20 '20 at 18:39
  • What I tried to do is to leave the beacon emission frequency at `100ms`, while from the library I set the scan frequency to `300ms`. In this way (theoretically) should I always be able to detect a packet emitted by beacons every `300ms` right? But that doesn't happen, because even with this configuration I often have 0 (i.e. if I have 3 beacons, I often only detect 2 in the callback). – fabchi Feb 21 '20 at 09:07
  • Again, you can never detect 100 percent of transmitted packets. If you try the BeaconScope app, it will tell you a packets per second receive rate using a scan interval of 1 second and a scan that does not stop. This will tell you approximately what is achievable. But remember, at 10 Hz transmission there will always be some 100ms periods where the beacon really does not transmit any packets because the transmission rate is not precisely regular. Similarly, in any 300ms period the beacon may transmit only one packet, and there is a 10-20% chance that any packet will not get received. – davidgyoung Feb 22 '20 at 11:27