UPS

WABAC Pic WABAC Pic I purchased a uninterruptible power supply, specifically the APC Back-UPS NS 1080, to smooth out the power dips that are far too frequent in my home. This product comes with the PowerChute software to provide safe system shutdown in the event of an extended power outage. Unfortunately, this software isn't supported on Linux, but there is an alternative to PowerChute.

apcupsd (the name stands for APC UPS Daemon) is a daemon that runs on Linux that allows the computer to interact with (almost all recent) American Power Conversion Corp (APC) uninterruptible power supplies (UPS). During a power failure, apcupsd informs users about the loss of utility power and that a shutdown may occur. If utility power is not restored, a system shutdown will follow when the battery is exhausted, a specified timeout expires, a specified battery charge percentage is reached, or a specified battery runtime (based on internal UPS calculations and determined by power consumption rates) expires. If the utility power is restored before one of the these shutdown conditions is met, apcupsd will inform users of this and the shutdown will generally be cancelled.

Installation

For my UPS, the apcupsd daemon will be communicating with the UPS via a USB connection. To make sure that your USB subsystem can see the UPS, plug in the UPS and connect the USB cable to your computer. Then just run lsusb from a shell prompt (see below, output included):

# the lsusb command can show you the hubs connected to your system
$ lsusb | grep American

Bus 003 Device 005: ID 051d:0002 American Power Conversion Uninterruptible Power Supply

Device File Name for the UPS

Under Linux, each and every hardware device, including USB ports, are treated as a file and call a device file. A device file allows a user to access hardware devices, but shields the users from the technical details about the hardware. A conventional serial port will typically have a device file such as /dev/ttyS0, /dev/ttyS1, etc. but a USB serial ports can appear as /dev/ttyUSB0, /dev/ttyUSB1, etc. or even appear in /dev/usb as in my Ubuntu Linux system.

When your device is plugged in, Linux assigns the device file name as it sees fit and isn’t always predicable (it doesn’t have to be this way). From the output of lsusb, you can deduce what device file your serial device is connected too. The string Bus 003 Device 005 and a search of the directory /dev/bus tells you that the device file is /dev/bus/usb/003/005.

Linux creates device nodes dynamically on the fly as they are needed. It is basically a hotplug system, freeing the user from making node assignments, but also means you have to search around to find where Linux put your device file. The apcupsd takes care of all this, so you don't need to create a persistent device name.

Never the less, if your curious about where things are located, running of the lsusb command above tells us UPS's VendorID:ProductID pair is 051d:0002. Using the udevadm info -a -n /dev/bus/usb/003/005 command, you conclude that the serial number of the device is 0000:00:14.0. See below: (command and output)

# get the serial number of the UPS device
udevadm info -a -n /dev/bus/usb/003/005 | grep ATTRS{serial}

    ATTRS{serial}=="0000:00:14.0"

Armed with this information and following guidance from this post, I could have update the UDEV rules. But Don't Do This, since from my experimenting, I believe it will cause problems with apcupsd. It appears that the daemon is designed to deal with all this.

Installing and Configuring the UPS Daemon

The apcupsd daemon is easy to install and is well documented at "apcupsd - Official Ubuntu Documentation". If you want to see the stat of the UPS through the browser, you can also install apcupsd-cgi package.

# install the apcupsd daemon and browser package
sudo apt-get install apcupsd apcupsd-cgi

Next you edit the apcupsd configuration file /etc/apcupsd/apcupsd.conf. Here are the modifications I made to this file:

# UPS name, max 8 characters
UPSNAME HOME_UPS

# Defines the type of cable connecting the UPS to your computer.
UPSCABLE usb

# the type of UPS you have
UPSTYPE usb

# with a usb type UPS apcupsd can autodetect the device,
# so you should comment out the DEVICE setting
#DEVICE /dev/ttyS0

# UPS should do a self test every two weeks
SELFTEST 336

Now you must edit the file /etc/default/apcupsd.

# Defaults for apcupsd initscript

# Apcupsd-devel internal configuration
APCACCESS=/sbin/apcaccess
ISCONFIGURED=yes

