Skip to content

Instantly share code, notes, and snippets.

@5p4k
Created March 25, 2020 15:54
Show Gist options
  • Save 5p4k/4c31900d92d3b03089ac2aab008af416 to your computer and use it in GitHub Desktop.
Save 5p4k/4c31900d92d3b03089ac2aab008af416 to your computer and use it in GitHub Desktop.
Blink Raspberry Pi LEDs depending on network status
[Unit]
Description=Network status as LED
StartLimitIntervalSec=0
[Service]
Type=simple
Restart=always
RestartSec=1
User=pi
ExecStart=/usr/local/bin/rpi-netstatus.sh
[Install]
WantedBy=multi-user.target
#!/bin/bash
GPIO_WORKING=26
GPIO_ERROR=19
GPIO_WARNING=13
GPIO_SUCCESS=6
GPIO_CONNECTION=16
TEST_IP_HOST=8.8.8.8
TEST_DNS_HOST=google.com
TEST_HTTP_URL="https://www.google.com"
TEST_WLAN_IF=wlan0
TEST_INTERVAL=10s
function usage() {
echo "$0 [options]"
echo ""
echo " --ip TEST_IP_HOST [default $TEST_IP_HOST]"
echo " IP to ping to test connectivity."
echo ""
echo " --dns TEST_DNS_HOST [default $TEST_DNS_HOST]"
echo " Domain name to ping to test connectivity and DNS lookup."
echo ""
echo " --url TEST_HTTP_URL [default $TEST_HTTP_URL]"
echo " URL to test for HTTP(S) connectivity."
echo ""
echo " --interface TEST_WLAN_IF [default $TEST_WLAN_IF]"
echo " Interface to check whether is up and has a valid IPv4."
echo ""
echo ""
echo " --interval TEST_INTERVAL [default $TEST_INTERVAL]"
echo " Interval in seconds between consecutive tests."
echo ""
echo " --success GPIO_SUCCESS [default $GPIO_SUCCESS]"
echo " GPIO pin number for the LED identifying success for ping and http."
echo ""
echo " --warning GPIO_WARNING [default $GPIO_WARNING]"
echo " GPIO pin number for the LED identifying partial success for ping and http."
echo ""
echo " --error GPIO_ERROR [default $GPIO_ERROR]"
echo " GPIO pin number for the LED identifying failure for ping and http."
echo ""
echo " --connection GPIO_CONNECTION [default $GPIO_CONNECTION]"
echo " GPIO pin number for the LED marking whether the network interface is up and running."
echo ""
echo " --working GPIO_WORKING [default $GPIO_WORKING]"
echo " GPIO pin number for the LED marking that tests are being performed."
echo ""
echo " -h, --help"
echo " Shows this help."
}
while [[ $# -gt 0 ]]; do
case "$1" in
--ip) shift; TEST_IP_HOST="$1";;
--dns) shift; TEST_DNS_HOST="$1";;
--url) shift; TEST_HTTP_URL="$1";;
--interface) shift; TEST_WLAN_IF="$1";;
--interval) shift; TEST_INTERVAL="$1";;
--success) shift; GPIO_SUCCESS="$1";;
--warning) shift; GPIO_WARNING="$1";;
--error) shift; GPIO_ERROR="$1";;
--connection) shift; GPIO_CONNECTION="$1";;
--working) shift; GPIO_WORKING="$1";;
-h|--help)
usage
exit 0
;;
*)
echo "Unrecognized option: $1"
usage
exit 1
;;
esac
shift
done
ALL_PINS=("$GPIO_WORKING" "$GPIO_ERROR" "$GPIO_WARNING" "$GPIO_SUCCESS" "$GPIO_CONNECTION")
function _boolecho() {
case $1 in
1) echo -n "OK";;
0) echo -n "FAIL";;
*) echo -n "N/A";;
esac
}
function _set_pins() {
VALUE="$1"
shift
for PIN in "${@}"; do
DEST="/sys/class/gpio/gpio${PIN}/value"
if [[ -f "$DEST" ]]; then
echo "$VALUE" > "$DEST"
fi
done
}
function seth() {
_set_pins 1 "$@"
}
function setl() {
_set_pins 0 "$@"
}
function blink() {
PIN="$1"
TIMES="$2"
PERIOD="$3"
if [[ -z "$PERIOD" ]]; then
PERIOD="0.3s"
fi
while [[ $TIMES -ne 0 ]]; do
seth "$PIN"
sleep "$PERIOD"
setl "$PIN"
if [[ $TIMES -gt 0 ]]; then
TIMES=$(( TIMES - 1 ))
fi
done
}
function setup_pins() {
for PIN in "${ALL_PINS[@]}"; do
echo "Exporting pin $PIN..."
echo "$PIN" > /sys/class/gpio/export
sleep 1s
DEST="/sys/class/gpio/gpio${PIN}/direction"
if [[ -f "$DEST" ]]; then
echo out > "/sys/class/gpio/gpio${PIN}/direction"
fi
setl "$PIN"
done
}
function teardown_pins() {
for PIN in "${ALL_PINS[@]}"; do
echo "Unexporting pin $PIN..."
setl "$PIN"
echo "$PIN" > /sys/class/gpio/unexport
done
}
function greet() {
for PIN in "${ALL_PINS[@]}"; do
blink "$PIN" 1
done
}
function goodbye() {
for PIN in "${ALL_PINS[@]}"; do
seth "$PIN"
done
sleep 0.5s
for PIN in "${ALL_PINS[@]}"; do
setl "$PIN"
done
}
function do_ping() {
IP_OK=2
DNS_OK=2
HTTP_OK=2
if [[ $# -eq 0 ]] || [[ $1 -eq 0 ]]; then
seth "$GPIO_WORKING"
if ping -c 1 -W 1 "$TEST_IP_HOST" > /dev/null 2>&1; then
IP_OK=1
if ping -c 1 -W 1 "$TEST_DNS_HOST" > /dev/null 2>&1; then
DNS_OK=1
case "$(curl -s --max-time 2 -I "$TEST_HTTP_URL" | sed 's/^[^ ]* *\([0-9]\).*/\1/; 1q')" in
[23]) HTTP_OK=1;;
* ) HTTP_OK=0;;
esac
else
DNS_OK=0
fi
else
IP_OK=0
fi
setl "$GPIO_WORKING"
fi
echo "Ping on IP: $(_boolecho $IP_OK); Ping on DNS: $(_boolecho $DNS_OK); Curl on DNS: $(_boolecho $HTTP_OK)"
if [[ $IP_OK -eq 1 ]] && [[ $DNS_OK -eq 1 ]] && [[ $HTTP_OK -eq 1 ]]; then
seth "$GPIO_SUCCESS"
setl "$GPIO_WARNING"
setl "$GPIO_ERROR"
elif [[ $IP_OK -eq 1 ]] || [[ $DNS_OK -eq 1 ]] || [[ $HTTP_OK -eq 1 ]]; then
setl "$GPIO_SUCCESS"
seth "$GPIO_WARNING"
setl "$GPIO_ERROR"
else
setl "$GPIO_SUCCESS"
setl "$GPIO_WARNING"
seth "$GPIO_ERROR"
fi
}
BLINK_JOB=""
function _blinkjob_kill() {
if [[ -n "$BLINK_JOB" ]]; then
kill "$BLINK_JOB"
BLINK_JOB=""
fi
}
function _blinkjob_start() {
if [[ -z "$BLINK_JOB" ]]; then
blink "$1" -1 &
BLINK_JOB=$!
fi
}
function do_wifi() {
IF_STATUS="$(ip addr show "$TEST_WLAN_IF" 2> /dev/null)"
UP=2
HAS_IP=2
if echo "$IF_STATUS" | grep -F "state UP" > /dev/null 2>&1; then
UP=1
if echo "$IF_STATUS" | grep '\binet \([0-9]\+\.\)\{3\}[0-9]\+/[0-9]\+\b' > /dev/null 2>&1; then
HAS_IP=1
else
HAS_IP=0
fi
else
UP=0
fi
echo "IF is up: $(_boolecho $UP); IF has IP: $(_boolecho $HAS_IP)"
if [[ $UP -eq 1 ]] && [[ $HAS_IP -eq 1 ]]; then
_blinkjob_kill
seth "$GPIO_CONNECTION"
return 0
elif [[ $UP -eq 1 ]] || [[ $HAS_IP -eq 1 ]]; then
_blinkjob_start "$GPIO_CONNECTION"
return 2
else
_blinkjob_kill
setl "$GPIO_CONNECTION"
return 1
fi
}
function main() {
while true; do
do_wifi
do_ping $?
sleep "$TEST_INTERVAL"
done
}
function graceful_exit() {
echo ""
echo "WARN Got SIGINT"
kill "$MAIN_JOB"
_blinkjob_kill
goodbye
teardown_pins
exit
}
trap graceful_exit INT # When running at command line
trap graceful_exit TERM # When running as a service
setup_pins
greet
main &
MAIN_JOB=$!
sleep infinity
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment