Skip to content
Merged
Show file tree
Hide file tree
Changes from 2 commits
Commits
Show all changes
24 commits
Select commit Hold shift + click to select a range
53c3e25
Add HomeKit Door accessory type
Dexwell Oct 21, 2022
ed6e722
Replace absolute positioning check with open/close
Dexwell Oct 22, 2022
4503911
feat: adding testing for the door type cover
jredd Jan 14, 2023
217ea79
Merge pull request #1 from jredd/feat-tests-for-door-cover
Dexwell Jan 14, 2023
21086a4
Merge branch 'dev' into homekit_door_accessory
jredd Jan 14, 2023
24ca92b
Merge branch 'dev' into homekit_door_accessory
bdraco Jan 17, 2023
3336dec
Fixed stale comment
Dexwell Jan 17, 2023
3fa617d
lint
bdraco Jan 17, 2023
b77bc0a
Base Door on Window instead of GarageDoorOpener
Dexwell Jan 20, 2023
0f76705
Base Door on Window
Dexwell Jan 20, 2023
8360d1f
Test Door the same way as Window
Dexwell Feb 2, 2023
d5aedd0
Fixes for flake8
Dexwell Feb 3, 2023
a41de92
Merge branch 'home-assistant:dev' into homekit_door_accessory
Dexwell Feb 3, 2023
7f7e1ab
Fix Black?
Dexwell Feb 3, 2023
b1d8f5d
Merge branch 'homekit_door_accessory' of https://github.com/Dexwell/c…
Dexwell Feb 3, 2023
e7af58c
Merge branch 'home-assistant:dev' into homekit_door_accessory
Dexwell Feb 3, 2023
5136a45
Merge latest changes
Dexwell Feb 13, 2023
7f5e9b1
Merge remote-tracking branch 'upstream/dev' into homekit_door_accessory
Dexwell Feb 13, 2023
38c48fd
Merge branch 'home-assistant:dev' into homekit_door_accessory
Dexwell Feb 13, 2023
6188b1f
Merge branch 'dev' into homekit_door_accessory
bdraco Feb 20, 2023
5d779f9
Merge branch 'dev' into homekit_door_accessory
Dexwell Feb 23, 2023
33c5c88
Merge branch 'dev' into homekit_door_accessory
bdraco Mar 2, 2023
f92a04b
Merge branch 'dev' into homekit_door_accessory
bdraco Mar 7, 2023
a4a936a
add missing coverage
bdraco Mar 7, 2023
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 5 additions & 0 deletions homeassistant/components/homekit/accessories.py
Original file line number Diff line number Diff line change
Expand Up @@ -147,6 +147,11 @@ def get_accessory( # noqa: C901
and features & CoverEntityFeature.SET_POSITION
):
a_type = "Window"
elif (
device_class == CoverDeviceClass.DOOR
and features & (CoverEntityFeature.OPEN | CoverEntityFeature.CLOSE)
):
a_type = "Door"
elif features & CoverEntityFeature.SET_POSITION:
a_type = "WindowCovering"
elif features & (CoverEntityFeature.OPEN | CoverEntityFeature.CLOSE):
Expand Down
1 change: 1 addition & 0 deletions homeassistant/components/homekit/const.py
Original file line number Diff line number Diff line change
Expand Up @@ -119,6 +119,7 @@
SERV_CARBON_DIOXIDE_SENSOR = "CarbonDioxideSensor"
SERV_CARBON_MONOXIDE_SENSOR = "CarbonMonoxideSensor"
SERV_CONTACT_SENSOR = "ContactSensor"
SERV_DOOR = "Door"
SERV_DOORBELL = "Doorbell"
SERV_FANV2 = "Fanv2"
SERV_GARAGE_DOOR_OPENER = "GarageDoorOpener"
Expand Down
106 changes: 106 additions & 0 deletions homeassistant/components/homekit/type_covers.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@
import logging

