Skip to content

Commit 3cfd29f

Browse files
authored
Add files via upload
1 parent 0ea8ef1 commit 3cfd29f

5 files changed

Lines changed: 184 additions & 2 deletions

File tree

README.md

Lines changed: 32 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,2 +1,32 @@
1-
# Wi-FiChannelScanner
2-
GUI крипт Wi-FiChannelScanner для сканирования загруженности каналов wifi
1+
<img src="https://github.com/Xprograms89/Wi-FiChannelScanner/blob/main/Work1.png" width="671">
2+
<img src="https://github.com/Xprograms89/Wi-FiChannelScanner/blob/main/Work2.png" width="1002">
3+
4+
# GUI крипт Wi-FiChannelScanner для сканирования загруженности каналов wifi.
5+
6+
Функционал: выбор диапазона 2.4 Ггц или 5 Ггц\
7+
Частота сканирования и интервал обновления\
8+
Графики числа точек и загруженности в процентах\
9+
Отображение в текстовом виде MAC адресов
10+
11+
12+
### Запуск установка:
13+
Python 3.12 64-bit\
14+
pip install -r requirements.txt\
15+
start Wi-FiChannelScanner.py
16+
17+
# GUI crypt Wi-FiChannelScanner for scanning wifi channel load.
18+
19+
Functionality: selection of 2.4 GHz or 5 GHz range\
20+
Scan frequency and update interval\
21+
Graphs of the number of points and load in percent\
22+
Display of MAC addresses in text form
23+
24+
### Launch installation:
25+
Python 3.12 64-bit\
26+
pip install -r requirements.txt\
27+
start Wi-FiChannelScanner.py
28+
29+
## Donate
30+
* **Bitcoin:** `bc1qngs6nyzh9mpcgn5f3vpsqqg90m4evxqxpk4gwr`
31+
* **Ethereum:** `0x846C0F2857743309B43DB4f7Ba7db91aaAfd7E55`
32+
* **Dogecoin:** `DQyXW6EM2ajNX5jseAar3vYEv3hyi7xWUf`

Wi-FiChannelScanner.py

