diff --git a/homeassistant/components/guardian/__init__.py b/homeassistant/components/guardian/__init__.py index 915746c5ed5..94413c76578 100644 --- a/homeassistant/components/guardian/__init__.py +++ b/homeassistant/components/guardian/__init__.py @@ -11,6 +11,7 @@ from homeassistant.config_entries import ConfigEntry from homeassistant.const import ATTR_ATTRIBUTION, CONF_IP_ADDRESS, CONF_PORT from homeassistant.core import HomeAssistant, callback from homeassistant.helpers.dispatcher import async_dispatcher_send +from homeassistant.helpers.entity import EntityDescription from homeassistant.helpers.update_coordinator import ( CoordinatorEntity, DataUpdateCoordinator, @@ -213,20 +214,13 @@ class GuardianEntity(CoordinatorEntity): """Define a base Guardian entity.""" def __init__( # pylint: disable=super-init-not-called - self, - entry: ConfigEntry, - kind: str, - name: str, - device_class: str | None, - icon: str | None, + self, entry: ConfigEntry, description: EntityDescription ) -> None: """Initialize.""" - self._attr_device_class = device_class self._attr_device_info = {"manufacturer": "Elexa"} self._attr_extra_state_attributes = {ATTR_ATTRIBUTION: "Data provided by Elexa"} - self._attr_icon = icon - self._attr_name = name self._entry = entry + self.entity_description = description @callback def _async_update_from_latest_data(self) -> None: @@ -244,13 +238,10 @@ class PairedSensorEntity(GuardianEntity): self, entry: ConfigEntry, coordinator: DataUpdateCoordinator, - kind: str, - name: str, - device_class: str | None, - icon: str | None, + description: EntityDescription, ) -> None: """Initialize.""" - super().__init__(entry, kind, name, device_class, icon) + super().__init__(entry, description) paired_sensor_uid = coordinator.data["uid"] self._attr_device_info = { @@ -258,9 +249,10 @@ class PairedSensorEntity(GuardianEntity): "name": f"Guardian Paired Sensor {paired_sensor_uid}", "via_device": (DOMAIN, entry.data[CONF_UID]), } - self._attr_name = f"Guardian Paired Sensor {paired_sensor_uid}: {name}" - self._attr_unique_id = f"{paired_sensor_uid}_{kind}" - self._kind = kind + self._attr_name = ( + f"Guardian Paired Sensor {paired_sensor_uid}: {description.name}" + ) + self._attr_unique_id = f"{paired_sensor_uid}_{description.key}" self.coordinator = coordinator async def async_added_to_hass(self) -> None: @@ -275,22 +267,18 @@ class ValveControllerEntity(GuardianEntity): self, entry: ConfigEntry, coordinators: dict[str, DataUpdateCoordinator], - kind: str, - name: str, - device_class: str | None, - icon: str | None, + description: EntityDescription, ) -> None: """Initialize.""" - super().__init__(entry, kind, name, device_class, icon) + super().__init__(entry, description) self._attr_device_info = { "identifiers": {(DOMAIN, entry.data[CONF_UID])}, "name": f"Guardian Valve Controller {entry.data[CONF_UID]}", "model": coordinators[API_SYSTEM_DIAGNOSTICS].data["firmware"], } - self._attr_name = f"Guardian {entry.data[CONF_UID]}: {name}" - self._attr_unique_id = f"{entry.data[CONF_UID]}_{kind}" - self._kind = kind + self._attr_name = f"Guardian {entry.data[CONF_UID]}: {description.name}" + self._attr_unique_id = f"{entry.data[CONF_UID]}_{description.key}" self.coordinators = coordinators @property diff --git a/homeassistant/components/guardian/binary_sensor.py b/homeassistant/components/guardian/binary_sensor.py index 1cbc9f5cede..b420605a0ec 100644 --- a/homeassistant/components/guardian/binary_sensor.py +++ b/homeassistant/components/guardian/binary_sensor.py @@ -6,6 +6,7 @@ from homeassistant.components.binary_sensor import ( DEVICE_CLASS_MOISTURE, DEVICE_CLASS_MOVING, BinarySensorEntity, + BinarySensorEntityDescription, ) from homeassistant.config_entries import ConfigEntry from homeassistant.core import HomeAssistant, callback @@ -31,14 +32,30 @@ SENSOR_KIND_AP_INFO = "ap_enabled" SENSOR_KIND_LEAK_DETECTED = "leak_detected" SENSOR_KIND_MOVED = "moved" -SENSOR_ATTRS_MAP = { - SENSOR_KIND_AP_INFO: ("Onboard AP Enabled", DEVICE_CLASS_CONNECTIVITY), - SENSOR_KIND_LEAK_DETECTED: ("Leak Detected", DEVICE_CLASS_MOISTURE), - SENSOR_KIND_MOVED: ("Recently Moved", DEVICE_CLASS_MOVING), -} +SENSOR_DESCRIPTION_AP_ENABLED = BinarySensorEntityDescription( + key=SENSOR_KIND_AP_INFO, + name="Onboard AP Enabled", + device_class=DEVICE_CLASS_CONNECTIVITY, +) +SENSOR_DESCRIPTION_LEAK_DETECTED = BinarySensorEntityDescription( + key=SENSOR_KIND_LEAK_DETECTED, + name="Leak Detected", + device_class=DEVICE_CLASS_MOISTURE, +) +SENSOR_DESCRIPTION_MOVED = BinarySensorEntityDescription( + key=SENSOR_KIND_MOVED, + name="Recently Moved", + device_class=DEVICE_CLASS_MOVING, +) -PAIRED_SENSOR_SENSORS = [SENSOR_KIND_LEAK_DETECTED, SENSOR_KIND_MOVED] -VALVE_CONTROLLER_SENSORS = [SENSOR_KIND_AP_INFO, SENSOR_KIND_LEAK_DETECTED] +PAIRED_SENSOR_DESCRIPTIONS = ( + SENSOR_DESCRIPTION_LEAK_DETECTED, + SENSOR_DESCRIPTION_MOVED, +) +VALVE_CONTROLLER_DESCRIPTIONS = ( + SENSOR_DESCRIPTION_AP_ENABLED, + SENSOR_DESCRIPTION_LEAK_DETECTED, +) async def async_setup_entry( @@ -53,21 +70,12 @@ async def async_setup_entry( uid ] - entities = [] - for kind in PAIRED_SENSOR_SENSORS: - name, device_class = SENSOR_ATTRS_MAP[kind] - entities.append( - PairedSensorBinarySensor( - entry, - coordinator, - kind, - name, - device_class, - None, - ) - ) - - async_add_entities(entities) + async_add_entities( + [ + PairedSensorBinarySensor(entry, coordinator, description) + for description in PAIRED_SENSOR_DESCRIPTIONS + ] + ) # Handle adding paired sensors after HASS startup: hass.data[DOMAIN][DATA_UNSUB_DISPATCHER_CONNECT][entry.entry_id].append( @@ -78,38 +86,24 @@ async def async_setup_entry( ) ) - sensors: list[PairedSensorBinarySensor | ValveControllerBinarySensor] = [] - # Add all valve controller-specific binary sensors: - for kind in VALVE_CONTROLLER_SENSORS: - name, device_class = SENSOR_ATTRS_MAP[kind] - sensors.append( - ValveControllerBinarySensor( - entry, - hass.data[DOMAIN][DATA_COORDINATOR][entry.entry_id], - kind, - name, - device_class, - None, - ) + sensors: list[PairedSensorBinarySensor | ValveControllerBinarySensor] = [ + ValveControllerBinarySensor( + entry, hass.data[DOMAIN][DATA_COORDINATOR][entry.entry_id], description ) + for description in VALVE_CONTROLLER_DESCRIPTIONS + ] # Add all paired sensor-specific binary sensors: - for coordinator in hass.data[DOMAIN][DATA_COORDINATOR_PAIRED_SENSOR][ - entry.entry_id - ].values(): - for kind in PAIRED_SENSOR_SENSORS: - name, device_class = SENSOR_ATTRS_MAP[kind] - sensors.append( - PairedSensorBinarySensor( - entry, - coordinator, - kind, - name, - device_class, - None, - ) - ) + sensors.extend( + [ + PairedSensorBinarySensor(entry, coordinator, description) + for coordinator in hass.data[DOMAIN][DATA_COORDINATOR_PAIRED_SENSOR][ + entry.entry_id + ].values() + for description in PAIRED_SENSOR_DESCRIPTIONS + ] + ) async_add_entities(sensors) @@ -121,22 +115,19 @@ class PairedSensorBinarySensor(PairedSensorEntity, BinarySensorEntity): self, entry: ConfigEntry, coordinator: DataUpdateCoordinator, - kind: str, - name: str, - device_class: str | None, - icon: str | None, + description: BinarySensorEntityDescription, ) -> None: """Initialize.""" - super().__init__(entry, coordinator, kind, name, device_class, icon) + super().__init__(entry, coordinator, description) self._attr_is_on = True @callback def _async_update_from_latest_data(self) -> None: """Update the entity.""" - if self._kind == SENSOR_KIND_LEAK_DETECTED: + if self.entity_description.key == SENSOR_KIND_LEAK_DETECTED: self._attr_is_on = self.coordinator.data["wet"] - elif self._kind == SENSOR_KIND_MOVED: + elif self.entity_description.key == SENSOR_KIND_MOVED: self._attr_is_on = self.coordinator.data["moved"] @@ -147,27 +138,24 @@ class ValveControllerBinarySensor(ValveControllerEntity, BinarySensorEntity): self, entry: ConfigEntry, coordinators: dict[str, DataUpdateCoordinator], - kind: str, - name: str, - device_class: str | None, - icon: str | None, + description: BinarySensorEntityDescription, ) -> None: """Initialize.""" - super().__init__(entry, coordinators, kind, name, device_class, icon) + super().__init__(entry, coordinators, description) self._attr_is_on = True async def _async_continue_entity_setup(self) -> None: """Add an API listener.""" - if self._kind == SENSOR_KIND_AP_INFO: + if self.entity_description.key == SENSOR_KIND_AP_INFO: self.async_add_coordinator_update_listener(API_WIFI_STATUS) - elif self._kind == SENSOR_KIND_LEAK_DETECTED: + elif self.entity_description.key == SENSOR_KIND_LEAK_DETECTED: self.async_add_coordinator_update_listener(API_SYSTEM_ONBOARD_SENSOR_STATUS) @callback def _async_update_from_latest_data(self) -> None: """Update the entity.""" - if self._kind == SENSOR_KIND_AP_INFO: + if self.entity_description.key == SENSOR_KIND_AP_INFO: self._attr_available = self.coordinators[ API_WIFI_STATUS ].last_update_success @@ -181,7 +169,7 @@ class ValveControllerBinarySensor(ValveControllerEntity, BinarySensorEntity): ) } ) - elif self._kind == SENSOR_KIND_LEAK_DETECTED: + elif self.entity_description.key == SENSOR_KIND_LEAK_DETECTED: self._attr_available = self.coordinators[ API_SYSTEM_ONBOARD_SENSOR_STATUS ].last_update_success diff --git a/homeassistant/components/guardian/sensor.py b/homeassistant/components/guardian/sensor.py index ed3cfedba0e..fb7952669cc 100644 --- a/homeassistant/components/guardian/sensor.py +++ b/homeassistant/components/guardian/sensor.py @@ -1,7 +1,7 @@ """Sensors for the Elexa Guardian integration.""" from __future__ import annotations -from homeassistant.components.sensor import SensorEntity +from homeassistant.components.sensor import SensorEntity, SensorEntityDescription from homeassistant.config_entries import ConfigEntry from homeassistant.const import ( DEVICE_CLASS_BATTERY, @@ -13,7 +13,6 @@ from homeassistant.const import ( from homeassistant.core import HomeAssistant, callback from homeassistant.helpers.dispatcher import async_dispatcher_connect from homeassistant.helpers.entity_platform import AddEntitiesCallback -from homeassistant.helpers.update_coordinator import DataUpdateCoordinator from . import PairedSensorEntity, ValveControllerEntity from .const import ( @@ -31,19 +30,33 @@ SENSOR_KIND_BATTERY = "battery" SENSOR_KIND_TEMPERATURE = "temperature" SENSOR_KIND_UPTIME = "uptime" -SENSOR_ATTRS_MAP = { - SENSOR_KIND_BATTERY: ("Battery", DEVICE_CLASS_BATTERY, None, PERCENTAGE), - SENSOR_KIND_TEMPERATURE: ( - "Temperature", - DEVICE_CLASS_TEMPERATURE, - None, - TEMP_FAHRENHEIT, - ), - SENSOR_KIND_UPTIME: ("Uptime", None, "mdi:timer", TIME_MINUTES), -} +SENSOR_DESCRIPTION_BATTERY = SensorEntityDescription( + key=SENSOR_KIND_BATTERY, + name="Battery", + device_class=DEVICE_CLASS_BATTERY, + native_unit_of_measurement=PERCENTAGE, +) +SENSOR_DESCRIPTION_TEMPERATURE = SensorEntityDescription( + key=SENSOR_KIND_TEMPERATURE, + name="Temperature", + device_class=DEVICE_CLASS_TEMPERATURE, + native_unit_of_measurement=TEMP_FAHRENHEIT, +) +SENSOR_DESCRIPTION_UPTIME = SensorEntityDescription( + key=SENSOR_KIND_UPTIME, + name="Uptime", + icon="mdi:timer", + native_unit_of_measurement=TIME_MINUTES, +) -PAIRED_SENSOR_SENSORS = [SENSOR_KIND_BATTERY, SENSOR_KIND_TEMPERATURE] -VALVE_CONTROLLER_SENSORS = [SENSOR_KIND_TEMPERATURE, SENSOR_KIND_UPTIME] +PAIRED_SENSOR_DESCRIPTIONS = ( + SENSOR_DESCRIPTION_BATTERY, + SENSOR_DESCRIPTION_TEMPERATURE, +) +VALVE_CONTROLLER_DESCRIPTIONS = ( + SENSOR_DESCRIPTION_TEMPERATURE, + SENSOR_DESCRIPTION_UPTIME, +) async def async_setup_entry( @@ -58,16 +71,12 @@ async def async_setup_entry( uid ] - entities = [] - for kind in PAIRED_SENSOR_SENSORS: - name, device_class, icon, unit = SENSOR_ATTRS_MAP[kind] - entities.append( - PairedSensorSensor( - entry, coordinator, kind, name, device_class, icon, unit - ) - ) - - async_add_entities(entities, True) + async_add_entities( + [ + PairedSensorSensor(entry, coordinator, description) + for description in PAIRED_SENSOR_DESCRIPTIONS + ] + ) # Handle adding paired sensors after HASS startup: hass.data[DOMAIN][DATA_UNSUB_DISPATCHER_CONNECT][entry.entry_id].append( @@ -78,34 +87,24 @@ async def async_setup_entry( ) ) - sensors: list[PairedSensorSensor | ValveControllerSensor] = [] - # Add all valve controller-specific binary sensors: - for kind in VALVE_CONTROLLER_SENSORS: - name, device_class, icon, unit = SENSOR_ATTRS_MAP[kind] - sensors.append( - ValveControllerSensor( - entry, - hass.data[DOMAIN][DATA_COORDINATOR][entry.entry_id], - kind, - name, - device_class, - icon, - unit, - ) + sensors: list[PairedSensorSensor | ValveControllerSensor] = [ + ValveControllerSensor( + entry, hass.data[DOMAIN][DATA_COORDINATOR][entry.entry_id], description ) + for description in VALVE_CONTROLLER_DESCRIPTIONS + ] # Add all paired sensor-specific binary sensors: - for coordinator in hass.data[DOMAIN][DATA_COORDINATOR_PAIRED_SENSOR][ - entry.entry_id - ].values(): - for kind in PAIRED_SENSOR_SENSORS: - name, device_class, icon, unit = SENSOR_ATTRS_MAP[kind] - sensors.append( - PairedSensorSensor( - entry, coordinator, kind, name, device_class, icon, unit - ) - ) + sensors.extend( + [ + PairedSensorSensor(entry, coordinator, description) + for coordinator in hass.data[DOMAIN][DATA_COORDINATOR_PAIRED_SENSOR][ + entry.entry_id + ].values() + for description in PAIRED_SENSOR_DESCRIPTIONS + ] + ) async_add_entities(sensors) @@ -113,64 +112,34 @@ async def async_setup_entry( class PairedSensorSensor(PairedSensorEntity, SensorEntity): """Define a binary sensor related to a Guardian valve controller.""" - def __init__( - self, - entry: ConfigEntry, - coordinator: DataUpdateCoordinator, - kind: str, - name: str, - device_class: str | None, - icon: str | None, - unit: str | None, - ) -> None: - """Initialize.""" - super().__init__(entry, coordinator, kind, name, device_class, icon) - - self._attr_native_unit_of_measurement = unit - @callback def _async_update_from_latest_data(self) -> None: """Update the entity.""" - if self._kind == SENSOR_KIND_BATTERY: + if self.entity_description.key == SENSOR_KIND_BATTERY: self._attr_native_value = self.coordinator.data["battery"] - elif self._kind == SENSOR_KIND_TEMPERATURE: + elif self.entity_description.key == SENSOR_KIND_TEMPERATURE: self._attr_native_value = self.coordinator.data["temperature"] class ValveControllerSensor(ValveControllerEntity, SensorEntity): """Define a generic Guardian sensor.""" - def __init__( - self, - entry: ConfigEntry, - coordinators: dict[str, DataUpdateCoordinator], - kind: str, - name: str, - device_class: str | None, - icon: str | None, - unit: str | None, - ) -> None: - """Initialize.""" - super().__init__(entry, coordinators, kind, name, device_class, icon) - - self._attr_native_unit_of_measurement = unit - async def _async_continue_entity_setup(self) -> None: """Register API interest (and related tasks) when the entity is added.""" - if self._kind == SENSOR_KIND_TEMPERATURE: + if self.entity_description.key == SENSOR_KIND_TEMPERATURE: self.async_add_coordinator_update_listener(API_SYSTEM_ONBOARD_SENSOR_STATUS) @callback def _async_update_from_latest_data(self) -> None: """Update the entity.""" - if self._kind == SENSOR_KIND_TEMPERATURE: + if self.entity_description.key == SENSOR_KIND_TEMPERATURE: self._attr_available = self.coordinators[ API_SYSTEM_ONBOARD_SENSOR_STATUS ].last_update_success self._attr_native_value = self.coordinators[ API_SYSTEM_ONBOARD_SENSOR_STATUS ].data["temperature"] - elif self._kind == SENSOR_KIND_UPTIME: + elif self.entity_description.key == SENSOR_KIND_UPTIME: self._attr_available = self.coordinators[ API_SYSTEM_DIAGNOSTICS ].last_update_success diff --git a/homeassistant/components/guardian/switch.py b/homeassistant/components/guardian/switch.py index 7343a1f5c27..9b7db16dd15 100644 --- a/homeassistant/components/guardian/switch.py +++ b/homeassistant/components/guardian/switch.py @@ -7,7 +7,7 @@ from aioguardian import Client from aioguardian.errors import GuardianError import voluptuous as vol -from homeassistant.components.switch import SwitchEntity +from homeassistant.components.switch import SwitchEntity, SwitchEntityDescription from homeassistant.config_entries import ConfigEntry from homeassistant.const import CONF_FILENAME, CONF_PORT, CONF_URL from homeassistant.core import HomeAssistant, callback @@ -39,6 +39,14 @@ SERVICE_RESET_VALVE_DIAGNOSTICS = "reset_valve_diagnostics" SERVICE_UNPAIR_SENSOR = "unpair_sensor" SERVICE_UPGRADE_FIRMWARE = "upgrade_firmware" +SWITCH_KIND_VALVE = "valve" + +SWITCH_DESCRIPTION_VALVE = SwitchEntityDescription( + key=SWITCH_KIND_VALVE, + name="Valve Controller", + icon="mdi:water", +) + async def async_setup_entry( hass: HomeAssistant, entry: ConfigEntry, async_add_entities: AddEntitiesCallback @@ -90,9 +98,7 @@ class ValveControllerSwitch(ValveControllerEntity, SwitchEntity): coordinators: dict[str, DataUpdateCoordinator], ) -> None: """Initialize.""" - super().__init__( - entry, coordinators, "valve", "Valve Controller", None, "mdi:water" - ) + super().__init__(entry, coordinators, SWITCH_DESCRIPTION_VALVE) self._attr_is_on = True self._client = client