Does your cable or DSL modem ever lose it’s internet connection? Mine does from time to time, and it’s kind of annoying. It seems to happen overnight, while everyone’s asleep. The wifi network is usually still fine, so our devices stay connected to wifi and then timeout when checking your email or social networks.
It’s even more annoying for me because I keep my modem out of the way in the basement, near the rest of my networking gear. So whenever the internet drops out, I need to trek on down to the basement and reset the modem. I usually just pull the power connector, wait a few seconds and plug it back in and let it reboot. Problem solved.
Like I said, a minor annoyance and inconvenience, but still, why do we need to suffer with annoying tech? Technology is supposed to make our lives better, right? So with this in mind, I decided to create a watchdog to reset my cable modem (or any other device) whenever the internet connection drops out.
What You’ll Need
- Raspberry Pi running a linux OS (like Raspbian). This has more than enough computing power, and consumes little energy, which is nice. This could also serve as a home automation hub later on if you so desire. If you have a different linux system running 24/7 you can use that as well.
- TP-Link HS100 Smart Plug. This is a relatively inexpensive wifi-enabled smart plug that switches AC power to connected devices. Others will work as well, but this instruction is specific to the HS100.
- An annoying modem (or other piece of tech) that needs to be reset occasionally.
This instruction assumes the reader has a basic knowledge of linux, including command line interface and some basic shell scripting. The scripts should work as-is, but may require an edit or two to customize for your specific installation or needs. If this is your first time using the linux command line, you may need to read additional resources. Google is your friend!
How it Works
The concept is simple, really:
- The computer (Raspberry Pi or other linux system) attempts to connect to an external host.
- If the host responds, the internet connection is still functioning, so do nothing and quit.
- If the host fails to respond, try another host.
- If the second host responds, the internet connection is still functioning, so do nothing and quit.
- If the second host fails to respond, the internet connection must be down, so reset the modem.
- Repeat periodically to minimize downtime
Note: The selected hosts should be major players on the internet, with high up-time, such as Google, Facebook, Amazon, etc. We want to ensure at least one of the hosts will always be available.
Putting it All Together
Controlling the HS100
The first step is to get the TP-Link HS100 Smart Plug working with the RPi/computer. Luckily, someone else has done all the heavy lifting for this and posted shell scripts on Github.com for us to use: https://github.com/branning/hs100.
- Plug in and setup your HS100 device as per the manufacturer’s instructions. It’s highly recommended that the HS100 have a dedicated IP address reservation in your router setup.
- Copy the following two files from the github.com link above to a folder on your linux system (e.g. /home/pi/bin)
- hs100.sh
- myip.sh
- Next, create a new file called netcheck.sh
nano netcheck.sh
- Paste in the following code, and edit the PATH statement (line 14) to include the absolute path to your files, if different from /home/pi/bin.
# Internet connection checker # (c) 2017 Rob Jamieson # # This script checks for internet connectivity and resets a # TP-Link HS100 wifi outlet switch if no connection is established. # # Add URLs to check in host1 or host2. If host1 fails, host2 # is checked. If host2 also fails, the switch is reset. # # Credit to branning for the HS100 script: https://github.com/branning/hs100 # #!/bin/bash PATH=/home/pi/bin:/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin host1=http://google.com host2=http://facebook.com resettime=10 echo -n $(date) "Checking for internet connectivity..." wget -q --tries=10 --timeout=20 --spider $host1 if [[ $? -eq 0 ]]; then echo $host1 " Online" exit else (>&2 echo $(date) "error " $host1 " offline") echo $host1 " Offline" fi echo -n $(date) "Checking secondary host..." wget -q --tries=10 --timeout=20 --spider $host2 if [[ $? -eq 0 ]]; then echo $host2 " Online" exit else (>&2 echo $(date) "error " $host2 " offline") echo $host2 " Offline" fi #Turn off switch echo $(date) "Unable to connect to internet." echo -n $(date) "Resetting modem... " (>&2 echo $(date) "resetting modem...") hs100.sh off #Delay echo "Waiting " $resettime " seconds..." sleep $resettime #Turn on switch echo -n $(date) "Powering on modem..." hs100.sh on if [[ $? -eq 0 ]]; then echo "Success!" else (>&2 echo $(date) "modem reset failed") echo "Failed" fi
- Next, we need to make the files executable. From the command prompt, enter:
chmod +x hs100.sh myip.sh netcheck.sh
Tip: If these files are the only ones in the folder, you can use * instead of listing the file names.
- Run the HS100.sh script by itself first, to identify the connected HS100 devices on the LAN. Running it using sudo will automatically update the system’s hosts file to include IP addresses of the devices. If no devices are found, or if it asks for an IP address, you can include it in the command using the -i option.
sudo ./hs100.sh discover
- Once the HS100 smart plug has been detected by the script, you can test it by turning it on and off using the following commands:
./hs100.sh on ./hs100.sh off
- Next, try running the netcheck.sh script. If everything is working, you should see the following:
./netcheck.sh Sat Jun 17 16:50:48 EDT 2017 Checking for internet connectivity...http://google.com Online
- Now test the script with bad host URLs to simulate communication failure. Edit the netcheck.sh file to add ‘z’ to the URLs on lines 16, 17. This will trick the script to think there is no network connectivity, and should switch the HS100 device off and then on again.
./netcheck.sh Sat Jun 17 17:00:36 EDT 2017 Checking for internet connectivity...http://google.comz Offline Sat Jun 17 17:00:36 EDT 2017 Checking secondary host...http://facebook.comz Offline Sat Jun 17 17:00:36 EDT 2017 Unable to connect to internet. Sat Jun 17 17:00:36 EDT 2017 Resetting router... Waiting 10 seconds... Sat Jun 17 17:00:46 EDT 2017 Powering on router...Success!
Note: You should see the HS100 device turn off, wait 10 seconds, and then turn back on again.
- Now that everything works, fix the bad URLs on lines 16, 17 of netcheck.sh (remove ‘z’ from the end of the URLs) to ensure the script will work properly.
Adding the Automatic Timer
Now that the scripts are working, they need to be called periodically to test the connection and perform a reset of the modem if necessary. Linux uses cron to schedule tasks, so that’s what we’ll be setting up.
- Edit the crontab to execute the netchecker.sh script periodically. I’ll set it to go every 15 minutes, but other time periods could be used. Read up on cron or crontab for more info on this.
crontab -e
Note:If this is the first time using crontab, it will prompt for editor selection. Stick with option 2, nano, as this is easiest.
- Edit the crontab to include the following line:
0,15,30,45 * * * * /bin/bash /home/pi/bin/netcheck.sh 2>> /home/pi/netcheck.log
This tells cron to execute the netcheck.sh script at 0, 15, 30, 45 minutes past the hour (i.e. every 15 minutes) and save any errors to a log file at /home/pi/netcheck.log.
Tip: Instead of 0,15,30,45 try using * to execute the script every minute while you’re getting this up and running.
Caution: Cycling power to electronic devices is usually not harmful if done occasionally, however frequent and repeated power cycling should be avoided. Ensure the cron period is not too frequent, as loss of network connectivity due to external issues (i.e. with your ISP) could cause your modem to power cycle until the issue is resolved.
- Save and exit the crontab file. Cron should automatically update with the new settings and the script should be called as requested.
Connect the Modem
Now that the script works and is scheduled to run periodically, all that’s left is to connect the modem’s power adapter to the HS100. The system is now live, and any internet disconnect will be detected and the modem power cycled, hopefully resolving the issue.
Note: Keep in mind that some modems take longer than one minute to establish a working internet connection. If you have set cron to run the script every minute, this could cause this script to loop/reset the modem infinitely. Make sure you have a sufficiently long duration in your crontab file when you “go live”.
Caution: Avoid connecting your router’s power adapter to the HS100. This could cause a loss of LAN connectivity after the HS100 is turned off, resulting in no way of turning the HS100 back on again. This would require manual intervention to turn on the HS100 again.
Troubleshooting
If you’re having difficulties getting the above to work, try the following:
- Ensure the IP address to the HS100 is correct, and that the device receives the same IP address whenever it’s connected or the router resets. Follow your router’s instructions on setting a dedicated/reserved IP address for the HS100 device.
- Check to see if the correct HS100 IP address is being added to the system’s hosts file.
- Ensure your HS100 device is connected to the same LAN or wifi network, and that you know it’s IP address. Your router may be able to give you this info if you log into it and sniff around. There are also many free apps to scan the network for devices and report their IP addresses.
- Ensure the PATH variable in netcheck.sh contains the path to your scripts. Without this, it will fail.
- Ensure all dependancies are installed on your system. The HS100 script will return error messages indicating missing dependancies. My Raspberry Pi running Raspbian did not have nmap software installed. To install this, I issued the following command:
sudo apt-get install nmap
- Read the system log for hints to other errors.