1 """Sensor platform for Teslemetry integration."""
3 from __future__
import annotations
5 from collections.abc
import Callable
6 from dataclasses
import dataclass
7 from datetime
import timedelta
8 from itertools
import chain
9 from typing
import cast
14 SensorEntityDescription,
20 UnitOfElectricCurrent,
21 UnitOfElectricPotential,
36 from .
import TeslemetryConfigEntry
37 from .const
import ENERGY_HISTORY_FIELDS
39 TeslemetryEnergyHistoryEntity,
40 TeslemetryEnergyInfoEntity,
41 TeslemetryEnergyLiveEntity,
42 TeslemetryVehicleEntity,
43 TeslemetryWallConnectorEntity,
45 from .models
import TeslemetryEnergyData, TeslemetryVehicleData
50 "Starting":
"starting",
51 "Charging":
"charging",
53 "Complete":
"complete",
54 "Disconnected":
"disconnected",
55 "NoPower":
"no_power",
58 SHIFT_STATES = {
"P":
"p",
"D":
"d",
"R":
"r",
"N":
"n"}
61 @dataclass(frozen=True, kw_only=True)
63 """Describes Teslemetry Sensor entity."""
65 value_fn: Callable[[StateType], StateType] =
lambda x: x
68 VEHICLE_DESCRIPTIONS: tuple[TeslemetrySensorEntityDescription, ...] = (
70 key=
"charge_state_charging_state",
71 options=
list(CHARGE_STATES.values()),
72 device_class=SensorDeviceClass.ENUM,
73 value_fn=
lambda value: CHARGE_STATES.get(cast(str, value)),
76 key=
"charge_state_battery_level",
77 state_class=SensorStateClass.MEASUREMENT,
78 native_unit_of_measurement=PERCENTAGE,
79 device_class=SensorDeviceClass.BATTERY,
82 key=
"charge_state_usable_battery_level",
83 state_class=SensorStateClass.MEASUREMENT,
84 native_unit_of_measurement=PERCENTAGE,
85 device_class=SensorDeviceClass.BATTERY,
86 entity_registry_enabled_default=
False,
89 key=
"charge_state_charge_energy_added",
90 state_class=SensorStateClass.TOTAL_INCREASING,
91 native_unit_of_measurement=UnitOfEnergy.KILO_WATT_HOUR,
92 device_class=SensorDeviceClass.ENERGY,
93 suggested_display_precision=1,
96 key=
"charge_state_charger_power",
97 state_class=SensorStateClass.MEASUREMENT,
98 native_unit_of_measurement=UnitOfPower.KILO_WATT,
99 device_class=SensorDeviceClass.POWER,
102 key=
"charge_state_charger_voltage",
103 state_class=SensorStateClass.MEASUREMENT,
104 native_unit_of_measurement=UnitOfElectricPotential.VOLT,
105 device_class=SensorDeviceClass.VOLTAGE,
106 entity_category=EntityCategory.DIAGNOSTIC,
109 key=
"charge_state_charger_actual_current",
110 state_class=SensorStateClass.MEASUREMENT,
111 native_unit_of_measurement=UnitOfElectricCurrent.AMPERE,
112 device_class=SensorDeviceClass.CURRENT,
113 entity_category=EntityCategory.DIAGNOSTIC,
116 key=
"charge_state_charge_rate",
117 state_class=SensorStateClass.MEASUREMENT,
118 native_unit_of_measurement=UnitOfSpeed.MILES_PER_HOUR,
119 device_class=SensorDeviceClass.SPEED,
120 entity_category=EntityCategory.DIAGNOSTIC,
123 key=
"charge_state_conn_charge_cable",
124 entity_category=EntityCategory.DIAGNOSTIC,
125 entity_registry_enabled_default=
False,
128 key=
"charge_state_fast_charger_type",
129 entity_category=EntityCategory.DIAGNOSTIC,
130 entity_registry_enabled_default=
False,
133 key=
"charge_state_battery_range",
134 state_class=SensorStateClass.MEASUREMENT,
135 native_unit_of_measurement=UnitOfLength.MILES,
136 device_class=SensorDeviceClass.DISTANCE,
137 suggested_display_precision=1,
140 key=
"charge_state_est_battery_range",
141 state_class=SensorStateClass.MEASUREMENT,
142 native_unit_of_measurement=UnitOfLength.MILES,
143 device_class=SensorDeviceClass.DISTANCE,
144 suggested_display_precision=1,
145 entity_registry_enabled_default=
False,
148 key=
"charge_state_ideal_battery_range",
149 state_class=SensorStateClass.MEASUREMENT,
150 native_unit_of_measurement=UnitOfLength.MILES,
151 device_class=SensorDeviceClass.DISTANCE,
152 suggested_display_precision=1,
153 entity_registry_enabled_default=
False,
156 key=
"drive_state_speed",
157 state_class=SensorStateClass.MEASUREMENT,
158 native_unit_of_measurement=UnitOfSpeed.MILES_PER_HOUR,
159 device_class=SensorDeviceClass.SPEED,
160 entity_registry_enabled_default=
False,
161 value_fn=
lambda value: value
or 0,
164 key=
"drive_state_power",
165 state_class=SensorStateClass.MEASUREMENT,
166 native_unit_of_measurement=UnitOfPower.KILO_WATT,
167 device_class=SensorDeviceClass.POWER,
168 entity_category=EntityCategory.DIAGNOSTIC,
169 entity_registry_enabled_default=
False,
170 value_fn=
lambda value: value
or 0,
173 key=
"drive_state_shift_state",
174 options=
list(SHIFT_STATES.values()),
175 device_class=SensorDeviceClass.ENUM,
176 value_fn=
lambda x: SHIFT_STATES.get(
str(x),
"p"),
177 entity_registry_enabled_default=
False,
180 key=
"vehicle_state_odometer",
181 state_class=SensorStateClass.TOTAL_INCREASING,
182 native_unit_of_measurement=UnitOfLength.MILES,
183 device_class=SensorDeviceClass.DISTANCE,
184 suggested_display_precision=0,
185 entity_category=EntityCategory.DIAGNOSTIC,
186 entity_registry_enabled_default=
False,
189 key=
"vehicle_state_tpms_pressure_fl",
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,
196 entity_registry_enabled_default=
False,
199 key=
"vehicle_state_tpms_pressure_fr",
200 state_class=SensorStateClass.MEASUREMENT,
201 native_unit_of_measurement=UnitOfPressure.BAR,
202 suggested_unit_of_measurement=UnitOfPressure.PSI,
203 device_class=SensorDeviceClass.PRESSURE,
204 suggested_display_precision=1,
205 entity_category=EntityCategory.DIAGNOSTIC,
206 entity_registry_enabled_default=
False,
209 key=
"vehicle_state_tpms_pressure_rl",
210 state_class=SensorStateClass.MEASUREMENT,
211 native_unit_of_measurement=UnitOfPressure.BAR,
212 suggested_unit_of_measurement=UnitOfPressure.PSI,
213 device_class=SensorDeviceClass.PRESSURE,
214 suggested_display_precision=1,
215 entity_category=EntityCategory.DIAGNOSTIC,
216 entity_registry_enabled_default=
False,
219 key=
"vehicle_state_tpms_pressure_rr",
220 state_class=SensorStateClass.MEASUREMENT,
221 native_unit_of_measurement=UnitOfPressure.BAR,
222 suggested_unit_of_measurement=UnitOfPressure.PSI,
223 device_class=SensorDeviceClass.PRESSURE,
224 suggested_display_precision=1,
225 entity_category=EntityCategory.DIAGNOSTIC,
226 entity_registry_enabled_default=
False,
229 key=
"climate_state_inside_temp",
230 state_class=SensorStateClass.MEASUREMENT,
231 native_unit_of_measurement=UnitOfTemperature.CELSIUS,
232 device_class=SensorDeviceClass.TEMPERATURE,
233 suggested_display_precision=1,
236 key=
"climate_state_outside_temp",
237 state_class=SensorStateClass.MEASUREMENT,
238 native_unit_of_measurement=UnitOfTemperature.CELSIUS,
239 device_class=SensorDeviceClass.TEMPERATURE,
240 suggested_display_precision=1,
243 key=
"climate_state_driver_temp_setting",
244 state_class=SensorStateClass.MEASUREMENT,
245 native_unit_of_measurement=UnitOfTemperature.CELSIUS,
246 device_class=SensorDeviceClass.TEMPERATURE,
247 suggested_display_precision=1,
248 entity_category=EntityCategory.DIAGNOSTIC,
249 entity_registry_enabled_default=
False,
252 key=
"climate_state_passenger_temp_setting",
253 state_class=SensorStateClass.MEASUREMENT,
254 native_unit_of_measurement=UnitOfTemperature.CELSIUS,
255 device_class=SensorDeviceClass.TEMPERATURE,
256 suggested_display_precision=1,
257 entity_category=EntityCategory.DIAGNOSTIC,
258 entity_registry_enabled_default=
False,
261 key=
"drive_state_active_route_traffic_minutes_delay",
262 state_class=SensorStateClass.MEASUREMENT,
263 native_unit_of_measurement=UnitOfTime.MINUTES,
264 device_class=SensorDeviceClass.DURATION,
265 entity_registry_enabled_default=
False,
268 key=
"drive_state_active_route_energy_at_arrival",
269 state_class=SensorStateClass.MEASUREMENT,
270 native_unit_of_measurement=PERCENTAGE,
271 device_class=SensorDeviceClass.BATTERY,
272 entity_category=EntityCategory.DIAGNOSTIC,
273 entity_registry_enabled_default=
False,
276 key=
"drive_state_active_route_miles_to_arrival",
277 state_class=SensorStateClass.MEASUREMENT,
278 native_unit_of_measurement=UnitOfLength.MILES,
279 device_class=SensorDeviceClass.DISTANCE,
284 @dataclass(frozen=True, kw_only=True)
286 """Describes Teslemetry Sensor entity."""
291 VEHICLE_TIME_DESCRIPTIONS: tuple[TeslemetryTimeEntityDescription, ...] = (
293 key=
"charge_state_minutes_to_full_charge",
294 device_class=SensorDeviceClass.TIMESTAMP,
295 entity_category=EntityCategory.DIAGNOSTIC,
299 key=
"drive_state_active_route_minutes_to_arrival",
300 device_class=SensorDeviceClass.TIMESTAMP,
305 ENERGY_LIVE_DESCRIPTIONS: tuple[SensorEntityDescription, ...] = (
308 state_class=SensorStateClass.MEASUREMENT,
309 native_unit_of_measurement=UnitOfPower.WATT,
310 suggested_unit_of_measurement=UnitOfPower.KILO_WATT,
311 suggested_display_precision=2,
312 device_class=SensorDeviceClass.POWER,
316 state_class=SensorStateClass.MEASUREMENT,
317 native_unit_of_measurement=UnitOfEnergy.WATT_HOUR,
318 suggested_unit_of_measurement=UnitOfEnergy.KILO_WATT_HOUR,
319 suggested_display_precision=2,
320 device_class=SensorDeviceClass.ENERGY_STORAGE,
321 entity_category=EntityCategory.DIAGNOSTIC,
324 key=
"total_pack_energy",
325 state_class=SensorStateClass.MEASUREMENT,
326 native_unit_of_measurement=UnitOfEnergy.WATT_HOUR,
327 suggested_unit_of_measurement=UnitOfEnergy.KILO_WATT_HOUR,
328 suggested_display_precision=2,
329 device_class=SensorDeviceClass.ENERGY_STORAGE,
330 entity_category=EntityCategory.DIAGNOSTIC,
331 entity_registry_enabled_default=
False,
334 key=
"percentage_charged",
335 state_class=SensorStateClass.MEASUREMENT,
336 native_unit_of_measurement=PERCENTAGE,
337 device_class=SensorDeviceClass.BATTERY,
338 suggested_display_precision=2,
342 state_class=SensorStateClass.MEASUREMENT,
343 native_unit_of_measurement=UnitOfPower.WATT,
344 suggested_unit_of_measurement=UnitOfPower.KILO_WATT,
345 suggested_display_precision=2,
346 device_class=SensorDeviceClass.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,
358 state_class=SensorStateClass.MEASUREMENT,
359 native_unit_of_measurement=UnitOfPower.WATT,
360 suggested_unit_of_measurement=UnitOfPower.KILO_WATT,
361 suggested_display_precision=2,
362 device_class=SensorDeviceClass.POWER,
365 key=
"grid_services_power",
366 state_class=SensorStateClass.MEASUREMENT,
367 native_unit_of_measurement=UnitOfPower.WATT,
368 suggested_unit_of_measurement=UnitOfPower.KILO_WATT,
369 suggested_display_precision=2,
370 device_class=SensorDeviceClass.POWER,
373 key=
"generator_power",
374 state_class=SensorStateClass.MEASUREMENT,
375 native_unit_of_measurement=UnitOfPower.WATT,
376 suggested_unit_of_measurement=UnitOfPower.KILO_WATT,
377 suggested_display_precision=2,
378 device_class=SensorDeviceClass.POWER,
379 entity_registry_enabled_default=
False,
383 device_class=SensorDeviceClass.ENUM,
387 "off_grid_intentional",
388 "off_grid_unintentional",
389 "island_status_unknown",
394 WALL_CONNECTOR_DESCRIPTIONS: tuple[TeslemetrySensorEntityDescription, ...] = (
396 key=
"wall_connector_state",
397 entity_category=EntityCategory.DIAGNOSTIC,
398 entity_registry_enabled_default=
False,
401 key=
"wall_connector_fault_state",
402 entity_category=EntityCategory.DIAGNOSTIC,
403 entity_registry_enabled_default=
False,
406 key=
"wall_connector_power",
407 state_class=SensorStateClass.MEASUREMENT,
408 native_unit_of_measurement=UnitOfPower.WATT,
409 suggested_unit_of_measurement=UnitOfPower.KILO_WATT,
410 suggested_display_precision=2,
411 device_class=SensorDeviceClass.POWER,
415 value_fn=
lambda vin: vin
or "disconnected",
419 ENERGY_INFO_DESCRIPTIONS: tuple[SensorEntityDescription, ...] = (
421 key=
"vpp_backup_reserve_percent",
422 entity_category=EntityCategory.DIAGNOSTIC,
423 device_class=SensorDeviceClass.BATTERY,
424 native_unit_of_measurement=PERCENTAGE,
429 ENERGY_HISTORY_DESCRIPTIONS: tuple[SensorEntityDescription, ...] =
tuple(
432 device_class=SensorDeviceClass.ENERGY,
433 native_unit_of_measurement=UnitOfEnergy.WATT_HOUR,
434 suggested_unit_of_measurement=UnitOfEnergy.KILO_WATT_HOUR,
435 suggested_display_precision=2,
436 state_class=SensorStateClass.TOTAL_INCREASING,
437 entity_registry_enabled_default=(
438 key.startswith(
"total")
or key ==
"grid_energy_imported"
441 for key
in ENERGY_HISTORY_FIELDS
447 entry: TeslemetryConfigEntry,
448 async_add_entities: AddEntitiesCallback,
450 """Set up the Teslemetry sensor platform from a config entry."""
455 for vehicle
in entry.runtime_data.vehicles
456 for description
in VEHICLE_DESCRIPTIONS
460 for vehicle
in entry.runtime_data.vehicles
461 for description
in VEHICLE_TIME_DESCRIPTIONS
465 for energysite
in entry.runtime_data.energysites
466 for description
in ENERGY_LIVE_DESCRIPTIONS
467 if description.key
in energysite.live_coordinator.data
471 for energysite
in entry.runtime_data.energysites
472 for din
in energysite.live_coordinator.data.get(
"wall_connectors", {})
473 for description
in WALL_CONNECTOR_DESCRIPTIONS
477 for energysite
in entry.runtime_data.energysites
478 for description
in ENERGY_INFO_DESCRIPTIONS
479 if description.key
in energysite.info_coordinator.data
483 for energysite
in entry.runtime_data.energysites
484 for description
in ENERGY_HISTORY_DESCRIPTIONS
485 if energysite.history_coordinator
492 """Base class for Teslemetry vehicle metric sensors."""
494 entity_description: TeslemetrySensorEntityDescription
498 data: TeslemetryVehicleData,
499 description: TeslemetrySensorEntityDescription,
501 """Initialize the sensor."""
503 super().
__init__(data, description.key)
506 """Update the attributes of the sensor."""
514 """Base class for Teslemetry vehicle time sensors."""
516 entity_description: TeslemetryTimeEntityDescription
520 data: TeslemetryVehicleData,
521 description: TeslemetryTimeEntityDescription,
523 """Initialize the sensor."""
526 func=
lambda value: dt_util.now() +
timedelta(minutes=value),
527 ignored_variance=
timedelta(minutes=description.variance),
530 super().
__init__(data, description.key)
533 """Update the attributes of the sensor."""
540 """Base class for Teslemetry energy site metric sensors."""
542 entity_description: SensorEntityDescription
546 data: TeslemetryEnergyData,
547 description: SensorEntityDescription,
549 """Initialize the sensor."""
551 super().
__init__(data, description.key)
554 """Update the attributes of the sensor."""
560 """Base class for Teslemetry energy site metric sensors."""
562 entity_description: TeslemetrySensorEntityDescription
566 data: TeslemetryEnergyData,
568 description: TeslemetrySensorEntityDescription,
570 """Initialize the sensor."""
579 """Update the attributes of the sensor."""
585 """Base class for Teslemetry energy site metric sensors."""
587 entity_description: SensorEntityDescription
591 data: TeslemetryEnergyData,
592 description: SensorEntityDescription,
594 """Initialize the sensor."""
596 super().
__init__(data, description.key)
599 """Update the attributes of the sensor."""
605 """Base class for Tesla Fleet energy site metric sensors."""
607 entity_description: SensorEntityDescription
611 data: TeslemetryEnergyData,
612 description: SensorEntityDescription,
614 """Initialize the sensor."""
616 super().
__init__(data, description.key)
619 """Update the attributes of the sensor."""
None _async_update_attrs(self)
None __init__(self, TeslemetryEnergyData data, SensorEntityDescription description)
None _async_update_attrs(self)
None __init__(self, TeslemetryEnergyData data, SensorEntityDescription description)
None __init__(self, TeslemetryEnergyData data, SensorEntityDescription description)
None _async_update_attrs(self)
None __init__(self, TeslemetryVehicleData data, TeslemetrySensorEntityDescription description)
None _async_update_attrs(self)
None _async_update_attrs(self)
None __init__(self, TeslemetryVehicleData data, TeslemetryTimeEntityDescription description)
None _async_update_attrs(self)
None __init__(self, TeslemetryEnergyData data, str din, TeslemetrySensorEntityDescription description)
None async_setup_entry(HomeAssistant hass, TeslemetryConfigEntry entry, AddEntitiesCallback async_add_entities)