Lines changed: 151 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,151 @@
1+
import subprocess
2+
import re
3+
import tkinter as tk
4+
from tkinter import ttk
5+
import matplotlib.pyplot as plt
6+
from matplotlib.backends.backend_tkagg import FigureCanvasTkAgg
7+
8+
import time
9+
10+
CHANNELS_24 = list(range(1, 14))
11+
CHANNELS_5 = [36, 40, 44, 48, 149, 153, 157, 161, 165]
12+
ALL_CHANNELS = sorted(set(CHANNELS_24 + CHANNELS_5))
13+
14+
scanning = False
15+
channel_details = {}
16+
17+
def parse_netsh_output():
18+
try:
19+
output = subprocess.check_output(
20+
["netsh", "wlan", "show", "networks", "mode=bssid"],
21+
encoding="cp866", # Русская кодировка
22+
errors="ignore"
23+
)
24+
except subprocess.CalledProcessError:
25+
return {}, {}
26+
27+
usage = {}
28+
details = {}
29+
30+
networks = output.split("SSID ")
31+
for net in networks[1:]:
32+
ssid_match = re.search(r":\s*(.+)", net.splitlines()[0])
33+
ssid = ssid_match.group(1).strip() if ssid_match else "Unknown"
34+
channel_matches = re.findall(r"(?:Канал|Channel)\s*:\s*(\d+)", net)
35+
for ch_str in channel_matches:
36+
ch = int(ch_str)
37+
usage[ch] = usage.get(ch, 0) + 1
38+
if ch not in details:
39+
details[ch] = []
40+
if ssid not in details[ch]:
41+
details[ch].append(ssid)
42+
return usage, details
43+
44+
def plot_usage(channel_usage, details, band_filter):
45+
if band_filter == "2.4":
46+
channels = CHANNELS_24
47+
elif band_filter == "5":
48+
channels = CHANNELS_5
49+
else:
50+
channels = ALL_CHANNELS
51+
52+
usage = [channel_usage.get(ch, 0) for ch in channels]
53+
max_usage = max(usage) if usage else 1
54+
usage_percent = [int((u / max_usage) * 100) if max_usage > 0 else 0 for u in usage]
55+
56+
fig, ax = plt.subplots(figsize=(10, 5))
57+
bars = ax.bar([str(c) for c in channels], usage_percent, color='skyblue')
58+
ax.set_title("Загруженность Wi-Fi каналов")
59+
ax.set_ylabel("Загруженность (%)")
60+
ax.set_xlabel("Каналы")
61+
ax.set_ylim(0, 100)
62+
ax.grid(True, axis='y', linestyle='--', alpha=0.7)
63+
64+
for bar, percent, ch in zip(bars, usage_percent, channels):
65+
ax.text(bar.get_x() + bar.get_width() / 2, bar.get_height() + 1,
66+
f"{percent}%\n({channel_usage.get(ch, 0)})", ha='center', va='bottom')
67+
68+
return fig
69+
70+
def update_scan():
71+
global channel_details
72+
usage, details = parse_netsh_output()
73+
channel_details = details
74+
fig = plot_usage(usage, details, band_var.get())
75+
76+
for widget in plot_frame.winfo_children():
77+
widget.destroy()
78+
79+
canvas = FigureCanvasTkAgg(fig, master=plot_frame)
80+
canvas.draw()
81+
canvas.get_tk_widget().pack(fill=tk.BOTH, expand=True)
82+
83+
text_output.delete(1.0, tk.END)
84+
for ch in sorted(details):
85+
if (band_var.get() == "2.4" and ch not in CHANNELS_24) or \
86+
(band_var.get() == "5" and ch not in CHANNELS_5):
87+
continue
88+
ssids = ", ".join(details[ch])
89+
text_output.insert(tk.END, f"Канал {ch}{len(details[ch])} точек: {ssids}\n")
90+
91+
def scan_loop():
92+
global scanning
93+
scan_duration = int(duration_entry.get())
94+
interval = int(interval_entry.get())
95+
start_time = time.time()
96+
97+
def loop_step():
98+
nonlocal start_time
99+
if not scanning or (time.time() - start_time >= scan_duration):
100+
return
101+
update_scan()
102+
root.after(interval * 1000, loop_step)
103+
104+
root.after(0, loop_step)
105+
106+
def start_scan():
107+
global scanning
108+
if scanning:
109+
return
110+
scanning = True
111+
scan_loop()
112+
113+
def stop_scan():
114+
global scanning
115+
scanning = False
116+
117+
# ---------------- GUI ------------------
118+
119+
root = tk.Tk()
120+
root.title("Wi-FiChannelScanner")
121+
122+
# Верхняя панель
123+
control_frame = ttk.Frame(root, padding=10)
124+
control_frame.pack(fill=tk.X)
125+
126+
ttk.Label(control_frame, text="Диапазон:").pack(side=tk.LEFT)
127+
band_var = tk.StringVar(value="all")
128+
ttk.OptionMenu(control_frame, band_var, "all", "2.4", "5", "all").pack(side=tk.LEFT, padx=5)
129+
130+
ttk.Label(control_frame, text="Сканировать секунд:").pack(side=tk.LEFT)
131+
duration_entry = ttk.Entry(control_frame, width=5)
132+
duration_entry.insert(0, "30")
133+
duration_entry.pack(side=tk.LEFT)
134+
135+
ttk.Label(control_frame, text="Интервал обновления (сек):").pack(side=tk.LEFT)
136+
interval_entry = ttk.Entry(control_frame, width=5)
137+
interval_entry.insert(0, "5")
138+
interval_entry.pack(side=tk.LEFT)
139+
140+
ttk.Button(control_frame, text="Старт", command=start_scan).pack(side=tk.LEFT, padx=10)
141+
ttk.Button(control_frame, text="Стоп", command=stop_scan).pack(side=tk.LEFT)
142+
143+
# График
144+
plot_frame = ttk.Frame(root)
145+
plot_frame.pack(fill=tk.BOTH, expand=True)
146+
147+
# Текстовый вывод
148+
text_output = tk.Text(root, height=10, wrap=tk.WORD)
149+
text_output.pack(fill=tk.BOTH, expand=False, padx=10, pady=5)
150+
151+
root.mainloop()

Work1.png

61.6 KB
Loading

Work2.png

334 KB
Loading

requirements.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
matplotlib

0 commit comments

Comments
 (0)