From 53135f5f5d187a04075ac724c03c08d5dc672dc0 Mon Sep 17 00:00:00 2001 From: Lars Kruse Date: Sun, 12 Jun 2016 02:51:52 +0200 Subject: [PATCH] network: new wifi_signal_noise_ plugin for signal strength and noise This new plugin offers the following advantages compared to the existing wifi_signal plugin: * support multiple wifi peers (e.g. mesh mode or master mode with multiple clients) * use "iwinfo" or "iw" for information retrieval (instead of Linux's procfs) --- plugins/network/wifi_signal_noise_ | 108 +++++++++++++++++++++++++++++ 1 file changed, 108 insertions(+) create mode 100755 plugins/network/wifi_signal_noise_ diff --git a/plugins/network/wifi_signal_noise_ b/plugins/network/wifi_signal_noise_ new file mode 100755 index 00000000..e4c2b946 --- /dev/null +++ b/plugins/network/wifi_signal_noise_ @@ -0,0 +1,108 @@ +#!/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