I want to get the Tx power of a BLE beacon with an Android device.
I defined the assigned number for Tx power here.
public class AssignedNumbers {
...
public static final byte TXPOWER = 0x0A;
...
}
Then I made a function to get Tx power here.
public class AdvertisingData {
...
public static Integer getTxPowerLevel(byte[] scanRecord) {
// Check for BLE 4.0 TX power
int pos = findCodeInBuffer(scanRecord, AssignedNumbers.TXPOWER);
if (pos > 0) {
return Integer.valueOf(scanRecord[pos]);
}
return null;
}
...
private static int findCodeInBuffer(byte[] buffer, byte code) {
final int length = buffer.length;
int i = 0;
while (i < length - 2) {
int len = buffer[i];
if (len < 0) {
return -1;
}
if (i + len >= length) {
return -1;
}
byte tcode = buffer[i + 1];
if (tcode == code) {
return i + 2;
}
i += len + 1;
}
return -1;
}
...
}
Finally, I put a line of code to check the Tx power.
private BluetoothAdapter.LeScanCallback mLeScanCallback =
new BluetoothAdapter.LeScanCallback() {
...
System.out.println("TxPower: " + AdvertisingData.getTxPowerLevel(scanRecord));
...
};
However, the result is shown as below.
04-22 16:34:14.249: I/System.out(29133): TxPower: null
The log of onScanResult() is
04-22 16:34:14.247: D/BluetoothLeScanner(29133): onScanResult() - ScanResult{mDevice=90:59:AF:0F:31:01, mScanRecord=ScanRecord [mAdvertiseFlags=6, mServiceUuids=null, mManufacturerSpecificData={76=[2, 21, -43, 117, 98, 71, 87, -94, 67, 68, -111, 93, -107, -103, 73, 121, 64, -89, 0, 0, 0, 0, -60]}, mServiceData={0000180a-0000-1000-8000-00805f9b34fb=[1, 49, 15, -81, 89, -112, -60, 0, 0, 0, 0]}, mTxPowerLevel=-2147483648, mDeviceName=pebBLE], mRssi=-79, mTimestampNanos=8204624857836}
How to get the right value of the Tx power? The values should be 4, 0, or -23(dBm).
You say beacon above - I think you're really trying to get iBeacon calibrated transmission power, which is different from the GAP 0x0A. iBeacon TxPower is just part of the manufacture data in the advertisement. There is a full breakdown of the advertising packet here - What is the iBeacon Bluetooth Profile
You can see that there are two variable size sections in the scanRecord, and that the TxPower is the last byte (not preceded by a 0A, as fitbit does in this example http://j2abro.blogspot.com/2014/06/analyzing-bluetooth-advertising-with.html).
Looking at your onScanResult, I believe the calibrated TxPower is the -60, which is the rssi measurement at 1 meter. There's an example of reverse engineering TxPower to distance in meters in this post - Understanding ibeacon distancing