#!/bin/sh # # Show current signal strength and noise for all connected peers of wifi devices. # This plugin is suitable for wifi interfaces with a stable selection of peers # (e.g. infrastructure). # Author: Lars Kruse, devel@sumpfralle.de # License: GPL v3 or later # # Requirements: # * "iwinfo" tool (alternatively: fall back to "iw" - with incomplete data) # * root privileges (for "iw" and "iwinfo") # # Magic markers #%# capabilities=autoconf suggest #%# family=auto set -eu # prefer "iwinfo" for information retrieval, if it is available if which iwinfo >/dev/null; then # "iwinfo" has a stable output format but is only available on openwrt get_wifi_interfaces() { iwinfo | grep "^[a-zA-Z]" | awk '{print $1}'; } # return MAC of peer and the signal strength get_wifi_peers() { iwinfo "$1" assoclist | grep "^[0-9a-fA-F]" | awk '{print $1,$2}'; } # the noise should be the same for all peers get_wifi_noise() { iwinfo "$1" info | sed -n 's/^.* Noise: \([0-9-]\+\).*/\1/p'; } else # "iw" is available everywhere - but its output format is not recommended for non-humans get_wifi_interfaces() { iw dev | awk '{ if ($1 == "Interface") print $2; }'; } get_wifi_peers() { iw dev wlan0 station dump \ | awk '{ if ($1 == "Station") mac=$2; if (($1 == "signal") && ($2 == "avg:")) print mac,$3}'; } # TODO: there seems to be no way to retrieve the noise level via "iw" get_wifi_noise() { echo; } fi clean_fieldname() { echo "$1" | sed 's/^\([^A-Za-z_]\)/_\1/; s/[^A-Za-z0-9_]/_/g' } get_ip_for_mac() { local ip ip=$(arp -n | grep -iw "$1$" | awk '{print $1}' | sort | head -1) [ -n "$ip" ] && echo "$ip" && return 0 # no IP found - return MAC instead echo "$1" } get_wifi_device_from_suffix() { local suffix local real_dev # pick the part after the basename of the real file suffix=$(basename "$0" | sed "s/^$(basename "$(readlink "$0")")//") for real_dev in $(get_wifi_interfaces); do [ "$suffix" != "$(clean_fieldname "$real_dev")" ] || echo "$real_dev" done | head -1 } ACTION="${1:-}" case "$ACTION" in config) wifi=$(get_wifi_device_from_suffix) echo "graph_title Wireless signal quality - $wifi" echo "graph_args --upper-limit 0" echo "graph_vlabel Signal and noise [dBm]" echo "graph_category network" echo "graph_info This graph shows the signal and noise for all wifi peers" echo "noise.label Noise floor" echo "noise.draw LINE" # sub graphs for all peers get_wifi_peers "$wifi" | while read mac signal; do fieldname=$(clean_fieldname "peer_${mac}") peer=$(get_ip_for_mac "$mac") echo "signal_${fieldname}.label $peer" echo "signal_${fieldname}.draw LINE" done ;; autoconf) [ -z "$(get_wifi_interfaces)" ] && echo "no (no wifi interfaces found)" && exit 1 echo "yes" ;; suggest) get_wifi_interfaces | while read ifname; do clean_fieldname "$ifname" done ;; "") wifi=$(get_wifi_device_from_suffix) peer_data=$(get_wifi_peers "$wifi") echo "$peer_data" | while read mac signal; do # ignore empty datasets [ -z "$signal" ] && continue fieldname=$(clean_fieldname "peer_${mac}") echo "signal_${fieldname}.value $signal" done echo "noise.value $(get_wifi_noise "$wifi")" ;; *) echo >&2 "Invalid action (valid: config)" echo >&2 ;; esac