Estimating beacon proximity/distance based on RSSI - Bluetooth LE
It is unclear whether your inability to read the "txPower" or "measuredPower" calibration constant is due to the AdRecord
class or due to the information being missing from the advertisements you are trying to parse. It doesn't look to me like that class will parse a standard iBeacon advertisement. Either way, there is a solution:
SOLUTION 1: If your beacons send a standard iBeacon advertisement that includes the calibration constant, you can parse it out using code in the open source Android iBeacon Library's IBeacon class here.
SOLUTION 2: If your beacons DO NOT send a standard iBeacon advertisement or do not include a calibration constant:
You must hard-code a calibration constant in your app for each device type you might use. All you really need from the advertisement to estimate distance is the the RSSI measurement. The whole point of embedding a calibration constant in the transmission is to allow a wide variety of beacons with quite different transmitter output power to work with the same distance estimating algorithm.
The calibration constant, as defined by Apple, basically says what the RSSI should be if your device is exactly one meter away from the beacon. If the signal is stronger (less negative RSSI), then the device is less than one meter away. If the signal is weaker (more negative RSSI), then the device is over one meter away. You can use a formula to make a numerical estimate of distance. See here.
If you aren't dealing with advertisements that contain a "txPower" or "measuredPower" calibration constant, then you can hard-code a lookup table in your app that stores the known calibration constants for various transmitters. You will first need to measure the average RSSI of each transmitter at one meter away. You'll then need some kind of key to look up these calibration constants in the table. (Perhaps you can use the some part of the string from the AD structure, or the mac address?) So your table might look like this:
HashMap<String,Integer> txPowerLookupTable = new HashMap<String,Integer>();
txPowerLookupTable.put("a5:09:37:78:c3:22", new Integer(-65));
txPowerLookupTable.put("d2:32:33:5c:87:09", new Integer(-78));
Then after parsing an advertisement, you can look up the calibration constant in your onLeScan
method like this:
String macAddress = device.getAddress();
Integer txPower = txPowerLookupTable.get(macAddress);
Understanding ibeacon distancing
The distance estimate provided by iOS is based on the ratio of the beacon signal strength (rssi) over the calibrated transmitter power (txPower). The txPower is the known measured signal strength in rssi at 1 meter away. Each beacon must be calibrated with this txPower value to allow accurate distance estimates.
While the distance estimates are useful, they are not perfect, and require that you control for other variables. Be sure you read up on the complexities and limitations before misusing this.
When we were building the Android iBeacon library, we had to come up with our own independent algorithm because the iOS CoreLocation source code is not available. We measured a bunch of rssi measurements at known distances, then did a best fit curve to match our data points. The algorithm we came up with is shown below as Java code.
Note that the term "accuracy" here is iOS speak for distance in meters. This formula isn't perfect, but it roughly approximates what iOS does.
protected static double calculateAccuracy(int txPower, double rssi) {
if (rssi == 0) {
return -1.0; // if we cannot determine accuracy, return -1.
}
double ratio = rssi*1.0/txPower;
if (ratio < 1.0) {
return Math.pow(ratio,10);
}
else {
double accuracy = (0.89976)*Math.pow(ratio,7.7095) + 0.111;
return accuracy;
}
}
Note: The values 0.89976, 7.7095 and 0.111 are the three constants calculated when solving for a best fit curve to our measured data points. YMMV
Calculate approximated distance using RSSI
This is an open issue. Basically, Measuring distance according to the RSSI in the ideal state is easy, The main challenge is reducing noise that produced due to multipath and reflecting RF signals and its Interferences. Anyway, you can convert RSSI to distance by below code:
double rssiToDistance(int RSSI, int txPower) {
/*
* RSSI in dBm
* txPower is a transmitter parameter that calculated according to its physic layer and antenna in dBm
* Return value in meter
*
* You should calculate "PL0" in calibration stage:
* PL0 = txPower - RSSI; // When distance is distance0 (distance0 = 1m or more)
*
* SO, RSSI will be calculated by below formula:
* RSSI = txPower - PL0 - 10 * n * log(distance/distance0) - G(t)
* G(t) ~= 0 //This parameter is the main challenge in achiving to more accuracy.
* n = 2 (Path Loss Exponent, in the free space is 2)
* distance0 = 1 (m)
* distance = 10 ^ ((txPower - RSSI - PL0 ) / (10 * n))
*
* Read more details:
* https://en.wikipedia.org/wiki/Log-distance_path_loss_model
*/
return pow(10, ((double) (txPower - RSSI - PL0)) / (10 * 2));
}
Estimating distance to iBeacon on iOS
Is there a way to get the distance estimate between an iOS device and a beacon WITHOUT having the 1-meter calibration value saved on the iOS device beforehand?
YES, you simply read the CLBeacon accuracy field as you suspected. This is an estimate of the distance to the beacon in meters.
This estimate uses an undocumented calculation that is based on the RSSI measurements (likely a 30 second running average, perhaps discarding outliers) combined with the 1-meter RSSI calibration value embedded in the iBeacon advertisement. A port of this calculation to Android is shown here.
And, no, there is no way to read the calibration value from an app. It is obscured by iOS, which disallows seeing the details of iBeacon Bluetooth LE advertisements. See here for a detailed explanation.
How to know closest iBeacon
You will find your answer here (as TX and RSSI concepts are not platform specific):
https://community.estimote.com/hc/en-us/articles/201636913-Broadcasting-Power-RSSI-and-Measured-Power-explained
Have a look over here too:
Estimating beacon proximity/distance based on RSSI - Bluetooth LE
Related Topics
How to Get a Fragment to Remove Itself, I.E. Its Equivalent of Finish()
Nested Fragments Disappear During Transition Animation
Custom Translucent Android Actionbar
What Does the Filter Parameter to Createscaledbitmap Do
How to Put a Constraintlayout Inside a Scrollview
Android Studio: How to Generate Signed APK Using Gradle
Resize Image to Full Width and Variable Height with Picasso
How to Hide One Item in an Android Spinner
Add a New Item to Recyclerview Programmatically
What Are the Ipc Mechanisms Available in the Android Os
Android: What Is Better - Multiple Activities or Switching Views Manually
How to Allocate These Folders in Another Place