Last active
August 19, 2023 12:29
-
-
Save cryptolok/516471ce35a9851197b204853c6de080 to your computer and use it in GitHub Desktop.
convert WiFi signal strength (dBm) to distance (meters)
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#!/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' |
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
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"
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
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?