Support speed parameter in Velux covers (#180036)

Co-authored-by: Joostlek <joostlek@outlook.com>
This commit is contained in:
wollew
2026-08-26 19:06:30 +02:00
committed by GitHub
co-authored by Joostlek
parent 4a07215226
commit d388ffc1cb
5 changed files with 255 additions and 52 deletions
+33 -5
View File
@@ -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,
)
+31 -2
View File
@@ -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": {
+133 -34
View File
@@ -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',
+52 -10
View File
@@ -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
)