From 1d816d25f71cd5d749798b62fc0a764115f356d5 Mon Sep 17 00:00:00 2001 From: Quentame Date: Wed, 30 Sep 2020 18:27:06 +0200 Subject: [PATCH] Add Surveillance Station home mode switch for Synology DSM (#40490) * Use camera name as device name * Add Surveillance Station home mode switch for Synology DSM - camera uses Surveillance Station as device parent - camera uses camera name instead of NAS name + camera name * Without device_class otherwise no icon * Update .coveragerc --- .coveragerc | 3 +- .../components/synology_dsm/camera.py | 8 +- .../components/synology_dsm/const.py | 34 ++++--- .../components/synology_dsm/switch.py | 98 +++++++++++++++++++ 4 files changed, 129 insertions(+), 14 deletions(-) create mode 100644 homeassistant/components/synology_dsm/switch.py diff --git a/.coveragerc b/.coveragerc index eb137602a75..377391b38ad 100644 --- a/.coveragerc +++ b/.coveragerc @@ -844,9 +844,10 @@ omit = homeassistant/components/synology/camera.py homeassistant/components/synology_chat/notify.py homeassistant/components/synology_dsm/__init__.py - homeassistant/components/synology_dsm/camera.py homeassistant/components/synology_dsm/binary_sensor.py + homeassistant/components/synology_dsm/camera.py homeassistant/components/synology_dsm/sensor.py + homeassistant/components/synology_dsm/switch.py homeassistant/components/synology_srm/device_tracker.py homeassistant/components/syslog/notify.py homeassistant/components/systemmonitor/sensor.py diff --git a/homeassistant/components/synology_dsm/camera.py b/homeassistant/components/synology_dsm/camera.py index 4cb34ee0431..80e6802e443 100644 --- a/homeassistant/components/synology_dsm/camera.py +++ b/homeassistant/components/synology_dsm/camera.py @@ -60,9 +60,13 @@ class SynoDSMCamera(SynologyDSMEntity, Camera): """Return the device information.""" return { "identifiers": {(DOMAIN, self._api.information.serial, self._camera.id)}, - "name": self.name, + "name": self._camera.name, "model": self._camera.model, - "via_device": (DOMAIN, self._api.information.serial), + "via_device": ( + DOMAIN, + self._api.information.serial, + SynoSurveillanceStation.INFO_API_KEY, + ), } @property diff --git a/homeassistant/components/synology_dsm/const.py b/homeassistant/components/synology_dsm/const.py index 0941bcb916b..82bb232461e 100644 --- a/homeassistant/components/synology_dsm/const.py +++ b/homeassistant/components/synology_dsm/const.py @@ -4,6 +4,7 @@ from synology_dsm.api.core.security import SynoCoreSecurity from synology_dsm.api.core.utilization import SynoCoreUtilization from synology_dsm.api.dsm.information import SynoDSMInformation from synology_dsm.api.storage.storage import SynoStorage +from synology_dsm.api.surveillance_station import SynoSurveillanceStation from homeassistant.components.binary_sensor import DEVICE_CLASS_SAFETY from homeassistant.const import ( @@ -16,7 +17,7 @@ from homeassistant.const import ( ) DOMAIN = "synology_dsm" -PLATFORMS = ["binary_sensor", "camera", "sensor"] +PLATFORMS = ["binary_sensor", "camera", "sensor", "switch"] # Entry keys SYNO_API = "syno_api" @@ -42,6 +43,16 @@ ENTITY_ENABLE = "enable" # Entity keys should start with the API_KEY to fetch # Binary sensors +SECURITY_BINARY_SENSORS = { + f"{SynoCoreSecurity.API_KEY}:status": { + ENTITY_NAME: "Security status", + ENTITY_UNIT: None, + ENTITY_ICON: None, + ENTITY_CLASS: DEVICE_CLASS_SAFETY, + ENTITY_ENABLE: True, + }, +} + STORAGE_DISK_BINARY_SENSORS = { f"{SynoStorage.API_KEY}:disk_exceed_bad_sector_thr": { ENTITY_NAME: "Exceeded Max Bad Sectors", @@ -59,16 +70,6 @@ STORAGE_DISK_BINARY_SENSORS = { }, } -SECURITY_BINARY_SENSORS = { - f"{SynoCoreSecurity.API_KEY}:status": { - ENTITY_NAME: "Security status", - ENTITY_UNIT: None, - ENTITY_ICON: None, - ENTITY_CLASS: DEVICE_CLASS_SAFETY, - ENTITY_ENABLE: True, - }, -} - # Sensors UTILISATION_SENSORS = { f"{SynoCoreUtilization.API_KEY}:cpu_other_load": { @@ -269,6 +270,17 @@ INFORMATION_SENSORS = { }, } +# Switch +SURVEILLANCE_SWITCH = { + f"{SynoSurveillanceStation.HOME_MODE_API_KEY}:home_mode": { + ENTITY_NAME: "home mode", + ENTITY_UNIT: None, + ENTITY_ICON: "mdi:home-account", + ENTITY_CLASS: None, + ENTITY_ENABLE: True, + }, +} + TEMP_SENSORS_KEYS = [ "volume_disk_temp_avg", diff --git a/homeassistant/components/synology_dsm/switch.py b/homeassistant/components/synology_dsm/switch.py new file mode 100644 index 00000000000..ee29c9f2692 --- /dev/null +++ b/homeassistant/components/synology_dsm/switch.py @@ -0,0 +1,98 @@ +"""Support for Synology DSM switch.""" +from typing import Dict + +from synology_dsm.api.surveillance_station import SynoSurveillanceStation + +from homeassistant.components.switch import ToggleEntity +from homeassistant.config_entries import ConfigEntry +from homeassistant.helpers.typing import HomeAssistantType + +from . import SynoApi, SynologyDSMEntity +from .const import DOMAIN, SURVEILLANCE_SWITCH, SYNO_API + + +async def async_setup_entry( + hass: HomeAssistantType, entry: ConfigEntry, async_add_entities +) -> None: + """Set up the Synology NAS switch.""" + + api = hass.data[DOMAIN][entry.unique_id][SYNO_API] + + entities = [] + + if SynoSurveillanceStation.INFO_API_KEY in api.dsm.apis: + info = await hass.async_add_executor_job(api.dsm.surveillance_station.get_info) + version = info["data"]["CMSMinVersion"] + entities += [ + SynoDSMSurveillanceHomeModeToggle( + api, sensor_type, SURVEILLANCE_SWITCH[sensor_type], version + ) + for sensor_type in SURVEILLANCE_SWITCH + ] + + async_add_entities(entities, True) + + +class SynoDSMSurveillanceHomeModeToggle(SynologyDSMEntity, ToggleEntity): + """Representation a Synology Surveillance Station Home Mode toggle.""" + + def __init__( + self, api: SynoApi, entity_type: str, entity_info: Dict[str, str], version: str + ): + """Initialize a Synology Surveillance Station Home Mode.""" + super().__init__( + api, + entity_type, + entity_info, + ) + self._version = version + self._state = None + + @property + def is_on(self) -> bool: + """Return the state.""" + if self.entity_type == "home_mode": + return self._state + return None + + @property + def should_poll(self) -> bool: + """No polling needed.""" + return True + + async def async_update(self): + """Update the toggle state.""" + self._state = await self.hass.async_add_executor_job( + self._api.surveillance_station.get_home_mode_status + ) + + def turn_on(self, **kwargs) -> None: + """Turn on Home mode.""" + self._api.surveillance_station.set_home_mode(True) + + def turn_off(self, **kwargs) -> None: + """Turn off Home mode.""" + self._api.surveillance_station.set_home_mode(False) + + @property + def available(self) -> bool: + """Return True if entity is available.""" + return bool(self._api.surveillance_station) + + @property + def device_info(self) -> Dict[str, any]: + """Return the device information.""" + return { + "identifiers": { + ( + DOMAIN, + self._api.information.serial, + SynoSurveillanceStation.INFO_API_KEY, + ) + }, + "name": "Surveillance Station", + "manufacturer": "Synology", + "model": self._api.information.model, + "sw_version": self._version, + "via_device": (DOMAIN, self._api.information.serial), + }