2019-02-13 20:21:14 +00:00
|
|
|
"""Support for APCUPSd sensors."""
|
2016-02-10 16:32:18 +00:00
|
|
|
import logging
|
|
|
|
|
2019-10-18 00:10:28 +00:00
|
|
|
from apcaccess.status import ALL_UNITS
|
2016-08-30 19:34:33 +00:00
|
|
|
import voluptuous as vol
|
|
|
|
|
2021-03-22 11:37:16 +00:00
|
|
|
from homeassistant.components.sensor import PLATFORM_SCHEMA, SensorEntity
|
2020-02-23 20:09:24 +00:00
|
|
|
from homeassistant.const import (
|
|
|
|
CONF_RESOURCES,
|
2021-07-12 20:45:29 +00:00
|
|
|
DEVICE_CLASS_TEMPERATURE,
|
2021-07-20 18:06:23 +00:00
|
|
|
ELECTRIC_CURRENT_AMPERE,
|
|
|
|
ELECTRIC_POTENTIAL_VOLT,
|
2020-04-12 20:44:31 +00:00
|
|
|
FREQUENCY_HERTZ,
|
2020-09-05 19:09:14 +00:00
|
|
|
PERCENTAGE,
|
2021-07-20 18:06:23 +00:00
|
|
|
POWER_VOLT_AMPERE,
|
2020-02-23 20:09:24 +00:00
|
|
|
POWER_WATT,
|
|
|
|
TEMP_CELSIUS,
|
|
|
|
TIME_MINUTES,
|
|
|
|
TIME_SECONDS,
|
|
|
|
)
|
2016-08-30 19:34:33 +00:00
|
|
|
import homeassistant.helpers.config_validation as cv
|
2016-02-10 16:32:18 +00:00
|
|
|
|
2020-04-05 21:54:37 +00:00
|
|
|
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 "
|
2016-07-07 01:25:57 +00:00
|
|
|
SENSOR_TYPES = {
|
2021-08-04 19:24:19 +00:00
|
|
|
"alarmdel": ["Alarm Delay", None, "mdi:alarm", None],
|
|
|
|
"ambtemp": ["Ambient Temperature", None, "mdi:thermometer", None],
|
|
|
|
"apc": ["Status Data", None, "mdi:information-outline", None],
|
|
|
|
"apcmodel": ["Model", None, "mdi:information-outline", None],
|
|
|
|
"badbatts": ["Bad Batteries", None, "mdi:information-outline", None],
|
|
|
|
"battdate": ["Battery Replaced", None, "mdi:calendar-clock", None],
|
|
|
|
"battstat": ["Battery Status", None, "mdi:information-outline", None],
|
2021-07-20 18:06:23 +00:00
|
|
|
"battv": ["Battery Voltage", ELECTRIC_POTENTIAL_VOLT, "mdi:flash", None],
|
2021-07-12 20:45:29 +00:00
|
|
|
"bcharge": ["Battery", PERCENTAGE, "mdi:battery", None],
|
2021-08-04 19:24:19 +00:00
|
|
|
"cable": ["Cable Type", None, "mdi:ethernet-cable", None],
|
|
|
|
"cumonbatt": ["Total Time on Battery", None, "mdi:timer-outline", None],
|
|
|
|
"date": ["Status Date", None, "mdi:calendar-clock", None],
|
|
|
|
"dipsw": ["Dip Switch Settings", None, "mdi:information-outline", None],
|
|
|
|
"dlowbatt": ["Low Battery Signal", None, "mdi:clock-alert", None],
|
|
|
|
"driver": ["Driver", None, "mdi:information-outline", None],
|
|
|
|
"dshutd": ["Shutdown Delay", None, "mdi:timer-outline", None],
|
|
|
|
"dwake": ["Wake Delay", None, "mdi:timer-outline", None],
|
|
|
|
"endapc": ["Date and Time", None, "mdi:calendar-clock", None],
|
|
|
|
"extbatts": ["External Batteries", None, "mdi:information-outline", None],
|
|
|
|
"firmware": ["Firmware Version", None, "mdi:information-outline", None],
|
2021-07-20 18:06:23 +00:00
|
|
|
"hitrans": ["Transfer High", ELECTRIC_POTENTIAL_VOLT, "mdi:flash", None],
|
2021-08-04 19:24:19 +00:00
|
|
|
"hostname": ["Hostname", None, "mdi:information-outline", None],
|
2021-07-12 20:45:29 +00:00
|
|
|
"humidity": ["Ambient Humidity", PERCENTAGE, "mdi:water-percent", None],
|
|
|
|
"itemp": ["Internal Temperature", TEMP_CELSIUS, None, DEVICE_CLASS_TEMPERATURE],
|
2021-08-04 19:24:19 +00:00
|
|
|
"lastxfer": ["Last Transfer", None, "mdi:transfer", None],
|
|
|
|
"linefail": ["Input Voltage Status", None, "mdi:information-outline", None],
|
2021-07-12 20:45:29 +00:00
|
|
|
"linefreq": ["Line Frequency", FREQUENCY_HERTZ, "mdi:information-outline", None],
|
2021-07-20 18:06:23 +00:00
|
|
|
"linev": ["Input Voltage", ELECTRIC_POTENTIAL_VOLT, "mdi:flash", None],
|
2021-07-12 20:45:29 +00:00
|
|
|
"loadpct": ["Load", PERCENTAGE, "mdi:gauge", None],
|
|
|
|
"loadapnt": ["Load Apparent Power", PERCENTAGE, "mdi:gauge", None],
|
2021-07-20 18:06:23 +00:00
|
|
|
"lotrans": ["Transfer Low", ELECTRIC_POTENTIAL_VOLT, "mdi:flash", None],
|
2021-08-04 19:24:19 +00:00
|
|
|
"mandate": ["Manufacture Date", None, "mdi:calendar", None],
|
|
|
|
"masterupd": ["Master Update", None, "mdi:information-outline", None],
|
2021-07-20 18:06:23 +00:00
|
|
|
"maxlinev": ["Input Voltage High", ELECTRIC_POTENTIAL_VOLT, "mdi:flash", None],
|
2021-08-04 19:24:19 +00:00
|
|
|
"maxtime": ["Battery Timeout", None, "mdi:timer-off-outline", None],
|
2021-07-12 20:45:29 +00:00
|
|
|
"mbattchg": ["Battery Shutdown", PERCENTAGE, "mdi:battery-alert", None],
|
2021-07-20 18:06:23 +00:00
|
|
|
"minlinev": ["Input Voltage Low", ELECTRIC_POTENTIAL_VOLT, "mdi:flash", None],
|
2021-08-04 19:24:19 +00:00
|
|
|
"mintimel": ["Shutdown Time", None, "mdi:timer-outline", None],
|
|
|
|
"model": ["Model", None, "mdi:information-outline", None],
|
2021-07-20 18:06:23 +00:00
|
|
|
"nombattv": ["Battery Nominal Voltage", ELECTRIC_POTENTIAL_VOLT, "mdi:flash", None],
|
|
|
|
"nominv": ["Nominal Input Voltage", ELECTRIC_POTENTIAL_VOLT, "mdi:flash", None],
|
|
|
|
"nomoutv": ["Nominal Output Voltage", ELECTRIC_POTENTIAL_VOLT, "mdi:flash", None],
|
2021-07-12 20:45:29 +00:00
|
|
|
"nompower": ["Nominal Output Power", POWER_WATT, "mdi:flash", None],
|
2021-07-20 18:06:23 +00:00
|
|
|
"nomapnt": ["Nominal Apparent Power", POWER_VOLT_AMPERE, "mdi:flash", None],
|
2021-08-04 19:24:19 +00:00
|
|
|
"numxfers": ["Transfer Count", None, "mdi:counter", None],
|
2021-07-20 18:06:23 +00:00
|
|
|
"outcurnt": ["Output Current", ELECTRIC_CURRENT_AMPERE, "mdi:flash", None],
|
|
|
|
"outputv": ["Output Voltage", ELECTRIC_POTENTIAL_VOLT, "mdi:flash", None],
|
2021-08-04 19:24:19 +00:00
|
|
|
"reg1": ["Register 1 Fault", None, "mdi:information-outline", None],
|
|
|
|
"reg2": ["Register 2 Fault", None, "mdi:information-outline", None],
|
|
|
|
"reg3": ["Register 3 Fault", None, "mdi:information-outline", None],
|
2021-07-12 20:45:29 +00:00
|
|
|
"retpct": ["Restore Requirement", PERCENTAGE, "mdi:battery-alert", None],
|
2021-08-04 19:24:19 +00:00
|
|
|
"selftest": ["Last Self Test", None, "mdi:calendar-clock", None],
|
|
|
|
"sense": ["Sensitivity", None, "mdi:information-outline", None],
|
|
|
|
"serialno": ["Serial Number", None, "mdi:information-outline", None],
|
|
|
|
"starttime": ["Startup Time", None, "mdi:calendar-clock", None],
|
|
|
|
"statflag": ["Status Flag", None, "mdi:information-outline", None],
|
|
|
|
"status": ["Status", None, "mdi:information-outline", None],
|
|
|
|
"stesti": ["Self Test Interval", None, "mdi:information-outline", None],
|
|
|
|
"timeleft": ["Time Left", None, "mdi:clock-alert", None],
|
|
|
|
"tonbatt": ["Time on Battery", None, "mdi:timer-outline", None],
|
|
|
|
"upsmode": ["Mode", None, "mdi:information-outline", None],
|
|
|
|
"upsname": ["Name", None, "mdi:information-outline", None],
|
|
|
|
"version": ["Daemon Info", None, "mdi:information-outline", None],
|
|
|
|
"xoffbat": ["Transfer from Battery", None, "mdi:transfer", None],
|
|
|
|
"xoffbatt": ["Transfer from Battery", None, "mdi:transfer", None],
|
|
|
|
"xonbatt": ["Transfer to Battery", None, "mdi:transfer", None],
|
2016-07-07 01:25:57 +00:00
|
|
|
}
|
|
|
|
|
2019-07-31 19:25:30 +00:00
|
|
|
SPECIFIC_UNITS = {"ITEMP": TEMP_CELSIUS}
|
2016-07-07 01:25:57 +00:00
|
|
|
INFERRED_UNITS = {
|
2020-02-23 20:09:24 +00:00
|
|
|
" Minutes": TIME_MINUTES,
|
|
|
|
" Seconds": TIME_SECONDS,
|
2020-09-05 19:09:14 +00:00
|
|
|
" Percent": PERCENTAGE,
|
2021-07-20 18:06:23 +00:00
|
|
|
" Volts": ELECTRIC_POTENTIAL_VOLT,
|
|
|
|
" Ampere": ELECTRIC_CURRENT_AMPERE,
|
|
|
|
" Volt-Ampere": POWER_VOLT_AMPERE,
|
2019-07-31 19:25:30 +00:00
|
|
|
" Watts": POWER_WATT,
|
2020-04-12 20:44:31 +00:00
|
|
|
" Hz": FREQUENCY_HERTZ,
|
2019-07-31 19:25:30 +00:00
|
|
|
" C": TEMP_CELSIUS,
|
2020-09-05 19:09:14 +00:00
|
|
|
" Percent Load Capacity": 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):
|
2017-05-02 16:18:47 +00:00
|
|
|
"""Set up the APCUPSd sensors."""
|
2020-04-05 21:54:37 +00:00
|
|
|
apcups_data = hass.data[DOMAIN]
|
2016-07-07 01:25:57 +00:00
|
|
|
entities = []
|
|
|
|
|
2016-08-30 19:34:33 +00:00
|
|
|
for resource in config[CONF_RESOURCES]:
|
2016-07-07 01:25:57 +00:00
|
|
|
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",
|
|
|
|
]
|
2016-07-07 01:25:57 +00:00
|
|
|
|
2020-04-05 21:54:37 +00:00
|
|
|
if sensor_type.upper() not in apcups_data.status:
|
2016-07-07 01:25:57 +00:00
|
|
|
_LOGGER.warning(
|
2017-05-02 16:18:47 +00:00
|
|
|
"Sensor type: %s does not appear in the APCUPSd status output",
|
2019-07-31 19:25:30 +00:00
|
|
|
sensor_type,
|
|
|
|
)
|
2016-07-07 01:25:57 +00:00
|
|
|
|
2020-04-05 21:54:37 +00:00
|
|
|
entities.append(APCUPSdSensor(apcups_data, sensor_type))
|
2016-07-07 01:25:57 +00:00
|
|
|
|
2017-08-08 18:21:33 +00:00
|
|
|
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
|
|
|
|
|
|
|
|
|
2021-03-22 11:37:16 +00:00
|
|
|
class APCUPSdSensor(SensorEntity):
|
2016-03-08 15:46:34 +00:00
|
|
|
"""Representation of a sensor entity for APCUPSd status values."""
|
|
|
|
|
2016-07-07 01:25:57 +00:00
|
|
|
def __init__(self, data, sensor_type):
|
2016-03-08 15:46:34 +00:00
|
|
|
"""Initialize the sensor."""
|
2016-02-11 07:33:53 +00:00
|
|
|
self._data = data
|
2016-07-07 01:25:57 +00:00
|
|
|
self.type = sensor_type
|
2021-07-08 09:55:26 +00:00
|
|
|
self._attr_name = SENSOR_PREFIX + SENSOR_TYPES[sensor_type][0]
|
|
|
|
self._attr_icon = SENSOR_TYPES[self.type][2]
|
2021-08-11 08:45:05 +00:00
|
|
|
self._attr_native_unit_of_measurement = SENSOR_TYPES[sensor_type][1]
|
2021-07-12 20:45:29 +00:00
|
|
|
self._attr_device_class = SENSOR_TYPES[sensor_type][3]
|
2016-02-10 16:32:18 +00:00
|
|
|
|
|
|
|
def update(self):
|
2016-02-23 05:21:49 +00:00
|
|
|
"""Get the latest status and use it to update our sensor state."""
|
2016-07-07 01:25:57 +00:00
|
|
|
if self.type.upper() not in self._data.status:
|
2021-08-11 08:45:05 +00:00
|
|
|
self._attr_native_value = None
|
2016-07-07 01:25:57 +00:00
|
|
|
else:
|
2021-08-11 08:45:05 +00:00
|
|
|
self._attr_native_value, inferred_unit = infer_unit(
|
2019-07-31 19:25:30 +00:00
|
|
|
self._data.status[self.type.upper()]
|
|
|
|
)
|
2021-08-11 08:45:05 +00:00
|
|
|
if not self._attr_native_unit_of_measurement:
|
|
|
|
self._attr_native_unit_of_measurement = inferred_unit
|