Add guest mode switch to Teslemetry (#151550)

This commit is contained in:
Brett Adams
2025-09-12 04:44:38 -04:00
committed by GitHub
parent e438b11afb
commit 8003a49571
3 changed files with 56 additions and 27 deletions
@@ -752,6 +752,9 @@
},
"vehicle_state_valet_mode": {
"default": "mdi:speedometer-slow"
},
"guest_mode_enabled": {
"default": "mdi:account-group"
}
}
},
@@ -1084,6 +1084,9 @@
},
"vehicle_state_valet_mode": {
"name": "Valet mode"
},
"guest_mode_enabled": {
"name": "Guest mode"
}
},
"update": {
+50 -27
View File
@@ -4,7 +4,6 @@ from __future__ import annotations
from collections.abc import Awaitable, Callable
from dataclasses import dataclass
from itertools import chain
from typing import Any
from tesla_fleet_api.const import AutoSeat, Scope
@@ -38,6 +37,7 @@ PARALLEL_UPDATES = 0
class TeslemetrySwitchEntityDescription(SwitchEntityDescription):
"""Describes Teslemetry Switch entity."""
polling: bool = False
on_func: Callable[[Vehicle], Awaitable[dict[str, Any]]]
off_func: Callable[[Vehicle], Awaitable[dict[str, Any]]]
scopes: list[Scope]
@@ -53,6 +53,7 @@ class TeslemetrySwitchEntityDescription(SwitchEntityDescription):
VEHICLE_DESCRIPTIONS: tuple[TeslemetrySwitchEntityDescription, ...] = (
TeslemetrySwitchEntityDescription(
key="vehicle_state_sentry_mode",
polling=True,
streaming_listener=lambda vehicle, callback: vehicle.listen_SentryMode(
lambda value: callback(None if value is None else value != "Off")
),
@@ -62,6 +63,7 @@ VEHICLE_DESCRIPTIONS: tuple[TeslemetrySwitchEntityDescription, ...] = (
),
TeslemetrySwitchEntityDescription(
key="vehicle_state_valet_mode",
polling=True,
streaming_listener=lambda vehicle, value: vehicle.listen_ValetModeEnabled(
value
),
@@ -72,6 +74,7 @@ VEHICLE_DESCRIPTIONS: tuple[TeslemetrySwitchEntityDescription, ...] = (
),
TeslemetrySwitchEntityDescription(
key="climate_state_auto_seat_climate_left",
polling=True,
streaming_listener=lambda vehicle, callback: vehicle.listen_AutoSeatClimateLeft(
callback
),
@@ -85,6 +88,7 @@ VEHICLE_DESCRIPTIONS: tuple[TeslemetrySwitchEntityDescription, ...] = (
),
TeslemetrySwitchEntityDescription(
key="climate_state_auto_seat_climate_right",
polling=True,
streaming_listener=lambda vehicle,
callback: vehicle.listen_AutoSeatClimateRight(callback),
on_func=lambda api: api.remote_auto_seat_climate_request(
@@ -97,6 +101,7 @@ VEHICLE_DESCRIPTIONS: tuple[TeslemetrySwitchEntityDescription, ...] = (
),
TeslemetrySwitchEntityDescription(
key="climate_state_auto_steering_wheel_heat",
polling=True,
streaming_listener=lambda vehicle,
callback: vehicle.listen_HvacSteeringWheelHeatAuto(callback),
on_func=lambda api: api.remote_auto_steering_wheel_heat_climate_request(
@@ -109,6 +114,7 @@ VEHICLE_DESCRIPTIONS: tuple[TeslemetrySwitchEntityDescription, ...] = (
),
TeslemetrySwitchEntityDescription(
key="climate_state_defrost_mode",
polling=True,
streaming_listener=lambda vehicle, callback: vehicle.listen_DefrostMode(
lambda value: callback(None if value is None else value != "Off")
),
@@ -120,6 +126,7 @@ VEHICLE_DESCRIPTIONS: tuple[TeslemetrySwitchEntityDescription, ...] = (
),
TeslemetrySwitchEntityDescription(
key="charge_state_charging_state",
polling=True,
unique_id="charge_state_user_charge_enable_request",
value_func=lambda state: state in {"Starting", "Charging"},
streaming_listener=lambda vehicle, callback: vehicle.listen_DetailedChargeState(
@@ -131,6 +138,17 @@ VEHICLE_DESCRIPTIONS: tuple[TeslemetrySwitchEntityDescription, ...] = (
off_func=lambda api: api.charge_stop(),
scopes=[Scope.VEHICLE_CMDS, Scope.VEHICLE_CHARGING_CMDS],
),
TeslemetrySwitchEntityDescription(
key="guest_mode_enabled",
polling=False,
unique_id="guest_mode_enabled",
streaming_listener=lambda vehicle, callback: vehicle.listen_GuestModeEnabled(
callback
),
on_func=lambda api: api.guest_mode(True),
off_func=lambda api: api.guest_mode(False),
scopes=[Scope.VEHICLE_CMDS],
),
)
@@ -141,35 +159,40 @@ async def async_setup_entry(
) -> None:
"""Set up the Teslemetry Switch platform from a config entry."""
async_add_entities(
chain(
(
TeslemetryVehiclePollingVehicleSwitchEntity(
vehicle, description, entry.runtime_data.scopes
entities: list[SwitchEntity] = []
for vehicle in entry.runtime_data.vehicles:
for description in VEHICLE_DESCRIPTIONS:
if vehicle.poll or vehicle.firmware < description.streaming_firmware:
if description.polling:
entities.append(
TeslemetryVehiclePollingVehicleSwitchEntity(
vehicle, description, entry.runtime_data.scopes
)
)
else:
entities.append(
TeslemetryStreamingVehicleSwitchEntity(
vehicle, description, entry.runtime_data.scopes
)
)
if vehicle.poll or vehicle.firmware < description.streaming_firmware
else TeslemetryStreamingVehicleSwitchEntity(
vehicle, description, entry.runtime_data.scopes
)
for vehicle in entry.runtime_data.vehicles
for description in VEHICLE_DESCRIPTIONS
),
(
TeslemetryChargeFromGridSwitchEntity(
energysite,
entry.runtime_data.scopes,
)
for energysite in entry.runtime_data.energysites
if energysite.info_coordinator.data.get("components_battery")
and energysite.info_coordinator.data.get("components_solar")
),
(
TeslemetryStormModeSwitchEntity(energysite, entry.runtime_data.scopes)
for energysite in entry.runtime_data.energysites
if energysite.info_coordinator.data.get("components_storm_mode_capable")
),
entities.extend(
TeslemetryChargeFromGridSwitchEntity(
energysite,
entry.runtime_data.scopes,
)
for energysite in entry.runtime_data.energysites
if energysite.info_coordinator.data.get("components_battery")
and energysite.info_coordinator.data.get("components_solar")
)
entities.extend(
TeslemetryStormModeSwitchEntity(energysite, entry.runtime_data.scopes)
for energysite in entry.runtime_data.energysites
if energysite.info_coordinator.data.get("components_storm_mode_capable")
)
async_add_entities(entities)
class TeslemetryVehicleSwitchEntity(TeslemetryRootEntity, SwitchEntity):