0

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.

  • Note that the `didDetermineStateForRegion`, `didEnterRegion` and `didExitRegion` callbacks only get called when the beacon starts or stops being detected. If you are expecting regular callbacks while the beacon is visible, you should use the ranging APIs that will call the `didRangeBeaconsInRegion` approximately once per second. – davidgyoung May 20 '16 at 01:17

1 Answers1

0

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.

Community
  • 1
  • 1
davidgyoung
  • 63,876
  • 14
  • 121
  • 204
  • I'm using a Nexus 5 on 6.0.1 for testing. Tried to disable WiFi, nothing changed, not even one call of the method appeared this time. Also, after posting here, I found that exact answer, but I'm not entirely sure what frequency to use for min/max intervals. I used the commands you recommended (second command with A0 00 A0 00). Still nothing. I tried using the Locate app to see if the beacon shows up, it doesn't. On the other hand, when I use the Beacon Scanner app (different app from the playStore) the beacon does show up. Just added the parse info in the Locate app, it shows up there too. – Daniel Lazarov May 19 '16 at 21:59
  • When you say "Still nothing" you mean you still get intermittent exit events? – davidgyoung May 20 '16 at 01:14
  • What I meant was that it did not call the method reliably, I got another set of calls just like the one in the initial post, as well as no call at all the second time I tried. On the other hand I tried the app on a Galaxy s4 running lollipop, and it worked flawlessly. So I'm assuming there is either a bug in marshmallow or some other permissions are required. I'm not sure what I should be looking for. – Daniel Lazarov May 20 '16 at 12:00
  • I just installed Lollipop (5.1.1) on my Nexus 5 and tried the app. Same story all over again. Sometimes when I run the app, and the beacon is emitting, it shows up in the log, but then when I turn the beacon off, it doesn't show up in the log, nor when I turn it back on. Another thing I tried was to run the app with the beacon off and turn it on while the app is running, it still doesn't detect it. [Here](http://pastebin.com/NtgHFtRv) is all the code. – Daniel Lazarov May 21 '16 at 11:10
  • As of version 2.8, the Android Beacon Library maintains state internally of the last known region in/out state. So if you restart your app when the region was "in" you will not get another enter callback until there is first an exit. If you want the extra enter callback, explicitly stop monitoring the region before starting monitoring for it when your app starts. This will clear history. – davidgyoung May 21 '16 at 12:49
  • It was the iBeacon all along. Something wasn't working properly. I used the code from [here](http://www.ioncannon.net/programming/1603/turn-a-raspberry-pi-into-an-ibeacon/) and now it calls the didEnterRegion/didExitRegion methods. Thanks for your help. – Daniel Lazarov May 23 '16 at 14:36