Home Assistant Unofficial Reference 2024.12.1
number.py
Go to the documentation of this file.
1 """Number platform for BMW."""
2 
3 from collections.abc import Callable, Coroutine
4 from dataclasses import dataclass
5 import logging
6 from typing import Any
7 
8 from bimmer_connected.models import MyBMWAPIError
9 from bimmer_connected.vehicle import MyBMWVehicle
10 
12  NumberDeviceClass,
13  NumberEntity,
14  NumberEntityDescription,
15  NumberMode,
16 )
17 from homeassistant.core import HomeAssistant
18 from homeassistant.exceptions import HomeAssistantError
19 from homeassistant.helpers.entity_platform import AddEntitiesCallback
20 
21 from . import BMWConfigEntry
22 from .coordinator import BMWDataUpdateCoordinator
23 from .entity import BMWBaseEntity
24 
25 _LOGGER = logging.getLogger(__name__)
26 
27 
28 @dataclass(frozen=True, kw_only=True)
30  """Describes BMW number entity."""
31 
32  value_fn: Callable[[MyBMWVehicle], float | int | None]
33  remote_service: Callable[[MyBMWVehicle, float | int], Coroutine[Any, Any, Any]]
34  is_available: Callable[[MyBMWVehicle], bool] = lambda _: False
35  dynamic_options: Callable[[MyBMWVehicle], list[str]] | None = None
36 
37 
38 NUMBER_TYPES: list[BMWNumberEntityDescription] = [
40  key="target_soc",
41  translation_key="target_soc",
42  device_class=NumberDeviceClass.BATTERY,
43  is_available=lambda v: v.is_remote_set_target_soc_enabled,
44  native_max_value=100.0,
45  native_min_value=20.0,
46  native_step=5.0,
47  mode=NumberMode.SLIDER,
48  value_fn=lambda v: v.fuel_and_battery.charging_target,
49  remote_service=lambda v, o: v.remote_services.trigger_charging_settings_update(
50  target_soc=int(o)
51  ),
52  ),
53 ]
54 
55 
57  hass: HomeAssistant,
58  config_entry: BMWConfigEntry,
59  async_add_entities: AddEntitiesCallback,
60 ) -> None:
61  """Set up the MyBMW number from config entry."""
62  coordinator = config_entry.runtime_data.coordinator
63 
64  entities: list[BMWNumber] = []
65 
66  for vehicle in coordinator.account.vehicles:
67  if not coordinator.read_only:
68  entities.extend(
69  [
70  BMWNumber(coordinator, vehicle, description)
71  for description in NUMBER_TYPES
72  if description.is_available(vehicle)
73  ]
74  )
75  async_add_entities(entities)
76 
77 
79  """Representation of BMW Number entity."""
80 
81  entity_description: BMWNumberEntityDescription
82 
83  def __init__(
84  self,
85  coordinator: BMWDataUpdateCoordinator,
86  vehicle: MyBMWVehicle,
87  description: BMWNumberEntityDescription,
88  ) -> None:
89  """Initialize an BMW Number."""
90  super().__init__(coordinator, vehicle)
91  self.entity_descriptionentity_description = description
92  self._attr_unique_id_attr_unique_id = f"{vehicle.vin}-{description.key}"
93 
94  @property
95  def native_value(self) -> float | None:
96  """Return the entity value to represent the entity state."""
97  return self.entity_descriptionentity_description.value_fn(self.vehiclevehicle)
98 
99  async def async_set_native_value(self, value: float) -> None:
100  """Update to the vehicle."""
101  _LOGGER.debug(
102  "Executing '%s' on vehicle '%s' to value '%s'",
103  self.entity_descriptionentity_description.key,
104  self.vehiclevehicle.vin,
105  value,
106  )
107  try:
108  await self.entity_descriptionentity_description.remote_service(self.vehiclevehicle, value)
109  except MyBMWAPIError as ex:
110  raise HomeAssistantError(ex) from ex
111 
112  self.coordinator.async_update_listeners()
None __init__(self, BMWDataUpdateCoordinator coordinator, MyBMWVehicle vehicle, BMWNumberEntityDescription description)
Definition: number.py:88
None async_setup_entry(HomeAssistant hass, BMWConfigEntry config_entry, AddEntitiesCallback async_add_entities)
Definition: number.py:60