Starting Things Up

To start/stop the apcupsd daemon manually, just execute this command:

# start the apcupsd daemon
sudo /etc/init.d/apcupsd start

# to check if the demon is in fact running
ps aux | grep --invert-match grep | grep apcupsd

# stop the apcupsd daemon
sudo /etc/init.d/apcupsd stop

The UPS daemon can be manual started/stopped, but also, the command /etc/init.d/apcupsd is automatically invoked at system startup and shutdown and is governed by the chkconfig procedures.

To get a snapshot of the UPS's status, run the command apcaccess status.

See the output below:

# UPS status check
$ apcaccess status

APC      : 001,036,0901
DATE     : 2015-02-07 10:59:40 -0500
HOSTNAME : desktop
VERSION  : 3.14.10 (13 September 2011) debian
UPSNAME  : desktop
CABLE    : USB Cable
DRIVER   : USB UPS Driver
UPSMODE  : Stand Alone
STARTTIME: 2015-02-07 10:59:39 -0500
MODEL    : Back-UPS NS1080G
STATUS   : ONLINE
LINEV    : 121.0 Volts
LOADPCT  :  20.0 Percent Load Capacity
BCHARGE  : 100.0 Percent
TIMELEFT :  36.1 Minutes
MBATTCHG : 5 Percent
MINTIMEL : 3 Minutes
MAXTIME  : 0 Seconds
SENSE    : Medium
LOTRANS  : 088.0 Volts
HITRANS  : 142.0 Volts
ALARMDEL : 30 seconds
BATTV    : 27.0 Volts
LASTXFER : No transfers since turnon
NUMXFERS : 0
TONBATT  : 0 seconds
CUMONBATT: 0 seconds
XOFFBATT : N/A
SELFTEST : NO
STATFLAG : 0x07000008 Status Flag
SERIALNO : 3B1405X05714
BATTDATE : 2014-01-28
NOMINV   : 120 Volts
NOMBATTV :  24.0 Volts
NOMPOWER : 650 Watts
FIRMWARE : 914.L2   .D USB FW:
END APC  : 2015-02-07 10:59:43 -0500

This shows that the UPS daemon is configured to do the following thing:

Parameter Value Description
MBATTCHG 5% If the battery charge percentage (BCHARGE) drops below this value, apcupsd will shutdown your system. Value is set in the configuration file (BATTERYLEVEL).
MINTIMEL 3 Min apcupsd will shutdown your system if the remaining runtime equals or is below this point. Value is set in the configuration file (MINUTES).
MAXTIME 0 Sec apcupsd will shutdown your system if the time on batteries exceeds this value. A value of zero disables the feature. Value is set in the configuration file (TIMEOUT).

These parameters say something about how the UPS is perfroming (see apcupsd Status Logging section in the apcupsd User Manual):

Parameter Value Description
STARTTIME time stamp The time/date that apcupsd was started (ex. 2015-02-07 10:59:39 -0500).
STATUS ONLINE The current status of the UPS (ONLINE, ONBATT, etc.)
LINEV 121.0 V The current line voltage as returned by the UPS.
LOADPCT 20.0% The percentage of load capacity as estimated by the UPS.
BCHARGE 100.0% The percentage charge on the batteries.
TIMELEFT 36.1 The remaining runtime left, in minutes on batteries as estimated by the UPS.
LOTRANS 088.0 V The line voltage below which the UPS will switch to batteries.
HITRANS 142.0 V The line voltage above which the UPS will switch to batteries.
SELFTEST NO The results of the last self test, and may have the following values: OK - self test indicates good battery, BT - self test failed due to insufficient battery capacity, NG - self test failed due to overload, NO - No results (i.e. no self test performed in the last 5 minutes)

Notification and Events

When a major event is generated within apcupsd, control is passed to the script /etc/apcupsd/apccontrol. The event name, and a number of other important parameters are passed to the script. The major function of the apccontrol script is to perform a shutdown of the system (as well as the killpower operation). Another major task for this script is to notify you (via wall by default) when certain events such as powerfail occur.

