Home Assistant Unofficial Reference 2024.12.1
select.py
Go to the documentation of this file.
1 """Select platform for Teslemetry integration."""
2 
3 from __future__ import annotations
4 
5 from collections.abc import Callable
6 from dataclasses import dataclass
7 from itertools import chain
8 
9 from tesla_fleet_api.const import EnergyExportMode, EnergyOperationMode, Scope, Seat
10 
11 from homeassistant.components.select import SelectEntity, SelectEntityDescription
12 from homeassistant.core import HomeAssistant
13 from homeassistant.helpers.entity_platform import AddEntitiesCallback
14 
15 from . import TeslemetryConfigEntry
16 from .entity import TeslemetryEnergyInfoEntity, TeslemetryVehicleEntity
17 from .helpers import handle_command, handle_vehicle_command
18 from .models import TeslemetryEnergyData, TeslemetryVehicleData
19 
20 OFF = "off"
21 LOW = "low"
22 MEDIUM = "medium"
23 HIGH = "high"
24 
25 PARALLEL_UPDATES = 0
26 
27 
28 @dataclass(frozen=True, kw_only=True)
30  """Seat Heater entity description."""
31 
32  position: Seat
33  available_fn: Callable[[TeslemetrySeatHeaterSelectEntity], bool] = lambda _: True
34 
35 
36 SEAT_HEATER_DESCRIPTIONS: tuple[SeatHeaterDescription, ...] = (
38  key="climate_state_seat_heater_left",
39  position=Seat.FRONT_LEFT,
40  ),
42  key="climate_state_seat_heater_right",
43  position=Seat.FRONT_RIGHT,
44  ),
46  key="climate_state_seat_heater_rear_left",
47  position=Seat.REAR_LEFT,
48  available_fn=lambda self: self.get("vehicle_config_rear_seat_heaters") != 0,
49  entity_registry_enabled_default=False,
50  ),
52  key="climate_state_seat_heater_rear_center",
53  position=Seat.REAR_CENTER,
54  available_fn=lambda self: self.get("vehicle_config_rear_seat_heaters") != 0,
55  entity_registry_enabled_default=False,
56  ),
58  key="climate_state_seat_heater_rear_right",
59  position=Seat.REAR_RIGHT,
60  available_fn=lambda self: self.get("vehicle_config_rear_seat_heaters") != 0,
61  entity_registry_enabled_default=False,
62  ),
64  key="climate_state_seat_heater_third_row_left",
65  position=Seat.THIRD_LEFT,
66  available_fn=lambda self: self.get("vehicle_config_third_row_seats") != "None",
67  entity_registry_enabled_default=False,
68  ),
70  key="climate_state_seat_heater_third_row_right",
71  position=Seat.THIRD_RIGHT,
72  available_fn=lambda self: self.get("vehicle_config_third_row_seats") != "None",
73  entity_registry_enabled_default=False,
74  ),
75 )
76 
77 
79  hass: HomeAssistant,
80  entry: TeslemetryConfigEntry,
81  async_add_entities: AddEntitiesCallback,
82 ) -> None:
83  """Set up the Teslemetry select platform from a config entry."""
84 
86  chain(
87  (
89  vehicle, description, entry.runtime_data.scopes
90  )
91  for description in SEAT_HEATER_DESCRIPTIONS
92  for vehicle in entry.runtime_data.vehicles
93  ),
94  (
95  TeslemetryWheelHeaterSelectEntity(vehicle, entry.runtime_data.scopes)
96  for vehicle in entry.runtime_data.vehicles
97  ),
98  (
99  TeslemetryOperationSelectEntity(energysite, entry.runtime_data.scopes)
100  for energysite in entry.runtime_data.energysites
101  if energysite.info_coordinator.data.get("components_battery")
102  ),
103  (
104  TeslemetryExportRuleSelectEntity(energysite, entry.runtime_data.scopes)
105  for energysite in entry.runtime_data.energysites
106  if energysite.info_coordinator.data.get("components_battery")
107  and energysite.info_coordinator.data.get("components_solar")
108  ),
109  )
110  )
111 
112 
114  """Select entity for vehicle seat heater."""
115 
116  entity_description: SeatHeaterDescription
117 
118  _attr_options = [
119  OFF,
120  LOW,
121  MEDIUM,
122  HIGH,
123  ]
124 
125  def __init__(
126  self,
127  data: TeslemetryVehicleData,
128  description: SeatHeaterDescription,
129  scopes: list[Scope],
130  ) -> None:
131  """Initialize the vehicle seat select entity."""
132  self.entity_descriptionentity_description = description
133  self.scopedscoped = Scope.VEHICLE_CMDS in scopes
134  super().__init__(data, description.key)
135 
136  def _async_update_attrs(self) -> None:
137  """Handle updated data from the coordinator."""
138  self._attr_available_attr_available = self.entity_descriptionentity_description.available_fn(self)
139  value = self._value_value_value
140  if value is None:
141  self._attr_current_option_attr_current_option = None
142  else:
143  self._attr_current_option_attr_current_option = self._attr_options_attr_options[value]
144 
145  async def async_select_option(self, option: str) -> None:
146  """Change the selected option."""
147  self.raise_for_scoperaise_for_scope(Scope.VEHICLE_CMDS)
148  await self.wake_up_if_asleepwake_up_if_asleep()
149  level = self._attr_options_attr_options.index(option)
150  # AC must be on to turn on seat heater
151  if level and not self.getget("climate_state_is_climate_on"):
152  await handle_vehicle_command(self.apiapiapiapiapiapi.auto_conditioning_start())
154  self.apiapiapiapiapiapi.remote_seat_heater_request(self.entity_descriptionentity_description.position, level)
155  )
156  self._attr_current_option_attr_current_option = option
157  self.async_write_ha_stateasync_write_ha_state()
158 
159 
161  """Select entity for vehicle steering wheel heater."""
162 
163  _attr_options = [
164  OFF,
165  LOW,
166  HIGH,
167  ]
168 
169  def __init__(
170  self,
171  data: TeslemetryVehicleData,
172  scopes: list[Scope],
173  ) -> None:
174  """Initialize the vehicle steering wheel select entity."""
175  self.scopedscoped = Scope.VEHICLE_CMDS in scopes
176  super().__init__(
177  data,
178  "climate_state_steering_wheel_heat_level",
179  )
180 
181  def _async_update_attrs(self) -> None:
182  """Handle updated data from the coordinator."""
183 
184  value = self._value_value_value
185  if value is None:
186  self._attr_current_option_attr_current_option = None
187  else:
188  self._attr_current_option_attr_current_option = self._attr_options_attr_options[value]
189 
190  async def async_select_option(self, option: str) -> None:
191  """Change the selected option."""
192  self.raise_for_scoperaise_for_scope(Scope.VEHICLE_CMDS)
193  await self.wake_up_if_asleepwake_up_if_asleep()
194  level = self._attr_options_attr_options.index(option)
195  # AC must be on to turn on steering wheel heater
196  if level and not self.getget("climate_state_is_climate_on"):
197  await handle_vehicle_command(self.apiapiapiapiapiapi.auto_conditioning_start())
199  self.apiapiapiapiapiapi.remote_steering_wheel_heat_level_request(level)
200  )
201  self._attr_current_option_attr_current_option = option
202  self.async_write_ha_stateasync_write_ha_state()
203 
204 
206  """Select entity for operation mode select entities."""
207 
208  _attr_options: list[str] = [
209  EnergyOperationMode.AUTONOMOUS,
210  EnergyOperationMode.BACKUP,
211  EnergyOperationMode.SELF_CONSUMPTION,
212  ]
213 
214  def __init__(
215  self,
216  data: TeslemetryEnergyData,
217  scopes: list[Scope],
218  ) -> None:
219  """Initialize the operation mode select entity."""
220  self.scopedscoped = Scope.ENERGY_CMDS in scopes
221  super().__init__(data, "default_real_mode")
222 
223  def _async_update_attrs(self) -> None:
224  """Update the attributes of the entity."""
225  self._attr_current_option_attr_current_option = self._value_value
226 
227  async def async_select_option(self, option: str) -> None:
228  """Change the selected option."""
229  self.raise_for_scoperaise_for_scope(Scope.ENERGY_CMDS)
230  await handle_command(self.apiapiapiapiapiapi.operation(option))
231  self._attr_current_option_attr_current_option = option
232  self.async_write_ha_stateasync_write_ha_state()
233 
234 
236  """Select entity for export rules select entities."""
237 
238  _attr_options: list[str] = [
239  EnergyExportMode.NEVER,
240  EnergyExportMode.BATTERY_OK,
241  EnergyExportMode.PV_ONLY,
242  ]
243 
244  def __init__(
245  self,
246  data: TeslemetryEnergyData,
247  scopes: list[Scope],
248  ) -> None:
249  """Initialize the export rules select entity."""
250  self.scopedscoped = Scope.ENERGY_CMDS in scopes
251  super().__init__(data, "components_customer_preferred_export_rule")
252 
253  def _async_update_attrs(self) -> None:
254  """Update the attributes of the entity."""
255  self._attr_current_option_attr_current_option = self.getget(self.keykey, EnergyExportMode.NEVER.value)
256 
257  async def async_select_option(self, option: str) -> None:
258  """Change the selected option."""
259  self.raise_for_scoperaise_for_scope(Scope.ENERGY_CMDS)
260  await handle_command(
261  self.apiapiapiapiapiapi.grid_import_export(customer_preferred_export_rule=option)
262  )
263  self._attr_current_option_attr_current_option = option
264  self.async_write_ha_stateasync_write_ha_state()
Any|None get(self, str key, Any|None default=None)
Definition: entity.py:61
None __init__(self, TeslemetryEnergyData data, list[Scope] scopes)
Definition: select.py:248
None __init__(self, TeslemetryEnergyData data, list[Scope] scopes)
Definition: select.py:218
None __init__(self, TeslemetryVehicleData data, SeatHeaterDescription description, list[Scope] scopes)
Definition: select.py:130
None __init__(self, TeslemetryVehicleData data, list[Scope] scopes)
Definition: select.py:173
bool handle_vehicle_command(Awaitable command)
Definition: helpers.py:50
dict[str, Any] handle_command(Awaitable command)
Definition: helpers.py:36
None async_setup_entry(HomeAssistant hass, TeslemetryConfigEntry entry, AddEntitiesCallback async_add_entities)
Definition: select.py:82