Skip to content

Instantly share code, notes, and snippets.

@mafredri
Last active May 22, 2017 01:57
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 1 You must be signed in to fork a gist
  • Save mafredri/f731ce154d8a3b30c9b2 to your computer and use it in GitHub Desktop.
Save mafredri/f731ce154d8a3b30c9b2 to your computer and use it in GitHub Desktop.
Upgrade WiFi AP (e.g on OpenWRT) when there is a stronger BSSID in vicinity (based on signal strength). Useful when you are a member of a SSID which has multiple APs under the same SSID but you don't want to commit to only one BSSID.
#!/bin/sh
COUNT=0
LIMIT=5
INTERFACE=wlan1
NAME=$(basename $0)
CLEAN_NAME=${NAME%.sh}
PID="/var/run/$CLEAN_NAME.pid"
LOGGER="logger -t $CLEAN_NAME -s"
check_status() {
if [ ! -f "$PID" ]; then
echo 0 > $PID
fi
pid=$(cat "$PID")
ps|egrep "^[ ]*$pid .*$NAME" 2>&1 >/dev/null
if [ $? -eq 0 ]; then
$LOGGER "Already running, exiting..."
exit
fi
echo $$ > "$PID"
}
check_status
while true; do
ping -4 -w1 -c1 8.8.8.8 2>&1 >/dev/null
if [ ! $? -eq 0 ]; then
if [ $COUNT -lt $LIMIT ]; then
if [ $COUNT -eq 0 ]; then
# Run a scan on the wifi interface, incase that would recover the connection
iw $INTERFACE scan 2>&1 >/dev/null
fi
COUNT=$(( $COUNT + 1 ))
$LOGGER "Connection test failed! ($COUNT/$LIMIT)"
continue
fi
$LOGGER "Limit reached, upgrading AP..."
/root/scripts/upgrade_ap.sh force
fi
COUNT=0
sleep 2
done
0 * * * * /root/scripts/check_connection.sh
*/2 * * * * /root/scripts/upgrade_ap.sh
#!/bin/sh
# SSID you are a member of
SSID=
# Which interface to do a iw scan on
WIFI_IF=wlan1
# Limit for how many times to search for AP
LIMIT=2
# Delay in seconds between iw scans
DELAY=2
# Wait for N seconds to give connection time to establish
WAIT=10
# GENERAL VARIABLES
# if script is called with "force", switch to first best AP available
NAME=$(basename $0)
CLEAN_NAME=${NAME%.sh}
PID="/var/run/$CLEAN_NAME.pid"
FORCE=$1
LOGGER="logger -t $CLEAN_NAME -s"
# Target is used to find correct line in /etc/config/wireless
# e.g:
# option bssid '00:00:00:00:00:00' #target
TARGET=" #target"
PREV=$(sed -nre "s/.*(')([[:alnum:]:]+)('$TARGET)/\2/p" /etc/config/wireless)
NEW=$PREV
COUNT=0
check_status() {
if [ ! -f "$PID" ]; then
echo 0 > $PID
fi
pid=$(cat "$PID")
ps|egrep "^[ ]*$pid .*$NAME" 2>&1 >/dev/null
if [ $? -eq 0 ]; then
$LOGGER "Already running, exiting..."
exit
fi
echo $$ > "$PID"
}
reload_wifi() {
wifi
sleep $WAIT
}
check_status
while true; do
LINE=$(iw $WIFI_IF scan \
| grep -i "SSID: $SSID" -B 8 \
| sed -e "s/(on $WIFI_IF)//" \
| egrep "(BSS|signal)" \
| awk '{printf $2 "|"}' \
| sed -re 's/([^|]+)\|([^|]+)\|?/\2 \1\n/g' \
| sort \
| head -n 1)
BEST=${LINE#* }
SIGNAL=${LINE% *}
if [ "$BEST" == "" ]; then
echo "Nothing found..."
continue
fi
if [ "$BEST" == "$PREV" ]; then
if [ "$PREV" != "$NEW" ]; then
$LOGGER "Found previous station: $PREV ($SIGNAL), canceling..."
fi
NEW=$BEST
break
fi
NEW=$BEST
$LOGGER "Found better station: $BEST ($SIGNAL)"
if [ "$FORCE" == "force" ]; then
$LOGGER "Force mode activated! No time to loop!"
break
fi
COUNT=$(( $COUNT + 1 ))
if [ $COUNT -gt $LIMIT ]; then
break
fi
sleep $DELAY
done
if [ "$PREV" != "$NEW" ]; then
$LOGGER "Found better AP: $NEW, was: $PREV"
sed -i -re "s/(')([[:alnum:]:]+)('$TARGET)/\1$NEW\3/" /etc/config/wireless
reload_wifi
elif [ "$FORCE" == "force" ]; then
$LOGGER "AP didn't change but force mode was activated! Reloading wifi..."
reload_wifi
fi
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment