package uk.co.alt236.bluetoothlelib.device.beacon.ibeacon;
import uk.co.alt236.bluetoothlelib.util.ByteUtils;
final class IBeaconUtils {
private static final double DISTANCE_THRESHOLD_WTF = 0.0;
private static final double DISTANCE_THRESHOLD_IMMEDIATE = 0.5;
private static final double DISTANCE_THRESHOLD_NEAR = 3.0;
private IBeaconUtils(){
// TO AVOID INSTANTIATION
}
/**
* Calculates the accuracy of an RSSI reading.
* <p/>
* The code was taken from <a href="http://stackoverflow.com/questions/20416218/understanding-ibeacon-distancing" /a>
*
* @param txPower the calibrated TX power of an iBeacon
* @param rssi the RSSI value of the iBeacon
* @return the calculated Accuracy
*/
public static double calculateAccuracy(final int txPower, final double rssi) {
if (rssi == 0) {
return -1.0; // if we cannot determine accuracy, return -1.
}
final double ratio = rssi * 1.0 / txPower;
if (ratio < 1.0) {
return Math.pow(ratio, 10);
} else {
return (0.89976) * Math.pow(ratio, 7.7095) + 0.111;
}
}
public static String calculateUuidString(final byte[] uuid) {
final StringBuilder sb = new StringBuilder();
for (int i = 0; i < uuid.length; i++) {
if (i == 4) {
sb.append('-');
}
if (i == 6) {
sb.append('-');
}
if (i == 8) {
sb.append('-');
}
if (i == 10) {
sb.append('-');
}
final int intFromByte = ByteUtils.getIntFromByte(uuid[i]);
if(intFromByte <= 0xF){
sb.append('0');
}
sb.append(Integer.toHexString(intFromByte));
}
return sb.toString();
}
public static IBeaconDistanceDescriptor getDistanceDescriptor(final double accuracy) {
if (accuracy < DISTANCE_THRESHOLD_WTF) {
return IBeaconDistanceDescriptor.UNKNOWN;
}
if (accuracy < DISTANCE_THRESHOLD_IMMEDIATE) {
return IBeaconDistanceDescriptor.IMMEDIATE;
}
if (accuracy < DISTANCE_THRESHOLD_NEAR) {
return IBeaconDistanceDescriptor.NEAR;
}
return IBeaconDistanceDescriptor.FAR;
}
}