Automate Restarting your Router with a Smart Plug

A while back, I had an issue with a faulty router that would drop my Internet connection every now and again. As I was leaving for the summer holidays, I needed to find a way to keep the Internet going at my house, as I am running a few services on my Raspberry Pi that I like to connect to when I’m abroad.

My first instinct was to find a way to do this from the router directly, i.e. some hack that would allow me to access it and reboot it remotely from my LAN with a script. I did find some repos where it was effectively hacked but this quickly proved pointless as ISPs tend to update the routers they provide against any vulnerabilities. So the hack I found did no longer apply. I also needed something future-proof, in case of disconnects with a newer router when I got back from my vacation.

I was about to give up when it hit me like a brick: Why not connect the router to a smart plug! Maybe that would be easier to “hack”. I already had a couple of TP-Link HS100 smart plugs for my office lights so I started looking for ways to control those via command line and, sure enough, stumbled upon this GitHub project. The idea is simple:

Download the script locally (i.e. on my Raspberry Pi), identify the IP of any of my smart plugs and then run "hs100.sh <IP> <Port> <on/off>“. For example:

  • hs100.sh 10.10.5.253 9999 on – To turn my smart plug on
  • hs100.sh 10.10.5.253 9999 off – To turn my smart plug off

Note that the port used on these devices is usually 9999, and the IP of my smart plug is 10.10.5.253. Yours will probably differ.

It worked like a charm! Light On, Light Off. Light On, Light Off.

So now, on to automation. The idea is simple: I want a script that will run every 15 minutes on my RPi which will “ping the Internet” and, if the pings are unsuccessful (aka no connection to the outside world, aka no Internet), switch off my router (in essence, my smart plug with the router plugged into it) for 20 seconds, and then switch it back on.

On my RPi, I created a folder named TPMonitor and added the hs100.sh script, (which I renamed to plugswitcher.sh) and a new ping_check.sh script:

/home/dodz/TPMonitor
  |── ping_check.sh
  |── plugswitcher.sh

After some trial and error, I ended up with the following:

#!/bin/bash

# Vars
HOSTS="1.1.1.1"           # IP/Hostname(s) to ping, separated by white space
COUNT="15"                # Nb of ping requests
SPLUG_IP="10.10.5.253"    # SmartPlug IP
SPLUG_PORT="9999"         # SmartPlug Port

# CD to /home/dodz/TPMonitor
cd /home/dodz/TPMonitor

# Ping check
for myHost in $HOSTS
do
  count=$(ping -c $COUNT $myHost | grep 'received' | awk -F',' '{ print $2 }' | awk '{ print $1 }')
  if [ $count -eq 0 ]; then
    # If count=0, this means 100% failed - In this case, run the following:
    ./plugswitcher.sh $SPLUG_IP $SPLUG_PORT off;sleep 20;./plugswitcher.sh $SPLUG_IP $SPLUG_PORT on
  fi
done

I simulated losing my connection and, after 15 failed ping attempts, the plugswitcher.sh script was called to turn off my smart plug, wait (sleep) 20 seconds and then turn it back on. Magic!

To run this check every 15 minutes, I added the following to the root’s crontab file:

# Check ISP connection
*/15 * * * * /home/dodz/TPMonitor/ping_check.sh

Sure enough, my Internet connection dropped shortly after and I didn’t need to lift a finger for the router to automagically restart!