from pyhap.const import (
CATEGORY_DOOR,
CATEGORY_GARAGE_DOOR_OPENER,
CATEGORY_WINDOW,
CATEGORY_WINDOW_COVERING,
Expand Down Expand Up @@ -54,6 +55,7 @@
HK_POSITION_STOPPED,
PROP_MAX_VALUE,
PROP_MIN_VALUE,
SERV_DOOR,
SERV_GARAGE_DOOR_OPENER,
SERV_WINDOW,
SERV_WINDOW_COVERING,
Expand Down Expand Up @@ -188,6 +190,110 @@ def async_update_state(self, new_state):
self.char_current_state.set_value(current_door_state)


@TYPES.register("Door")
class Door(HomeAccessory):
"""Generate a Door accessory for a cover entity.

The cover entity must be in the 'door' device class
and support no more than open, close, and stop.
"""

def __init__(self, *args):
"""Initialize a Door accessory object."""
super().__init__(*args, category=CATEGORY_DOOR)
state = self.hass.states.get(self.entity_id)

serv_door = self.add_preload_service(SERV_DOOR)
self.char_current_state = serv_door.configure_char(
CHAR_CURRENT_DOOR_STATE, value=0
)
self.char_target_state = serv_door.configure_char(
CHAR_TARGET_DOOR_STATE, value=0, setter_callback=self.set_state
)
Comment thread
Dexwell marked this conversation as resolved.
Outdated
self.char_obstruction_detected = serv_door.configure_char(
CHAR_OBSTRUCTION_DETECTED, value=False
)

self.linked_obstruction_sensor = self.config.get(CONF_LINKED_OBSTRUCTION_SENSOR)
if self.linked_obstruction_sensor:
self._async_update_obstruction_state(
self.hass.states.get(self.linked_obstruction_sensor)
)

self.async_update_state(state)

async def run(self):
"""Handle accessory driver started event.

Run inside the Home Assistant event loop.
"""
if self.linked_obstruction_sensor:
self._subscriptions.append(
async_track_state_change_event(
self.hass,
[self.linked_obstruction_sensor],
self._async_update_obstruction_event,
)
)

await super().run()

@callback
def _async_update_obstruction_event(self, event):
"""Handle state change event listener callback."""
self._async_update_obstruction_state(event.data.get("new_state"))

@callback
def _async_update_obstruction_state(self, new_state):
"""Handle linked obstruction sensor state change to update HomeKit value."""
if not new_state:
return

detected = new_state.state == STATE_ON
if self.char_obstruction_detected.value == detected:
return

self.char_obstruction_detected.set_value(detected)
_LOGGER.debug(
"%s: Set linked obstruction %s sensor to %d",
self.entity_id,
self.linked_obstruction_sensor,
detected,
)

def set_state(self, value):
"""Change door state if call came from HomeKit."""
_LOGGER.debug("%s: Set state to %d", self.entity_id, value)

params = {ATTR_ENTITY_ID: self.entity_id}
if value == HK_DOOR_OPEN:
if self.char_current_state.value != value:
self.char_current_state.set_value(HK_DOOR_OPENING)
self.async_call_service(DOMAIN, SERVICE_OPEN_COVER, params)
elif value == HK_DOOR_CLOSED:
if self.char_current_state.value != value:
self.char_current_state.set_value(HK_DOOR_CLOSING)
self.async_call_service(DOMAIN, SERVICE_CLOSE_COVER, params)

@callback
def async_update_state(self, new_state):
"""Update door state after state changed."""
hass_state = new_state.state
target_door_state = DOOR_TARGET_HASS_TO_HK.get(hass_state)
current_door_state = DOOR_CURRENT_HASS_TO_HK.get(hass_state)

if ATTR_OBSTRUCTION_DETECTED in new_state.attributes:
obstruction_detected = (
new_state.attributes[ATTR_OBSTRUCTION_DETECTED] is True
)
self.char_obstruction_detected.set_value(obstruction_detected)

if target_door_state is not None:
self.char_target_state.set_value(target_door_state)
if current_door_state is not None:
self.char_current_state.set_value(current_door_state)


class OpeningDeviceBase(HomeAccessory):
"""Generate a base Window accessory for a cover entity.

Expand Down