Skip to content

Instantly share code, notes, and snippets.

@ekawahyu
Created October 28, 2024 23:29
Show Gist options
  • Save ekawahyu/f990dd1421d48ca0a2d496c04593badf to your computer and use it in GitHub Desktop.
Save ekawahyu/f990dd1421d48ca0a2d496c04593badf to your computer and use it in GitHub Desktop.
Wi-Fi Spectrum Analyzer written in Python
import matplotlib.pyplot as plt
import pandas as pd
import numpy as np
import subprocess
import re
all_colors = ['tab:blue', 'tab:orange', 'tab:green', 'tab:red', 'tab:purple', 'tab:brown', 'tab:pink', 'tab:gray', 'tab:olive', 'tab:cyan']
plt.style.use('dark_background')
while True:
# Scan for other local Wi-Fi networks
stdoutlines = []
command_line = 'system_profiler SPAirPortDataType | grep -A 9999 "Other Local Wi-Fi Networks:"'
p = subprocess.Popen(command_line, shell=True, stdout=subprocess.PIPE)
stdoutlines = [line.lstrip() for line in p.communicate()[0].decode().split('\n')]
# Parse the output and get the SSID, channel, bandwidth and RSSI
scanned_ssid = []
for line in stdoutlines:
if line.endswith(':') and stdoutlines.index(line) != 0:
scanned_ssid.append(line.split(':')[0])
if line.startswith('Channel:'):
channel = re.search('Channel: \d+', line)
if channel:
res = channel.group().split()
scanned_ssid.append(res[-1])
bandwidth = re.search('\d+MHz', line)
if bandwidth:
res = bandwidth.group().split('MHz')
scanned_ssid.append(res[0])
if line.startswith('Signal / Noise:'):
rssi = re.search('-\d+', line)
if rssi:
res = rssi.group().split()
scanned_ssid.append(res[0])
# Reformat scanned_ssid into a list of tuples
data = []
for ssid, channel, bandwidth, rssi in zip(scanned_ssid[::4], scanned_ssid[1::4], scanned_ssid[2::4], scanned_ssid[3::4]):
data.append((ssid, channel, bandwidth, rssi))
# Convert the list of tuples into a dataframe
df = pd.DataFrame(data, columns=['ssid', 'channel', 'bandwidth', 'rssi'])
# Clear and redraw the plot
plt.clf()
plt.xlabel('Wi-Fi Channel')
plt.ylabel('RSSI [dBm]')
plt.grid(axis='y', linestyle='--')
plt.grid(axis='x', linestyle=':', color='r', alpha=0.3)
y_major_ticks = np.arange(-20, -100, -10)
plt.gca().set_yticks(y_major_ticks)
x_major_ticks = np.arange(0, 16, 1)
plt.gca().set_xticks(x_major_ticks)
plt.ylim(-99, -20)
plt.xlim(-2, 16)
# Plot the points
for index, row in df.iterrows():
bw = int(row['bandwidth'])
ch = int(row['channel'])
rs = int(row['rssi'])
diff = bw / 5
x = np.linspace(ch-diff, ch+diff, 50)
y = (-99 - rs) * np.sin((x - ch + 2) / diff * np.pi)
y = -99 - y
color = all_colors[ index % len(all_colors) ]
plt.fill(x, y, color=color, alpha=0.3)
plt.plot(x, y, color=color)
plt.text(ch, rs+1, row['ssid'], horizontalalignment='center')
plt.draw()
plt.pause(0.01)
@ekawahyu
Copy link
Author

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