Many people use a Raspberry Pi as a server at home. Even though most uses are recreational and non-critical, power outages can occasionally lead to loss of data and corruption of the SD card. To avoid that, cautious users often connect their Pis to a backup uninterruptible power source (UPS). There are many dedicated UPS solutions for the Raspberry Pi. Some are sold as ready made products, others are DIY projects. If there is other IT equipment connected to a UPS, the Rasperry Pi can simply be plugged into one of those outlets instead of having its own separate UPS.
UPS systems have limited backup, and depending on the load and battery capacity, they can last anywhere from a few minutes to several hours. Many UPSs have a PC interface that alerts the system that a power outage is in effect and of the state of the batteries so that the system can gracefully shut itself down before the UPS dies. Dedicated Raspberry Pi UPSs also often come with circuitry that can send a message to the Pi via a GPIO pin. There are also cases where there is no such facility, for example, when sharing a UPS meant for other devices. People have come up with many DIY circuits that detect when there is no power in a non-UPS backed up outlet, but these involve spending money on components and building circuits.
Here, we will try to come up with a software only solution to detect the power outage.
During a power outage any WiFi routers not connected to a UPS will go down. Keeping an eye on how many traditionally stable WiFi networks are are down at the same time can be used to determine if there is a power outage in the area. This assumes the Raspberry Pi has WiFi capability (like an RPi3 or a WiFi USB dongle). It does not matter whether the Pi uses WiFi or Ethernet for Internet connectivity, WiFi is merely used to scan for available SSIDs.
Here is a simple script that counts the number of active SSIDs using the
iwlist command, and if the number is less than a set threshold, it is flagged as an outage.
#!/bin/bash # THIS SCRIPT MUST BE RUN WITH SUDO MIN_NUM_SSID=5 NUM_SSID=$(iwlist wlan0 scan | grep -c ESSID) echo $NUM_SSID if [ $NUM_SSID -gt $MIN_NUM_SSID ]; then echo "Power is good." else echo "Power outage suspected." fi
In this example, the Raspberry Pi sees about 10 SSIDs on average with good strength at any given time. During a power cut, I expect at least half of them to be out of service as almost no one around me plugs their WiFi routers to a UPS but for a few mobile hotspots that spring up, so a threshold of 5 seems reasonable.
This script can be run as a root cron job, executing at say five minute intervals. When the script detects an outage, it can do several things, I am listing only two here:
- Shut down the Raspberry Pi
shutdown -h now
Although this is the safest method, this is not recommended as the Raspberry Pi will not turn itself on unless it is actually power cycled – manually or by the UPS draining out. You could be stuck with a shut off Raspberry Pi.
- Shut down all important services and sync the filesystem
service vsftpd stop
service nginx stop
service mysql stop
service php5-fpm stop
To get a list of active services, run
sudo service --status-all. The
synccommand flushes all buffers to the SD card. This is not a fool proof measure against data corruption, but it just might work. When all the networks come back up, you can restart all the services or simply reboot the Pi with the
Better detection of the outage?
The script above only counts the number of SSIDs at the instant the cron job executes it. For a more reliable count, the script should average the number of SSIDs visible over a few minutes to prevent false triggering.
The script is also flawed because it assumes the number of active SSIDs in the area won’t change over time. New networks could come up and old ones could be taken down permanently. The script can keep track of online SSIDs over several days and use the moving average as the total. The threshold used to detect a power outage could be a fraction of this value.
There are many many ways to implement this more gracefully and I will leave it to the curious minds out there to do it in their own way.