Home Assistant Unofficial Reference 2024.12.1
button.py
Go to the documentation of this file.
1 """Support for MyBMW button entities."""
2 
3 from __future__ import annotations
4 
5 from collections.abc import Callable, Coroutine
6 from dataclasses import dataclass
7 import logging
8 from typing import TYPE_CHECKING, Any
9 
10 from bimmer_connected.models import MyBMWAPIError
11 from bimmer_connected.vehicle import MyBMWVehicle
12 from bimmer_connected.vehicle.remote_services import RemoteServiceStatus
13 
14 from homeassistant.components.button import ButtonEntity, ButtonEntityDescription
15 from homeassistant.core import HomeAssistant
16 from homeassistant.exceptions import HomeAssistantError
17 from homeassistant.helpers.entity_platform import AddEntitiesCallback
18 
19 from . import BMWConfigEntry
20 from .entity import BMWBaseEntity
21 
22 if TYPE_CHECKING:
23  from .coordinator import BMWDataUpdateCoordinator
24 
25 _LOGGER = logging.getLogger(__name__)
26 
27 
28 @dataclass(frozen=True, kw_only=True)
30  """Class describing BMW button entities."""
31 
32  remote_function: Callable[[MyBMWVehicle], Coroutine[Any, Any, RemoteServiceStatus]]
33  enabled_when_read_only: bool = False
34  is_available: Callable[[MyBMWVehicle], bool] = lambda _: True
35 
36 
37 BUTTON_TYPES: tuple[BMWButtonEntityDescription, ...] = (
39  key="light_flash",
40  translation_key="light_flash",
41  remote_function=lambda vehicle: vehicle.remote_services.trigger_remote_light_flash(),
42  ),
44  key="sound_horn",
45  translation_key="sound_horn",
46  remote_function=lambda vehicle: vehicle.remote_services.trigger_remote_horn(),
47  ),
49  key="activate_air_conditioning",
50  translation_key="activate_air_conditioning",
51  remote_function=lambda vehicle: vehicle.remote_services.trigger_remote_air_conditioning(),
52  ),
54  key="deactivate_air_conditioning",
55  translation_key="deactivate_air_conditioning",
56  name="Deactivate air conditioning",
57  remote_function=lambda vehicle: vehicle.remote_services.trigger_remote_air_conditioning_stop(),
58  is_available=lambda vehicle: vehicle.is_remote_climate_stop_enabled,
59  ),
61  key="find_vehicle",
62  translation_key="find_vehicle",
63  remote_function=lambda vehicle: vehicle.remote_services.trigger_remote_vehicle_finder(),
64  ),
65 )
66 
67 
69  hass: HomeAssistant,
70  config_entry: BMWConfigEntry,
71  async_add_entities: AddEntitiesCallback,
72 ) -> None:
73  """Set up the BMW buttons from config entry."""
74  coordinator = config_entry.runtime_data.coordinator
75 
76  entities: list[BMWButton] = []
77 
78  for vehicle in coordinator.account.vehicles:
79  entities.extend(
80  [
81  BMWButton(coordinator, vehicle, description)
82  for description in BUTTON_TYPES
83  if (not coordinator.read_only and description.is_available(vehicle))
84  or (coordinator.read_only and description.enabled_when_read_only)
85  ]
86  )
87 
88  async_add_entities(entities)
89 
90 
92  """Representation of a MyBMW button."""
93 
94  entity_description: BMWButtonEntityDescription
95 
96  def __init__(
97  self,
98  coordinator: BMWDataUpdateCoordinator,
99  vehicle: MyBMWVehicle,
100  description: BMWButtonEntityDescription,
101  ) -> None:
102  """Initialize BMW vehicle sensor."""
103  super().__init__(coordinator, vehicle)
104  self.entity_descriptionentity_description = description
105  self._attr_unique_id_attr_unique_id = f"{vehicle.vin}-{description.key}"
106 
107  async def async_press(self) -> None:
108  """Press the button."""
109  try:
110  await self.entity_descriptionentity_description.remote_function(self.vehiclevehicle)
111  except MyBMWAPIError as ex:
112  raise HomeAssistantError(ex) from ex
113 
114  self.coordinator.async_update_listeners()
None __init__(self, BMWDataUpdateCoordinator coordinator, MyBMWVehicle vehicle, BMWButtonEntityDescription description)
Definition: button.py:101
None async_setup_entry(HomeAssistant hass, BMWConfigEntry config_entry, AddEntitiesCallback async_add_entities)
Definition: button.py:72