title: Estimating beacon proximity/distance based on RSSI - Bluetooth LE
body: <p>I've got a simple iOS app which displays the proximity of the Bluetooth LE beacons it detects using such expressions as "immediate", "near" etc. and I need to write something similar on Android.</p>
  
  <p>I've followed the tutorial at <a href="https://developer.android.com/guide/topics/connectivity/bluetooth-le.html" rel="noreferrer">Android developer</a> and I'm able to list detected devices and now want to estimate the distance/proximity - this is where it's become a problem. According to <a href="https://stackoverflow.com/questions/20416218/understanding-ibeacon-distancing">this SO thread</a> it's just a handful of mathematical calculations. However, they require me to provide a txPower value.</p>
  
  <p>According to <a href="https://thenewcircle.com/s/post/1553/bluetooth_smart_le_android_tutorial" rel="noreferrer">this tutorial by Dave Smith</a> (and cross-referencing with this <a href="https://www.bluetooth.org/en-us/specification/assigned-numbers/generic-access-profile" rel="noreferrer">Bluetooth SIG statement</a>), it should be broadcast by the beacon devices as an "AD structure" of type <code>0x0A</code>. So what I do is parse the AD structures and look for the payload of the one that matches the type.</p>
  
  <p><strong>Problem:</strong> I've got 4 beacons - 2 estimotes and 2 appflares. The estimotes don't broadcast the txPower at all and the appflares broadcast theirs as 0.</p>
  
  <p>Is there anything I'm missing here? The iOS app seems to be handling it all without any problem, but using the iOS SDK it does it behind the scenes so I'm not sure how to produce the exact same or similar behaviour. Is there any other way I could solve my problem?</p>
  
  <p>In case you'd like to take a look at the code I'm using to parse the AD structures, it's taken from the aforementioned Dave Smith's github and can be found <a href="https://github.com/devunwired/accessory-samples/blob/master/BluetoothGatt/src/com/example/bluetoothgatt/AdRecord.java" rel="noreferrer">here</a>. The only change I did to that class was add the following method:</p>
  
  <pre><code>public byte[] getData() {
  
      return mData;
  }
  </code></pre>
  
  <p>And this is how I handle the callback from the scans:</p>
  
  <pre><code>// Prepare the callback for BLE device scan
  this.leScanCallback = new BluetoothAdapter.LeScanCallback() {
  
      @Override
      public void onLeScan(final BluetoothDevice device, int rssi, byte[] scanRecord) {
  
          if (!deviceList.contains(device)) {
  
              MyService.this.deviceList.add(device);
              Log.e("Test", "Device: " + device.getName());
  
              List&lt;AdRecord&gt; adRecords = AdRecord.parseScanRecord(scanRecord);
  
              for (AdRecord adRecord : adRecords) {
  
                  if (adRecord.getType() == AdRecord.TYPE_TRANSMITPOWER) {
  
                      Log.e("Test", "size of payload: " + adRecord.getData().length);
                      Log.e("Test", "payload: " + Byte.toString(adRecord.getData()[0]));
                  }
              }
          }
      }
  };
  </code></pre>
  
  <p>And what I see in the console is:</p>
  
  <pre><code>04-01 11:33:35.864: E/Test(15061): Device: estimote
  04-01 11:33:36.304: E/Test(15061): Device: estimote
  04-01 11:33:36.475: E/Test(15061): Device: n86
  04-01 11:33:36.475: E/Test(15061): size of payload: 1
  04-01 11:33:36.475: E/Test(15061): payload: 0
  04-01 11:33:36.525: E/Test(15061): Device: f79
  04-01 11:33:36.525: E/Test(15061): size of payload: 1
  04-01 11:33:36.525: E/Test(15061): payload: 0
  </code></pre>