1
mirror of https://github.com/home-assistant/core synced 2024-10-07 10:13:38 +02:00

Add Vallox bypass locking switch entity (#75857)

* Switch entity

* adding missing function for tests

* Apply suggestions from code review

Co-authored-by: Sebastian Lövdahl <slovdahl@hibox.fi>

* Review

* fix

* Update homeassistant/components/vallox/switch.py

Co-authored-by: Andre Richter <andre-richter@users.noreply.github.com>

* Apply suggestions from code review

Co-authored-by: Martin Hjelmare <marhje52@gmail.com>

* Adding a separate parameter for the expected state

Co-authored-by: Sebastian Lövdahl <slovdahl@hibox.fi>
Co-authored-by: Andre Richter <andre-richter@users.noreply.github.com>
Co-authored-by: Martin Hjelmare <marhje52@gmail.com>
This commit is contained in:
Jevgeni Kiski 2022-11-18 11:16:54 +02:00 committed by GitHub
parent b166a6d88b
commit 5453b346dd
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
4 changed files with 179 additions and 0 deletions

View File

@ -63,6 +63,7 @@ PLATFORMS: list[str] = [
Platform.SENSOR,
Platform.FAN,
Platform.BINARY_SENSOR,
Platform.SWITCH,
]
ATTR_PROFILE_FAN_SPEED = "fan_speed"

View File

@ -0,0 +1,105 @@
"""Support for Vallox ventilation unit switches."""
from __future__ import annotations
from dataclasses import dataclass
from typing import Any
from vallox_websocket_api import Vallox
from homeassistant.components.switch import SwitchEntity, SwitchEntityDescription
from homeassistant.config_entries import ConfigEntry
from homeassistant.core import HomeAssistant
from homeassistant.helpers.entity import EntityCategory
from homeassistant.helpers.entity_platform import AddEntitiesCallback
from . import ValloxDataUpdateCoordinator, ValloxEntity
from .const import DOMAIN
class ValloxSwitchEntity(ValloxEntity, SwitchEntity):
"""Representation of a Vallox switch."""
entity_description: ValloxSwitchEntityDescription
_attr_entity_category = EntityCategory.CONFIG
_attr_has_entity_name = True
def __init__(
self,
name: str,
coordinator: ValloxDataUpdateCoordinator,
description: ValloxSwitchEntityDescription,
client: Vallox,
) -> None:
"""Initialize the Vallox switch."""
super().__init__(name, coordinator)
self.entity_description = description
self._attr_unique_id = f"{self._device_uuid}-{description.key}"
self._client = client
@property
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
)
) is None:
return None
return value == 1
async def async_turn_on(self, **kwargs: Any) -> None:
"""Turn on."""
await self._set_value(True)
async def async_turn_off(self, **kwargs: Any) -> None:
"""Turn off."""
await self._set_value(False)
async def _set_value(self, value: bool) -> None:
"""Update the current value."""
metric_key = self.entity_description.metric_key
await self._client.set_values({metric_key: 1 if value else 0})
await self.coordinator.async_request_refresh()
@dataclass
class ValloxMetricKeyMixin:
"""Dataclass to allow defining metric_key without a default value."""
metric_key: str
@dataclass
class ValloxSwitchEntityDescription(SwitchEntityDescription, ValloxMetricKeyMixin):
"""Describes Vallox switch entity."""
SWITCH_ENTITIES: tuple[ValloxSwitchEntityDescription, ...] = (
ValloxSwitchEntityDescription(
key="bypass_locked",
name="Bypass locked",
icon="mdi:arrow-horizontal-lock",
metric_key="A_CYC_BYPASS_LOCKED",
),
)
async def async_setup_entry(
hass: HomeAssistant,
entry: ConfigEntry,
async_add_entities: AddEntitiesCallback,
) -> None:
"""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)
for description in SWITCH_ENTITIES
]
)

View File

@ -39,6 +39,11 @@ def patch_metrics(metrics: dict[str, Any]):
)
def patch_metrics_set():
"""Patch the Vallox metrics set values."""
return patch("homeassistant.components.vallox.Vallox.set_values")
@pytest.fixture(autouse=True)
def patch_profile_home():
"""Patch the Vallox profile response."""

View File

@ -0,0 +1,68 @@
"""Tests for Vallox switch platform."""
import pytest
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 tests.common import MockConfigEntry
@pytest.mark.parametrize(
"entity_id, metric_key, value, expected_state",
[
("switch.vallox_bypass_locked", "A_CYC_BYPASS_LOCKED", 1, "on"),
("switch.vallox_bypass_locked", "A_CYC_BYPASS_LOCKED", 0, "off"),
],
)
async def test_switch_entities(
entity_id: str,
metric_key: str,
value: int,
expected_state: str,
mock_entry: MockConfigEntry,
hass: HomeAssistant,
) -> None:
"""Test switch entities."""
# Arrange
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()
# Assert
sensor = hass.states.get(entity_id)
assert sensor
assert sensor.state == expected_state
@pytest.mark.parametrize(
"service, metric_key, value",
[
(SERVICE_TURN_ON, "A_CYC_BYPASS_LOCKED", 1),
(SERVICE_TURN_OFF, "A_CYC_BYPASS_LOCKED", 0),
],
)
async def test_bypass_lock_switch_entitity_set(
service: str,
metric_key: str,
value: int,
mock_entry: MockConfigEntry,
hass: HomeAssistant,
) -> None:
"""Test bypass lock switch set."""
# Act
with patch_metrics(metrics={}), patch_metrics_set() as metrics_set:
await hass.config_entries.async_setup(mock_entry.entry_id)
await hass.async_block_till_done()
await hass.services.async_call(
SWITCH_DOMAIN,
service,
service_data={ATTR_ENTITY_ID: "switch.vallox_bypass_locked"},
)
await hass.async_block_till_done()
metrics_set.assert_called_once_with({metric_key: value})