Skip to content

Instantly share code, notes, and snippets.

@qosmio
Created January 13, 2021 20:36
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save qosmio/c08670a43fade9f1204944674de5d616 to your computer and use it in GitHub Desktop.
Save qosmio/c08670a43fade9f1204944674de5d616 to your computer and use it in GitHub Desktop.
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
# Description: OpenWrt iwchan wrapper script
IWCHAN="/path/to/iwchan.awk"
PHYID="0"
CHAN="$(awk -f "${IWCHAN}" get "phy${PHYID}" 2> /dev/null)"
if [ -z "${CHAN}" ]; then exit 0; fi
uci set wireless."radio${PHYID}".channel="${CHAN}"
wifi reload
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment