Files
blackroad/roadnet/roadnet-status.sh
Alexa Amundson 78fbe80f2a Initial monorepo — everything BlackRoad in one place
bin/       230 CLI tools (ask-*, br-*, agent-*, roadid, carpool)
scripts/   99 automation scripts
fleet/     Node configs and deployment
workers/   Cloudflare Worker sources (roadpay, road-search, squad webhooks)
roadc/     RoadC programming language
roadnet/   Mesh network (5 APs, WireGuard)
operator/  Memory system scripts
config/    System configs
dotfiles/  Shell configs
docs/      Documentation

BlackRoad OS — Pave Tomorrow.

RoadChain-SHA2048: d1a24f55318d338b
RoadChain-Identity: alexa@sovereign
RoadChain-Full: d1a24f55318d338b24b60bad7be39286379c76ae5470817482100cb0ddbbcb97e147d07ac7243da0a9f0363e4e5c833d612b9c0df3a3cd20802465420278ef74875a5b77f55af6fe42a931b8b635b3d0d0b6bde9abf33dc42eea52bc03c951406d8cbe49f1a3d29b26a94dade05e9477f34a7d4d4c6ec4005c3c2ac54e73a68440c512c8e83fd9b1fe234750b898ef8f4032c23db173961fe225e67a0432b5293a9714f76c5c57ed5fdf35b9fb40fd73c03ebf88b7253c6a0575f5afb6a6b49b3bda310602fb1ef676859962dad2aebbb2875814b30eee0a8ba195e482d4cbc91d8819e7f38f6db53e8063401649c77bb994371473cabfb917fb53e8cbe73d60
2026-03-14 17:08:41 -05:00

149 lines
5.9 KiB
Bash
Executable File

