core/homeassistant/components/synology_dsm/entity.py

135 lines
4.6 KiB
Python

"""Entities for Synology DSM."""
from __future__ import annotations
from dataclasses import dataclass
from typing import Any, TypeVar
from homeassistant.helpers.device_registry import DeviceInfo
from homeassistant.helpers.entity import EntityDescription
from homeassistant.helpers.update_coordinator import CoordinatorEntity
from .common import SynoApi
from .const import ATTRIBUTION, DOMAIN
from .coordinator import (
SynologyDSMCentralUpdateCoordinator,
SynologyDSMUpdateCoordinator,
)
_CoordinatorT = TypeVar("_CoordinatorT", bound=SynologyDSMUpdateCoordinator[Any])
@dataclass(frozen=True, kw_only=True)
class SynologyDSMEntityDescription(EntityDescription):
"""Generic Synology DSM entity description."""
api_key: str
class SynologyDSMBaseEntity(CoordinatorEntity[_CoordinatorT]):
"""Representation of a Synology NAS entry."""
entity_description: SynologyDSMEntityDescription
unique_id: str
_attr_attribution = ATTRIBUTION
_attr_has_entity_name = True
def __init__(
self,
api: SynoApi,
coordinator: _CoordinatorT,
description: SynologyDSMEntityDescription,
) -> None:
"""Initialize the Synology DSM entity."""
super().__init__(coordinator)
self.entity_description = description
self._api = api
information = api.information
network = api.network
assert information is not None
assert network is not None
self._attr_unique_id: str = (
f"{information.serial}_{description.api_key}:{description.key}"
)
self._attr_device_info = DeviceInfo(
identifiers={(DOMAIN, information.serial)},
name=network.hostname,
manufacturer="Synology",
model=information.model,
sw_version=information.version_string,
configuration_url=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[SynologyDSMCentralUpdateCoordinator]
):
"""Representation of a Synology NAS disk or volume entry."""
def __init__(
self,
api: SynoApi,
coordinator: SynologyDSMCentralUpdateCoordinator,
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
storage = api.storage
information = api.information
network = api.network
assert information is not None
assert storage is not None
assert network is not None
if "volume" in description.key:
assert self._device_id is not None
volume = storage.get_volume(self._device_id)
assert volume is not None
# Volume does not have a name
self._device_name = volume["id"].replace("_", " ").capitalize()
self._device_manufacturer = "Synology"
self._device_model = information.model
self._device_firmware = information.version_string
self._device_type = (
volume["device_type"]
.replace("_", " ")
.replace("raid", "RAID")
.replace("shr", "SHR")
)
elif "disk" in description.key:
assert self._device_id is not None
disk = storage.get_disk(self._device_id)
assert disk is not None
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_unique_id += f"_{self._device_id}"
self._attr_device_info = DeviceInfo(
identifiers={(DOMAIN, f"{information.serial}_{self._device_id}")},
name=f"{network.hostname} ({self._device_name})",
manufacturer=self._device_manufacturer,
model=self._device_model,
sw_version=self._device_firmware,
via_device=(DOMAIN, information.serial),
configuration_url=self._api.config_url,
)