From 678c361b4142b1bfeb34d2b33b9747fd48aff695 Mon Sep 17 00:00:00 2001 From: sommerfeld Date: Tue, 21 Apr 2026 01:25:02 +0100 Subject: waybar: use iwd D-Bus + /proc for wifi instead of scraping iwctl Replace iwctl ANSI-stripping with busctl calls against net.connman.iwd (a formally stable, documented D-Bus API) to get state and SSID, and read signal strength directly from /proc/net/wireless. No more parser fragility if iwctl's human-readable layout changes. --- dot_config/waybar/executable_wifi-status.sh | 57 +++++++++++++++++++---------- 1 file changed, 37 insertions(+), 20 deletions(-) (limited to 'dot_config/waybar/executable_wifi-status.sh') diff --git a/dot_config/waybar/executable_wifi-status.sh b/dot_config/waybar/executable_wifi-status.sh index e69e5bb..eae2ff3 100755 --- a/dot_config/waybar/executable_wifi-status.sh +++ b/dot_config/waybar/executable_wifi-status.sh @@ -1,27 +1,44 @@ #!/bin/sh -# Emit waybar JSON describing wifi link state. Uses iwctl (from iwd) so we -# don't need the separate `iw` package. Handles bond-slaved wlan where -# waybar's built-in network module fails to detect wifi. +# Emit waybar JSON describing wifi link state. +# +# Uses iwd's D-Bus API for state + SSID (net.connman.iwd is a documented, +# stable interface) and /proc/net/wireless for signal strength. No reliance +# on iwctl's human-readable TTY output. set -eu iface=wlan0 +svc=net.connman.iwd -# iwctl emits ANSI colour codes even when stdout is a pipe; strip them. -out=$(iwctl station "$iface" show 2>/dev/null | sed 's/\x1b\[[0-9;]*[a-zA-Z]//g' || true) - -state=$(printf '%s\n' "$out" | awk '/ State / {print $NF; exit}') -if [ "$state" != "connected" ]; then - printf '{"text":"wifi off","class":"down"}\n' - exit 0 -fi - -ssid=$(printf '%s\n' "$out" | - sed -n 's/^[[:space:]]*Connected network[[:space:]]\{2,\}//p' | - sed 's/[[:space:]]*$//') -rssi=$(printf '%s\n' "$out" | - sed -n 's/^[[:space:]]*\*\{0,1\}[[:space:]]*AverageRSSI[[:space:]]\{2,\}//p' | - awk '{print $1; exit}') -pct=$(awk -v r="${rssi:-0}" 'BEGIN{p=2*(r+100); if(p>100)p=100; if(p<0)p=0; printf "%d",p}') +down() { + printf '{"text":"wifi off","class":"down"}\n' + exit 0 +} + +# Locate the iwd object path for this interface. +station=$(busctl --system --json=short call "$svc" / \ + org.freedesktop.DBus.ObjectManager GetManagedObjects 2>/dev/null | + jq -r --arg iface "$iface" ' + (.data[0] // .data) as $objs + | $objs | to_entries[] + | select(.value["net.connman.iwd.Device"].Name.data == $iface) + | .key' 2>/dev/null || true) +[ -n "$station" ] || down + +state=$(busctl --system --json=short get-property "$svc" "$station" \ + net.connman.iwd.Station State 2>/dev/null | jq -r '.data' 2>/dev/null || true) +[ "$state" = "connected" ] || down + +netpath=$(busctl --system --json=short get-property "$svc" "$station" \ + net.connman.iwd.Station ConnectedNetwork | jq -r '.data') +ssid=$(busctl --system --json=short get-property "$svc" "$netpath" \ + net.connman.iwd.Network Name | jq -r '.data') + +# /proc/net/wireless: ": . . . ..." +# We want (column 4), which is dBm. Strip trailing dot. +rssi=$(awk -v i="$iface:" '$1==i { sub(/\./, "", $4); print $4; exit }' /proc/net/wireless) +rssi=${rssi:-0} + +pct=$(awk -v r="$rssi" 'BEGIN{p=2*(r+100); if(p>100)p=100; if(p<0)p=0; printf "%d",p}') color=$(awk -v p="$pct" 'BEGIN{ if (p < 20) print "#fb4934" else if (p < 40) print "#fe8019" @@ -30,4 +47,4 @@ color=$(awk -v p="$pct" 'BEGIN{ }') printf '{"text":"%s %s%%","class":"up","tooltip":"%s ยท %s dBm"}\n' \ - "$ssid" "$color" "$pct" "$iface" "$rssi" + "$ssid" "$color" "$pct" "$iface" "$rssi" -- cgit v1.2.3-70-g09d2