Detecting Outages

A palm tree covered in snow Millions of my fellow Texans were in crisis the week after Valentine’s day 2021. The weather was colder than it had been since Santa Anna marched his army to San Antonio, and the whole state was experiencing blackouts. But I was lucky. I had an exact record of precisely when the power shut off and was restored throughout this whole ordeal. How did this help me? It didn’t. But it was nice to know that my power outage notification system was working as intended.

I have an ODROID-HC2 computer in my closet that handles a variety of tasks. It is primarily a media server running Jellyfin so I can have a netflix-style interface for my personal movie collection. It also acts as an always-on syncthing node to keep the files on my desktop and laptop synchronized even when one of them is turned off. I figured that those functions were entirely too useful, and that it desperately needed at least one pointless task to carry out if it was going to be worthy of my network. Cue power outage detection.

The concept is fairly straightforward. The Odroid will make a connection to my webserver. If that connection breaks, that means there is a power outage, and the server should notify me. When the connection is restored, that means power has returned, and the server should notify me. The remote server is necessary because the Odroid would encounter some amount of difficulty when trying to tell me directly that it has no power.

The whole system was realized with 2 bash scripts. The first runs on the Odroid:

1
2
3
4
5
6
7
#!/bin/bash

while [ 1 ]
do
    ssh $MYREMOTESERVER "echo $(date +%s) > /tmp/dateping"
    sleep 30
done

This is about as simple as it gets. The script writes the current date and time to a file on my remote server called /tmp/dateping every 30 seconds. Is there a better way than opening a new ssh connection every 30 seconds? Probably, but I don’t care.

The second script runs on the remote server:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
#!/bin/bash
poweron="true"
sleep 120
while [ 1 ]
do
    pingtime="$(cat /tmp/dateping)"
    sleep 2
    now="$(date +%s)"
    delta=$((now - pingtime))
    if [ $delta -gt 80 ]; then
        echo "poweron=$poweron"
        if [ $poweron = "true" ]; then
            poweron="false"
            echo "Power outage at $(date)."
            echo "Power outage at $(date)." | mail -aFrom:msg@cws.xyz 5558675309@tmomail.net
        fi
    else
        if [ $poweron = "false" ]; then
            poweron="true"
            echo "Power restored at $(date)."
            echo "Power restored at $(date)." | mail -aFrom:msg@cws.xyz 5558675309@tmomail.net
        fi
    fi
    sleep 60
done

This one is slightly more involved. Every minute, it checks if the current time is more than 80 seconds different than what is recorded in /tmp/dateping. If this is the case, the Odroid has missed sending at least 2 pings, meaning it has been disconnected for over a minute. From this we can conclude that the power is out and a message should be sent. At this point, we set the $poweron flag to "false". On the other hand, if the time difference is less than 80 seconds, we can conclude that the Odroid has power. In the case that the odroid has power and the $poweron flag is "false", we conclude that power has only just been restored so we send a message and reset $poweron.

Messages are sent using an SMS gateway, a system by which an email can be sent to a phone subscriber, who receives the message as a text. I use the GNU mail utility to send a message from a dummy address to [myphonenumber]@tmomail.net. Each cellular provider uses a different domain. If you’re in the US, you can find your provider in this table and try emailing a rude message to your phone number. Try it!

Mobile carrier SMS gateway domain MMS gateway domain
Alltel sms.alltelwireless.com mms.alltelwireless.com
AT&T txt.att.net mms.att.net
Boost Mobile sms.myboostmobile.com myboostmobile.com
Cricket Wireless mms.cricketwireless.net mms.cricketwireless.net
FirstNet txt.att.net mms.att.net
Google Fi msg.fi.google.com
MetroPCS mymetropcs.com mymetropcs.com
Republic Wireless text.republicwireless.com
Sprint messaging.sprintpcs.com pm.sprint.com
T-Mobile tmomail.net tmomail.net
U.S. Cellular email.uscc.net mms.uscc.net
Verizon Wireless vtext.com vzwpix.com
Virgin Mobile vmobl.com vmpix.com

Finally, I would be remiss not to include a table of my data:

Time Status Time since last change
02-15 16:02:00 out
02-15 18:53:35 restored 02:51:35
02-15 19:24:38 out 00:31:03
02-15 22:29:38 restored 03:05:00
02-15 22:33:48 out 00:04:10
02-16 00:22:21 restored 01:48:33
02-16 01:09:55 out 00:47:34
02-16 06:41:41 restored 05:31:46
02-16 07:44:45 out 01:03:04
02-16 10:11:32 restored 02:26:47
02-16 10:30:10 out 00:18:38
02-16 10:32:16 restored 00:02:06
02-16 11:27:05 out 00:54:49
02-16 13:20:47 restored 01:53:42
02-16 13:24:57 out 00:04:10
02-16 13:26:01 restored 00:01:04
02-16 14:38:24 out 01:12:23
02-17 03:53:08 restored 13:14:44
02-17 10:51:42 out 06:58:34
02-17 12:52:39 restored 02:00:57

The longest power outage lasted over 13 hours, from 2pm to almost 4 in the morning - the coldest part of the day. My house relies on electricity for heat.