1 """Sensor platform for Tessie integration."""
3 from __future__
import annotations
5 from collections.abc
import Callable
6 from dataclasses
import dataclass
7 from datetime
import datetime, timedelta
8 from itertools
import chain
9 from typing
import cast
14 SensorEntityDescription,
20 UnitOfElectricCurrent,
21 UnitOfElectricPotential,
36 from .
import TessieConfigEntry
37 from .const
import TessieChargeStates, TessieWallConnectorStates
38 from .entity
import TessieEnergyEntity, TessieEntity, TessieWallConnectorEntity
39 from .models
import TessieEnergyData, TessieVehicleData
44 """Convert relative minutes into absolute datetime."""
45 if isinstance(value, (int, float))
and value > 0:
46 return dt_util.now() +
timedelta(minutes=value)
50 @dataclass(frozen=True, kw_only=True)
52 """Describes Tessie Sensor entity."""
54 value_fn: Callable[[StateType], StateType | datetime] =
lambda x: x
55 available_fn: Callable[[StateType], bool] =
lambda _:
True
58 DESCRIPTIONS: tuple[TessieSensorEntityDescription, ...] = (
60 key=
"charge_state_charging_state",
61 options=
list(TessieChargeStates.values()),
62 device_class=SensorDeviceClass.ENUM,
63 value_fn=
lambda value: TessieChargeStates[cast(str, value)],
66 key=
"charge_state_usable_battery_level",
67 state_class=SensorStateClass.MEASUREMENT,
68 native_unit_of_measurement=PERCENTAGE,
69 device_class=SensorDeviceClass.BATTERY,
72 key=
"charge_state_charge_energy_added",
73 state_class=SensorStateClass.TOTAL_INCREASING,
74 native_unit_of_measurement=UnitOfEnergy.KILO_WATT_HOUR,
75 device_class=SensorDeviceClass.ENERGY,
76 suggested_display_precision=1,
79 key=
"charge_state_charger_power",
80 state_class=SensorStateClass.MEASUREMENT,
81 native_unit_of_measurement=UnitOfPower.KILO_WATT,
82 device_class=SensorDeviceClass.POWER,
85 key=
"charge_state_charger_voltage",
86 state_class=SensorStateClass.MEASUREMENT,
87 native_unit_of_measurement=UnitOfElectricPotential.VOLT,
88 device_class=SensorDeviceClass.VOLTAGE,
89 entity_category=EntityCategory.DIAGNOSTIC,
92 key=
"charge_state_charger_actual_current",
93 state_class=SensorStateClass.MEASUREMENT,
94 native_unit_of_measurement=UnitOfElectricCurrent.AMPERE,
95 device_class=SensorDeviceClass.CURRENT,
96 entity_category=EntityCategory.DIAGNOSTIC,
99 key=
"charge_state_charge_rate",
100 state_class=SensorStateClass.MEASUREMENT,
101 native_unit_of_measurement=UnitOfSpeed.MILES_PER_HOUR,
102 device_class=SensorDeviceClass.SPEED,
103 entity_category=EntityCategory.DIAGNOSTIC,
106 key=
"charge_state_minutes_to_full_charge",
107 device_class=SensorDeviceClass.TIMESTAMP,
108 entity_category=EntityCategory.DIAGNOSTIC,
109 value_fn=minutes_to_datetime,
112 key=
"charge_state_battery_range",
113 state_class=SensorStateClass.MEASUREMENT,
114 native_unit_of_measurement=UnitOfLength.MILES,
115 device_class=SensorDeviceClass.DISTANCE,
116 suggested_display_precision=1,
119 key=
"charge_state_est_battery_range",
120 state_class=SensorStateClass.MEASUREMENT,
121 native_unit_of_measurement=UnitOfLength.MILES,
122 device_class=SensorDeviceClass.DISTANCE,
123 suggested_display_precision=1,
124 entity_registry_enabled_default=
False,
127 key=
"charge_state_ideal_battery_range",
128 state_class=SensorStateClass.MEASUREMENT,
129 native_unit_of_measurement=UnitOfLength.MILES,
130 device_class=SensorDeviceClass.DISTANCE,
131 suggested_display_precision=1,
132 entity_registry_enabled_default=
False,
135 key=
"drive_state_speed",
136 state_class=SensorStateClass.MEASUREMENT,
137 native_unit_of_measurement=UnitOfSpeed.MILES_PER_HOUR,
138 device_class=SensorDeviceClass.SPEED,
141 key=
"drive_state_power",
142 state_class=SensorStateClass.MEASUREMENT,
143 native_unit_of_measurement=UnitOfPower.KILO_WATT,
144 device_class=SensorDeviceClass.POWER,
145 entity_category=EntityCategory.DIAGNOSTIC,
148 key=
"drive_state_shift_state",
149 options=[
"p",
"d",
"r",
"n"],
150 device_class=SensorDeviceClass.ENUM,
151 value_fn=
lambda x: x.lower()
if isinstance(x, str)
else x,
154 key=
"vehicle_state_odometer",
155 state_class=SensorStateClass.TOTAL_INCREASING,
156 native_unit_of_measurement=UnitOfLength.MILES,
157 device_class=SensorDeviceClass.DISTANCE,
158 suggested_display_precision=0,
159 entity_category=EntityCategory.DIAGNOSTIC,
162 key=
"vehicle_state_tpms_pressure_fl",
163 state_class=SensorStateClass.MEASUREMENT,
164 native_unit_of_measurement=UnitOfPressure.BAR,
165 suggested_unit_of_measurement=UnitOfPressure.PSI,
166 device_class=SensorDeviceClass.PRESSURE,
167 suggested_display_precision=1,
168 entity_category=EntityCategory.DIAGNOSTIC,
171 key=
"vehicle_state_tpms_pressure_fr",
172 state_class=SensorStateClass.MEASUREMENT,
173 native_unit_of_measurement=UnitOfPressure.BAR,
174 suggested_unit_of_measurement=UnitOfPressure.PSI,
175 device_class=SensorDeviceClass.PRESSURE,
176 suggested_display_precision=1,
177 entity_category=EntityCategory.DIAGNOSTIC,
180 key=
"vehicle_state_tpms_pressure_rl",
181 state_class=SensorStateClass.MEASUREMENT,
182 native_unit_of_measurement=UnitOfPressure.BAR,
183 suggested_unit_of_measurement=UnitOfPressure.PSI,
184 device_class=SensorDeviceClass.PRESSURE,
185 suggested_display_precision=1,
186 entity_category=EntityCategory.DIAGNOSTIC,
189 key=
"vehicle_state_tpms_pressure_rr",
190 state_class=SensorStateClass.MEASUREMENT,
191 native_unit_of_measurement=UnitOfPressure.BAR,
192 suggested_unit_of_measurement=UnitOfPressure.PSI,
193 device_class=SensorDeviceClass.PRESSURE,
194 suggested_display_precision=1,
195 entity_category=EntityCategory.DIAGNOSTIC,
198 key=
"climate_state_inside_temp",
199 state_class=SensorStateClass.MEASUREMENT,
200 native_unit_of_measurement=UnitOfTemperature.CELSIUS,
201 device_class=SensorDeviceClass.TEMPERATURE,
202 suggested_display_precision=1,
205 key=
"climate_state_outside_temp",
206 state_class=SensorStateClass.MEASUREMENT,
207 native_unit_of_measurement=UnitOfTemperature.CELSIUS,
208 device_class=SensorDeviceClass.TEMPERATURE,
209 suggested_display_precision=1,
212 key=
"climate_state_driver_temp_setting",
213 state_class=SensorStateClass.MEASUREMENT,
214 native_unit_of_measurement=UnitOfTemperature.CELSIUS,
215 device_class=SensorDeviceClass.TEMPERATURE,
216 suggested_display_precision=1,
217 entity_category=EntityCategory.DIAGNOSTIC,
220 key=
"climate_state_passenger_temp_setting",
221 state_class=SensorStateClass.MEASUREMENT,
222 native_unit_of_measurement=UnitOfTemperature.CELSIUS,
223 device_class=SensorDeviceClass.TEMPERATURE,
224 suggested_display_precision=1,
225 entity_category=EntityCategory.DIAGNOSTIC,
228 key=
"drive_state_active_route_traffic_minutes_delay",
229 state_class=SensorStateClass.MEASUREMENT,
230 native_unit_of_measurement=UnitOfTime.MINUTES,
231 device_class=SensorDeviceClass.DURATION,
234 key=
"drive_state_active_route_energy_at_arrival",
235 state_class=SensorStateClass.MEASUREMENT,
236 native_unit_of_measurement=PERCENTAGE,
237 device_class=SensorDeviceClass.BATTERY,
238 entity_category=EntityCategory.DIAGNOSTIC,
241 key=
"drive_state_active_route_miles_to_arrival",
242 state_class=SensorStateClass.MEASUREMENT,
243 native_unit_of_measurement=UnitOfLength.MILES,
244 device_class=SensorDeviceClass.DISTANCE,
247 key=
"drive_state_active_route_minutes_to_arrival",
248 device_class=SensorDeviceClass.TIMESTAMP,
249 value_fn=ignore_variance(
250 lambda value: dt_util.now() +
timedelta(minutes=cast(float, value)),
253 available_fn=
lambda x: x
is not None,
256 key=
"drive_state_active_route_destination",
257 entity_category=EntityCategory.DIAGNOSTIC,
261 ENERGY_LIVE_DESCRIPTIONS: tuple[TessieSensorEntityDescription, ...] = (
264 state_class=SensorStateClass.MEASUREMENT,
265 native_unit_of_measurement=UnitOfPower.WATT,
266 suggested_unit_of_measurement=UnitOfPower.KILO_WATT,
267 suggested_display_precision=2,
268 device_class=SensorDeviceClass.POWER,
272 state_class=SensorStateClass.MEASUREMENT,
273 native_unit_of_measurement=UnitOfEnergy.WATT_HOUR,
274 suggested_unit_of_measurement=UnitOfEnergy.KILO_WATT_HOUR,
275 suggested_display_precision=2,
276 device_class=SensorDeviceClass.ENERGY_STORAGE,
277 entity_category=EntityCategory.DIAGNOSTIC,
280 key=
"total_pack_energy",
281 state_class=SensorStateClass.MEASUREMENT,
282 native_unit_of_measurement=UnitOfEnergy.WATT_HOUR,
283 suggested_unit_of_measurement=UnitOfEnergy.KILO_WATT_HOUR,
284 suggested_display_precision=2,
285 device_class=SensorDeviceClass.ENERGY_STORAGE,
286 entity_category=EntityCategory.DIAGNOSTIC,
287 entity_registry_enabled_default=
False,
290 key=
"percentage_charged",
291 state_class=SensorStateClass.MEASUREMENT,
292 native_unit_of_measurement=PERCENTAGE,
293 device_class=SensorDeviceClass.BATTERY,
294 suggested_display_precision=2,
298 state_class=SensorStateClass.MEASUREMENT,
299 native_unit_of_measurement=UnitOfPower.WATT,
300 suggested_unit_of_measurement=UnitOfPower.KILO_WATT,
301 suggested_display_precision=2,
302 device_class=SensorDeviceClass.POWER,
306 state_class=SensorStateClass.MEASUREMENT,
307 native_unit_of_measurement=UnitOfPower.WATT,
308 suggested_unit_of_measurement=UnitOfPower.KILO_WATT,
309 suggested_display_precision=2,
310 device_class=SensorDeviceClass.POWER,
314 state_class=SensorStateClass.MEASUREMENT,
315 native_unit_of_measurement=UnitOfPower.WATT,
316 suggested_unit_of_measurement=UnitOfPower.KILO_WATT,
317 suggested_display_precision=2,
318 device_class=SensorDeviceClass.POWER,
321 key=
"grid_services_power",
322 state_class=SensorStateClass.MEASUREMENT,
323 native_unit_of_measurement=UnitOfPower.WATT,
324 suggested_unit_of_measurement=UnitOfPower.KILO_WATT,
325 suggested_display_precision=2,
326 device_class=SensorDeviceClass.POWER,
329 key=
"generator_power",
330 state_class=SensorStateClass.MEASUREMENT,
331 native_unit_of_measurement=UnitOfPower.WATT,
332 suggested_unit_of_measurement=UnitOfPower.KILO_WATT,
333 suggested_display_precision=2,
334 device_class=SensorDeviceClass.POWER,
335 entity_registry_enabled_default=
False,
339 WALL_CONNECTOR_DESCRIPTIONS: tuple[TessieSensorEntityDescription, ...] = (
341 key=
"wall_connector_state",
342 entity_category=EntityCategory.DIAGNOSTIC,
343 entity_registry_enabled_default=
False,
344 device_class=SensorDeviceClass.ENUM,
346 options=[state.name.lower()
for state
in TessieWallConnectorStates],
349 key=
"wall_connector_power",
350 state_class=SensorStateClass.MEASUREMENT,
351 native_unit_of_measurement=UnitOfPower.WATT,
352 suggested_unit_of_measurement=UnitOfPower.KILO_WATT,
353 suggested_display_precision=2,
354 device_class=SensorDeviceClass.POWER,
361 ENERGY_INFO_DESCRIPTIONS: tuple[TessieSensorEntityDescription, ...] = (
363 key=
"vpp_backup_reserve_percent",
364 entity_category=EntityCategory.DIAGNOSTIC,
365 device_class=SensorDeviceClass.BATTERY,
366 native_unit_of_measurement=PERCENTAGE,
375 entry: TessieConfigEntry,
376 async_add_entities: AddEntitiesCallback,
378 """Set up the Tessie sensor platform from a config entry."""
384 for vehicle
in entry.runtime_data.vehicles
385 for description
in DESCRIPTIONS
389 for energysite
in entry.runtime_data.energysites
390 for description
in ENERGY_INFO_DESCRIPTIONS
391 if description.key
in energysite.info_coordinator.data
395 for energysite
in entry.runtime_data.energysites
396 for description
in ENERGY_LIVE_DESCRIPTIONS
397 if description.key
in energysite.live_coordinator.data
401 for energysite
in entry.runtime_data.energysites
402 for din
in energysite.live_coordinator.data.get(
"wall_connectors", {})
403 for description
in WALL_CONNECTOR_DESCRIPTIONS
410 """Base class for Tessie sensor entities."""
412 entity_description: TessieSensorEntityDescription
416 vehicle: TessieVehicleData,
417 description: TessieSensorEntityDescription,
419 """Initialize the sensor."""
421 super().
__init__(vehicle, description.key)
425 """Return the state of the sensor."""
430 """Return if sensor is available."""
435 """Base class for Tessie energy site sensor entity."""
437 entity_description: TessieSensorEntityDescription
441 data: TessieEnergyData,
442 description: TessieSensorEntityDescription,
444 """Initialize the sensor."""
446 super().
__init__(data, data.live_coordinator, description.key)
449 """Update the attributes of the sensor."""
455 """Base class for Tessie energy site sensor entity."""
457 entity_description: TessieSensorEntityDescription
461 data: TessieEnergyData,
462 description: TessieSensorEntityDescription,
464 """Initialize the sensor."""
466 super().
__init__(data, data.info_coordinator, description.key)
469 """Update the attributes of the sensor."""
475 """Base class for Tessie wall connector sensor entity."""
477 entity_description: TessieSensorEntityDescription
481 data: TessieEnergyData,
483 description: TessieSensorEntityDescription,
485 """Initialize the sensor."""
494 """Update the attributes of the sensor."""
Any get(self, str|None key=None, Any|None default=None)
None _async_update_attrs(self)
None __init__(self, TessieEnergyData data, TessieSensorEntityDescription description)
None __init__(self, TessieEnergyData data, TessieSensorEntityDescription description)
None _async_update_attrs(self)
None __init__(self, TessieVehicleData vehicle, TessieSensorEntityDescription description)
StateType|datetime native_value(self)
None __init__(self, TessieEnergyData data, str din, TessieSensorEntityDescription description)
None _async_update_attrs(self)
None async_setup_entry(HomeAssistant hass, TessieConfigEntry entry, AddEntitiesCallback async_add_entities)
datetime|None minutes_to_datetime(StateType value)