Home Assistant Unofficial Reference 2024.12.1
lock.py
Go to the documentation of this file.
1 """Support for BMW car locks with BMW ConnectedDrive."""
2 
3 from __future__ import annotations
4 
5 import logging
6 from typing import Any
7 
8 from bimmer_connected.models import MyBMWAPIError
9 from bimmer_connected.vehicle import MyBMWVehicle
10 from bimmer_connected.vehicle.doors_windows import LockState
11 
12 from homeassistant.components.lock import LockEntity
13 from homeassistant.core import HomeAssistant, callback
14 from homeassistant.exceptions import HomeAssistantError
15 from homeassistant.helpers.entity_platform import AddEntitiesCallback
16 
17 from . import BMWConfigEntry
18 from .coordinator import BMWDataUpdateCoordinator
19 from .entity import BMWBaseEntity
20 
21 DOOR_LOCK_STATE = "door_lock_state"
22 _LOGGER = logging.getLogger(__name__)
23 
24 
26  hass: HomeAssistant,
27  config_entry: BMWConfigEntry,
28  async_add_entities: AddEntitiesCallback,
29 ) -> None:
30  """Set up the MyBMW lock from config entry."""
31  coordinator = config_entry.runtime_data.coordinator
32 
33  if not coordinator.read_only:
35  BMWLock(coordinator, vehicle) for vehicle in coordinator.account.vehicles
36  )
37 
38 
40  """Representation of a MyBMW vehicle lock."""
41 
42  _attr_translation_key = "lock"
43 
44  def __init__(
45  self,
46  coordinator: BMWDataUpdateCoordinator,
47  vehicle: MyBMWVehicle,
48  ) -> None:
49  """Initialize the lock."""
50  super().__init__(coordinator, vehicle)
51 
52  self._attr_unique_id_attr_unique_id = f"{vehicle.vin}-lock"
53  self.door_lock_state_availabledoor_lock_state_available = vehicle.is_lsc_enabled
54 
55  async def async_lock(self, **kwargs: Any) -> None:
56  """Lock the car."""
57  _LOGGER.debug("%s: locking doors", self.vehiclevehicle.name)
58  # Only update the HA state machine if the vehicle reliably reports its lock state
59  if self.door_lock_state_availabledoor_lock_state_available:
60  # Optimistic state set here because it takes some time before the
61  # update callback response
62  self._attr_is_locked_attr_is_locked = True
63  self.async_write_ha_stateasync_write_ha_state()
64  try:
65  await self.vehiclevehicle.remote_services.trigger_remote_door_lock()
66  except MyBMWAPIError as ex:
67  # Set the state to unknown if the command fails
68  self._attr_is_locked_attr_is_locked = None
69  self.async_write_ha_stateasync_write_ha_state()
70  raise HomeAssistantError(ex) from ex
71  finally:
72  # Always update the listeners to get the latest state
73  self.coordinator.async_update_listeners()
74 
75  async def async_unlock(self, **kwargs: Any) -> None:
76  """Unlock the car."""
77  _LOGGER.debug("%s: unlocking doors", self.vehiclevehicle.name)
78  # Only update the HA state machine if the vehicle reliably reports its lock state
79  if self.door_lock_state_availabledoor_lock_state_available:
80  # Optimistic state set here because it takes some time before the
81  # update callback response
82  self._attr_is_locked_attr_is_locked = False
83  self.async_write_ha_stateasync_write_ha_state()
84  try:
85  await self.vehiclevehicle.remote_services.trigger_remote_door_unlock()
86  except MyBMWAPIError as ex:
87  # Set the state to unknown if the command fails
88  self._attr_is_locked_attr_is_locked = None
89  self.async_write_ha_stateasync_write_ha_state()
90  raise HomeAssistantError(ex) from ex
91  finally:
92  # Always update the listeners to get the latest state
93  self.coordinator.async_update_listeners()
94 
95  @callback
96  def _handle_coordinator_update(self) -> None:
97  """Handle updated data from the coordinator."""
98  _LOGGER.debug("Updating lock data of %s", self.vehiclevehicle.name)
99 
100  # Only update the HA state machine if the vehicle reliably reports its lock state
101  if self.door_lock_state_availabledoor_lock_state_available:
102  self._attr_is_locked_attr_is_locked = self.vehiclevehicle.doors_and_windows.door_lock_state in {
103  LockState.LOCKED,
104  LockState.SECURED,
105  }
106  self._attr_extra_state_attributes_attr_extra_state_attributes = {
107  DOOR_LOCK_STATE: self.vehiclevehicle.doors_and_windows.door_lock_state.value
108  }
109 
None __init__(self, BMWDataUpdateCoordinator coordinator, MyBMWVehicle vehicle)
Definition: lock.py:48
None async_setup_entry(HomeAssistant hass, BMWConfigEntry config_entry, AddEntitiesCallback async_add_entities)
Definition: lock.py:29