iBeacon Transmission seems unstable, Altbeacon android Kotlin - altbeacon

When I tried to create iBeacon and then detect the beacon for some region range notifier does't notify the bacon for very small interval of time after again it starts appearing but there is drop for second and beacon gets disappear and again is start to appear.
I expect when an beacon is emitting then Range notifier should always return the beacon but sometimes it goes to 0 count and then again it returns the beacon.
**val beacon = Beacon.Builder()
.setId1("f7826da6-4fa2-4e98-8024-bc5b71e0893e")
.setId2("1")
.setId3("2")
.setManufacturer(0x004c)
.setTxPower("-59")
.build()**
**beaconTransmitter = BeaconTransmitter (this, BeaconParser()
.setBeaconLayout ("m:2-3=0215,i:4-19,i:20-21,i:22-23,p:24-24");
beaconTransmitter?.startAdvertising(beacon)
mBeaconManager = BeaconManager.getInstanceForApplication(applicationContext)
mBeaconManager?.beaconParsers?.add(BeaconParser().setBeaconLayout("m:2-3=0215,i:4-19,i:20-21,i:22-23,p:24-24"))**
**private val mRangeNotifier = RangeNotifier { beacons, region ->
//Here I receive zero beacon some time, mostly it works but form very small interval of time beacon count is zero
}**
There should be proper detection of beacon so no inconsistency occurs, at least I could always track the beacons.
I have tested it on -
One plus 5 with Android version 9
One plus 6 Plus with Android version 9
Poco F1 with Android version 8
Library version - 2.16.4

There are lots of variables here where there could be a problem:
The code shown (or supporting code not shown in the question.)
Hardware issues with the transmitting phone.
Hardware issues with the receiving phone.
Because you are working with three different phones, the combinations of possible sources of trouble grow with the combinations of phones.
In order to track this down, you must simplify your test cases:
Use a reference beacon transmitter for your tests that is most reliable. Choose a hardware beacon (best) or laptop-based beacon transmitter program (better) if you have one available. If you have no other choice, pick one of the phones to be the transmitter, and choose the one you suspect is most reliable.
Use an off-the-shelf beacon detector program based on this same library such as Beacon Scope, and test detections of the beacon. Using an off the shelf program will eliminate any coding errors in your detection software.
Test the off the shelf detection on each of your phones. This will tell you which, if any, have hardware trouble if they fail to detect reliably.
Once you have a reliable transmitter and know which phones are reliable detectors, go back to your program and work to make it as reliable as what you see with Beacon Scope using the most reliable transmitter.

Related

IOS: iBeacon scanning frequency when phone is locked?

If an iBeacon starts emitting (100ms), how long should it takes before a locked iPhone detects it? Let's say the iPhone is very close to the emitting iBeacon but my app is not even running in the background.
In other words, what is the LBE scanning frequency when an iPhone is locked?
We have done a lot of research on this subject at Radius Networks. The answers are complicated, but the executive summary is that their are two tiers of detection:
Hardware Accelerated: The first beacon apps to register the first 30 beacon regions on the phone get hardware accelerated detection. Thisey get background detection within 5 seconds about 90% of the time.
Software Scanned: Subsequently registered beacon regions get detections as software allows. If no other apps are ranging, this is on a fixed 15 minute interval. Statistics say that the average detection time would be 7.5 minutes for these regions. The maximum time is 15 minutes.
Unfortunately, there is no known way to tell which tier your app will get. Plan accordingly.
Read more here:
http://developer.radiusnetworks.com/2015/04/21/max-beacon-regions-ios.html
http://developer.radiusnetworks.com/2014/03/12/ios7-1-background-detection-times.html
The documentation doesn't seem to be really specific about the scanning times, and I feel like most of the information one can find is going to be anecdotal.
From my personal research and experience, beacon scanning when the app is backgrounded or inactive is variable on the iPhone's battery level and various other factors. For the most part, in most cases, I've determined that region detection should occur within a few seconds.
With that said, I've noticed that it happens a little faster when the phone is in use, taken out of the pocket, etc. This could be due to the fact that as the phone is moving, scanning is increased to bring the user up to speed and prepare apps for use.

Use Core Bluetooth instead of iBeacon - Any Downsides?

I am working on a project where I first wanted to advertise a device as an iBeacon and make it possible to connect to that device via Core Bluetooth at the same time. Besides the fact that this is not easily doable (a device cannot advertise as an iBeacon and CB device at the same time), I noticed that the iBeacon part seems unnecessary - discovering peripherals with Core Bluetooth seems to be basically the same as discovering iBeacons.
My first Question: Am I right in assuming this? Or does iBeacon provide anything that central/peripherals in CB do not? Especially in regard to background advertisement/searching?
The only issue I can see right now is that the CLBeacon gives me both an rssi and an accuracy (and from this, the approximated proximity is calculated). With Core Bluetooth, centralManager:didDiscoverPeripheral:advertisementData:RSSI: gives me only an RSSI. Is there any way to retrieve the accuracy here so I can calculate a proximity? This is important for me and I guess relying on RSSI only for the proximity will give me less accurate results?
My second Question: Can I get the accuracy that I get with iBeacon in Core Bluetooth or a similar measure to calculate the proximity?
You can calculate your own distance estimate with RSSI using an algorithm like the one I posted here:
https://stackoverflow.com/a/20434019/1461050
The trick is that you will need as many RSSI measurements as possible averaged over a time window of 20 seconds or so to reduce the noise on the estimate.
The main advantages of using CoreLocation APIs to detect standard iBeacons vs. using CoreBluetooth to detect custom beacons are:
A variety of cheap off-the shelf hardware is available for the iBeacon standard.
CoreLocation can scan for iBeacons in the background (likely using hardware assist on iPhone 5+) in a way that can automatically launch your app relatively quickly, even if the user did not manually launch it since boot. As of iOS 7.1, even if the user kills the app from the task switcher, CoreLocation can re-launch it into the background if an iBeacon is detected. I do not believe all this is possible with CoreBluetooth.
The iBeacon transmission allows you to easily read the UUID/major/minor identifier combination in iOS without pairing. This 20 bytes of data (with the major and minor fields able to be set to arbitrary values) is more than you can get from a 16 byte Bluetooth Service UUID.
You don't have to roll your own software for distance estimation.

Not all active iBeacons are detected by locationManager:didRangeBeacons:inRegion:

I order to test an iBeacon app for iOS, I have configured a RaspberryPi with four BLE usb dongles to simulate real iBeacons.
It happens that all iBeacons are detected but not simultaneously. The beacons array passed to locationManager:didRangeBeacons:inRegion: method contains no more than 2 iBeacons and it changes content almost at every invocation.
How should I interpret the documentation for locationManager:didRangeBeacons:inRegion: method?
beacons:
An array of CLBeacon objects representing the beacons currently in range. You can use the information in these objects to determine the range of each beacon and its identifying information.
Discussion:
The location manager calls this method whenever a beacon comes within range or goes out of range. The location manager also calls this method when the range of the beacon changes; for example, when the beacon gets closer.*
Seems to me that all beacons in range should be in the beacons array. If not, how the beacons that become out of range can be determined? Or may be this is a problem due to the fake beacons?
UPDATE
I added another BLE usb dongle and now the device detects three beacons every time. Seems to me that the device has no memory of the beacons detected in previous scanning windows. My understanding of this behaviour is illustrated in this picture.
At end the device detects all beacons probably because there is some random delay in the scanning period (as illustrated in the picture) and/or some other delay in beacon transmission.
Understand that that method is invoked once per second for each region you are ranging. Each invocation will only include the beacons visible in that one second period in that same region. Note that the region object is passed in the method as well.
EDIT: Further investigation revealed that the questioner was using a Raspberry Pi iBeacon transmitter that is probably only sending out an advertisement every 1280ms, which will definitely cause the problem reported. The solution is to increase the advertising frequency so that at least one packet goes out every second (ideally at a rate of 10Hz or higher for the best distance estimates.)

How can I tell if CLLocationManager is actively scanning for a beacon?

When you set up an iOS device as a beacon (peripheral role), you can query its state by calling CBPeripheralManager.isAdvertising. I can't find the equivalent to query whether a device is scanning for a beacon (central role) on CLLocationManager. Any ideas?
Update:
Given David's answer, I encapsulated the code setting up the CLBeaconRegion with the specific UUID and added a boolean variable which is changed when calling startMonitoringRegion and stopMonitoringRegion on CLLocationManager.
I do not believe there is any way this is possible. Even though CoreLocation's iBeacon APIs use Bluetooth LE and CoreBluetooth under the hood, Apple appears to have gone to some lengths to hide this implementation. There is no obvious way to see whether a Bluetooth LE scan is going on at a specific point in time.
Generally speaking, a Bluetooth LE scan is always going on when an app is ranging for iBeacons in the foreground. When an app is monitoring for iBeacons (either in the foreground or background) or ranging in the background, indirect evidence suggests that scans for beacons take place every few minutes, with the exact number ranging from 1-15 depending on phone model and state. I know of no way to programmatically detect the exact times when this starts and stops, although it can be inferred by iBeacon monitoring entry/exit times. If you look at the graph below, the blue dots show the inferred scan times for one particular test case. Details of how I inferred this are described in this blog post.

How to limit the advertising range of a beacon?

Is it possible to limit the ranging of the beacon, so that only devices within a certain close range(or proximity) can identify and connect to the beacon? Lets say for example the devices outside 0.5 meter zone shouldn't be able to see or connect to the beacon. I am using a iOS device as a beacon. In the Apple's CoreLocation API, there is a method called peripheralDataWithMeasuredPower in the CLBeaconRegion class which says:
peripheralDataWithMeasuredPower:
Retrieves data that can be used to advertise the current device as a beacon.
(NSMutableDictionary *)peripheralDataWithMeasuredPower:(NSNumber *)measuredPower
Parameters:
measuredPower:
The received signal strength indicator (RSSI) value (measured in decibels) for the device. This value represents the measured strength of the beacon from one meter away and is used during ranging. Specify nil to use the default value for the device.
Can this be used to limit the range of beacon? If yes, I am unable to understand how to decide the value to set for measurePower parameter? What are they trying to say by ...value represents the measured strength of the beacon from one meter away..?
Please forgive if this is a very basic question. I've recently started iOS development and will appreciate your help. Thanks.
Unfortunately, there is no easy way to adjust the range of an iBeacon without special hardware.
The power field that you mention is simply a calibration value transmitted by an iBeacon. It doesn't affect the actual physical radio range of the iBeacon. If the transmitter can be seen by an iPhone 50 meters away, altering the power field value will not change this at all. The only thing it does is change is the calibration constant which is an input to the distance estimation algorithm (used for the accuracy and proximity fields) inside the iOS software. Altering the power field will affect the estimated distance returned by the API, but it won't change the actual distance at which the iBeacon is first detected.
Altering the transmit power of a standard bluetooth iBeacon is practically impossible. In theory you can use metal shielding to construct a "faraday cage" around the transmitter to mute its power, but my experience is that it isn't very effective and it is highly susceptible to tiny imperfections in the shielding. If you want to change the transmit power you have to have somebody build you custom hardware.
The software alternative is to use the ranging API to track an iBeacon while it is visible, and only perform an action when the estimated distance is close enough, say 0.5 meters as you suggest. This works great -- only in the foreground.
If you require actually waking up your app in the background at a close range, this won't work. The best you can do is have the monitoring API wake up your app when the iBeacon is first detected, and then send a notification to the user and start ranging. If the user elects to bring the app to the foreground (at 50 meters) you can keep monitoring and then perform your desired action at 0.5 meters. If the user does not elect to bring the app to the foreground, iOS will only give you about 5 seconds of time to continue ranging before it suspends your app. It is very unlikely that the distance will change from 50 meters to 0.5 meters in this time.
With most BLE chips I've investigated, there are usually at least four settings for transmission power level that can be used to limit the advertising range.
The Texas Instruments CC2541 (as used in their SensorTag development device) and CC2540 have +4, 0, -6, and -23 as their power level options. However, changing that in the SensorTag does require a recompile of the firmware. As-is, the provided firmware mentions the power level in only one place, but that is just a value that is broadcasted to inform any central listener how loud the beacon is—so that the central device can better calculate an estimated range based on received signal strength (RSSI). An additional line must be added to the firmware to actually change the transmission power. For example:
HCI_EXT_SetTxPowerCmd( HCI_EXT_TX_POWER_0_DBM );
Based on this, there should be two places on an iOS device where you can set the power level: one that just informs the listeners what the level is, and one where the BLE chip's true transmission power is actually changed. However, expect these values to be restricted to only a few enumerated choices which may or may not meet your real-world range needs.
(The SensorTag's -23 setting would probably do well for a 0.5 meter detection range. But if you want the SensorTag to always be advertising, it will require an additional firmware change.)
Have you looked to see if the proximity property was helpful? From the apple docs:
CLProximity
Constants that reflect the relative distance to a beacon.
typedef {
CLProximityUnknown,
CLProximityImmediate,
CLProximityNear,
CLProximityFar
} CLProximity;
I would also experiment trying to combine the the proximity with accuracy and rssi.
It's gonna vary from beacon to beacon. If you use beacons from Radius Networks, they have a transmit power setting that lets you essentially limit the ability of the beacon radio to broadcast to long ranges. I don't know if other brands have it, but most do not from what I've seen.

Resources