Add tilt support to deCONZ covers (#43607)

This commit is contained in:
Robert Svensson 2020-11-24 21:42:11 +01:00 committed by GitHub
parent dae286aed5
commit acb94b0b59
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
5 changed files with 133 additions and 16 deletions

View File

@ -1,12 +1,17 @@
"""Support for deCONZ covers."""
from homeassistant.components.cover import (
ATTR_POSITION,
ATTR_TILT_POSITION,
DEVICE_CLASS_WINDOW,
DOMAIN,
SUPPORT_CLOSE,
SUPPORT_CLOSE_TILT,
SUPPORT_OPEN,
SUPPORT_OPEN_TILT,
SUPPORT_SET_POSITION,
SUPPORT_SET_TILT_POSITION,
SUPPORT_STOP,
SUPPORT_STOP_TILT,
CoverEntity,
)
from homeassistant.core import callback
@ -60,15 +65,16 @@ class DeconzCover(DeconzDevice, CoverEntity):
self._features |= SUPPORT_STOP
self._features |= SUPPORT_SET_POSITION
@property
def current_cover_position(self):
"""Return the current position of the cover."""
return 100 - self._device.position
if self._device.tilt is not None:
self._features |= SUPPORT_OPEN_TILT
self._features |= SUPPORT_CLOSE_TILT
self._features |= SUPPORT_STOP_TILT
self._features |= SUPPORT_SET_TILT_POSITION
@property
def is_closed(self):
"""Return if the cover is closed."""
return not self._device.is_open
def supported_features(self):
"""Flag supported features."""
return self._features
@property
def device_class(self):
@ -79,14 +85,19 @@ class DeconzCover(DeconzDevice, CoverEntity):
return DEVICE_CLASS_WINDOW
@property
def supported_features(self):
"""Flag supported features."""
return self._features
def current_cover_position(self):
"""Return the current position of the cover."""
return 100 - self._device.lift
@property
def is_closed(self):
"""Return if the cover is closed."""
return not self._device.is_open
async def async_set_cover_position(self, **kwargs):
"""Move the cover to a specific position."""
position = 100 - kwargs[ATTR_POSITION]
await self._device.set_position(position)
await self._device.set_position(lift=position)
async def async_open_cover(self, **kwargs):
"""Open cover."""
@ -99,3 +110,26 @@ class DeconzCover(DeconzDevice, CoverEntity):
async def async_stop_cover(self, **kwargs):
"""Stop cover."""
await self._device.stop()
@property
def current_cover_tilt_position(self):
"""Return the current tilt position of the cover."""
if self._device.tilt is not None:
return 100 - self._device.tilt
async def async_set_cover_tilt_position(self, **kwargs):
"""Tilt the cover to a specific position."""
position = 100 - kwargs[ATTR_TILT_POSITION]
await self._device.set_position(tilt=position)
async def async_open_cover_tilt(self, **kwargs):
"""Open cover tilt."""
await self._device.set_position(tilt=0)
async def async_close_cover_tilt(self, **kwargs):
"""Close cover tilt."""
await self._device.set_position(tilt=100)
async def async_stop_cover_tilt(self, **kwargs):
"""Stop cover tilt."""
await self._device.stop()

View File

@ -3,7 +3,7 @@
"name": "deCONZ",
"config_flow": true,
"documentation": "https://www.home-assistant.io/integrations/deconz",
"requirements": ["pydeconz==74"],
"requirements": ["pydeconz==75"],
"ssdp": [
{
"manufacturer": "Royal Philips Electronics"

View File

@ -1337,7 +1337,7 @@ pydaikin==2.3.1
pydanfossair==0.1.0
# homeassistant.components.deconz
pydeconz==74
pydeconz==75
# homeassistant.components.delijn
pydelijn==0.6.1

View File

@ -670,7 +670,7 @@ pycountry==19.8.18
pydaikin==2.3.1
# homeassistant.components.deconz
pydeconz==74
pydeconz==75
# homeassistant.components.dexcom
pydexcom==0.2.0

View File

@ -3,12 +3,18 @@
from copy import deepcopy
from homeassistant.components.cover import (
ATTR_CURRENT_TILT_POSITION,
ATTR_POSITION,
ATTR_TILT_POSITION,
DOMAIN as COVER_DOMAIN,
SERVICE_CLOSE_COVER,
SERVICE_CLOSE_COVER_TILT,
SERVICE_OPEN_COVER,
SERVICE_OPEN_COVER_TILT,
SERVICE_SET_COVER_POSITION,
SERVICE_SET_COVER_TILT_POSITION,
SERVICE_STOP_COVER,
SERVICE_STOP_COVER_TILT,
)
from homeassistant.components.deconz.const import DOMAIN as DECONZ_DOMAIN
from homeassistant.components.deconz.gateway import get_gateway_from_config_entry
@ -47,7 +53,7 @@ COVERS = {
"id": "deconz old brightness cover id",
"name": "deconz old brightness cover",
"type": "Level controllable output",
"state": {"bri": 254, "on": False, "reachable": True},
"state": {"bri": 255, "on": False, "reachable": True},
"modelid": "Not zigbee spec",
"uniqueid": "00:00:00:00:00:00:00:03-00",
},
@ -165,7 +171,7 @@ async def test_cover(hass):
blocking=True,
)
await hass.async_block_till_done()
set_callback.assert_called_with("put", "/lights/2/state", json={"bri_inc": 0})
set_callback.assert_called_with("put", "/lights/2/state", json={"stop": True})
# Verify service calls for legacy cover
@ -247,3 +253,80 @@ async def test_cover(hass):
await hass.config_entries.async_unload(config_entry.entry_id)
assert len(hass.states.async_all()) == 0
async def test_tilt_cover(hass):
"""Test that tilting a cover works."""
data = deepcopy(DECONZ_WEB_REQUEST)
data["lights"] = {
"0": {
"etag": "87269755b9b3a046485fdae8d96b252c",
"lastannounced": None,
"lastseen": "2020-08-01T16:22:05Z",
"manufacturername": "AXIS",
"modelid": "Gear",
"name": "Covering device",
"state": {
"bri": 0,
"lift": 0,
"on": False,
"open": True,
"reachable": True,
"tilt": 0,
},
"swversion": "100-5.3.5.1122",
"type": "Window covering device",
"uniqueid": "00:24:46:00:00:12:34:56-01",
}
}
config_entry = await setup_deconz_integration(hass, get_state_response=data)
gateway = get_gateway_from_config_entry(hass, config_entry)
assert len(hass.states.async_all()) == 1
entity = hass.states.get("cover.covering_device")
assert entity.state == STATE_OPEN
assert entity.attributes[ATTR_CURRENT_TILT_POSITION] == 100
covering_device = gateway.api.lights["0"]
with patch.object(covering_device, "_request", return_value=True) as set_callback:
await hass.services.async_call(
COVER_DOMAIN,
SERVICE_SET_COVER_TILT_POSITION,
{ATTR_ENTITY_ID: "cover.covering_device", ATTR_TILT_POSITION: 40},
blocking=True,
)
await hass.async_block_till_done()
set_callback.assert_called_with("put", "/lights/0/state", json={"tilt": 60})
with patch.object(covering_device, "_request", return_value=True) as set_callback:
await hass.services.async_call(
COVER_DOMAIN,
SERVICE_OPEN_COVER_TILT,
{ATTR_ENTITY_ID: "cover.covering_device"},
blocking=True,
)
await hass.async_block_till_done()
set_callback.assert_called_with("put", "/lights/0/state", json={"tilt": 0})
with patch.object(covering_device, "_request", return_value=True) as set_callback:
await hass.services.async_call(
COVER_DOMAIN,
SERVICE_CLOSE_COVER_TILT,
{ATTR_ENTITY_ID: "cover.covering_device"},
blocking=True,
)
await hass.async_block_till_done()
set_callback.assert_called_with("put", "/lights/0/state", json={"tilt": 100})
# Service stop cover movement
with patch.object(covering_device, "_request", return_value=True) as set_callback:
await hass.services.async_call(
COVER_DOMAIN,
SERVICE_STOP_COVER_TILT,
{ATTR_ENTITY_ID: "cover.covering_device"},
blocking=True,
)
await hass.async_block_till_done()
set_callback.assert_called_with("put", "/lights/0/state", json={"stop": True})