Linux + APC Smart UPS 750 notes (apcupsd and other stuff)
Introduction
These are my somewhat messy jots while setting up an APC Smart UPS 750 (SMT750I) with a Linux Mint 19 machine, for a clean shutdown on power failure. Failures and mistakes shown as well.
Even though I had issues with receiving a broken UPS at first, and waiting two months for a replacement (ridiculous support by Israeli Serv Pro support company), the bottom line is that it seems like a good choice: The UPS and its apcupsd driver handles the events in a sensible way, in particular when power returns after the shutdown process has begun (this is where UPSes tend to mess up).
As for battery replacement, two standard 12V / 7 AH batteries can be used, as shown in this video. Otherwise, good luck finding vendor-specific parts ten years from now in Israel. For my lengthy notes on battery replacement, see this separate post.
Turning off the UPS manually (and losing power to computer): Press and hold the power button until the second beep. The first beep confirms pressing the button, the second says releasing the button will shut down the UPS.
Turning off beeping when the UPS is on battery: Press the ESC button for a second or so.
Basic installation
Driver for UPS:
# apt-get install apcupsd
Settings
Edit /etc/apcupsd/apcupsd.conf, and remove the line saying
DEVICE /dev/ttyS0
Change TIMEOUT, so the system is shut down after 10 minutes of not having power. Don’t empty the batteries — I may want to fetch a file from the computer with the network power down. This timeout applies also if the computer was started in an on-battery state.
TIMEOUT 600
Don’t annoy anyone to log off. There is nobody to annoy except myself:
ANNOY 0
No need for a net info server. A security hole at best in my case.
NETSERVER off
Wrong. Keep the server, or apcaccess won’t work.
Stop “wall” messages
This is really unnecessary on a single-user computer (is it ever a good idea?). If power goes out, it’s dark and the UPS beeps. No need to get all shell consoles cluttered. The events are logged in /var/log/apcupsd.events as well as the syslog, so there’s no need to store them anywhere.
Edit /etc/apcupsd/apccontrol, changing
WALL=wall
to
WALL=cat
The bad news is that an apt-get upgrade on apcupsd is likely to revert this change.
Hello, world
Possibly as non-root:
$ apcaccess status APC : 001,027,0656 DATE : 2018-10-28 21:36:29 +0200 HOSTNAME : preruhe VERSION : 3.14.14 (31 May 2016) debian UPSNAME : preruhe CABLE : USB Cable DRIVER : USB UPS Driver UPSMODE : Stand Alone STARTTIME: 2018-10-28 21:36:27 +0200 MODEL : Smart-UPS 750 STATUS : ONLINE BCHARGE : 100.0 Percent TIMELEFT : 48.0 Minutes MBATTCHG : 5 Percent MINTIMEL : 3 Minutes MAXTIME : 0 Seconds ALARMDEL : 30 Seconds BATTV : 27.0 Volts NUMXFERS : 0 TONBATT : 0 Seconds CUMONBATT: 0 Seconds XOFFBATT : N/A STATFLAG : 0x05000008 MANDATE : 2018-05-22 SERIALNO : AS182158746 NOMBATTV : 24.0 Volts FIRMWARE : UPS 09.3 / ID=18 END APC : 2018-10-28 21:36:47 +0200
Shutting down UPS on computer shutdown
By default, the computer puts the UPS in “hibernation” mode at a late stage of its own shutdown. This turns the power down (saving battery), and resumes power when the network power returns. The trick is that apcupsd creates a /etc/apcupsd/powerfail file before shutting down the computer due to a power failure, and /lib/systemd/system-shutdown/apcupsd_shutdown handles the rest:
#!/bin/sh # apcupsd: kill power via UPS (if powerfail situation) # (Originally from Fedora.) # See if this is a powerfail situation. faildir=$(grep -e^PWRFAILDIR /etc/apcupsd/apcupsd.conf) faildir="${faildir#PWRFAILDIR }" if [ -f "${faildir:=/etc/apcupsd}/powerfail" ]; then echo echo "APCUPSD will now power off the UPS" echo /etc/apcupsd/apccontrol killpower fi
Note that the powerfail file is created before the shutdown, not when the UPS goes on battery.
So for the fun, try
# touch /etc/apcupsd/powerfail
and then shutdown the computer normally. This shows the behavior of a shutdown forced by the UPS daemon. As expected, this file is deleted after booting the system (most likely by apcusbd itself).
What happens on shutdown
The UPS powers down after 90 seconds (after displaying a countdown on its small screen), regardless of whether power has returned or not. This is followed by a “stayoff” of 60 seconds, after which it will power on again when power returns. During the UPS hibernation, the four LEDs are doing a disco pattern.
I want the USB to stay off until I turn it on manually. The nature of power failures is that they can go on and off, and I don’t want the UPS to go on, and then empty the battery on these.
To make a full poweroff instead of a hibernation, edit (or create) /etc/apcupsd/killpower, so it says:
#!/bin/bash # APCUPSD=/sbin/apcupsd echo "Apccontrol doing: ${APCUPSD} --power-off on UPS ${2}" sleep 10 ${APCUPSD} --power-off echo "Apccontrol has done: ${APCUPSD} --power-off on UPS ${2}" exit 99
This is more or less a replica of /etc/apcupsd/apccontrol’s handler for “killpower” command, only with apcupsd called with the –power-off flag instead of –killpower. The latter “hibernates” the UPS, so it wakes up when power returns. That’s the thing I didn’t want.
The “exit 99″ at the end inhibits apccontrol’s original handler.
So now there’s a “UPS TurnOff” countdown of 60 seconds, after which the UPS is shut down until power on manually.
Manual fixes
Set menus to advanced, if they’re not already. Then:
- Configuration > Auto Self Test, set to Startup Only: I tried to yank the battery’s plug on the UPS’ rear during a self test, and the computer’s power went down. So I presume that a failing self test will drop the power to the computer. Not clear what the point is.
- Configuration > Config Main Group Outlets > Turn Off Delay set to 10 seconds, to prevent an attempt to reboot the computer when the USB is about to power down. Surprisingly enough, this works when hibernating the UPS, but when enabling the power-off script above, the delay is 60 seconds, despite this change. I haven’t figured out how to change this.
Maybe the source code tells something
I dug in the sources for the reason that the UPS shuts down after 60 seconds, despite me setting the “Turn Off Delay” to 10 seconds directly on the UPS’ control buttons.
The relevant files in the acpupsd tarball:
- src/apcupsd.c: The actual daemon and main executable. Surprisingly readable.
- src/drivers/apcsmart/smartoper.c: The actual handlers of the operations (shutdown and power kill, with functions with obvious names). Written quite well, in terms of the persistence to carry out sensible operations when things go unexpected. Also see drivers/apcsmart/apcsmart.h.
So looking at smartoper.c, it turns out that the kill_power() method (which is used for “hibernation” of the UPS) sends a “soft” shutdown with an “S” command to the UPS, and doesn’t tell it the delay time. Hence the UPS decides the delay by itself (which is what I selected with the buttons).
The shutdown() method, on the other hand, calls apcsmart_ups_get_shutdown_delay(), which accepts an argument saying what the delay is. The name of this function is however misleading, as it just sends a shutdown command to the UPS, without telling it the delay. The figure in the delay is used only in the log messages. The UPS gets a “K” command, and doesn’t tell the UPS anything else. Basically, it works the same as kill_power(), only with a different command.
Trying NUT (actually, don’t)
What tempted me into trying out NUT was this page which implied that it has something related with shutdown.stayoff. And it’s keeping the UPS off that I wanted. But it seems like apcupsd is a much better choice.
Note my older post on NUT.
Since I went through the rubbish, here’s a quick runthrough. First install nut (which automatically ditches apcuspd (uninstalls it totally, it seems):
# apt-get install nut
The relevant part in /etc/nut/ups.conf for the ups named “smarter”:
[smarter] driver = usbhid-ups port = auto vendorid = 051d
I’m under the impression that the “port” assignment is ignored altogether. Don’t try it with other drivers — you’ll get “no such file”, for good reasons. Possibly usbhid-ups is the only way to utilize a USB connection.
And then in /etc/nut/upsmon.conf, added the line
MONITOR smarter@localhost 1 upsmon pass master
The truth is that I messed around a bit without too much notice of what I did, so I might have missed something. Anyhow, a reboot was required, after which the UPS was visible:
# upsc smarter Init SSL without certificate database battery.charge: 100 battery.charge.low: 10 battery.charge.warning: 50 battery.runtime: 3000 battery.runtime.low: 120 battery.type: PbAc battery.voltage: 26.8 battery.voltage.nominal: 24.0 device.mfr: American Power Conversion device.model: Smart-UPS 750 device.serial: AS1821351109 device.type: ups driver.name: usbhid-ups driver.parameter.pollfreq: 30 driver.parameter.pollinterval: 2 driver.parameter.port: auto driver.parameter.synchronous: no driver.parameter.vendorid: 051d driver.version: 2.7.4 driver.version.data: APC HID 0.96 driver.version.internal: 0.41 ups.beeper.status: enabled ups.delay.shutdown: 20 ups.firmware: UPS 09.3 / ID=18 ups.mfr: American Power Conversion ups.mfr.date: 2018/05/22 ups.model: Smart-UPS 750 ups.productid: 0003 ups.serial: AS1821351109 ups.status: OL ups.timer.reboot: -1 ups.timer.shutdown: -1 ups.vendorid: 051d
and getting the list of commands:
# upscmd -l smarter Instant commands supported on UPS [smarter]: beeper.disable - Disable the UPS beeper beeper.enable - Enable the UPS beeper beeper.mute - Temporarily mute the UPS beeper beeper.off - Obsolete (use beeper.disable or beeper.mute) beeper.on - Obsolete (use beeper.enable) load.off - Turn off the load immediately load.off.delay - Turn off the load with a delay (seconds) shutdown.reboot - Shut down the load briefly while rebooting the UPS shutdown.stop - Stop a shutdown in progress
So it didn’t really help.
Reader Comments
Thanks , I learned some details from this article. Ubuntu 16.04 + SMT750U