core/homeassistant/components/apcupsd/sensor.py

200 lines
7.5 KiB
Python
Raw Normal View History

"""Support for APCUPSd sensors."""
2016-02-10 16:32:18 +00:00
import logging
from apcaccess.status import ALL_UNITS
2016-08-30 19:34:33 +00:00
import voluptuous as vol
from homeassistant.components.sensor import PLATFORM_SCHEMA
from homeassistant.const import (
CONF_RESOURCES,
FREQUENCY_HERTZ,
POWER_WATT,
TEMP_CELSIUS,
TIME_MINUTES,
TIME_SECONDS,
UNIT_PERCENTAGE,
UNIT_VOLT,
)
2016-08-30 19:34:33 +00:00
import homeassistant.helpers.config_validation as cv
2016-02-10 16:32:18 +00:00
from homeassistant.helpers.entity import Entity
from . import DOMAIN
2016-08-30 19:34:33 +00:00
_LOGGER = logging.getLogger(__name__)
2019-07-31 19:25:30 +00:00
SENSOR_PREFIX = "UPS "
SENSOR_TYPES = {
2019-07-31 19:25:30 +00:00
"alarmdel": ["Alarm Delay", "", "mdi:alarm"],
"ambtemp": ["Ambient Temperature", "", "mdi:thermometer"],
"apc": ["Status Data", "", "mdi:information-outline"],
"apcmodel": ["Model", "", "mdi:information-outline"],
"badbatts": ["Bad Batteries", "", "mdi:information-outline"],
"battdate": ["Battery Replaced", "", "mdi:calendar-clock"],
"battstat": ["Battery Status", "", "mdi:information-outline"],
"battv": ["Battery Voltage", UNIT_VOLT, "mdi:flash"],
"bcharge": ["Battery", UNIT_PERCENTAGE, "mdi:battery"],
2019-07-31 19:25:30 +00:00
"cable": ["Cable Type", "", "mdi:ethernet-cable"],
"cumonbatt": ["Total Time on Battery", "", "mdi:timer"],
"date": ["Status Date", "", "mdi:calendar-clock"],
"dipsw": ["Dip Switch Settings", "", "mdi:information-outline"],
"dlowbatt": ["Low Battery Signal", "", "mdi:clock-alert"],
"driver": ["Driver", "", "mdi:information-outline"],
"dshutd": ["Shutdown Delay", "", "mdi:timer"],
"dwake": ["Wake Delay", "", "mdi:timer"],
"endapc": ["Date and Time", "", "mdi:calendar-clock"],
"extbatts": ["External Batteries", "", "mdi:information-outline"],
"firmware": ["Firmware Version", "", "mdi:information-outline"],
"hitrans": ["Transfer High", UNIT_VOLT, "mdi:flash"],
2019-07-31 19:25:30 +00:00
"hostname": ["Hostname", "", "mdi:information-outline"],
"humidity": ["Ambient Humidity", UNIT_PERCENTAGE, "mdi:water-percent"],
2019-07-31 19:25:30 +00:00
"itemp": ["Internal Temperature", TEMP_CELSIUS, "mdi:thermometer"],
"lastxfer": ["Last Transfer", "", "mdi:transfer"],
"linefail": ["Input Voltage Status", "", "mdi:information-outline"],
"linefreq": ["Line Frequency", FREQUENCY_HERTZ, "mdi:information-outline"],
"linev": ["Input Voltage", UNIT_VOLT, "mdi:flash"],
"loadpct": ["Load", UNIT_PERCENTAGE, "mdi:gauge"],
"loadapnt": ["Load Apparent Power", UNIT_PERCENTAGE, "mdi:gauge"],
"lotrans": ["Transfer Low", UNIT_VOLT, "mdi:flash"],
2019-07-31 19:25:30 +00:00
"mandate": ["Manufacture Date", "", "mdi:calendar"],
"masterupd": ["Master Update", "", "mdi:information-outline"],
"maxlinev": ["Input Voltage High", UNIT_VOLT, "mdi:flash"],
2019-07-31 19:25:30 +00:00
"maxtime": ["Battery Timeout", "", "mdi:timer-off"],
"mbattchg": ["Battery Shutdown", UNIT_PERCENTAGE, "mdi:battery-alert"],
"minlinev": ["Input Voltage Low", UNIT_VOLT, "mdi:flash"],
2019-07-31 19:25:30 +00:00
"mintimel": ["Shutdown Time", "", "mdi:timer"],
"model": ["Model", "", "mdi:information-outline"],
"nombattv": ["Battery Nominal Voltage", UNIT_VOLT, "mdi:flash"],
"nominv": ["Nominal Input Voltage", UNIT_VOLT, "mdi:flash"],
"nomoutv": ["Nominal Output Voltage", UNIT_VOLT, "mdi:flash"],
2019-07-31 19:25:30 +00:00
"nompower": ["Nominal Output Power", POWER_WATT, "mdi:flash"],
"nomapnt": ["Nominal Apparent Power", "VA", "mdi:flash"],
"numxfers": ["Transfer Count", "", "mdi:counter"],
"outcurnt": ["Output Current", "A", "mdi:flash"],
"outputv": ["Output Voltage", UNIT_VOLT, "mdi:flash"],
2019-07-31 19:25:30 +00:00
"reg1": ["Register 1 Fault", "", "mdi:information-outline"],
"reg2": ["Register 2 Fault", "", "mdi:information-outline"],
"reg3": ["Register 3 Fault", "", "mdi:information-outline"],
"retpct": ["Restore Requirement", UNIT_PERCENTAGE, "mdi:battery-alert"],
2019-07-31 19:25:30 +00:00
"selftest": ["Last Self Test", "", "mdi:calendar-clock"],
"sense": ["Sensitivity", "", "mdi:information-outline"],
"serialno": ["Serial Number", "", "mdi:information-outline"],
"starttime": ["Startup Time", "", "mdi:calendar-clock"],
"statflag": ["Status Flag", "", "mdi:information-outline"],
"status": ["Status", "", "mdi:information-outline"],
"stesti": ["Self Test Interval", "", "mdi:information-outline"],
"timeleft": ["Time Left", "", "mdi:clock-alert"],
"tonbatt": ["Time on Battery", "", "mdi:timer"],
"upsmode": ["Mode", "", "mdi:information-outline"],
"upsname": ["Name", "", "mdi:information-outline"],
"version": ["Daemon Info", "", "mdi:information-outline"],
"xoffbat": ["Transfer from Battery", "", "mdi:transfer"],
"xoffbatt": ["Transfer from Battery", "", "mdi:transfer"],
"xonbatt": ["Transfer to Battery", "", "mdi:transfer"],
}
2019-07-31 19:25:30 +00:00
SPECIFIC_UNITS = {"ITEMP": TEMP_CELSIUS}
INFERRED_UNITS = {
" Minutes": TIME_MINUTES,
" Seconds": TIME_SECONDS,
" Percent": UNIT_PERCENTAGE,
" Volts": UNIT_VOLT,
2019-07-31 19:25:30 +00:00
" Ampere": "A",
" Volt-Ampere": "VA",
" Watts": POWER_WATT,
" Hz": FREQUENCY_HERTZ,
2019-07-31 19:25:30 +00:00
" C": TEMP_CELSIUS,
" Percent Load Capacity": UNIT_PERCENTAGE,
2016-02-10 16:32:18 +00:00
}
2019-07-31 19:25:30 +00:00
PLATFORM_SCHEMA = PLATFORM_SCHEMA.extend(
{
vol.Required(CONF_RESOURCES, default=[]): vol.All(
cv.ensure_list, [vol.In(SENSOR_TYPES)]
)
}
)
2016-02-10 16:32:18 +00:00
def setup_platform(hass, config, add_entities, discovery_info=None):
"""Set up the APCUPSd sensors."""
apcups_data = hass.data[DOMAIN]
entities = []
2016-08-30 19:34:33 +00:00
for resource in config[CONF_RESOURCES]:
sensor_type = resource.lower()
if sensor_type not in SENSOR_TYPES:
SENSOR_TYPES[sensor_type] = [
2019-07-31 19:25:30 +00:00
sensor_type.title(),
"",
"mdi:information-outline",
]
if sensor_type.upper() not in apcups_data.status:
_LOGGER.warning(
"Sensor type: %s does not appear in the APCUPSd status output",
2019-07-31 19:25:30 +00:00
sensor_type,
)
entities.append(APCUPSdSensor(apcups_data, sensor_type))
add_entities(entities, True)
2016-02-10 16:32:18 +00:00
def infer_unit(value):
2016-03-08 15:46:34 +00:00
"""If the value ends with any of the units from ALL_UNITS.
Split the unit off the end of the value and return the value, unit tuple
pair. Else return the original value and None as the unit.
2016-02-10 16:32:18 +00:00
"""
2019-07-31 19:25:30 +00:00
2016-02-10 16:32:18 +00:00
for unit in ALL_UNITS:
if value.endswith(unit):
2019-07-31 19:25:30 +00:00
return value[: -len(unit)], INFERRED_UNITS.get(unit, unit.strip())
2016-02-10 16:32:18 +00:00
return value, None
class APCUPSdSensor(Entity):
2016-03-08 15:46:34 +00:00
"""Representation of a sensor entity for APCUPSd status values."""
def __init__(self, data, sensor_type):
2016-03-08 15:46:34 +00:00
"""Initialize the sensor."""
self._data = data
self.type = sensor_type
self._name = SENSOR_PREFIX + SENSOR_TYPES[sensor_type][0]
self._unit = SENSOR_TYPES[sensor_type][1]
2016-02-10 16:32:18 +00:00
self._inferred_unit = None
self._state = None
2016-02-10 16:32:18 +00:00
@property
def name(self):
2016-03-08 15:46:34 +00:00
"""Return the name of the UPS sensor."""
return self._name
@property
def icon(self):
"""Icon to use in the frontend, if any."""
return SENSOR_TYPES[self.type][2]
2016-02-10 16:32:18 +00:00
@property
def state(self):
2016-03-08 15:46:34 +00:00
"""Return true if the UPS is online, else False."""
2016-02-10 16:32:18 +00:00
return self._state
@property
def unit_of_measurement(self):
2016-03-08 15:46:34 +00:00
"""Return the unit of measurement of this entity, if any."""
if not self._unit:
2016-02-10 16:32:18 +00:00
return self._inferred_unit
return self._unit
def update(self):
2016-02-23 05:21:49 +00:00
"""Get the latest status and use it to update our sensor state."""
if self.type.upper() not in self._data.status:
self._state = None
self._inferred_unit = None
else:
self._state, self._inferred_unit = infer_unit(
2019-07-31 19:25:30 +00:00
self._data.status[self.type.upper()]
)