Search code examples
androidibeaconibeacon-androidaltbeacon

AltBeacon didEnterRegion()/didExitRegion not working properly with PiBeacon. Methods are randomly being called


I'm fairly new to Android development and Bluetooth LE. I've researched quite a bit before posting here. I'm fairly sure, there's something I'm doing wrong and I cannot figure it out.

I want my android app to execute some code when it gets inside a specified range of a certain Beacon (RaspberryPi with Bluetooth dongle).

This is the command I use on the RPi to start emitting:

sudo hcitool -i hci0 cmd 0x08 0x0008 1E 02 01 1A 1A FF 4C 00 02 15 E2 0A 39
     F4 73 F5 4B C4 A1 2F 17 D1 AD 07 A9 61 00 00 00 00 C8 00

I have edited the BeaconLayout to detect iBeacons:

beaconManager.getBeaconParsers().add(new BeaconParser().
            setBeaconLayout("m:2-3=0215,i:4-19,i:20-21,i:22-23,p:24-24"));

Besides the custom region, the code is from the AltBeacon documentation.

Region region1 = new Region("RaspberryPi", Identifier.parse("E20A39F4-73F5-4BC4-A12F-17D1AD07A961"), null, null);

beaconManager.setMonitorNotifier(new MonitorNotifier() {
        @Override
        public void didEnterRegion(Region region) {
            Log.i(TAG, "I just saw a beacon for the first time!");
        }

        @Override
        public void didExitRegion(Region region) {
            Log.i(TAG, "I no longer see a beacon");
        }

        @Override
        public void didDetermineStateForRegion(int state, Region region) {
            Log.i(TAG, "I have just switched from seeing/not seeing beacons: "+ state);
        }
    });

try {
    beaconManager.startMonitoringBeaconsInRegion(region1);
} catch (RemoteException e) {      }

Now here is part of the log I get. During this time, the beacon did not leave the region. Except for those few calls that happen randomly when I run the app, the methods never get called again:

05-19 23:18:52.487 31204-31220/com.daniellazarov.tempapp D/BluetoothLeScanner: onClientRegistered() - status=0 clientIf=5
05-19 23:18:53.952 31204-31220/com.daniellazarov.tempapp D/BluetoothLeScanner: onClientRegistered() - status=0 clientIf=5
05-19 23:18:55.195 31204-31220/com.daniellazarov.tempapp D/BluetoothLeScanner: onClientRegistered() - status=0 clientIf=5
05-19 23:18:56.570 31204-31220/com.daniellazarov.tempapp D/BluetoothLeScanner: onClientRegistered() - status=0 clientIf=5
05-19 23:18:57.742 31204-31219/com.daniellazarov.tempapp D/BluetoothLeScanner: onClientRegistered() - status=0 clientIf=5
05-19 23:18:57.782 31204-32016/com.daniellazarov.tempapp I/MonitoringActivity: I have just switched from seeing/not seeing beacons: 0
05-19 23:18:57.782 31204-32016/com.daniellazarov.tempapp I/MonitoringActivity: I no longer see a beacon
05-19 23:18:57.790 31204-32016/com.daniellazarov.tempapp I/MonitoringActivity: I have just switched from seeing/not seeing beacons: 0
05-19 23:18:57.790 31204-32016/com.daniellazarov.tempapp I/MonitoringActivity: I no longer see a beacon
05-19 23:18:57.790 31204-32016/com.daniellazarov.tempapp I/MonitoringActivity: I have just switched from seeing/not seeing beacons: 0
05-19 23:18:57.790 31204-32016/com.daniellazarov.tempapp I/MonitoringActivity: I no longer see a beacon
05-19 23:18:58.933 31204-31219/com.daniellazarov.tempapp D/BluetoothLeScanner: onClientRegistered() - status=0 clientIf=5
05-19 23:19:00.098 31204-31220/com.daniellazarov.tempapp D/BluetoothLeScanner: onClientRegistered() - status=0 clientIf=5
05-19 23:19:01.287 31204-31220/com.daniellazarov.tempapp D/BluetoothLeScanner: onClientRegistered() - status=0 clientIf=5
05-19 23:19:01.537 31204-32140/com.daniellazarov.tempapp I/MonitoringActivity: I have just switched from seeing/not seeing beacons: 1
05-19 23:19:01.537 31204-32140/com.daniellazarov.tempapp I/MonitoringActivity: I just saw a beacon for the first time!
05-19 23:19:01.538 31204-32140/com.daniellazarov.tempapp I/MonitoringActivity: I have just switched from seeing/not seeing beacons: 1
05-19 23:19:01.538 31204-32140/com.daniellazarov.tempapp I/MonitoringActivity: I just saw a beacon for the first time!
05-19 23:19:01.539 31204-32140/com.daniellazarov.tempapp I/MonitoringActivity: I have just switched from seeing/not seeing beacons: 1
05-19 23:19:01.539 31204-32140/com.daniellazarov.tempapp I/MonitoringActivity: I just saw a beacon for the first time!
05-19 23:19:02.629 31204-31219/com.daniellazarov.tempapp D/BluetoothLeScanner: onClientRegistered() - status=0 clientIf=5

I'm assuming it has something to do with the Raspberry Pi's transmission rate, but I was unable to change it to something that works.


Solution

  • Nice work! Everything appears to be mostly working. (With the strange exception of seeing three log lines for each distinct log message -- not sure why that is happening.)

    The logs show that you had a dropout in beacon detections which caused an exit event at 05-19 23:18:57.782, then another entry event at 05-19 23:19:01.537. While this time period looks pretty short (about 4 seconds), the dropout must have been significantly longer than that. By default, the Android Beacon Library will not send a region exit event until it has not seen a beacon matching the region definition for 10 seconds. This means there was a period of 14 seconds where your Android device saw no transmissions from the Raspberry Pi.

    It is normal for some transmissions from a beacon to not be received by an Android device. At close range perhaps 80% of packets are received correctly, with the rest lost due to radio noise, collisions, channel issues or other low-level bluetooth factors. If you get really unlucky, you might miss a few transmissions in a row. But missing more than two or three transmissions in a row should be extremely rare.

    This means one of two things is wrong:

    • Your Raspberry Pi is not advertising very frequently (perhaps only once every 5 seconds, which would cause a region exit if you missed two packets in a row).

    • Your Android device is missing a lot of packets. This can sometimes be caused by WiFi/Bluetooth interference on devices with known interference issues like the Nexus 7, Nexus 4, Moto G and Moto X.

    To figure out which one it is try the following:

    1. Turn off WiFi on your Android device. Does this solve the problem?

    2. Increase the transmission rate of the Raspberry Pi BlueZ. You can see how to do this in my answer here.