mirror of
https://github.com/home-assistant/core.git
synced 2026-08-28 02:24:46 -05:00
Support speed parameter in Velux covers (#180036)
Co-authored-by: Joostlek <joostlek@outlook.com>
This commit is contained in:
@@ -3,6 +3,7 @@
|
||||
from enum import StrEnum
|
||||
from typing import Any, override
|
||||
|
||||
from pyvlx.const import Velocity
|
||||
from pyvlx.opening_device import (
|
||||
Awning,
|
||||
Blind,
|
||||
@@ -17,6 +18,7 @@ from pyvlx.opening_device import (
|
||||
|
||||
from homeassistant.components.cover import (
|
||||
ATTR_POSITION,
|
||||
ATTR_SPEED,
|
||||
ATTR_TILT_POSITION,
|
||||
CoverDeviceClass,
|
||||
CoverEntity,
|
||||
@@ -70,6 +72,7 @@ class VeluxCover(VeluxEntity, CoverEntity):
|
||||
"""Representation of a Velux cover."""
|
||||
|
||||
node: OpeningDevice
|
||||
_attr_translation_key = "cover"
|
||||
|
||||
# Features common to all covers
|
||||
_attr_supported_features = (
|
||||
@@ -77,7 +80,19 @@ class VeluxCover(VeluxEntity, CoverEntity):
|
||||
| CoverEntityFeature.CLOSE
|
||||
| CoverEntityFeature.SET_POSITION
|
||||
| CoverEntityFeature.STOP
|
||||
| CoverEntityFeature.SPEED
|
||||
)
|
||||
_attr_supported_speeds = [
|
||||
Velocity.SILENT.name.lower(),
|
||||
Velocity.FAST.name.lower(),
|
||||
Velocity.DEFAULT.name.lower(),
|
||||
]
|
||||
|
||||
def _velocity_from_speed(self, speed: str | None) -> Velocity | None:
|
||||
"""Return pyvlx Velocity for the given speed string, or None for default."""
|
||||
if speed in self._attr_supported_speeds:
|
||||
return Velocity[speed.upper()]
|
||||
return None
|
||||
|
||||
def __init__(
|
||||
self, hass: HomeAssistant, node: OpeningDevice, config_entry_id: str
|
||||
@@ -128,22 +143,27 @@ class VeluxCover(VeluxEntity, CoverEntity):
|
||||
@override
|
||||
async def async_close_cover(self, **kwargs: Any) -> None:
|
||||
"""Close the cover."""
|
||||
await self.node.close(wait_for_completion=False)
|
||||
velocity = self._velocity_from_speed(kwargs.get(ATTR_SPEED))
|
||||
await self.node.close(velocity=velocity, wait_for_completion=False)
|
||||
|
||||
@wrap_pyvlx_call_exceptions
|
||||
@override
|
||||
async def async_open_cover(self, **kwargs: Any) -> None:
|
||||
"""Open the cover."""
|
||||
await self.node.open(wait_for_completion=False)
|
||||
velocity = self._velocity_from_speed(kwargs.get(ATTR_SPEED))
|
||||
await self.node.open(velocity=velocity, wait_for_completion=False)
|
||||
|
||||
@wrap_pyvlx_call_exceptions
|
||||
@override
|
||||
async def async_set_cover_position(self, **kwargs: Any) -> None:
|
||||
"""Move the cover to a specific position."""
|
||||
position_percent = 100 - kwargs[ATTR_POSITION]
|
||||
velocity = self._velocity_from_speed(kwargs.get(ATTR_SPEED))
|
||||
|
||||
await self.node.set_position(
|
||||
Position(position_percent=position_percent), wait_for_completion=False
|
||||
Position(position_percent=position_percent),
|
||||
velocity=velocity,
|
||||
wait_for_completion=False,
|
||||
)
|
||||
|
||||
@wrap_pyvlx_call_exceptions
|
||||
@@ -214,23 +234,31 @@ class VeluxDualRollerShutter(VeluxCover):
|
||||
@override
|
||||
async def async_close_cover(self, **kwargs: Any) -> None:
|
||||
"""Close the cover."""
|
||||
await self.node.close(curtain=self.part, wait_for_completion=False)
|
||||
velocity = self._velocity_from_speed(kwargs.get(ATTR_SPEED))
|
||||
await self.node.close(
|
||||
curtain=self.part, velocity=velocity, wait_for_completion=False
|
||||
)
|
||||
|
||||
@wrap_pyvlx_call_exceptions
|
||||
@override
|
||||
async def async_open_cover(self, **kwargs: Any) -> None:
|
||||
"""Open the cover."""
|
||||
await self.node.open(curtain=self.part, wait_for_completion=False)
|
||||
velocity = self._velocity_from_speed(kwargs.get(ATTR_SPEED))
|
||||
await self.node.open(
|
||||
curtain=self.part, velocity=velocity, wait_for_completion=False
|
||||
)
|
||||
|
||||
@wrap_pyvlx_call_exceptions
|
||||
@override
|
||||
async def async_set_cover_position(self, **kwargs: Any) -> None:
|
||||
"""Move the cover to a specific position."""
|
||||
position_percent = 100 - kwargs[ATTR_POSITION]
|
||||
velocity = self._velocity_from_speed(kwargs.get(ATTR_SPEED))
|
||||
|
||||
await self.node.set_position(
|
||||
Position(position_percent=position_percent),
|
||||
curtain=self.part,
|
||||
velocity=velocity,
|
||||
wait_for_completion=False,
|
||||
)
|
||||
|
||||
|
||||
@@ -47,11 +47,40 @@
|
||||
}
|
||||
},
|
||||
"cover": {
|
||||
"cover": {
|
||||
"state_attributes": {
|
||||
"speed": {
|
||||
"state": {
|
||||
"default": "Default",
|
||||
"fast": "Fast",
|
||||
"silent": "Silent"
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"dual_roller_shutter_lower": {
|
||||
"name": "Lower shutter"
|
||||
"name": "Lower shutter",
|
||||
"state_attributes": {
|
||||
"speed": {
|
||||
"state": {
|
||||
"default": "[%key:component::velux::entity::cover::cover::state_attributes::speed::state::default%]",
|
||||
"fast": "[%key:component::velux::entity::cover::cover::state_attributes::speed::state::fast%]",
|
||||
"silent": "[%key:component::velux::entity::cover::cover::state_attributes::speed::state::silent%]"
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"dual_roller_shutter_upper": {
|
||||
"name": "Upper shutter"
|
||||
"name": "Upper shutter",
|
||||
"state_attributes": {
|
||||
"speed": {
|
||||
"state": {
|
||||
"default": "[%key:component::velux::entity::cover::cover::state_attributes::speed::state::default%]",
|
||||
"fast": "[%key:component::velux::entity::cover::cover::state_attributes::speed::state::fast%]",
|
||||
"silent": "[%key:component::velux::entity::cover::cover::state_attributes::speed::state::silent%]"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"number": {
|
||||
|
||||
@@ -5,7 +5,13 @@
|
||||
None,
|
||||
]),
|
||||
'area_id': None,
|
||||
'capabilities': None,
|
||||
'capabilities': dict({
|
||||
<CoverEntityCapabilityAttribute.SUPPORTED_SPEEDS: 'supported_speeds'>: list([
|
||||
'silent',
|
||||
'fast',
|
||||
'default',
|
||||
]),
|
||||
}),
|
||||
'config_entry_id': <ANY>,
|
||||
'config_subentry_id': <ANY>,
|
||||
'device_class': None,
|
||||
@@ -30,8 +36,8 @@
|
||||
'platform': 'velux',
|
||||
'previous_unique_id': None,
|
||||
'suggested_object_id': None,
|
||||
'supported_features': <CoverEntityFeature: 255>,
|
||||
'translation_key': None,
|
||||
'supported_features': <CoverEntityFeature: 511>,
|
||||
'translation_key': 'cover',
|
||||
'unique_id': '4711',
|
||||
'unit_of_measurement': None,
|
||||
})
|
||||
@@ -44,7 +50,12 @@
|
||||
<EntityStateAttribute.DEVICE_CLASS: 'device_class'>: 'blind',
|
||||
<EntityStateAttribute.FRIENDLY_NAME: 'friendly_name'>: 'Test Blind',
|
||||
<CoverEntityStateAttribute.IS_CLOSED: 'is_closed'>: False,
|
||||
<EntityStateAttribute.SUPPORTED_FEATURES: 'supported_features'>: <CoverEntityFeature: 255>,
|
||||
<EntityStateAttribute.SUPPORTED_FEATURES: 'supported_features'>: <CoverEntityFeature: 511>,
|
||||
<CoverEntityCapabilityAttribute.SUPPORTED_SPEEDS: 'supported_speeds'>: list([
|
||||
'silent',
|
||||
'fast',
|
||||
'default',
|
||||
]),
|
||||
}),
|
||||
'context': <ANY>,
|
||||
'entity_id': 'cover.test_blind',
|
||||
@@ -60,7 +71,13 @@
|
||||
None,
|
||||
]),
|
||||
'area_id': None,
|
||||
'capabilities': None,
|
||||
'capabilities': dict({
|
||||
<CoverEntityCapabilityAttribute.SUPPORTED_SPEEDS: 'supported_speeds'>: list([
|
||||
'silent',
|
||||
'fast',
|
||||
'default',
|
||||
]),
|
||||
}),
|
||||
'config_entry_id': <ANY>,
|
||||
'config_subentry_id': <ANY>,
|
||||
'device_class': None,
|
||||
@@ -85,8 +102,8 @@
|
||||
'platform': 'velux',
|
||||
'previous_unique_id': None,
|
||||
'suggested_object_id': None,
|
||||
'supported_features': <CoverEntityFeature: 15>,
|
||||
'translation_key': None,
|
||||
'supported_features': <CoverEntityFeature: 271>,
|
||||
'translation_key': 'cover',
|
||||
'unique_id': 'serial_Awning',
|
||||
'unit_of_measurement': None,
|
||||
})
|
||||
@@ -98,7 +115,12 @@
|
||||
<EntityStateAttribute.DEVICE_CLASS: 'device_class'>: 'awning',
|
||||
<EntityStateAttribute.FRIENDLY_NAME: 'friendly_name'>: 'Test Awning',
|
||||
<CoverEntityStateAttribute.IS_CLOSED: 'is_closed'>: False,
|
||||
<EntityStateAttribute.SUPPORTED_FEATURES: 'supported_features'>: <CoverEntityFeature: 15>,
|
||||
<EntityStateAttribute.SUPPORTED_FEATURES: 'supported_features'>: <CoverEntityFeature: 271>,
|
||||
<CoverEntityCapabilityAttribute.SUPPORTED_SPEEDS: 'supported_speeds'>: list([
|
||||
'silent',
|
||||
'fast',
|
||||
'default',
|
||||
]),
|
||||
}),
|
||||
'context': <ANY>,
|
||||
'entity_id': 'cover.test_awning',
|
||||
@@ -114,7 +136,13 @@
|
||||
None,
|
||||
]),
|
||||
'area_id': None,
|
||||
'capabilities': None,
|
||||
'capabilities': dict({
|
||||
<CoverEntityCapabilityAttribute.SUPPORTED_SPEEDS: 'supported_speeds'>: list([
|
||||
'silent',
|
||||
'fast',
|
||||
'default',
|
||||
]),
|
||||
}),
|
||||
'config_entry_id': <ANY>,
|
||||
'config_subentry_id': <ANY>,
|
||||
'device_class': None,
|
||||
@@ -139,8 +167,8 @@
|
||||
'platform': 'velux',
|
||||
'previous_unique_id': None,
|
||||
'suggested_object_id': None,
|
||||
'supported_features': <CoverEntityFeature: 15>,
|
||||
'translation_key': None,
|
||||
'supported_features': <CoverEntityFeature: 271>,
|
||||
'translation_key': 'cover',
|
||||
'unique_id': 'serial_DualRollerShutter',
|
||||
'unit_of_measurement': None,
|
||||
})
|
||||
@@ -152,7 +180,12 @@
|
||||
<EntityStateAttribute.DEVICE_CLASS: 'device_class'>: 'shutter',
|
||||
<EntityStateAttribute.FRIENDLY_NAME: 'friendly_name'>: 'Test DualRollerShutter',
|
||||
<CoverEntityStateAttribute.IS_CLOSED: 'is_closed'>: False,
|
||||
<EntityStateAttribute.SUPPORTED_FEATURES: 'supported_features'>: <CoverEntityFeature: 15>,
|
||||
<EntityStateAttribute.SUPPORTED_FEATURES: 'supported_features'>: <CoverEntityFeature: 271>,
|
||||
<CoverEntityCapabilityAttribute.SUPPORTED_SPEEDS: 'supported_speeds'>: list([
|
||||
'silent',
|
||||
'fast',
|
||||
'default',
|
||||
]),
|
||||
}),
|
||||
'context': <ANY>,
|
||||
'entity_id': 'cover.test_dualrollershutter',
|
||||
@@ -168,7 +201,13 @@
|
||||
None,
|
||||
]),
|
||||
'area_id': None,
|
||||
'capabilities': None,
|
||||
'capabilities': dict({
|
||||
<CoverEntityCapabilityAttribute.SUPPORTED_SPEEDS: 'supported_speeds'>: list([
|
||||
'silent',
|
||||
'fast',
|
||||
'default',
|
||||
]),
|
||||
}),
|
||||
'config_entry_id': <ANY>,
|
||||
'config_subentry_id': <ANY>,
|
||||
'device_class': None,
|
||||
@@ -193,7 +232,7 @@
|
||||
'platform': 'velux',
|
||||
'previous_unique_id': None,
|
||||
'suggested_object_id': None,
|
||||
'supported_features': <CoverEntityFeature: 15>,
|
||||
'supported_features': <CoverEntityFeature: 271>,
|
||||
'translation_key': 'dual_roller_shutter_lower',
|
||||
'unique_id': 'serial_DualRollerShutter_lower',
|
||||
'unit_of_measurement': None,
|
||||
@@ -206,7 +245,12 @@
|
||||
<EntityStateAttribute.DEVICE_CLASS: 'device_class'>: 'shutter',
|
||||
<EntityStateAttribute.FRIENDLY_NAME: 'friendly_name'>: 'Test DualRollerShutter Lower shutter',
|
||||
<CoverEntityStateAttribute.IS_CLOSED: 'is_closed'>: False,
|
||||
<EntityStateAttribute.SUPPORTED_FEATURES: 'supported_features'>: <CoverEntityFeature: 15>,
|
||||
<EntityStateAttribute.SUPPORTED_FEATURES: 'supported_features'>: <CoverEntityFeature: 271>,
|
||||
<CoverEntityCapabilityAttribute.SUPPORTED_SPEEDS: 'supported_speeds'>: list([
|
||||
'silent',
|
||||
'fast',
|
||||
'default',
|
||||
]),
|
||||
}),
|
||||
'context': <ANY>,
|
||||
'entity_id': 'cover.test_dualrollershutter_lower_shutter',
|
||||
@@ -222,7 +266,13 @@
|
||||
None,
|
||||
]),
|
||||
'area_id': None,
|
||||
'capabilities': None,
|
||||
'capabilities': dict({
|
||||
<CoverEntityCapabilityAttribute.SUPPORTED_SPEEDS: 'supported_speeds'>: list([
|
||||
'silent',
|
||||
'fast',
|
||||
'default',
|
||||
]),
|
||||
}),
|
||||
'config_entry_id': <ANY>,
|
||||
'config_subentry_id': <ANY>,
|
||||
'device_class': None,
|
||||
@@ -247,7 +297,7 @@
|
||||
'platform': 'velux',
|
||||
'previous_unique_id': None,
|
||||
'suggested_object_id': None,
|
||||
'supported_features': <CoverEntityFeature: 15>,
|
||||
'supported_features': <CoverEntityFeature: 271>,
|
||||
'translation_key': 'dual_roller_shutter_upper',
|
||||
'unique_id': 'serial_DualRollerShutter_upper',
|
||||
'unit_of_measurement': None,
|
||||
@@ -260,7 +310,12 @@
|
||||
<EntityStateAttribute.DEVICE_CLASS: 'device_class'>: 'shutter',
|
||||
<EntityStateAttribute.FRIENDLY_NAME: 'friendly_name'>: 'Test DualRollerShutter Upper shutter',
|
||||
<CoverEntityStateAttribute.IS_CLOSED: 'is_closed'>: False,
|
||||
<EntityStateAttribute.SUPPORTED_FEATURES: 'supported_features'>: <CoverEntityFeature: 15>,
|
||||
<EntityStateAttribute.SUPPORTED_FEATURES: 'supported_features'>: <CoverEntityFeature: 271>,
|
||||
<CoverEntityCapabilityAttribute.SUPPORTED_SPEEDS: 'supported_speeds'>: list([
|
||||
'silent',
|
||||
'fast',
|
||||
'default',
|
||||
]),
|
||||
}),
|
||||
'context': <ANY>,
|
||||
'entity_id': 'cover.test_dualrollershutter_upper_shutter',
|
||||
@@ -276,7 +331,13 @@
|
||||
None,
|
||||
]),
|
||||
'area_id': None,
|
||||
'capabilities': None,
|
||||
'capabilities': dict({
|
||||
<CoverEntityCapabilityAttribute.SUPPORTED_SPEEDS: 'supported_speeds'>: list([
|
||||
'silent',
|
||||
'fast',
|
||||
'default',
|
||||
]),
|
||||
}),
|
||||
'config_entry_id': <ANY>,
|
||||
'config_subentry_id': <ANY>,
|
||||
'device_class': None,
|
||||
@@ -301,8 +362,8 @@
|
||||
'platform': 'velux',
|
||||
'previous_unique_id': None,
|
||||
'suggested_object_id': None,
|
||||
'supported_features': <CoverEntityFeature: 15>,
|
||||
'translation_key': None,
|
||||
'supported_features': <CoverEntityFeature: 271>,
|
||||
'translation_key': 'cover',
|
||||
'unique_id': 'serial_GarageDoor',
|
||||
'unit_of_measurement': None,
|
||||
})
|
||||
@@ -314,7 +375,12 @@
|
||||
<EntityStateAttribute.DEVICE_CLASS: 'device_class'>: 'garage',
|
||||
<EntityStateAttribute.FRIENDLY_NAME: 'friendly_name'>: 'Test GarageDoor',
|
||||
<CoverEntityStateAttribute.IS_CLOSED: 'is_closed'>: False,
|
||||
<EntityStateAttribute.SUPPORTED_FEATURES: 'supported_features'>: <CoverEntityFeature: 15>,
|
||||
<EntityStateAttribute.SUPPORTED_FEATURES: 'supported_features'>: <CoverEntityFeature: 271>,
|
||||
<CoverEntityCapabilityAttribute.SUPPORTED_SPEEDS: 'supported_speeds'>: list([
|
||||
'silent',
|
||||
'fast',
|
||||
'default',
|
||||
]),
|
||||
}),
|
||||
'context': <ANY>,
|
||||
'entity_id': 'cover.test_garagedoor',
|
||||
@@ -330,7 +396,13 @@
|
||||
None,
|
||||
]),
|
||||
'area_id': None,
|
||||
'capabilities': None,
|
||||
'capabilities': dict({
|
||||
<CoverEntityCapabilityAttribute.SUPPORTED_SPEEDS: 'supported_speeds'>: list([
|
||||
'silent',
|
||||
'fast',
|
||||
'default',
|
||||
]),
|
||||
}),
|
||||
'config_entry_id': <ANY>,
|
||||
'config_subentry_id': <ANY>,
|
||||
'device_class': None,
|
||||
@@ -355,8 +427,8 @@
|
||||
'platform': 'velux',
|
||||
'previous_unique_id': None,
|
||||
'suggested_object_id': None,
|
||||
'supported_features': <CoverEntityFeature: 15>,
|
||||
'translation_key': None,
|
||||
'supported_features': <CoverEntityFeature: 271>,
|
||||
'translation_key': 'cover',
|
||||
'unique_id': 'serial_Gate',
|
||||
'unit_of_measurement': None,
|
||||
})
|
||||
@@ -368,7 +440,12 @@
|
||||
<EntityStateAttribute.DEVICE_CLASS: 'device_class'>: 'gate',
|
||||
<EntityStateAttribute.FRIENDLY_NAME: 'friendly_name'>: 'Test Gate',
|
||||
<CoverEntityStateAttribute.IS_CLOSED: 'is_closed'>: False,
|
||||
<EntityStateAttribute.SUPPORTED_FEATURES: 'supported_features'>: <CoverEntityFeature: 15>,
|
||||
<EntityStateAttribute.SUPPORTED_FEATURES: 'supported_features'>: <CoverEntityFeature: 271>,
|
||||
<CoverEntityCapabilityAttribute.SUPPORTED_SPEEDS: 'supported_speeds'>: list([
|
||||
'silent',
|
||||
'fast',
|
||||
'default',
|
||||
]),
|
||||
}),
|
||||
'context': <ANY>,
|
||||
'entity_id': 'cover.test_gate',
|
||||
@@ -384,7 +461,13 @@
|
||||
None,
|
||||
]),
|
||||
'area_id': None,
|
||||
'capabilities': None,
|
||||
'capabilities': dict({
|
||||
<CoverEntityCapabilityAttribute.SUPPORTED_SPEEDS: 'supported_speeds'>: list([
|
||||
'silent',
|
||||
'fast',
|
||||
'default',
|
||||
]),
|
||||
}),
|
||||
'config_entry_id': <ANY>,
|
||||
'config_subentry_id': <ANY>,
|
||||
'device_class': None,
|
||||
@@ -409,8 +492,8 @@
|
||||
'platform': 'velux',
|
||||
'previous_unique_id': None,
|
||||
'suggested_object_id': None,
|
||||
'supported_features': <CoverEntityFeature: 15>,
|
||||
'translation_key': None,
|
||||
'supported_features': <CoverEntityFeature: 271>,
|
||||
'translation_key': 'cover',
|
||||
'unique_id': 'serial_RollerShutter',
|
||||
'unit_of_measurement': None,
|
||||
})
|
||||
@@ -422,7 +505,12 @@
|
||||
<EntityStateAttribute.DEVICE_CLASS: 'device_class'>: 'shutter',
|
||||
<EntityStateAttribute.FRIENDLY_NAME: 'friendly_name'>: 'Test RollerShutter',
|
||||
<CoverEntityStateAttribute.IS_CLOSED: 'is_closed'>: False,
|
||||
<EntityStateAttribute.SUPPORTED_FEATURES: 'supported_features'>: <CoverEntityFeature: 15>,
|
||||
<EntityStateAttribute.SUPPORTED_FEATURES: 'supported_features'>: <CoverEntityFeature: 271>,
|
||||
<CoverEntityCapabilityAttribute.SUPPORTED_SPEEDS: 'supported_speeds'>: list([
|
||||
'silent',
|
||||
'fast',
|
||||
'default',
|
||||
]),
|
||||
}),
|
||||
'context': <ANY>,
|
||||
'entity_id': 'cover.test_rollershutter',
|
||||
@@ -438,7 +526,13 @@
|
||||
None,
|
||||
]),
|
||||
'area_id': None,
|
||||
'capabilities': None,
|
||||
'capabilities': dict({
|
||||
<CoverEntityCapabilityAttribute.SUPPORTED_SPEEDS: 'supported_speeds'>: list([
|
||||
'silent',
|
||||
'fast',
|
||||
'default',
|
||||
]),
|
||||
}),
|
||||
'config_entry_id': <ANY>,
|
||||
'config_subentry_id': <ANY>,
|
||||
'device_class': None,
|
||||
@@ -463,8 +557,8 @@
|
||||
'platform': 'velux',
|
||||
'previous_unique_id': None,
|
||||
'suggested_object_id': None,
|
||||
'supported_features': <CoverEntityFeature: 15>,
|
||||
'translation_key': None,
|
||||
'supported_features': <CoverEntityFeature: 271>,
|
||||
'translation_key': 'cover',
|
||||
'unique_id': 'serial_Window',
|
||||
'unit_of_measurement': None,
|
||||
})
|
||||
@@ -476,7 +570,12 @@
|
||||
<EntityStateAttribute.DEVICE_CLASS: 'device_class'>: 'window',
|
||||
<EntityStateAttribute.FRIENDLY_NAME: 'friendly_name'>: 'Test Window',
|
||||
<CoverEntityStateAttribute.IS_CLOSED: 'is_closed'>: False,
|
||||
<EntityStateAttribute.SUPPORTED_FEATURES: 'supported_features'>: <CoverEntityFeature: 15>,
|
||||
<EntityStateAttribute.SUPPORTED_FEATURES: 'supported_features'>: <CoverEntityFeature: 271>,
|
||||
<CoverEntityCapabilityAttribute.SUPPORTED_SPEEDS: 'supported_speeds'>: list([
|
||||
'silent',
|
||||
'fast',
|
||||
'default',
|
||||
]),
|
||||
}),
|
||||
'context': <ANY>,
|
||||
'entity_id': 'cover.test_window',
|
||||
|
||||
@@ -31,7 +31,12 @@
|
||||
'device_class': 'window',
|
||||
'friendly_name': 'Test Window',
|
||||
'is_closed': False,
|
||||
'supported_features': 15,
|
||||
'supported_features': 271,
|
||||
'supported_speeds': list([
|
||||
'silent',
|
||||
'fast',
|
||||
'default',
|
||||
]),
|
||||
}),
|
||||
'entity_id': 'cover.test_window',
|
||||
'last_changed': '2025-01-01T00:00:00+00:00',
|
||||
|
||||
@@ -1,8 +1,9 @@
|
||||
"""Tests for the Velux cover platform."""
|
||||
|
||||
from unittest.mock import AsyncMock
|
||||
from unittest.mock import ANY, AsyncMock
|
||||
|
||||
import pytest
|
||||
from pyvlx.const import Velocity
|
||||
from pyvlx.exception import PyVLXException
|
||||
from pyvlx.opening_device import (
|
||||
Awning,
|
||||
@@ -15,6 +16,7 @@ from pyvlx.opening_device import (
|
||||
|
||||
from homeassistant.components.cover import (
|
||||
ATTR_POSITION,
|
||||
ATTR_SPEED,
|
||||
ATTR_TILT_POSITION,
|
||||
DOMAIN as COVER_DOMAIN,
|
||||
SERVICE_CLOSE_COVER,
|
||||
@@ -159,7 +161,7 @@ async def test_cover_closed(
|
||||
# Window command tests
|
||||
|
||||
|
||||
async def test_window_open_close_stop_services(
|
||||
async def test_window_open_close_stop_services_no_speed(
|
||||
hass: HomeAssistant, mock_window: AsyncMock
|
||||
) -> None:
|
||||
"""Verify open/close/stop services map to device calls with no wait."""
|
||||
@@ -169,12 +171,12 @@ async def test_window_open_close_stop_services(
|
||||
await hass.services.async_call(
|
||||
COVER_DOMAIN, SERVICE_OPEN_COVER, {"entity_id": entity_id}, blocking=True
|
||||
)
|
||||
mock_window.open.assert_awaited_once_with(wait_for_completion=False)
|
||||
mock_window.open.assert_awaited_once_with(velocity=None, wait_for_completion=False)
|
||||
|
||||
await hass.services.async_call(
|
||||
COVER_DOMAIN, SERVICE_CLOSE_COVER, {"entity_id": entity_id}, blocking=True
|
||||
)
|
||||
mock_window.close.assert_awaited_once_with(wait_for_completion=False)
|
||||
mock_window.close.assert_awaited_once_with(velocity=None, wait_for_completion=False)
|
||||
|
||||
await hass.services.async_call(
|
||||
COVER_DOMAIN, SERVICE_STOP_COVER, {"entity_id": entity_id}, blocking=True
|
||||
@@ -182,6 +184,45 @@ async def test_window_open_close_stop_services(
|
||||
mock_window.stop.assert_awaited_once_with(wait_for_completion=False)
|
||||
|
||||
|
||||
async def test_window_services_with_speed(
|
||||
hass: HomeAssistant, mock_window: AsyncMock
|
||||
) -> None:
|
||||
"""Verify open/close/stop services map to device calls with no wait."""
|
||||
|
||||
entity_id = "cover.test_window"
|
||||
await hass.services.async_call(
|
||||
COVER_DOMAIN,
|
||||
SERVICE_OPEN_COVER,
|
||||
{"entity_id": entity_id, ATTR_SPEED: "silent"},
|
||||
blocking=True,
|
||||
)
|
||||
mock_window.open.assert_awaited_once_with(
|
||||
velocity=Velocity.SILENT, wait_for_completion=False
|
||||
)
|
||||
|
||||
await hass.services.async_call(
|
||||
COVER_DOMAIN,
|
||||
SERVICE_CLOSE_COVER,
|
||||
{"entity_id": entity_id, ATTR_SPEED: "fast"},
|
||||
blocking=True,
|
||||
)
|
||||
mock_window.close.assert_awaited_once_with(
|
||||
velocity=Velocity.FAST, wait_for_completion=False
|
||||
)
|
||||
|
||||
await hass.services.async_call(
|
||||
COVER_DOMAIN,
|
||||
SERVICE_SET_COVER_POSITION,
|
||||
{"entity_id": entity_id, ATTR_SPEED: "default", ATTR_POSITION: 50},
|
||||
blocking=True,
|
||||
)
|
||||
mock_window.set_position.assert_awaited_once_with(
|
||||
ANY,
|
||||
velocity=Velocity.DEFAULT,
|
||||
wait_for_completion=False,
|
||||
)
|
||||
|
||||
|
||||
async def test_window_set_cover_position_inversion(
|
||||
hass: HomeAssistant, mock_window: AsyncMock
|
||||
) -> None:
|
||||
@@ -202,6 +243,7 @@ async def test_window_set_cover_position_inversion(
|
||||
position_obj = args[0]
|
||||
assert position_obj.position_percent == 70
|
||||
assert kwargs.get("wait_for_completion") is False
|
||||
assert kwargs.get("velocity") is None
|
||||
|
||||
|
||||
async def test_window_current_position_and_opening_closing_states(
|
||||
@@ -251,7 +293,7 @@ async def test_dual_roller_shutter_open_close_services(
|
||||
COVER_DOMAIN, SERVICE_OPEN_COVER, {"entity_id": upper_entity_id}, blocking=True
|
||||
)
|
||||
mock_dual_roller_shutter.open.assert_awaited_with(
|
||||
curtain="upper", wait_for_completion=False
|
||||
curtain="upper", velocity=None, wait_for_completion=False
|
||||
)
|
||||
|
||||
# Open lower part
|
||||
@@ -259,7 +301,7 @@ async def test_dual_roller_shutter_open_close_services(
|
||||
COVER_DOMAIN, SERVICE_OPEN_COVER, {"entity_id": lower_entity_id}, blocking=True
|
||||
)
|
||||
mock_dual_roller_shutter.open.assert_awaited_with(
|
||||
curtain="lower", wait_for_completion=False
|
||||
curtain="lower", velocity=None, wait_for_completion=False
|
||||
)
|
||||
|
||||
# Open dual
|
||||
@@ -267,7 +309,7 @@ async def test_dual_roller_shutter_open_close_services(
|
||||
COVER_DOMAIN, SERVICE_OPEN_COVER, {"entity_id": dual_entity_id}, blocking=True
|
||||
)
|
||||
mock_dual_roller_shutter.open.assert_awaited_with(
|
||||
curtain="dual", wait_for_completion=False
|
||||
curtain="dual", velocity=None, wait_for_completion=False
|
||||
)
|
||||
|
||||
# Close upper part
|
||||
@@ -275,7 +317,7 @@ async def test_dual_roller_shutter_open_close_services(
|
||||
COVER_DOMAIN, SERVICE_CLOSE_COVER, {"entity_id": upper_entity_id}, blocking=True
|
||||
)
|
||||
mock_dual_roller_shutter.close.assert_awaited_with(
|
||||
curtain="upper", wait_for_completion=False
|
||||
curtain="upper", velocity=None, wait_for_completion=False
|
||||
)
|
||||
|
||||
# Close lower part
|
||||
@@ -283,7 +325,7 @@ async def test_dual_roller_shutter_open_close_services(
|
||||
COVER_DOMAIN, SERVICE_CLOSE_COVER, {"entity_id": lower_entity_id}, blocking=True
|
||||
)
|
||||
mock_dual_roller_shutter.close.assert_awaited_with(
|
||||
curtain="lower", wait_for_completion=False
|
||||
curtain="lower", velocity=None, wait_for_completion=False
|
||||
)
|
||||
|
||||
# Close dual
|
||||
@@ -291,7 +333,7 @@ async def test_dual_roller_shutter_open_close_services(
|
||||
COVER_DOMAIN, SERVICE_CLOSE_COVER, {"entity_id": dual_entity_id}, blocking=True
|
||||
)
|
||||
mock_dual_roller_shutter.close.assert_awaited_with(
|
||||
curtain="dual", wait_for_completion=False
|
||||
curtain="dual", velocity=None, wait_for_completion=False
|
||||
)
|
||||
|
||||
|
||||
|
||||
Reference in New Issue
Block a user