Use EntityDescription - guardian (#55118)

This commit is contained in:
Aaron Bach 2021-08-25 02:34:02 -06:00 committed by GitHub
parent e2b1122eec
commit bf6d549910
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
4 changed files with 129 additions and 178 deletions

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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