mirror of
https://github.com/home-assistant/core.git
synced 2026-07-13 17:44:45 +01:00
Add fan speed mode control to Synology DSM (#173051)
Co-authored-by: Joostlek <joostlek@outlook.com>
This commit is contained in:
@@ -8,6 +8,7 @@ import logging
|
||||
from awesomeversion import AwesomeVersion
|
||||
from synology_dsm import SynologyDSM
|
||||
from synology_dsm.api.core.external_usb import SynoCoreExternalUSB
|
||||
from synology_dsm.api.core.hardware import SynoCoreHardware
|
||||
from synology_dsm.api.core.security import SynoCoreSecurity
|
||||
from synology_dsm.api.core.system import SynoCoreSystem
|
||||
from synology_dsm.api.core.upgrade import SynoCoreUpgrade
|
||||
@@ -68,6 +69,7 @@ class SynoApi:
|
||||
|
||||
# DSM APIs
|
||||
self.file_station: SynoFileStation | None = None
|
||||
self.hardware: SynoCoreHardware | None = None
|
||||
self.information: SynoDSMInformation | None = None
|
||||
self.network: SynoDSMNetwork | None = None
|
||||
self.photos: SynoPhotos | None = None
|
||||
@@ -82,6 +84,7 @@ class SynoApi:
|
||||
# Should we fetch them
|
||||
self._fetching_entities: dict[str, set[str]] = {}
|
||||
self._with_file_station = True
|
||||
self._with_hardware = True
|
||||
self._with_information = True
|
||||
self._with_photos = True
|
||||
self._with_security = True
|
||||
@@ -205,6 +208,14 @@ class SynoApi:
|
||||
self._with_file_station,
|
||||
)
|
||||
|
||||
# check if hardware info is available
|
||||
try:
|
||||
await self.dsm.hardware.update()
|
||||
except SYNOLOGY_CONNECTION_EXCEPTIONS as ex:
|
||||
self._with_hardware = False
|
||||
self.dsm.reset(SynoCoreHardware.API_KEY)
|
||||
LOGGER.debug("Disabled fetching hardware data during setup: %s", ex)
|
||||
|
||||
await self._fetch_device_configuration()
|
||||
|
||||
try:
|
||||
@@ -265,6 +276,9 @@ class SynoApi:
|
||||
self._with_external_usb = bool(
|
||||
self._fetching_entities.get(SynoCoreExternalUSB.API_KEY)
|
||||
)
|
||||
self._with_hardware = bool(
|
||||
self._fetching_entities.get(SynoCoreHardware.API_KEY)
|
||||
)
|
||||
|
||||
# Reset not used API, information is not reset since it's used in device_info
|
||||
if not self._with_security:
|
||||
@@ -335,6 +349,15 @@ class SynoApi:
|
||||
self.dsm.reset(self.external_usb)
|
||||
self.external_usb = None
|
||||
|
||||
if not self._with_hardware:
|
||||
LOGGER.debug(
|
||||
"Disable hardware api from being updated for '%s'",
|
||||
self._entry.unique_id,
|
||||
)
|
||||
if self.hardware:
|
||||
self.dsm.reset(self.hardware)
|
||||
self.hardware = None
|
||||
|
||||
async def _fetch_device_configuration(self) -> None:
|
||||
"""Fetch initial device config."""
|
||||
self.network = self.dsm.network
|
||||
@@ -385,6 +408,10 @@ class SynoApi:
|
||||
)
|
||||
self.external_usb = self.dsm.external_usb
|
||||
|
||||
if self._with_hardware:
|
||||
LOGGER.debug("Enable hardware api updates for '%s'", self._entry.unique_id)
|
||||
self.hardware = self.dsm.hardware
|
||||
|
||||
async def _syno_api_executer(self, api_call: Callable) -> None:
|
||||
"""Synology api call wrapper."""
|
||||
try:
|
||||
|
||||
@@ -6,6 +6,7 @@ from aiohttp import ClientTimeout
|
||||
from synology_dsm.api.surveillance_station.const import SNAPSHOT_PROFILE_BALANCED
|
||||
from synology_dsm.exceptions import (
|
||||
SynologyDSMAPIErrorException,
|
||||
SynologyDSMAPINoDataException,
|
||||
SynologyDSMLogin2SARequiredException,
|
||||
SynologyDSMLoginDisabledAccountException,
|
||||
SynologyDSMLoginFailedException,
|
||||
@@ -26,6 +27,7 @@ PLATFORMS = [
|
||||
Platform.BINARY_SENSOR,
|
||||
Platform.BUTTON,
|
||||
Platform.CAMERA,
|
||||
Platform.SELECT,
|
||||
Platform.SENSOR,
|
||||
Platform.SWITCH,
|
||||
Platform.UPDATE,
|
||||
@@ -76,6 +78,7 @@ SYNOLOGY_AUTH_FAILED_EXCEPTIONS = (
|
||||
|
||||
SYNOLOGY_CONNECTION_EXCEPTIONS = (
|
||||
SynologyDSMAPIErrorException,
|
||||
SynologyDSMAPINoDataException,
|
||||
SynologyDSMLoginFailedException,
|
||||
SynologyDSMRequestException,
|
||||
)
|
||||
|
||||
@@ -63,6 +63,11 @@ async def async_get_config_entry_diagnostics(
|
||||
"size_total": partition.partition_size_total(False),
|
||||
}
|
||||
|
||||
if syno_api.hardware is not None:
|
||||
diag_data["device_info"]["fan_speed_mode"] = (
|
||||
syno_api.dsm.hardware.fan_speed.value
|
||||
)
|
||||
|
||||
if syno_api.network is not None:
|
||||
for intf in syno_api.network.interfaces:
|
||||
diag_data["network"]["interfaces"][intf["id"]] = {
|
||||
|
||||
@@ -5,6 +5,16 @@
|
||||
"default": "mdi:power"
|
||||
}
|
||||
},
|
||||
"select": {
|
||||
"fan_speed_mode": {
|
||||
"default": "mdi:fan",
|
||||
"state": {
|
||||
"cool": "mdi:fan-speed-2",
|
||||
"full_speed": "mdi:fan-speed-3",
|
||||
"quiet": "mdi:fan-speed-1"
|
||||
}
|
||||
}
|
||||
},
|
||||
"sensor": {
|
||||
"cpu_15min_load": {
|
||||
"default": "mdi:chip"
|
||||
|
||||
@@ -0,0 +1,77 @@
|
||||
"""Support for Synology DSM select entities."""
|
||||
|
||||
from dataclasses import dataclass
|
||||
from typing import override
|
||||
|
||||
from synology_dsm.api.core.hardware import FanSpeed, SynoCoreHardware
|
||||
|
||||
from homeassistant.components.select import SelectEntity, SelectEntityDescription
|
||||
from homeassistant.const import EntityCategory
|
||||
from homeassistant.core import HomeAssistant
|
||||
from homeassistant.helpers.entity_platform import AddConfigEntryEntitiesCallback
|
||||
|
||||
from . import SynoApi
|
||||
from .coordinator import SynologyDSMCentralUpdateCoordinator, SynologyDSMConfigEntry
|
||||
from .entity import SynologyDSMBaseEntity, SynologyDSMEntityDescription
|
||||
|
||||
FAN_SPEED_MAP = {
|
||||
FanSpeed.QUIET: "quiet",
|
||||
FanSpeed.COOL: "cool",
|
||||
FanSpeed.FULL: "full_speed",
|
||||
}
|
||||
FAN_SPEED_MAP_INVERSE = {v: k for k, v in FAN_SPEED_MAP.items()}
|
||||
|
||||
|
||||
@dataclass(frozen=True, kw_only=True)
|
||||
class SynologyDSMSelectEntityDescription(
|
||||
SynologyDSMEntityDescription, SelectEntityDescription
|
||||
):
|
||||
"""Describes Synology DSM select entity."""
|
||||
|
||||
|
||||
async def async_setup_entry(
|
||||
hass: HomeAssistant,
|
||||
entry: SynologyDSMConfigEntry,
|
||||
async_add_entities: AddConfigEntryEntitiesCallback,
|
||||
) -> None:
|
||||
"""Set select entities for device."""
|
||||
data = entry.runtime_data
|
||||
if data.api.hardware is not None:
|
||||
async_add_entities(
|
||||
[SynologyDSMFanSpeedMode(data.api, data.coordinator_central)]
|
||||
)
|
||||
|
||||
|
||||
class SynologyDSMFanSpeedMode(
|
||||
SynologyDSMBaseEntity[SynologyDSMCentralUpdateCoordinator], SelectEntity
|
||||
):
|
||||
"""Represent a Synology DSM fan speed mode select entity."""
|
||||
|
||||
_attr_options = list(FAN_SPEED_MAP.values())
|
||||
entity_description: SynologyDSMSelectEntityDescription
|
||||
|
||||
def __init__(
|
||||
self,
|
||||
api: SynoApi,
|
||||
coordinator: SynologyDSMCentralUpdateCoordinator,
|
||||
) -> None:
|
||||
"""Initialize a Synology DSM select entity."""
|
||||
description = SynologyDSMSelectEntityDescription(
|
||||
api_key=SynoCoreHardware.API_KEY,
|
||||
key="fan_speed_mode",
|
||||
translation_key="fan_speed_mode",
|
||||
entity_category=EntityCategory.CONFIG,
|
||||
)
|
||||
super().__init__(api, coordinator, description)
|
||||
|
||||
@property
|
||||
def current_option(self) -> str | None:
|
||||
"""Return the selected entity option to represent the entity state."""
|
||||
return FAN_SPEED_MAP[self._api.dsm.hardware.fan_speed]
|
||||
|
||||
@override
|
||||
async def async_select_option(self, option: str) -> None:
|
||||
"""Set the fan speed mode."""
|
||||
await self._api.dsm.hardware.set_fan_speed(FAN_SPEED_MAP_INVERSE[option])
|
||||
await self._api.dsm.hardware.update()
|
||||
self.async_write_ha_state()
|
||||
@@ -81,6 +81,16 @@
|
||||
"name": "Shut down"
|
||||
}
|
||||
},
|
||||
"select": {
|
||||
"fan_speed_mode": {
|
||||
"name": "Fan speed mode",
|
||||
"state": {
|
||||
"cool": "Cool mode",
|
||||
"full_speed": "Full-speed mode",
|
||||
"quiet": "Quiet mode"
|
||||
}
|
||||
}
|
||||
},
|
||||
"sensor": {
|
||||
"cpu_15min_load": {
|
||||
"name": "CPU load average (15 min)"
|
||||
|
||||
@@ -4,11 +4,17 @@ from unittest.mock import AsyncMock, Mock
|
||||
|
||||
from awesomeversion import AwesomeVersion
|
||||
from synology_dsm.api.core.external_usb import SynoCoreExternalUSBDevice
|
||||
from synology_dsm.api.core.hardware import FanSpeed
|
||||
from synology_dsm.api.storage.storage import SynoStorageDisk, SynoStorageVolume
|
||||
|
||||
from .consts import SERIAL
|
||||
|
||||
|
||||
def mock_dsm_hardware(fan_speed: FanSpeed = FanSpeed.COOL) -> Mock:
|
||||
"""Mock SynologyDSM hardware information."""
|
||||
return AsyncMock(update=AsyncMock(), fan_speed=fan_speed)
|
||||
|
||||
|
||||
def mock_dsm_information(
|
||||
serial: str | None = SERIAL,
|
||||
update_result: bool = True,
|
||||
|
||||
@@ -8,7 +8,7 @@ import pytest
|
||||
from homeassistant.core import HomeAssistant
|
||||
from homeassistant.setup import async_setup_component
|
||||
|
||||
from .common import mock_dsm_information
|
||||
from .common import mock_dsm_hardware, mock_dsm_information
|
||||
|
||||
|
||||
@pytest.fixture
|
||||
@@ -35,6 +35,7 @@ def fixture_dsm():
|
||||
|
||||
dsm.information = mock_dsm_information()
|
||||
dsm.network.update = AsyncMock(return_value=True)
|
||||
dsm.hardware = mock_dsm_hardware()
|
||||
dsm.surveillance_station.update = AsyncMock(return_value=True)
|
||||
dsm.upgrade.update = AsyncMock(return_value=True)
|
||||
dsm.file = AsyncMock(get_shared_folders=AsyncMock(return_value=None))
|
||||
|
||||
@@ -2,6 +2,7 @@
|
||||
# name: test_entry_diagnostics
|
||||
dict({
|
||||
'device_info': dict({
|
||||
'fan_speed_mode': 'coolfan',
|
||||
'model': 'DS1821+',
|
||||
'ram': 32768,
|
||||
'temperature': 58,
|
||||
|
||||
@@ -0,0 +1,63 @@
|
||||
# serializer version: 1
|
||||
# name: test_fan_speed[select.nas_meontheinternet_com_fan_speed_mode-entry]
|
||||
EntityRegistryEntrySnapshot({
|
||||
'aliases': list([
|
||||
None,
|
||||
]),
|
||||
'area_id': None,
|
||||
'capabilities': dict({
|
||||
'options': list([
|
||||
'quiet',
|
||||
'cool',
|
||||
'full_speed',
|
||||
]),
|
||||
}),
|
||||
'config_entry_id': <ANY>,
|
||||
'config_subentry_id': <ANY>,
|
||||
'device_class': None,
|
||||
'device_id': <ANY>,
|
||||
'disabled_by': None,
|
||||
'domain': 'select',
|
||||
'entity_category': <EntityCategory.CONFIG: 'config'>,
|
||||
'entity_id': 'select.nas_meontheinternet_com_fan_speed_mode',
|
||||
'has_entity_name': True,
|
||||
'hidden_by': None,
|
||||
'icon': None,
|
||||
'id': <ANY>,
|
||||
'labels': set({
|
||||
}),
|
||||
'name': None,
|
||||
'object_id_base': 'Fan speed mode',
|
||||
'options': dict({
|
||||
}),
|
||||
'original_device_class': None,
|
||||
'original_icon': None,
|
||||
'original_name': 'Fan speed mode',
|
||||
'platform': 'synology_dsm',
|
||||
'previous_unique_id': None,
|
||||
'suggested_object_id': None,
|
||||
'supported_features': 0,
|
||||
'translation_key': 'fan_speed_mode',
|
||||
'unique_id': 'mySerial_SYNO.Core.Hardware:fan_speed_mode',
|
||||
'unit_of_measurement': None,
|
||||
})
|
||||
# ---
|
||||
# name: test_fan_speed[select.nas_meontheinternet_com_fan_speed_mode-state]
|
||||
StateSnapshot({
|
||||
'attributes': ReadOnlyDict({
|
||||
'attribution': 'Data provided by Synology',
|
||||
'friendly_name': 'nas.meontheinternet.com Fan speed mode',
|
||||
'options': list([
|
||||
'quiet',
|
||||
'cool',
|
||||
'full_speed',
|
||||
]),
|
||||
}),
|
||||
'context': <ANY>,
|
||||
'entity_id': 'select.nas_meontheinternet_com_fan_speed_mode',
|
||||
'last_changed': <ANY>,
|
||||
'last_reported': <ANY>,
|
||||
'last_updated': <ANY>,
|
||||
'state': 'cool',
|
||||
})
|
||||
# ---
|
||||
@@ -35,7 +35,7 @@ from homeassistant.core import HomeAssistant
|
||||
from homeassistant.setup import async_setup_component
|
||||
from homeassistant.util.aiohttp import MockStreamReader, MockStreamReaderChunked
|
||||
|
||||
from .common import mock_dsm_information
|
||||
from .common import mock_dsm_hardware, mock_dsm_information
|
||||
from .consts import HOST, MACS, PASSWORD, PORT, USE_SSL, USERNAME
|
||||
|
||||
from tests.common import MockConfigEntry
|
||||
@@ -93,6 +93,7 @@ def mock_dsm_with_filestation():
|
||||
dsm.upgrade.update = AsyncMock(return_value=True)
|
||||
dsm.utilisation = Mock(cpu_user_load=1, update=AsyncMock(return_value=True))
|
||||
dsm.network = Mock(update=AsyncMock(return_value=True), macs=MACS)
|
||||
dsm.hardware = mock_dsm_hardware()
|
||||
dsm.storage = Mock(
|
||||
disks_ids=["sda", "sdb", "sdc"],
|
||||
volumes_ids=["volume_1"],
|
||||
@@ -146,6 +147,7 @@ def mock_dsm_without_filestation():
|
||||
dsm.upgrade.update = AsyncMock(return_value=True)
|
||||
dsm.utilisation = Mock(cpu_user_load=1, update=AsyncMock(return_value=True))
|
||||
dsm.network = Mock(update=AsyncMock(return_value=True), macs=MACS)
|
||||
dsm.hardware = mock_dsm_hardware()
|
||||
dsm.information = mock_dsm_information()
|
||||
dsm.storage = Mock(
|
||||
disks_ids=["sda", "sdb", "sdc"],
|
||||
|
||||
@@ -40,7 +40,7 @@ from homeassistant.helpers.service_info.ssdp import (
|
||||
)
|
||||
from homeassistant.helpers.service_info.zeroconf import ZeroconfServiceInfo
|
||||
|
||||
from .common import mock_dsm_information
|
||||
from .common import mock_dsm_hardware, mock_dsm_information
|
||||
from .consts import (
|
||||
DEVICE_TOKEN,
|
||||
HOST,
|
||||
@@ -68,6 +68,7 @@ def mock_controller_service():
|
||||
dsm.upgrade.update = AsyncMock(return_value=True)
|
||||
dsm.utilisation = Mock(cpu_user_load=1, update=AsyncMock(return_value=True))
|
||||
dsm.network = Mock(update=AsyncMock(return_value=True), macs=MACS)
|
||||
dsm.hardware = mock_dsm_hardware()
|
||||
dsm.storage = Mock(
|
||||
disks_ids=["sda", "sdb", "sdc"],
|
||||
volumes_ids=["volume_1"],
|
||||
@@ -91,6 +92,7 @@ def mock_controller_service_2sa():
|
||||
dsm.upgrade.update = AsyncMock(return_value=True)
|
||||
dsm.utilisation = Mock(cpu_user_load=1, update=AsyncMock(return_value=True))
|
||||
dsm.network = Mock(update=AsyncMock(return_value=True), macs=MACS)
|
||||
dsm.hardware = mock_dsm_hardware()
|
||||
dsm.storage = Mock(
|
||||
disks_ids=["sda", "sdb", "sdc"],
|
||||
volumes_ids=["volume_1"],
|
||||
@@ -112,6 +114,7 @@ def mock_controller_service_vdsm():
|
||||
dsm.upgrade.update = AsyncMock(return_value=True)
|
||||
dsm.utilisation = Mock(cpu_user_load=1, update=AsyncMock(return_value=True))
|
||||
dsm.network = Mock(update=AsyncMock(return_value=True), macs=MACS)
|
||||
dsm.hardware = mock_dsm_hardware()
|
||||
dsm.storage = Mock(
|
||||
disks_ids=[],
|
||||
volumes_ids=["volume_1"],
|
||||
@@ -133,6 +136,7 @@ def mock_controller_service_with_filestation():
|
||||
dsm.upgrade.update = AsyncMock(return_value=True)
|
||||
dsm.utilisation = Mock(cpu_user_load=1, update=AsyncMock(return_value=True))
|
||||
dsm.network = Mock(update=AsyncMock(return_value=True), macs=MACS)
|
||||
dsm.hardware = mock_dsm_hardware()
|
||||
dsm.storage = Mock(
|
||||
disks_ids=["sda", "sdb", "sdc"],
|
||||
volumes_ids=["volume_1"],
|
||||
@@ -166,6 +170,7 @@ def mock_controller_service_failed():
|
||||
dsm.upgrade.update = AsyncMock(return_value=True)
|
||||
dsm.utilisation = Mock(cpu_user_load=None, update=AsyncMock(return_value=True))
|
||||
dsm.network = Mock(update=AsyncMock(return_value=True), macs=[])
|
||||
dsm.hardware = mock_dsm_hardware()
|
||||
dsm.storage = Mock(
|
||||
disks_ids=[],
|
||||
volumes_ids=[],
|
||||
|
||||
@@ -19,7 +19,7 @@ from homeassistant.const import (
|
||||
)
|
||||
from homeassistant.core import HomeAssistant
|
||||
|
||||
from .common import mock_dsm_information
|
||||
from .common import mock_dsm_hardware, mock_dsm_information
|
||||
from .consts import HOST, MACS, PASSWORD, PORT, SERIAL, USE_SSL, USERNAME
|
||||
|
||||
from tests.common import MockConfigEntry
|
||||
@@ -92,6 +92,7 @@ def mock_dsm_with_usb():
|
||||
)
|
||||
],
|
||||
)
|
||||
dsm.hardware = mock_dsm_hardware()
|
||||
dsm.information = mock_dsm_information()
|
||||
dsm.file = Mock(get_shared_folders=AsyncMock(return_value=None))
|
||||
dsm.external_usb = Mock(
|
||||
|
||||
@@ -28,7 +28,7 @@ from homeassistant.const import (
|
||||
from homeassistant.core import HomeAssistant
|
||||
from homeassistant.util.aiohttp import MockRequest
|
||||
|
||||
from .common import mock_dsm_information
|
||||
from .common import mock_dsm_hardware, mock_dsm_information
|
||||
from .consts import HOST, MACS, PASSWORD, PORT, USE_SSL, USERNAME
|
||||
|
||||
from tests.common import MockConfigEntry
|
||||
@@ -42,6 +42,7 @@ def dsm_with_photos() -> MagicMock:
|
||||
dsm.update = AsyncMock(return_value=True)
|
||||
dsm.information = mock_dsm_information()
|
||||
dsm.network.update = AsyncMock(return_value=True)
|
||||
dsm.hardware = mock_dsm_hardware()
|
||||
dsm.surveillance_station.update = AsyncMock(return_value=True)
|
||||
dsm.upgrade.update = AsyncMock(return_value=True)
|
||||
|
||||
|
||||
@@ -23,7 +23,7 @@ from homeassistant.core import HomeAssistant
|
||||
from homeassistant.helpers import issue_registry as ir
|
||||
from homeassistant.setup import async_setup_component
|
||||
|
||||
from .common import mock_dsm_information
|
||||
from .common import mock_dsm_hardware, mock_dsm_information
|
||||
from .consts import HOST, MACS, PASSWORD, PORT, USE_SSL, USERNAME
|
||||
|
||||
from tests.common import ANY, MockConfigEntry
|
||||
@@ -42,6 +42,7 @@ def mock_dsm_with_filestation():
|
||||
dsm.upgrade.update = AsyncMock(return_value=True)
|
||||
dsm.utilisation = Mock(cpu_user_load=1, update=AsyncMock(return_value=True))
|
||||
dsm.network = Mock(update=AsyncMock(return_value=True), macs=MACS)
|
||||
dsm.hardware = mock_dsm_hardware()
|
||||
dsm.storage = Mock(
|
||||
disks_ids=["sda", "sdb", "sdc"],
|
||||
volumes_ids=["volume_1"],
|
||||
|
||||
@@ -0,0 +1,129 @@
|
||||
"""Tests for Synology DSM select entities."""
|
||||
|
||||
from unittest.mock import AsyncMock, MagicMock, Mock, patch
|
||||
|
||||
from pylint_home_assistant.const import Platform
|
||||
import pytest
|
||||
from synology_dsm.api.core.hardware import FanSpeed
|
||||
from syrupy.assertion import SnapshotAssertion
|
||||
|
||||
from homeassistant.components.select import (
|
||||
DOMAIN as SELECT_DOMAIN,
|
||||
SERVICE_SELECT_OPTION,
|
||||
)
|
||||
from homeassistant.components.synology_dsm.const import DOMAIN
|
||||
from homeassistant.const import (
|
||||
ATTR_ENTITY_ID,
|
||||
ATTR_OPTION,
|
||||
CONF_HOST,
|
||||
CONF_MAC,
|
||||
CONF_PASSWORD,
|
||||
CONF_PORT,
|
||||
CONF_SSL,
|
||||
CONF_USERNAME,
|
||||
)
|
||||
from homeassistant.core import HomeAssistant
|
||||
from homeassistant.helpers import entity_registry as er
|
||||
|
||||
from .common import mock_dsm_hardware, mock_dsm_information
|
||||
from .consts import HOST, MACS, PASSWORD, PORT, SERIAL, USE_SSL, USERNAME
|
||||
|
||||
from tests.common import MockConfigEntry, snapshot_platform
|
||||
|
||||
|
||||
@pytest.fixture
|
||||
def mock_dsm():
|
||||
"""Mock a successful service."""
|
||||
with patch("homeassistant.components.synology_dsm.common.SynologyDSM") as dsm:
|
||||
dsm.login = AsyncMock(return_value=True)
|
||||
dsm.update = AsyncMock(return_value=True)
|
||||
|
||||
dsm.surveillance_station.update = AsyncMock(return_value=True)
|
||||
dsm.upgrade.update = AsyncMock(return_value=True)
|
||||
dsm.network = Mock(
|
||||
update=AsyncMock(return_value=True), macs=MACS, hostname=HOST
|
||||
)
|
||||
dsm.hardware = mock_dsm_hardware()
|
||||
dsm.information = mock_dsm_information()
|
||||
dsm.file = Mock(get_shared_folders=AsyncMock(return_value=None))
|
||||
dsm.logout = AsyncMock(return_value=True)
|
||||
yield dsm
|
||||
|
||||
|
||||
async def test_fan_speed(
|
||||
hass: HomeAssistant,
|
||||
entity_registry: er.EntityRegistry,
|
||||
snapshot: SnapshotAssertion,
|
||||
mock_dsm: MagicMock,
|
||||
) -> None:
|
||||
"""Test Synology DSM fan speed mode select entity."""
|
||||
with (
|
||||
patch(
|
||||
"homeassistant.components.synology_dsm.common.SynologyDSM",
|
||||
return_value=mock_dsm,
|
||||
),
|
||||
patch("homeassistant.components.synology_dsm.PLATFORMS", ["select"]),
|
||||
):
|
||||
entry = MockConfigEntry(
|
||||
domain=DOMAIN,
|
||||
data={
|
||||
CONF_HOST: HOST,
|
||||
CONF_PORT: PORT,
|
||||
CONF_SSL: USE_SSL,
|
||||
CONF_USERNAME: USERNAME,
|
||||
CONF_PASSWORD: PASSWORD,
|
||||
CONF_MAC: MACS[0],
|
||||
},
|
||||
unique_id=SERIAL,
|
||||
)
|
||||
entry.add_to_hass(hass)
|
||||
await hass.config_entries.async_setup(entry.entry_id)
|
||||
await hass.async_block_till_done()
|
||||
|
||||
await snapshot_platform(hass, entity_registry, snapshot, entry.entry_id)
|
||||
|
||||
|
||||
@pytest.mark.parametrize(
|
||||
("fan_speed", "fan_speed_parameter"),
|
||||
[("full_speed", FanSpeed.FULL), ("cool", FanSpeed.COOL), ("quiet", FanSpeed.QUIET)],
|
||||
)
|
||||
async def test_fan_speed_select_option(
|
||||
hass: HomeAssistant,
|
||||
mock_dsm: MagicMock,
|
||||
fan_speed: str,
|
||||
fan_speed_parameter: FanSpeed,
|
||||
) -> None:
|
||||
"""Test selecting a fan speed mode option."""
|
||||
with (
|
||||
patch(
|
||||
"homeassistant.components.synology_dsm.common.SynologyDSM",
|
||||
return_value=mock_dsm,
|
||||
),
|
||||
patch("homeassistant.components.synology_dsm.PLATFORMS", [Platform.SELECT]),
|
||||
):
|
||||
entry = MockConfigEntry(
|
||||
domain=DOMAIN,
|
||||
data={
|
||||
CONF_HOST: HOST,
|
||||
CONF_PORT: PORT,
|
||||
CONF_SSL: USE_SSL,
|
||||
CONF_USERNAME: USERNAME,
|
||||
CONF_PASSWORD: PASSWORD,
|
||||
CONF_MAC: MACS[0],
|
||||
},
|
||||
unique_id=SERIAL,
|
||||
)
|
||||
entry.add_to_hass(hass)
|
||||
await hass.config_entries.async_setup(entry.entry_id)
|
||||
await hass.async_block_till_done()
|
||||
|
||||
await hass.services.async_call(
|
||||
SELECT_DOMAIN,
|
||||
SERVICE_SELECT_OPTION,
|
||||
{
|
||||
ATTR_ENTITY_ID: "select.nas_meontheinternet_com_fan_speed_mode",
|
||||
ATTR_OPTION: fan_speed,
|
||||
},
|
||||
blocking=True,
|
||||
)
|
||||
assert mock_dsm.hardware.set_fan_speed.call_args[0][0] == fan_speed_parameter
|
||||
@@ -24,6 +24,7 @@ from .common import (
|
||||
mock_dsm_external_usb_devices_usb0,
|
||||
mock_dsm_external_usb_devices_usb1,
|
||||
mock_dsm_external_usb_devices_usb2,
|
||||
mock_dsm_hardware,
|
||||
mock_dsm_information,
|
||||
mock_dsm_storage_get_disk,
|
||||
mock_dsm_storage_get_volume,
|
||||
@@ -49,6 +50,7 @@ def mock_dsm_with_usb():
|
||||
dsm.network = Mock(
|
||||
update=AsyncMock(return_value=True), macs=MACS, hostname=HOST
|
||||
)
|
||||
dsm.hardware = mock_dsm_hardware()
|
||||
dsm.information = mock_dsm_information()
|
||||
dsm.storage = Mock(
|
||||
get_disk=mock_dsm_storage_get_disk,
|
||||
@@ -83,6 +85,7 @@ def mock_dsm_without_usb():
|
||||
dsm.network = Mock(
|
||||
update=AsyncMock(return_value=True), macs=MACS, hostname=HOST
|
||||
)
|
||||
dsm.hardware = mock_dsm_hardware()
|
||||
dsm.information = mock_dsm_information()
|
||||
dsm.file = Mock(get_shared_folders=AsyncMock(return_value=None))
|
||||
dsm.logout = AsyncMock(return_value=True)
|
||||
|
||||
Reference in New Issue
Block a user