I have two WiFi access points in the house, a FritzBox 7412 and a TP-Link TL-WR740N v4 running the open source DD-WRT firmware.
I also use Munin for monitoring my home, and had the fritzbox-munin plugin installed to see the number of connected WiFi devices:
There was no dd-wrt plugin available for munin, so I built one: The source code can be found at my git server and on sourcehut: ~cweiske/dd-wrt-munin.
As of 2022-03-11, the dd-wrt-munin is part of the official munin-contrib plugin repository.
It will generate a graph like this:
Combined view of connected devices
Now I had two graphs; one for the devices on the FritzBox, and one for the DD-WRT router. I wanted to have them in one single graph. The keyword here is loaning data:
wifidevs.update no wifidevs.graph_title Connected Wifi devices wifidevs.graph_args --base 1000 wifidevs.graph_vlabel Number of devices wifidevs.graph_info Sum of all access points wifidevs.graph_scale no wifidevs.graph_category network-wifi wifidevs.graph_total Total wifidevs.total.label not_used wifidevs.total.type GAUGE wifidevs.total.draw AREA wifidevs.total.stack \ frit_rt=frit:fritzbox_wifi_devices.wifi \ tpli_wz=frit:dd_wrt_wifi_devices_tpli_wz.wifi
This combines the wifi data from plugin fritzbox_wifi_devices on node frit and the wifi data from plugin dd_wrt_wifi_devices_tpli_wz. The result is what I wanted:
Status_Wireless.live.asp format
My dd-wrt-munin plugin uses DD-WRT's /Status_Wireless.live.asp page and tries to parse it. Here are some example data with two connected devices:
{wl_mac::F8:D1:11:8B:23:42}{wl_ssid::home.cweiske.de}{wl_channel::11 + 7 (2462 MHz HT40)}{wl_radio::Radio is On}{wl_xmit::18 dBm}{wl_rate::150 Mbit/s}{wl_busy::20053342 ms}{wl_active::785275128 ms}{wl_quality::98%}{wl_ack::15µs (2250m)}{active_wireless::'48:2C:A0:74:23:42','','ath0','1:33:36','72M','1M','HT20SGI[PS]','-61','-95','34','780','-58','0','0','0','98:CD:AC:2E:23:42','','ath0','1 day, 8:19:17','43M','48M','HT20SGI','-72','-95','23','560','-71','0','0','0'}{active_wds::}{assoc_count::10}{packet_info::SWRXgoodPacket=1965092;SWRXerrorPacket=0;SWTXgoodPacket=13036095;SWTXerrorPacket=0;}{uptime:: 16:59:35 up 9 days, 2:40, load average: 0.00, 0.01, 0.04}{ipinfo::: Disabled}
This are blocks beginning with { and ending with }. The block name is up to the first :::
wl_mac::F8:D1:11:8B:23:42 wl_ssid::home.cweiske.de wl_channel::11 + 7 (2462 MHz HT40) wl_radio::Radio is On wl_xmit::18 dBm wl_rate::150 Mbit/s wl_busy::20053342 ms wl_active::785275128 ms wl_quality::98% wl_ack::15µs (2250m) active_wireless::'48:2C:A0:74:23:42','','ath0','1:33:36','72M','1M','HT20SGI[PS]','-61','-95','34','780','-58','0','0','0','98:CD:AC:2E:23:42','','ath0','1 day, 8:19:17','43M','48M','HT20SGI','-72','-95','23','560','-71','0','0','0' active_wds:: assoc_count::10 packet_info::SWRXgoodPacket=1965092;SWRXerrorPacket=0;SWTXgoodPacket=13036095;SWTXerrorPacket=0; uptime:: 16:59:35 up 9 days, 2:40, load average: 0.00, 0.01, 0.04 ipinfo::: Disabled
The active_wireless line is a bit cryptic, but the source code wireless_madwifi.c: active_wireless_if helps to understand the columns:
websWrite( wp, "'%s','%s','%s','%s','%dM','%dM','%s','%d','%d','%d','%d','%d','%d','%d','%d'", mac, radioname, wc->ifname, UPTIME(wc->uptime, str), wc->txrate / 10 * mul / div, wc->rxrate / 10 * mul / div, info, wc->signal + bias, wc->noise + bias, wc->signal - wc->noise, qual, wc->chaininfo_avg[0], wc->chaininfo_avg[1], wc->chaininfo_avg[2], wc->chaininfo_avg[3] );