|
|
#!/usr/bin/env bash |
|
|
|
|
|
# Get the default interface used for routing |
|
|
INTERFACE=$(ip route 2>/dev/null | grep '^default' | awk '{print $5}' | head -1) |
|
|
|
|
|
if [ -z "$INTERFACE" ]; then |
|
|
echo '{"text": " No net", "tooltip": "No network connection"}' |
|
|
exit 0 |
|
|
fi |
|
|
|
|
|
# Get IPv4 address of the interface |
|
|
IP=$(ip -4 addr show "$INTERFACE" 2>/dev/null | grep -oP '(?<=inet\s)\d+(\.\d+){3}' | head -1) |
|
|
|
|
|
if [ -z "$IP" ]; then |
|
|
echo '{"text": " No IP", "tooltip": "Interface '"$INTERFACE"' has no IP"}' |
|
|
exit 0 |
|
|
fi |
|
|
|
|
|
# Determine interface type and set appropriate icon |
|
|
if [[ "$INTERFACE" =~ ^(wlan|wlp) ]]; then |
|
|
ICON="" # generic network icon (nerd font) |
|
|
TYPE="WiFi" |
|
|
elif [[ "$INTERFACE" =~ ^(eth|enp|eno|ens) ]]; then |
|
|
ICON="" # generic network icon (nerd font) |
|
|
TYPE="Ethernet" |
|
|
else |
|
|
ICON="" # generic network icon (nerd font) |
|
|
TYPE="$INTERFACE" |
|
|
fi |
|
|
|
|
|
# --- Transfer rate calculation --- |
|
|
|
|
|
# Path to sysfs statistics |
|
|
RX_FILE="/sys/class/net/$INTERFACE/statistics/rx_bytes" |
|
|
TX_FILE="/sys/class/net/$INTERFACE/statistics/tx_bytes" |
|
|
STATE_FILE="/tmp/waybar-network-stats-$INTERFACE" |
|
|
|
|
|
# Read current byte counters |
|
|
NOW_RX=$(cat "$RX_FILE" 2>/dev/null) |
|
|
NOW_TX=$(cat "$TX_FILE" 2>/dev/null) |
|
|
NOW_TS=$(date +%s%N) # nanoseconds for precision |
|
|
|
|
|
# Helper: format bytes/sec to human-readable |
|
|
format_rate() { |
|
|
local bytes_per_sec="$1" |
|
|
if [ "$bytes_per_sec" -lt 0 ]; then |
|
|
bytes_per_sec=0 |
|
|
fi |
|
|
if [ "$bytes_per_sec" -ge 1073741824 ]; then |
|
|
awk -v n="$bytes_per_sec" 'BEGIN { printf "%.1fG", n / 1073741824 }' |
|
|
elif [ "$bytes_per_sec" -ge 1048576 ]; then |
|
|
awk -v n="$bytes_per_sec" 'BEGIN { printf "%.1fM", n / 1048576 }' |
|
|
elif [ "$bytes_per_sec" -ge 1024 ]; then |
|
|
awk -v n="$bytes_per_sec" 'BEGIN { printf "%.1fK", n / 1024 }' |
|
|
else |
|
|
awk -v n="$bytes_per_sec" 'BEGIN { printf "%.1fB", n }' |
|
|
fi |
|
|
} |
|
|
|
|
|
RATE_DOWN="" |
|
|
RATE_UP="" |
|
|
|
|
|
if [ -f "$STATE_FILE" ]; then |
|
|
# Read previous values: rx tx timestamp_ns |
|
|
read -r PREV_RX PREV_TX PREV_TS < "$STATE_FILE" |
|
|
|
|
|
if [ -n "$PREV_RX" ] && [ -n "$PREV_TX" ] && [ -n "$PREV_TS" ]; then |
|
|
# Calculate time delta in seconds (nanosecond difference) |
|
|
DELTA_NS=$((NOW_TS - PREV_TS)) |
|
|
if [ "$DELTA_NS" -gt 0 ]; then |
|
|
DELTA_RX=$((NOW_RX - PREV_RX)) |
|
|
DELTA_TX=$((NOW_TX - PREV_TX)) |
|
|
|
|
|
# bytes per second = delta_bytes / (delta_ns / 1e9) |
|
|
RX_BPS=$(awk -v rx="$DELTA_RX" -v ns="$DELTA_NS" 'BEGIN { printf "%.0f", rx * 1000000000 / ns }') |
|
|
TX_BPS=$(awk -v tx="$DELTA_TX" -v ns="$DELTA_NS" 'BEGIN { printf "%.0f", tx * 1000000000 / ns }') |
|
|
|
|
|
if [ -n "$RX_BPS" ] && [ -n "$TX_BPS" ]; then |
|
|
RATE_DOWN=$(format_rate "$RX_BPS") |
|
|
RATE_UP=$(format_rate "$TX_BPS") |
|
|
fi |
|
|
fi |
|
|
fi |
|
|
fi |
|
|
|
|
|
# Save current state for next run |
|
|
echo "$NOW_RX $NOW_TX $NOW_TS" > "$STATE_FILE" |
|
|
|
|
|
# --- Build output --- |
|
|
|
|
|
if [ -n "$RATE_DOWN" ] && [ -n "$RATE_UP" ]; then |
|
|
RATE_STR=" ↓${RATE_DOWN} ↑${RATE_UP}" |
|
|
else |
|
|
RATE_STR="" |
|
|
fi |
|
|
|
|
|
echo "{\"text\": \"<span size='x-large' rise='-1500'>$ICON</span> $INTERFACE $IP${RATE_STR}\", \"tooltip\": \"$TYPE: $INTERFACE — $IP | ↓ ${RATE_DOWN:-?}/s ↑ ${RATE_UP:-?}/s\"}"
|
|
|
|