mirror of
https://github.com/home-assistant/core.git
synced 2025-04-23 08:47:57 +00:00
Correct the behavior of the Charge switch in Tessie/Teslemetry/Tesla Fleet (#136562)
This commit is contained in:
parent
aa6ffb3da5
commit
ea62da553e
@ -298,7 +298,7 @@
|
||||
}
|
||||
},
|
||||
"switch": {
|
||||
"charge_state_user_charge_enable_request": {
|
||||
"charge_state_charging_state": {
|
||||
"default": "mdi:ev-station"
|
||||
},
|
||||
"climate_state_auto_seat_climate_left": {
|
||||
|
@ -522,7 +522,7 @@
|
||||
}
|
||||
},
|
||||
"switch": {
|
||||
"charge_state_user_charge_enable_request": {
|
||||
"charge_state_charging_state": {
|
||||
"name": "Charge"
|
||||
},
|
||||
"climate_state_auto_seat_climate_left": {
|
||||
|
@ -16,6 +16,7 @@ from homeassistant.components.switch import (
|
||||
)
|
||||
from homeassistant.core import HomeAssistant
|
||||
from homeassistant.helpers.entity_platform import AddEntitiesCallback
|
||||
from homeassistant.helpers.typing import StateType
|
||||
|
||||
from . import TeslaFleetConfigEntry
|
||||
from .entity import TeslaFleetEnergyInfoEntity, TeslaFleetVehicleEntity
|
||||
@ -32,6 +33,8 @@ class TeslaFleetSwitchEntityDescription(SwitchEntityDescription):
|
||||
on_func: Callable
|
||||
off_func: Callable
|
||||
scopes: list[Scope]
|
||||
value_func: Callable[[StateType], bool] = bool
|
||||
unique_id: str | None = None
|
||||
|
||||
|
||||
VEHICLE_DESCRIPTIONS: tuple[TeslaFleetSwitchEntityDescription, ...] = (
|
||||
@ -77,13 +80,14 @@ VEHICLE_DESCRIPTIONS: tuple[TeslaFleetSwitchEntityDescription, ...] = (
|
||||
),
|
||||
scopes=[Scope.VEHICLE_CMDS],
|
||||
),
|
||||
)
|
||||
|
||||
VEHICLE_CHARGE_DESCRIPTION = TeslaFleetSwitchEntityDescription(
|
||||
key="charge_state_user_charge_enable_request",
|
||||
on_func=lambda api: api.charge_start(),
|
||||
off_func=lambda api: api.charge_stop(),
|
||||
scopes=[Scope.VEHICLE_CHARGING_CMDS, Scope.VEHICLE_CMDS],
|
||||
TeslaFleetSwitchEntityDescription(
|
||||
key="charge_state_charging_state",
|
||||
unique_id="charge_state_user_charge_enable_request",
|
||||
on_func=lambda api: api.charge_start(),
|
||||
off_func=lambda api: api.charge_stop(),
|
||||
value_func=lambda state: state in {"Starting", "Charging"},
|
||||
scopes=[Scope.VEHICLE_CHARGING_CMDS, Scope.VEHICLE_CMDS],
|
||||
),
|
||||
)
|
||||
|
||||
|
||||
@ -103,12 +107,6 @@ async def async_setup_entry(
|
||||
for vehicle in entry.runtime_data.vehicles
|
||||
for description in VEHICLE_DESCRIPTIONS
|
||||
),
|
||||
(
|
||||
TeslaFleetChargeSwitchEntity(
|
||||
vehicle, VEHICLE_CHARGE_DESCRIPTION, entry.runtime_data.scopes
|
||||
)
|
||||
for vehicle in entry.runtime_data.vehicles
|
||||
),
|
||||
(
|
||||
TeslaFleetChargeFromGridSwitchEntity(
|
||||
energysite,
|
||||
@ -144,16 +142,18 @@ class TeslaFleetVehicleSwitchEntity(TeslaFleetVehicleEntity, TeslaFleetSwitchEnt
|
||||
scopes: list[Scope],
|
||||
) -> None:
|
||||
"""Initialize the Switch."""
|
||||
super().__init__(data, description.key)
|
||||
self.entity_description = description
|
||||
self.scoped = any(scope in scopes for scope in description.scopes)
|
||||
super().__init__(data, description.key)
|
||||
if description.unique_id:
|
||||
self._attr_unique_id = f"{data.vin}-{description.unique_id}"
|
||||
|
||||
def _async_update_attrs(self) -> None:
|
||||
"""Update the attributes of the sensor."""
|
||||
if self._value is None:
|
||||
self._attr_is_on = None
|
||||
else:
|
||||
self._attr_is_on = bool(self._value)
|
||||
self._attr_is_on = self.entity_description.value_func(self._value)
|
||||
|
||||
async def async_turn_on(self, **kwargs: Any) -> None:
|
||||
"""Turn on the Switch."""
|
||||
@ -172,17 +172,6 @@ class TeslaFleetVehicleSwitchEntity(TeslaFleetVehicleEntity, TeslaFleetSwitchEnt
|
||||
self.async_write_ha_state()
|
||||
|
||||
|
||||
class TeslaFleetChargeSwitchEntity(TeslaFleetVehicleSwitchEntity):
|
||||
"""Entity class for TeslaFleet charge switch."""
|
||||
|
||||
def _async_update_attrs(self) -> None:
|
||||
"""Update the attributes of the entity."""
|
||||
if self._value is None:
|
||||
self._attr_is_on = self.get("charge_state_charge_enable_request")
|
||||
else:
|
||||
self._attr_is_on = self._value
|
||||
|
||||
|
||||
class TeslaFleetChargeFromGridSwitchEntity(
|
||||
TeslaFleetEnergyInfoEntity, TeslaFleetSwitchEntity
|
||||
):
|
||||
|
@ -291,7 +291,7 @@
|
||||
}
|
||||
},
|
||||
"switch": {
|
||||
"charge_state_user_charge_enable_request": {
|
||||
"charge_state_charging_state": {
|
||||
"default": "mdi:ev-station"
|
||||
},
|
||||
"climate_state_auto_seat_climate_left": {
|
||||
|
@ -608,7 +608,7 @@
|
||||
}
|
||||
},
|
||||
"switch": {
|
||||
"charge_state_user_charge_enable_request": {
|
||||
"charge_state_charging_state": {
|
||||
"name": "Charge"
|
||||
},
|
||||
"climate_state_auto_seat_climate_left": {
|
||||
|
@ -16,6 +16,7 @@ from homeassistant.components.switch import (
|
||||
)
|
||||
from homeassistant.core import HomeAssistant
|
||||
from homeassistant.helpers.entity_platform import AddEntitiesCallback
|
||||
from homeassistant.helpers.typing import StateType
|
||||
|
||||
from . import TeslemetryConfigEntry
|
||||
from .entity import TeslemetryEnergyInfoEntity, TeslemetryVehicleEntity
|
||||
@ -32,6 +33,8 @@ class TeslemetrySwitchEntityDescription(SwitchEntityDescription):
|
||||
on_func: Callable
|
||||
off_func: Callable
|
||||
scopes: list[Scope]
|
||||
value_func: Callable[[StateType], bool] = bool
|
||||
unique_id: str | None = None
|
||||
|
||||
|
||||
VEHICLE_DESCRIPTIONS: tuple[TeslemetrySwitchEntityDescription, ...] = (
|
||||
@ -77,13 +80,14 @@ VEHICLE_DESCRIPTIONS: tuple[TeslemetrySwitchEntityDescription, ...] = (
|
||||
),
|
||||
scopes=[Scope.VEHICLE_CMDS],
|
||||
),
|
||||
)
|
||||
|
||||
VEHICLE_CHARGE_DESCRIPTION = TeslemetrySwitchEntityDescription(
|
||||
key="charge_state_user_charge_enable_request",
|
||||
on_func=lambda api: api.charge_start(),
|
||||
off_func=lambda api: api.charge_stop(),
|
||||
scopes=[Scope.VEHICLE_CMDS, Scope.VEHICLE_CHARGING_CMDS],
|
||||
TeslemetrySwitchEntityDescription(
|
||||
key="charge_state_charging_state",
|
||||
unique_id="charge_state_user_charge_enable_request",
|
||||
on_func=lambda api: api.charge_start(),
|
||||
off_func=lambda api: api.charge_stop(),
|
||||
value_func=lambda state: state in {"Starting", "Charging"},
|
||||
scopes=[Scope.VEHICLE_CMDS, Scope.VEHICLE_CHARGING_CMDS],
|
||||
),
|
||||
)
|
||||
|
||||
|
||||
@ -104,12 +108,6 @@ async def async_setup_entry(
|
||||
for description in VEHICLE_DESCRIPTIONS
|
||||
if description.key in vehicle.coordinator.data
|
||||
),
|
||||
(
|
||||
TeslemetryChargeSwitchEntity(
|
||||
vehicle, VEHICLE_CHARGE_DESCRIPTION, entry.runtime_data.scopes
|
||||
)
|
||||
for vehicle in entry.runtime_data.vehicles
|
||||
),
|
||||
(
|
||||
TeslemetryChargeFromGridSwitchEntity(
|
||||
energysite,
|
||||
@ -145,13 +143,15 @@ class TeslemetryVehicleSwitchEntity(TeslemetryVehicleEntity, TeslemetrySwitchEnt
|
||||
scopes: list[Scope],
|
||||
) -> None:
|
||||
"""Initialize the Switch."""
|
||||
super().__init__(data, description.key)
|
||||
self.entity_description = description
|
||||
self.scoped = any(scope in scopes for scope in description.scopes)
|
||||
super().__init__(data, description.key)
|
||||
if description.unique_id:
|
||||
self._attr_unique_id = f"{data.vin}-{description.unique_id}"
|
||||
|
||||
def _async_update_attrs(self) -> None:
|
||||
"""Update the attributes of the sensor."""
|
||||
self._attr_is_on = bool(self._value)
|
||||
self._attr_is_on = self.entity_description.value_func(self._value)
|
||||
|
||||
async def async_turn_on(self, **kwargs: Any) -> None:
|
||||
"""Turn on the Switch."""
|
||||
@ -170,17 +170,6 @@ class TeslemetryVehicleSwitchEntity(TeslemetryVehicleEntity, TeslemetrySwitchEnt
|
||||
self.async_write_ha_state()
|
||||
|
||||
|
||||
class TeslemetryChargeSwitchEntity(TeslemetryVehicleSwitchEntity):
|
||||
"""Entity class for Teslemetry charge switch."""
|
||||
|
||||
def _async_update_attrs(self) -> None:
|
||||
"""Update the attributes of the entity."""
|
||||
if self._value is None:
|
||||
self._attr_is_on = self.get("charge_state_charge_enable_request")
|
||||
else:
|
||||
self._attr_is_on = self._value
|
||||
|
||||
|
||||
class TeslemetryChargeFromGridSwitchEntity(
|
||||
TeslemetryEnergyInfoEntity, TeslemetrySwitchEntity
|
||||
):
|
||||
|
@ -459,7 +459,7 @@
|
||||
}
|
||||
},
|
||||
"switch": {
|
||||
"charge_state_charge_enable_request": {
|
||||
"charge_state_charging_state": {
|
||||
"name": "Charge"
|
||||
},
|
||||
"climate_state_defrost_mode": {
|
||||
|
@ -27,6 +27,7 @@ from homeassistant.components.switch import (
|
||||
)
|
||||
from homeassistant.core import HomeAssistant
|
||||
from homeassistant.helpers.entity_platform import AddEntitiesCallback
|
||||
from homeassistant.helpers.typing import StateType
|
||||
|
||||
from . import TessieConfigEntry
|
||||
from .entity import TessieEnergyEntity, TessieEntity
|
||||
@ -40,6 +41,8 @@ class TessieSwitchEntityDescription(SwitchEntityDescription):
|
||||
|
||||
on_func: Callable
|
||||
off_func: Callable
|
||||
value_func: Callable[[StateType], bool] = bool
|
||||
unique_id: str | None = None
|
||||
|
||||
|
||||
DESCRIPTIONS: tuple[TessieSwitchEntityDescription, ...] = (
|
||||
@ -63,12 +66,13 @@ DESCRIPTIONS: tuple[TessieSwitchEntityDescription, ...] = (
|
||||
on_func=lambda: start_steering_wheel_heater,
|
||||
off_func=lambda: stop_steering_wheel_heater,
|
||||
),
|
||||
)
|
||||
|
||||
CHARGE_DESCRIPTION: TessieSwitchEntityDescription = TessieSwitchEntityDescription(
|
||||
key="charge_state_charge_enable_request",
|
||||
on_func=lambda: start_charging,
|
||||
off_func=lambda: stop_charging,
|
||||
TessieSwitchEntityDescription(
|
||||
key="charge_state_charging_state",
|
||||
unique_id="charge_state_charge_enable_request",
|
||||
on_func=lambda: start_charging,
|
||||
off_func=lambda: stop_charging,
|
||||
value_func=lambda state: state in {"Starting", "Charging"},
|
||||
),
|
||||
)
|
||||
|
||||
PARALLEL_UPDATES = 0
|
||||
@ -89,10 +93,6 @@ async def async_setup_entry(
|
||||
for description in DESCRIPTIONS
|
||||
if description.key in vehicle.data_coordinator.data
|
||||
),
|
||||
(
|
||||
TessieChargeSwitchEntity(vehicle, CHARGE_DESCRIPTION)
|
||||
for vehicle in entry.runtime_data.vehicles
|
||||
),
|
||||
(
|
||||
TessieChargeFromGridSwitchEntity(energysite)
|
||||
for energysite in entry.runtime_data.energysites
|
||||
@ -120,13 +120,15 @@ class TessieSwitchEntity(TessieEntity, SwitchEntity):
|
||||
description: TessieSwitchEntityDescription,
|
||||
) -> None:
|
||||
"""Initialize the Switch."""
|
||||
super().__init__(vehicle, description.key)
|
||||
self.entity_description = description
|
||||
super().__init__(vehicle, description.key)
|
||||
if description.unique_id:
|
||||
self._attr_unique_id = f"{vehicle.vin}-{description.unique_id}"
|
||||
|
||||
@property
|
||||
def is_on(self) -> bool:
|
||||
"""Return the state of the Switch."""
|
||||
return self._value
|
||||
return self.entity_description.value_func(self._value)
|
||||
|
||||
async def async_turn_on(self, **kwargs: Any) -> None:
|
||||
"""Turn on the Switch."""
|
||||
@ -139,18 +141,6 @@ class TessieSwitchEntity(TessieEntity, SwitchEntity):
|
||||
self.set((self.entity_description.key, False))
|
||||
|
||||
|
||||
class TessieChargeSwitchEntity(TessieSwitchEntity):
|
||||
"""Entity class for Tessie charge switch."""
|
||||
|
||||
@property
|
||||
def is_on(self) -> bool:
|
||||
"""Return the state of the Switch."""
|
||||
|
||||
if (charge := self.get("charge_state_user_charge_enable_request")) is not None:
|
||||
return charge
|
||||
return self._value
|
||||
|
||||
|
||||
class TessieChargeFromGridSwitchEntity(TessieEnergyEntity, SwitchEntity):
|
||||
"""Entity class for Charge From Grid switch."""
|
||||
|
||||
|
@ -262,7 +262,7 @@
|
||||
'platform': 'tesla_fleet',
|
||||
'previous_unique_id': None,
|
||||
'supported_features': 0,
|
||||
'translation_key': 'charge_state_user_charge_enable_request',
|
||||
'translation_key': 'charge_state_charging_state',
|
||||
'unique_id': 'LRWXF7EK4KC700000-charge_state_user_charge_enable_request',
|
||||
'unit_of_measurement': None,
|
||||
})
|
||||
@ -278,7 +278,7 @@
|
||||
'last_changed': <ANY>,
|
||||
'last_reported': <ANY>,
|
||||
'last_updated': <ANY>,
|
||||
'state': 'on',
|
||||
'state': 'off',
|
||||
})
|
||||
# ---
|
||||
# name: test_switch[switch.test_defrost-entry]
|
||||
@ -456,7 +456,7 @@
|
||||
'last_changed': <ANY>,
|
||||
'last_reported': <ANY>,
|
||||
'last_updated': <ANY>,
|
||||
'state': 'on',
|
||||
'state': 'off',
|
||||
})
|
||||
# ---
|
||||
# name: test_switch_alt[switch.test_defrost-statealt]
|
||||
|
@ -262,7 +262,7 @@
|
||||
'platform': 'teslemetry',
|
||||
'previous_unique_id': None,
|
||||
'supported_features': 0,
|
||||
'translation_key': 'charge_state_user_charge_enable_request',
|
||||
'translation_key': 'charge_state_charging_state',
|
||||
'unique_id': 'LRW3F7EK4NC700000-charge_state_user_charge_enable_request',
|
||||
'unit_of_measurement': None,
|
||||
})
|
||||
@ -278,7 +278,7 @@
|
||||
'last_changed': <ANY>,
|
||||
'last_reported': <ANY>,
|
||||
'last_updated': <ANY>,
|
||||
'state': 'on',
|
||||
'state': 'off',
|
||||
})
|
||||
# ---
|
||||
# name: test_switch[switch.test_defrost-entry]
|
||||
@ -456,7 +456,7 @@
|
||||
'last_changed': <ANY>,
|
||||
'last_reported': <ANY>,
|
||||
'last_updated': <ANY>,
|
||||
'state': 'on',
|
||||
'state': 'off',
|
||||
})
|
||||
# ---
|
||||
# name: test_switch_alt[switch.test_defrost-statealt]
|
||||
|
@ -119,7 +119,7 @@
|
||||
'platform': 'tessie',
|
||||
'previous_unique_id': None,
|
||||
'supported_features': 0,
|
||||
'translation_key': 'charge_state_charge_enable_request',
|
||||
'translation_key': 'charge_state_charging_state',
|
||||
'unique_id': 'VINVINVIN-charge_state_charge_enable_request',
|
||||
'unit_of_measurement': None,
|
||||
})
|
||||
@ -351,6 +351,6 @@
|
||||
'last_changed': <ANY>,
|
||||
'last_reported': <ANY>,
|
||||
'last_updated': <ANY>,
|
||||
'state': 'on',
|
||||
'state': 'off',
|
||||
})
|
||||
# ---
|
||||
|
@ -20,7 +20,7 @@ from .common import RESPONSE_OK, assert_entities, setup_platform
|
||||
async def test_switches(
|
||||
hass: HomeAssistant, snapshot: SnapshotAssertion, entity_registry: er.EntityRegistry
|
||||
) -> None:
|
||||
"""Tests that the switche entities are correct."""
|
||||
"""Tests that the switch entities are correct."""
|
||||
|
||||
entry = await setup_platform(hass, [Platform.SWITCH])
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user