Fix level controllable output controls in deCONZ (#77223)
Fix level controllable output controls
This commit is contained in:
parent
859effee56
commit
2161b6f049
5 changed files with 125 additions and 6 deletions
|
@ -4,6 +4,7 @@ from __future__ import annotations
|
|||
from typing import Any, cast
|
||||
|
||||
from pydeconz.interfaces.lights import CoverAction
|
||||
from pydeconz.models import ResourceType
|
||||
from pydeconz.models.event import EventType
|
||||
from pydeconz.models.light.cover import Cover
|
||||
|
||||
|
@ -23,9 +24,9 @@ from .deconz_device import DeconzDevice
|
|||
from .gateway import DeconzGateway, get_gateway_from_config_entry
|
||||
|
||||
DECONZ_TYPE_TO_DEVICE_CLASS = {
|
||||
"Level controllable output": CoverDeviceClass.DAMPER,
|
||||
"Window covering controller": CoverDeviceClass.SHADE,
|
||||
"Window covering device": CoverDeviceClass.SHADE,
|
||||
ResourceType.LEVEL_CONTROLLABLE_OUTPUT.value: CoverDeviceClass.DAMPER,
|
||||
ResourceType.WINDOW_COVERING_CONTROLLER.value: CoverDeviceClass.SHADE,
|
||||
ResourceType.WINDOW_COVERING_DEVICE.value: CoverDeviceClass.SHADE,
|
||||
}
|
||||
|
||||
|
||||
|
@ -71,6 +72,8 @@ class DeconzCover(DeconzDevice[Cover], CoverEntity):
|
|||
|
||||
self._attr_device_class = DECONZ_TYPE_TO_DEVICE_CLASS.get(cover.type)
|
||||
|
||||
self.legacy_mode = cover.type == ResourceType.LEVEL_CONTROLLABLE_OUTPUT.value
|
||||
|
||||
@property
|
||||
def current_cover_position(self) -> int:
|
||||
"""Return the current position of the cover."""
|
||||
|
@ -87,6 +90,7 @@ class DeconzCover(DeconzDevice[Cover], CoverEntity):
|
|||
await self.gateway.api.lights.covers.set_state(
|
||||
id=self._device.resource_id,
|
||||
lift=position,
|
||||
legacy_mode=self.legacy_mode,
|
||||
)
|
||||
|
||||
async def async_open_cover(self, **kwargs: Any) -> None:
|
||||
|
@ -94,6 +98,7 @@ class DeconzCover(DeconzDevice[Cover], CoverEntity):
|
|||
await self.gateway.api.lights.covers.set_state(
|
||||
id=self._device.resource_id,
|
||||
action=CoverAction.OPEN,
|
||||
legacy_mode=self.legacy_mode,
|
||||
)
|
||||
|
||||
async def async_close_cover(self, **kwargs: Any) -> None:
|
||||
|
@ -101,6 +106,7 @@ class DeconzCover(DeconzDevice[Cover], CoverEntity):
|
|||
await self.gateway.api.lights.covers.set_state(
|
||||
id=self._device.resource_id,
|
||||
action=CoverAction.CLOSE,
|
||||
legacy_mode=self.legacy_mode,
|
||||
)
|
||||
|
||||
async def async_stop_cover(self, **kwargs: Any) -> None:
|
||||
|
@ -108,6 +114,7 @@ class DeconzCover(DeconzDevice[Cover], CoverEntity):
|
|||
await self.gateway.api.lights.covers.set_state(
|
||||
id=self._device.resource_id,
|
||||
action=CoverAction.STOP,
|
||||
legacy_mode=self.legacy_mode,
|
||||
)
|
||||
|
||||
@property
|
||||
|
@ -123,6 +130,7 @@ class DeconzCover(DeconzDevice[Cover], CoverEntity):
|
|||
await self.gateway.api.lights.covers.set_state(
|
||||
id=self._device.resource_id,
|
||||
tilt=position,
|
||||
legacy_mode=self.legacy_mode,
|
||||
)
|
||||
|
||||
async def async_open_cover_tilt(self, **kwargs: Any) -> None:
|
||||
|
@ -130,6 +138,7 @@ class DeconzCover(DeconzDevice[Cover], CoverEntity):
|
|||
await self.gateway.api.lights.covers.set_state(
|
||||
id=self._device.resource_id,
|
||||
tilt=0,
|
||||
legacy_mode=self.legacy_mode,
|
||||
)
|
||||
|
||||
async def async_close_cover_tilt(self, **kwargs: Any) -> None:
|
||||
|
@ -137,6 +146,7 @@ class DeconzCover(DeconzDevice[Cover], CoverEntity):
|
|||
await self.gateway.api.lights.covers.set_state(
|
||||
id=self._device.resource_id,
|
||||
tilt=100,
|
||||
legacy_mode=self.legacy_mode,
|
||||
)
|
||||
|
||||
async def async_stop_cover_tilt(self, **kwargs: Any) -> None:
|
||||
|
@ -144,4 +154,5 @@ class DeconzCover(DeconzDevice[Cover], CoverEntity):
|
|||
await self.gateway.api.lights.covers.set_state(
|
||||
id=self._device.resource_id,
|
||||
action=CoverAction.STOP,
|
||||
legacy_mode=self.legacy_mode,
|
||||
)
|
||||
|
|
|
@ -3,7 +3,7 @@
|
|||
"name": "deCONZ",
|
||||
"config_flow": true,
|
||||
"documentation": "https://www.home-assistant.io/integrations/deconz",
|
||||
"requirements": ["pydeconz==103"],
|
||||
"requirements": ["pydeconz==104"],
|
||||
"ssdp": [
|
||||
{
|
||||
"manufacturer": "Royal Philips Electronics",
|
||||
|
|
|
@ -1467,7 +1467,7 @@ pydaikin==2.7.0
|
|||
pydanfossair==0.1.0
|
||||
|
||||
# homeassistant.components.deconz
|
||||
pydeconz==103
|
||||
pydeconz==104
|
||||
|
||||
# homeassistant.components.delijn
|
||||
pydelijn==1.0.0
|
||||
|
|
|
@ -1022,7 +1022,7 @@ pycoolmasternet-async==0.1.2
|
|||
pydaikin==2.7.0
|
||||
|
||||
# homeassistant.components.deconz
|
||||
pydeconz==103
|
||||
pydeconz==104
|
||||
|
||||
# homeassistant.components.dexcom
|
||||
pydexcom==0.2.3
|
||||
|
|
|
@ -213,3 +213,111 @@ async def test_tilt_cover(hass, aioclient_mock):
|
|||
blocking=True,
|
||||
)
|
||||
assert aioclient_mock.mock_calls[4][2] == {"stop": True}
|
||||
|
||||
|
||||
async def test_level_controllable_output_cover(hass, aioclient_mock):
|
||||
"""Test that tilting a cover works."""
|
||||
data = {
|
||||
"lights": {
|
||||
"0": {
|
||||
"etag": "4cefc909134c8e99086b55273c2bde67",
|
||||
"hascolor": False,
|
||||
"lastannounced": "2022-08-08T12:06:18Z",
|
||||
"lastseen": "2022-08-14T14:22Z",
|
||||
"manufacturername": "Keen Home Inc",
|
||||
"modelid": "SV01-410-MP-1.0",
|
||||
"name": "Vent",
|
||||
"state": {
|
||||
"alert": "none",
|
||||
"bri": 242,
|
||||
"on": False,
|
||||
"reachable": True,
|
||||
"sat": 10,
|
||||
},
|
||||
"swversion": "0x00000012",
|
||||
"type": "Level controllable output",
|
||||
"uniqueid": "00:22:a3:00:00:00:00:00-01",
|
||||
}
|
||||
}
|
||||
}
|
||||
with patch.dict(DECONZ_WEB_REQUEST, data):
|
||||
config_entry = await setup_deconz_integration(hass, aioclient_mock)
|
||||
|
||||
assert len(hass.states.async_all()) == 1
|
||||
covering_device = hass.states.get("cover.vent")
|
||||
assert covering_device.state == STATE_OPEN
|
||||
assert covering_device.attributes[ATTR_CURRENT_TILT_POSITION] == 97
|
||||
|
||||
# Verify service calls for tilting cover
|
||||
|
||||
mock_deconz_put_request(aioclient_mock, config_entry.data, "/lights/0/state")
|
||||
|
||||
# Service open cover
|
||||
|
||||
await hass.services.async_call(
|
||||
COVER_DOMAIN,
|
||||
SERVICE_OPEN_COVER,
|
||||
{ATTR_ENTITY_ID: "cover.vent"},
|
||||
blocking=True,
|
||||
)
|
||||
assert aioclient_mock.mock_calls[1][2] == {"on": False}
|
||||
|
||||
# Service close cover
|
||||
|
||||
await hass.services.async_call(
|
||||
COVER_DOMAIN,
|
||||
SERVICE_CLOSE_COVER,
|
||||
{ATTR_ENTITY_ID: "cover.vent"},
|
||||
blocking=True,
|
||||
)
|
||||
assert aioclient_mock.mock_calls[2][2] == {"on": True}
|
||||
|
||||
# Service set cover position
|
||||
|
||||
await hass.services.async_call(
|
||||
COVER_DOMAIN,
|
||||
SERVICE_SET_COVER_POSITION,
|
||||
{ATTR_ENTITY_ID: "cover.vent", ATTR_POSITION: 40},
|
||||
blocking=True,
|
||||
)
|
||||
assert aioclient_mock.mock_calls[3][2] == {"bri": 152}
|
||||
|
||||
# Service set tilt cover
|
||||
|
||||
await hass.services.async_call(
|
||||
COVER_DOMAIN,
|
||||
SERVICE_SET_COVER_TILT_POSITION,
|
||||
{ATTR_ENTITY_ID: "cover.vent", ATTR_TILT_POSITION: 40},
|
||||
blocking=True,
|
||||
)
|
||||
assert aioclient_mock.mock_calls[4][2] == {"sat": 152}
|
||||
|
||||
# Service open tilt cover
|
||||
|
||||
await hass.services.async_call(
|
||||
COVER_DOMAIN,
|
||||
SERVICE_OPEN_COVER_TILT,
|
||||
{ATTR_ENTITY_ID: "cover.vent"},
|
||||
blocking=True,
|
||||
)
|
||||
assert aioclient_mock.mock_calls[5][2] == {"sat": 0}
|
||||
|
||||
# Service close tilt cover
|
||||
|
||||
await hass.services.async_call(
|
||||
COVER_DOMAIN,
|
||||
SERVICE_CLOSE_COVER_TILT,
|
||||
{ATTR_ENTITY_ID: "cover.vent"},
|
||||
blocking=True,
|
||||
)
|
||||
assert aioclient_mock.mock_calls[6][2] == {"sat": 254}
|
||||
|
||||
# Service stop cover movement
|
||||
|
||||
await hass.services.async_call(
|
||||
COVER_DOMAIN,
|
||||
SERVICE_STOP_COVER_TILT,
|
||||
{ATTR_ENTITY_ID: "cover.vent"},
|
||||
blocking=True,
|
||||
)
|
||||
assert aioclient_mock.mock_calls[7][2] == {"bri_inc": 0}
|
||||
|
|
Loading…
Add table
Reference in a new issue