Migrate APCUPSD to has entity name (#112997)
* Properly set entity names for APCUPSD * Add test cases to prevent future regressions * Fix tests due to the updated entity IDs * Prettify code * Remove redundant translation key
This commit is contained in:
parent
b125a6b1bb
commit
db31afe019
6 changed files with 344 additions and 108 deletions
|
@ -20,7 +20,6 @@ from .coordinator import APCUPSdCoordinator
|
|||
_LOGGER = logging.getLogger(__name__)
|
||||
_DESCRIPTION = BinarySensorEntityDescription(
|
||||
key="statflag",
|
||||
name="UPS Online Status",
|
||||
translation_key="online_status",
|
||||
)
|
||||
# The bit in STATFLAG that indicates the online status of the APC UPS.
|
||||
|
@ -46,6 +45,8 @@ async def async_setup_entry(
|
|||
class OnlineStatus(CoordinatorEntity[APCUPSdCoordinator], BinarySensorEntity):
|
||||
"""Representation of a UPS online status."""
|
||||
|
||||
_attr_has_entity_name = True
|
||||
|
||||
def __init__(
|
||||
self,
|
||||
coordinator: APCUPSdCoordinator,
|
||||
|
|
|
@ -34,11 +34,10 @@ SENSORS: dict[str, SensorEntityDescription] = {
|
|||
"alarmdel": SensorEntityDescription(
|
||||
key="alarmdel",
|
||||
translation_key="alarm_delay",
|
||||
name="UPS Alarm Delay",
|
||||
),
|
||||
"ambtemp": SensorEntityDescription(
|
||||
key="ambtemp",
|
||||
name="UPS Ambient Temperature",
|
||||
translation_key="ambient_temperature",
|
||||
native_unit_of_measurement=UnitOfTemperature.CELSIUS,
|
||||
device_class=SensorDeviceClass.TEMPERATURE,
|
||||
state_class=SensorStateClass.MEASUREMENT,
|
||||
|
@ -46,40 +45,34 @@ SENSORS: dict[str, SensorEntityDescription] = {
|
|||
"apc": SensorEntityDescription(
|
||||
key="apc",
|
||||
translation_key="apc_status",
|
||||
name="UPS Status Data",
|
||||
entity_registry_enabled_default=False,
|
||||
),
|
||||
"apcmodel": SensorEntityDescription(
|
||||
key="apcmodel",
|
||||
translation_key="apc_model",
|
||||
name="UPS Model",
|
||||
entity_registry_enabled_default=False,
|
||||
),
|
||||
"badbatts": SensorEntityDescription(
|
||||
key="badbatts",
|
||||
translation_key="bad_batteries",
|
||||
name="UPS Bad Batteries",
|
||||
),
|
||||
"battdate": SensorEntityDescription(
|
||||
key="battdate",
|
||||
translation_key="battery_replacement_date",
|
||||
name="UPS Battery Replaced",
|
||||
),
|
||||
"battstat": SensorEntityDescription(
|
||||
key="battstat",
|
||||
translation_key="battery_status",
|
||||
name="UPS Battery Status",
|
||||
),
|
||||
"battv": SensorEntityDescription(
|
||||
key="battv",
|
||||
name="UPS Battery Voltage",
|
||||
translation_key="battery_voltage",
|
||||
native_unit_of_measurement=UnitOfElectricPotential.VOLT,
|
||||
device_class=SensorDeviceClass.VOLTAGE,
|
||||
state_class=SensorStateClass.MEASUREMENT,
|
||||
),
|
||||
"bcharge": SensorEntityDescription(
|
||||
key="bcharge",
|
||||
name="UPS Battery",
|
||||
native_unit_of_measurement=PERCENTAGE,
|
||||
device_class=SensorDeviceClass.BATTERY,
|
||||
state_class=SensorStateClass.MEASUREMENT,
|
||||
|
@ -87,86 +80,74 @@ SENSORS: dict[str, SensorEntityDescription] = {
|
|||
"cable": SensorEntityDescription(
|
||||
key="cable",
|
||||
translation_key="cable_type",
|
||||
name="UPS Cable Type",
|
||||
entity_registry_enabled_default=False,
|
||||
),
|
||||
"cumonbatt": SensorEntityDescription(
|
||||
key="cumonbatt",
|
||||
translation_key="total_time_on_battery",
|
||||
name="UPS Total Time on Battery",
|
||||
state_class=SensorStateClass.TOTAL_INCREASING,
|
||||
),
|
||||
"date": SensorEntityDescription(
|
||||
key="date",
|
||||
translation_key="date",
|
||||
name="UPS Status Date",
|
||||
entity_registry_enabled_default=False,
|
||||
),
|
||||
"dipsw": SensorEntityDescription(
|
||||
key="dipsw",
|
||||
translation_key="dip_switch_settings",
|
||||
name="UPS Dip Switch Settings",
|
||||
),
|
||||
"dlowbatt": SensorEntityDescription(
|
||||
key="dlowbatt",
|
||||
translation_key="low_battery_signal",
|
||||
name="UPS Low Battery Signal",
|
||||
),
|
||||
"driver": SensorEntityDescription(
|
||||
key="driver",
|
||||
translation_key="driver",
|
||||
name="UPS Driver",
|
||||
entity_registry_enabled_default=False,
|
||||
),
|
||||
"dshutd": SensorEntityDescription(
|
||||
key="dshutd",
|
||||
translation_key="shutdown_delay",
|
||||
name="UPS Shutdown Delay",
|
||||
),
|
||||
"dwake": SensorEntityDescription(
|
||||
key="dwake",
|
||||
translation_key="wake_delay",
|
||||
name="UPS Wake Delay",
|
||||
),
|
||||
"end apc": SensorEntityDescription(
|
||||
key="end apc",
|
||||
translation_key="date_and_time",
|
||||
name="UPS Date and Time",
|
||||
entity_registry_enabled_default=False,
|
||||
),
|
||||
"extbatts": SensorEntityDescription(
|
||||
key="extbatts",
|
||||
translation_key="external_batteries",
|
||||
name="UPS External Batteries",
|
||||
),
|
||||
"firmware": SensorEntityDescription(
|
||||
key="firmware",
|
||||
translation_key="firmware_version",
|
||||
name="UPS Firmware Version",
|
||||
entity_registry_enabled_default=False,
|
||||
),
|
||||
"hitrans": SensorEntityDescription(
|
||||
key="hitrans",
|
||||
name="UPS Transfer High",
|
||||
translation_key="transfer_high",
|
||||
native_unit_of_measurement=UnitOfElectricPotential.VOLT,
|
||||
device_class=SensorDeviceClass.VOLTAGE,
|
||||
),
|
||||
"hostname": SensorEntityDescription(
|
||||
key="hostname",
|
||||
translation_key="hostname",
|
||||
name="UPS Hostname",
|
||||
entity_registry_enabled_default=False,
|
||||
),
|
||||
"humidity": SensorEntityDescription(
|
||||
key="humidity",
|
||||
name="UPS Ambient Humidity",
|
||||
translation_key="humidity",
|
||||
native_unit_of_measurement=PERCENTAGE,
|
||||
device_class=SensorDeviceClass.HUMIDITY,
|
||||
state_class=SensorStateClass.MEASUREMENT,
|
||||
),
|
||||
"itemp": SensorEntityDescription(
|
||||
key="itemp",
|
||||
name="UPS Internal Temperature",
|
||||
translation_key="internal_temperature",
|
||||
native_unit_of_measurement=UnitOfTemperature.CELSIUS,
|
||||
device_class=SensorDeviceClass.TEMPERATURE,
|
||||
state_class=SensorStateClass.MEASUREMENT,
|
||||
|
@ -174,29 +155,26 @@ SENSORS: dict[str, SensorEntityDescription] = {
|
|||
"laststest": SensorEntityDescription(
|
||||
key="laststest",
|
||||
translation_key="last_self_test",
|
||||
name="UPS Last Self Test",
|
||||
),
|
||||
"lastxfer": SensorEntityDescription(
|
||||
key="lastxfer",
|
||||
translation_key="last_transfer",
|
||||
name="UPS Last Transfer",
|
||||
entity_registry_enabled_default=False,
|
||||
),
|
||||
"linefail": SensorEntityDescription(
|
||||
key="linefail",
|
||||
translation_key="line_failure",
|
||||
name="UPS Input Voltage Status",
|
||||
),
|
||||
"linefreq": SensorEntityDescription(
|
||||
key="linefreq",
|
||||
name="UPS Line Frequency",
|
||||
translation_key="line_frequency",
|
||||
native_unit_of_measurement=UnitOfFrequency.HERTZ,
|
||||
device_class=SensorDeviceClass.FREQUENCY,
|
||||
state_class=SensorStateClass.MEASUREMENT,
|
||||
),
|
||||
"linev": SensorEntityDescription(
|
||||
key="linev",
|
||||
name="UPS Input Voltage",
|
||||
translation_key="line_voltage",
|
||||
native_unit_of_measurement=UnitOfElectricPotential.VOLT,
|
||||
device_class=SensorDeviceClass.VOLTAGE,
|
||||
state_class=SensorStateClass.MEASUREMENT,
|
||||
|
@ -204,113 +182,104 @@ SENSORS: dict[str, SensorEntityDescription] = {
|
|||
"loadpct": SensorEntityDescription(
|
||||
key="loadpct",
|
||||
translation_key="load_capacity",
|
||||
name="UPS Load",
|
||||
native_unit_of_measurement=PERCENTAGE,
|
||||
state_class=SensorStateClass.MEASUREMENT,
|
||||
),
|
||||
"loadapnt": SensorEntityDescription(
|
||||
key="loadapnt",
|
||||
translation_key="apparent_power",
|
||||
name="UPS Load Apparent Power",
|
||||
native_unit_of_measurement=PERCENTAGE,
|
||||
),
|
||||
"lotrans": SensorEntityDescription(
|
||||
key="lotrans",
|
||||
name="UPS Transfer Low",
|
||||
translation_key="transfer_low",
|
||||
native_unit_of_measurement=UnitOfElectricPotential.VOLT,
|
||||
device_class=SensorDeviceClass.VOLTAGE,
|
||||
),
|
||||
"mandate": SensorEntityDescription(
|
||||
key="mandate",
|
||||
translation_key="manufacture_date",
|
||||
name="UPS Manufacture Date",
|
||||
entity_registry_enabled_default=False,
|
||||
),
|
||||
"masterupd": SensorEntityDescription(
|
||||
key="masterupd",
|
||||
translation_key="master_update",
|
||||
name="UPS Master Update",
|
||||
),
|
||||
"maxlinev": SensorEntityDescription(
|
||||
key="maxlinev",
|
||||
name="UPS Input Voltage High",
|
||||
translation_key="input_voltage_high",
|
||||
native_unit_of_measurement=UnitOfElectricPotential.VOLT,
|
||||
device_class=SensorDeviceClass.VOLTAGE,
|
||||
),
|
||||
"maxtime": SensorEntityDescription(
|
||||
key="maxtime",
|
||||
translation_key="max_time",
|
||||
name="UPS Battery Timeout",
|
||||
),
|
||||
"mbattchg": SensorEntityDescription(
|
||||
key="mbattchg",
|
||||
translation_key="max_battery_charge",
|
||||
name="UPS Battery Shutdown",
|
||||
native_unit_of_measurement=PERCENTAGE,
|
||||
),
|
||||
"minlinev": SensorEntityDescription(
|
||||
key="minlinev",
|
||||
name="UPS Input Voltage Low",
|
||||
translation_key="input_voltage_low",
|
||||
native_unit_of_measurement=UnitOfElectricPotential.VOLT,
|
||||
device_class=SensorDeviceClass.VOLTAGE,
|
||||
),
|
||||
"mintimel": SensorEntityDescription(
|
||||
key="mintimel",
|
||||
translation_key="min_time",
|
||||
name="UPS Shutdown Time",
|
||||
),
|
||||
"model": SensorEntityDescription(
|
||||
key="model",
|
||||
translation_key="model",
|
||||
name="UPS Model",
|
||||
entity_registry_enabled_default=False,
|
||||
),
|
||||
"nombattv": SensorEntityDescription(
|
||||
key="nombattv",
|
||||
name="UPS Battery Nominal Voltage",
|
||||
translation_key="battery_nominal_voltage",
|
||||
native_unit_of_measurement=UnitOfElectricPotential.VOLT,
|
||||
device_class=SensorDeviceClass.VOLTAGE,
|
||||
),
|
||||
"nominv": SensorEntityDescription(
|
||||
key="nominv",
|
||||
name="UPS Nominal Input Voltage",
|
||||
translation_key="nominal_input_voltage",
|
||||
native_unit_of_measurement=UnitOfElectricPotential.VOLT,
|
||||
device_class=SensorDeviceClass.VOLTAGE,
|
||||
),
|
||||
"nomoutv": SensorEntityDescription(
|
||||
key="nomoutv",
|
||||
name="UPS Nominal Output Voltage",
|
||||
translation_key="nominal_output_voltage",
|
||||
native_unit_of_measurement=UnitOfElectricPotential.VOLT,
|
||||
device_class=SensorDeviceClass.VOLTAGE,
|
||||
),
|
||||
"nompower": SensorEntityDescription(
|
||||
key="nompower",
|
||||
name="UPS Nominal Output Power",
|
||||
translation_key="nominal_output_power",
|
||||
native_unit_of_measurement=UnitOfPower.WATT,
|
||||
device_class=SensorDeviceClass.POWER,
|
||||
),
|
||||
"nomapnt": SensorEntityDescription(
|
||||
key="nomapnt",
|
||||
name="UPS Nominal Apparent Power",
|
||||
translation_key="nominal_apparent_power",
|
||||
native_unit_of_measurement=UnitOfApparentPower.VOLT_AMPERE,
|
||||
device_class=SensorDeviceClass.APPARENT_POWER,
|
||||
),
|
||||
"numxfers": SensorEntityDescription(
|
||||
key="numxfers",
|
||||
translation_key="transfer_count",
|
||||
name="UPS Transfer Count",
|
||||
state_class=SensorStateClass.TOTAL_INCREASING,
|
||||
),
|
||||
"outcurnt": SensorEntityDescription(
|
||||
key="outcurnt",
|
||||
name="UPS Output Current",
|
||||
translation_key="output_current",
|
||||
native_unit_of_measurement=UnitOfElectricCurrent.AMPERE,
|
||||
device_class=SensorDeviceClass.CURRENT,
|
||||
state_class=SensorStateClass.MEASUREMENT,
|
||||
),
|
||||
"outputv": SensorEntityDescription(
|
||||
key="outputv",
|
||||
name="UPS Output Voltage",
|
||||
translation_key="output_voltage",
|
||||
native_unit_of_measurement=UnitOfElectricPotential.VOLT,
|
||||
device_class=SensorDeviceClass.VOLTAGE,
|
||||
state_class=SensorStateClass.MEASUREMENT,
|
||||
|
@ -318,108 +287,89 @@ SENSORS: dict[str, SensorEntityDescription] = {
|
|||
"reg1": SensorEntityDescription(
|
||||
key="reg1",
|
||||
translation_key="register_1_fault",
|
||||
name="UPS Register 1 Fault",
|
||||
entity_registry_enabled_default=False,
|
||||
),
|
||||
"reg2": SensorEntityDescription(
|
||||
key="reg2",
|
||||
translation_key="register_2_fault",
|
||||
name="UPS Register 2 Fault",
|
||||
entity_registry_enabled_default=False,
|
||||
),
|
||||
"reg3": SensorEntityDescription(
|
||||
key="reg3",
|
||||
translation_key="register_3_fault",
|
||||
name="UPS Register 3 Fault",
|
||||
entity_registry_enabled_default=False,
|
||||
),
|
||||
"retpct": SensorEntityDescription(
|
||||
key="retpct",
|
||||
translation_key="restore_capacity",
|
||||
name="UPS Restore Requirement",
|
||||
native_unit_of_measurement=PERCENTAGE,
|
||||
),
|
||||
"selftest": SensorEntityDescription(
|
||||
key="selftest",
|
||||
translation_key="self_test_result",
|
||||
name="UPS Self Test result",
|
||||
),
|
||||
"sense": SensorEntityDescription(
|
||||
key="sense",
|
||||
translation_key="sensitivity",
|
||||
name="UPS Sensitivity",
|
||||
entity_registry_enabled_default=False,
|
||||
),
|
||||
"serialno": SensorEntityDescription(
|
||||
key="serialno",
|
||||
translation_key="serial_number",
|
||||
name="UPS Serial Number",
|
||||
entity_registry_enabled_default=False,
|
||||
),
|
||||
"starttime": SensorEntityDescription(
|
||||
key="starttime",
|
||||
translation_key="startup_time",
|
||||
name="UPS Startup Time",
|
||||
),
|
||||
"statflag": SensorEntityDescription(
|
||||
key="statflag",
|
||||
translation_key="online_status",
|
||||
name="UPS Status Flag",
|
||||
entity_registry_enabled_default=False,
|
||||
),
|
||||
"status": SensorEntityDescription(
|
||||
key="status",
|
||||
translation_key="status",
|
||||
name="UPS Status",
|
||||
),
|
||||
"stesti": SensorEntityDescription(
|
||||
key="stesti",
|
||||
translation_key="self_test_interval",
|
||||
name="UPS Self Test Interval",
|
||||
),
|
||||
"timeleft": SensorEntityDescription(
|
||||
key="timeleft",
|
||||
translation_key="time_left",
|
||||
name="UPS Time Left",
|
||||
state_class=SensorStateClass.MEASUREMENT,
|
||||
),
|
||||
"tonbatt": SensorEntityDescription(
|
||||
key="tonbatt",
|
||||
translation_key="time_on_battery",
|
||||
name="UPS Time on Battery",
|
||||
state_class=SensorStateClass.TOTAL_INCREASING,
|
||||
),
|
||||
"upsmode": SensorEntityDescription(
|
||||
key="upsmode",
|
||||
translation_key="ups_mode",
|
||||
name="UPS Mode",
|
||||
),
|
||||
"upsname": SensorEntityDescription(
|
||||
key="upsname",
|
||||
translation_key="ups_name",
|
||||
name="UPS Name",
|
||||
entity_registry_enabled_default=False,
|
||||
),
|
||||
"version": SensorEntityDescription(
|
||||
key="version",
|
||||
translation_key="version",
|
||||
name="UPS Daemon Info",
|
||||
entity_registry_enabled_default=False,
|
||||
),
|
||||
"xoffbat": SensorEntityDescription(
|
||||
key="xoffbat",
|
||||
translation_key="transfer_from_battery",
|
||||
name="UPS Transfer from Battery",
|
||||
),
|
||||
"xoffbatt": SensorEntityDescription(
|
||||
key="xoffbatt",
|
||||
translation_key="transfer_from_battery",
|
||||
name="UPS Transfer from Battery",
|
||||
),
|
||||
"xonbatt": SensorEntityDescription(
|
||||
key="xonbatt",
|
||||
translation_key="transfer_to_battery",
|
||||
name="UPS Transfer to Battery",
|
||||
),
|
||||
}
|
||||
|
||||
|
@ -486,6 +436,8 @@ def infer_unit(value: str) -> tuple[str, str | None]:
|
|||
class APCUPSdSensor(CoordinatorEntity[APCUPSdCoordinator], SensorEntity):
|
||||
"""Representation of a sensor entity for APCUPSd status values."""
|
||||
|
||||
_attr_has_entity_name = True
|
||||
|
||||
def __init__(
|
||||
self,
|
||||
coordinator: APCUPSdCoordinator,
|
||||
|
|
|
@ -16,5 +16,209 @@
|
|||
"description": "Enter the host and port on which the apcupsd NIS is being served."
|
||||
}
|
||||
}
|
||||
},
|
||||
"entity": {
|
||||
"binary_sensor": {
|
||||
"online_status": {
|
||||
"name": "Online status"
|
||||
}
|
||||
},
|
||||
"sensor": {
|
||||
"alarm_delay": {
|
||||
"name": "Alarm delay"
|
||||
},
|
||||
"ambient_temperature": {
|
||||
"name": "Ambient temperature"
|
||||
},
|
||||
"apc_status": {
|
||||
"name": "Status data"
|
||||
},
|
||||
"apc_model": {
|
||||
"name": "Model"
|
||||
},
|
||||
"bad_batteries": {
|
||||
"name": "Bad batteries"
|
||||
},
|
||||
"battery_replacement_date": {
|
||||
"name": "Battery replaced"
|
||||
},
|
||||
"battery_status": {
|
||||
"name": "Battery status"
|
||||
},
|
||||
"battery_voltage": {
|
||||
"name": "Battery voltage"
|
||||
},
|
||||
"cable_type": {
|
||||
"name": "Cable type"
|
||||
},
|
||||
"total_time_on_battery": {
|
||||
"name": "Total time on battery"
|
||||
},
|
||||
"date": {
|
||||
"name": "Status date"
|
||||
},
|
||||
"dip_switch_settings": {
|
||||
"name": "Dip switch settings"
|
||||
},
|
||||
"low_battery_signal": {
|
||||
"name": "Low battery signal"
|
||||
},
|
||||
"driver": {
|
||||
"name": "Driver"
|
||||
},
|
||||
"shutdown_delay": {
|
||||
"name": "Shutdown delay"
|
||||
},
|
||||
"wake_delay": {
|
||||
"name": "Wake delay"
|
||||
},
|
||||
"date_and_time": {
|
||||
"name": "Date and time"
|
||||
},
|
||||
"external_batteries": {
|
||||
"name": "External batteries"
|
||||
},
|
||||
"firmware_version": {
|
||||
"name": "Firmware version"
|
||||
},
|
||||
"transfer_high": {
|
||||
"name": "Transfer high"
|
||||
},
|
||||
"hostname": {
|
||||
"name": "Hostname"
|
||||
},
|
||||
"humidity": {
|
||||
"name": "Ambient humidity"
|
||||
},
|
||||
"internal_temperature": {
|
||||
"name": "Internal temperature"
|
||||
},
|
||||
"last_self_test": {
|
||||
"name": "Last self test"
|
||||
},
|
||||
"last_transfer": {
|
||||
"name": "Last transfer"
|
||||
},
|
||||
"line_failure": {
|
||||
"name": "Input voltage status"
|
||||
},
|
||||
"line_frequency": {
|
||||
"name": "Line frequency"
|
||||
},
|
||||
"line_voltage": {
|
||||
"name": "Input voltage"
|
||||
},
|
||||
"load_capacity": {
|
||||
"name": "Load"
|
||||
},
|
||||
"apparent_power": {
|
||||
"name": "Load apparent power"
|
||||
},
|
||||
"transfer_low": {
|
||||
"name": "Transfer low"
|
||||
},
|
||||
"manufacture_date": {
|
||||
"name": "Manufacture date"
|
||||
},
|
||||
"master_update": {
|
||||
"name": "Master update"
|
||||
},
|
||||
"input_voltage_high": {
|
||||
"name": "Input voltage high"
|
||||
},
|
||||
"max_time": {
|
||||
"name": "Battery timeout"
|
||||
},
|
||||
"max_battery_charge": {
|
||||
"name": "Battery shutdown"
|
||||
},
|
||||
"input_voltage_low": {
|
||||
"name": "Input voltage low"
|
||||
},
|
||||
"min_time": {
|
||||
"name": "Shutdown time"
|
||||
},
|
||||
"model": {
|
||||
"name": "Model"
|
||||
},
|
||||
"battery_nominal_voltage": {
|
||||
"name": "Battery nominal voltage"
|
||||
},
|
||||
"nominal_input_voltage": {
|
||||
"name": "Nominal input voltage"
|
||||
},
|
||||
"nominal_output_voltage": {
|
||||
"name": "Nominal output voltage"
|
||||
},
|
||||
"nominal_output_power": {
|
||||
"name": "Nominal output power"
|
||||
},
|
||||
"nominal_apparent_power": {
|
||||
"name": "Nominal apparent power"
|
||||
},
|
||||
"transfer_count": {
|
||||
"name": "Transfer count"
|
||||
},
|
||||
"output_current": {
|
||||
"name": "Output current"
|
||||
},
|
||||
"output_voltage": {
|
||||
"name": "Output voltage"
|
||||
},
|
||||
"register_1_fault": {
|
||||
"name": "Register 1 fault"
|
||||
},
|
||||
"register_2_fault": {
|
||||
"name": "Register 2 fault"
|
||||
},
|
||||
"register_3_fault": {
|
||||
"name": "Register 3 fault"
|
||||
},
|
||||
"restore_capacity": {
|
||||
"name": "Restore requirement"
|
||||
},
|
||||
"self_test_result": {
|
||||
"name": "Self test result"
|
||||
},
|
||||
"sensitivity": {
|
||||
"name": "Sensitivity"
|
||||
},
|
||||
"serial_number": {
|
||||
"name": "Serial number"
|
||||
},
|
||||
"startup_time": {
|
||||
"name": "Startup time"
|
||||
},
|
||||
"online_status": {
|
||||
"name": "Status flag"
|
||||
},
|
||||
"status": {
|
||||
"name": "Status"
|
||||
},
|
||||
"self_test_interval": {
|
||||
"name": "Self test interval"
|
||||
},
|
||||
"time_left": {
|
||||
"name": "Time left"
|
||||
},
|
||||
"time_on_battery": {
|
||||
"name": "Time on battery"
|
||||
},
|
||||
"ups_mode": {
|
||||
"name": "Mode"
|
||||
},
|
||||
"ups_name": {
|
||||
"name": "Name"
|
||||
},
|
||||
"version": {
|
||||
"name": "Daemon version"
|
||||
},
|
||||
"transfer_from_battery": {
|
||||
"name": "Transfer from battery"
|
||||
},
|
||||
"transfer_to_battery": {
|
||||
"name": "Transfer to battery"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -2,6 +2,7 @@
|
|||
|
||||
from homeassistant.core import HomeAssistant
|
||||
from homeassistant.helpers import entity_registry as er
|
||||
from homeassistant.util import slugify
|
||||
|
||||
from . import MOCK_STATUS, async_init_integration
|
||||
|
||||
|
@ -12,12 +13,13 @@ async def test_binary_sensor(
|
|||
"""Test states of binary sensor."""
|
||||
await async_init_integration(hass, status=MOCK_STATUS)
|
||||
|
||||
state = hass.states.get("binary_sensor.ups_online_status")
|
||||
device_slug, serialno = slugify(MOCK_STATUS["UPSNAME"]), MOCK_STATUS["SERIALNO"]
|
||||
state = hass.states.get(f"binary_sensor.{device_slug}_online_status")
|
||||
assert state
|
||||
assert state.state == "on"
|
||||
entry = entity_registry.async_get("binary_sensor.ups_online_status")
|
||||
entry = entity_registry.async_get(f"binary_sensor.{device_slug}_online_status")
|
||||
assert entry
|
||||
assert entry.unique_id == "XXXXXXXXXXXX_statflag"
|
||||
assert entry.unique_id == f"{serialno}_statflag"
|
||||
|
||||
|
||||
async def test_no_binary_sensor(hass: HomeAssistant) -> None:
|
||||
|
@ -26,5 +28,6 @@ async def test_no_binary_sensor(hass: HomeAssistant) -> None:
|
|||
status.pop("STATFLAG")
|
||||
await async_init_integration(hass, status=status)
|
||||
|
||||
state = hass.states.get("binary_sensor.ups_online_status")
|
||||
device_slug = slugify(MOCK_STATUS["UPSNAME"])
|
||||
state = hass.states.get(f"binary_sensor.{device_slug}_online_status")
|
||||
assert state is None
|
||||
|
|
|
@ -12,23 +12,41 @@ from homeassistant.config_entries import SOURCE_USER, ConfigEntryState
|
|||
from homeassistant.const import STATE_UNAVAILABLE
|
||||
from homeassistant.core import HomeAssistant
|
||||
from homeassistant.helpers import device_registry as dr
|
||||
from homeassistant.util import utcnow
|
||||
from homeassistant.util import slugify, utcnow
|
||||
|
||||
from . import CONF_DATA, MOCK_MINIMAL_STATUS, MOCK_STATUS, async_init_integration
|
||||
|
||||
from tests.common import MockConfigEntry, async_fire_time_changed
|
||||
|
||||
|
||||
@pytest.mark.parametrize("status", (MOCK_STATUS, MOCK_MINIMAL_STATUS))
|
||||
@pytest.mark.parametrize(
|
||||
"status",
|
||||
(
|
||||
# Contains "SERIALNO" and "UPSNAME" fields.
|
||||
# We should create devices for the entities and prefix their IDs with "MyUPS".
|
||||
MOCK_STATUS,
|
||||
# Contains "SERIALNO" but no "UPSNAME" field.
|
||||
# We should create devices for the entities and prefix their IDs with default "APC UPS".
|
||||
MOCK_MINIMAL_STATUS | {"SERIALNO": "XXXX"},
|
||||
# Does not contain either "SERIALNO" field.
|
||||
# We should _not_ create devices for the entities and their IDs will not have prefixes.
|
||||
MOCK_MINIMAL_STATUS,
|
||||
),
|
||||
)
|
||||
async def test_async_setup_entry(hass: HomeAssistant, status: OrderedDict) -> None:
|
||||
"""Test a successful setup entry."""
|
||||
# Minimal status does not contain "SERIALNO" field, which is used to determine the
|
||||
# unique ID of this integration. But, the integration should work fine without it.
|
||||
# In such a case, the device will not be added either
|
||||
await async_init_integration(hass, status=status)
|
||||
|
||||
prefix = ""
|
||||
if "SERIALNO" in status:
|
||||
prefix = slugify(status.get("UPSNAME", "APC UPS")) + "_"
|
||||
|
||||
# Verify successful setup by querying the status sensor.
|
||||
state = hass.states.get("binary_sensor.ups_online_status")
|
||||
assert state is not None
|
||||
state = hass.states.get(f"binary_sensor.{prefix}online_status")
|
||||
assert state
|
||||
assert state.state != STATE_UNAVAILABLE
|
||||
assert state.state == "on"
|
||||
|
||||
|
@ -93,12 +111,32 @@ async def test_multiple_integrations(hass: HomeAssistant) -> None:
|
|||
assert len(hass.config_entries.async_entries(DOMAIN)) == 2
|
||||
assert all(entry.state is ConfigEntryState.LOADED for entry in entries)
|
||||
|
||||
state1 = hass.states.get("sensor.ups_load")
|
||||
state2 = hass.states.get("sensor.ups_load_2")
|
||||
# Since the two UPS device names are the same, we will have to add a "_2" suffix.
|
||||
device_slug = slugify(MOCK_STATUS["UPSNAME"])
|
||||
state1 = hass.states.get(f"sensor.{device_slug}_load")
|
||||
state2 = hass.states.get(f"sensor.{device_slug}_load_2")
|
||||
assert state1 is not None and state2 is not None
|
||||
assert state1.state != state2.state
|
||||
|
||||
|
||||
async def test_multiple_integrations_different_devices(hass: HomeAssistant) -> None:
|
||||
"""Test successful setup for multiple entries with different device names."""
|
||||
status1 = MOCK_STATUS | {"SERIALNO": "XXXXX1", "UPSNAME": "MyUPS1"}
|
||||
status2 = MOCK_STATUS | {"SERIALNO": "XXXXX2", "UPSNAME": "MyUPS2"}
|
||||
entries = (
|
||||
await async_init_integration(hass, host="test1", status=status1),
|
||||
await async_init_integration(hass, host="test2", status=status2),
|
||||
)
|
||||
|
||||
assert len(hass.config_entries.async_entries(DOMAIN)) == 2
|
||||
assert all(entry.state is ConfigEntryState.LOADED for entry in entries)
|
||||
|
||||
# The device names are different, so they are prefixed differently.
|
||||
state1 = hass.states.get("sensor.myups1_load")
|
||||
state2 = hass.states.get("sensor.myups2_load")
|
||||
assert state1 is not None and state2 is not None
|
||||
|
||||
|
||||
@pytest.mark.parametrize(
|
||||
"error",
|
||||
(OSError(), asyncio.IncompleteReadError(partial=b"", expected=0)),
|
||||
|
@ -154,7 +192,8 @@ async def test_availability(hass: HomeAssistant) -> None:
|
|||
"""Ensure that we mark the entity's availability properly when network is down / back up."""
|
||||
await async_init_integration(hass)
|
||||
|
||||
state = hass.states.get("sensor.ups_load")
|
||||
device_slug = slugify(MOCK_STATUS["UPSNAME"])
|
||||
state = hass.states.get(f"sensor.{device_slug}_load")
|
||||
assert state
|
||||
assert state.state != STATE_UNAVAILABLE
|
||||
assert pytest.approx(float(state.state)) == 14.0
|
||||
|
@ -167,7 +206,7 @@ async def test_availability(hass: HomeAssistant) -> None:
|
|||
await hass.async_block_till_done()
|
||||
|
||||
# Sensors should be marked as unavailable.
|
||||
state = hass.states.get("sensor.ups_load")
|
||||
state = hass.states.get(f"sensor.{device_slug}_load")
|
||||
assert state
|
||||
assert state.state == STATE_UNAVAILABLE
|
||||
|
||||
|
@ -179,7 +218,7 @@ async def test_availability(hass: HomeAssistant) -> None:
|
|||
await hass.async_block_till_done()
|
||||
|
||||
# Sensors should be online now with the new value.
|
||||
state = hass.states.get("sensor.ups_load")
|
||||
state = hass.states.get(f"sensor.{device_slug}_load")
|
||||
assert state
|
||||
assert state.state != STATE_UNAVAILABLE
|
||||
assert pytest.approx(float(state.state)) == 15.0
|
||||
|
|
|
@ -22,6 +22,7 @@ from homeassistant.const import (
|
|||
from homeassistant.core import HomeAssistant
|
||||
from homeassistant.helpers import entity_registry as er
|
||||
from homeassistant.setup import async_setup_component
|
||||
from homeassistant.util import slugify
|
||||
from homeassistant.util.dt import utcnow
|
||||
|
||||
from . import MOCK_STATUS, async_init_integration
|
||||
|
@ -32,17 +33,18 @@ from tests.common import async_fire_time_changed
|
|||
async def test_sensor(hass: HomeAssistant, entity_registry: er.EntityRegistry) -> None:
|
||||
"""Test states of sensor."""
|
||||
await async_init_integration(hass, status=MOCK_STATUS)
|
||||
device_slug, serialno = slugify(MOCK_STATUS["UPSNAME"]), MOCK_STATUS["SERIALNO"]
|
||||
|
||||
# Test a representative string sensor.
|
||||
state = hass.states.get("sensor.ups_mode")
|
||||
state = hass.states.get(f"sensor.{device_slug}_mode")
|
||||
assert state
|
||||
assert state.state == "Stand Alone"
|
||||
entry = entity_registry.async_get("sensor.ups_mode")
|
||||
entry = entity_registry.async_get(f"sensor.{device_slug}_mode")
|
||||
assert entry
|
||||
assert entry.unique_id == "XXXXXXXXXXXX_upsmode"
|
||||
assert entry.unique_id == f"{serialno}_upsmode"
|
||||
|
||||
# Test two representative voltage sensors.
|
||||
state = hass.states.get("sensor.ups_input_voltage")
|
||||
state = hass.states.get(f"sensor.{device_slug}_input_voltage")
|
||||
assert state
|
||||
assert state.state == "124.0"
|
||||
assert (
|
||||
|
@ -50,11 +52,11 @@ async def test_sensor(hass: HomeAssistant, entity_registry: er.EntityRegistry) -
|
|||
)
|
||||
assert state.attributes.get(ATTR_STATE_CLASS) == SensorStateClass.MEASUREMENT
|
||||
assert state.attributes.get(ATTR_DEVICE_CLASS) == SensorDeviceClass.VOLTAGE
|
||||
entry = entity_registry.async_get("sensor.ups_input_voltage")
|
||||
entry = entity_registry.async_get(f"sensor.{device_slug}_input_voltage")
|
||||
assert entry
|
||||
assert entry.unique_id == "XXXXXXXXXXXX_linev"
|
||||
assert entry.unique_id == f"{serialno}_linev"
|
||||
|
||||
state = hass.states.get("sensor.ups_battery_voltage")
|
||||
state = hass.states.get(f"sensor.{device_slug}_battery_voltage")
|
||||
assert state
|
||||
assert state.state == "13.7"
|
||||
assert (
|
||||
|
@ -62,38 +64,59 @@ async def test_sensor(hass: HomeAssistant, entity_registry: er.EntityRegistry) -
|
|||
)
|
||||
assert state.attributes.get(ATTR_STATE_CLASS) == SensorStateClass.MEASUREMENT
|
||||
assert state.attributes.get(ATTR_DEVICE_CLASS) == SensorDeviceClass.VOLTAGE
|
||||
entry = entity_registry.async_get("sensor.ups_battery_voltage")
|
||||
entry = entity_registry.async_get(f"sensor.{device_slug}_battery_voltage")
|
||||
assert entry
|
||||
assert entry.unique_id == "XXXXXXXXXXXX_battv"
|
||||
assert entry.unique_id == f"{serialno}_battv"
|
||||
|
||||
# test a representative time sensor.
|
||||
state = hass.states.get("sensor.ups_self_test_interval")
|
||||
# Test a representative time sensor.
|
||||
state = hass.states.get(f"sensor.{device_slug}_self_test_interval")
|
||||
assert state
|
||||
assert state.state == "7"
|
||||
assert state.attributes.get(ATTR_UNIT_OF_MEASUREMENT) == UnitOfTime.DAYS
|
||||
entry = entity_registry.async_get("sensor.ups_self_test_interval")
|
||||
entry = entity_registry.async_get(f"sensor.{device_slug}_self_test_interval")
|
||||
assert entry
|
||||
assert entry.unique_id == "XXXXXXXXXXXX_stesti"
|
||||
assert entry.unique_id == f"{serialno}_stesti"
|
||||
|
||||
# Test a representative percentage sensor.
|
||||
state = hass.states.get("sensor.ups_load")
|
||||
state = hass.states.get(f"sensor.{device_slug}_load")
|
||||
assert state
|
||||
assert state.state == "14.0"
|
||||
assert state.attributes.get(ATTR_UNIT_OF_MEASUREMENT) == PERCENTAGE
|
||||
assert state.attributes.get(ATTR_STATE_CLASS) == SensorStateClass.MEASUREMENT
|
||||
entry = entity_registry.async_get("sensor.ups_load")
|
||||
entry = entity_registry.async_get(f"sensor.{device_slug}_load")
|
||||
assert entry
|
||||
assert entry.unique_id == "XXXXXXXXXXXX_loadpct"
|
||||
assert entry.unique_id == f"{serialno}_loadpct"
|
||||
|
||||
# Test a representative wattage sensor.
|
||||
state = hass.states.get("sensor.ups_nominal_output_power")
|
||||
state = hass.states.get(f"sensor.{device_slug}_nominal_output_power")
|
||||
assert state
|
||||
assert state.state == "330"
|
||||
assert state.attributes.get(ATTR_UNIT_OF_MEASUREMENT) == UnitOfPower.WATT
|
||||
assert state.attributes.get(ATTR_DEVICE_CLASS) == SensorDeviceClass.POWER
|
||||
entry = entity_registry.async_get("sensor.ups_nominal_output_power")
|
||||
entry = entity_registry.async_get(f"sensor.{device_slug}_nominal_output_power")
|
||||
assert entry
|
||||
assert entry.unique_id == "XXXXXXXXXXXX_nompower"
|
||||
assert entry.unique_id == f"{serialno}_nompower"
|
||||
|
||||
|
||||
async def test_sensor_name(hass: HomeAssistant) -> None:
|
||||
"""Test if sensor name follows the recommended entity naming scheme.
|
||||
|
||||
See https://developers.home-assistant.io/docs/core/entity/#entity-naming for more details.
|
||||
"""
|
||||
await async_init_integration(hass, status=MOCK_STATUS)
|
||||
|
||||
all_states = hass.states.async_all()
|
||||
assert len(all_states) != 0
|
||||
|
||||
device_name = MOCK_STATUS["UPSNAME"]
|
||||
for state in all_states:
|
||||
# Friendly name must start with the device name.
|
||||
friendly_name = state.name
|
||||
assert friendly_name.startswith(device_name)
|
||||
|
||||
# Entity names should start with a capital letter, the rest of the words are lower case.
|
||||
entity_name = friendly_name.removeprefix(device_name).strip()
|
||||
assert entity_name == entity_name.capitalize()
|
||||
|
||||
|
||||
async def test_sensor_disabled(
|
||||
|
@ -102,10 +125,11 @@ async def test_sensor_disabled(
|
|||
"""Test sensor disabled by default."""
|
||||
await async_init_integration(hass)
|
||||
|
||||
device_slug, serialno = slugify(MOCK_STATUS["UPSNAME"]), MOCK_STATUS["SERIALNO"]
|
||||
# Test a representative integration-disabled sensor.
|
||||
entry = entity_registry.async_get("sensor.ups_model")
|
||||
entry = entity_registry.async_get(f"sensor.{device_slug}_model")
|
||||
assert entry.disabled
|
||||
assert entry.unique_id == "XXXXXXXXXXXX_model"
|
||||
assert entry.unique_id == f"{serialno}_model"
|
||||
assert entry.disabled_by is er.RegistryEntryDisabler.INTEGRATION
|
||||
|
||||
# Test enabling entity.
|
||||
|
@ -121,7 +145,8 @@ async def test_state_update(hass: HomeAssistant) -> None:
|
|||
"""Ensure the sensor state changes after updating the data."""
|
||||
await async_init_integration(hass)
|
||||
|
||||
state = hass.states.get("sensor.ups_load")
|
||||
device_slug = slugify(MOCK_STATUS["UPSNAME"])
|
||||
state = hass.states.get(f"sensor.{device_slug}_load")
|
||||
assert state
|
||||
assert state.state != STATE_UNAVAILABLE
|
||||
assert state.state == "14.0"
|
||||
|
@ -132,7 +157,7 @@ async def test_state_update(hass: HomeAssistant) -> None:
|
|||
async_fire_time_changed(hass, future)
|
||||
await hass.async_block_till_done()
|
||||
|
||||
state = hass.states.get("sensor.ups_load")
|
||||
state = hass.states.get(f"sensor.{device_slug}_load")
|
||||
assert state
|
||||
assert state.state != STATE_UNAVAILABLE
|
||||
assert state.state == "15.0"
|
||||
|
@ -142,8 +167,9 @@ async def test_manual_update_entity(hass: HomeAssistant) -> None:
|
|||
"""Test manual update entity via service homeassistant/update_entity."""
|
||||
await async_init_integration(hass)
|
||||
|
||||
device_slug = slugify(MOCK_STATUS["UPSNAME"])
|
||||
# Assert the initial state of sensor.ups_load.
|
||||
state = hass.states.get("sensor.ups_load")
|
||||
state = hass.states.get(f"sensor.{device_slug}_load")
|
||||
assert state
|
||||
assert state.state != STATE_UNAVAILABLE
|
||||
assert state.state == "14.0"
|
||||
|
@ -163,7 +189,12 @@ async def test_manual_update_entity(hass: HomeAssistant) -> None:
|
|||
await hass.services.async_call(
|
||||
"homeassistant",
|
||||
"update_entity",
|
||||
{ATTR_ENTITY_ID: ["sensor.ups_load", "sensor.ups_battery"]},
|
||||
{
|
||||
ATTR_ENTITY_ID: [
|
||||
f"sensor.{device_slug}_load",
|
||||
f"sensor.{device_slug}_battery",
|
||||
]
|
||||
},
|
||||
blocking=True,
|
||||
)
|
||||
# Even if we requested updates for two entities, our integration should smartly
|
||||
|
@ -171,7 +202,7 @@ async def test_manual_update_entity(hass: HomeAssistant) -> None:
|
|||
assert mock_request_status.call_count == 1
|
||||
|
||||
# The new state should be effective.
|
||||
state = hass.states.get("sensor.ups_load")
|
||||
state = hass.states.get(f"sensor.{device_slug}_load")
|
||||
assert state
|
||||
assert state.state != STATE_UNAVAILABLE
|
||||
assert state.state == "15.0"
|
||||
|
@ -184,6 +215,7 @@ async def test_multiple_manual_update_entity(hass: HomeAssistant) -> None:
|
|||
"""
|
||||
await async_init_integration(hass)
|
||||
|
||||
device_slug = slugify(MOCK_STATUS["UPSNAME"])
|
||||
# Setup HASS for calling the update_entity service.
|
||||
await async_setup_component(hass, "homeassistant", {})
|
||||
|
||||
|
@ -196,7 +228,12 @@ async def test_multiple_manual_update_entity(hass: HomeAssistant) -> None:
|
|||
await hass.services.async_call(
|
||||
"homeassistant",
|
||||
"update_entity",
|
||||
{ATTR_ENTITY_ID: ["sensor.ups_load", "sensor.ups_input_voltage"]},
|
||||
{
|
||||
ATTR_ENTITY_ID: [
|
||||
f"sensor.{device_slug}_load",
|
||||
f"sensor.{device_slug}_input_voltage",
|
||||
]
|
||||
},
|
||||
blocking=True,
|
||||
)
|
||||
assert mock_request_status.call_count == 1
|
||||
|
|
Loading…
Add table
Reference in a new issue