What is the best way to parse ubus output

so i got this output :

root@AP3:~#  ubus -S call hostapd.wlan2 get_clients
{"freq":2462,"clients":{"70:8a:09:df:f1:bc":{"auth":true,"assoc":true,"authorized":true,"preauth":false,"wds":false,"wmm":true,"ht":true,"vht":false,"he":false,"wps":false,"mfp":false,"rrm":[115,0,1,0,0],"extended_capabilities":[0,0,8,2,1],"aid":2,"bytes":{"rx":75767,"tx":159599},"airtime":{"rx":52775,"tx":36795},"packets":{"rx":590,"tx":396},"rate":{"rx":6000,"tx":72200},"signal":-47,"capabilities":{}},"ee:52:2a:09:59:ba":{"auth":true,"assoc":true,"authorized":true,"preauth":false,"wds":false,"wmm":true,"ht":true,"vht":false,"he":false,"wps":false,"mfp":false,"rrm":[113,0,0,0,0],"extended_capabilities":[0,0,8,0,0,0,0,64],"aid":1,"bytes":{"rx":447139,"tx":4233106},"airtime":{"rx":382161,"tx":680202},"packets":{"rx":4565,"tx":4355},"rate":{"rx":6000,"tx":72200},"signal":-47,"capabilities":{}}}}
root@AP3:~#

and i need to grepp all MACs and i need each MAC signal lvl
and i have no idea how to make it grep probably wont do it.
Maybe some kind of json but It would be best to not install anything more than alredy by default in openwrt firmware

jsonfilter should be preinstalled.

2 Likes
client_signal() {
local CLIENT="${2//_/:}"
local SIGNAL
json_select "${CLIENT}"
json_get_var SIGNAL signal
json_select ..
echo "${CLIENT} ${SIGNAL}"
}
JSON="$(ubus -S call hostapd.wlan2 get_clients)"
. /usr/share/libubox/jshn.sh
json_init
json_load "${JSON}"
json_for_each_item client_signal clients

https://openwrt.org/docs/guide-developer/jshn

3 Likes

OpenWrt 22.03.05 alredy there

that's what "preinstalled" means ...

1 Like

thanks a lot goona test now .
Actually my interest is is it faster with json to get signal lvl or use iw and grep with awk
how to get time in miliseconds
looks like doesnt work on ash
seconds only

i thought should be means i have to do it myself
well ok anyway

The very bottom of iw output reads:

Do NOT screenscrape this tool, we don't consider its output stable.
2 Likes

i still dont get it what is screen scrape iw
did you mean not to use iw with grep ?

Exactly that, expressively mentioned in the full quote of "we don't consider its output stable."

iw is an enduser tool, to be used interactively - it's not meant to be used non-interactively in a way to rely on the format of its onscreen output (so no post-processing with grep, awk, sed, tr, whatever). If you need that information, don't use iw, but link directly to nl80211 instead (e.g. via libnl3).

1 Like

as i understand ubus -S call hostapd.wlan2 get_clients with json much reliable than using iw ?
also why iw 2 times faster then directly to hostapd with json

iw does not talk to hostapd nor ubus, it queries (only-) the kernel, it has no idea what hostapd or netifd are doing. But, as mentioned, iw is not a tool with a stable output structure, it does- and will change without notice; you can't parse its output (and expect it to work longer term).

1 Like

well i guess i have to rewrite that part in my script now

Four more approaches:

  1. using ucode + ubus:
root@apu:~# ucode -lubus -e 'for (k, v in ubus.connect().call("hostapd.wlan0", "get_clients").clients) { print(`${k} ${v.signal}\n`) }'
fc:03:9f:1f:13:1c -60
42:b6:67:b7:18:81 -47
  1. using Lua + ubus:
root@apu:~# lua -lubus -e 'for k, v in pairs(ubus.connect():call("hostapd.wlan0", "get_clients", {}).clients) do print(k .. " " .. v .signal) end'
fc:03:9f:1f:13:1c -60
42:b6:67:b7:18:81 -47
  1. using Ash scripting + jsonfilter:
json=$(ubus call hostapd.wlan0 get_clients)
eval $(jsonfilter -s "$json" -e "macs=@.clients")
for mac in $macs; do
    echo "$mac $(jsonfilter -s "$json" -e "@.clients['$mac'].signal")"
done
root@apu:~# json=$(ubus call hostapd.wlan0 get_clients); eval $(jsonfilter -s "$json" -e "macs=@.clients"); for mac in $macs; do echo "
$mac $(jsonfilter -s "$json" -e "@.clients['$mac'].signal")"; done
fc:03:9f:1f:13:1c -58
42:b6:67:b7:18:81 -46
  1. using Lua + libiwinfo-lua (present on OpenWrt <= 22.03 when LuCI is installed):
root@apu:~# lua -liwinfo -e 'for mac, client in pairs(iwinfo.nl80211.assoclist("wlan0")) do print(mac .. " " .. client.signal) end'
FC:03:9F:1F:13:1C -59
42:B6:67:B7:18:81 -47
4 Likes

tried first 2 examples that are much faster.
thanks for advise gonna try it in my script !
ucode is fastest
can i using ucode get signal from a specific mac?

Sure, like this for example:

root@apu:~# ucode -lubus -p 'ubus.connect().call("hostapd.wlan0", "get_clients").clients["fc:03:9f:1f:13:1c"]?.signal'
-60

Or if you want to pass the MAC to lookup as parameter:

root@apu:~# mac=FC:03:9F:1F:13:1C
root@apu:~# ucode -lubus -p 'ubus.connect().call("hostapd.wlan0", "get_clients").clients[lc(ARGV[0])]?.signal' -- $mac
-60
3 Likes

at the end i use jsonfilter and all works good ,thanks a lot :+1:
also this metod solves the problem with alredy moved devices by signal this can tell if deveced alredy moved

now i get it :+1:
so tecnically i can use iw but after an update my scripts probably will stop working

This topic was automatically closed 10 days after the last reply. New replies are no longer allowed.