Skip to content

Instantly share code, notes, and snippets.

@cryptolok
Last active August 19, 2023 12:29
Show Gist options
  • Save cryptolok/516471ce35a9851197b204853c6de080 to your computer and use it in GitHub Desktop.
Save cryptolok/516471ce35a9851197b204853c6de080 to your computer and use it in GitHub Desktop.
convert WiFi signal strength (dBm) to distance (meters)
#!/usr/bin/env python2
# a simple script for one of my articles - https://cryptolok.blogspot.com/2017/08/practical-wifi-hosts-triangulation-with.html
from math import log10
MHz=raw_input('MHz FREQUENCY (2417, 5200, ...) : ')
MHz=int(MHz)
dBm=raw_input('dBm TRANSMITTER POWER (23, 63, ...) : ')
dBm=int(dBm)
FSPL = 27.55
# Free-Space Path Loss adapted avarage constant for home WiFI routers and following units
m = 10 ** (( FSPL - (20 * log10(MHz)) + dBm ) / 20 )
m=round(m,2)
print 'DISTANCE : ',m,'m'
@joseagm1001
Copy link

joseagm1001 commented Sep 9, 2022

Do you have a paper or something that prove this ? in case of the FSPL is always the same or change in different situations than home?

@cryptolok
Copy link
Author

check the wiki
the constant depends on units (m/kHz, km/GHz or m/MHz in this case)
it also depends on conditions like antenna (considered the same), obstacles (considered low), etc.
tldr; a constant is just a thing to make other things work

@cboychinedu
Copy link

cboychinedu commented Aug 19, 2023

Getting the distance of wifi networks using the code posted above.

import os
import sys
import re
import subprocess 
import pandas as pd 
from math import log10 
from subprocess import getoutput, getstatusoutput

# Creating a function for converting the distance into meters 
def getDistance(dbmValue, frequency): 
    # Converting both the dbm , frequency value to integer's
    dbmValue = float(dbmValue)
    frequency = float(frequency) 
    
    # Setting the free space path loss adapted average constant 
    FSPL = 27.55 
    
    # Getting the distance in meters 
    distance = 10 ** (( FSPL - (20 * log10(frequency)) + dbmValue) / 20 )
    distance = round(distance, 4)
    
    # Returning the distance in meters 
    return distance; 

# Creating the command 
iwCommand = "nmcli -f SSID,FREQ,SIGNAL,SECURITY device wifi list"
iwScanStatus, iwScanResult = getstatusoutput(iwCommand)

# Splitting the values to form a dataframe
wifiInfoArray = iwScanResult.split("\n")

# Extracting information from the list and preparing data for DataFrame
data = []

# Looping 
for line in wifiInfoArray[1:]:
    ssid = line[:20].strip()
    freq = line[20:29].strip()
    signal = line[29:38].strip()
    security = line[38:].strip()
    data.append((ssid, freq, signal, security))

# Create a pandas DataFrame
df = pd.DataFrame(data, columns=['SSID', 'FREQ', 'SIGNAL', 'SECURITY'])
# pd.set_option('display.max_colwidth', 200)

# Print the DataFrame
df.head()

# Extract the "Network" "SSID" from the loaded pandas dataframe 
# Getting the signals strength 
wifiData = []

# Creating the command from the "SSID" value
iwCommand = "iw dev wlo1 scan | grep -B 6 'SSID NAME' "
iwScanStatus, iwScanResult = getstatusoutput(iwCommand)

# Creating a list for the wifi data 
wifiDict = {} 
wifiInformationArray = []

# 
wifiDataList = iwScanResult.replace("\t", "").split("\n")


# Looping for the items in the wifi Datalist 
for items in wifiDataList: 
    # Split the items 
    splittedItems = items.split(":")
    print(splittedItems)
    
    # If the length is 2 items 
    if len(splittedItems) == 2: 
        # Append the data into the wifiInformation Array
        wifiInformationArray.append(tuple((splittedItems[0], [splittedItems[1]])))
        
# Update the wifiDict Dictionary 
wifiDict.update(dict(wifiInformationArray))

# Converting into a dataframe 
df = pd.DataFrame(wifiDict)
df.drop(columns=['Information elements from Probe Response frame', 'capability'], inplace=True)

# Displaying the head 
df.head() 

# Getting the dbm signal 
dbmSignal = df['signal'].iloc[0]
dbmSignal = dbmSignal.split("-")[-1].split("dBm")[0].replace(' ', '')
dbmSignal = float(dbmSignal)

# Getting the frequency 
frequencyValue = df['freq'].iloc[0].replace(' ', '')
frequencyValue = float(frequencyValue)

# Creating a function for converting the distance into 
# meters from decibels 
def getDistance(dbmValue, frequency): 
    # Converting both the dbm , frequency value to integer's
    dbmValue = float(dbmValue)
    frequency = float(frequency) 
    
    # Setting the free space path loss adapted average constant 
    FSPL = 27.55 
    
    # Getting the distance in meters 
    distance = 10 ** (( FSPL - (20 * log10(frequency)) + dbmValue) / 20 )
    distance = round(distance, 4)
    
    # Returning the distance in meters 
    return distance; 

# Getting the distance 
distance = getDistance(dbmValue=dbmSignal, frequency=frequencyValue)

# Displaying the results 
print(f"The distance is: {distance} meters")

>> "The distance is: 2.4584 meters" 

@cboychinedu
Copy link

Which language did you use

The python programming language was used for this.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment