Add HomeKit support for slat tilting (#33388)

* Add HomeKit support for slat tilting

* Reset tilt-specific attribute, not position attribute

Co-Authored-By: J. Nick Koston <nick@koston.org>

* Add explanation why we fix HomeKit's targets

We have to assume that the device has worse precision than HomeKit. If it
reports back a state that is only _close_ to HK's requested state, we'll
"fix" what HomeKit requested so that it won't appear out of sync.

Co-authored-by: J. Nick Koston <nick@koston.org>
This commit is contained in:
Marcel Steinbach 2020-03-31 02:47:03 +02:00 committed by GitHub
parent d0dad4bfd6
commit 6208d8c911
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
3 changed files with 143 additions and 4 deletions

View file

@ -5,8 +5,11 @@ import pytest
from homeassistant.components.cover import (
ATTR_CURRENT_POSITION,
ATTR_CURRENT_TILT_POSITION,
ATTR_POSITION,
ATTR_TILT_POSITION,
DOMAIN,
SUPPORT_SET_TILT_POSITION,
SUPPORT_STOP,
)
from homeassistant.components.homekit.const import ATTR_VALUE
@ -14,6 +17,7 @@ from homeassistant.const import (
ATTR_ENTITY_ID,
ATTR_SUPPORTED_FEATURES,
EVENT_HOMEASSISTANT_START,
SERVICE_SET_COVER_TILT_POSITION,
STATE_CLOSED,
STATE_CLOSING,
STATE_OPEN,
@ -193,6 +197,72 @@ async def test_window_set_cover_position(hass, hk_driver, cls, events):
assert events[-1].data[ATTR_VALUE] == 75
async def test_window_cover_set_tilt(hass, hk_driver, cls, events):
"""Test if accessory and HA update slat tilt accordingly."""
entity_id = "cover.window"
hass.states.async_set(
entity_id, STATE_UNKNOWN, {ATTR_SUPPORTED_FEATURES: SUPPORT_SET_TILT_POSITION}
)
await hass.async_block_till_done()
acc = cls.window(hass, hk_driver, "Cover", entity_id, 2, None)
await hass.async_add_job(acc.run)
assert acc.aid == 2
assert acc.category == 14 # CATEGORY_WINDOW_COVERING
assert acc.char_current_tilt.value == 0
assert acc.char_target_tilt.value == 0
hass.states.async_set(entity_id, STATE_UNKNOWN, {ATTR_CURRENT_TILT_POSITION: None})
await hass.async_block_till_done()
assert acc.char_current_tilt.value == 0
assert acc.char_target_tilt.value == 0
hass.states.async_set(entity_id, STATE_UNKNOWN, {ATTR_CURRENT_TILT_POSITION: 100})
await hass.async_block_till_done()
assert acc.char_current_tilt.value == 90
assert acc.char_target_tilt.value == 90
hass.states.async_set(entity_id, STATE_UNKNOWN, {ATTR_CURRENT_TILT_POSITION: 50})
await hass.async_block_till_done()
assert acc.char_current_tilt.value == 0
assert acc.char_target_tilt.value == 0
hass.states.async_set(entity_id, STATE_UNKNOWN, {ATTR_CURRENT_TILT_POSITION: 0})
await hass.async_block_till_done()
assert acc.char_current_tilt.value == -90
assert acc.char_target_tilt.value == -90
# set from HomeKit
call_set_tilt_position = async_mock_service(
hass, DOMAIN, SERVICE_SET_COVER_TILT_POSITION
)
# HomeKit sets tilts between -90 and 90 (degrees), whereas
# Homeassistant expects a % between 0 and 100. Keep that in mind
# when comparing
await hass.async_add_job(acc.char_target_tilt.client_update_value, 90)
await hass.async_block_till_done()
assert call_set_tilt_position[0]
assert call_set_tilt_position[0].data[ATTR_ENTITY_ID] == entity_id
assert call_set_tilt_position[0].data[ATTR_TILT_POSITION] == 100
assert acc.char_current_tilt.value == -90
assert acc.char_target_tilt.value == 90
assert len(events) == 1
assert events[-1].data[ATTR_VALUE] == 100
await hass.async_add_job(acc.char_target_tilt.client_update_value, 45)
await hass.async_block_till_done()
assert call_set_tilt_position[1]
assert call_set_tilt_position[1].data[ATTR_ENTITY_ID] == entity_id
assert call_set_tilt_position[1].data[ATTR_TILT_POSITION] == 75
assert acc.char_current_tilt.value == -90
assert acc.char_target_tilt.value == 45
assert len(events) == 2
assert events[-1].data[ATTR_VALUE] == 75
async def test_window_open_close(hass, hk_driver, cls, events):
"""Test if accessory and HA are updated accordingly."""
entity_id = "cover.window"