ADSL Modem Auto Power Cycle

I had an issue with my business ADSL connection dropping out occasionally. The only way to restore the connection was to power cycle the ADSL modem. Cue Roy from the IT Crowd saying; “Did you try turning it off and back on again?” !

The dropouts would invariably occur on the weekend or overnight. This meant I couldn’t send or receive email when the connection was down, as it hosted my email server. What a pain in the rear end is was.

After too many after hours trips to reset the connection, I came up with a workaround solution that’s still in place now. Although the ISP seems to have finally sorted the underlying cause for the dropouts, I felt it was a good backup.

What I came up with was a simple script that runs (via a cron job) every 15 minutes on the Linux server. Each time the script runs, it pings the Google servers four times. If none of those pings is responded to, the script assumes that the ADSL connection has dropped out. At that point, it sends a serial string to a custom USB (powered) relay box. It also sends me an email so I know that a problem occurred. This proved helpful when talking to my ISP.

The relay box employs an FT232RL USB-UART chip and enumerates as a serial port. A small PIC microcontroller listens for specific commands – one of which will operate the relay, then release it about 10 seconds later.

The relay’s normally closed contact is wired in series with the DC positive wire of the ADSL modem’s power supply. This ensures that the modem will stay powered if the relay dies (unlikely) or the relay box is unplugged from the server.

I originally intended to use separate relay on and off commands, but changed to the self-timed relay off method in case the unit ever got sent an on command (cut power to modem) without a matching off command (to restore power).

A friend (Hi Mark!) helped me refine the script that runs on the Linux box every 15 mins:

#!/bin/bash
# Lock a file descriptor to prevent multiple copies running.
( flock -n -e 42 || { echo "Cannot get lock on $0: another process running?"; exit 1; }
# Configure the comms parameters for the USB relay box
stty -F /dev/ttyUSB1 9600
# Ping the Google servers 4 times and see how many replies we get
count="$(ping -c 4 8.8.8.8 | awk '/received/ { print $4 }')"
if [ "$count" == "0" ]; then
  # Send an email with date stamp
  echo "Ping failed at $(date --rfc-3339=sec) so ADSL modem power was cycled" |
    mail -s "Modem Power Cycled" user@email-address-to-notify.com
  # Send a serial string to the relay box to do the actual power cycle
  echo -e -n '\x02\x30\x30\x30\x31\x35\x30\x30\x32\x30\x31\x3b\x32\x03' > /dev/ttyUSB1
fi
# Create file descriptor using shell redirection into a subshell.
) 42< $0

Relay box details to be added.