Fix level controllable output controls in deCONZ (#77223)

Fix level controllable output controls
This commit is contained in:
Robert Svensson 2022-08-25 04:00:54 +02:00 committed by GitHub
parent 859effee56
commit 2161b6f049
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
5 changed files with 125 additions and 6 deletions

View file

@ -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,
)

View file

@ -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",

View file

@ -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

View file

@ -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

View file

@ -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}