#!/bin/bash
# RoadNet Status Dashboard — run from Mac
# Shows all nodes, connected clients, transport state
PINK='\033[38;5;205m'
AMBER='\033[38;5;214m'
BLUE='\033[38;5;69m'
GREEN='\033[38;5;82m'
RED='\033[38;5;196m'
VIOLET='\033[38;5;135m'
DIM='\033[2m'
RESET='\033[0m'
declare -A NODES=(
[Alice]="pi@192.168.4.49"
[Cecilia]="blackroad@192.168.4.96"
[Octavia]="pi@192.168.4.97"
[Aria]="pi@192.168.4.98"
[Lucidia]="octavia@192.168.4.38"
)
declare -A NODE_IDS=([Alice]=1 [Cecilia]=2 [Octavia]=3 [Aria]=4 [Lucidia]=5)
declare -A CHANNELS=([Alice]=1 [Cecilia]=6 [Octavia]=11 [Aria]=1 [Lucidia]=11)
TMPDIR=$(mktemp -d)
trap "rm -rf $TMPDIR" EXIT
echo ""
echo -e "${PINK}╔══════════════════════════════════════════════════════════════╗${RESET}"
echo -e "${PINK}║ R O A D N E T — S T A T U S ║${RESET}"
echo -e "${PINK}║ Your Network. Your Rules. No Carrier. ║${RESET}"
echo -e "${PINK}╠══════════════════════════════════════════════════════════════╣${RESET}"
# Query each node in parallel
for name in Alice Cecilia Octavia Aria Lucidia; do
ssh_target="${NODES[$name]}"
nid="${NODE_IDS[$name]}"
(
ssh -o ConnectTimeout=3 -o StrictHostKeyChecking=no "$ssh_target" "
echo 'NODE=${name}'
# hostapd status
if pgrep -x hostapd >/dev/null 2>&1; then
echo 'AP=UP'
# Count connected clients
CLIENTS=\$(hostapd_cli -i wlan0 all_sta 2>/dev/null | grep -c '^\([0-9a-f]\{2\}:\)\{5\}' || echo 0)
[[ -z \"\$CLIENTS\" || \"\$CLIENTS\" == \"\" ]] && CLIENTS=0
echo \"CLIENTS=\${CLIENTS}\"
else
echo 'AP=DOWN'
echo 'CLIENTS=0'
fi
# WiFi interface IP
WIFI_IP=\$(ip addr show wlan0 2>/dev/null | grep 'inet ' | awk '{print \$2}' | head -1)
echo \"WIFI_IP=\${WIFI_IP:-none}\"
# Current exit route
if ip route show table 100 2>/dev/null | grep -q 'dev wg0'; then
echo 'EXIT=wg0'
elif ip route show table 100 2>/dev/null | grep -q 'dev eth0\|dev end0'; then
echo 'EXIT=eth0'
else
DEFAULT=\$(ip route show default 2>/dev/null | head -1 | awk '{print \$5}')
echo \"EXIT=\${DEFAULT:-unknown}\"
fi
# WireGuard
if ip link show wg0 >/dev/null 2>&1; then
echo 'WG=UP'
else
echo 'WG=DOWN'
fi
# Bluetooth PAN
if ip link show bnep0 >/dev/null 2>&1 || ip link show br-roadnet >/dev/null 2>&1; then
echo 'BT=UP'
else
echo 'BT=DOWN'
fi
# DHCP leases
LEASES=\$(cat /var/lib/misc/dnsmasq.leases 2>/dev/null | grep '10.10.${nid}' | wc -l)
echo \"LEASES=\${LEASES}\"
# System
LOAD=\$(cat /proc/loadavg 2>/dev/null | awk '{print \$1}')
DISK=\$(df / 2>/dev/null | tail -1 | awk '{print \$5}')
TEMP=\$(vcgencmd measure_temp 2>/dev/null | grep -oP '[0-9.]+' || echo '?')
echo \"LOAD=\${LOAD}\"
echo \"DISK=\${DISK}\"
echo \"TEMP=\${TEMP}\"
# Failover service
if systemctl is-active roadnet-failover >/dev/null 2>&1; then
echo 'FAILOVER=UP'
else
echo 'FAILOVER=DOWN'
fi
" > "$TMPDIR/${name}.txt" 2>/dev/null
) &
done
wait
# Display results
for name in Alice Cecilia Octavia Aria Lucidia; do
ch="${CHANNELS[$name]}"
file="$TMPDIR/${name}.txt"
if [[ ! -s "$file" ]]; then
echo -e "${PINK}${RESET} ${RED}${RESET} ${name} ${DIM}OFFLINE — SSH failed${RESET}"
continue
fi
source "$file" 2>/dev/null
# AP status indicator
if [[ "$AP" == "UP" ]]; then
AP_ICON="${GREEN}${RESET} WiFi CH${ch}"
else
AP_ICON="${RED}${RESET} WiFi OFF"
fi
# WireGuard indicator
WG_ICON=""
[[ "$WG" == "UP" ]] && WG_ICON="${GREEN}WG●${RESET}" || WG_ICON="${RED}WG○${RESET}"
# Bluetooth indicator
BT_ICON=""
[[ "$name" == "Aria" ]] && { [[ "$BT" == "UP" ]] && BT_ICON=" ${BLUE}BT●${RESET}" || BT_ICON=" ${DIM}BT○${RESET}"; }
# Client count
TOTAL_CLIENTS=$((${CLIENTS:-0} + ${LEASES:-0}))
[[ $TOTAL_CLIENTS -gt ${CLIENTS:-0} ]] && TOTAL_CLIENTS=${CLIENTS:-0}
# Format line
printf "${PINK}${RESET} %s %-9s │ %b │ %d clients │ exit: %-5s │ %b%b │ %s°C %s\n" \
"" "$name" "$AP_ICON" "${CLIENTS:-0}" "${EXIT:-?}" "$WG_ICON" "$BT_ICON" "${TEMP:-?}" "${DISK:-?}"
done
echo -e "${PINK}╠══════════════════════════════════════════════════════════════╣${RESET}"
# Summary line
TOTAL_UP=0
TOTAL_CLIENTS=0
for name in Alice Cecilia Octavia Aria Lucidia; do
file="$TMPDIR/${name}.txt"
[[ -s "$file" ]] && source "$file" 2>/dev/null
[[ "$AP" == "UP" ]] && ((TOTAL_UP++))
TOTAL_CLIENTS=$((TOTAL_CLIENTS + ${CLIENTS:-0}))
done
echo -e "${PINK}${RESET} ${GREEN}${TOTAL_UP}/5 APs active${RESET}${AMBER}${TOTAL_CLIENTS} total clients${RESET}${BLUE}DNS: Pi-hole (Alice)${RESET}"
echo -e "${PINK}${RESET} ${VIOLET}SSID: RoadNet${RESET}${DIM}3 transports: WiFi + WireGuard + Bluetooth${RESET}"
echo -e "${PINK}╚══════════════════════════════════════════════════════════════╝${RESET}"
echo ""