I'm looking for the most efficient way to obtain WiFI status information from the command line or in a shell script. By that I mean two things:
Query whether my wifi interfaces (2.4G and 5G) are up.
I'm aware that ubus call network.wireless status
holds this information in JSON format. I have been trying to mangle this by piping it to sed/awk/grep in order to only get the information whether my two interfaces are up. This worked (via a somewhat ugly and long pipe sequence of sed, awk and grep), but it wasn't really efficient (the command took 2-3s to complete on my device).
Count the number of connected clients per interface.
This seems to be easily done via iwinfo <interface> assoclist | grep -cE '^([0-9A-F]{2}:){5}[0-9A-F]{2}'
which is already faster than the first command. But is this really the most efficient way?
The reason I'm asking for the quickest and most efficient way is that I'd like to monitor and log the Wi-Fi status with a script that is exectued in regular intervals. Hence I would like to keep the overhead of this as low as possbile.
You could write a Lua script which uses libiwinfo. Here's a little example:
#!/usr/bin/lua
require "iwinfo"
local device = "wlan0"
function getinfo(ifname, func)
local driver_type = iwinfo.type(ifname)
if driver_type and iwinfo[driver_type][func] then
return iwinfo[driver_type][func](ifname)
end
return nil
end
local opmode = getinfo(device, "mode")
if opmode then
print("Device " .. device .. " is up with mode " .. opmode)
local assoclist = getinfo(device, "assoclist")
if assoclist then
local count = 0
local mac, info
for mac, info in pairs(assoclist) do
print("Client #" .. mac .. ": " .. info.signal .. "dB")
count = count + 1
end
print("There are " .. count .. " clients")
else
print("Unable to fetch associated client list")
end
else
print("Device " .. device .. " appears to be down")
end
Thanks a lot for the detailed answer and sample script. I quickly tested the various options against each other and it seems the lua script is the quickest and cleanest way to do this.
One more question though: I see you use "mode" as an indicator whether the device is up or not. Is that equal to the ubus wireless node radio{0,1}.up being set to true? Or are there corner cases where mode would still return "Master" but the radio would actually be disassociated?
I'm asking this because in the past I had issues with the ath10k firmware where it would crash or not be loaded during boot under certain circumstances. In these situations, iirc, the 5G radio would be shown as "disassociated" in LuCI.
So, I modified your script to return the information I'd like to collect. Apologies for any errors or style issues that I might have added to the code, but this is the first time I acutally played with LUA. Yet, it works fine so far:
#!/usr/bin/lua
require "iwinfo"
local devices = {}
devices["5G"] = "wlan0"
devices["2.4G"] = "wlan1"
function getinfo(ifname, func)
local driver_type = iwinfo.type(ifname)
if driver_type and iwinfo[driver_type][func] then
return iwinfo[driver_type][func](ifname)
end
return nil
end
local key, device
for key, device in pairs(devices) do
local opmode = getinfo(device, "mode")
if opmode == "Master" then
local count = 0
local assoclist = getinfo(device, "assoclist")
if assoclist then
local _
for _ in pairs(assoclist) do
count = count + 1
end
end
print(key .. " radio is up, " .. count .. " clients connected")
else
print(key .. " radio appears to be down")
end
end
Here's how it looks:
root@lede:~# ./wifi_info.lua
2.4G radio is up, 7 clients connected
5G radio is up, 5 clients connected
I can now answer my own question as I experienced such an ath10k driver crash again. At least in my case, the "mode" property is not a good indicator for the radio being up or not. When the ath10k driver crashes, "mode" would still return "Master", but the radio is actually down. iwinfo would instead show that the properties "signal" and "bit rate" return "unknown" (or "nil" inside the lua script) and "link quality" would show "unknown/70". So I changed the script to check for the value of "signal" as well when there are no clients connected. If there are 0 clients and signal is "nil", my script would report the radio is down or in failed state.