Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Estimating beacon proximity/distance based on RSSI - Bluetooth LE

Tags:

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.

I've followed the tutorial at Android developer 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 this SO thread it's just a handful of mathematical calculations. However, they require me to provide a txPower value.

According to this tutorial by Dave Smith (and cross-referencing with this Bluetooth SIG statement), it should be broadcast by the beacon devices as an "AD structure" of type 0x0A. So what I do is parse the AD structures and look for the payload of the one that matches the type.

Problem: 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.

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?

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 here. The only change I did to that class was add the following method:

public byte[] getData() {      return mData; } 

And this is how I handle the callback from the scans:

// 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<AdRecord> 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]));                 }             }         }     } }; 

And what I see in the console is:

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 
like image 905
JakeP Avatar asked Apr 01 '14 11:04

JakeP


People also ask

How do you calculate the distance from the RSSI value of a BLE beacon?

Distance = 10 ^ ((Measured Power -RSSI)/(10 * N))

What is a good RSSI number for Bluetooth?

RSSI is a negative value where the more negative it is, the further away the Bluetooth device. Close devices are usually in the range -10 dBm to -30 dBm while devices at the limit of detection give values less than -90 dBm.

How is RSSI Bluetooth calculated?

With the system preferences open, hold the Option key and a small bar graph with an RSSI number should appear that shows the signal strength. At the bottom of the Bluetooth system preferences there is a small gear menu that contains an option to "Monitor Connection RSSI" for any connected Bluetooth device.

What is RSSI in beacons?

RSSI stands for Received Signal Strength Indicator. It is the strength of the beacon's signal as seen on the receiving device, e.g. a smartphone. The signal strength depends on distance and Broadcasting Power value.


2 Answers

The txPower mentioned by @davidgyoung is given by the formula:

RSSI = -10 n log d + A

where

  • d = distance
  • A = txPower
  • n = signal propagation constant
  • RSSI = dBm

In free space n = 2, but it will vary based on local geometry – for example, a wall will reduce RSSI by ~3dBm and will affect n accordingly.

If you want the highest possible accuracy, it may be worthwhile to experimentally determine these values for your particular system.

Reference: see the paper Evaluation of the Reliability of RSSI for Indoor Localization by Qian Dong and Waltenegus Dargie for a more detailed explanation of the derivation and calibration.

like image 56
tep Avatar answered Oct 18 '22 08:10

tep


double getDistance(int rssi, int txPower) {     /*      * RSSI = TxPower - 10 * n * lg(d)      * n = 2 (in free space)      *       * d = 10 ^ ((TxPower - RSSI) / (10 * n))      */      return Math.pow(10d, ((double) txPower - rssi) / (10 * 2)); } 
like image 43
sergey.n Avatar answered Oct 18 '22 07:10

sergey.n