Can you monitor the signal strength of different Wi-Fi devices that are connected to your (home) router with Zabbix? Of course you can! This is a really quick post that also shows how ChatGPT or any LLM can boost your productivity when doing this kind of thing.
I have an ASUS RT-AX68U router running on Asuswrt-Merlin firmware. On its web interface, it can show you all kinds of details about your network and the devices on it. This is nice, but it would be even nicer to add some of that to Zabbix. One interesting idea for me would be to monitor the signal strength of my Wi-FI devices around the house, so let’s do that and start monitoring RSSI!
What’s RSSI?
Here’s a reply by ChatGPT:
In Wi-Fi (and RF in general), RSSI (Received Signal Strength Indicator) is typically measured in negative dBm values:
• The closer the value is to 0 dBm, the stronger (better) the signal.
• The more negative the value, the weaker the signal.
Broadly speaking, here is a rough guideline:
• -30 dBm: Extremely strong signal (almost too strong – rare in normal conditions).
• -50 dBm: Excellent signal.
• -60 dBm: Very good signal, plenty strong for most uses.
• -70 dBm: Adequate; connectivity is usually reliable but might slow at times.
• -80 dBm: Marginal; still connected but performance may degrade.
• -90 dBm or lower: Very weak; likely to drop connection or have very poor speeds.
Monitoring implementation
If you are a regular reader, you should know by now that I’m not a fan of letting Zabbix agent or any other agent run commands directly for gathering metrics unless I really need the metrics that second. Rather, I’ll use cron jobs or any other background way of creating text files which then will be parsed by Zabbix.
That said, my ASUS now runs a shell script every minute, which then writes a text file /tmp/rssi.txt, which is read by Zabbix agent.
The shell script
Thank you ChatGPT for the following: The script uses wl -i assoclist command to list the connected devices with their MAC addresses and signal strength, and converts those MAC addresses to hostnames to be human-readable.
#!/bin/sh # Interfaces for 2.4 and 5 GHz (adjust if your router uses different names) IFACES="eth5 eth6" LEASES_FILE="/var/lib/misc/dnsmasq.leases" rm -f /tmp/rssi.txt echo "Hostname:RSSI" >/tmp/rssi.txt for iface in $IFACES do # List all MACs associated on this interface for MAC in $(wl -i "$iface" assoclist 2>/dev/null | awk '{print $2}') do # Get RSSI RSSI=$(wl -i "$iface" rssi "$MAC" 2>/dev/null) # Look up IP and hostname in dnsmasq leases (if present) # The leases file format is: <epoch> <MAC> <IP> <hostname> <clientid> IP=$(grep -i "$MAC" "$LEASES_FILE" | awk '{print $3}') HOSTNAME=$(grep -i "$MAC" "$LEASES_FILE" | awk '{print $4}') # If the device is static or not found in dnsmasq leases, IP/HOSTNAME might be empty # so handle that gracefully [ -z "$IP" ] && IP="Unknown" [ -z "$HOSTNAME" ] && HOSTNAME="Unknown" #echo "MAC $MAC:" #echo " RSSI: $RSSI dBm" #echo " IP: $IP" #echo " Hostname: $HOSTNAME" echo "$HOSTNAME:$RSSI" >>/tmp/rssi.txt done done
It outputs this, with self-explanatory results.
Hostname:RSSI Watch:-43 058743599:-66 Samsung:-62 SonosZP:-45 BroadLink_OEM-T1-89-d3-bb:-57 Kitchen:-52 Mac:-39 iPhone:-40 *:-60 MacBookPro:-43
Adding it to Zabbix
First, I added a new template, for which I then added a new master item reading the /tmp/rssi.txt file.
Because ChatGPT script did make the output in CSV format with : as delimiter, we can use Zabbix item preprocessing to convert that CSV to JSON. The JSON output looks like this.
[{"Hostname":"Watch","RSSI":"-45"},{"Hostname":"058743599","RSSI":"-70"},{"Hostname":"Samsung","RSSI":"-60"},{"Hostname":"SonosZP","RSSI":"-44"},{"Hostname":"BroadLink_OEM-T1-89-d3-bb","RSSI":"-61"},{"Hostname":"Kitchen","RSSI":"-53"},{"Hostname":"Mac","RSSI":"-37"},{"Hostname":"iPhone","RSSI":"-39"},{"Hostname":"*","RSSI":"-56"},{"Hostname":"MacBookPro","RSSI":"-41"}]
With this, we can then use Zabbix low-level discovery to automatically create the items.
Discovery rule
Now that we have our master item, let’s add the discovery rule, which can go through the JSON. The discovery rule uses my previous item as a dependent item, from which it can parse everything in one go.
Discovery item prototype
In item prototype, let’s make it again use the raw list as a dependent item and go from there.
Then in preprocessing, it picks the RSSI value for whatever device LLD was going through by using a JSONPath query…
…or as text:
$[?(@.Hostname=='{#WIFICLIENT}’)].RSSI.first()
That’s pretty much it!
We now have the data coming in once per minute:
Here’s a little dashboard, too. It shows you the traditional bar that’s available on the Top hosts/items widget, and also the new Sparkline that’s on Zabbix 7.2.
Bonus: Location estimation
After a little bit of walking around and observing the devices, I added some value mapping to make Zabbix estimate where the devices would be located. It’s not so useful for static objects, but when I move around with my Apple Watch and iPhone, I could make an attempt to monitor my location at home, too.
After this fine-tuning, my dashboard now looks like this:
Thanks for reading, and have fun conducting your own experiments!