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
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(...)
Related
I use android phone to detect a beacon using startScan method, the interval time of beacon adversing is 800ms, but I got the beacon data from callback of startScan every 3~10 seconds. My expectation is I can get the data every 1 second.
Below is my codes. So is there any other ways to get my expectation. Or someone can explain why the interval time is not the same as the adversing time ?
ScanSettings.Builder builder = new ScanSettings.Builder()
.setScanMode(ScanSettings.SCAN_MODE_LOW_LATENCY);
// scan filters has been set the right value.
bluetoothLeScanner.startScan(scanFilters, builder.build(), scanCallback);
Nothing about the code shown is a problem. I can confirm your expectation is met with equivalent code in other apps on other devices. This suggests a problem with :
Your BLE device not advertising as often as you expect
Your Android phone (possible but unlikely)
Some other aspect of your code that you did not show in your question.
Is you BLE device a beacon? If so, I suggest:
Install BeaconScope on the same phone, scan for your beacon, then check the PPS rating (Packets Per Second -- scan for at least 30 seconds until the measurement stabilizes). If you see a value of 0.1-0.3 then the problem is NOT with your code and must be (1) or (2). If you see a much higher PPS value, the problem is with some other aspect of your code not shown.
Use a second Android phone with BeaconScope as a transmitter and transmit a beacon at the 10 Hz default rate. Does your app get a packet every 100-200ms? If so, you have confirmed the problem is with your BLE device not transmitting as much as you expect.
If your BLE device is not a beacon you can at least perform the second test.
It's recommended to use 'SCAN_MODE_LOW_LATENCY' mode only hen the application is running in the foreground.
Incase you are in background, you can run a sticky foreground service and set a periodic frequency of 1 sec for your service.
Also scanning Ble for every 1 sec might be extremely heavy for the app.
Hello I am poor at English.
I use Android Beacon Library
implementation 'org.altbeacon:android-beacon-library:2.15.2'
My Android application gradle imformation
compileSdkVersion 28
minSdkVersion 21
targetSdkVersion 28
My Beacon manager information
beaconManager.getBeaconParsers().add(new BeaconParser().setBeaconLayout("m:2-3=0215,i:4-19,i:20-21,i:22-23,p:24-24"));
beaconManager.setForegroundScanPeriod(1100L);
beaconManager.setBackgroundScanPeriod(1100L);
beaconManager.setForegroundBetweenScanPeriod(0);
beaconManager.setBackgroundBetweenScanPeriod(0);
beaconManager.enableForegroundServiceScanning(notificationcompatBuilder_Scannging.build(),456);
beaconManager.setEnableScheduledScanJobs(false);
BeaconManager.setDebug(true);
regionBootstrap = new RegionBootstrap(this, myBeaconRegion);
Error
I want to develop all day beacon scanner application.
So I use regionBootstrap to scan in background.
It looked like it was working.
However time passed and Exit Event suddenly occurred and Enter Event occurred shortly after.
I think scan does not work for a few seconds and I have conducted a test on this.
Error Test 1
one smartphone , two beacons
Error1
One beacon signal is not detected for more than 10 seconds while another beacon signal is detected.
So I think scan work well and it is a problem of beacon.
Error Test 2
two smartphone , two beacons
smartphone 1
enter image description here
smartphone 2
enter image description here
In smartphone 1 Logcat, Also One beacon signal is not detected for more than 10 seconds while another beacon signal is detected.
In smartphone 2 Logcat, Unscanned beacon is being scanned at the same time.
So beacon does not problem and I can't find reason.
Error Test 3
Added test
two smart phone
My beacon transmit the signal about once every three seconds.
In smart phone 1, download the other beacon application which has beacon signal transmit and transmit at 1Hz.
In smart phone 2, by using my application, watch the signal.
enter image description here
The beacon signal of smart phone 1 increase markedly, but the same problem arose.
Does anyone know about this matter?
I want a help...
Please
I suspect that the beacons you are using to test are not transmitting frequently enough. Manufacturers often reduce the transmission rate to save battery. When the transmission rate gets below 1Hz, this can cause problems, because not 100% of beacon packets transmitted are received by any phone. Radio noise often causes packets to be missed. If one device misses a few packets in a row (it happens sometimes) it causes a region exit event.
The solution is to increase the frequency at which the beacons transmit. With some manufacturers this is configurable. With others, it is not. If it is not configurable, you may need to buy different beacons
You can test if this is the problem by using an Android beacon simulator app on one of the devices. Try my BeaconScope app, which will advertise at 10Hz by default.
This library return result only when a specific event is triggered, not for all beacon scanned.. if you need this I suggest you to use the standart android standard beacon library, if you want to know more about this and how to implements comment this post and I'll edit it with the implementation
I've seen a lot of discussions on battery for altbeacon, specially if beacons are inside a region for a long time. This post was actually very clarifying.
I am currently working in a solution that requires a good sensibility (which I define as being a small detection time for a new beacon in a region).
As some beacons may be anonymous (which I define as presenting unexpected MAC addresses but share a same matching byte sequence) to the scanner in this particular solution, I would like to achieve good sensibility to new beacons but also a balanced battery impact to the user.
What concerns me is if a first beacon is found and the region triggers based on the matching sequence, how could I get a notification once another beacon approaches (or leaves) ?
A guess I was going to try was to keep monitoring for a generic matching sequence and once a beacon is found for that general sequence, range it to get its address and them create a particular region for the mac I've taken. The only problem with this approach was how could I prevent the first beacon to keep triggering the generic region?
And just out of curiosity. Is the ScanFilter class related to those hardware filters introduced on android 5?
Thank you,
If you need to quickly find new beacons with the same byte patterns as ones that already exist in the vicinity, you really have no choice but to keep ranging.
In such a situation, there is no distinction between ranging and monitoring in terms of battery consumption. Both will require constant Bluetooth scans and decoding of all beacons in the vicinity. Scan filters (yes, the hardware filters introduced in Android 5,) will not help because you expect the byte patterns to be the same. There is no such thing as a packet "does not match" scan filter that could be used to find only new MAC addresses.
You may need to accept the battery drain of constant scans and just try to limit how long they last, if your use case allows. Short scans of 30 minutes or less might be acceptable.
You could possibly save some battery by writing your own BLE scanning parsing code tailored to this use case. You could first look for unique MAC addresses, and only do further processing and parsing if the MAC address has never been seen before. This will not reduce battery usage from the constant scan, but it would cut down on battery usage from CPU expended on parsing packets. This might save 10-30% depending on the number of beacons in the vicinity.
Bottom line: you are right to be concerned about battery usage with this use case.
I am attempting to intermittently scan for nearby beacons and store off every received beacon with a particular manufacturer code. How do I use the altbeacon Library to start and stop scanning for altbeacons with a specific manufacturer code and store off every received beacon during each scan? I would like for the scanner to scan for 20 seconds every 5 minutes after the activity has been created.
#davidgyoung
For the manufacturer code 268 (hex 0x0112), you can match this with the following BeaconParser setup code:
beaconManager.getBeaconParsers().clear();
beaconManager.getBeaconParsers().add(new BeaconParser().setLayout("m:0-3=1201beac,i:4-19,i:20-21,i:22-23,p:24-24,d:25-25"));
Note that in the layout string, the two hex bytes of the manufacturer code are put as the first part of the "matching" m expression m:0-3=1201beac. They are in reverse "little endian" order because this is how they appear in the packet. So 0x0112 becomes m:0-3=1201. Similarly if you were using radius networks 0x0118 company code, you would use m:0-3=1801.
The regular ranging APIs will return you a list of all beacons that match this. To scan for 20 seconds out of every 5 minutes, simply use:
beaconManager.setForegroundScanPeriod(20000l); // 20,000 ms
beaconManager.setForegroundBetweenScanPeriod(280000l);// 280,000 ms + 20,000 ms = 5 minutes
I am using android beacon library to detect beacons.I have created a service which implements Bootstrap Notifier and It got two methods :
#Override
public void didEnterRegion(Region arg0) {
Log.i(TAG, "A beacon has enter the region .........");
}
#Override
public void didExitRegion(Region arg0) {
Log.i(TAG, "A beacon has exit the region .........");
}
and also :
mAllBeaconsRegion = new Region("all beacons", Identifier.parse(UUID),null, null);
mBeaconManager = BeaconManager.getInstanceForApplication(this);
new BackgroundPowerSaver(this);
bootstrap = new RegionBootstrap(this, mAllBeaconsRegion);
mBeaconManager.setBackgroundScanPeriod(1000l);
mBeaconManager.setBackgroundBetweenScanPeriod(1000l);
My problem is that in some devices beacon exits the region automatically and didExitRegion called and then re-enters in region and didEnterRegion called.It again disconnects automatically.
This is happening in loop. I am testing it with Lollipop.
How can i get rid of this?
Please help.
It is important to understand what causes a Region exit. A region exit fires when no advertising packets from a beacon matching a Region object are detected in a 10 second period. There are a number of things that can cause this:
Hardware beacons that do not advertise frequently enough. For best performance, beacons should advertise at a rate of 10 Hz or more. Some manufacturers slow down the advertising rate to save battery, making beacons advertise only every 5 seconds or so. This can cause region exits if some of the packets are missed by the receiver due to radio noise or other issues. To solve this problem, configure your beacon to advertise at least once per second (1 Hz.)
Beacons being on the edge of the radio range of the mobile device. Bluetooth beacons have a varying range of 2-50 meters, depending on the manufacturer, settings, placement and the antenna on the receiving mobile device. If the signal is very weak, detections an be intermittent, causing exits if no packets have been seen in 10 seconds. To fix this, increase the transmitter power of your beacon, or add a software filter to ignore intermittent exit events.
Some mobile devices (e.g. Moto X, Moto G, Nexus 4, Nexus 7) have a hardware flaw where bluetooth and WiFi do not work simultaneously. This can cause the symptoms you describe because it makes beacon detections intermittent. To solve this problem, disable WiFi when looking for beacons on one of these devices.