mirror of
https://github.com/home-assistant/core.git
synced 2025-04-23 16:57:53 +00:00
Update vallox_websocket_api to 5.0.2 (#110752)
Co-authored-by: Sebastian Lövdahl <slovdahl@hibox.fi>
This commit is contained in:
parent
efac3b0a60
commit
2250baab21
@ -1456,8 +1456,8 @@ build.json @home-assistant/supervisor
|
||||
/tests/components/v2c/ @dgomes
|
||||
/homeassistant/components/vacuum/ @home-assistant/core
|
||||
/tests/components/vacuum/ @home-assistant/core
|
||||
/homeassistant/components/vallox/ @andre-richter @slovdahl @viiru-
|
||||
/tests/components/vallox/ @andre-richter @slovdahl @viiru-
|
||||
/homeassistant/components/vallox/ @andre-richter @slovdahl @viiru- @yozik04
|
||||
/tests/components/vallox/ @andre-richter @slovdahl @viiru- @yozik04
|
||||
/homeassistant/components/valve/ @home-assistant/core
|
||||
/tests/components/valve/ @home-assistant/core
|
||||
/homeassistant/components/velbus/ @Cereal2nd @brefra
|
||||
|
@ -1,20 +1,11 @@
|
||||
"""Support for Vallox ventilation units."""
|
||||
from __future__ import annotations
|
||||
|
||||
from dataclasses import dataclass, field
|
||||
from datetime import date
|
||||
import ipaddress
|
||||
import logging
|
||||
from typing import Any, NamedTuple
|
||||
from uuid import UUID
|
||||
from typing import NamedTuple
|
||||
|
||||
from vallox_websocket_api import PROFILE as VALLOX_PROFILE, Vallox, ValloxApiException
|
||||
from vallox_websocket_api.vallox import (
|
||||
get_model as _api_get_model,
|
||||
get_next_filter_change_date as _api_get_next_filter_change_date,
|
||||
get_sw_version as _api_get_sw_version,
|
||||
get_uuid as _api_get_uuid,
|
||||
)
|
||||
from vallox_websocket_api import MetricData, Profile, Vallox, ValloxApiException
|
||||
import voluptuous as vol
|
||||
|
||||
from homeassistant.config_entries import ConfigEntry
|
||||
@ -22,7 +13,6 @@ from homeassistant.const import CONF_HOST, CONF_NAME, Platform
|
||||
from homeassistant.core import HomeAssistant, ServiceCall
|
||||
from homeassistant.helpers import config_validation as cv
|
||||
from homeassistant.helpers.device_registry import DeviceInfo
|
||||
from homeassistant.helpers.typing import StateType
|
||||
from homeassistant.helpers.update_coordinator import (
|
||||
CoordinatorEntity,
|
||||
DataUpdateCoordinator,
|
||||
@ -35,9 +25,6 @@ from .const import (
|
||||
DEFAULT_FAN_SPEED_HOME,
|
||||
DEFAULT_NAME,
|
||||
DOMAIN,
|
||||
METRIC_KEY_PROFILE_FAN_SPEED_AWAY,
|
||||
METRIC_KEY_PROFILE_FAN_SPEED_BOOST,
|
||||
METRIC_KEY_PROFILE_FAN_SPEED_HOME,
|
||||
STATE_SCAN_INTERVAL,
|
||||
)
|
||||
|
||||
@ -104,58 +91,7 @@ SERVICE_TO_METHOD = {
|
||||
}
|
||||
|
||||
|
||||
@dataclass
|
||||
class ValloxState:
|
||||
"""Describes the current state of the unit."""
|
||||
|
||||
metric_cache: dict[str, Any] = field(default_factory=dict)
|
||||
profile: VALLOX_PROFILE = VALLOX_PROFILE.NONE
|
||||
|
||||
def get_metric(self, metric_key: str) -> StateType:
|
||||
"""Return cached state value."""
|
||||
|
||||
if (value := self.metric_cache.get(metric_key)) is None:
|
||||
return None
|
||||
|
||||
if not isinstance(value, (str, int, float)):
|
||||
return None
|
||||
|
||||
return value
|
||||
|
||||
@property
|
||||
def model(self) -> str | None:
|
||||
"""Return the model, if any."""
|
||||
model = _api_get_model(self.metric_cache)
|
||||
|
||||
if model == "Unknown":
|
||||
return None
|
||||
|
||||
return model
|
||||
|
||||
@property
|
||||
def sw_version(self) -> str:
|
||||
"""Return the SW version."""
|
||||
return _api_get_sw_version(self.metric_cache)
|
||||
|
||||
@property
|
||||
def uuid(self) -> UUID | None:
|
||||
"""Return cached UUID value."""
|
||||
uuid = _api_get_uuid(self.metric_cache)
|
||||
if not isinstance(uuid, UUID):
|
||||
raise TypeError
|
||||
return uuid
|
||||
|
||||
def get_next_filter_change_date(self) -> date | None:
|
||||
"""Return the next filter change date."""
|
||||
next_filter_change_date = _api_get_next_filter_change_date(self.metric_cache)
|
||||
|
||||
if not isinstance(next_filter_change_date, date):
|
||||
return None
|
||||
|
||||
return next_filter_change_date
|
||||
|
||||
|
||||
class ValloxDataUpdateCoordinator(DataUpdateCoordinator[ValloxState]): # pylint: disable=hass-enforce-coordinator-module
|
||||
class ValloxDataUpdateCoordinator(DataUpdateCoordinator[MetricData]): # pylint: disable=hass-enforce-coordinator-module
|
||||
"""The DataUpdateCoordinator for Vallox."""
|
||||
|
||||
|
||||
@ -166,19 +102,15 @@ async def async_setup_entry(hass: HomeAssistant, entry: ConfigEntry) -> bool:
|
||||
|
||||
client = Vallox(host)
|
||||
|
||||
async def async_update_data() -> ValloxState:
|
||||
async def async_update_data() -> MetricData:
|
||||
"""Fetch state update."""
|
||||
_LOGGER.debug("Updating Vallox state cache")
|
||||
|
||||
try:
|
||||
metric_cache = await client.fetch_metrics()
|
||||
profile = await client.get_profile()
|
||||
|
||||
return await client.fetch_metric_data()
|
||||
except ValloxApiException as err:
|
||||
raise UpdateFailed("Error during state cache update") from err
|
||||
|
||||
return ValloxState(metric_cache, profile)
|
||||
|
||||
coordinator = ValloxDataUpdateCoordinator(
|
||||
hass,
|
||||
_LOGGER,
|
||||
@ -227,7 +159,7 @@ class ValloxServiceHandler:
|
||||
"""Services implementation."""
|
||||
|
||||
def __init__(
|
||||
self, client: Vallox, coordinator: DataUpdateCoordinator[ValloxState]
|
||||
self, client: Vallox, coordinator: DataUpdateCoordinator[MetricData]
|
||||
) -> None:
|
||||
"""Initialize the proxy."""
|
||||
self._client = client
|
||||
@ -240,9 +172,7 @@ class ValloxServiceHandler:
|
||||
_LOGGER.debug("Setting Home fan speed to: %d%%", fan_speed)
|
||||
|
||||
try:
|
||||
await self._client.set_values(
|
||||
{METRIC_KEY_PROFILE_FAN_SPEED_HOME: fan_speed}
|
||||
)
|
||||
await self._client.set_fan_speed(Profile.HOME, fan_speed)
|
||||
return True
|
||||
|
||||
except ValloxApiException as err:
|
||||
@ -256,9 +186,7 @@ class ValloxServiceHandler:
|
||||
_LOGGER.debug("Setting Away fan speed to: %d%%", fan_speed)
|
||||
|
||||
try:
|
||||
await self._client.set_values(
|
||||
{METRIC_KEY_PROFILE_FAN_SPEED_AWAY: fan_speed}
|
||||
)
|
||||
await self._client.set_fan_speed(Profile.AWAY, fan_speed)
|
||||
return True
|
||||
|
||||
except ValloxApiException as err:
|
||||
@ -272,9 +200,7 @@ class ValloxServiceHandler:
|
||||
_LOGGER.debug("Setting Boost fan speed to: %d%%", fan_speed)
|
||||
|
||||
try:
|
||||
await self._client.set_values(
|
||||
{METRIC_KEY_PROFILE_FAN_SPEED_BOOST: fan_speed}
|
||||
)
|
||||
await self._client.set_fan_speed(Profile.BOOST, fan_speed)
|
||||
return True
|
||||
|
||||
except ValloxApiException as err:
|
||||
|
@ -38,7 +38,7 @@ class ValloxBinarySensorEntity(ValloxEntity, BinarySensorEntity):
|
||||
@property
|
||||
def is_on(self) -> bool | None:
|
||||
"""Return true if the binary sensor is on."""
|
||||
return self.coordinator.data.get_metric(self.entity_description.metric_key) == 1
|
||||
return self.coordinator.data.get(self.entity_description.metric_key) == 1
|
||||
|
||||
|
||||
@dataclass(frozen=True)
|
||||
|
@ -32,7 +32,7 @@ async def validate_host(hass: HomeAssistant, host: str) -> None:
|
||||
raise InvalidHost(f"Invalid IP address: {host}")
|
||||
|
||||
client = Vallox(host)
|
||||
await client.get_info()
|
||||
await client.fetch_metric_data()
|
||||
|
||||
|
||||
class ConfigFlow(config_entries.ConfigFlow, domain=DOMAIN):
|
||||
|
@ -2,7 +2,7 @@
|
||||
|
||||
from datetime import timedelta
|
||||
|
||||
from vallox_websocket_api import PROFILE as VALLOX_PROFILE
|
||||
from vallox_websocket_api import Profile as VALLOX_PROFILE
|
||||
|
||||
DOMAIN = "vallox"
|
||||
DEFAULT_NAME = "Vallox"
|
||||
@ -30,8 +30,11 @@ VALLOX_PROFILE_TO_PRESET_MODE_SETTABLE = {
|
||||
}
|
||||
|
||||
VALLOX_PROFILE_TO_PRESET_MODE_REPORTABLE = {
|
||||
VALLOX_PROFILE.HOME: "Home",
|
||||
VALLOX_PROFILE.AWAY: "Away",
|
||||
VALLOX_PROFILE.BOOST: "Boost",
|
||||
VALLOX_PROFILE.FIREPLACE: "Fireplace",
|
||||
VALLOX_PROFILE.EXTRA: "Extra",
|
||||
**VALLOX_PROFILE_TO_PRESET_MODE_SETTABLE,
|
||||
}
|
||||
|
||||
PRESET_MODE_TO_VALLOX_PROFILE_SETTABLE = {
|
||||
|
@ -4,12 +4,7 @@ from __future__ import annotations
|
||||
from collections.abc import Mapping
|
||||
from typing import Any, NamedTuple
|
||||
|
||||
from vallox_websocket_api import (
|
||||
PROFILE_TO_SET_FAN_SPEED_METRIC_MAP,
|
||||
Vallox,
|
||||
ValloxApiException,
|
||||
ValloxInvalidInputException,
|
||||
)
|
||||
from vallox_websocket_api import Vallox, ValloxApiException, ValloxInvalidInputException
|
||||
|
||||
from homeassistant.components.fan import FanEntity, FanEntityFeature
|
||||
from homeassistant.config_entries import ConfigEntry
|
||||
@ -99,7 +94,7 @@ class ValloxFanEntity(ValloxEntity, FanEntity):
|
||||
@property
|
||||
def is_on(self) -> bool:
|
||||
"""Return if device is on."""
|
||||
return self.coordinator.data.get_metric(METRIC_KEY_MODE) == MODE_ON
|
||||
return self.coordinator.data.get(METRIC_KEY_MODE) == MODE_ON
|
||||
|
||||
@property
|
||||
def preset_mode(self) -> str | None:
|
||||
@ -112,19 +107,18 @@ class ValloxFanEntity(ValloxEntity, FanEntity):
|
||||
"""Return the current speed as a percentage."""
|
||||
|
||||
vallox_profile = self.coordinator.data.profile
|
||||
metric_key = PROFILE_TO_SET_FAN_SPEED_METRIC_MAP.get(vallox_profile)
|
||||
if not metric_key:
|
||||
try:
|
||||
return _convert_to_int(self.coordinator.data.get_fan_speed(vallox_profile))
|
||||
except ValloxInvalidInputException:
|
||||
return None
|
||||
|
||||
return _convert_to_int(self.coordinator.data.get_metric(metric_key))
|
||||
|
||||
@property
|
||||
def extra_state_attributes(self) -> Mapping[str, int | None]:
|
||||
"""Return device specific state attributes."""
|
||||
data = self.coordinator.data
|
||||
|
||||
return {
|
||||
attr.description: _convert_to_int(data.get_metric(attr.metric_key))
|
||||
attr.description: _convert_to_int(data.get(attr.metric_key))
|
||||
for attr in EXTRA_STATE_ATTRIBUTES
|
||||
}
|
||||
|
||||
@ -153,7 +147,9 @@ class ValloxFanEntity(ValloxEntity, FanEntity):
|
||||
update_needed |= await self._async_set_preset_mode_internal(preset_mode)
|
||||
|
||||
if percentage is not None:
|
||||
update_needed |= await self._async_set_percentage_internal(percentage)
|
||||
update_needed |= await self._async_set_percentage_internal(
|
||||
percentage, preset_mode
|
||||
)
|
||||
|
||||
if update_needed:
|
||||
# This state change affects other entities like sensors. Force an immediate update that
|
||||
@ -202,19 +198,24 @@ class ValloxFanEntity(ValloxEntity, FanEntity):
|
||||
try:
|
||||
profile = PRESET_MODE_TO_VALLOX_PROFILE_SETTABLE[preset_mode]
|
||||
await self._client.set_profile(profile)
|
||||
self.coordinator.data.profile = profile
|
||||
|
||||
except ValloxApiException as err:
|
||||
raise HomeAssistantError(f"Failed to set profile: {preset_mode}") from err
|
||||
|
||||
return True
|
||||
|
||||
async def _async_set_percentage_internal(self, percentage: int) -> bool:
|
||||
async def _async_set_percentage_internal(
|
||||
self, percentage: int, preset_mode: str | None = None
|
||||
) -> bool:
|
||||
"""Set fan speed percentage for current profile.
|
||||
|
||||
Returns true if speed has been changed, false otherwise.
|
||||
"""
|
||||
vallox_profile = self.coordinator.data.profile
|
||||
vallox_profile = (
|
||||
PRESET_MODE_TO_VALLOX_PROFILE_SETTABLE[preset_mode]
|
||||
if preset_mode is not None
|
||||
else self.coordinator.data.profile
|
||||
)
|
||||
|
||||
try:
|
||||
await self._client.set_fan_speed(vallox_profile, percentage)
|
||||
|
@ -1,10 +1,10 @@
|
||||
{
|
||||
"domain": "vallox",
|
||||
"name": "Vallox",
|
||||
"codeowners": ["@andre-richter", "@slovdahl", "@viiru-"],
|
||||
"codeowners": ["@andre-richter", "@slovdahl", "@viiru-", "@yozik04"],
|
||||
"config_flow": true,
|
||||
"documentation": "https://www.home-assistant.io/integrations/vallox",
|
||||
"iot_class": "local_polling",
|
||||
"loggers": ["vallox_websocket_api"],
|
||||
"requirements": ["vallox-websocket-api==4.0.3"]
|
||||
"requirements": ["vallox-websocket-api==5.0.2"]
|
||||
}
|
||||
|
@ -44,9 +44,7 @@ class ValloxNumberEntity(ValloxEntity, NumberEntity):
|
||||
def native_value(self) -> float | None:
|
||||
"""Return the value reported by the sensor."""
|
||||
if (
|
||||
value := self.coordinator.data.get_metric(
|
||||
self.entity_description.metric_key
|
||||
)
|
||||
value := self.coordinator.data.get(self.entity_description.metric_key)
|
||||
) is None:
|
||||
return None
|
||||
|
||||
|
@ -58,7 +58,7 @@ class ValloxSensorEntity(ValloxEntity, SensorEntity):
|
||||
if (metric_key := self.entity_description.metric_key) is None:
|
||||
return None
|
||||
|
||||
value = self.coordinator.data.get_metric(metric_key)
|
||||
value = self.coordinator.data.get(metric_key)
|
||||
|
||||
if self.entity_description.round_ndigits is not None and isinstance(
|
||||
value, float
|
||||
@ -90,7 +90,7 @@ class ValloxFanSpeedSensor(ValloxSensorEntity):
|
||||
@property
|
||||
def native_value(self) -> StateType | datetime:
|
||||
"""Return the value reported by the sensor."""
|
||||
fan_is_on = self.coordinator.data.get_metric(METRIC_KEY_MODE) == MODE_ON
|
||||
fan_is_on = self.coordinator.data.get(METRIC_KEY_MODE) == MODE_ON
|
||||
return super().native_value if fan_is_on else 0
|
||||
|
||||
|
||||
@ -100,7 +100,7 @@ class ValloxFilterRemainingSensor(ValloxSensorEntity):
|
||||
@property
|
||||
def native_value(self) -> StateType | datetime:
|
||||
"""Return the value reported by the sensor."""
|
||||
next_filter_change_date = self.coordinator.data.get_next_filter_change_date()
|
||||
next_filter_change_date = self.coordinator.data.next_filter_change_date
|
||||
|
||||
if next_filter_change_date is None:
|
||||
return None
|
||||
|
@ -41,9 +41,7 @@ class ValloxSwitchEntity(ValloxEntity, SwitchEntity):
|
||||
def is_on(self) -> bool | None:
|
||||
"""Return true if the switch is on."""
|
||||
if (
|
||||
value := self.coordinator.data.get_metric(
|
||||
self.entity_description.metric_key
|
||||
)
|
||||
value := self.coordinator.data.get(self.entity_description.metric_key)
|
||||
) is None:
|
||||
return None
|
||||
return value == 1
|
||||
@ -93,12 +91,12 @@ async def async_setup_entry(
|
||||
"""Set up the switches."""
|
||||
|
||||
data = hass.data[DOMAIN][entry.entry_id]
|
||||
client = data["client"]
|
||||
client.set_settable_address("A_CYC_BYPASS_LOCKED", int)
|
||||
|
||||
async_add_entities(
|
||||
[
|
||||
ValloxSwitchEntity(data["name"], data["coordinator"], description, client)
|
||||
ValloxSwitchEntity(
|
||||
data["name"], data["coordinator"], description, data["client"]
|
||||
)
|
||||
for description in SWITCH_ENTITIES
|
||||
]
|
||||
)
|
||||
|
@ -2786,7 +2786,7 @@ uvcclient==0.11.0
|
||||
vacuum-map-parser-roborock==0.1.1
|
||||
|
||||
# homeassistant.components.vallox
|
||||
vallox-websocket-api==4.0.3
|
||||
vallox-websocket-api==5.0.2
|
||||
|
||||
# homeassistant.components.rdw
|
||||
vehicle==2.2.1
|
||||
|
@ -2130,7 +2130,7 @@ uvcclient==0.11.0
|
||||
vacuum-map-parser-roborock==0.1.1
|
||||
|
||||
# homeassistant.components.vallox
|
||||
vallox-websocket-api==4.0.3
|
||||
vallox-websocket-api==5.0.2
|
||||
|
||||
# homeassistant.components.rdw
|
||||
vehicle==2.2.1
|
||||
|
@ -1,13 +1,9 @@
|
||||
"""Common utilities for Vallox tests."""
|
||||
|
||||
import random
|
||||
import string
|
||||
from typing import Any
|
||||
from unittest.mock import patch
|
||||
from uuid import UUID
|
||||
from unittest.mock import AsyncMock, patch
|
||||
|
||||
import pytest
|
||||
from vallox_websocket_api.vallox import PROFILE
|
||||
from vallox_websocket_api import MetricData
|
||||
|
||||
from homeassistant.components.vallox.const import DOMAIN
|
||||
from homeassistant.const import CONF_HOST, CONF_NAME
|
||||
@ -31,83 +27,80 @@ def mock_entry(hass: HomeAssistant) -> MockConfigEntry:
|
||||
return vallox_mock_entry
|
||||
|
||||
|
||||
def patch_metrics(metrics: dict[str, Any]):
|
||||
@pytest.fixture
|
||||
def default_metrics():
|
||||
"""Return default Vallox metrics."""
|
||||
return {
|
||||
"A_CYC_MACHINE_MODEL": 3,
|
||||
"A_CYC_APPL_SW_VERSION_1": 2,
|
||||
"A_CYC_APPL_SW_VERSION_2": 0,
|
||||
"A_CYC_APPL_SW_VERSION_3": 16,
|
||||
"A_CYC_UUID0": 5,
|
||||
"A_CYC_UUID1": 6,
|
||||
"A_CYC_UUID2": 7,
|
||||
"A_CYC_UUID3": 8,
|
||||
"A_CYC_UUID4": 9,
|
||||
"A_CYC_UUID5": 10,
|
||||
"A_CYC_UUID6": 11,
|
||||
"A_CYC_UUID7": 12,
|
||||
"A_CYC_BOOST_TIMER": 30,
|
||||
"A_CYC_FIREPLACE_TIMER": 30,
|
||||
"A_CYC_EXTRA_TIMER": 30,
|
||||
"A_CYC_MODE": 0,
|
||||
"A_CYC_STATE": 0,
|
||||
"A_CYC_FILTER_CHANGED_YEAR": 24,
|
||||
"A_CYC_FILTER_CHANGED_MONTH": 2,
|
||||
"A_CYC_FILTER_CHANGED_DAY": 16,
|
||||
"A_CYC_FILTER_CHANGE_INTERVAL": 120,
|
||||
"A_CYC_TOTAL_FAULT_COUNT": 0,
|
||||
"A_CYC_FAULT_CODE": 0,
|
||||
"A_CYC_FAULT_ACTIVITY": 0,
|
||||
"A_CYC_FAULT_FIRST_DATE": 0,
|
||||
"A_CYC_FAULT_LAST_DATE": 0,
|
||||
"A_CYC_FAULT_SEVERITY": 0,
|
||||
"A_CYC_FAULT_COUNT": 0,
|
||||
"A_CYC_HOME_SPEED_SETTING": 30,
|
||||
"A_CYC_AWAY_SPEED_SETTING": 10,
|
||||
"A_CYC_BOOST_SPEED_SETTING": 80,
|
||||
}
|
||||
|
||||
|
||||
@pytest.fixture(autouse=True)
|
||||
def fetch_metric_data_mock(default_metrics):
|
||||
"""Stub the Vallox fetch_metric_data method."""
|
||||
with patch(
|
||||
"homeassistant.components.vallox.Vallox.fetch_metric_data",
|
||||
new_callable=AsyncMock,
|
||||
) as mock:
|
||||
mock.return_value = MetricData(default_metrics)
|
||||
yield mock
|
||||
|
||||
|
||||
@pytest.fixture
|
||||
def setup_fetch_metric_data_mock(fetch_metric_data_mock, default_metrics):
|
||||
"""Patch the Vallox metrics response."""
|
||||
return patch(
|
||||
"homeassistant.components.vallox.Vallox.fetch_metrics",
|
||||
return_value=metrics,
|
||||
)
|
||||
|
||||
def _setup(metrics=None, metric_data_class=MetricData):
|
||||
metrics = metrics or {}
|
||||
fetch_metric_data_mock.return_value = metric_data_class(
|
||||
{**default_metrics, **metrics}
|
||||
)
|
||||
|
||||
return fetch_metric_data_mock
|
||||
|
||||
return _setup
|
||||
|
||||
|
||||
def patch_profile(profile: PROFILE):
|
||||
"""Patch the Vallox metrics response."""
|
||||
return patch(
|
||||
"homeassistant.components.vallox.Vallox.get_profile",
|
||||
return_value=profile,
|
||||
)
|
||||
|
||||
|
||||
def patch_profile_set():
|
||||
def patch_set_profile():
|
||||
"""Patch the Vallox metrics set values."""
|
||||
return patch("homeassistant.components.vallox.Vallox.set_profile")
|
||||
|
||||
|
||||
def patch_metrics_set():
|
||||
def patch_set_fan_speed():
|
||||
"""Patch the Vallox metrics set values."""
|
||||
return patch("homeassistant.components.vallox.Vallox.set_fan_speed")
|
||||
|
||||
|
||||
def patch_set_values():
|
||||
"""Patch the Vallox metrics set values."""
|
||||
return patch("homeassistant.components.vallox.Vallox.set_values")
|
||||
|
||||
|
||||
@pytest.fixture(autouse=True)
|
||||
def patch_empty_metrics():
|
||||
"""Patch the Vallox profile response."""
|
||||
with patch(
|
||||
"homeassistant.components.vallox.Vallox.fetch_metrics",
|
||||
return_value={},
|
||||
):
|
||||
yield
|
||||
|
||||
|
||||
@pytest.fixture(autouse=True)
|
||||
def patch_default_profile():
|
||||
"""Patch the Vallox profile response."""
|
||||
with patch(
|
||||
"homeassistant.components.vallox.Vallox.get_profile",
|
||||
return_value=PROFILE.HOME,
|
||||
):
|
||||
yield
|
||||
|
||||
|
||||
@pytest.fixture(autouse=True)
|
||||
def patch_model():
|
||||
"""Patch the Vallox model response."""
|
||||
with patch(
|
||||
"homeassistant.components.vallox._api_get_model",
|
||||
return_value="Vallox Testmodel",
|
||||
):
|
||||
yield
|
||||
|
||||
|
||||
@pytest.fixture(autouse=True)
|
||||
def patch_sw_version():
|
||||
"""Patch the Vallox SW version response."""
|
||||
with patch(
|
||||
"homeassistant.components.vallox._api_get_sw_version",
|
||||
return_value="0.1.2",
|
||||
):
|
||||
yield
|
||||
|
||||
|
||||
@pytest.fixture(autouse=True)
|
||||
def patch_uuid():
|
||||
"""Patch the Vallox UUID response."""
|
||||
with patch(
|
||||
"homeassistant.components.vallox._api_get_uuid",
|
||||
return_value=_random_uuid(),
|
||||
):
|
||||
yield
|
||||
|
||||
|
||||
def _random_uuid():
|
||||
"""Generate a random UUID."""
|
||||
uuid = "".join(random.choices(string.hexdigits, k=32))
|
||||
return UUID(uuid)
|
||||
|
@ -5,8 +5,6 @@ import pytest
|
||||
|
||||
from homeassistant.core import HomeAssistant
|
||||
|
||||
from .conftest import patch_metrics
|
||||
|
||||
from tests.common import MockConfigEntry
|
||||
|
||||
|
||||
@ -21,14 +19,19 @@ async def test_binary_sensor_entitity(
|
||||
metrics: dict[str, Any],
|
||||
expected_state: str,
|
||||
mock_entry: MockConfigEntry,
|
||||
setup_fetch_metric_data_mock,
|
||||
hass: HomeAssistant,
|
||||
):
|
||||
) -> None:
|
||||
"""Test binary sensor with metrics."""
|
||||
|
||||
# Arrange
|
||||
fetch_metric_data_mock = setup_fetch_metric_data_mock(metrics)
|
||||
|
||||
# Act
|
||||
with patch_metrics(metrics=metrics):
|
||||
await hass.config_entries.async_setup(mock_entry.entry_id)
|
||||
await hass.async_block_till_done()
|
||||
await hass.config_entries.async_setup(mock_entry.entry_id)
|
||||
await hass.async_block_till_done()
|
||||
|
||||
# Assert
|
||||
fetch_metric_data_mock.assert_called_once()
|
||||
sensor = hass.states.get("binary_sensor.vallox_post_heater")
|
||||
assert sensor.state == expected_state
|
||||
|
@ -33,7 +33,7 @@ async def test_form_create_entry(hass: HomeAssistant) -> None:
|
||||
assert init["errors"] is None
|
||||
|
||||
with patch(
|
||||
"homeassistant.components.vallox.config_flow.Vallox.get_info",
|
||||
"homeassistant.components.vallox.config_flow.Vallox.fetch_metric_data",
|
||||
return_value=None,
|
||||
), patch(
|
||||
"homeassistant.components.vallox.async_setup_entry",
|
||||
@ -74,7 +74,7 @@ async def test_form_vallox_api_exception_cannot_connect(hass: HomeAssistant) ->
|
||||
)
|
||||
|
||||
with patch(
|
||||
"homeassistant.components.vallox.config_flow.Vallox.get_info",
|
||||
"homeassistant.components.vallox.config_flow.Vallox.fetch_metric_data",
|
||||
side_effect=ValloxApiException,
|
||||
):
|
||||
result = await hass.config_entries.flow.async_configure(
|
||||
@ -94,7 +94,7 @@ async def test_form_os_error_cannot_connect(hass: HomeAssistant) -> None:
|
||||
)
|
||||
|
||||
with patch(
|
||||
"homeassistant.components.vallox.config_flow.Vallox.get_info",
|
||||
"homeassistant.components.vallox.config_flow.Vallox.fetch_metric_data",
|
||||
side_effect=ValloxWebsocketException,
|
||||
):
|
||||
result = await hass.config_entries.flow.async_configure(
|
||||
@ -114,7 +114,7 @@ async def test_form_unknown_exception(hass: HomeAssistant) -> None:
|
||||
)
|
||||
|
||||
with patch(
|
||||
"homeassistant.components.vallox.config_flow.Vallox.get_info",
|
||||
"homeassistant.components.vallox.config_flow.Vallox.fetch_metric_data",
|
||||
side_effect=Exception,
|
||||
):
|
||||
result = await hass.config_entries.flow.async_configure(
|
||||
|
@ -2,7 +2,7 @@
|
||||
from unittest.mock import call
|
||||
|
||||
import pytest
|
||||
from vallox_websocket_api import PROFILE, ValloxApiException
|
||||
from vallox_websocket_api import MetricData, MetricValue, Profile, ValloxApiException
|
||||
|
||||
from homeassistant.components.fan import (
|
||||
ATTR_PERCENTAGE,
|
||||
@ -16,7 +16,7 @@ from homeassistant.const import ATTR_ENTITY_ID, SERVICE_TURN_OFF, SERVICE_TURN_O
|
||||
from homeassistant.core import HomeAssistant
|
||||
from homeassistant.exceptions import HomeAssistantError
|
||||
|
||||
from .conftest import patch_metrics, patch_metrics_set, patch_profile, patch_profile_set
|
||||
from .conftest import patch_set_fan_speed, patch_set_profile, patch_set_values
|
||||
|
||||
from tests.common import MockConfigEntry
|
||||
|
||||
@ -26,45 +26,57 @@ from tests.common import MockConfigEntry
|
||||
[({"A_CYC_MODE": 0}, "on"), ({"A_CYC_MODE": 5}, "off")],
|
||||
)
|
||||
async def test_fan_state(
|
||||
metrics: dict[str, int],
|
||||
metrics: dict[str, MetricValue],
|
||||
expected_state: str,
|
||||
mock_entry: MockConfigEntry,
|
||||
setup_fetch_metric_data_mock,
|
||||
hass: HomeAssistant,
|
||||
) -> None:
|
||||
"""Test fan on/off state."""
|
||||
|
||||
# Arrange
|
||||
fetch_metric_data_mock = setup_fetch_metric_data_mock(metrics=metrics)
|
||||
|
||||
# Act
|
||||
with patch_metrics(metrics=metrics):
|
||||
await hass.config_entries.async_setup(mock_entry.entry_id)
|
||||
await hass.async_block_till_done()
|
||||
await hass.config_entries.async_setup(mock_entry.entry_id)
|
||||
await hass.async_block_till_done()
|
||||
|
||||
# Assert
|
||||
fetch_metric_data_mock.assert_called_once()
|
||||
sensor = hass.states.get("fan.vallox")
|
||||
assert sensor
|
||||
assert sensor.state == expected_state
|
||||
|
||||
|
||||
@pytest.mark.parametrize(
|
||||
("profile", "expected_preset"),
|
||||
("vallox_profile", "expected_preset"),
|
||||
[
|
||||
(PROFILE.HOME, "Home"),
|
||||
(PROFILE.AWAY, "Away"),
|
||||
(PROFILE.BOOST, "Boost"),
|
||||
(PROFILE.FIREPLACE, "Fireplace"),
|
||||
(Profile.HOME, "Home"),
|
||||
(Profile.AWAY, "Away"),
|
||||
(Profile.BOOST, "Boost"),
|
||||
(Profile.FIREPLACE, "Fireplace"),
|
||||
],
|
||||
)
|
||||
async def test_fan_profile(
|
||||
profile: PROFILE,
|
||||
vallox_profile: Profile,
|
||||
expected_preset: str,
|
||||
mock_entry: MockConfigEntry,
|
||||
setup_fetch_metric_data_mock,
|
||||
hass: HomeAssistant,
|
||||
) -> None:
|
||||
"""Test fan profile."""
|
||||
|
||||
# Arrange
|
||||
class MockMetricData(MetricData):
|
||||
@property
|
||||
def profile(self):
|
||||
return vallox_profile
|
||||
|
||||
setup_fetch_metric_data_mock(metric_data_class=MockMetricData)
|
||||
|
||||
# Act
|
||||
with patch_profile(profile):
|
||||
await hass.config_entries.async_setup(mock_entry.entry_id)
|
||||
await hass.async_block_till_done()
|
||||
await hass.config_entries.async_setup(mock_entry.entry_id)
|
||||
await hass.async_block_till_done()
|
||||
|
||||
# Assert
|
||||
sensor = hass.states.get("fan.vallox")
|
||||
@ -81,13 +93,16 @@ async def test_fan_profile(
|
||||
)
|
||||
async def test_turn_on_off(
|
||||
service: str,
|
||||
initial_metrics: dict[str, int],
|
||||
expected_called_with: dict[str, int],
|
||||
initial_metrics: dict[str, MetricValue],
|
||||
expected_called_with: dict[str, MetricValue],
|
||||
mock_entry: MockConfigEntry,
|
||||
setup_fetch_metric_data_mock,
|
||||
hass: HomeAssistant,
|
||||
) -> None:
|
||||
"""Test turn on/off."""
|
||||
with patch_metrics(metrics=initial_metrics), patch_metrics_set() as metrics_set:
|
||||
setup_fetch_metric_data_mock(metrics=initial_metrics)
|
||||
|
||||
with patch_set_values() as set_values:
|
||||
await hass.config_entries.async_setup(mock_entry.entry_id)
|
||||
await hass.async_block_till_done()
|
||||
await hass.services.async_call(
|
||||
@ -96,7 +111,7 @@ async def test_turn_on_off(
|
||||
service_data={ATTR_ENTITY_ID: "fan.vallox"},
|
||||
blocking=True,
|
||||
)
|
||||
metrics_set.assert_called_once_with(expected_called_with)
|
||||
set_values.assert_called_once_with(expected_called_with)
|
||||
|
||||
|
||||
@pytest.mark.parametrize(
|
||||
@ -118,15 +133,17 @@ async def test_turn_on_off(
|
||||
],
|
||||
)
|
||||
async def test_turn_on_with_parameters(
|
||||
initial_metrics: dict[str, int],
|
||||
initial_metrics: dict[str, MetricValue],
|
||||
expected_call_args_list: list[tuple],
|
||||
mock_entry: MockConfigEntry,
|
||||
hass: HomeAssistant,
|
||||
setup_fetch_metric_data_mock,
|
||||
) -> None:
|
||||
"""Test turn on/off."""
|
||||
with patch_metrics(
|
||||
metrics=initial_metrics
|
||||
), patch_metrics_set() as metrics_set, patch_profile_set() as profile_set:
|
||||
|
||||
setup_fetch_metric_data_mock(metrics=initial_metrics)
|
||||
|
||||
with patch_set_values() as set_values, patch_set_profile() as set_profile:
|
||||
await hass.config_entries.async_setup(mock_entry.entry_id)
|
||||
await hass.async_block_till_done()
|
||||
await hass.services.async_call(
|
||||
@ -139,29 +156,38 @@ async def test_turn_on_with_parameters(
|
||||
},
|
||||
blocking=True,
|
||||
)
|
||||
assert metrics_set.call_args_list == expected_call_args_list
|
||||
profile_set.assert_called_once_with(PROFILE.AWAY)
|
||||
set_profile.assert_called_once_with(Profile.AWAY)
|
||||
assert set_values.call_args_list == expected_call_args_list
|
||||
|
||||
|
||||
@pytest.mark.parametrize(
|
||||
("preset", "initial_profile", "expected_call_args_list"),
|
||||
[
|
||||
("Home", PROFILE.AWAY, [call(PROFILE.HOME)]),
|
||||
("Away", PROFILE.HOME, [call(PROFILE.AWAY)]),
|
||||
("Boost", PROFILE.HOME, [call(PROFILE.BOOST)]),
|
||||
("Fireplace", PROFILE.HOME, [call(PROFILE.FIREPLACE)]),
|
||||
("Home", PROFILE.HOME, []),
|
||||
("Home", Profile.AWAY, [call(Profile.HOME)]),
|
||||
("Away", Profile.HOME, [call(Profile.AWAY)]),
|
||||
("Boost", Profile.HOME, [call(Profile.BOOST)]),
|
||||
("Fireplace", Profile.HOME, [call(Profile.FIREPLACE)]),
|
||||
("Home", Profile.HOME, []), # No change
|
||||
],
|
||||
)
|
||||
async def test_set_preset_mode(
|
||||
preset: str,
|
||||
initial_profile: PROFILE,
|
||||
initial_profile: Profile,
|
||||
expected_call_args_list: list[tuple],
|
||||
mock_entry: MockConfigEntry,
|
||||
hass: HomeAssistant,
|
||||
setup_fetch_metric_data_mock,
|
||||
) -> None:
|
||||
"""Test set preset mode."""
|
||||
with patch_profile(initial_profile), patch_profile_set() as profile_set:
|
||||
|
||||
class MockMetricData(MetricData):
|
||||
@property
|
||||
def profile(self):
|
||||
return initial_profile
|
||||
|
||||
setup_fetch_metric_data_mock(metric_data_class=MockMetricData)
|
||||
|
||||
with patch_set_profile() as set_profile:
|
||||
await hass.config_entries.async_setup(mock_entry.entry_id)
|
||||
await hass.async_block_till_done()
|
||||
await hass.services.async_call(
|
||||
@ -170,7 +196,7 @@ async def test_set_preset_mode(
|
||||
service_data={ATTR_ENTITY_ID: "fan.vallox", ATTR_PRESET_MODE: preset},
|
||||
blocking=True,
|
||||
)
|
||||
assert profile_set.call_args_list == expected_call_args_list
|
||||
assert set_profile.call_args_list == expected_call_args_list
|
||||
|
||||
|
||||
async def test_set_invalid_preset_mode(
|
||||
@ -198,8 +224,8 @@ async def test_set_preset_mode_exception(
|
||||
hass: HomeAssistant,
|
||||
) -> None:
|
||||
"""Test set preset mode."""
|
||||
with patch_profile_set() as profile_set:
|
||||
profile_set.side_effect = ValloxApiException("Fake exception")
|
||||
with patch_set_profile() as set_profile:
|
||||
set_profile.side_effect = ValloxApiException("Fake exception")
|
||||
await hass.config_entries.async_setup(mock_entry.entry_id)
|
||||
await hass.async_block_till_done()
|
||||
with pytest.raises(HomeAssistantError):
|
||||
@ -212,25 +238,40 @@ async def test_set_preset_mode_exception(
|
||||
|
||||
|
||||
@pytest.mark.parametrize(
|
||||
("profile", "percentage", "expected_call_args_list"),
|
||||
(
|
||||
"initial_profile",
|
||||
"percentage",
|
||||
"expected_set_fan_speed_call",
|
||||
"expected_set_values_call",
|
||||
),
|
||||
[
|
||||
(PROFILE.HOME, 40, [call({"A_CYC_HOME_SPEED_SETTING": 40})]),
|
||||
(PROFILE.AWAY, 30, [call({"A_CYC_AWAY_SPEED_SETTING": 30})]),
|
||||
(PROFILE.BOOST, 60, [call({"A_CYC_BOOST_SPEED_SETTING": 60})]),
|
||||
(PROFILE.HOME, 0, [call({"A_CYC_MODE": 5})]),
|
||||
(Profile.HOME, 40, [call(Profile.HOME, 40)], []),
|
||||
(Profile.AWAY, 30, [call(Profile.AWAY, 30)], []),
|
||||
(Profile.BOOST, 60, [call(Profile.BOOST, 60)], []),
|
||||
(Profile.HOME, 0, [], [call({"A_CYC_MODE": 5})]), # Turn off
|
||||
],
|
||||
)
|
||||
async def test_set_fan_speed(
|
||||
profile: PROFILE,
|
||||
initial_profile: Profile,
|
||||
percentage: int,
|
||||
expected_call_args_list: list[tuple],
|
||||
expected_set_fan_speed_call: list[tuple],
|
||||
expected_set_values_call: list[tuple],
|
||||
mock_entry: MockConfigEntry,
|
||||
hass: HomeAssistant,
|
||||
setup_fetch_metric_data_mock,
|
||||
) -> None:
|
||||
"""Test set fan speed percentage."""
|
||||
with patch_profile(profile), patch_metrics_set() as metrics_set, patch_metrics(
|
||||
{"A_CYC_MODE": 0}
|
||||
):
|
||||
|
||||
class MockMetricData(MetricData):
|
||||
@property
|
||||
def profile(self):
|
||||
return initial_profile
|
||||
|
||||
setup_fetch_metric_data_mock(
|
||||
metrics={"A_CYC_MODE": 0}, metric_data_class=MockMetricData
|
||||
)
|
||||
|
||||
with patch_set_fan_speed() as set_fan_speed, patch_set_values() as set_values:
|
||||
await hass.config_entries.async_setup(mock_entry.entry_id)
|
||||
await hass.async_block_till_done()
|
||||
await hass.services.async_call(
|
||||
@ -239,18 +280,20 @@ async def test_set_fan_speed(
|
||||
service_data={ATTR_ENTITY_ID: "fan.vallox", ATTR_PERCENTAGE: percentage},
|
||||
blocking=True,
|
||||
)
|
||||
assert metrics_set.call_args_list == expected_call_args_list
|
||||
assert set_fan_speed.call_args_list == expected_set_fan_speed_call
|
||||
assert set_values.call_args_list == expected_set_values_call
|
||||
|
||||
|
||||
async def test_set_fan_speed_exception(
|
||||
mock_entry: MockConfigEntry,
|
||||
hass: HomeAssistant,
|
||||
mock_entry: MockConfigEntry, hass: HomeAssistant, setup_fetch_metric_data_mock
|
||||
) -> None:
|
||||
"""Test set fan speed percentage."""
|
||||
with patch_metrics_set() as metrics_set, patch_metrics(
|
||||
{"A_CYC_MODE": 0, "A_CYC_HOME_SPEED_SETTING": 30}
|
||||
):
|
||||
metrics_set.side_effect = ValloxApiException("Fake failure")
|
||||
setup_fetch_metric_data_mock(
|
||||
metrics={"A_CYC_MODE": 0, "A_CYC_HOME_SPEED_SETTING": 30}
|
||||
)
|
||||
|
||||
with patch_set_values() as set_values:
|
||||
set_values.side_effect = ValloxApiException("Fake failure")
|
||||
await hass.config_entries.async_setup(mock_entry.entry_id)
|
||||
await hass.async_block_till_done()
|
||||
with pytest.raises(HomeAssistantError):
|
||||
|
49
tests/components/vallox/test_init.py
Normal file
49
tests/components/vallox/test_init.py
Normal file
@ -0,0 +1,49 @@
|
||||
"""Tests for the Vallox integration."""
|
||||
|
||||
import pytest
|
||||
from vallox_websocket_api import Profile
|
||||
|
||||
from homeassistant.components.vallox import (
|
||||
ATTR_PROFILE_FAN_SPEED,
|
||||
SERVICE_SET_PROFILE_FAN_SPEED_AWAY,
|
||||
SERVICE_SET_PROFILE_FAN_SPEED_BOOST,
|
||||
SERVICE_SET_PROFILE_FAN_SPEED_HOME,
|
||||
)
|
||||
from homeassistant.components.vallox.const import DOMAIN
|
||||
from homeassistant.core import HomeAssistant
|
||||
|
||||
from .conftest import patch_set_fan_speed
|
||||
|
||||
from tests.common import MockConfigEntry
|
||||
|
||||
|
||||
@pytest.mark.parametrize(
|
||||
("service", "profile"),
|
||||
[
|
||||
(SERVICE_SET_PROFILE_FAN_SPEED_HOME, Profile.HOME),
|
||||
(SERVICE_SET_PROFILE_FAN_SPEED_AWAY, Profile.AWAY),
|
||||
(SERVICE_SET_PROFILE_FAN_SPEED_BOOST, Profile.BOOST),
|
||||
],
|
||||
)
|
||||
async def test_create_service(
|
||||
hass: HomeAssistant,
|
||||
mock_entry: MockConfigEntry,
|
||||
service: str,
|
||||
profile: Profile,
|
||||
) -> None:
|
||||
"""Test services for setting fan speed."""
|
||||
# Act
|
||||
await hass.config_entries.async_setup(mock_entry.entry_id)
|
||||
await hass.async_block_till_done()
|
||||
|
||||
with patch_set_fan_speed() as set_fan_speed:
|
||||
await hass.services.async_call(
|
||||
DOMAIN,
|
||||
service,
|
||||
service_data={ATTR_PROFILE_FAN_SPEED: 30},
|
||||
)
|
||||
|
||||
await hass.async_block_till_done()
|
||||
|
||||
# Assert
|
||||
set_fan_speed.assert_called_once_with(profile, 30)
|
@ -9,7 +9,7 @@ from homeassistant.components.number.const import (
|
||||
from homeassistant.const import ATTR_ENTITY_ID
|
||||
from homeassistant.core import HomeAssistant
|
||||
|
||||
from .conftest import patch_metrics, patch_metrics_set
|
||||
from .conftest import patch_set_values
|
||||
|
||||
from tests.common import MockConfigEntry
|
||||
|
||||
@ -41,15 +41,15 @@ async def test_temperature_number_entities(
|
||||
value: float,
|
||||
mock_entry: MockConfigEntry,
|
||||
hass: HomeAssistant,
|
||||
setup_fetch_metric_data_mock,
|
||||
) -> None:
|
||||
"""Test temperature entities."""
|
||||
# Arrange
|
||||
metrics = {metric_key: value}
|
||||
setup_fetch_metric_data_mock(metrics={metric_key: value})
|
||||
|
||||
# Act
|
||||
with patch_metrics(metrics=metrics):
|
||||
await hass.config_entries.async_setup(mock_entry.entry_id)
|
||||
await hass.async_block_till_done()
|
||||
await hass.config_entries.async_setup(mock_entry.entry_id)
|
||||
await hass.async_block_till_done()
|
||||
|
||||
# Assert
|
||||
sensor = hass.states.get(entity_id)
|
||||
@ -66,10 +66,14 @@ async def test_temperature_number_entity_set(
|
||||
value: float,
|
||||
mock_entry: MockConfigEntry,
|
||||
hass: HomeAssistant,
|
||||
setup_fetch_metric_data_mock,
|
||||
) -> None:
|
||||
"""Test temperature set."""
|
||||
# Arrange
|
||||
setup_fetch_metric_data_mock(metrics={metric_key: value})
|
||||
|
||||
# Act
|
||||
with patch_metrics(metrics={}), patch_metrics_set() as metrics_set:
|
||||
with patch_set_values() as set_values:
|
||||
await hass.config_entries.async_setup(mock_entry.entry_id)
|
||||
await hass.async_block_till_done()
|
||||
await hass.services.async_call(
|
||||
@ -81,4 +85,4 @@ async def test_temperature_number_entity_set(
|
||||
},
|
||||
)
|
||||
await hass.async_block_till_done()
|
||||
metrics_set.assert_called_once_with({metric_key: value})
|
||||
set_values.assert_called_once_with({metric_key: value})
|
||||
|
@ -1,15 +1,13 @@
|
||||
"""Tests for Vallox sensor platform."""
|
||||
|
||||
from datetime import datetime, timedelta, tzinfo
|
||||
from unittest.mock import patch
|
||||
|
||||
import pytest
|
||||
from vallox_websocket_api import MetricData
|
||||
|
||||
from homeassistant.core import HomeAssistant
|
||||
from homeassistant.util import dt as dt_util
|
||||
|
||||
from .conftest import patch_metrics
|
||||
|
||||
from tests.common import MockConfigEntry
|
||||
|
||||
|
||||
@ -45,34 +43,21 @@ def _now_at_13():
|
||||
return dt_util.now().timetz().replace(hour=13, minute=0, second=0, microsecond=0)
|
||||
|
||||
|
||||
async def test_remaining_filter_returns_timestamp(
|
||||
mock_entry: MockConfigEntry, hass: HomeAssistant
|
||||
) -> None:
|
||||
"""Test that the remaining time for filter sensor returns a timestamp."""
|
||||
# Act
|
||||
with patch(
|
||||
"homeassistant.components.vallox._api_get_next_filter_change_date",
|
||||
return_value=dt_util.now().date(),
|
||||
), patch_metrics(metrics={}):
|
||||
await hass.config_entries.async_setup(mock_entry.entry_id)
|
||||
await hass.async_block_till_done()
|
||||
|
||||
# Assert
|
||||
sensor = hass.states.get("sensor.vallox_remaining_time_for_filter")
|
||||
assert sensor.attributes["device_class"] == "timestamp"
|
||||
|
||||
|
||||
async def test_remaining_time_for_filter_none_returned_from_vallox(
|
||||
mock_entry: MockConfigEntry, hass: HomeAssistant
|
||||
mock_entry: MockConfigEntry, hass: HomeAssistant, setup_fetch_metric_data_mock
|
||||
) -> None:
|
||||
"""Test that the remaining time for filter sensor returns 'unknown' when Vallox returns None."""
|
||||
|
||||
class MockMetricData(MetricData):
|
||||
@property
|
||||
def next_filter_change_date(self):
|
||||
return None
|
||||
|
||||
# Arrange
|
||||
setup_fetch_metric_data_mock(metric_data_class=MockMetricData)
|
||||
# Act
|
||||
with patch(
|
||||
"homeassistant.components.vallox._api_get_next_filter_change_date",
|
||||
return_value=None,
|
||||
), patch_metrics(metrics={}):
|
||||
await hass.config_entries.async_setup(mock_entry.entry_id)
|
||||
await hass.async_block_till_done()
|
||||
await hass.config_entries.async_setup(mock_entry.entry_id)
|
||||
await hass.async_block_till_done()
|
||||
|
||||
# Assert
|
||||
sensor = hass.states.get("sensor.vallox_remaining_time_for_filter")
|
||||
@ -80,166 +65,72 @@ async def test_remaining_time_for_filter_none_returned_from_vallox(
|
||||
|
||||
|
||||
@pytest.mark.parametrize(
|
||||
"set_tz",
|
||||
("remaining_days", "set_tz"),
|
||||
[
|
||||
"utc",
|
||||
"helsinki",
|
||||
"new_york",
|
||||
(112, "utc"),
|
||||
(112, "helsinki"),
|
||||
(112, "new_york"),
|
||||
(0, "utc"),
|
||||
(-3, "utc"),
|
||||
],
|
||||
indirect=True,
|
||||
indirect=["set_tz"],
|
||||
)
|
||||
async def test_remaining_time_for_filter_in_the_future(
|
||||
mock_entry: MockConfigEntry, set_tz: tzinfo, hass: HomeAssistant
|
||||
async def test_remaining_time_for_filter(
|
||||
remaining_days,
|
||||
set_tz: tzinfo,
|
||||
mock_entry: MockConfigEntry,
|
||||
hass: HomeAssistant,
|
||||
setup_fetch_metric_data_mock,
|
||||
) -> None:
|
||||
"""Test remaining time for filter when Vallox returns a date in the future."""
|
||||
"""Test remaining time for filter when Vallox returns different dates."""
|
||||
# Arrange
|
||||
remaining_days = 112
|
||||
mocked_filter_end_date = dt_util.now().date() + timedelta(days=remaining_days)
|
||||
|
||||
class MockMetricData(MetricData):
|
||||
@property
|
||||
def next_filter_change_date(self):
|
||||
return mocked_filter_end_date
|
||||
|
||||
setup_fetch_metric_data_mock(metric_data_class=MockMetricData)
|
||||
|
||||
# Act
|
||||
with patch(
|
||||
"homeassistant.components.vallox._api_get_next_filter_change_date",
|
||||
return_value=mocked_filter_end_date,
|
||||
), patch_metrics(metrics={}):
|
||||
await hass.config_entries.async_setup(mock_entry.entry_id)
|
||||
await hass.async_block_till_done()
|
||||
await hass.config_entries.async_setup(mock_entry.entry_id)
|
||||
await hass.async_block_till_done()
|
||||
|
||||
# Assert
|
||||
sensor = hass.states.get("sensor.vallox_remaining_time_for_filter")
|
||||
assert sensor.attributes["device_class"] == "timestamp"
|
||||
assert _sensor_to_datetime(sensor) == datetime.combine(
|
||||
mocked_filter_end_date,
|
||||
_now_at_13(),
|
||||
)
|
||||
|
||||
|
||||
async def test_remaining_time_for_filter_today(
|
||||
mock_entry: MockConfigEntry, hass: HomeAssistant
|
||||
@pytest.mark.parametrize(
|
||||
("metrics", "expected_state"),
|
||||
[
|
||||
({"A_CYC_CELL_STATE": 0}, "Heat Recovery"),
|
||||
({"A_CYC_CELL_STATE": 1}, "Cool Recovery"),
|
||||
({"A_CYC_CELL_STATE": 2}, "Bypass"),
|
||||
({"A_CYC_CELL_STATE": 3}, "Defrosting"),
|
||||
({"A_CYC_CELL_STATE": 4}, "unknown"),
|
||||
],
|
||||
)
|
||||
async def test_cell_state_sensor(
|
||||
metrics,
|
||||
expected_state,
|
||||
mock_entry: MockConfigEntry,
|
||||
hass: HomeAssistant,
|
||||
setup_fetch_metric_data_mock,
|
||||
) -> None:
|
||||
"""Test remaining time for filter when Vallox returns today."""
|
||||
"""Test cell state sensor in different states."""
|
||||
# Arrange
|
||||
remaining_days = 0
|
||||
mocked_filter_end_date = dt_util.now().date() + timedelta(days=remaining_days)
|
||||
setup_fetch_metric_data_mock(metrics=metrics)
|
||||
|
||||
# Act
|
||||
with patch(
|
||||
"homeassistant.components.vallox._api_get_next_filter_change_date",
|
||||
return_value=mocked_filter_end_date,
|
||||
), patch_metrics(metrics={}):
|
||||
await hass.config_entries.async_setup(mock_entry.entry_id)
|
||||
await hass.async_block_till_done()
|
||||
|
||||
# Assert
|
||||
sensor = hass.states.get("sensor.vallox_remaining_time_for_filter")
|
||||
assert _sensor_to_datetime(sensor) == datetime.combine(
|
||||
mocked_filter_end_date,
|
||||
_now_at_13(),
|
||||
)
|
||||
|
||||
|
||||
async def test_remaining_time_for_filter_in_the_past(
|
||||
mock_entry: MockConfigEntry, hass: HomeAssistant
|
||||
) -> None:
|
||||
"""Test remaining time for filter when Vallox returns a date in the past."""
|
||||
# Arrange
|
||||
remaining_days = -3
|
||||
mocked_filter_end_date = dt_util.now().date() + timedelta(days=remaining_days)
|
||||
|
||||
# Act
|
||||
with patch(
|
||||
"homeassistant.components.vallox._api_get_next_filter_change_date",
|
||||
return_value=mocked_filter_end_date,
|
||||
), patch_metrics(metrics={}):
|
||||
await hass.config_entries.async_setup(mock_entry.entry_id)
|
||||
await hass.async_block_till_done()
|
||||
|
||||
# Assert
|
||||
sensor = hass.states.get("sensor.vallox_remaining_time_for_filter")
|
||||
assert _sensor_to_datetime(sensor) == datetime.combine(
|
||||
mocked_filter_end_date,
|
||||
_now_at_13(),
|
||||
)
|
||||
|
||||
|
||||
async def test_cell_state_sensor_heat_recovery(
|
||||
mock_entry: MockConfigEntry, hass: HomeAssistant
|
||||
) -> None:
|
||||
"""Test cell state sensor in heat recovery state."""
|
||||
# Arrange
|
||||
metrics = {"A_CYC_CELL_STATE": 0}
|
||||
|
||||
# Act
|
||||
with patch_metrics(metrics=metrics):
|
||||
await hass.config_entries.async_setup(mock_entry.entry_id)
|
||||
await hass.async_block_till_done()
|
||||
await hass.config_entries.async_setup(mock_entry.entry_id)
|
||||
await hass.async_block_till_done()
|
||||
|
||||
# Assert
|
||||
sensor = hass.states.get("sensor.vallox_cell_state")
|
||||
assert sensor.state == "Heat Recovery"
|
||||
|
||||
|
||||
async def test_cell_state_sensor_cool_recovery(
|
||||
mock_entry: MockConfigEntry, hass: HomeAssistant
|
||||
) -> None:
|
||||
"""Test cell state sensor in cool recovery state."""
|
||||
# Arrange
|
||||
metrics = {"A_CYC_CELL_STATE": 1}
|
||||
|
||||
# Act
|
||||
with patch_metrics(metrics=metrics):
|
||||
await hass.config_entries.async_setup(mock_entry.entry_id)
|
||||
await hass.async_block_till_done()
|
||||
|
||||
# Assert
|
||||
sensor = hass.states.get("sensor.vallox_cell_state")
|
||||
assert sensor.state == "Cool Recovery"
|
||||
|
||||
|
||||
async def test_cell_state_sensor_bypass(
|
||||
mock_entry: MockConfigEntry, hass: HomeAssistant
|
||||
) -> None:
|
||||
"""Test cell state sensor in bypass state."""
|
||||
# Arrange
|
||||
metrics = {"A_CYC_CELL_STATE": 2}
|
||||
|
||||
# Act
|
||||
with patch_metrics(metrics=metrics):
|
||||
await hass.config_entries.async_setup(mock_entry.entry_id)
|
||||
await hass.async_block_till_done()
|
||||
|
||||
# Assert
|
||||
sensor = hass.states.get("sensor.vallox_cell_state")
|
||||
assert sensor.state == "Bypass"
|
||||
|
||||
|
||||
async def test_cell_state_sensor_defrosting(
|
||||
mock_entry: MockConfigEntry, hass: HomeAssistant
|
||||
) -> None:
|
||||
"""Test cell state sensor in defrosting state."""
|
||||
# Arrange
|
||||
metrics = {"A_CYC_CELL_STATE": 3}
|
||||
|
||||
# Act
|
||||
with patch_metrics(metrics=metrics):
|
||||
await hass.config_entries.async_setup(mock_entry.entry_id)
|
||||
await hass.async_block_till_done()
|
||||
|
||||
# Assert
|
||||
sensor = hass.states.get("sensor.vallox_cell_state")
|
||||
assert sensor.state == "Defrosting"
|
||||
|
||||
|
||||
async def test_cell_state_sensor_unknown_state(
|
||||
mock_entry: MockConfigEntry, hass: HomeAssistant
|
||||
) -> None:
|
||||
"""Test cell state sensor in unknown state."""
|
||||
# Arrange
|
||||
metrics = {"A_CYC_CELL_STATE": 4}
|
||||
|
||||
# Act
|
||||
with patch_metrics(metrics=metrics):
|
||||
await hass.config_entries.async_setup(mock_entry.entry_id)
|
||||
await hass.async_block_till_done()
|
||||
|
||||
# Assert
|
||||
sensor = hass.states.get("sensor.vallox_cell_state")
|
||||
assert sensor.state == "unknown"
|
||||
assert sensor.state == expected_state
|
||||
|
@ -1,5 +1,4 @@
|
||||
"""Tests for Vallox switch platform."""
|
||||
from unittest.mock import patch
|
||||
|
||||
import pytest
|
||||
|
||||
@ -7,7 +6,7 @@ from homeassistant.components.switch.const import DOMAIN as SWITCH_DOMAIN
|
||||
from homeassistant.const import ATTR_ENTITY_ID, SERVICE_TURN_OFF, SERVICE_TURN_ON
|
||||
from homeassistant.core import HomeAssistant
|
||||
|
||||
from .conftest import patch_metrics, patch_metrics_set
|
||||
from .conftest import patch_set_values
|
||||
|
||||
from tests.common import MockConfigEntry
|
||||
|
||||
@ -26,17 +25,15 @@ async def test_switch_entities(
|
||||
expected_state: str,
|
||||
mock_entry: MockConfigEntry,
|
||||
hass: HomeAssistant,
|
||||
setup_fetch_metric_data_mock,
|
||||
) -> None:
|
||||
"""Test switch entities."""
|
||||
# Arrange
|
||||
metrics = {metric_key: value}
|
||||
setup_fetch_metric_data_mock(metrics={metric_key: value})
|
||||
|
||||
# Act
|
||||
with patch_metrics(metrics=metrics), patch(
|
||||
"homeassistant.components.vallox.Vallox.set_settable_address"
|
||||
):
|
||||
await hass.config_entries.async_setup(mock_entry.entry_id)
|
||||
await hass.async_block_till_done()
|
||||
await hass.config_entries.async_setup(mock_entry.entry_id)
|
||||
await hass.async_block_till_done()
|
||||
|
||||
# Assert
|
||||
sensor = hass.states.get(entity_id)
|
||||
@ -60,9 +57,7 @@ async def test_bypass_lock_switch_entitity_set(
|
||||
) -> None:
|
||||
"""Test bypass lock switch set."""
|
||||
# Act
|
||||
with patch_metrics(metrics={}), patch_metrics_set() as metrics_set, patch(
|
||||
"homeassistant.components.vallox.Vallox.set_settable_address"
|
||||
):
|
||||
with patch_set_values() as set_values:
|
||||
await hass.config_entries.async_setup(mock_entry.entry_id)
|
||||
await hass.async_block_till_done()
|
||||
await hass.services.async_call(
|
||||
@ -71,4 +66,4 @@ async def test_bypass_lock_switch_entitity_set(
|
||||
service_data={ATTR_ENTITY_ID: "switch.vallox_bypass_locked"},
|
||||
)
|
||||
await hass.async_block_till_done()
|
||||
metrics_set.assert_called_once_with({metric_key: value})
|
||||
set_values.assert_called_once_with({metric_key: value})
|
||||
|
Loading…
x
Reference in New Issue
Block a user