User Tools

Site Tools


How to add data from a TP9605BT multimeter to apcupsd rrd and graphs.

WARNING: All liability is yours: this procedure involves handling of potentially lethal electrical currents.

This describes how to add Voltage Output data to the apcupsd RRD database.
I did this because the APC BackUps ES-500 I have does not report a value I was interested in: "OUTPUTV - The voltage the UPS is supplying to your equipment" ( ).

The plan was simple:

  • Get a multimeter that could output voltage readings to my router.
  • Add the readings to the apcupsd RRD database.
  • Verify the readings appear in the appropriate graph.

I found a multimeter that worked and was cheap enough, the Tekpower TP9605BT ( This an affiliate link from Louis Rossmann's work with this meter at: Multimeter Overlay in OBS ).

The physical attachment of the multimeter involved:

  • Connecting the meter's USB cable to the router USB, which further required a small USB hub.
  • Experimenting until I found the correct button-press combination that put the meter into always-on mode.
    • The documentation had an incorrect sequence.
    • The correct sequence is: hold down the [Range] button while turning on the meter.
  • Switching to probes that would stay in a mains socket
  • Cobbling up a 9 volt battery eliminator.
  • Making sure I used the same circuit on the battery-backed-up side of the UPS for both the meter probes, and the battery eliminator. This minimizes the chances of a ground loop destroying the multimeter.

The next step was to establish communication between the meter and the router:

  • opkg install kmod-usb-serial-ch341
  • Make sure the communication worked.
  • Write some code that periodically took a value from the meter, and dumped it in the apcupsd RRD database.

From looking at logread, I determined that the meter's port is on /dev/ttyUSB0. So, I did:

# cat /dev/ttyUSB0
and got some very reasonable results:
+1227 3)�

+1227 3)�

Now, came the analysis part. The ")?" characters tell us what range the meter is set to. This didn't matter to me in this application, because I already knew the settings.

  • "+1227" are the numbers on the meter display.
  • "3" is where to put the decimal point.
  • So, "+1227 3)�" = 122.7 Volts AC.

Below is some code I whipped up. I'm sure it can be improved. Note that it has custom locations for the RRD files, and the port for the meter.

I added these lines to the crontabs/root:

# get AC Volts from the multimeter once every minute
*/1 * * * * /usr/share/

This runs the program every minute, and seems to work well when I look at the graph:

Now for some cleanup. Add this line to /etc/sysupgrade.conf, which preserves this new script across upgrades:


And, here is the script, to add to /usr/share/


#, Copyright 2017 Bob Meizlik, license: CC Attribution-Noncommercial-Share Alike 3.0.
# All liability is yours: this code presumes handling of dangerous tools and electricity.
# Purpose:
# Collect and store AC Voltage Output readings, when your UPS does not. 
# Usage:
# Connect your meter appropriately, to the output AC of the UPS, and the (USB or RS232 or Bluetooth) of your computer or access point.
# Hold down RANGE button, and turn meter on, to defeat the auto-power-off timer.
# Set meter range to Volts, AC.
# Set meter to RS232 output (this enables, RS232, USB and Bluetooth)
# Install drivers 
# Set this script to run periodically, perhaps with a cron script, or a daemon.
# Code Process:
# Get AC Voltage readings from a TekPower TP9605BT multimeter, and 
# send them to the apcups, collectd RRD file meant for these readings.
# get the latest voltage reading from a TekPower TP9605BT multimeter
# set to AC Volts range
# set to RS232 output
# We get 4 readings per second.
# each reading is 14 bytes long
# the lines look like this: 2b 31 32 31 38 20 33 29  20 20 80 20 0a 0a 2b 31  |+1218 3)  . ..+1|
# if we start in the middle of a line, ignore the line, and go to the next line, which is presumably complete.
# the x0a characters look like new lines in this processing, resulting in a data line that is 12 bytes long.
# Known issues:
# The input will hang, when there is no device at /dev/ttyUSB0.
# The input will hang, when the meter is turned off.


# todo: get the rrdfile name from /etc/config/luci-statistics option DataDir '/mnt/share/stats/rrd'

# translate 0 to space, because the length is our checksum
dat=$(dd bs=1 count=50 if=$inputfile | tr \\000 \\040 )

line1=$(echo -en "$dat" | sed --quiet '1p')
line2=$(echo -en "$dat" | sed --quiet '2p')
line3=$(echo -en "$dat" | sed --quiet '3p')


# todo, this would be nicer if it was a loop
if [ 12 -eq "$line1len" ]; then

# extract the data from the line, and convert it to a form that rrd can use.
set -- junk $theline
val=$2 # the value, like +1234

dec=`expr "$3" : '\([0-9]\)'` # the decimal place, like 3
decp1=`expr 1 + $dec`         # add 1 to get past the sign
theValue=${val:0:$decp1}.${val:$decp1} # put the value together with the decimal place

# generate and run a line like: rrdtool update .rrd $(date +%s):+122.5 
theSeconds=$(date +%s)
rrdcmd='rrdtool update '$rrdfile' ''N:'$theValue   

doc/howto/statistics.apcupsd_multimeter.txt · Last modified: 2017/08/02 06:22 by bobmseagithub