I recently purchased a CyberPower CST135XLU for my OpenBSD router and home computer. The main reason being that I do not want corrupted flash sectors whenever the power goes out due to a storm or snow. Not to mention, multiyear uptime is always a badge of honor!

Plugging in the UPS immediately resulted in a dmesg output:

uhidev2 at uhub0 port 2 configuration 1 interface 0 "CPS CST135XLU" rev 2.00/2.00 addr 4
uhidev2: iclass 3/0, 28 report ids
upd0 at uhidev2

We can immediately go ahead and use sysctl to probe the UPS status:

otis# sysctl -A | grep upd0
...
hw.sensors.upd0.indicator0=Off (Charging), OK
hw.sensors.upd0.indicator1=Off (Discharging), OK
hw.sensors.upd0.indicator2=On (ACPresent), OK
hw.sensors.upd0.percent0=100.00% (RemainingCapacity), OK
hw.sensors.upd0.timedelta0=3900.000000 secs (RunTimeToEmpty), OK

Since we are trying to avoid corrupted flash, we want to shutdown whenever the battery is close to empty. I personally want to avoid the UPS going below 20%, as deep draining batteries can severely inhibit their future capacity. sensorsd is a OpenBSD service which is like crond for sensors – it will be running these checks.

Special Notes:

  • It does not run checks very often, but you can tweak it with the -c flag if needed.

  • sensorsd will only run commands on state changes.

  • sensorsd cannot (that I could find) perform comparisons. So we will need to feed the current sensor value to an external script to perform the shutdown operation.

Create the sensorsd configuration file:

otis# vim /etc/sensorsd.conf
otis# cat /etc/sensorsd.conf
# Every sensor update below 30%, run the following python3 script.
# If the sensor value is below a value specified in the script, then gracefully shut down the system.
hw.sensors.upd0.percent0:low=30.00%:command=/home/austin/scripts/ups-shutdown.py %2

Here is the python3 script which gets ran:

#!/usr/local/bin/python3
import sys 
import subprocess

percentage = sys.argv[1].replace("%", "")
percentage = float(percentage)
print("Current UPS Percentage: " + str(percentage))
if percentage < 25.0:
    subprocess.run(["shutdown","now"])

Let’s go ahead and test our fancy new UPS setup:

otis# sensorsd -c 1 -d #check every second, do not daemonize
Current UPS Percentage: 100.0
Current UPS Percentage: 99.0
...
Current UPS Percentage: 24.0
Shutdown NOW!
shutdown: [pid 36404]
                                                                               
*** FINAL System shutdown message from austin@otis.BENTLEY ***               
System going down IMMEDIATELY                                                  
                                                                               
                                                                               

System shutdown time has arrived
Connection to 192.168.0.1 closed by remote host.
Connection to 192.168.0.1 closed.

Now that we’ve tested our setup, we can put it in place. We will start sensord and run it on system startup:

otis# /etc/rc.d/sensorsd start                                                                                                                                                                                    
/etc/rc.d/sensorsd: need -f to force start since sensorsd_flags=NO
otis# echo "sensorsd_flags=\"\"" >> /etc/rc.conf.local # copy and paste this or you will be sad your rc.conf is broken.                                                                                           
otis# /etc/rc.d/sensorsd start                                                                                          
sensorsd(ok)

Now we’re good to go! Enjoy your new setup.