Use EntityDescription - apcupsd (#55790)

This commit is contained in:
Marc Mueller 2021-09-06 10:19:31 +02:00 committed by GitHub
parent 655399eb7b
commit a4e4ffef0a
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23

View File

@ -1,10 +1,16 @@
"""Support for APCUPSd sensors.""" """Support for APCUPSd sensors."""
from __future__ import annotations
import logging import logging
from apcaccess.status import ALL_UNITS from apcaccess.status import ALL_UNITS
import voluptuous as vol import voluptuous as vol
from homeassistant.components.sensor import PLATFORM_SCHEMA, SensorEntity from homeassistant.components.sensor import (
PLATFORM_SCHEMA,
SensorEntity,
SensorEntityDescription,
)
from homeassistant.const import ( from homeassistant.const import (
CONF_RESOURCES, CONF_RESOURCES,
DEVICE_CLASS_TEMPERATURE, DEVICE_CLASS_TEMPERATURE,
@ -25,74 +31,360 @@ from . import DOMAIN
_LOGGER = logging.getLogger(__name__) _LOGGER = logging.getLogger(__name__)
SENSOR_PREFIX = "UPS " SENSOR_PREFIX = "UPS "
SENSOR_TYPES = { SENSOR_TYPES: tuple[SensorEntityDescription, ...] = (
"alarmdel": ["Alarm Delay", None, "mdi:alarm", None], SensorEntityDescription(
"ambtemp": ["Ambient Temperature", None, "mdi:thermometer", None], key="alarmdel",
"apc": ["Status Data", None, "mdi:information-outline", None], name="Alarm Delay",
"apcmodel": ["Model", None, "mdi:information-outline", None], icon="mdi:alarm",
"badbatts": ["Bad Batteries", None, "mdi:information-outline", None], ),
"battdate": ["Battery Replaced", None, "mdi:calendar-clock", None], SensorEntityDescription(
"battstat": ["Battery Status", None, "mdi:information-outline", None], key="ambtemp",
"battv": ["Battery Voltage", ELECTRIC_POTENTIAL_VOLT, "mdi:flash", None], name="Ambient Temperature",
"bcharge": ["Battery", PERCENTAGE, "mdi:battery", None], icon="mdi:thermometer",
"cable": ["Cable Type", None, "mdi:ethernet-cable", None], ),
"cumonbatt": ["Total Time on Battery", None, "mdi:timer-outline", None], SensorEntityDescription(
"date": ["Status Date", None, "mdi:calendar-clock", None], key="apc",
"dipsw": ["Dip Switch Settings", None, "mdi:information-outline", None], name="Status Data",
"dlowbatt": ["Low Battery Signal", None, "mdi:clock-alert", None], icon="mdi:information-outline",
"driver": ["Driver", None, "mdi:information-outline", None], ),
"dshutd": ["Shutdown Delay", None, "mdi:timer-outline", None], SensorEntityDescription(
"dwake": ["Wake Delay", None, "mdi:timer-outline", None], key="apcmodel",
"endapc": ["Date and Time", None, "mdi:calendar-clock", None], name="Model",
"extbatts": ["External Batteries", None, "mdi:information-outline", None], icon="mdi:information-outline",
"firmware": ["Firmware Version", None, "mdi:information-outline", None], ),
"hitrans": ["Transfer High", ELECTRIC_POTENTIAL_VOLT, "mdi:flash", None], SensorEntityDescription(
"hostname": ["Hostname", None, "mdi:information-outline", None], key="badbatts",
"humidity": ["Ambient Humidity", PERCENTAGE, "mdi:water-percent", None], name="Bad Batteries",
"itemp": ["Internal Temperature", TEMP_CELSIUS, None, DEVICE_CLASS_TEMPERATURE], icon="mdi:information-outline",
"lastxfer": ["Last Transfer", None, "mdi:transfer", None], ),
"linefail": ["Input Voltage Status", None, "mdi:information-outline", None], SensorEntityDescription(
"linefreq": ["Line Frequency", FREQUENCY_HERTZ, "mdi:information-outline", None], key="battdate",
"linev": ["Input Voltage", ELECTRIC_POTENTIAL_VOLT, "mdi:flash", None], name="Battery Replaced",
"loadpct": ["Load", PERCENTAGE, "mdi:gauge", None], icon="mdi:calendar-clock",
"loadapnt": ["Load Apparent Power", PERCENTAGE, "mdi:gauge", None], ),
"lotrans": ["Transfer Low", ELECTRIC_POTENTIAL_VOLT, "mdi:flash", None], SensorEntityDescription(
"mandate": ["Manufacture Date", None, "mdi:calendar", None], key="battstat",
"masterupd": ["Master Update", None, "mdi:information-outline", None], name="Battery Status",
"maxlinev": ["Input Voltage High", ELECTRIC_POTENTIAL_VOLT, "mdi:flash", None], icon="mdi:information-outline",
"maxtime": ["Battery Timeout", None, "mdi:timer-off-outline", None], ),
"mbattchg": ["Battery Shutdown", PERCENTAGE, "mdi:battery-alert", None], SensorEntityDescription(
"minlinev": ["Input Voltage Low", ELECTRIC_POTENTIAL_VOLT, "mdi:flash", None], key="battv",
"mintimel": ["Shutdown Time", None, "mdi:timer-outline", None], name="Battery Voltage",
"model": ["Model", None, "mdi:information-outline", None], native_unit_of_measurement=ELECTRIC_POTENTIAL_VOLT,
"nombattv": ["Battery Nominal Voltage", ELECTRIC_POTENTIAL_VOLT, "mdi:flash", None], icon="mdi:flash",
"nominv": ["Nominal Input Voltage", ELECTRIC_POTENTIAL_VOLT, "mdi:flash", None], ),
"nomoutv": ["Nominal Output Voltage", ELECTRIC_POTENTIAL_VOLT, "mdi:flash", None], SensorEntityDescription(
"nompower": ["Nominal Output Power", POWER_WATT, "mdi:flash", None], key="bcharge",
"nomapnt": ["Nominal Apparent Power", POWER_VOLT_AMPERE, "mdi:flash", None], name="Battery",
"numxfers": ["Transfer Count", None, "mdi:counter", None], native_unit_of_measurement=PERCENTAGE,
"outcurnt": ["Output Current", ELECTRIC_CURRENT_AMPERE, "mdi:flash", None], icon="mdi:battery",
"outputv": ["Output Voltage", ELECTRIC_POTENTIAL_VOLT, "mdi:flash", None], ),
"reg1": ["Register 1 Fault", None, "mdi:information-outline", None], SensorEntityDescription(
"reg2": ["Register 2 Fault", None, "mdi:information-outline", None], key="cable",
"reg3": ["Register 3 Fault", None, "mdi:information-outline", None], name="Cable Type",
"retpct": ["Restore Requirement", PERCENTAGE, "mdi:battery-alert", None], icon="mdi:ethernet-cable",
"selftest": ["Last Self Test", None, "mdi:calendar-clock", None], ),
"sense": ["Sensitivity", None, "mdi:information-outline", None], SensorEntityDescription(
"serialno": ["Serial Number", None, "mdi:information-outline", None], key="cumonbatt",
"starttime": ["Startup Time", None, "mdi:calendar-clock", None], name="Total Time on Battery",
"statflag": ["Status Flag", None, "mdi:information-outline", None], icon="mdi:timer-outline",
"status": ["Status", None, "mdi:information-outline", None], ),
"stesti": ["Self Test Interval", None, "mdi:information-outline", None], SensorEntityDescription(
"timeleft": ["Time Left", None, "mdi:clock-alert", None], key="date",
"tonbatt": ["Time on Battery", None, "mdi:timer-outline", None], name="Status Date",
"upsmode": ["Mode", None, "mdi:information-outline", None], icon="mdi:calendar-clock",
"upsname": ["Name", None, "mdi:information-outline", None], ),
"version": ["Daemon Info", None, "mdi:information-outline", None], SensorEntityDescription(
"xoffbat": ["Transfer from Battery", None, "mdi:transfer", None], key="dipsw",
"xoffbatt": ["Transfer from Battery", None, "mdi:transfer", None], name="Dip Switch Settings",
"xonbatt": ["Transfer to Battery", None, "mdi:transfer", None], icon="mdi:information-outline",
} ),
SensorEntityDescription(
key="dlowbatt",
name="Low Battery Signal",
icon="mdi:clock-alert",
),
SensorEntityDescription(
key="driver",
name="Driver",
icon="mdi:information-outline",
),
SensorEntityDescription(
key="dshutd",
name="Shutdown Delay",
icon="mdi:timer-outline",
),
SensorEntityDescription(
key="dwake",
name="Wake Delay",
icon="mdi:timer-outline",
),
SensorEntityDescription(
key="endapc",
name="Date and Time",
icon="mdi:calendar-clock",
),
SensorEntityDescription(
key="extbatts",
name="External Batteries",
icon="mdi:information-outline",
),
SensorEntityDescription(
key="firmware",
name="Firmware Version",
icon="mdi:information-outline",
),
SensorEntityDescription(
key="hitrans",
name="Transfer High",
native_unit_of_measurement=ELECTRIC_POTENTIAL_VOLT,
icon="mdi:flash",
),
SensorEntityDescription(
key="hostname",
name="Hostname",
icon="mdi:information-outline",
),
SensorEntityDescription(
key="humidity",
name="Ambient Humidity",
native_unit_of_measurement=PERCENTAGE,
icon="mdi:water-percent",
),
SensorEntityDescription(
key="itemp",
name="Internal Temperature",
native_unit_of_measurement=TEMP_CELSIUS,
device_class=DEVICE_CLASS_TEMPERATURE,
),
SensorEntityDescription(
key="lastxfer",
name="Last Transfer",
icon="mdi:transfer",
),
SensorEntityDescription(
key="linefail",
name="Input Voltage Status",
icon="mdi:information-outline",
),
SensorEntityDescription(
key="linefreq",
name="Line Frequency",
native_unit_of_measurement=FREQUENCY_HERTZ,
icon="mdi:information-outline",
),
SensorEntityDescription(
key="linev",
name="Input Voltage",
native_unit_of_measurement=ELECTRIC_POTENTIAL_VOLT,
icon="mdi:flash",
),
SensorEntityDescription(
key="loadpct",
name="Load",
native_unit_of_measurement=PERCENTAGE,
icon="mdi:gauge",
),
SensorEntityDescription(
key="loadapnt",
name="Load Apparent Power",
native_unit_of_measurement=PERCENTAGE,
icon="mdi:gauge",
),
SensorEntityDescription(
key="lotrans",
name="Transfer Low",
native_unit_of_measurement=ELECTRIC_POTENTIAL_VOLT,
icon="mdi:flash",
),
SensorEntityDescription(
key="mandate",
name="Manufacture Date",
icon="mdi:calendar",
),
SensorEntityDescription(
key="masterupd",
name="Master Update",
icon="mdi:information-outline",
),
SensorEntityDescription(
key="maxlinev",
name="Input Voltage High",
native_unit_of_measurement=ELECTRIC_POTENTIAL_VOLT,
icon="mdi:flash",
),
SensorEntityDescription(
key="maxtime",
name="Battery Timeout",
icon="mdi:timer-off-outline",
),
SensorEntityDescription(
key="mbattchg",
name="Battery Shutdown",
native_unit_of_measurement=PERCENTAGE,
icon="mdi:battery-alert",
),
SensorEntityDescription(
key="minlinev",
name="Input Voltage Low",
native_unit_of_measurement=ELECTRIC_POTENTIAL_VOLT,
icon="mdi:flash",
),
SensorEntityDescription(
key="mintimel",
name="Shutdown Time",
icon="mdi:timer-outline",
),
SensorEntityDescription(
key="model",
name="Model",
icon="mdi:information-outline",
),
SensorEntityDescription(
key="nombattv",
name="Battery Nominal Voltage",
native_unit_of_measurement=ELECTRIC_POTENTIAL_VOLT,
icon="mdi:flash",
),
SensorEntityDescription(
key="nominv",
name="Nominal Input Voltage",
native_unit_of_measurement=ELECTRIC_POTENTIAL_VOLT,
icon="mdi:flash",
),
SensorEntityDescription(
key="nomoutv",
name="Nominal Output Voltage",
native_unit_of_measurement=ELECTRIC_POTENTIAL_VOLT,
icon="mdi:flash",
),
SensorEntityDescription(
key="nompower",
name="Nominal Output Power",
native_unit_of_measurement=POWER_WATT,
icon="mdi:flash",
),
SensorEntityDescription(
key="nomapnt",
name="Nominal Apparent Power",
native_unit_of_measurement=POWER_VOLT_AMPERE,
icon="mdi:flash",
),
SensorEntityDescription(
key="numxfers",
name="Transfer Count",
icon="mdi:counter",
),
SensorEntityDescription(
key="outcurnt",
name="Output Current",
native_unit_of_measurement=ELECTRIC_CURRENT_AMPERE,
icon="mdi:flash",
),
SensorEntityDescription(
key="outputv",
name="Output Voltage",
native_unit_of_measurement=ELECTRIC_POTENTIAL_VOLT,
icon="mdi:flash",
),
SensorEntityDescription(
key="reg1",
name="Register 1 Fault",
icon="mdi:information-outline",
),
SensorEntityDescription(
key="reg2",
name="Register 2 Fault",
icon="mdi:information-outline",
),
SensorEntityDescription(
key="reg3",
name="Register 3 Fault",
icon="mdi:information-outline",
),
SensorEntityDescription(
key="retpct",
name="Restore Requirement",
native_unit_of_measurement=PERCENTAGE,
icon="mdi:battery-alert",
),
SensorEntityDescription(
key="selftest",
name="Last Self Test",
icon="mdi:calendar-clock",
),
SensorEntityDescription(
key="sense",
name="Sensitivity",
icon="mdi:information-outline",
),
SensorEntityDescription(
key="serialno",
name="Serial Number",
icon="mdi:information-outline",
),
SensorEntityDescription(
key="starttime",
name="Startup Time",
icon="mdi:calendar-clock",
),
SensorEntityDescription(
key="statflag",
name="Status Flag",
icon="mdi:information-outline",
),
SensorEntityDescription(
key="status",
name="Status",
icon="mdi:information-outline",
),
SensorEntityDescription(
key="stesti",
name="Self Test Interval",
icon="mdi:information-outline",
),
SensorEntityDescription(
key="timeleft",
name="Time Left",
icon="mdi:clock-alert",
),
SensorEntityDescription(
key="tonbatt",
name="Time on Battery",
icon="mdi:timer-outline",
),
SensorEntityDescription(
key="upsmode",
name="Mode",
icon="mdi:information-outline",
),
SensorEntityDescription(
key="upsname",
name="Name",
icon="mdi:information-outline",
),
SensorEntityDescription(
key="version",
name="Daemon Info",
icon="mdi:information-outline",
),
SensorEntityDescription(
key="xoffbat",
name="Transfer from Battery",
icon="mdi:transfer",
),
SensorEntityDescription(
key="xoffbatt",
name="Transfer from Battery",
icon="mdi:transfer",
),
SensorEntityDescription(
key="xonbatt",
name="Transfer to Battery",
icon="mdi:transfer",
),
)
SENSOR_KEYS: list[str] = [desc.key for desc in SENSOR_TYPES]
SPECIFIC_UNITS = {"ITEMP": TEMP_CELSIUS} SPECIFIC_UNITS = {"ITEMP": TEMP_CELSIUS}
INFERRED_UNITS = { INFERRED_UNITS = {
@ -111,7 +403,7 @@ INFERRED_UNITS = {
PLATFORM_SCHEMA = PLATFORM_SCHEMA.extend( PLATFORM_SCHEMA = PLATFORM_SCHEMA.extend(
{ {
vol.Required(CONF_RESOURCES, default=[]): vol.All( vol.Required(CONF_RESOURCES, default=[]): vol.All(
cv.ensure_list, [vol.In(SENSOR_TYPES)] cv.ensure_list, [vol.In(SENSOR_KEYS)]
) )
} }
) )
@ -120,25 +412,20 @@ PLATFORM_SCHEMA = PLATFORM_SCHEMA.extend(
def setup_platform(hass, config, add_entities, discovery_info=None): def setup_platform(hass, config, add_entities, discovery_info=None):
"""Set up the APCUPSd sensors.""" """Set up the APCUPSd sensors."""
apcups_data = hass.data[DOMAIN] apcups_data = hass.data[DOMAIN]
entities = [] resources = config[CONF_RESOURCES]
for resource in config[CONF_RESOURCES]: for resource in resources:
sensor_type = resource.lower() if resource.upper() not in apcups_data.status:
if sensor_type not in SENSOR_TYPES:
SENSOR_TYPES[sensor_type] = [
sensor_type.title(),
"",
"mdi:information-outline",
]
if sensor_type.upper() not in apcups_data.status:
_LOGGER.warning( _LOGGER.warning(
"Sensor type: %s does not appear in the APCUPSd status output", "Sensor type: %s does not appear in the APCUPSd status output",
sensor_type, resource,
) )
entities.append(APCUPSdSensor(apcups_data, sensor_type)) entities = [
APCUPSdSensor(apcups_data, description)
for description in SENSOR_TYPES
if description.key in resources
]
add_entities(entities, True) add_entities(entities, True)
@ -159,22 +446,18 @@ def infer_unit(value):
class APCUPSdSensor(SensorEntity): class APCUPSdSensor(SensorEntity):
"""Representation of a sensor entity for APCUPSd status values.""" """Representation of a sensor entity for APCUPSd status values."""
def __init__(self, data, sensor_type): def __init__(self, data, description: SensorEntityDescription):
"""Initialize the sensor.""" """Initialize the sensor."""
self.entity_description = description
self._data = data self._data = data
self.type = sensor_type self._attr_name = f"{SENSOR_PREFIX}{description.name}"
self._attr_name = SENSOR_PREFIX + SENSOR_TYPES[sensor_type][0]
self._attr_icon = SENSOR_TYPES[self.type][2]
self._attr_native_unit_of_measurement = SENSOR_TYPES[sensor_type][1]
self._attr_device_class = SENSOR_TYPES[sensor_type][3]
def update(self): def update(self):
"""Get the latest status and use it to update our sensor state.""" """Get the latest status and use it to update our sensor state."""
if self.type.upper() not in self._data.status: key = self.entity_description.key.upper()
if key not in self._data.status:
self._attr_native_value = None self._attr_native_value = None
else: else:
self._attr_native_value, inferred_unit = infer_unit( self._attr_native_value, inferred_unit = infer_unit(self._data.status[key])
self._data.status[self.type.upper()] if not self.native_unit_of_measurement:
)
if not self._attr_native_unit_of_measurement:
self._attr_native_unit_of_measurement = inferred_unit self._attr_native_unit_of_measurement = inferred_unit