Add support for tilt only covers to HomeKit (#53130)
parent
cb1eab6c24
commit
236738c455
|
@ -127,7 +127,7 @@ def get_accessory(hass, driver, state, aid, config): # noqa: C901
|
|||
and features & cover.SUPPORT_SET_POSITION
|
||||
):
|
||||
a_type = "Window"
|
||||
elif features & cover.SUPPORT_SET_POSITION:
|
||||
elif features & (cover.SUPPORT_SET_POSITION | cover.SUPPORT_SET_TILT_POSITION):
|
||||
a_type = "WindowCovering"
|
||||
elif features & (cover.SUPPORT_OPEN | cover.SUPPORT_CLOSE):
|
||||
a_type = "WindowCoveringBasic"
|
||||
|
|
|
@ -13,6 +13,7 @@ from homeassistant.components.cover import (
|
|||
ATTR_POSITION,
|
||||
ATTR_TILT_POSITION,
|
||||
DOMAIN,
|
||||
SUPPORT_SET_POSITION,
|
||||
SUPPORT_SET_TILT_POSITION,
|
||||
SUPPORT_STOP,
|
||||
)
|
||||
|
@ -53,6 +54,8 @@ from .const import (
|
|||
HK_POSITION_GOING_TO_MAX,
|
||||
HK_POSITION_GOING_TO_MIN,
|
||||
HK_POSITION_STOPPED,
|
||||
PROP_MAX_VALUE,
|
||||
PROP_MIN_VALUE,
|
||||
SERV_GARAGE_DOOR_OPENER,
|
||||
SERV_WINDOW,
|
||||
SERV_WINDOW_COVERING,
|
||||
|
@ -273,12 +276,24 @@ class OpeningDevice(OpeningDeviceBase, HomeAccessory):
|
|||
"""Initialize a WindowCovering accessory object."""
|
||||
super().__init__(*args, category=category, service=service)
|
||||
state = self.hass.states.get(self.entity_id)
|
||||
|
||||
self.char_current_position = self.serv_cover.configure_char(
|
||||
CHAR_CURRENT_POSITION, value=0
|
||||
)
|
||||
target_args = {"value": 0}
|
||||
if self.features & SUPPORT_SET_POSITION:
|
||||
target_args["setter_callback"] = self.move_cover
|
||||
else:
|
||||
# If its tilt only we lock the position state to 0 (closed)
|
||||
# since CHAR_CURRENT_POSITION/CHAR_TARGET_POSITION are required
|
||||
# by homekit, but really don't exist.
|
||||
_LOGGER.debug(
|
||||
"%s does not support setting position, current position will be locked to closed",
|
||||
self.entity_id,
|
||||
)
|
||||
target_args["properties"] = {PROP_MIN_VALUE: 0, PROP_MAX_VALUE: 0}
|
||||
|
||||
self.char_target_position = self.serv_cover.configure_char(
|
||||
CHAR_TARGET_POSITION, value=0, setter_callback=self.move_cover
|
||||
CHAR_TARGET_POSITION, **target_args
|
||||
)
|
||||
self.char_position_state = self.serv_cover.configure_char(
|
||||
CHAR_POSITION_STATE, value=HK_POSITION_STOPPED
|
||||
|
|
|
@ -126,14 +126,28 @@ def test_types(type_name, entity_id, state, attrs, config):
|
|||
"Window",
|
||||
"cover.set_position",
|
||||
"open",
|
||||
{ATTR_DEVICE_CLASS: "window", ATTR_SUPPORTED_FEATURES: 4},
|
||||
{
|
||||
ATTR_DEVICE_CLASS: "window",
|
||||
ATTR_SUPPORTED_FEATURES: cover.SUPPORT_SET_POSITION,
|
||||
},
|
||||
),
|
||||
(
|
||||
"WindowCovering",
|
||||
"cover.set_position",
|
||||
"open",
|
||||
{ATTR_SUPPORTED_FEATURES: cover.SUPPORT_SET_POSITION},
|
||||
),
|
||||
(
|
||||
"WindowCovering",
|
||||
"cover.tilt",
|
||||
"open",
|
||||
{ATTR_SUPPORTED_FEATURES: cover.SUPPORT_SET_TILT_POSITION},
|
||||
),
|
||||
("WindowCovering", "cover.set_position", "open", {ATTR_SUPPORTED_FEATURES: 4}),
|
||||
(
|
||||
"WindowCoveringBasic",
|
||||
"cover.open_window",
|
||||
"open",
|
||||
{ATTR_SUPPORTED_FEATURES: 3},
|
||||
{ATTR_SUPPORTED_FEATURES: (cover.SUPPORT_OPEN | cover.SUPPORT_CLOSE)},
|
||||
),
|
||||
],
|
||||
)
|
||||
|
|
|
@ -18,6 +18,8 @@ from homeassistant.components.homekit.const import (
|
|||
HK_DOOR_CLOSING,
|
||||
HK_DOOR_OPEN,
|
||||
HK_DOOR_OPENING,
|
||||
PROP_MAX_VALUE,
|
||||
PROP_MIN_VALUE,
|
||||
)
|
||||
from homeassistant.components.homekit.type_covers import (
|
||||
GarageDoorOpener,
|
||||
|
@ -133,7 +135,9 @@ async def test_windowcovering_set_cover_position(hass, hk_driver, events):
|
|||
"""Test if accessory and HA are updated accordingly."""
|
||||
entity_id = "cover.window"
|
||||
|
||||
hass.states.async_set(entity_id, None)
|
||||
hass.states.async_set(
|
||||
entity_id, STATE_UNKNOWN, {ATTR_SUPPORTED_FEATURES: SUPPORT_SET_POSITION}
|
||||
)
|
||||
await hass.async_block_till_done()
|
||||
acc = WindowCovering(hass, hk_driver, "Cover", entity_id, 2, None)
|
||||
await acc.run()
|
||||
|
@ -145,31 +149,51 @@ async def test_windowcovering_set_cover_position(hass, hk_driver, events):
|
|||
assert acc.char_current_position.value == 0
|
||||
assert acc.char_target_position.value == 0
|
||||
|
||||
hass.states.async_set(entity_id, STATE_UNKNOWN, {ATTR_CURRENT_POSITION: None})
|
||||
hass.states.async_set(
|
||||
entity_id,
|
||||
STATE_UNKNOWN,
|
||||
{ATTR_SUPPORTED_FEATURES: SUPPORT_SET_POSITION, ATTR_CURRENT_POSITION: None},
|
||||
)
|
||||
await hass.async_block_till_done()
|
||||
assert acc.char_current_position.value == 0
|
||||
assert acc.char_target_position.value == 0
|
||||
assert acc.char_position_state.value == 2
|
||||
|
||||
hass.states.async_set(entity_id, STATE_OPENING, {ATTR_CURRENT_POSITION: 60})
|
||||
hass.states.async_set(
|
||||
entity_id,
|
||||
STATE_OPENING,
|
||||
{ATTR_SUPPORTED_FEATURES: SUPPORT_SET_POSITION, ATTR_CURRENT_POSITION: 60},
|
||||
)
|
||||
await hass.async_block_till_done()
|
||||
assert acc.char_current_position.value == 60
|
||||
assert acc.char_target_position.value == 60
|
||||
assert acc.char_position_state.value == 1
|
||||
|
||||
hass.states.async_set(entity_id, STATE_OPENING, {ATTR_CURRENT_POSITION: 70.0})
|
||||
hass.states.async_set(
|
||||
entity_id,
|
||||
STATE_OPENING,
|
||||
{ATTR_SUPPORTED_FEATURES: SUPPORT_SET_POSITION, ATTR_CURRENT_POSITION: 70.0},
|
||||
)
|
||||
await hass.async_block_till_done()
|
||||
assert acc.char_current_position.value == 70
|
||||
assert acc.char_target_position.value == 70
|
||||
assert acc.char_position_state.value == 1
|
||||
|
||||
hass.states.async_set(entity_id, STATE_CLOSING, {ATTR_CURRENT_POSITION: 50})
|
||||
hass.states.async_set(
|
||||
entity_id,
|
||||
STATE_CLOSING,
|
||||
{ATTR_SUPPORTED_FEATURES: SUPPORT_SET_POSITION, ATTR_CURRENT_POSITION: 50},
|
||||
)
|
||||
await hass.async_block_till_done()
|
||||
assert acc.char_current_position.value == 50
|
||||
assert acc.char_target_position.value == 50
|
||||
assert acc.char_position_state.value == 0
|
||||
|
||||
hass.states.async_set(entity_id, STATE_OPEN, {ATTR_CURRENT_POSITION: 50})
|
||||
hass.states.async_set(
|
||||
entity_id,
|
||||
STATE_OPEN,
|
||||
{ATTR_SUPPORTED_FEATURES: SUPPORT_SET_POSITION, ATTR_CURRENT_POSITION: 50},
|
||||
)
|
||||
await hass.async_block_till_done()
|
||||
assert acc.char_current_position.value == 50
|
||||
assert acc.char_target_position.value == 50
|
||||
|
@ -283,6 +307,27 @@ async def test_windowcovering_cover_set_tilt(hass, hk_driver, events):
|
|||
assert events[-1].data[ATTR_VALUE] == 75
|
||||
|
||||
|
||||
async def test_windowcovering_tilt_only(hass, hk_driver, events):
|
||||
"""Test we lock the window covering closed when its tilt only."""
|
||||
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 = WindowCovering(hass, hk_driver, "Cover", entity_id, 2, None)
|
||||
await acc.run()
|
||||
await hass.async_block_till_done()
|
||||
|
||||
assert acc.aid == 2
|
||||
assert acc.category == 14 # WindowCovering
|
||||
|
||||
assert acc.char_current_position.value == 0
|
||||
assert acc.char_target_position.value == 0
|
||||
assert acc.char_target_position.properties[PROP_MIN_VALUE] == 0
|
||||
assert acc.char_target_position.properties[PROP_MAX_VALUE] == 0
|
||||
|
||||
|
||||
async def test_windowcovering_open_close(hass, hk_driver, events):
|
||||
"""Test if accessory and HA are updated accordingly."""
|
||||
entity_id = "cover.window"
|
||||
|
|
Loading…
Reference in New Issue