APC UPS

APC UPS

2025, Jun 22    

We have a large UPS for the NOC team, and we should monitor it appropriately.

It has a non-standard serial connector, and the plan is to connect it to a raspberry pi, add some exporter and maybe alerting also.

UPS and cable

It is an APC smart UPS 2200INET

Image of a grey 2200INET UPS

Yes, it is old, but batteries has been replaced recently, so we continue to use it.

The serial connector must be wired in a non-default way. Source 1 and source 2 both agree

My personal yolo style connector. Open with three connector attached and the rest scotched to avoid shorts

I didn’t succeed with connecting with minicom using “2400 8N1 SW flow control”, but with the correct settings, apcupsd was able to connect.

We followed this guide, which boils down to installing apcupsd and change two things in the config files. Remeber to restart service apcupsd restart.

Working config is as follows

grep -v -e '^#' -e '^$' /etc/default/apcupsd     
ISCONFIGURED=yesgrep -v -e '^#' -e '^$' /etc/apcupsd/apcupsd.conf
UPSCABLE 940-1524C
UPSTYPE apcsmart
DEVICE /dev/ttyUSB0
LOCKFILE /var/lock
SCRIPTDIR /etc/apcupsd
PWRFAILDIR /etc/apcupsd
NOLOGINDIR /etc
ONBATTERYDELAY 6
BATTERYLEVEL 5
MINUTES 3
TIMEOUT 0
ANNOY 300
ANNOYDELAY 60
NOLOGON disable
KILLDELAY 0
NETSERVER on
NISIP 127.0.0.1
NISPORT 3551
EVENTSFILE /var/log/apcupsd.events
EVENTSFILEMAX 10
UPSCLASS standalone
UPSMODE disable
STATTIME 0
STATFILE /var/log/apcupsd.status
LOGSTATS off
DATATIME 0

The only change I made is the UPSABLE, UPSTYPE and DEVICE. The NIS-stuff looks like a candidate for something to be disabled.

Use apcaccess to verify the connection

sysuser@upsmon:~ $ sudo apcaccess
APC      : 001,048,1017
DATE     : 2025-06-09 20:37:55 +0100  
HOSTNAME : upsmon
VERSION  : 3.14.14 (31 May 2016) debian
CABLE    : Custom Cable Smart
DRIVER   : APC Smart UPS (any)
UPSMODE  : Stand Alone
STARTTIME: 2025-06-09 20:37:47 +0100  
MODEL    : 
STATUS   : ONLINE REPLACEBATT 
LINEV    : 0.0 Volts
LOADPCT  : 0.0 Percent
BCHARGE  : 0.0 Percent
TIMELEFT : 0.0 Minutes
MBATTCHG : 5 Percent
MINTIMEL : 3 Minutes
MAXTIME  : 0 Seconds
MAXLINEV : 0.0 Volts
MINLINEV : 0.0 Volts
OUTPUTV  : 0.0 Volts
SENSE    : Unknown
DWAKE    : -1 Seconds
DSHUTD   : -1 Seconds
DLOWBATT : -1 Minutes
LOTRANS  : -1.0 Volts
HITRANS  : -1.0 Volts
RETPCT   : -1.0 Percent
ITEMP    : 0.0 C
ALARMDEL : Always
BATTV    : 0.0 Volts
LINEFREQ : 0.0 Hz
NUMXFERS : 0
TONBATT  : 0 Seconds
CUMONBATT: 0 Seconds
XOFFBATT : N/A
STESTI   : -1
STATFLAG : 0x05000088
DIPSW    : 0x00
REG1     : 0x00
REG2     : 0x00
REG3     : 0x00
MANDATE  : 
SERIALNO : 
BATTDATE : 
NOMOUTV  : -1 Volts
NOMBATTV : 0.0 Volts
EXTBATTS : 0
FIRMWARE : 
END APC  : 2025-06-09 20:37:55 +0100  

To avoid the host with apcupsd to shutdown when the UPS runs out of power, add the doshutdown file


sysuser@upsmon:/etc/apcupsd $ cat /etc/apcupsd/doshutdown 
#!/usr/bin/env bash

logger "apcupsd requested shudown. But it is ignored but ignored by '$0'"
exit 99

Exporting values

Apparently someone has already made an exporter and the associated grafana dashboard is here. Nice.

The installer is made in go - how does that work with raspberry? Much the same apparently…. We install go following the pimylife guide

sysuser@upsmon:~ $ dpkg-architecture | grep BITS
DEB_BUILD_ARCH_BITS=32
DEB_HOST_ARCH_BITS=32
DEB_TARGET_ARCH_BITS=32

Ok, we install the 32 bit version of go.

Download and extract, update .bashrc and source it.

sysuser@upsmon:~ $ go version
go version go1.24.4 linux/arm

Looks ok.

Git pull acpupsd_exporter, build it and activate.

Add to prometheus and grafana dashboard.

Screenshot of grafana dash with current values from my UPS

Make it persistent by adding a systemd service

sysuser@upsmon:~ $ cat /lib/systemd/system/apcupsd_exporter.service
[Unit]
Description=Prometheus exporter for apcupsd
After=network.target

[Service]
Type=simple
User=sysuser
WorkingDirectory=/home/sysuser/apcupsd_exporter/cmd/apcupsd_exporter/
ExecStart=/home/sysuser/apcupsd_exporter/cmd/apcupsd_exporter/apcupsd_exporter
Restart=on-failure

[Install]
WantedBy=multi-user.target

and do daemon reload (systemctl daemon-reload) and enable it (systemctl enable --now apcupsd_exporter.service).

Just to reiterate, I am just following the guide mentioned above.

Verify that it is working by getting the data curl localhost:9162/metrics.

Bootnore

  • It is really cool that people make these things and share them
  • I really ought to get better at handling go, so I don’t have to have entire build chains lying around and sources to. It would be noce to just build the binary and copy it.
  • “Time remaining” estimates are completely way off. Also, when testing the UPS was working for 15 minutes with 0% battery.