Home Assistant Unofficial Reference 2024.12.1
type_locks.py
Go to the documentation of this file.
1 """Class to hold all lock accessories."""
2 
3 import logging
4 from typing import Any
5 
6 from pyhap.const import CATEGORY_DOOR_LOCK
7 
8 from homeassistant.components.lock import DOMAIN as LOCK_DOMAIN, LockState
9 from homeassistant.const import ATTR_CODE, ATTR_ENTITY_ID, STATE_UNKNOWN
10 from homeassistant.core import State, callback
11 
12 from .accessories import TYPES, HomeAccessory
13 from .const import CHAR_LOCK_CURRENT_STATE, CHAR_LOCK_TARGET_STATE, SERV_LOCK
14 
15 _LOGGER = logging.getLogger(__name__)
16 
17 HASS_TO_HOMEKIT_CURRENT = {
18  LockState.UNLOCKED.value: 0,
19  LockState.UNLOCKING.value: 1,
20  LockState.LOCKING.value: 0,
21  LockState.LOCKED.value: 1,
22  LockState.JAMMED.value: 2,
23  STATE_UNKNOWN: 3,
24 }
25 
26 HASS_TO_HOMEKIT_TARGET = {
27  LockState.UNLOCKED.value: 0,
28  LockState.UNLOCKING.value: 0,
29  LockState.LOCKING.value: 1,
30  LockState.LOCKED.value: 1,
31 }
32 
33 VALID_TARGET_STATES = {
34  LockState.LOCKING.value,
35  LockState.UNLOCKING.value,
36  LockState.LOCKED.value,
37  LockState.UNLOCKED.value,
38 }
39 
40 HOMEKIT_TO_HASS = {
41  0: LockState.UNLOCKED.value,
42  1: LockState.LOCKED.value,
43  2: LockState.JAMMED.value,
44  3: STATE_UNKNOWN,
45 }
46 
47 STATE_TO_SERVICE = {
48  LockState.LOCKING.value: "unlock",
49  LockState.LOCKED.value: "lock",
50  LockState.UNLOCKING.value: "lock",
51  LockState.UNLOCKED.value: "unlock",
52 }
53 
54 
55 @TYPES.register("Lock")
57  """Generate a Lock accessory for a lock entity.
58 
59  The lock entity must support: unlock and lock.
60  """
61 
62  def __init__(self, *args: Any) -> None:
63  """Initialize a Lock accessory object."""
64  super().__init__(*args, category=CATEGORY_DOOR_LOCK)
65  self._code_code = self.configconfig.get(ATTR_CODE)
66  state = self.hasshass.states.get(self.entity_identity_id)
67  assert state is not None
68 
69  serv_lock_mechanism = self.add_preload_service(SERV_LOCK)
70  self.char_current_statechar_current_state = serv_lock_mechanism.configure_char(
71  CHAR_LOCK_CURRENT_STATE, value=HASS_TO_HOMEKIT_CURRENT[STATE_UNKNOWN]
72  )
73  self.char_target_statechar_target_state = serv_lock_mechanism.configure_char(
74  CHAR_LOCK_TARGET_STATE,
75  value=HASS_TO_HOMEKIT_CURRENT[LockState.LOCKED.value],
76  setter_callback=self.set_stateset_state,
77  )
78  self.async_update_stateasync_update_stateasync_update_state(state)
79 
80  def set_state(self, value: int) -> None:
81  """Set lock state to value if call came from HomeKit."""
82  _LOGGER.debug("%s: Set state to %d", self.entity_identity_id, value)
83 
84  hass_value = HOMEKIT_TO_HASS[value]
85  service = STATE_TO_SERVICE[hass_value]
86 
87  params = {ATTR_ENTITY_ID: self.entity_identity_id}
88  if self._code_code:
89  params[ATTR_CODE] = self._code_code
90  self.async_call_serviceasync_call_service(LOCK_DOMAIN, service, params)
91 
92  @callback
93  def async_update_state(self, new_state: State) -> None:
94  """Update lock after state changed."""
95  hass_state = new_state.state
96  current_lock_state = HASS_TO_HOMEKIT_CURRENT.get(
97  hass_state, HASS_TO_HOMEKIT_CURRENT[STATE_UNKNOWN]
98  )
99  target_lock_state = HASS_TO_HOMEKIT_TARGET.get(hass_state)
100  _LOGGER.debug(
101  "%s: Updated current state to %s (current=%d) (target=%s)",
102  self.entity_identity_id,
103  hass_state,
104  current_lock_state,
105  target_lock_state,
106  )
107  # LockTargetState only supports locked and unlocked
108  # Must set lock target state before current state
109  # or there will be no notification
110  if target_lock_state is not None:
111  self.char_target_statechar_target_state.set_value(target_lock_state)
112 
113  # Set lock current state ONLY after ensuring that
114  # target state is correct or there will be no
115  # notification
116  self.char_current_statechar_current_state.set_value(current_lock_state)
None async_call_service(self, str domain, str service, dict[str, Any]|None service_data, Any|None value=None)
Definition: accessories.py:609
None async_update_state(self, State new_state)
Definition: type_locks.py:93
web.Response get(self, web.Request request, str config_key)
Definition: view.py:88