Home Assistant Unofficial Reference 2024.12.1
switch.py
Go to the documentation of this file.
1 """Switch platform for Tessie 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 from typing import Any
9 
10 from tessie_api import (
11  disable_sentry_mode,
12  disable_valet_mode,
13  enable_sentry_mode,
14  enable_valet_mode,
15  start_charging,
16  start_defrost,
17  start_steering_wheel_heater,
18  stop_charging,
19  stop_defrost,
20  stop_steering_wheel_heater,
21 )
22 
24  SwitchDeviceClass,
25  SwitchEntity,
26  SwitchEntityDescription,
27 )
28 from homeassistant.core import HomeAssistant
29 from homeassistant.helpers.entity_platform import AddEntitiesCallback
30 
31 from . import TessieConfigEntry
32 from .entity import TessieEnergyEntity, TessieEntity
33 from .helpers import handle_command
34 from .models import TessieEnergyData, TessieVehicleData
35 
36 
37 @dataclass(frozen=True, kw_only=True)
39  """Describes Tessie Switch entity."""
40 
41  on_func: Callable
42  off_func: Callable
43 
44 
45 DESCRIPTIONS: tuple[TessieSwitchEntityDescription, ...] = (
47  key="climate_state_defrost_mode",
48  on_func=lambda: start_defrost,
49  off_func=lambda: stop_defrost,
50  ),
52  key="vehicle_state_sentry_mode",
53  on_func=lambda: enable_sentry_mode,
54  off_func=lambda: disable_sentry_mode,
55  ),
57  key="vehicle_state_valet_mode",
58  on_func=lambda: enable_valet_mode,
59  off_func=lambda: disable_valet_mode,
60  ),
62  key="climate_state_steering_wheel_heater",
63  on_func=lambda: start_steering_wheel_heater,
64  off_func=lambda: stop_steering_wheel_heater,
65  ),
66 )
67 
68 CHARGE_DESCRIPTION: TessieSwitchEntityDescription = TessieSwitchEntityDescription(
69  key="charge_state_charge_enable_request",
70  on_func=lambda: start_charging,
71  off_func=lambda: stop_charging,
72 )
73 
74 PARALLEL_UPDATES = 0
75 
76 
78  hass: HomeAssistant,
79  entry: TessieConfigEntry,
80  async_add_entities: AddEntitiesCallback,
81 ) -> None:
82  """Set up the Tessie Switch platform from a config entry."""
83 
85  chain(
86  (
87  TessieSwitchEntity(vehicle, description)
88  for vehicle in entry.runtime_data.vehicles
89  for description in DESCRIPTIONS
90  if description.key in vehicle.data_coordinator.data
91  ),
92  (
93  TessieChargeSwitchEntity(vehicle, CHARGE_DESCRIPTION)
94  for vehicle in entry.runtime_data.vehicles
95  ),
96  (
98  for energysite in entry.runtime_data.energysites
99  if energysite.info_coordinator.data.get("components_battery")
100  and energysite.info_coordinator.data.get("components_solar")
101  ),
102  (
103  TessieStormModeSwitchEntity(energysite)
104  for energysite in entry.runtime_data.energysites
105  if energysite.info_coordinator.data.get("components_storm_mode_capable")
106  ),
107  )
108  )
109 
110 
112  """Base class for Tessie Switch."""
113 
114  _attr_device_class = SwitchDeviceClass.SWITCH
115  entity_description: TessieSwitchEntityDescription
116 
117  def __init__(
118  self,
119  vehicle: TessieVehicleData,
120  description: TessieSwitchEntityDescription,
121  ) -> None:
122  """Initialize the Switch."""
123  super().__init__(vehicle, description.key)
124  self.entity_descriptionentity_description = description
125 
126  @property
127  def is_on(self) -> bool:
128  """Return the state of the Switch."""
129  return self._value_value_value
130 
131  async def async_turn_on(self, **kwargs: Any) -> None:
132  """Turn on the Switch."""
133  await self.runrun(self.entity_descriptionentity_description.on_func())
134  self.setset((self.entity_descriptionentity_description.key, True))
135 
136  async def async_turn_off(self, **kwargs: Any) -> None:
137  """Turn off the Switch."""
138  await self.runrun(self.entity_descriptionentity_description.off_func())
139  self.setset((self.entity_descriptionentity_description.key, False))
140 
141 
143  """Entity class for Tessie charge switch."""
144 
145  @property
146  def is_on(self) -> bool:
147  """Return the state of the Switch."""
148 
149  if (charge := self.getget("charge_state_user_charge_enable_request")) is not None:
150  return charge
151  return self._value_value_value
152 
153 
155  """Entity class for Charge From Grid switch."""
156 
157  def __init__(
158  self,
159  data: TessieEnergyData,
160  ) -> None:
161  """Initialize the switch."""
162  super().__init__(
163  data,
164  data.info_coordinator,
165  "components_disallow_charge_from_grid_with_solar_installed",
166  )
167 
168  def _async_update_attrs(self) -> None:
169  """Update the attributes of the entity."""
170  # When disallow_charge_from_grid_with_solar_installed is missing, its Off.
171  # But this sensor is flipped to match how the Tesla app works.
172  self._attr_is_on_attr_is_on = not self.getget(self.keykey, False)
173 
174  async def async_turn_on(self, **kwargs: Any) -> None:
175  """Turn on the Switch."""
176  await handle_command(
177  self.apiapiapiapi.grid_import_export(
178  disallow_charge_from_grid_with_solar_installed=False
179  )
180  )
181  self._attr_is_on_attr_is_on = True
182  self.async_write_ha_stateasync_write_ha_state()
183 
184  async def async_turn_off(self, **kwargs: Any) -> None:
185  """Turn off the Switch."""
186  await handle_command(
187  self.apiapiapiapi.grid_import_export(
188  disallow_charge_from_grid_with_solar_installed=True
189  )
190  )
191  self._attr_is_on_attr_is_on = False
192  self.async_write_ha_stateasync_write_ha_state()
193 
194 
196  """Entity class for Storm Mode switch."""
197 
198  def __init__(
199  self,
200  data: TessieEnergyData,
201  ) -> None:
202  """Initialize the switch."""
203  super().__init__(
204  data, data.info_coordinator, "user_settings_storm_mode_enabled"
205  )
206 
207  def _async_update_attrs(self) -> None:
208  """Update the attributes of the sensor."""
209  self._attr_available_attr_available = self._value_value is not None
210  self._attr_is_on_attr_is_on = bool(self._value_value)
211 
212  async def async_turn_on(self, **kwargs: Any) -> None:
213  """Turn on the Switch."""
214  await handle_command(self.apiapiapiapi.storm_mode(enabled=True))
215  self._attr_is_on_attr_is_on = True
216  self.async_write_ha_stateasync_write_ha_state()
217 
218  async def async_turn_off(self, **kwargs: Any) -> None:
219  """Turn off the Switch."""
220  await handle_command(self.apiapiapiapi.storm_mode(enabled=False))
221  self._attr_is_on_attr_is_on = False
222  self.async_write_ha_stateasync_write_ha_state()
Any get(self, str|None key=None, Any|None default=None)
Definition: entity.py:52
None run(self, Callable[..., Awaitable[dict[str, Any]]] func, **Any kargs)
Definition: entity.py:96
None __init__(self, TessieVehicleData vehicle, TessieSwitchEntityDescription description)
Definition: switch.py:121
dict[str, Any] handle_command(Awaitable command)
Definition: helpers.py:36
None async_setup_entry(HomeAssistant hass, TessieConfigEntry entry, AddEntitiesCallback async_add_entities)
Definition: switch.py:81