Select wireless channel automatically
#!/usr/bin/awk -f | |
# Coded by: Vladislav Grigoryev <vg[dot]aetera[at]gmail[dot]com> | |
# License: GNU General Public License (GPL) version 3+ | |
# Description: Select wireless channel automatically | |
function get_iwphy() { | |
cmd = "iw phy" | |
while(cmd | getline) { | |
if($0 ~ /^\s*Wiphy\s/) | |
phy = gensub(/^\s*\w*\s(\w+)$/, "\\1", 1, $0) | |
else if($0 ~ /^\s*Band\s/) | |
band = gensub(/^\s*\w*\s([0-9]+):$/, "\\1", 1, $0) | |
else if($0 ~ /^\s*\*\s*[0-9]+\s*MHz.*dBm/) { | |
freq = gensub(/^.*\s([0-9]+)\s*MHz.*$/, "\\1", 1, $0) | |
chan = gensub(/^.*\[([0-9]+)\].*$/, "\\1", 1, $0) | |
iwphy[phy, freq, "band"] = band | |
iwphy[phy, freq, "chan"] = chan | |
} | |
} | |
close(cmd) | |
} | |
function get_iwdev() { | |
cmd = "iw dev" | |
while(cmd | getline) { | |
if($0 ~ /^\s*phy\x23/) | |
phy = gensub(/^\s*(\w+)\x23([0-9]+)$/, "\\1\\2", 1, $0) | |
else if($0 ~ /^\s*Interface\s/) | |
dev = gensub(/^\s*\w*\s(\w+)$/, "\\1", 1, $0) | |
else if($0 ~ /^\s*channel\s/) { | |
freq = gensub(/^.*\(([0-9]+)\s*MHz\).*$/, "\\1", 1, $0) | |
iwdev[phy, dev, "freq"] = freq | |
} | |
} | |
close(cmd) | |
} | |
function get_iwconf() { | |
for(iwdev_subs in iwdev) { | |
split(iwdev_subs, iwdev_sub, SUBSEP) | |
if(iwdev_sub[3] != "freq") continue | |
phy = iwdev_sub[1] | |
dev = iwdev_sub[2] | |
if(phy_conf == "") phy_conf = phy | |
if(phy_conf != phy) continue | |
dev_conf = dev | |
freq_conf = iwdev[phy_conf, dev_conf, "freq"] | |
band_conf = iwphy[phy_conf, freq_conf, "band"] | |
} | |
} | |
function get_iwscan() { | |
cmd = "iw dev "dev_conf" scan" | |
while(cmd | getline) { | |
if($0 ~ /^\s*BSS\s/) | |
bssid = gensub(/^\s*\w*\s*([:0-9a-f]+).*$/, "\\1", 1, $0) | |
else if($0 ~ /^\s*freq:/) { | |
freq = gensub(/^\s*\w*:\s*([0-9]+).*$/, "\\1", 1, $0) | |
iwscan[bssid, "freq"] = freq | |
} | |
else if($0 ~ /^\s*signal:/) { | |
signal = gensub(/^\s*\w*:\s*([-.0-9]+).*$/, "\\1", 1, $0) + 0 | |
iwscan[bssid, "signal"] = signal | |
if(signal < - 100) quality = 0 | |
else if(signal < - 50) quality = 2 * (signal + 100) | |
else quality = 100 | |
iwscan[bssid, "quality"] = quality | |
} | |
else if($0 ~ /^\s*SSID:/) { | |
ssid = gensub(/^\s*\w*:\s*(.*)$/, "\\1", 1, $0) | |
iwscan[bssid, "ssid"] = ssid | |
} | |
} | |
close(cmd) | |
} | |
function get_iwload() { | |
for(iwphy_subs in iwphy) { | |
split(iwphy_subs, iwphy_sub, SUBSEP) | |
if(iwphy_sub[3] != "chan") continue | |
phy = iwphy_sub[1] | |
freq = iwphy_sub[2] | |
band = iwphy[phy, freq, "band"] | |
load = iwphy[phy, freq, "load"] | |
if(band != band_conf) continue | |
for(iwscan_subs in iwscan) { | |
split(iwscan_subs, iwscan_sub, SUBSEP) | |
if(iwscan_sub[2] != "freq") continue | |
bssid = iwscan_sub[1] | |
freq_bssid = iwscan[bssid, "freq"] | |
signal = iwscan[bssid, "signal"] | |
freq_diff = freq - freq_bssid | |
if(freq_diff < 0) freq_diff = - freq_diff | |
if(freq_diff < 5) signal_factor = 100 | |
else if(freq_diff < 10) signal_factor = 95 | |
else if(freq_diff < 15) signal_factor = 85 | |
else if(freq_diff < 20) signal_factor = 15 | |
else if(freq_diff < 25) signal_factor = 5 | |
else signal_factor = 0 | |
if(signal < - 100) load += 0 | |
else load += (signal + 100) * signal_factor | |
iwphy[phy, freq, "load"] = load | |
} | |
} | |
} | |
function get_iwstatus() { | |
for(iwphy_subs in iwphy) { | |
split(iwphy_subs, iwphy_sub, SUBSEP) | |
if(iwphy_sub[3] != "chan") continue | |
phy = iwphy_sub[1] | |
freq = iwphy_sub[2] | |
band = iwphy[phy, freq, "band"] | |
load = iwphy[phy, freq, "load"] | |
if(band != band_conf) continue | |
if(load_optim != "" && load_optim < load) continue | |
freq_optim = freq | |
load_optim = load | |
} | |
status_conf = "-" | |
iwphy[phy_conf, freq_conf, "status"] = status_conf | |
status_optim = iwphy[phy_conf, freq_optim, "status"] "+" | |
iwphy[phy_conf, freq_optim, "status"] = status_optim | |
} | |
function get_iwchan() { | |
freq_diff = freq_conf - freq_optim | |
load_conf = iwphy[phy_conf, freq_conf, "load"] | |
load_optim = iwphy[phy_conf, freq_optim, "load"] | |
load_diff = load_conf - load_optim | |
if(freq_diff < 0) freq_diff = - freq_diff | |
if(freq_diff < freq_thr || load_diff < load_thr) return | |
chan_optim = iwphy[phy_conf, freq_optim, "chan"] | |
printf "%d\n", chan_optim | |
} | |
function print_iwinfo() { | |
printf "Phy:\t%s\nDev:\t%s\nBand:\t%s\nFreqTh:\t%d\nLoadTh:\t%d\n", | |
phy_conf, dev_conf, band_conf, freq_thr, load_thr | |
} | |
function print_iwscan() { | |
cmd = "sort -n" | |
printf "\nFreq\tChannel\tSignal\tQuality\tBSSID\t\t\tSSID\n" | |
for(iwscan_subs in iwscan) { | |
split(iwscan_subs, iwscan_sub, SUBSEP) | |
if(iwscan_sub[2] != "ssid") continue | |
bssid = iwscan_sub[1] | |
freq = iwscan[bssid, "freq"] | |
chan = iwphy[phy_conf, freq, "chan"] | |
signal = iwscan[bssid, "signal"] | |
quality = iwscan[bssid, "quality"] | |
ssid = iwscan[bssid, "ssid"] | |
printf "%d\t%d\t%d\t%d\t%s\t%s\n", freq, chan, signal, quality, | |
bssid, ssid | cmd | |
} | |
close(cmd) | |
} | |
function print_iwlist() { | |
cmd = "sort -n" | |
printf "\nFreq\tChannel\tLoad\tStatus\n" | |
for(iwphy_subs in iwphy) { | |
split(iwphy_subs, iwphy_sub, SUBSEP) | |
if(iwphy_sub[3] != "chan") continue | |
phy = iwphy_sub[1] | |
freq = iwphy_sub[2] | |
band = iwphy[phy, freq, "band"] | |
chan = iwphy[phy, freq, "chan"] | |
load = iwphy[phy, freq, "load"] | |
status = iwphy[phy, freq, "status"] | |
if(band != band_conf) continue | |
printf "%d\t%d\t%d\t%s\n", freq, chan, load, status | cmd | |
} | |
close(cmd) | |
} | |
BEGIN { | |
subcmd = ARGV[1] | |
phy_conf = ARGV[2] | |
freq_thr = ARGV[3] | |
load_thr = ARGV[4] | |
if(subcmd == "") subcmd = "help" | |
if(freq_thr == "") freq_thr = 15 | |
if(load_thr == "") load_thr = 1000 | |
if(subcmd == "help") | |
printf "awk -f iwchan.awk [show|get|help] [phy] [freq_thr] [load_thr]\n" | |
else if(subcmd == "get" || subcmd == "show") { | |
get_iwphy() | |
get_iwdev() | |
get_iwconf() | |
get_iwscan() | |
get_iwload() | |
get_iwstatus() | |
if(subcmd == "get") get_iwchan() | |
else if(subcmd == "show") { | |
print_iwinfo() | |
print_iwscan() | |
print_iwlist() | |
} | |
} | |
} |
# awk -f iwchan.awk help | |
awk -f iwchan.awk [show|get|help] [phy] [freq_thr] [load_thr] | |
# awk -f iwchan.awk get | |
5 | |
# awk -f iwchan.awk show | |
Phy: phy0 | |
Dev: wlp2s0 | |
Band: 1 | |
FreqTh: 15 | |
LoadTh: 1000 | |
Freq Channel Signal Quality BSSID SSID | |
2412 1 -63 74 90:94:e4:ef:0c:66 vghome | |
2412 1 -74 52 10:fe:ed:2a:1f:cc Dead Moroz-z-z | |
2437 6 -72 56 c4:6e:1f:65:65:02 TP-LINK_656502 | |
2457 10 -65 70 d8:0d:17:21:ff:a6 TP-Link_FFA6 | |
2457 10 -83 34 c4:6e:1f:70:ed:6e TP-LINK_ED6E | |
2462 11 -57 86 c0:25:e9:c4:b8:68 CityLink-12 | |
2467 12 -58 84 54:04:a6:c7:34:ac quick3 | |
Freq Channel Load Status | |
2412 1 6300 - | |
2417 2 6125 | |
2422 3 5775 | |
2427 4 3325 | |
2432 5 2975 + | |
2437 6 3060 | |
2442 7 3655 | |
2447 8 7655 | |
2452 9 9645 | |
2457 10 12995 | |
2462 11 13230 | |
2467 12 12705 | |
2472 13 8425 |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment