I have converted the AppleScript noted in
this topic to Python. This script
does not require the
apcaccess program and can run on Indigo 5 or 6.
A few notes:
- The script must be called from inside Indigo, preferably from file rather than embedded - just in case it should hang while reading the UPS data.
- You must create 2 Indigo variables: apcUpsHost and apcUpsPort.
apcUpsHost is the IP Address, FQDN or bonjour name of the host running the apcupsd daemon (I.e. the host the UPS is connected to). Eg: 192.168.1.1, indigo.local, localhost, my.indigo.com, etc.
apcUpsPort is the port assigned to the APC apcupsd daemon Netserver. Usually 3551.
- Data read from the UPS will be saved to variables of the same names used in the apcaccess report.
I.e. any of the following: ALARMDEL, BATTDATE, BATTV, BCHARGE, CABLE, CUMONBATT, DATE, DRIVER, FIRMWARE, HITRANS, HOSTNAME, LASTXFER, LINEV, LOADPCT, LOTRANS, MAXTIME, MBATTCHG, MINTIMEL, MODEL, NOMBATTV, NOMINV, NOMPOWER, NUMXFERS, SELFTEST, SENSE, SERIALNO, STARTTIME, STATFLAG, STATUS, TIMELEFT, TONBATT, UPSMODE, UPSNAME, VERSION, XOFFBATT, XONBATT
- You just need to create variables for the data items you wish. If you do not create a variable for a given item, it will be silently ignored. You may place the variables in a folder if you wish.
Save the script (see below) as apcupsdata.py (or any name you like, with a .py extension), create a schedule to run it as often as you wish and go. That's it.
For now, I think this is probably sufficient. As noted in the other topic re: the UPS plugin, I do not presently see any increased value in having this instantiated as a plugin (creating a UPS device with states representing the data items) instead of a script with variables representing the data items. But, if there is a convincing argument, I could change my mind. Or, someone else is free to take this work and adapt it as they wish.
The script:
- Code: Select all
"""Revised by berkinet from
https://github.com/BrightcoveOS/Diamond/blob/master/src/collectors/apcupsd/apcupsd.py
"""
import socket
from struct import pack
import re
import indigo
def getData(apcHostname, apcPort):
# Get the data via TCP stream
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
s.connect((apcHostname, apcPort))
# Packet is pad byte, size byte, and command
s.send(pack('xb6s', 6, 'status'))
# Ditch the header
s.recv(1024)
data = s.recv(1024)
# We're done. Close the socket
s.close()
return data
apcHostname = indigo.variables["apcUpsHost"].value
apcPort = int(indigo.variables["apcUpsPort"].value)
metrics = {}
raw = {}
data = getData(apcHostname, apcPort)
data = data.split('\n\x00')
for d in data:
matches = re.search("([A-Z]+)\s+:\s+(.*)$", d)
if matches:
value = matches.group(2).strip()
raw[matches.group(1)] = matches.group(2).strip()
metrics[matches.group(1)] = value
for metric in metrics: # config['metrics']:
value = metrics[metric]
try:
indigo.variable.updateValue(metric, value)
except:
pass