Since /etc/apcupsd/apccontrol is a script, you can customize it to your own needs using any text editor. In addition, another feature is that you can write your own scripts that will be automatically called by apccontrol before any of its own code is executed. For more details, see the apcupsd User Manual.

By default, the /etc/apcupsd/apccontrol script uses wall to notify online uses of UPS related events. I wanted modify the script to use sendmail but many public mail servers appear to block the Simple Mail Transfer Protocol (SMTP) coming from unknow sources. See below for my systems mail log, /var/log/mail.log:

# test message for send mail
$ echo "Subject: sendmail test" | /usr/sbin/sendmail [email protected]

# now check the log to see what happend to this message
$ tail /var/log/mail.log
.
.
.
Jul 16 14:21:05 desktop postfix/pickup[6588]: 723364012A: uid=1000 from=<jeff>
Jul 16 14:21:05 desktop postfix/cleanup[8835]: 723364012A: message-id=<[email protected]>
Jul 16 14:21:05 desktop postfix/qmgr[2208]: 723364012A: from=<[email protected]@gmail.com>, size=307, nrcpt=1 (queue active)
Jul 16 14:21:05 desktop postfix/smtp[8810]: 723364012A: to=<[email protected]>, relay=relay.verizon.net[206.46.232.11]:25, delay=0.1, delays=0.01/0/0.09/0, dsn=4.0.0, status=deferred (host relay.verizon.net[206.46.232.11] refused to talk to me: 571 Email from 71.171.94.138 is currently blocked by Verizon Online's anti-spam system. The email sender or Email Service Provider may visit http://www.verizon.net/whitelist and request removal of the block. 160716)

As the last line says, the Verizon mail service is blocking my sendmail message via its anti-spam system.

Instead, I choose to take another approach. I have modified the apccontrol script to not only use wall but also my personal push notification utility apprise, which leverages the Pushover service. (WARNING - The /etc/apcupsd/apccontrol script will be overwritten every time you update your apcupsd, when doing make install):

The modifications to the /etc/apcupsd/apccontrol script required me to replace the scripts WALL environment variable as shown below:

# repleae this line
WALL=wall

# with this
WALL="eval tee /tmp/apccontrol.file | wall ; /home/jeff/bin/apprise -t \"UPS Event Notification\" -m \"\$(cat /tmp/apccontrol.file)\""

UPS Test Program

apctest is a program that runs low-level tests to check the operation of the UPS, checks that your apcupsd configuration is correctly setup, and assures you can establish communication with the UPS.

When run, apctest displays a menu of options. Also, apctest saves a transcript of the session to the file apctest.out in the directory from which the program was called.

IMPORTANT: Before running apctest Check that the UPSCABLE, UPSTYPE and DEVICE configuration directives in the /etc/apcupsd/apcupsd.conf configuration file have been set appropriately; and shutdown apcupsd via sudo /etc/init.d/apcupsd stop if it is running. You cannot run both apcupsd and apctest at the same time.

You must run apctest as root:

# stop the apcupsd daemon
sudo /etc/init.d/apcupsd stop

# start the test
$ sudo apctest


2016-07-16 16:34:56 apctest 3.14.12 (29 March 2014) debian
Checking configuration ...
sharenet.type = Network & ShareUPS Disabled
cable.type = USB Cable
mode.type = USB UPS Driver
Setting up the port ...
Doing prep_device() ...

You are using a USB cable type, so I'm entering USB test mode
Hello, this is the apcupsd Cable Test program.
This part of apctest is for testing USB UPSes.

Getting UPS capabilities...SUCCESS

Please select the function you want to perform.

1)  Test kill UPS power
2)  Perform self-test
3)  Read last self-test result
4)  View/Change battery date
5)  View manufacturing date
6)  View/Change alarm behavior
7)  View/Change sensitivity
8)  View/Change low transfer voltage
9)  View/Change high transfer voltage
10) Perform battery calibration
11) Test alarm
12) View/Change self-test interval
 Q) Quit

Select function number:
.
.
.

# start the apcupsd daemon
sudo /etc/init.d/apcupsd start

Sources

For more information and details, check out the following: