mirror of
https://github.com/home-assistant/core.git
synced 2025-07-18 18:57:06 +00:00
Use EntityDescription - synology_dsm (#55407)
This commit is contained in:
parent
f5cd321185
commit
4eba2ccebc
@ -26,14 +26,9 @@ from synology_dsm.exceptions import (
|
||||
SynologyDSMRequestException,
|
||||
)
|
||||
|
||||
from homeassistant.components.sensor import ATTR_STATE_CLASS
|
||||
from homeassistant.config_entries import SOURCE_REAUTH, ConfigEntry
|
||||
from homeassistant.const import (
|
||||
ATTR_ATTRIBUTION,
|
||||
ATTR_DEVICE_CLASS,
|
||||
ATTR_ICON,
|
||||
ATTR_NAME,
|
||||
ATTR_UNIT_OF_MEASUREMENT,
|
||||
CONF_HOST,
|
||||
CONF_MAC,
|
||||
CONF_PASSWORD,
|
||||
@ -68,7 +63,6 @@ from .const import (
|
||||
DEFAULT_SCAN_INTERVAL,
|
||||
DEFAULT_VERIFY_SSL,
|
||||
DOMAIN,
|
||||
ENTITY_ENABLE,
|
||||
EXCEPTION_DETAILS,
|
||||
EXCEPTION_UNKNOWN,
|
||||
PLATFORMS,
|
||||
@ -82,7 +76,7 @@ from .const import (
|
||||
SYSTEM_LOADED,
|
||||
UNDO_UPDATE_LISTENER,
|
||||
UTILISATION_SENSORS,
|
||||
EntityInfo,
|
||||
SynologyDSMEntityDescription,
|
||||
)
|
||||
|
||||
CONFIG_SCHEMA = cv.deprecated(DOMAIN)
|
||||
@ -109,12 +103,12 @@ async def async_setup_entry( # noqa: C901
|
||||
if "SYNO." in entity_entry.unique_id:
|
||||
return None
|
||||
|
||||
entries = {
|
||||
**STORAGE_DISK_BINARY_SENSORS,
|
||||
**STORAGE_DISK_SENSORS,
|
||||
**STORAGE_VOL_SENSORS,
|
||||
**UTILISATION_SENSORS,
|
||||
}
|
||||
entries = (
|
||||
*STORAGE_DISK_BINARY_SENSORS,
|
||||
*STORAGE_DISK_SENSORS,
|
||||
*STORAGE_VOL_SENSORS,
|
||||
*UTILISATION_SENSORS,
|
||||
)
|
||||
infos = entity_entry.unique_id.split("_")
|
||||
serial = infos.pop(0)
|
||||
label = infos.pop(0)
|
||||
@ -129,22 +123,22 @@ async def async_setup_entry( # noqa: C901
|
||||
return None
|
||||
|
||||
entity_type: str | None = None
|
||||
for entity_key, entity_attrs in entries.items():
|
||||
for description in entries:
|
||||
if (
|
||||
device_id
|
||||
and entity_attrs[ATTR_NAME] == "Status"
|
||||
and description.name == "Status"
|
||||
and "Status" in entity_entry.unique_id
|
||||
and "(Smart)" not in entity_entry.unique_id
|
||||
):
|
||||
if "sd" in device_id and "disk" in entity_key:
|
||||
entity_type = entity_key
|
||||
if "sd" in device_id and "disk" in description.key:
|
||||
entity_type = description.key
|
||||
continue
|
||||
if "volume" in device_id and "volume" in entity_key:
|
||||
entity_type = entity_key
|
||||
if "volume" in device_id and "volume" in description.key:
|
||||
entity_type = description.key
|
||||
continue
|
||||
|
||||
if entity_attrs[ATTR_NAME] == label:
|
||||
entity_type = entity_key
|
||||
if description.name == label:
|
||||
entity_type = description.key
|
||||
|
||||
if entity_type is None:
|
||||
return None
|
||||
@ -604,51 +598,25 @@ class SynoApi:
|
||||
class SynologyDSMBaseEntity(CoordinatorEntity):
|
||||
"""Representation of a Synology NAS entry."""
|
||||
|
||||
entity_description: SynologyDSMEntityDescription
|
||||
unique_id: str
|
||||
_attr_extra_state_attributes = {ATTR_ATTRIBUTION: ATTRIBUTION}
|
||||
|
||||
def __init__(
|
||||
self,
|
||||
api: SynoApi,
|
||||
entity_type: str,
|
||||
entity_info: EntityInfo,
|
||||
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._api_key = entity_type.split(":")[0]
|
||||
self.entity_type = entity_type.split(":")[-1]
|
||||
self._name = f"{api.network.hostname} {entity_info[ATTR_NAME]}"
|
||||
self._class = entity_info[ATTR_DEVICE_CLASS]
|
||||
self._enable_default = entity_info[ENTITY_ENABLE]
|
||||
self._icon = entity_info[ATTR_ICON]
|
||||
self._unit = entity_info[ATTR_UNIT_OF_MEASUREMENT]
|
||||
self._unique_id = f"{self._api.information.serial}_{entity_type}"
|
||||
self._attr_state_class = entity_info[ATTR_STATE_CLASS]
|
||||
|
||||
@property
|
||||
def unique_id(self) -> str:
|
||||
"""Return a unique ID."""
|
||||
return self._unique_id
|
||||
|
||||
@property
|
||||
def name(self) -> str:
|
||||
"""Return the name."""
|
||||
return self._name
|
||||
|
||||
@property
|
||||
def icon(self) -> str | None:
|
||||
"""Return the icon."""
|
||||
return self._icon
|
||||
|
||||
@property
|
||||
def device_class(self) -> str | None:
|
||||
"""Return the class of this device."""
|
||||
return self._class
|
||||
|
||||
@property
|
||||
def extra_state_attributes(self) -> dict[str, Any]:
|
||||
"""Return the state attributes."""
|
||||
return {ATTR_ATTRIBUTION: ATTRIBUTION}
|
||||
self._attr_name = f"{api.network.hostname} {description.name}"
|
||||
self._attr_unique_id: str = (
|
||||
f"{api.information.serial}_{description.api_key}:{description.key}"
|
||||
)
|
||||
|
||||
@property
|
||||
def device_info(self) -> DeviceInfo:
|
||||
@ -661,14 +629,11 @@ class SynologyDSMBaseEntity(CoordinatorEntity):
|
||||
"sw_version": self._api.information.version_string,
|
||||
}
|
||||
|
||||
@property
|
||||
def entity_registry_enabled_default(self) -> bool:
|
||||
"""Return if the entity should be enabled when first added to the entity registry."""
|
||||
return self._enable_default
|
||||
|
||||
async def async_added_to_hass(self) -> None:
|
||||
"""Register entity for updates from API."""
|
||||
self.async_on_remove(self._api.subscribe(self._api_key, self.unique_id))
|
||||
self.async_on_remove(
|
||||
self._api.subscribe(self.entity_description.api_key, self.unique_id)
|
||||
)
|
||||
await super().async_added_to_hass()
|
||||
|
||||
|
||||
@ -678,13 +643,12 @@ class SynologyDSMDeviceEntity(SynologyDSMBaseEntity):
|
||||
def __init__(
|
||||
self,
|
||||
api: SynoApi,
|
||||
entity_type: str,
|
||||
entity_info: EntityInfo,
|
||||
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, entity_type, entity_info, coordinator)
|
||||
super().__init__(api, coordinator, description)
|
||||
self._device_id = device_id
|
||||
self._device_name: str | None = None
|
||||
self._device_manufacturer: str | None = None
|
||||
@ -692,7 +656,7 @@ class SynologyDSMDeviceEntity(SynologyDSMBaseEntity):
|
||||
self._device_firmware: str | None = None
|
||||
self._device_type = None
|
||||
|
||||
if "volume" in entity_type:
|
||||
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()
|
||||
@ -705,7 +669,7 @@ class SynologyDSMDeviceEntity(SynologyDSMBaseEntity):
|
||||
.replace("raid", "RAID")
|
||||
.replace("shr", "SHR")
|
||||
)
|
||||
elif "disk" in entity_type:
|
||||
elif "disk" in description.key:
|
||||
disk = self._api.storage.get_disk(self._device_id)
|
||||
self._device_name = disk["name"]
|
||||
self._device_manufacturer = disk["vendor"]
|
||||
@ -713,9 +677,9 @@ class SynologyDSMDeviceEntity(SynologyDSMBaseEntity):
|
||||
self._device_firmware = disk["firm"]
|
||||
self._device_type = disk["diskType"]
|
||||
self._name = (
|
||||
f"{self._api.network.hostname} {self._device_name} {entity_info[ATTR_NAME]}"
|
||||
f"{self._api.network.hostname} {self._device_name} {description.name}"
|
||||
)
|
||||
self._unique_id += f"_{self._device_id}"
|
||||
self._attr_unique_id += f"_{self._device_id}"
|
||||
|
||||
@property
|
||||
def available(self) -> bool:
|
||||
|
@ -1,11 +1,14 @@
|
||||
"""Support for Synology DSM binary sensors."""
|
||||
from __future__ import annotations
|
||||
|
||||
from typing import Any
|
||||
|
||||
from homeassistant.components.binary_sensor import BinarySensorEntity
|
||||
from homeassistant.config_entries import ConfigEntry
|
||||
from homeassistant.const import CONF_DISKS
|
||||
from homeassistant.core import HomeAssistant
|
||||
from homeassistant.helpers.entity_platform import AddEntitiesCallback
|
||||
from homeassistant.helpers.update_coordinator import DataUpdateCoordinator
|
||||
|
||||
from . import SynoApi, SynologyDSMBaseEntity, SynologyDSMDeviceEntity
|
||||
from .const import (
|
||||
@ -15,6 +18,7 @@ from .const import (
|
||||
STORAGE_DISK_BINARY_SENSORS,
|
||||
SYNO_API,
|
||||
UPGRADE_BINARY_SENSORS,
|
||||
SynologyDSMBinarySensorEntityDescription,
|
||||
)
|
||||
|
||||
|
||||
@ -32,39 +36,52 @@ async def async_setup_entry(
|
||||
| SynoDSMUpgradeBinarySensor
|
||||
| SynoDSMStorageBinarySensor
|
||||
] = [
|
||||
SynoDSMSecurityBinarySensor(api, sensor_type, sensor, coordinator)
|
||||
for sensor_type, sensor in SECURITY_BINARY_SENSORS.items()
|
||||
SynoDSMSecurityBinarySensor(api, coordinator, description)
|
||||
for description in SECURITY_BINARY_SENSORS
|
||||
]
|
||||
|
||||
entities += [
|
||||
SynoDSMUpgradeBinarySensor(api, sensor_type, sensor, coordinator)
|
||||
for sensor_type, sensor in UPGRADE_BINARY_SENSORS.items()
|
||||
]
|
||||
entities.extend(
|
||||
[
|
||||
SynoDSMUpgradeBinarySensor(api, coordinator, description)
|
||||
for description in UPGRADE_BINARY_SENSORS
|
||||
]
|
||||
)
|
||||
|
||||
# Handle all disks
|
||||
if api.storage.disks_ids:
|
||||
for disk in entry.data.get(CONF_DISKS, api.storage.disks_ids):
|
||||
entities += [
|
||||
SynoDSMStorageBinarySensor(
|
||||
api,
|
||||
sensor_type,
|
||||
sensor,
|
||||
coordinator,
|
||||
disk,
|
||||
)
|
||||
for sensor_type, sensor in STORAGE_DISK_BINARY_SENSORS.items()
|
||||
entities.extend(
|
||||
[
|
||||
SynoDSMStorageBinarySensor(api, coordinator, description, disk)
|
||||
for disk in entry.data.get(CONF_DISKS, api.storage.disks_ids)
|
||||
for description in STORAGE_DISK_BINARY_SENSORS
|
||||
]
|
||||
)
|
||||
|
||||
async_add_entities(entities)
|
||||
|
||||
|
||||
class SynoDSMSecurityBinarySensor(SynologyDSMBaseEntity, BinarySensorEntity):
|
||||
class SynoDSMBinarySensor(SynologyDSMBaseEntity, BinarySensorEntity):
|
||||
"""Mixin for binary sensor specific attributes."""
|
||||
|
||||
entity_description: SynologyDSMBinarySensorEntityDescription
|
||||
|
||||
def __init__(
|
||||
self,
|
||||
api: SynoApi,
|
||||
coordinator: DataUpdateCoordinator[dict[str, dict[str, Any]]],
|
||||
description: SynologyDSMBinarySensorEntityDescription,
|
||||
) -> None:
|
||||
"""Initialize the Synology DSM binary_sensor entity."""
|
||||
super().__init__(api, coordinator, description)
|
||||
|
||||
|
||||
class SynoDSMSecurityBinarySensor(SynoDSMBinarySensor):
|
||||
"""Representation a Synology Security binary sensor."""
|
||||
|
||||
@property
|
||||
def is_on(self) -> bool:
|
||||
"""Return the state."""
|
||||
return getattr(self._api.security, self.entity_type) != "safe" # type: ignore[no-any-return]
|
||||
return getattr(self._api.security, self.entity_description.key) != "safe" # type: ignore[no-any-return]
|
||||
|
||||
@property
|
||||
def available(self) -> bool:
|
||||
@ -77,22 +94,36 @@ class SynoDSMSecurityBinarySensor(SynologyDSMBaseEntity, BinarySensorEntity):
|
||||
return self._api.security.status_by_check # type: ignore[no-any-return]
|
||||
|
||||
|
||||
class SynoDSMStorageBinarySensor(SynologyDSMDeviceEntity, BinarySensorEntity):
|
||||
class SynoDSMStorageBinarySensor(SynologyDSMDeviceEntity, SynoDSMBinarySensor):
|
||||
"""Representation a Synology Storage binary sensor."""
|
||||
|
||||
entity_description: SynologyDSMBinarySensorEntityDescription
|
||||
|
||||
def __init__(
|
||||
self,
|
||||
api: SynoApi,
|
||||
coordinator: DataUpdateCoordinator[dict[str, dict[str, Any]]],
|
||||
description: SynologyDSMBinarySensorEntityDescription,
|
||||
device_id: str | None = None,
|
||||
) -> None:
|
||||
"""Initialize the Synology DSM storage binary_sensor entity."""
|
||||
super().__init__(api, coordinator, description, device_id)
|
||||
|
||||
@property
|
||||
def is_on(self) -> bool:
|
||||
"""Return the state."""
|
||||
return bool(getattr(self._api.storage, self.entity_type)(self._device_id))
|
||||
return bool(
|
||||
getattr(self._api.storage, self.entity_description.key)(self._device_id)
|
||||
)
|
||||
|
||||
|
||||
class SynoDSMUpgradeBinarySensor(SynologyDSMBaseEntity, BinarySensorEntity):
|
||||
class SynoDSMUpgradeBinarySensor(SynoDSMBinarySensor):
|
||||
"""Representation a Synology Upgrade binary sensor."""
|
||||
|
||||
@property
|
||||
def is_on(self) -> bool:
|
||||
"""Return the state."""
|
||||
return bool(getattr(self._api.upgrade, self.entity_type))
|
||||
return bool(getattr(self._api.upgrade, self.entity_description.key))
|
||||
|
||||
@property
|
||||
def available(self) -> bool:
|
||||
|
@ -1,6 +1,7 @@
|
||||
"""Support for Synology DSM cameras."""
|
||||
from __future__ import annotations
|
||||
|
||||
from dataclasses import dataclass
|
||||
import logging
|
||||
|
||||
from synology_dsm.api.surveillance_station import SynoCamera, SynoSurveillanceStation
|
||||
@ -9,26 +10,30 @@ from synology_dsm.exceptions import (
|
||||
SynologyDSMRequestException,
|
||||
)
|
||||
|
||||
from homeassistant.components.camera import SUPPORT_STREAM, Camera
|
||||
from homeassistant.components.sensor import ATTR_STATE_CLASS
|
||||
from homeassistant.config_entries import ConfigEntry
|
||||
from homeassistant.const import (
|
||||
ATTR_DEVICE_CLASS,
|
||||
ATTR_ICON,
|
||||
ATTR_NAME,
|
||||
ATTR_UNIT_OF_MEASUREMENT,
|
||||
from homeassistant.components.camera import (
|
||||
SUPPORT_STREAM,
|
||||
Camera,
|
||||
CameraEntityDescription,
|
||||
)
|
||||
from homeassistant.config_entries import ConfigEntry
|
||||
from homeassistant.core import HomeAssistant
|
||||
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_CAMERAS, DOMAIN, ENTITY_ENABLE, SYNO_API
|
||||
from .const import COORDINATOR_CAMERAS, DOMAIN, SYNO_API, SynologyDSMEntityDescription
|
||||
|
||||
_LOGGER = logging.getLogger(__name__)
|
||||
|
||||
|
||||
@dataclass
|
||||
class SynologyDSMCameraEntityDescription(
|
||||
CameraEntityDescription, SynologyDSMEntityDescription
|
||||
):
|
||||
"""Describes Synology DSM camera entity."""
|
||||
|
||||
|
||||
async def async_setup_entry(
|
||||
hass: HomeAssistant, entry: ConfigEntry, async_add_entities: AddEntitiesCallback
|
||||
) -> None:
|
||||
@ -56,6 +61,7 @@ class SynoDSMCamera(SynologyDSMBaseEntity, Camera):
|
||||
"""Representation a Synology camera."""
|
||||
|
||||
coordinator: DataUpdateCoordinator[dict[str, dict[str, SynoCamera]]]
|
||||
entity_description: SynologyDSMCameraEntityDescription
|
||||
|
||||
def __init__(
|
||||
self,
|
||||
@ -64,26 +70,21 @@ class SynoDSMCamera(SynologyDSMBaseEntity, Camera):
|
||||
camera_id: str,
|
||||
) -> None:
|
||||
"""Initialize a Synology camera."""
|
||||
super().__init__(
|
||||
api,
|
||||
f"{SynoSurveillanceStation.CAMERA_API_KEY}:{camera_id}",
|
||||
{
|
||||
ATTR_NAME: coordinator.data["cameras"][camera_id].name,
|
||||
ENTITY_ENABLE: coordinator.data["cameras"][camera_id].is_enabled,
|
||||
ATTR_DEVICE_CLASS: None,
|
||||
ATTR_ICON: None,
|
||||
ATTR_UNIT_OF_MEASUREMENT: None,
|
||||
ATTR_STATE_CLASS: None,
|
||||
},
|
||||
coordinator,
|
||||
description = SynologyDSMCameraEntityDescription(
|
||||
api_key=SynoSurveillanceStation.CAMERA_API_KEY,
|
||||
key=camera_id,
|
||||
name=coordinator.data["cameras"][camera_id].name,
|
||||
entity_registry_enabled_default=coordinator.data["cameras"][
|
||||
camera_id
|
||||
].is_enabled,
|
||||
)
|
||||
super().__init__(api, coordinator, description)
|
||||
Camera.__init__(self)
|
||||
self._camera_id = camera_id
|
||||
|
||||
@property
|
||||
def camera_data(self) -> SynoCamera:
|
||||
"""Camera data."""
|
||||
return self.coordinator.data["cameras"][self._camera_id]
|
||||
return self.coordinator.data["cameras"][self.entity_description.key]
|
||||
|
||||
@property
|
||||
def device_info(self) -> DeviceInfo:
|
||||
@ -134,7 +135,7 @@ class SynoDSMCamera(SynologyDSMBaseEntity, Camera):
|
||||
if not self.available:
|
||||
return None
|
||||
try:
|
||||
return self._api.surveillance_station.get_camera_image(self._camera_id) # type: ignore[no-any-return]
|
||||
return self._api.surveillance_station.get_camera_image(self.entity_description.key) # type: ignore[no-any-return]
|
||||
except (
|
||||
SynologyDSMAPIErrorException,
|
||||
SynologyDSMRequestException,
|
||||
@ -163,7 +164,9 @@ class SynoDSMCamera(SynologyDSMBaseEntity, Camera):
|
||||
"SynoDSMCamera.enable_motion_detection(%s)",
|
||||
self.camera_data.name,
|
||||
)
|
||||
self._api.surveillance_station.enable_motion_detection(self._camera_id)
|
||||
self._api.surveillance_station.enable_motion_detection(
|
||||
self.entity_description.key
|
||||
)
|
||||
|
||||
def disable_motion_detection(self) -> None:
|
||||
"""Disable motion detection in camera."""
|
||||
@ -171,4 +174,6 @@ class SynoDSMCamera(SynologyDSMBaseEntity, Camera):
|
||||
"SynoDSMCamera.disable_motion_detection(%s)",
|
||||
self.camera_data.name,
|
||||
)
|
||||
self._api.surveillance_station.disable_motion_detection(self._camera_id)
|
||||
self._api.surveillance_station.disable_motion_detection(
|
||||
self.entity_description.key
|
||||
)
|
||||
|
@ -1,7 +1,7 @@
|
||||
"""Constants for Synology DSM."""
|
||||
from __future__ import annotations
|
||||
|
||||
from typing import Final, TypedDict
|
||||
from dataclasses import dataclass
|
||||
|
||||
from synology_dsm.api.core.security import SynoCoreSecurity
|
||||
from synology_dsm.api.core.upgrade import SynoCoreUpgrade
|
||||
@ -13,13 +13,14 @@ from synology_dsm.api.surveillance_station import SynoSurveillanceStation
|
||||
from homeassistant.components.binary_sensor import (
|
||||
DEVICE_CLASS_SAFETY,
|
||||
DEVICE_CLASS_UPDATE,
|
||||
BinarySensorEntityDescription,
|
||||
)
|
||||
from homeassistant.components.sensor import ATTR_STATE_CLASS, STATE_CLASS_MEASUREMENT
|
||||
from homeassistant.components.sensor import (
|
||||
STATE_CLASS_MEASUREMENT,
|
||||
SensorEntityDescription,
|
||||
)
|
||||
from homeassistant.components.switch import SwitchEntityDescription
|
||||
from homeassistant.const import (
|
||||
ATTR_DEVICE_CLASS,
|
||||
ATTR_ICON,
|
||||
ATTR_NAME,
|
||||
ATTR_UNIT_OF_MEASUREMENT,
|
||||
DATA_MEGABYTES,
|
||||
DATA_RATE_KILOBYTES_PER_SECOND,
|
||||
DATA_TERABYTES,
|
||||
@ -28,18 +29,7 @@ from homeassistant.const import (
|
||||
PERCENTAGE,
|
||||
TEMP_CELSIUS,
|
||||
)
|
||||
|
||||
|
||||
class EntityInfo(TypedDict):
|
||||
"""TypedDict for EntityInfo."""
|
||||
|
||||
name: str
|
||||
unit_of_measurement: str | None
|
||||
icon: str | None
|
||||
device_class: str | None
|
||||
state_class: str | None
|
||||
enable: bool
|
||||
|
||||
from homeassistant.helpers.entity import EntityDescription
|
||||
|
||||
DOMAIN = "synology_dsm"
|
||||
PLATFORMS = ["binary_sensor", "camera", "sensor", "switch"]
|
||||
@ -68,7 +58,6 @@ DEFAULT_SCAN_INTERVAL = 15 # min
|
||||
DEFAULT_TIMEOUT = 10 # sec
|
||||
|
||||
ENTITY_UNIT_LOAD = "load"
|
||||
ENTITY_ENABLE: Final = "enable"
|
||||
|
||||
# Services
|
||||
SERVICE_REBOOT = "reboot"
|
||||
@ -78,285 +67,302 @@ SERVICES = [
|
||||
SERVICE_SHUTDOWN,
|
||||
]
|
||||
|
||||
# Entity keys should start with the API_KEY to fetch
|
||||
|
||||
@dataclass
|
||||
class SynologyDSMRequiredKeysMixin:
|
||||
"""Mixin for required keys."""
|
||||
|
||||
api_key: str
|
||||
|
||||
|
||||
@dataclass
|
||||
class SynologyDSMEntityDescription(EntityDescription, SynologyDSMRequiredKeysMixin):
|
||||
"""Generic Synology DSM entity description."""
|
||||
|
||||
|
||||
@dataclass
|
||||
class SynologyDSMBinarySensorEntityDescription(
|
||||
BinarySensorEntityDescription, SynologyDSMEntityDescription
|
||||
):
|
||||
"""Describes Synology DSM binary sensor entity."""
|
||||
|
||||
|
||||
@dataclass
|
||||
class SynologyDSMSensorEntityDescription(
|
||||
SensorEntityDescription, SynologyDSMEntityDescription
|
||||
):
|
||||
"""Describes Synology DSM sensor entity."""
|
||||
|
||||
|
||||
@dataclass
|
||||
class SynologyDSMSwitchEntityDescription(
|
||||
SwitchEntityDescription, SynologyDSMEntityDescription
|
||||
):
|
||||
"""Describes Synology DSM switch entity."""
|
||||
|
||||
|
||||
# Binary sensors
|
||||
UPGRADE_BINARY_SENSORS: dict[str, EntityInfo] = {
|
||||
f"{SynoCoreUpgrade.API_KEY}:update_available": {
|
||||
ATTR_NAME: "Update available",
|
||||
ATTR_UNIT_OF_MEASUREMENT: None,
|
||||
ATTR_ICON: None,
|
||||
ATTR_DEVICE_CLASS: DEVICE_CLASS_UPDATE,
|
||||
ENTITY_ENABLE: True,
|
||||
ATTR_STATE_CLASS: None,
|
||||
},
|
||||
}
|
||||
UPGRADE_BINARY_SENSORS: tuple[SynologyDSMBinarySensorEntityDescription, ...] = (
|
||||
SynologyDSMBinarySensorEntityDescription(
|
||||
api_key=SynoCoreUpgrade.API_KEY,
|
||||
key="update_available",
|
||||
name="Update available",
|
||||
device_class=DEVICE_CLASS_UPDATE,
|
||||
),
|
||||
)
|
||||
|
||||
SECURITY_BINARY_SENSORS: dict[str, EntityInfo] = {
|
||||
f"{SynoCoreSecurity.API_KEY}:status": {
|
||||
ATTR_NAME: "Security status",
|
||||
ATTR_UNIT_OF_MEASUREMENT: None,
|
||||
ATTR_ICON: None,
|
||||
ATTR_DEVICE_CLASS: DEVICE_CLASS_SAFETY,
|
||||
ENTITY_ENABLE: True,
|
||||
ATTR_STATE_CLASS: None,
|
||||
},
|
||||
}
|
||||
SECURITY_BINARY_SENSORS: tuple[SynologyDSMBinarySensorEntityDescription, ...] = (
|
||||
SynologyDSMBinarySensorEntityDescription(
|
||||
api_key=SynoCoreSecurity.API_KEY,
|
||||
key="status",
|
||||
name="Security status",
|
||||
device_class=DEVICE_CLASS_SAFETY,
|
||||
),
|
||||
)
|
||||
|
||||
STORAGE_DISK_BINARY_SENSORS: dict[str, EntityInfo] = {
|
||||
f"{SynoStorage.API_KEY}:disk_exceed_bad_sector_thr": {
|
||||
ATTR_NAME: "Exceeded Max Bad Sectors",
|
||||
ATTR_UNIT_OF_MEASUREMENT: None,
|
||||
ATTR_ICON: None,
|
||||
ATTR_DEVICE_CLASS: DEVICE_CLASS_SAFETY,
|
||||
ENTITY_ENABLE: True,
|
||||
ATTR_STATE_CLASS: None,
|
||||
},
|
||||
f"{SynoStorage.API_KEY}:disk_below_remain_life_thr": {
|
||||
ATTR_NAME: "Below Min Remaining Life",
|
||||
ATTR_UNIT_OF_MEASUREMENT: None,
|
||||
ATTR_ICON: None,
|
||||
ATTR_DEVICE_CLASS: DEVICE_CLASS_SAFETY,
|
||||
ENTITY_ENABLE: True,
|
||||
ATTR_STATE_CLASS: None,
|
||||
},
|
||||
}
|
||||
STORAGE_DISK_BINARY_SENSORS: tuple[SynologyDSMBinarySensorEntityDescription, ...] = (
|
||||
SynologyDSMBinarySensorEntityDescription(
|
||||
api_key=SynoStorage.API_KEY,
|
||||
key="disk_exceed_bad_sector_thr",
|
||||
name="Exceeded Max Bad Sectors",
|
||||
device_class=DEVICE_CLASS_SAFETY,
|
||||
),
|
||||
SynologyDSMBinarySensorEntityDescription(
|
||||
api_key=SynoStorage.API_KEY,
|
||||
key="disk_below_remain_life_thr",
|
||||
name="Below Min Remaining Life",
|
||||
device_class=DEVICE_CLASS_SAFETY,
|
||||
),
|
||||
)
|
||||
|
||||
# Sensors
|
||||
UTILISATION_SENSORS: dict[str, EntityInfo] = {
|
||||
f"{SynoCoreUtilization.API_KEY}:cpu_other_load": {
|
||||
ATTR_NAME: "CPU Utilization (Other)",
|
||||
ATTR_UNIT_OF_MEASUREMENT: PERCENTAGE,
|
||||
ATTR_ICON: "mdi:chip",
|
||||
ATTR_DEVICE_CLASS: None,
|
||||
ENTITY_ENABLE: False,
|
||||
ATTR_STATE_CLASS: STATE_CLASS_MEASUREMENT,
|
||||
},
|
||||
f"{SynoCoreUtilization.API_KEY}:cpu_user_load": {
|
||||
ATTR_NAME: "CPU Utilization (User)",
|
||||
ATTR_UNIT_OF_MEASUREMENT: PERCENTAGE,
|
||||
ATTR_ICON: "mdi:chip",
|
||||
ATTR_DEVICE_CLASS: None,
|
||||
ENTITY_ENABLE: True,
|
||||
ATTR_STATE_CLASS: STATE_CLASS_MEASUREMENT,
|
||||
},
|
||||
f"{SynoCoreUtilization.API_KEY}:cpu_system_load": {
|
||||
ATTR_NAME: "CPU Utilization (System)",
|
||||
ATTR_UNIT_OF_MEASUREMENT: PERCENTAGE,
|
||||
ATTR_ICON: "mdi:chip",
|
||||
ATTR_DEVICE_CLASS: None,
|
||||
ENTITY_ENABLE: False,
|
||||
ATTR_STATE_CLASS: STATE_CLASS_MEASUREMENT,
|
||||
},
|
||||
f"{SynoCoreUtilization.API_KEY}:cpu_total_load": {
|
||||
ATTR_NAME: "CPU Utilization (Total)",
|
||||
ATTR_UNIT_OF_MEASUREMENT: PERCENTAGE,
|
||||
ATTR_ICON: "mdi:chip",
|
||||
ATTR_DEVICE_CLASS: None,
|
||||
ENTITY_ENABLE: True,
|
||||
ATTR_STATE_CLASS: STATE_CLASS_MEASUREMENT,
|
||||
},
|
||||
f"{SynoCoreUtilization.API_KEY}:cpu_1min_load": {
|
||||
ATTR_NAME: "CPU Load Average (1 min)",
|
||||
ATTR_UNIT_OF_MEASUREMENT: ENTITY_UNIT_LOAD,
|
||||
ATTR_ICON: "mdi:chip",
|
||||
ATTR_DEVICE_CLASS: None,
|
||||
ENTITY_ENABLE: False,
|
||||
ATTR_STATE_CLASS: None,
|
||||
},
|
||||
f"{SynoCoreUtilization.API_KEY}:cpu_5min_load": {
|
||||
ATTR_NAME: "CPU Load Average (5 min)",
|
||||
ATTR_UNIT_OF_MEASUREMENT: ENTITY_UNIT_LOAD,
|
||||
ATTR_ICON: "mdi:chip",
|
||||
ATTR_DEVICE_CLASS: None,
|
||||
ENTITY_ENABLE: True,
|
||||
ATTR_STATE_CLASS: None,
|
||||
},
|
||||
f"{SynoCoreUtilization.API_KEY}:cpu_15min_load": {
|
||||
ATTR_NAME: "CPU Load Average (15 min)",
|
||||
ATTR_UNIT_OF_MEASUREMENT: ENTITY_UNIT_LOAD,
|
||||
ATTR_ICON: "mdi:chip",
|
||||
ATTR_DEVICE_CLASS: None,
|
||||
ENTITY_ENABLE: True,
|
||||
ATTR_STATE_CLASS: None,
|
||||
},
|
||||
f"{SynoCoreUtilization.API_KEY}:memory_real_usage": {
|
||||
ATTR_NAME: "Memory Usage (Real)",
|
||||
ATTR_UNIT_OF_MEASUREMENT: PERCENTAGE,
|
||||
ATTR_ICON: "mdi:memory",
|
||||
ATTR_DEVICE_CLASS: None,
|
||||
ENTITY_ENABLE: True,
|
||||
ATTR_STATE_CLASS: STATE_CLASS_MEASUREMENT,
|
||||
},
|
||||
f"{SynoCoreUtilization.API_KEY}:memory_size": {
|
||||
ATTR_NAME: "Memory Size",
|
||||
ATTR_UNIT_OF_MEASUREMENT: DATA_MEGABYTES,
|
||||
ATTR_ICON: "mdi:memory",
|
||||
ATTR_DEVICE_CLASS: None,
|
||||
ENTITY_ENABLE: False,
|
||||
ATTR_STATE_CLASS: STATE_CLASS_MEASUREMENT,
|
||||
},
|
||||
f"{SynoCoreUtilization.API_KEY}:memory_cached": {
|
||||
ATTR_NAME: "Memory Cached",
|
||||
ATTR_UNIT_OF_MEASUREMENT: DATA_MEGABYTES,
|
||||
ATTR_ICON: "mdi:memory",
|
||||
ATTR_DEVICE_CLASS: None,
|
||||
ENTITY_ENABLE: False,
|
||||
ATTR_STATE_CLASS: STATE_CLASS_MEASUREMENT,
|
||||
},
|
||||
f"{SynoCoreUtilization.API_KEY}:memory_available_swap": {
|
||||
ATTR_NAME: "Memory Available (Swap)",
|
||||
ATTR_UNIT_OF_MEASUREMENT: DATA_MEGABYTES,
|
||||
ATTR_ICON: "mdi:memory",
|
||||
ATTR_DEVICE_CLASS: None,
|
||||
ENTITY_ENABLE: True,
|
||||
ATTR_STATE_CLASS: STATE_CLASS_MEASUREMENT,
|
||||
},
|
||||
f"{SynoCoreUtilization.API_KEY}:memory_available_real": {
|
||||
ATTR_NAME: "Memory Available (Real)",
|
||||
ATTR_UNIT_OF_MEASUREMENT: DATA_MEGABYTES,
|
||||
ATTR_ICON: "mdi:memory",
|
||||
ATTR_DEVICE_CLASS: None,
|
||||
ENTITY_ENABLE: True,
|
||||
ATTR_STATE_CLASS: STATE_CLASS_MEASUREMENT,
|
||||
},
|
||||
f"{SynoCoreUtilization.API_KEY}:memory_total_swap": {
|
||||
ATTR_NAME: "Memory Total (Swap)",
|
||||
ATTR_UNIT_OF_MEASUREMENT: DATA_MEGABYTES,
|
||||
ATTR_ICON: "mdi:memory",
|
||||
ATTR_DEVICE_CLASS: None,
|
||||
ENTITY_ENABLE: True,
|
||||
ATTR_STATE_CLASS: STATE_CLASS_MEASUREMENT,
|
||||
},
|
||||
f"{SynoCoreUtilization.API_KEY}:memory_total_real": {
|
||||
ATTR_NAME: "Memory Total (Real)",
|
||||
ATTR_UNIT_OF_MEASUREMENT: DATA_MEGABYTES,
|
||||
ATTR_ICON: "mdi:memory",
|
||||
ATTR_DEVICE_CLASS: None,
|
||||
ENTITY_ENABLE: True,
|
||||
ATTR_STATE_CLASS: STATE_CLASS_MEASUREMENT,
|
||||
},
|
||||
f"{SynoCoreUtilization.API_KEY}:network_up": {
|
||||
ATTR_NAME: "Upload Throughput",
|
||||
ATTR_UNIT_OF_MEASUREMENT: DATA_RATE_KILOBYTES_PER_SECOND,
|
||||
ATTR_ICON: "mdi:upload",
|
||||
ATTR_DEVICE_CLASS: None,
|
||||
ENTITY_ENABLE: True,
|
||||
ATTR_STATE_CLASS: STATE_CLASS_MEASUREMENT,
|
||||
},
|
||||
f"{SynoCoreUtilization.API_KEY}:network_down": {
|
||||
ATTR_NAME: "Download Throughput",
|
||||
ATTR_UNIT_OF_MEASUREMENT: DATA_RATE_KILOBYTES_PER_SECOND,
|
||||
ATTR_ICON: "mdi:download",
|
||||
ATTR_DEVICE_CLASS: None,
|
||||
ENTITY_ENABLE: True,
|
||||
ATTR_STATE_CLASS: STATE_CLASS_MEASUREMENT,
|
||||
},
|
||||
}
|
||||
STORAGE_VOL_SENSORS: dict[str, EntityInfo] = {
|
||||
f"{SynoStorage.API_KEY}:volume_status": {
|
||||
ATTR_NAME: "Status",
|
||||
ATTR_UNIT_OF_MEASUREMENT: None,
|
||||
ATTR_ICON: "mdi:checkbox-marked-circle-outline",
|
||||
ATTR_DEVICE_CLASS: None,
|
||||
ENTITY_ENABLE: True,
|
||||
ATTR_STATE_CLASS: None,
|
||||
},
|
||||
f"{SynoStorage.API_KEY}:volume_size_total": {
|
||||
ATTR_NAME: "Total Size",
|
||||
ATTR_UNIT_OF_MEASUREMENT: DATA_TERABYTES,
|
||||
ATTR_ICON: "mdi:chart-pie",
|
||||
ATTR_DEVICE_CLASS: None,
|
||||
ENTITY_ENABLE: False,
|
||||
ATTR_STATE_CLASS: STATE_CLASS_MEASUREMENT,
|
||||
},
|
||||
f"{SynoStorage.API_KEY}:volume_size_used": {
|
||||
ATTR_NAME: "Used Space",
|
||||
ATTR_UNIT_OF_MEASUREMENT: DATA_TERABYTES,
|
||||
ATTR_ICON: "mdi:chart-pie",
|
||||
ATTR_DEVICE_CLASS: None,
|
||||
ENTITY_ENABLE: True,
|
||||
ATTR_STATE_CLASS: STATE_CLASS_MEASUREMENT,
|
||||
},
|
||||
f"{SynoStorage.API_KEY}:volume_percentage_used": {
|
||||
ATTR_NAME: "Volume Used",
|
||||
ATTR_UNIT_OF_MEASUREMENT: PERCENTAGE,
|
||||
ATTR_ICON: "mdi:chart-pie",
|
||||
ATTR_DEVICE_CLASS: None,
|
||||
ENTITY_ENABLE: True,
|
||||
ATTR_STATE_CLASS: None,
|
||||
},
|
||||
f"{SynoStorage.API_KEY}:volume_disk_temp_avg": {
|
||||
ATTR_NAME: "Average Disk Temp",
|
||||
ATTR_UNIT_OF_MEASUREMENT: TEMP_CELSIUS,
|
||||
ATTR_ICON: None,
|
||||
ATTR_DEVICE_CLASS: DEVICE_CLASS_TEMPERATURE,
|
||||
ENTITY_ENABLE: True,
|
||||
ATTR_STATE_CLASS: None,
|
||||
},
|
||||
f"{SynoStorage.API_KEY}:volume_disk_temp_max": {
|
||||
ATTR_NAME: "Maximum Disk Temp",
|
||||
ATTR_UNIT_OF_MEASUREMENT: TEMP_CELSIUS,
|
||||
ATTR_ICON: None,
|
||||
ATTR_DEVICE_CLASS: DEVICE_CLASS_TEMPERATURE,
|
||||
ENTITY_ENABLE: False,
|
||||
ATTR_STATE_CLASS: None,
|
||||
},
|
||||
}
|
||||
STORAGE_DISK_SENSORS: dict[str, EntityInfo] = {
|
||||
f"{SynoStorage.API_KEY}:disk_smart_status": {
|
||||
ATTR_NAME: "Status (Smart)",
|
||||
ATTR_UNIT_OF_MEASUREMENT: None,
|
||||
ATTR_ICON: "mdi:checkbox-marked-circle-outline",
|
||||
ATTR_DEVICE_CLASS: None,
|
||||
ENTITY_ENABLE: False,
|
||||
ATTR_STATE_CLASS: None,
|
||||
},
|
||||
f"{SynoStorage.API_KEY}:disk_status": {
|
||||
ATTR_NAME: "Status",
|
||||
ATTR_UNIT_OF_MEASUREMENT: None,
|
||||
ATTR_ICON: "mdi:checkbox-marked-circle-outline",
|
||||
ATTR_DEVICE_CLASS: None,
|
||||
ENTITY_ENABLE: True,
|
||||
ATTR_STATE_CLASS: None,
|
||||
},
|
||||
f"{SynoStorage.API_KEY}:disk_temp": {
|
||||
ATTR_NAME: "Temperature",
|
||||
ATTR_UNIT_OF_MEASUREMENT: TEMP_CELSIUS,
|
||||
ATTR_ICON: None,
|
||||
ATTR_DEVICE_CLASS: DEVICE_CLASS_TEMPERATURE,
|
||||
ENTITY_ENABLE: True,
|
||||
ATTR_STATE_CLASS: STATE_CLASS_MEASUREMENT,
|
||||
},
|
||||
}
|
||||
UTILISATION_SENSORS: tuple[SynologyDSMSensorEntityDescription, ...] = (
|
||||
SynologyDSMSensorEntityDescription(
|
||||
api_key=SynoCoreUtilization.API_KEY,
|
||||
key="cpu_other_load",
|
||||
name="CPU Utilization (Other)",
|
||||
native_unit_of_measurement=PERCENTAGE,
|
||||
icon="mdi:chip",
|
||||
entity_registry_enabled_default=False,
|
||||
state_class=STATE_CLASS_MEASUREMENT,
|
||||
),
|
||||
SynologyDSMSensorEntityDescription(
|
||||
api_key=SynoCoreUtilization.API_KEY,
|
||||
key="cpu_user_load",
|
||||
name="CPU Utilization (User)",
|
||||
native_unit_of_measurement=PERCENTAGE,
|
||||
icon="mdi:chip",
|
||||
state_class=STATE_CLASS_MEASUREMENT,
|
||||
),
|
||||
SynologyDSMSensorEntityDescription(
|
||||
api_key=SynoCoreUtilization.API_KEY,
|
||||
key="cpu_system_load",
|
||||
name="CPU Utilization (System)",
|
||||
native_unit_of_measurement=PERCENTAGE,
|
||||
icon="mdi:chip",
|
||||
entity_registry_enabled_default=False,
|
||||
state_class=STATE_CLASS_MEASUREMENT,
|
||||
),
|
||||
SynologyDSMSensorEntityDescription(
|
||||
api_key=SynoCoreUtilization.API_KEY,
|
||||
key="cpu_total_load",
|
||||
name="CPU Utilization (Total)",
|
||||
native_unit_of_measurement=PERCENTAGE,
|
||||
icon="mdi:chip",
|
||||
state_class=STATE_CLASS_MEASUREMENT,
|
||||
),
|
||||
SynologyDSMSensorEntityDescription(
|
||||
api_key=SynoCoreUtilization.API_KEY,
|
||||
key="cpu_1min_load",
|
||||
name="CPU Load Average (1 min)",
|
||||
native_unit_of_measurement=ENTITY_UNIT_LOAD,
|
||||
icon="mdi:chip",
|
||||
entity_registry_enabled_default=False,
|
||||
),
|
||||
SynologyDSMSensorEntityDescription(
|
||||
api_key=SynoCoreUtilization.API_KEY,
|
||||
key="cpu_5min_load",
|
||||
name="CPU Load Average (5 min)",
|
||||
native_unit_of_measurement=ENTITY_UNIT_LOAD,
|
||||
icon="mdi:chip",
|
||||
),
|
||||
SynologyDSMSensorEntityDescription(
|
||||
api_key=SynoCoreUtilization.API_KEY,
|
||||
key="cpu_15min_load",
|
||||
name="CPU Load Average (15 min)",
|
||||
native_unit_of_measurement=ENTITY_UNIT_LOAD,
|
||||
icon="mdi:chip",
|
||||
),
|
||||
SynologyDSMSensorEntityDescription(
|
||||
api_key=SynoCoreUtilization.API_KEY,
|
||||
key="memory_real_usage",
|
||||
name="Memory Usage (Real)",
|
||||
native_unit_of_measurement=PERCENTAGE,
|
||||
icon="mdi:memory",
|
||||
state_class=STATE_CLASS_MEASUREMENT,
|
||||
),
|
||||
SynologyDSMSensorEntityDescription(
|
||||
api_key=SynoCoreUtilization.API_KEY,
|
||||
key="memory_size",
|
||||
name="Memory Size",
|
||||
native_unit_of_measurement=DATA_MEGABYTES,
|
||||
icon="mdi:memory",
|
||||
entity_registry_enabled_default=False,
|
||||
state_class=STATE_CLASS_MEASUREMENT,
|
||||
),
|
||||
SynologyDSMSensorEntityDescription(
|
||||
api_key=SynoCoreUtilization.API_KEY,
|
||||
key="memory_cached",
|
||||
name="Memory Cached",
|
||||
native_unit_of_measurement=DATA_MEGABYTES,
|
||||
icon="mdi:memory",
|
||||
entity_registry_enabled_default=False,
|
||||
state_class=STATE_CLASS_MEASUREMENT,
|
||||
),
|
||||
SynologyDSMSensorEntityDescription(
|
||||
api_key=SynoCoreUtilization.API_KEY,
|
||||
key="memory_available_swap",
|
||||
name="Memory Available (Swap)",
|
||||
native_unit_of_measurement=DATA_MEGABYTES,
|
||||
icon="mdi:memory",
|
||||
state_class=STATE_CLASS_MEASUREMENT,
|
||||
),
|
||||
SynologyDSMSensorEntityDescription(
|
||||
api_key=SynoCoreUtilization.API_KEY,
|
||||
key="memory_available_real",
|
||||
name="Memory Available (Real)",
|
||||
native_unit_of_measurement=DATA_MEGABYTES,
|
||||
icon="mdi:memory",
|
||||
state_class=STATE_CLASS_MEASUREMENT,
|
||||
),
|
||||
SynologyDSMSensorEntityDescription(
|
||||
api_key=SynoCoreUtilization.API_KEY,
|
||||
key="memory_total_swap",
|
||||
name="Memory Total (Swap)",
|
||||
native_unit_of_measurement=DATA_MEGABYTES,
|
||||
icon="mdi:memory",
|
||||
state_class=STATE_CLASS_MEASUREMENT,
|
||||
),
|
||||
SynologyDSMSensorEntityDescription(
|
||||
api_key=SynoCoreUtilization.API_KEY,
|
||||
key="memory_total_real",
|
||||
name="Memory Total (Real)",
|
||||
native_unit_of_measurement=DATA_MEGABYTES,
|
||||
icon="mdi:memory",
|
||||
state_class=STATE_CLASS_MEASUREMENT,
|
||||
),
|
||||
SynologyDSMSensorEntityDescription(
|
||||
api_key=SynoCoreUtilization.API_KEY,
|
||||
key="network_up",
|
||||
name="Upload Throughput",
|
||||
native_unit_of_measurement=DATA_RATE_KILOBYTES_PER_SECOND,
|
||||
icon="mdi:upload",
|
||||
state_class=STATE_CLASS_MEASUREMENT,
|
||||
),
|
||||
SynologyDSMSensorEntityDescription(
|
||||
api_key=SynoCoreUtilization.API_KEY,
|
||||
key="network_down",
|
||||
name="Download Throughput",
|
||||
native_unit_of_measurement=DATA_RATE_KILOBYTES_PER_SECOND,
|
||||
icon="mdi:download",
|
||||
state_class=STATE_CLASS_MEASUREMENT,
|
||||
),
|
||||
)
|
||||
STORAGE_VOL_SENSORS: tuple[SynologyDSMSensorEntityDescription, ...] = (
|
||||
SynologyDSMSensorEntityDescription(
|
||||
api_key=SynoStorage.API_KEY,
|
||||
key="volume_status",
|
||||
name="Status",
|
||||
icon="mdi:checkbox-marked-circle-outline",
|
||||
),
|
||||
SynologyDSMSensorEntityDescription(
|
||||
api_key=SynoStorage.API_KEY,
|
||||
key="volume_size_total",
|
||||
name="Total Size",
|
||||
native_unit_of_measurement=DATA_TERABYTES,
|
||||
icon="mdi:chart-pie",
|
||||
entity_registry_enabled_default=False,
|
||||
state_class=STATE_CLASS_MEASUREMENT,
|
||||
),
|
||||
SynologyDSMSensorEntityDescription(
|
||||
api_key=SynoStorage.API_KEY,
|
||||
key="volume_size_used",
|
||||
name="Used Space",
|
||||
native_unit_of_measurement=DATA_TERABYTES,
|
||||
icon="mdi:chart-pie",
|
||||
state_class=STATE_CLASS_MEASUREMENT,
|
||||
),
|
||||
SynologyDSMSensorEntityDescription(
|
||||
api_key=SynoStorage.API_KEY,
|
||||
key="volume_percentage_used",
|
||||
name="Volume Used",
|
||||
native_unit_of_measurement=PERCENTAGE,
|
||||
icon="mdi:chart-pie",
|
||||
),
|
||||
SynologyDSMSensorEntityDescription(
|
||||
api_key=SynoStorage.API_KEY,
|
||||
key="volume_disk_temp_avg",
|
||||
name="Average Disk Temp",
|
||||
native_unit_of_measurement=TEMP_CELSIUS,
|
||||
device_class=DEVICE_CLASS_TEMPERATURE,
|
||||
),
|
||||
SynologyDSMSensorEntityDescription(
|
||||
api_key=SynoStorage.API_KEY,
|
||||
key="volume_disk_temp_max",
|
||||
name="Maximum Disk Temp",
|
||||
native_unit_of_measurement=TEMP_CELSIUS,
|
||||
device_class=DEVICE_CLASS_TEMPERATURE,
|
||||
entity_registry_enabled_default=False,
|
||||
),
|
||||
)
|
||||
STORAGE_DISK_SENSORS: tuple[SynologyDSMSensorEntityDescription, ...] = (
|
||||
SynologyDSMSensorEntityDescription(
|
||||
api_key=SynoStorage.API_KEY,
|
||||
key="disk_smart_status",
|
||||
name="Status (Smart)",
|
||||
icon="mdi:checkbox-marked-circle-outline",
|
||||
entity_registry_enabled_default=False,
|
||||
),
|
||||
SynologyDSMSensorEntityDescription(
|
||||
api_key=SynoStorage.API_KEY,
|
||||
key="disk_status",
|
||||
name="Status",
|
||||
icon="mdi:checkbox-marked-circle-outline",
|
||||
),
|
||||
SynologyDSMSensorEntityDescription(
|
||||
api_key=SynoStorage.API_KEY,
|
||||
key="disk_temp",
|
||||
name="Temperature",
|
||||
native_unit_of_measurement=TEMP_CELSIUS,
|
||||
device_class=DEVICE_CLASS_TEMPERATURE,
|
||||
state_class=STATE_CLASS_MEASUREMENT,
|
||||
),
|
||||
)
|
||||
|
||||
INFORMATION_SENSORS: dict[str, EntityInfo] = {
|
||||
f"{SynoDSMInformation.API_KEY}:temperature": {
|
||||
ATTR_NAME: "temperature",
|
||||
ATTR_UNIT_OF_MEASUREMENT: TEMP_CELSIUS,
|
||||
ATTR_ICON: None,
|
||||
ATTR_DEVICE_CLASS: DEVICE_CLASS_TEMPERATURE,
|
||||
ENTITY_ENABLE: True,
|
||||
ATTR_STATE_CLASS: STATE_CLASS_MEASUREMENT,
|
||||
},
|
||||
f"{SynoDSMInformation.API_KEY}:uptime": {
|
||||
ATTR_NAME: "last boot",
|
||||
ATTR_UNIT_OF_MEASUREMENT: None,
|
||||
ATTR_ICON: None,
|
||||
ATTR_DEVICE_CLASS: DEVICE_CLASS_TIMESTAMP,
|
||||
ENTITY_ENABLE: False,
|
||||
ATTR_STATE_CLASS: None,
|
||||
},
|
||||
}
|
||||
INFORMATION_SENSORS: tuple[SynologyDSMSensorEntityDescription, ...] = (
|
||||
SynologyDSMSensorEntityDescription(
|
||||
api_key=SynoDSMInformation.API_KEY,
|
||||
key="temperature",
|
||||
name="temperature",
|
||||
native_unit_of_measurement=TEMP_CELSIUS,
|
||||
device_class=DEVICE_CLASS_TEMPERATURE,
|
||||
state_class=STATE_CLASS_MEASUREMENT,
|
||||
),
|
||||
SynologyDSMSensorEntityDescription(
|
||||
api_key=SynoDSMInformation.API_KEY,
|
||||
key="uptime",
|
||||
name="last boot",
|
||||
device_class=DEVICE_CLASS_TIMESTAMP,
|
||||
entity_registry_enabled_default=False,
|
||||
),
|
||||
)
|
||||
|
||||
# Switch
|
||||
SURVEILLANCE_SWITCH: dict[str, EntityInfo] = {
|
||||
f"{SynoSurveillanceStation.HOME_MODE_API_KEY}:home_mode": {
|
||||
ATTR_NAME: "home mode",
|
||||
ATTR_UNIT_OF_MEASUREMENT: None,
|
||||
ATTR_ICON: "mdi:home-account",
|
||||
ATTR_DEVICE_CLASS: None,
|
||||
ENTITY_ENABLE: True,
|
||||
ATTR_STATE_CLASS: None,
|
||||
},
|
||||
}
|
||||
SURVEILLANCE_SWITCH: tuple[SynologyDSMSwitchEntityDescription, ...] = (
|
||||
SynologyDSMSwitchEntityDescription(
|
||||
api_key=SynoSurveillanceStation.HOME_MODE_API_KEY,
|
||||
key="home_mode",
|
||||
name="home mode",
|
||||
icon="mdi:home-account",
|
||||
),
|
||||
)
|
||||
|
@ -28,7 +28,7 @@ from .const import (
|
||||
STORAGE_VOL_SENSORS,
|
||||
SYNO_API,
|
||||
UTILISATION_SENSORS,
|
||||
EntityInfo,
|
||||
SynologyDSMSensorEntityDescription,
|
||||
)
|
||||
|
||||
|
||||
@ -42,77 +42,77 @@ async def async_setup_entry(
|
||||
coordinator = data[COORDINATOR_CENTRAL]
|
||||
|
||||
entities: list[SynoDSMUtilSensor | SynoDSMStorageSensor | SynoDSMInfoSensor] = [
|
||||
SynoDSMUtilSensor(api, sensor_type, sensor, coordinator)
|
||||
for sensor_type, sensor in UTILISATION_SENSORS.items()
|
||||
SynoDSMUtilSensor(api, coordinator, description)
|
||||
for description in UTILISATION_SENSORS
|
||||
]
|
||||
|
||||
# Handle all volumes
|
||||
if api.storage.volumes_ids:
|
||||
for volume in entry.data.get(CONF_VOLUMES, api.storage.volumes_ids):
|
||||
entities += [
|
||||
SynoDSMStorageSensor(
|
||||
api,
|
||||
sensor_type,
|
||||
sensor,
|
||||
coordinator,
|
||||
volume,
|
||||
)
|
||||
for sensor_type, sensor in STORAGE_VOL_SENSORS.items()
|
||||
entities.extend(
|
||||
[
|
||||
SynoDSMStorageSensor(api, coordinator, description, volume)
|
||||
for volume in entry.data.get(CONF_VOLUMES, api.storage.volumes_ids)
|
||||
for description in STORAGE_VOL_SENSORS
|
||||
]
|
||||
)
|
||||
|
||||
# Handle all disks
|
||||
if api.storage.disks_ids:
|
||||
for disk in entry.data.get(CONF_DISKS, api.storage.disks_ids):
|
||||
entities += [
|
||||
SynoDSMStorageSensor(
|
||||
api,
|
||||
sensor_type,
|
||||
sensor,
|
||||
coordinator,
|
||||
disk,
|
||||
)
|
||||
for sensor_type, sensor in STORAGE_DISK_SENSORS.items()
|
||||
entities.extend(
|
||||
[
|
||||
SynoDSMStorageSensor(api, coordinator, description, disk)
|
||||
for disk in entry.data.get(CONF_DISKS, api.storage.disks_ids)
|
||||
for description in STORAGE_DISK_SENSORS
|
||||
]
|
||||
)
|
||||
|
||||
entities += [
|
||||
SynoDSMInfoSensor(api, sensor_type, sensor, coordinator)
|
||||
for sensor_type, sensor in INFORMATION_SENSORS.items()
|
||||
]
|
||||
entities.extend(
|
||||
[
|
||||
SynoDSMInfoSensor(api, coordinator, description)
|
||||
for description in INFORMATION_SENSORS
|
||||
]
|
||||
)
|
||||
|
||||
async_add_entities(entities)
|
||||
|
||||
|
||||
class SynoDSMSensor(SynologyDSMBaseEntity):
|
||||
class SynoDSMSensor(SynologyDSMBaseEntity, SensorEntity):
|
||||
"""Mixin for sensor specific attributes."""
|
||||
|
||||
@property
|
||||
def native_unit_of_measurement(self) -> str | None:
|
||||
"""Return the unit the value is expressed in."""
|
||||
return self._unit
|
||||
entity_description: SynologyDSMSensorEntityDescription
|
||||
|
||||
def __init__(
|
||||
self,
|
||||
api: SynoApi,
|
||||
coordinator: DataUpdateCoordinator[dict[str, dict[str, Any]]],
|
||||
description: SynologyDSMSensorEntityDescription,
|
||||
) -> None:
|
||||
"""Initialize the Synology DSM sensor entity."""
|
||||
super().__init__(api, coordinator, description)
|
||||
|
||||
|
||||
class SynoDSMUtilSensor(SynoDSMSensor, SensorEntity):
|
||||
class SynoDSMUtilSensor(SynoDSMSensor):
|
||||
"""Representation a Synology Utilisation sensor."""
|
||||
|
||||
@property
|
||||
def native_value(self) -> Any | None:
|
||||
"""Return the state."""
|
||||
attr = getattr(self._api.utilisation, self.entity_type)
|
||||
attr = getattr(self._api.utilisation, self.entity_description.key)
|
||||
if callable(attr):
|
||||
attr = attr()
|
||||
if attr is None:
|
||||
return None
|
||||
|
||||
# Data (RAM)
|
||||
if self._unit == DATA_MEGABYTES:
|
||||
if self.native_unit_of_measurement == DATA_MEGABYTES:
|
||||
return round(attr / 1024.0 ** 2, 1)
|
||||
|
||||
# Network
|
||||
if self._unit == DATA_RATE_KILOBYTES_PER_SECOND:
|
||||
if self.native_unit_of_measurement == DATA_RATE_KILOBYTES_PER_SECOND:
|
||||
return round(attr / 1024.0, 1)
|
||||
|
||||
# CPU load average
|
||||
if self._unit == ENTITY_UNIT_LOAD:
|
||||
if self.native_unit_of_measurement == ENTITY_UNIT_LOAD:
|
||||
return round(attr / 100, 2)
|
||||
|
||||
return attr
|
||||
@ -123,46 +123,57 @@ class SynoDSMUtilSensor(SynoDSMSensor, SensorEntity):
|
||||
return bool(self._api.utilisation)
|
||||
|
||||
|
||||
class SynoDSMStorageSensor(SynologyDSMDeviceEntity, SynoDSMSensor, SensorEntity):
|
||||
class SynoDSMStorageSensor(SynologyDSMDeviceEntity, SynoDSMSensor):
|
||||
"""Representation a Synology Storage sensor."""
|
||||
|
||||
entity_description: SynologyDSMSensorEntityDescription
|
||||
|
||||
def __init__(
|
||||
self,
|
||||
api: SynoApi,
|
||||
coordinator: DataUpdateCoordinator[dict[str, dict[str, Any]]],
|
||||
description: SynologyDSMSensorEntityDescription,
|
||||
device_id: str | None = None,
|
||||
) -> None:
|
||||
"""Initialize the Synology DSM storage sensor entity."""
|
||||
super().__init__(api, coordinator, description, device_id)
|
||||
|
||||
@property
|
||||
def native_value(self) -> Any | None:
|
||||
"""Return the state."""
|
||||
attr = getattr(self._api.storage, self.entity_type)(self._device_id)
|
||||
attr = getattr(self._api.storage, self.entity_description.key)(self._device_id)
|
||||
if attr is None:
|
||||
return None
|
||||
|
||||
# Data (disk space)
|
||||
if self._unit == DATA_TERABYTES:
|
||||
if self.native_unit_of_measurement == DATA_TERABYTES:
|
||||
return round(attr / 1024.0 ** 4, 2)
|
||||
|
||||
return attr
|
||||
|
||||
|
||||
class SynoDSMInfoSensor(SynoDSMSensor, SensorEntity):
|
||||
class SynoDSMInfoSensor(SynoDSMSensor):
|
||||
"""Representation a Synology information sensor."""
|
||||
|
||||
def __init__(
|
||||
self,
|
||||
api: SynoApi,
|
||||
entity_type: str,
|
||||
entity_info: EntityInfo,
|
||||
coordinator: DataUpdateCoordinator[dict[str, dict[str, Any]]],
|
||||
description: SynologyDSMSensorEntityDescription,
|
||||
) -> None:
|
||||
"""Initialize the Synology SynoDSMInfoSensor entity."""
|
||||
super().__init__(api, entity_type, entity_info, coordinator)
|
||||
super().__init__(api, coordinator, description)
|
||||
self._previous_uptime: str | None = None
|
||||
self._last_boot: str | None = None
|
||||
|
||||
@property
|
||||
def native_value(self) -> Any | None:
|
||||
"""Return the state."""
|
||||
attr = getattr(self._api.information, self.entity_type)
|
||||
attr = getattr(self._api.information, self.entity_description.key)
|
||||
if attr is None:
|
||||
return None
|
||||
|
||||
if self.entity_type == "uptime":
|
||||
if self.entity_description.key == "uptime":
|
||||
# reboot happened or entity creation
|
||||
if self._previous_uptime is None or self._previous_uptime > attr:
|
||||
last_boot = utcnow() - timedelta(seconds=attr)
|
||||
|
@ -19,7 +19,7 @@ from .const import (
|
||||
DOMAIN,
|
||||
SURVEILLANCE_SWITCH,
|
||||
SYNO_API,
|
||||
EntityInfo,
|
||||
SynologyDSMSwitchEntityDescription,
|
||||
)
|
||||
|
||||
_LOGGER = logging.getLogger(__name__)
|
||||
@ -42,12 +42,14 @@ async def async_setup_entry(
|
||||
# initial data fetch
|
||||
coordinator: DataUpdateCoordinator = data[COORDINATOR_SWITCHES]
|
||||
await coordinator.async_refresh()
|
||||
entities += [
|
||||
SynoDSMSurveillanceHomeModeToggle(
|
||||
api, sensor_type, switch, version, coordinator
|
||||
)
|
||||
for sensor_type, switch in SURVEILLANCE_SWITCH.items()
|
||||
]
|
||||
entities.extend(
|
||||
[
|
||||
SynoDSMSurveillanceHomeModeToggle(
|
||||
api, version, coordinator, description
|
||||
)
|
||||
for description in SURVEILLANCE_SWITCH
|
||||
]
|
||||
)
|
||||
|
||||
async_add_entities(entities, True)
|
||||
|
||||
@ -56,28 +58,23 @@ class SynoDSMSurveillanceHomeModeToggle(SynologyDSMBaseEntity, ToggleEntity):
|
||||
"""Representation a Synology Surveillance Station Home Mode toggle."""
|
||||
|
||||
coordinator: DataUpdateCoordinator[dict[str, dict[str, bool]]]
|
||||
entity_description: SynologyDSMSwitchEntityDescription
|
||||
|
||||
def __init__(
|
||||
self,
|
||||
api: SynoApi,
|
||||
entity_type: str,
|
||||
entity_info: EntityInfo,
|
||||
version: str,
|
||||
coordinator: DataUpdateCoordinator[dict[str, dict[str, bool]]],
|
||||
description: SynologyDSMSwitchEntityDescription,
|
||||
) -> None:
|
||||
"""Initialize a Synology Surveillance Station Home Mode."""
|
||||
super().__init__(
|
||||
api,
|
||||
entity_type,
|
||||
entity_info,
|
||||
coordinator,
|
||||
)
|
||||
super().__init__(api, coordinator, description)
|
||||
self._version = version
|
||||
|
||||
@property
|
||||
def is_on(self) -> bool:
|
||||
"""Return the state."""
|
||||
return self.coordinator.data["switches"][self.entity_type]
|
||||
return self.coordinator.data["switches"][self.entity_description.key]
|
||||
|
||||
async def async_turn_on(self, **kwargs: Any) -> None:
|
||||
"""Turn on Home mode."""
|
||||
|
Loading…
x
Reference in New Issue
Block a user