From 781f18e0c3fd5f9aa65bdcf10c4e5aca105ac3c6 Mon Sep 17 00:00:00 2001 From: Michael <35783820+mib1185@users.noreply.github.com> Date: Sun, 24 Apr 2022 10:26:34 +0200 Subject: [PATCH] Extract entity base classes into a new module for Synology DSM (#69796) Co-authored-by: J. Nick Koston --- .coveragerc | 1 + .../components/synology_dsm/__init__.py | 112 +--------------- .../components/synology_dsm/binary_sensor.py | 9 +- .../components/synology_dsm/camera.py | 4 +- .../components/synology_dsm/const.py | 16 +-- .../components/synology_dsm/entity.py | 122 ++++++++++++++++++ .../components/synology_dsm/sensor.py | 12 +- .../components/synology_dsm/switch.py | 5 +- .../components/synology_dsm/update.py | 5 +- 9 files changed, 145 insertions(+), 141 deletions(-) create mode 100644 homeassistant/components/synology_dsm/entity.py diff --git a/.coveragerc b/.coveragerc index b26654730d1..140d8cd7349 100644 --- a/.coveragerc +++ b/.coveragerc @@ -1177,6 +1177,7 @@ omit = homeassistant/components/synology_dsm/camera.py homeassistant/components/synology_dsm/diagnostics.py homeassistant/components/synology_dsm/common.py + homeassistant/components/synology_dsm/entity.py homeassistant/components/synology_dsm/sensor.py homeassistant/components/synology_dsm/service.py homeassistant/components/synology_dsm/switch.py diff --git a/homeassistant/components/synology_dsm/__init__.py b/homeassistant/components/synology_dsm/__init__.py index 8e42a2c02ae..1151bf128cc 100644 --- a/homeassistant/components/synology_dsm/__init__.py +++ b/homeassistant/components/synology_dsm/__init__.py @@ -28,12 +28,7 @@ from homeassistant.helpers.device_registry import ( DeviceEntry, async_get_registry as get_dev_reg, ) -from homeassistant.helpers.entity import DeviceInfo -from homeassistant.helpers.update_coordinator import ( - CoordinatorEntity, - DataUpdateCoordinator, - UpdateFailed, -) +from homeassistant.helpers.update_coordinator import DataUpdateCoordinator, UpdateFailed from .common import SynoApi from .const import ( @@ -49,16 +44,12 @@ from .const import ( SYNO_API, SYSTEM_LOADED, UNDO_UPDATE_LISTENER, - SynologyDSMEntityDescription, ) from .service import async_setup_services CONFIG_SCHEMA = cv.removed(DOMAIN, raise_if_present=False) -ATTRIBUTION = "Data provided by Synology" - - _LOGGER = logging.getLogger(__name__) @@ -223,104 +214,3 @@ async def async_unload_entry(hass: HomeAssistant, entry: ConfigEntry) -> bool: async def _async_update_listener(hass: HomeAssistant, entry: ConfigEntry) -> None: """Handle options update.""" await hass.config_entries.async_reload(entry.entry_id) - - -class SynologyDSMBaseEntity( - CoordinatorEntity[DataUpdateCoordinator[dict[str, dict[str, Any]]]] -): - """Representation of a Synology NAS entry.""" - - entity_description: SynologyDSMEntityDescription - unique_id: str - _attr_attribution = ATTRIBUTION - - def __init__( - self, - api: SynoApi, - coordinator: DataUpdateCoordinator[dict[str, dict[str, Any]]], - description: SynologyDSMEntityDescription, - ) -> None: - """Initialize the Synology DSM entity.""" - super().__init__(coordinator) - self.entity_description = description - - self._api = api - self._attr_name = f"{api.network.hostname} {description.name}" - self._attr_unique_id: str = ( - f"{api.information.serial}_{description.api_key}:{description.key}" - ) - self._attr_device_info = DeviceInfo( - identifiers={(DOMAIN, self._api.information.serial)}, - name=self._api.network.hostname, - manufacturer="Synology", - model=self._api.information.model, - sw_version=self._api.information.version_string, - configuration_url=self._api.config_url, - ) - - async def async_added_to_hass(self) -> None: - """Register entity for updates from API.""" - self.async_on_remove( - self._api.subscribe(self.entity_description.api_key, self.unique_id) - ) - await super().async_added_to_hass() - - -class SynologyDSMDeviceEntity(SynologyDSMBaseEntity): - """Representation of a Synology NAS disk or volume entry.""" - - def __init__( - self, - api: SynoApi, - coordinator: DataUpdateCoordinator[dict[str, dict[str, Any]]], - description: SynologyDSMEntityDescription, - device_id: str | None = None, - ) -> None: - """Initialize the Synology DSM disk or volume entity.""" - super().__init__(api, coordinator, description) - self._device_id = device_id - self._device_name: str | None = None - self._device_manufacturer: str | None = None - self._device_model: str | None = None - self._device_firmware: str | None = None - self._device_type = None - - if "volume" in description.key: - volume = self._api.storage.get_volume(self._device_id) - # Volume does not have a name - self._device_name = volume["id"].replace("_", " ").capitalize() - self._device_manufacturer = "Synology" - self._device_model = self._api.information.model - self._device_firmware = self._api.information.version_string - self._device_type = ( - volume["device_type"] - .replace("_", " ") - .replace("raid", "RAID") - .replace("shr", "SHR") - ) - elif "disk" in description.key: - disk = self._api.storage.get_disk(self._device_id) - self._device_name = disk["name"] - self._device_manufacturer = disk["vendor"] - self._device_model = disk["model"].strip() - self._device_firmware = disk["firm"] - self._device_type = disk["diskType"] - - self._attr_name = ( - f"{self._api.network.hostname} ({self._device_name}) {description.name}" - ) - self._attr_unique_id += f"_{self._device_id}" - self._attr_device_info = DeviceInfo( - identifiers={(DOMAIN, f"{self._api.information.serial}_{self._device_id}")}, - name=f"{self._api.network.hostname} ({self._device_name})", - manufacturer=self._device_manufacturer, - model=self._device_model, - sw_version=self._device_firmware, - via_device=(DOMAIN, self._api.information.serial), - configuration_url=self._api.config_url, - ) - - @property - def available(self) -> bool: - """Return True if entity is available.""" - return self._api.storage # type: ignore [no-any-return] diff --git a/homeassistant/components/synology_dsm/binary_sensor.py b/homeassistant/components/synology_dsm/binary_sensor.py index db41b49970d..a5c96575307 100644 --- a/homeassistant/components/synology_dsm/binary_sensor.py +++ b/homeassistant/components/synology_dsm/binary_sensor.py @@ -21,8 +21,13 @@ from homeassistant.helpers.entity import EntityCategory from homeassistant.helpers.entity_platform import AddEntitiesCallback from homeassistant.helpers.update_coordinator import DataUpdateCoordinator -from . import SynoApi, SynologyDSMBaseEntity, SynologyDSMDeviceEntity -from .const import COORDINATOR_CENTRAL, DOMAIN, SYNO_API, SynologyDSMEntityDescription +from . import SynoApi +from .const import COORDINATOR_CENTRAL, DOMAIN, SYNO_API +from .entity import ( + SynologyDSMBaseEntity, + SynologyDSMDeviceEntity, + SynologyDSMEntityDescription, +) @dataclass diff --git a/homeassistant/components/synology_dsm/camera.py b/homeassistant/components/synology_dsm/camera.py index ddf6531cae5..c6d44d8883d 100644 --- a/homeassistant/components/synology_dsm/camera.py +++ b/homeassistant/components/synology_dsm/camera.py @@ -21,15 +21,15 @@ from homeassistant.helpers.entity import DeviceInfo from homeassistant.helpers.entity_platform import AddEntitiesCallback from homeassistant.helpers.update_coordinator import DataUpdateCoordinator -from . import SynoApi, SynologyDSMBaseEntity +from . import SynoApi from .const import ( CONF_SNAPSHOT_QUALITY, COORDINATOR_CAMERAS, DEFAULT_SNAPSHOT_QUALITY, DOMAIN, SYNO_API, - SynologyDSMEntityDescription, ) +from .entity import SynologyDSMBaseEntity, SynologyDSMEntityDescription _LOGGER = logging.getLogger(__name__) diff --git a/homeassistant/components/synology_dsm/const.py b/homeassistant/components/synology_dsm/const.py index e83cae41a2e..1b4e5f0bb36 100644 --- a/homeassistant/components/synology_dsm/const.py +++ b/homeassistant/components/synology_dsm/const.py @@ -1,14 +1,12 @@ """Constants for Synology DSM.""" from __future__ import annotations -from dataclasses import dataclass - from synology_dsm.api.surveillance_station.const import SNAPSHOT_PROFILE_BALANCED from homeassistant.const import Platform -from homeassistant.helpers.entity import EntityDescription DOMAIN = "synology_dsm" +ATTRIBUTION = "Data provided by Synology" PLATFORMS = [ Platform.BINARY_SENSOR, Platform.BUTTON, @@ -52,15 +50,3 @@ SERVICES = [ SERVICE_REBOOT, SERVICE_SHUTDOWN, ] - - -@dataclass -class SynologyDSMRequiredKeysMixin: - """Mixin for required keys.""" - - api_key: str - - -@dataclass -class SynologyDSMEntityDescription(EntityDescription, SynologyDSMRequiredKeysMixin): - """Generic Synology DSM entity description.""" diff --git a/homeassistant/components/synology_dsm/entity.py b/homeassistant/components/synology_dsm/entity.py new file mode 100644 index 00000000000..1404d933020 --- /dev/null +++ b/homeassistant/components/synology_dsm/entity.py @@ -0,0 +1,122 @@ +"""Entities for Synology DSM.""" +from __future__ import annotations + +from dataclasses import dataclass +from typing import Any + +from homeassistant.helpers.entity import DeviceInfo, EntityDescription +from homeassistant.helpers.update_coordinator import ( + CoordinatorEntity, + DataUpdateCoordinator, +) + +from .common import SynoApi +from .const import ATTRIBUTION, DOMAIN + + +@dataclass +class SynologyDSMRequiredKeysMixin: + """Mixin for required keys.""" + + api_key: str + + +@dataclass +class SynologyDSMEntityDescription(EntityDescription, SynologyDSMRequiredKeysMixin): + """Generic Synology DSM entity description.""" + + +class SynologyDSMBaseEntity( + CoordinatorEntity[DataUpdateCoordinator[dict[str, dict[str, Any]]]] +): + """Representation of a Synology NAS entry.""" + + entity_description: SynologyDSMEntityDescription + unique_id: str + _attr_attribution = ATTRIBUTION + + def __init__( + self, + api: SynoApi, + coordinator: DataUpdateCoordinator[dict[str, dict[str, Any]]], + description: SynologyDSMEntityDescription, + ) -> None: + """Initialize the Synology DSM entity.""" + super().__init__(coordinator) + self.entity_description = description + + self._api = api + self._attr_name = f"{api.network.hostname} {description.name}" + self._attr_unique_id: str = ( + f"{api.information.serial}_{description.api_key}:{description.key}" + ) + self._attr_device_info = DeviceInfo( + identifiers={(DOMAIN, self._api.information.serial)}, + name=self._api.network.hostname, + manufacturer="Synology", + model=self._api.information.model, + sw_version=self._api.information.version_string, + configuration_url=self._api.config_url, + ) + + async def async_added_to_hass(self) -> None: + """Register entity for updates from API.""" + self.async_on_remove( + self._api.subscribe(self.entity_description.api_key, self.unique_id) + ) + await super().async_added_to_hass() + + +class SynologyDSMDeviceEntity(SynologyDSMBaseEntity): + """Representation of a Synology NAS disk or volume entry.""" + + def __init__( + self, + api: SynoApi, + coordinator: DataUpdateCoordinator[dict[str, dict[str, Any]]], + description: SynologyDSMEntityDescription, + device_id: str | None = None, + ) -> None: + """Initialize the Synology DSM disk or volume entity.""" + super().__init__(api, coordinator, description) + self._device_id = device_id + self._device_name: str | None = None + self._device_manufacturer: str | None = None + self._device_model: str | None = None + self._device_firmware: str | None = None + self._device_type = None + + if "volume" in description.key: + volume = self._api.storage.get_volume(self._device_id) + # Volume does not have a name + self._device_name = volume["id"].replace("_", " ").capitalize() + self._device_manufacturer = "Synology" + self._device_model = self._api.information.model + self._device_firmware = self._api.information.version_string + self._device_type = ( + volume["device_type"] + .replace("_", " ") + .replace("raid", "RAID") + .replace("shr", "SHR") + ) + elif "disk" in description.key: + disk = self._api.storage.get_disk(self._device_id) + self._device_name = disk["name"] + self._device_manufacturer = disk["vendor"] + self._device_model = disk["model"].strip() + self._device_firmware = disk["firm"] + self._device_type = disk["diskType"] + + self._attr_name = ( + f"{self._api.network.hostname} ({self._device_name}) {description.name}" + ) + self._attr_unique_id += f"_{self._device_id}" + self._attr_device_info = DeviceInfo( + identifiers={(DOMAIN, f"{self._api.information.serial}_{self._device_id}")}, + name=f"{self._api.network.hostname} ({self._device_name})", + manufacturer=self._device_manufacturer, + model=self._device_model, + sw_version=self._device_firmware, + via_device=(DOMAIN, self._api.information.serial), + configuration_url=self._api.config_url, + ) diff --git a/homeassistant/components/synology_dsm/sensor.py b/homeassistant/components/synology_dsm/sensor.py index 4dec3b8b67c..6015dc689b7 100644 --- a/homeassistant/components/synology_dsm/sensor.py +++ b/homeassistant/components/synology_dsm/sensor.py @@ -30,13 +30,11 @@ from homeassistant.helpers.entity_platform import AddEntitiesCallback from homeassistant.helpers.update_coordinator import DataUpdateCoordinator from homeassistant.util.dt import utcnow -from . import SynoApi, SynologyDSMBaseEntity, SynologyDSMDeviceEntity -from .const import ( - CONF_VOLUMES, - COORDINATOR_CENTRAL, - DOMAIN, - ENTITY_UNIT_LOAD, - SYNO_API, +from . import SynoApi +from .const import CONF_VOLUMES, COORDINATOR_CENTRAL, DOMAIN, ENTITY_UNIT_LOAD, SYNO_API +from .entity import ( + SynologyDSMBaseEntity, + SynologyDSMDeviceEntity, SynologyDSMEntityDescription, ) diff --git a/homeassistant/components/synology_dsm/switch.py b/homeassistant/components/synology_dsm/switch.py index bef88da166c..eb61b8334ca 100644 --- a/homeassistant/components/synology_dsm/switch.py +++ b/homeassistant/components/synology_dsm/switch.py @@ -14,8 +14,9 @@ from homeassistant.helpers.entity import DeviceInfo from homeassistant.helpers.entity_platform import AddEntitiesCallback from homeassistant.helpers.update_coordinator import DataUpdateCoordinator -from . import SynoApi, SynologyDSMBaseEntity -from .const import COORDINATOR_SWITCHES, DOMAIN, SYNO_API, SynologyDSMEntityDescription +from . import SynoApi +from .const import COORDINATOR_SWITCHES, DOMAIN, SYNO_API +from .entity import SynologyDSMBaseEntity, SynologyDSMEntityDescription _LOGGER = logging.getLogger(__name__) diff --git a/homeassistant/components/synology_dsm/update.py b/homeassistant/components/synology_dsm/update.py index 836468d6f50..48b3eeca2ed 100644 --- a/homeassistant/components/synology_dsm/update.py +++ b/homeassistant/components/synology_dsm/update.py @@ -13,8 +13,9 @@ from homeassistant.core import HomeAssistant from homeassistant.helpers.entity import EntityCategory from homeassistant.helpers.entity_platform import AddEntitiesCallback -from . import SynoApi, SynologyDSMBaseEntity -from .const import COORDINATOR_CENTRAL, DOMAIN, SYNO_API, SynologyDSMEntityDescription +from . import SynoApi +from .const import COORDINATOR_CENTRAL, DOMAIN, SYNO_API +from .entity import SynologyDSMBaseEntity, SynologyDSMEntityDescription @dataclass