#!/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\": \"$ICON $INTERFACE $IP${RATE_STR}\", \"tooltip\": \"$TYPE: $INTERFACE — $IP | ↓ ${RATE_DOWN:-?}/s ↑ ${RATE_UP:-?}/s\"}"