Measuring distance with Bluetooth in indoor environment using Python

June 13, 2022
Measuring distance with Bluetooth in indoor environment using Python

Bluetooth ranging technology is very popular. There are many localization systems that exist based on beacons. Beacon technology usually estimates the distance between devices using the received signal strength (RSSI). 

Bluetooth can be an excellent way to narrow down a search area at close distances when tracking something. This feature can be used in several fields. such as Secure Locks for Buildings and Automotive, Asset localization & tracking, Indoor navigation etc

GPS tracking isn’t excellent at giving accurate measurements of the close distance, especially in the indoor environment. On the other hand, Bluetooth is excellent in short ranges because the waves can go through walls. This might fill the gap that GPS tracking has when tracking devices in indoor spaces.

However, most calculations of the distance between two Bluetooth devices are estimates. It’s hard to determine the exact distance between two Bluetooth devices because many factors affect the calculations. Despite the challenges, there are methods to determine the distance between two Bluetooth devices with an accuracy of at least 80%.

The ranging method is simple to implement, and it has the formula to calculate the distance between two Bluetooth devices. As the name suggests, both devices need to be within Bluetooth range to estimate the distance. 

This article will share a simple python script to determine nearby Bluetooth devices and their distance in meters.

This script scans for nearby Bluetooth devices and gets an approximation of the distance by using the well-known RSSI to distance formula.

Read more about how to calculate the distance

Requirments 

Instructions

  • Get the script from GitHub at https://github.com/smart-sensor-devices-ab/python_bluetooth_device_distance_meter.git
  • Connect the BleuIO to your computer. The script uses pyserial to connect to the Bluetooth USB dongle BleuIO.
  • Update the script and write the correct COM port, where the dongle is connected. 
  • After connecting to the dongle, we put the dongle into the central role so that it can scan for nearby Bluetooth devices. 
  • Then we do a simple Gap scan using AT+GAPSCAN=3 command to scan for nearby Bluetooth devices for 3 seconds.
  • After that, we read the output from the serial port and use our RSSI to distance formula to get the distance in meters. 
  • Finally, we sort the result by distance before printing it out on screen.

Here is the final script file. 

import serial
import time

your_com_port = "COM18"  # Change this to the com port your dongle is connected to.
connecting_to_dongle = True

print("Connecting to dongle...")
# Trying to connect to dongle until connected. Make sure the port and baudrate is the same as your dongle.
# You can check in the device manager to see what port then right-click and choose properties then the Port Settings
# tab to see the other settings

while connecting_to_dongle:
    try:
        console = serial.Serial(
            port=your_com_port,
            baudrate=57600,
            parity="N",
            stopbits=1,
            bytesize=8,
            timeout=0,
        )
        if console.is_open.__bool__():
            connecting_to_dongle = False
    except:
        print("Dongle not connected. Please reconnect Dongle.")
        time.sleep(5)

print("Connected to Dongle.")

# function to convert rssi to distance in meter
def rssiToDistance(rssi):    
  n=2
  mp=-69
  return round(10 ** ((mp - (int(rssi)))/(10 * n)),2)    

#put the dongle in dual role, so we can scan for nearby device
console.write(str.encode("AT+CENTRAL"))
console.write("\r".encode())
print("Putting dongle in Central role.")
time.sleep(0.1)
# Scan for nearby devices for 3 seconds
console.write(str.encode("AT+GAPSCAN=3"))
console.write("\r".encode())
time.sleep(0.1)
print("Looking for nearby Bluetooth devices ...")
dongle_output2 = console.read(console.in_waiting)
time.sleep(3)
print("Scan Complete!")
filtered = []
# Filter out unncecssary outputs and keep only the list of devices (also remove index)
for dev in dongle_output2.decode().splitlines():
    if len(dev)>20:
        filtered.append(dev.split(maxsplit=1)[1])
# Get unique device by device id and add distance to each raw        
seen = set()
out = []
for elem in filtered:
    prefix = elem.split(' ')[1]
    if prefix not in seen:
        seen.add(prefix)
        out.append(elem + " Distance: "+str(rssiToDistance(elem.split()[3]))+" meter") 

# sort list by closest device
out.sort(key=lambda x:int(x.split()[3]),reverse=True)

# print(out)
for i in range(0, len(out)):
    print (out[i]) 

time.sleep(0.1)
console.close()

Output

After running the script, we see a total 20 devices found nearby. The list shows their distance in meter from the central device.

Share this post on :

2 thoughts on “Measuring distance with Bluetooth in indoor environment using Python

  1. What’s the speed of the data collection? Could it do (near) real time detection (even for just a single specific MAC address)?

    Pretty cool either way! Congrats!

Leave a Reply

Your email address will not be published.

Order Now

BleuIO

$15.99

Buy Now

Get a FREE product for every 10 pcs ordered.