mirror of
https://github.com/home-assistant/core.git
synced 2025-07-13 16:27:08 +00:00
Code quality improvements for Teslemetry (#123444)
This commit is contained in:
parent
66ab90b518
commit
cad87f51a3
@ -107,6 +107,7 @@ async def async_setup_entry(hass: HomeAssistant, entry: TeslemetryConfigEntry) -
|
|||||||
device=device,
|
device=device,
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
|
|
||||||
elif "energy_site_id" in product and Scope.ENERGY_DEVICE_DATA in scopes:
|
elif "energy_site_id" in product and Scope.ENERGY_DEVICE_DATA in scopes:
|
||||||
site_id = product["energy_site_id"]
|
site_id = product["energy_site_id"]
|
||||||
if not (
|
if not (
|
||||||
|
@ -120,7 +120,8 @@ class TeslemetryClimateEntity(TeslemetryVehicleEntity, ClimateEntity):
|
|||||||
|
|
||||||
async def async_turn_on(self) -> None:
|
async def async_turn_on(self) -> None:
|
||||||
"""Set the climate state to on."""
|
"""Set the climate state to on."""
|
||||||
self.raise_for_scope()
|
|
||||||
|
self.raise_for_scope(Scope.VEHICLE_CMDS)
|
||||||
await self.wake_up_if_asleep()
|
await self.wake_up_if_asleep()
|
||||||
await handle_vehicle_command(self.api.auto_conditioning_start())
|
await handle_vehicle_command(self.api.auto_conditioning_start())
|
||||||
|
|
||||||
@ -129,7 +130,8 @@ class TeslemetryClimateEntity(TeslemetryVehicleEntity, ClimateEntity):
|
|||||||
|
|
||||||
async def async_turn_off(self) -> None:
|
async def async_turn_off(self) -> None:
|
||||||
"""Set the climate state to off."""
|
"""Set the climate state to off."""
|
||||||
self.raise_for_scope()
|
|
||||||
|
self.raise_for_scope(Scope.VEHICLE_CMDS)
|
||||||
await self.wake_up_if_asleep()
|
await self.wake_up_if_asleep()
|
||||||
await handle_vehicle_command(self.api.auto_conditioning_stop())
|
await handle_vehicle_command(self.api.auto_conditioning_stop())
|
||||||
|
|
||||||
@ -261,10 +263,11 @@ class TeslemetryCabinOverheatProtectionEntity(TeslemetryVehicleEntity, ClimateEn
|
|||||||
|
|
||||||
async def async_set_temperature(self, **kwargs: Any) -> None:
|
async def async_set_temperature(self, **kwargs: Any) -> None:
|
||||||
"""Set the climate temperature."""
|
"""Set the climate temperature."""
|
||||||
if not (temp := kwargs.get(ATTR_TEMPERATURE)):
|
self.raise_for_scope(Scope.VEHICLE_CMDS)
|
||||||
return
|
|
||||||
|
|
||||||
if (cop_mode := TEMP_LEVELS.get(temp)) is None:
|
if (temp := kwargs.get(ATTR_TEMPERATURE)) is None or (
|
||||||
|
cop_mode := TEMP_LEVELS.get(temp)
|
||||||
|
) is None:
|
||||||
raise ServiceValidationError(
|
raise ServiceValidationError(
|
||||||
translation_domain=DOMAIN,
|
translation_domain=DOMAIN,
|
||||||
translation_key="invalid_cop_temp",
|
translation_key="invalid_cop_temp",
|
||||||
@ -297,7 +300,7 @@ class TeslemetryCabinOverheatProtectionEntity(TeslemetryVehicleEntity, ClimateEn
|
|||||||
|
|
||||||
async def async_set_hvac_mode(self, hvac_mode: HVACMode) -> None:
|
async def async_set_hvac_mode(self, hvac_mode: HVACMode) -> None:
|
||||||
"""Set the climate mode and state."""
|
"""Set the climate mode and state."""
|
||||||
self.raise_for_scope()
|
self.raise_for_scope(Scope.VEHICLE_CMDS)
|
||||||
await self.wake_up_if_asleep()
|
await self.wake_up_if_asleep()
|
||||||
await self._async_set_cop(hvac_mode)
|
await self._async_set_cop(hvac_mode)
|
||||||
self.async_write_ha_state()
|
self.async_write_ha_state()
|
||||||
|
@ -52,7 +52,6 @@ class TeslemetryVehicleDataCoordinator(DataUpdateCoordinator[dict[str, Any]]):
|
|||||||
"""Class to manage fetching data from the Teslemetry API."""
|
"""Class to manage fetching data from the Teslemetry API."""
|
||||||
|
|
||||||
updated_once: bool
|
updated_once: bool
|
||||||
pre2021: bool
|
|
||||||
last_active: datetime
|
last_active: datetime
|
||||||
|
|
||||||
def __init__(
|
def __init__(
|
||||||
|
@ -79,7 +79,7 @@ class TeslemetryWindowEntity(TeslemetryVehicleEntity, CoverEntity):
|
|||||||
|
|
||||||
async def async_open_cover(self, **kwargs: Any) -> None:
|
async def async_open_cover(self, **kwargs: Any) -> None:
|
||||||
"""Vent windows."""
|
"""Vent windows."""
|
||||||
self.raise_for_scope()
|
self.raise_for_scope(Scope.VEHICLE_CMDS)
|
||||||
await self.wake_up_if_asleep()
|
await self.wake_up_if_asleep()
|
||||||
await handle_vehicle_command(
|
await handle_vehicle_command(
|
||||||
self.api.window_control(command=WindowCommand.VENT)
|
self.api.window_control(command=WindowCommand.VENT)
|
||||||
@ -89,7 +89,7 @@ class TeslemetryWindowEntity(TeslemetryVehicleEntity, CoverEntity):
|
|||||||
|
|
||||||
async def async_close_cover(self, **kwargs: Any) -> None:
|
async def async_close_cover(self, **kwargs: Any) -> None:
|
||||||
"""Close windows."""
|
"""Close windows."""
|
||||||
self.raise_for_scope()
|
self.raise_for_scope(Scope.VEHICLE_CMDS)
|
||||||
await self.wake_up_if_asleep()
|
await self.wake_up_if_asleep()
|
||||||
await handle_vehicle_command(
|
await handle_vehicle_command(
|
||||||
self.api.window_control(command=WindowCommand.CLOSE)
|
self.api.window_control(command=WindowCommand.CLOSE)
|
||||||
@ -122,7 +122,7 @@ class TeslemetryChargePortEntity(TeslemetryVehicleEntity, CoverEntity):
|
|||||||
|
|
||||||
async def async_open_cover(self, **kwargs: Any) -> None:
|
async def async_open_cover(self, **kwargs: Any) -> None:
|
||||||
"""Open charge port."""
|
"""Open charge port."""
|
||||||
self.raise_for_scope()
|
self.raise_for_scope(Scope.VEHICLE_CHARGING_CMDS)
|
||||||
await self.wake_up_if_asleep()
|
await self.wake_up_if_asleep()
|
||||||
await handle_vehicle_command(self.api.charge_port_door_open())
|
await handle_vehicle_command(self.api.charge_port_door_open())
|
||||||
self._attr_is_closed = False
|
self._attr_is_closed = False
|
||||||
@ -130,7 +130,7 @@ class TeslemetryChargePortEntity(TeslemetryVehicleEntity, CoverEntity):
|
|||||||
|
|
||||||
async def async_close_cover(self, **kwargs: Any) -> None:
|
async def async_close_cover(self, **kwargs: Any) -> None:
|
||||||
"""Close charge port."""
|
"""Close charge port."""
|
||||||
self.raise_for_scope()
|
self.raise_for_scope(Scope.VEHICLE_CHARGING_CMDS)
|
||||||
await self.wake_up_if_asleep()
|
await self.wake_up_if_asleep()
|
||||||
await handle_vehicle_command(self.api.charge_port_door_close())
|
await handle_vehicle_command(self.api.charge_port_door_close())
|
||||||
self._attr_is_closed = True
|
self._attr_is_closed = True
|
||||||
@ -157,7 +157,7 @@ class TeslemetryFrontTrunkEntity(TeslemetryVehicleEntity, CoverEntity):
|
|||||||
|
|
||||||
async def async_open_cover(self, **kwargs: Any) -> None:
|
async def async_open_cover(self, **kwargs: Any) -> None:
|
||||||
"""Open front trunk."""
|
"""Open front trunk."""
|
||||||
self.raise_for_scope()
|
self.raise_for_scope(Scope.VEHICLE_CMDS)
|
||||||
await self.wake_up_if_asleep()
|
await self.wake_up_if_asleep()
|
||||||
await handle_vehicle_command(self.api.actuate_trunk(Trunk.FRONT))
|
await handle_vehicle_command(self.api.actuate_trunk(Trunk.FRONT))
|
||||||
self._attr_is_closed = False
|
self._attr_is_closed = False
|
||||||
@ -193,7 +193,7 @@ class TeslemetryRearTrunkEntity(TeslemetryVehicleEntity, CoverEntity):
|
|||||||
async def async_open_cover(self, **kwargs: Any) -> None:
|
async def async_open_cover(self, **kwargs: Any) -> None:
|
||||||
"""Open rear trunk."""
|
"""Open rear trunk."""
|
||||||
if self.is_closed is not False:
|
if self.is_closed is not False:
|
||||||
self.raise_for_scope()
|
self.raise_for_scope(Scope.VEHICLE_CMDS)
|
||||||
await self.wake_up_if_asleep()
|
await self.wake_up_if_asleep()
|
||||||
await handle_vehicle_command(self.api.actuate_trunk(Trunk.REAR))
|
await handle_vehicle_command(self.api.actuate_trunk(Trunk.REAR))
|
||||||
self._attr_is_closed = False
|
self._attr_is_closed = False
|
||||||
@ -202,7 +202,7 @@ class TeslemetryRearTrunkEntity(TeslemetryVehicleEntity, CoverEntity):
|
|||||||
async def async_close_cover(self, **kwargs: Any) -> None:
|
async def async_close_cover(self, **kwargs: Any) -> None:
|
||||||
"""Close rear trunk."""
|
"""Close rear trunk."""
|
||||||
if self.is_closed is not True:
|
if self.is_closed is not True:
|
||||||
self.raise_for_scope()
|
self.raise_for_scope(Scope.VEHICLE_CMDS)
|
||||||
await self.wake_up_if_asleep()
|
await self.wake_up_if_asleep()
|
||||||
await handle_vehicle_command(self.api.actuate_trunk(Trunk.REAR))
|
await handle_vehicle_command(self.api.actuate_trunk(Trunk.REAR))
|
||||||
self._attr_is_closed = True
|
self._attr_is_closed = True
|
||||||
@ -240,7 +240,7 @@ class TeslemetrySunroofEntity(TeslemetryVehicleEntity, CoverEntity):
|
|||||||
|
|
||||||
async def async_open_cover(self, **kwargs: Any) -> None:
|
async def async_open_cover(self, **kwargs: Any) -> None:
|
||||||
"""Open sunroof."""
|
"""Open sunroof."""
|
||||||
self.raise_for_scope()
|
self.raise_for_scope(Scope.VEHICLE_CMDS)
|
||||||
await self.wake_up_if_asleep()
|
await self.wake_up_if_asleep()
|
||||||
await handle_vehicle_command(self.api.sun_roof_control(SunRoofCommand.VENT))
|
await handle_vehicle_command(self.api.sun_roof_control(SunRoofCommand.VENT))
|
||||||
self._attr_is_closed = False
|
self._attr_is_closed = False
|
||||||
@ -248,7 +248,7 @@ class TeslemetrySunroofEntity(TeslemetryVehicleEntity, CoverEntity):
|
|||||||
|
|
||||||
async def async_close_cover(self, **kwargs: Any) -> None:
|
async def async_close_cover(self, **kwargs: Any) -> None:
|
||||||
"""Close sunroof."""
|
"""Close sunroof."""
|
||||||
self.raise_for_scope()
|
self.raise_for_scope(Scope.VEHICLE_CMDS)
|
||||||
await self.wake_up_if_asleep()
|
await self.wake_up_if_asleep()
|
||||||
await handle_vehicle_command(self.api.sun_roof_control(SunRoofCommand.CLOSE))
|
await handle_vehicle_command(self.api.sun_roof_control(SunRoofCommand.CLOSE))
|
||||||
self._attr_is_closed = True
|
self._attr_is_closed = True
|
||||||
@ -256,7 +256,7 @@ class TeslemetrySunroofEntity(TeslemetryVehicleEntity, CoverEntity):
|
|||||||
|
|
||||||
async def async_stop_cover(self, **kwargs: Any) -> None:
|
async def async_stop_cover(self, **kwargs: Any) -> None:
|
||||||
"""Close sunroof."""
|
"""Close sunroof."""
|
||||||
self.raise_for_scope()
|
self.raise_for_scope(Scope.VEHICLE_CMDS)
|
||||||
await self.wake_up_if_asleep()
|
await self.wake_up_if_asleep()
|
||||||
await handle_vehicle_command(self.api.sun_roof_control(SunRoofCommand.STOP))
|
await handle_vehicle_command(self.api.sun_roof_control(SunRoofCommand.STOP))
|
||||||
self._attr_is_closed = False
|
self._attr_is_closed = False
|
||||||
|
@ -4,6 +4,7 @@ from abc import abstractmethod
|
|||||||
from typing import Any
|
from typing import Any
|
||||||
|
|
||||||
from tesla_fleet_api import EnergySpecific, VehicleSpecific
|
from tesla_fleet_api import EnergySpecific, VehicleSpecific
|
||||||
|
from tesla_fleet_api.const import Scope
|
||||||
|
|
||||||
from homeassistant.exceptions import ServiceValidationError
|
from homeassistant.exceptions import ServiceValidationError
|
||||||
from homeassistant.helpers.device_registry import DeviceInfo
|
from homeassistant.helpers.device_registry import DeviceInfo
|
||||||
@ -31,6 +32,7 @@ class TeslemetryEntity(
|
|||||||
"""Parent class for all Teslemetry entities."""
|
"""Parent class for all Teslemetry entities."""
|
||||||
|
|
||||||
_attr_has_entity_name = True
|
_attr_has_entity_name = True
|
||||||
|
scoped: bool
|
||||||
|
|
||||||
def __init__(
|
def __init__(
|
||||||
self,
|
self,
|
||||||
@ -38,12 +40,10 @@ class TeslemetryEntity(
|
|||||||
| TeslemetryEnergyHistoryCoordinator
|
| TeslemetryEnergyHistoryCoordinator
|
||||||
| TeslemetryEnergySiteLiveCoordinator
|
| TeslemetryEnergySiteLiveCoordinator
|
||||||
| TeslemetryEnergySiteInfoCoordinator,
|
| TeslemetryEnergySiteInfoCoordinator,
|
||||||
api: VehicleSpecific | EnergySpecific,
|
|
||||||
key: str,
|
key: str,
|
||||||
) -> None:
|
) -> None:
|
||||||
"""Initialize common aspects of a Teslemetry entity."""
|
"""Initialize common aspects of a Teslemetry entity."""
|
||||||
super().__init__(coordinator)
|
super().__init__(coordinator)
|
||||||
self.api = api
|
|
||||||
self.key = key
|
self.key = key
|
||||||
self._attr_translation_key = self.key
|
self._attr_translation_key = self.key
|
||||||
self._async_update_attrs()
|
self._async_update_attrs()
|
||||||
@ -87,16 +87,22 @@ class TeslemetryEntity(
|
|||||||
def _async_update_attrs(self) -> None:
|
def _async_update_attrs(self) -> None:
|
||||||
"""Update the attributes of the entity."""
|
"""Update the attributes of the entity."""
|
||||||
|
|
||||||
def raise_for_scope(self):
|
def raise_for_scope(self, scope: Scope):
|
||||||
"""Raise an error if a scope is not available."""
|
"""Raise an error if a scope is not available."""
|
||||||
if not self.scoped:
|
if not self.scoped:
|
||||||
raise ServiceValidationError("Missing required scope")
|
raise ServiceValidationError(
|
||||||
|
translation_domain=DOMAIN,
|
||||||
|
translation_key="missing_scope",
|
||||||
|
translation_placeholders={"scope": scope},
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
class TeslemetryVehicleEntity(TeslemetryEntity):
|
class TeslemetryVehicleEntity(TeslemetryEntity):
|
||||||
"""Parent class for Teslemetry Vehicle entities."""
|
"""Parent class for Teslemetry Vehicle entities."""
|
||||||
|
|
||||||
_last_update: int = 0
|
_last_update: int = 0
|
||||||
|
api: VehicleSpecific
|
||||||
|
vehicle: TeslemetryVehicleData
|
||||||
|
|
||||||
def __init__(
|
def __init__(
|
||||||
self,
|
self,
|
||||||
@ -105,11 +111,11 @@ class TeslemetryVehicleEntity(TeslemetryEntity):
|
|||||||
) -> None:
|
) -> None:
|
||||||
"""Initialize common aspects of a Teslemetry entity."""
|
"""Initialize common aspects of a Teslemetry entity."""
|
||||||
|
|
||||||
self._attr_unique_id = f"{data.vin}-{key}"
|
self.api = data.api
|
||||||
self.vehicle = data
|
self.vehicle = data
|
||||||
|
self._attr_unique_id = f"{data.vin}-{key}"
|
||||||
self._attr_device_info = data.device
|
self._attr_device_info = data.device
|
||||||
super().__init__(data.coordinator, data.api, key)
|
super().__init__(data.coordinator, key)
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def _value(self) -> Any | None:
|
def _value(self) -> Any | None:
|
||||||
@ -124,31 +130,39 @@ class TeslemetryVehicleEntity(TeslemetryEntity):
|
|||||||
class TeslemetryEnergyLiveEntity(TeslemetryEntity):
|
class TeslemetryEnergyLiveEntity(TeslemetryEntity):
|
||||||
"""Parent class for Teslemetry Energy Site Live entities."""
|
"""Parent class for Teslemetry Energy Site Live entities."""
|
||||||
|
|
||||||
|
api: EnergySpecific
|
||||||
|
|
||||||
def __init__(
|
def __init__(
|
||||||
self,
|
self,
|
||||||
data: TeslemetryEnergyData,
|
data: TeslemetryEnergyData,
|
||||||
key: str,
|
key: str,
|
||||||
) -> None:
|
) -> None:
|
||||||
"""Initialize common aspects of a Teslemetry Energy Site Live entity."""
|
"""Initialize common aspects of a Teslemetry Energy Site Live entity."""
|
||||||
|
|
||||||
|
self.api = data.api
|
||||||
self._attr_unique_id = f"{data.id}-{key}"
|
self._attr_unique_id = f"{data.id}-{key}"
|
||||||
self._attr_device_info = data.device
|
self._attr_device_info = data.device
|
||||||
|
|
||||||
super().__init__(data.live_coordinator, data.api, key)
|
super().__init__(data.live_coordinator, key)
|
||||||
|
|
||||||
|
|
||||||
class TeslemetryEnergyInfoEntity(TeslemetryEntity):
|
class TeslemetryEnergyInfoEntity(TeslemetryEntity):
|
||||||
"""Parent class for Teslemetry Energy Site Info Entities."""
|
"""Parent class for Teslemetry Energy Site Info Entities."""
|
||||||
|
|
||||||
|
api: EnergySpecific
|
||||||
|
|
||||||
def __init__(
|
def __init__(
|
||||||
self,
|
self,
|
||||||
data: TeslemetryEnergyData,
|
data: TeslemetryEnergyData,
|
||||||
key: str,
|
key: str,
|
||||||
) -> None:
|
) -> None:
|
||||||
"""Initialize common aspects of a Teslemetry Energy Site Info entity."""
|
"""Initialize common aspects of a Teslemetry Energy Site Info entity."""
|
||||||
|
|
||||||
|
self.api = data.api
|
||||||
self._attr_unique_id = f"{data.id}-{key}"
|
self._attr_unique_id = f"{data.id}-{key}"
|
||||||
self._attr_device_info = data.device
|
self._attr_device_info = data.device
|
||||||
|
|
||||||
super().__init__(data.info_coordinator, data.api, key)
|
super().__init__(data.info_coordinator, key)
|
||||||
|
|
||||||
|
|
||||||
class TeslemetryEnergyHistoryEntity(TeslemetryEntity):
|
class TeslemetryEnergyHistoryEntity(TeslemetryEntity):
|
||||||
@ -160,18 +174,19 @@ class TeslemetryEnergyHistoryEntity(TeslemetryEntity):
|
|||||||
key: str,
|
key: str,
|
||||||
) -> None:
|
) -> None:
|
||||||
"""Initialize common aspects of a Teslemetry Energy Site Info entity."""
|
"""Initialize common aspects of a Teslemetry Energy Site Info entity."""
|
||||||
|
|
||||||
|
self.api = data.api
|
||||||
self._attr_unique_id = f"{data.id}-{key}"
|
self._attr_unique_id = f"{data.id}-{key}"
|
||||||
self._attr_device_info = data.device
|
self._attr_device_info = data.device
|
||||||
|
|
||||||
super().__init__(data.history_coordinator, data.api, key)
|
super().__init__(data.history_coordinator, key)
|
||||||
|
|
||||||
|
|
||||||
class TeslemetryWallConnectorEntity(
|
class TeslemetryWallConnectorEntity(TeslemetryEntity):
|
||||||
TeslemetryEntity, CoordinatorEntity[TeslemetryEnergySiteLiveCoordinator]
|
|
||||||
):
|
|
||||||
"""Parent class for Teslemetry Wall Connector Entities."""
|
"""Parent class for Teslemetry Wall Connector Entities."""
|
||||||
|
|
||||||
_attr_has_entity_name = True
|
_attr_has_entity_name = True
|
||||||
|
api: EnergySpecific
|
||||||
|
|
||||||
def __init__(
|
def __init__(
|
||||||
self,
|
self,
|
||||||
@ -180,6 +195,8 @@ class TeslemetryWallConnectorEntity(
|
|||||||
key: str,
|
key: str,
|
||||||
) -> None:
|
) -> None:
|
||||||
"""Initialize common aspects of a Teslemetry entity."""
|
"""Initialize common aspects of a Teslemetry entity."""
|
||||||
|
|
||||||
|
self.api = data.api
|
||||||
self.din = din
|
self.din = din
|
||||||
self._attr_unique_id = f"{data.id}-{din}-{key}"
|
self._attr_unique_id = f"{data.id}-{din}-{key}"
|
||||||
|
|
||||||
@ -200,7 +217,7 @@ class TeslemetryWallConnectorEntity(
|
|||||||
model=model,
|
model=model,
|
||||||
)
|
)
|
||||||
|
|
||||||
super().__init__(data.live_coordinator, data.api, key)
|
super().__init__(data.live_coordinator, key)
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def _value(self) -> int:
|
def _value(self) -> int:
|
||||||
|
@ -7,7 +7,7 @@ from tesla_fleet_api.exceptions import TeslaFleetError
|
|||||||
|
|
||||||
from homeassistant.exceptions import HomeAssistantError
|
from homeassistant.exceptions import HomeAssistantError
|
||||||
|
|
||||||
from .const import LOGGER, TeslemetryState
|
from .const import DOMAIN, LOGGER, TeslemetryState
|
||||||
|
|
||||||
|
|
||||||
async def wake_up_vehicle(vehicle) -> None:
|
async def wake_up_vehicle(vehicle) -> None:
|
||||||
@ -22,12 +22,19 @@ async def wake_up_vehicle(vehicle) -> None:
|
|||||||
cmd = await vehicle.api.vehicle()
|
cmd = await vehicle.api.vehicle()
|
||||||
state = cmd["response"]["state"]
|
state = cmd["response"]["state"]
|
||||||
except TeslaFleetError as e:
|
except TeslaFleetError as e:
|
||||||
raise HomeAssistantError(str(e)) from e
|
raise HomeAssistantError(
|
||||||
|
translation_domain=DOMAIN,
|
||||||
|
translation_key="wake_up_failed",
|
||||||
|
translation_placeholders={"message": e.message},
|
||||||
|
) from e
|
||||||
vehicle.coordinator.data["state"] = state
|
vehicle.coordinator.data["state"] = state
|
||||||
if state != TeslemetryState.ONLINE:
|
if state != TeslemetryState.ONLINE:
|
||||||
times += 1
|
times += 1
|
||||||
if times >= 4: # Give up after 30 seconds total
|
if times >= 4: # Give up after 30 seconds total
|
||||||
raise HomeAssistantError("Could not wake up vehicle")
|
raise HomeAssistantError(
|
||||||
|
translation_domain=DOMAIN,
|
||||||
|
translation_key="wake_up_timeout",
|
||||||
|
)
|
||||||
await asyncio.sleep(times * 5)
|
await asyncio.sleep(times * 5)
|
||||||
|
|
||||||
|
|
||||||
@ -36,18 +43,26 @@ async def handle_command(command) -> dict[str, Any]:
|
|||||||
try:
|
try:
|
||||||
result = await command
|
result = await command
|
||||||
except TeslaFleetError as e:
|
except TeslaFleetError as e:
|
||||||
raise HomeAssistantError(f"Teslemetry command failed, {e.message}") from e
|
raise HomeAssistantError(
|
||||||
|
translation_domain=DOMAIN,
|
||||||
|
translation_key="command_exception",
|
||||||
|
translation_placeholders={"message": e.message},
|
||||||
|
) from e
|
||||||
LOGGER.debug("Command result: %s", result)
|
LOGGER.debug("Command result: %s", result)
|
||||||
return result
|
return result
|
||||||
|
|
||||||
|
|
||||||
async def handle_vehicle_command(command) -> dict[str, Any]:
|
async def handle_vehicle_command(command) -> Any:
|
||||||
"""Handle a vehicle command."""
|
"""Handle a vehicle command."""
|
||||||
result = await handle_command(command)
|
result = await handle_command(command)
|
||||||
if (response := result.get("response")) is None:
|
if (response := result.get("response")) is None:
|
||||||
if error := result.get("error"):
|
if error := result.get("error"):
|
||||||
# No response with error
|
# No response with error
|
||||||
raise HomeAssistantError(error)
|
raise HomeAssistantError(
|
||||||
|
translation_domain=DOMAIN,
|
||||||
|
translation_key="command_error",
|
||||||
|
translation_placeholders={"error": error},
|
||||||
|
)
|
||||||
# No response without error (unexpected)
|
# No response without error (unexpected)
|
||||||
raise HomeAssistantError(f"Unknown response: {response}")
|
raise HomeAssistantError(f"Unknown response: {response}")
|
||||||
if (result := response.get("result")) is not True:
|
if (result := response.get("result")) is not True:
|
||||||
@ -56,8 +71,14 @@ async def handle_vehicle_command(command) -> dict[str, Any]:
|
|||||||
# Reason is acceptable
|
# Reason is acceptable
|
||||||
return result
|
return result
|
||||||
# Result of false with reason
|
# Result of false with reason
|
||||||
raise HomeAssistantError(reason)
|
raise HomeAssistantError(
|
||||||
|
translation_domain=DOMAIN,
|
||||||
|
translation_key="command_reason",
|
||||||
|
translation_placeholders={"reason": reason},
|
||||||
|
)
|
||||||
# Result of false without reason (unexpected)
|
# Result of false without reason (unexpected)
|
||||||
raise HomeAssistantError("Command failed with no reason")
|
raise HomeAssistantError(
|
||||||
|
translation_domain=DOMAIN, translation_key="command_no_result"
|
||||||
|
)
|
||||||
# Response with result of true
|
# Response with result of true
|
||||||
return result
|
return result
|
||||||
|
@ -53,7 +53,7 @@ class TeslemetryVehicleLockEntity(TeslemetryVehicleEntity, LockEntity):
|
|||||||
|
|
||||||
async def async_lock(self, **kwargs: Any) -> None:
|
async def async_lock(self, **kwargs: Any) -> None:
|
||||||
"""Lock the doors."""
|
"""Lock the doors."""
|
||||||
self.raise_for_scope()
|
self.raise_for_scope(Scope.VEHICLE_CMDS)
|
||||||
await self.wake_up_if_asleep()
|
await self.wake_up_if_asleep()
|
||||||
await handle_vehicle_command(self.api.door_lock())
|
await handle_vehicle_command(self.api.door_lock())
|
||||||
self._attr_is_locked = True
|
self._attr_is_locked = True
|
||||||
@ -61,7 +61,7 @@ class TeslemetryVehicleLockEntity(TeslemetryVehicleEntity, LockEntity):
|
|||||||
|
|
||||||
async def async_unlock(self, **kwargs: Any) -> None:
|
async def async_unlock(self, **kwargs: Any) -> None:
|
||||||
"""Unlock the doors."""
|
"""Unlock the doors."""
|
||||||
self.raise_for_scope()
|
self.raise_for_scope(Scope.VEHICLE_CMDS)
|
||||||
await self.wake_up_if_asleep()
|
await self.wake_up_if_asleep()
|
||||||
await handle_vehicle_command(self.api.door_unlock())
|
await handle_vehicle_command(self.api.door_unlock())
|
||||||
self._attr_is_locked = False
|
self._attr_is_locked = False
|
||||||
@ -96,7 +96,7 @@ class TeslemetryCableLockEntity(TeslemetryVehicleEntity, LockEntity):
|
|||||||
|
|
||||||
async def async_unlock(self, **kwargs: Any) -> None:
|
async def async_unlock(self, **kwargs: Any) -> None:
|
||||||
"""Unlock charge cable lock."""
|
"""Unlock charge cable lock."""
|
||||||
self.raise_for_scope()
|
self.raise_for_scope(Scope.VEHICLE_CMDS)
|
||||||
await self.wake_up_if_asleep()
|
await self.wake_up_if_asleep()
|
||||||
await handle_vehicle_command(self.api.charge_port_door_open())
|
await handle_vehicle_command(self.api.charge_port_door_open())
|
||||||
self._attr_is_locked = False
|
self._attr_is_locked = False
|
||||||
|
@ -115,7 +115,7 @@ class TeslemetryMediaEntity(TeslemetryVehicleEntity, MediaPlayerEntity):
|
|||||||
|
|
||||||
async def async_set_volume_level(self, volume: float) -> None:
|
async def async_set_volume_level(self, volume: float) -> None:
|
||||||
"""Set volume level, range 0..1."""
|
"""Set volume level, range 0..1."""
|
||||||
self.raise_for_scope()
|
self.raise_for_scope(Scope.VEHICLE_CMDS)
|
||||||
await self.wake_up_if_asleep()
|
await self.wake_up_if_asleep()
|
||||||
await handle_vehicle_command(
|
await handle_vehicle_command(
|
||||||
self.api.adjust_volume(int(volume * self._volume_max))
|
self.api.adjust_volume(int(volume * self._volume_max))
|
||||||
@ -126,7 +126,7 @@ class TeslemetryMediaEntity(TeslemetryVehicleEntity, MediaPlayerEntity):
|
|||||||
async def async_media_play(self) -> None:
|
async def async_media_play(self) -> None:
|
||||||
"""Send play command."""
|
"""Send play command."""
|
||||||
if self.state != MediaPlayerState.PLAYING:
|
if self.state != MediaPlayerState.PLAYING:
|
||||||
self.raise_for_scope()
|
self.raise_for_scope(Scope.VEHICLE_CMDS)
|
||||||
await self.wake_up_if_asleep()
|
await self.wake_up_if_asleep()
|
||||||
await handle_vehicle_command(self.api.media_toggle_playback())
|
await handle_vehicle_command(self.api.media_toggle_playback())
|
||||||
self._attr_state = MediaPlayerState.PLAYING
|
self._attr_state = MediaPlayerState.PLAYING
|
||||||
@ -135,7 +135,7 @@ class TeslemetryMediaEntity(TeslemetryVehicleEntity, MediaPlayerEntity):
|
|||||||
async def async_media_pause(self) -> None:
|
async def async_media_pause(self) -> None:
|
||||||
"""Send pause command."""
|
"""Send pause command."""
|
||||||
if self.state == MediaPlayerState.PLAYING:
|
if self.state == MediaPlayerState.PLAYING:
|
||||||
self.raise_for_scope()
|
self.raise_for_scope(Scope.VEHICLE_CMDS)
|
||||||
await self.wake_up_if_asleep()
|
await self.wake_up_if_asleep()
|
||||||
await handle_vehicle_command(self.api.media_toggle_playback())
|
await handle_vehicle_command(self.api.media_toggle_playback())
|
||||||
self._attr_state = MediaPlayerState.PAUSED
|
self._attr_state = MediaPlayerState.PAUSED
|
||||||
@ -143,12 +143,12 @@ class TeslemetryMediaEntity(TeslemetryVehicleEntity, MediaPlayerEntity):
|
|||||||
|
|
||||||
async def async_media_next_track(self) -> None:
|
async def async_media_next_track(self) -> None:
|
||||||
"""Send next track command."""
|
"""Send next track command."""
|
||||||
self.raise_for_scope()
|
self.raise_for_scope(Scope.VEHICLE_CMDS)
|
||||||
await self.wake_up_if_asleep()
|
await self.wake_up_if_asleep()
|
||||||
await handle_vehicle_command(self.api.media_next_track())
|
await handle_vehicle_command(self.api.media_next_track())
|
||||||
|
|
||||||
async def async_media_previous_track(self) -> None:
|
async def async_media_previous_track(self) -> None:
|
||||||
"""Send previous track command."""
|
"""Send previous track command."""
|
||||||
self.raise_for_scope()
|
self.raise_for_scope(Scope.VEHICLE_CMDS)
|
||||||
await self.wake_up_if_asleep()
|
await self.wake_up_if_asleep()
|
||||||
await handle_vehicle_command(self.api.media_prev_track())
|
await handle_vehicle_command(self.api.media_prev_track())
|
||||||
|
@ -164,7 +164,7 @@ class TeslemetryVehicleNumberEntity(TeslemetryVehicleEntity, NumberEntity):
|
|||||||
async def async_set_native_value(self, value: float) -> None:
|
async def async_set_native_value(self, value: float) -> None:
|
||||||
"""Set new value."""
|
"""Set new value."""
|
||||||
value = int(value)
|
value = int(value)
|
||||||
self.raise_for_scope()
|
self.raise_for_scope(self.entity_description.scopes[0])
|
||||||
await self.wake_up_if_asleep()
|
await self.wake_up_if_asleep()
|
||||||
await handle_vehicle_command(self.entity_description.func(self.api, value))
|
await handle_vehicle_command(self.entity_description.func(self.api, value))
|
||||||
self._attr_native_value = value
|
self._attr_native_value = value
|
||||||
@ -200,7 +200,7 @@ class TeslemetryEnergyInfoNumberSensorEntity(TeslemetryEnergyInfoEntity, NumberE
|
|||||||
async def async_set_native_value(self, value: float) -> None:
|
async def async_set_native_value(self, value: float) -> None:
|
||||||
"""Set new value."""
|
"""Set new value."""
|
||||||
value = int(value)
|
value = int(value)
|
||||||
self.raise_for_scope()
|
self.raise_for_scope(Scope.ENERGY_CMDS)
|
||||||
await handle_command(self.entity_description.func(self.api, value))
|
await handle_command(self.entity_description.func(self.api, value))
|
||||||
self._attr_native_value = value
|
self._attr_native_value = value
|
||||||
self.async_write_ha_state()
|
self.async_write_ha_state()
|
||||||
|
@ -144,7 +144,7 @@ class TeslemetrySeatHeaterSelectEntity(TeslemetryVehicleEntity, SelectEntity):
|
|||||||
|
|
||||||
async def async_select_option(self, option: str) -> None:
|
async def async_select_option(self, option: str) -> None:
|
||||||
"""Change the selected option."""
|
"""Change the selected option."""
|
||||||
self.raise_for_scope()
|
self.raise_for_scope(Scope.VEHICLE_CMDS)
|
||||||
await self.wake_up_if_asleep()
|
await self.wake_up_if_asleep()
|
||||||
level = self._attr_options.index(option)
|
level = self._attr_options.index(option)
|
||||||
# AC must be on to turn on seat heater
|
# AC must be on to turn on seat heater
|
||||||
@ -189,7 +189,7 @@ class TeslemetryWheelHeaterSelectEntity(TeslemetryVehicleEntity, SelectEntity):
|
|||||||
|
|
||||||
async def async_select_option(self, option: str) -> None:
|
async def async_select_option(self, option: str) -> None:
|
||||||
"""Change the selected option."""
|
"""Change the selected option."""
|
||||||
self.raise_for_scope()
|
self.raise_for_scope(Scope.VEHICLE_CMDS)
|
||||||
await self.wake_up_if_asleep()
|
await self.wake_up_if_asleep()
|
||||||
level = self._attr_options.index(option)
|
level = self._attr_options.index(option)
|
||||||
# AC must be on to turn on steering wheel heater
|
# AC must be on to turn on steering wheel heater
|
||||||
@ -226,7 +226,7 @@ class TeslemetryOperationSelectEntity(TeslemetryEnergyInfoEntity, SelectEntity):
|
|||||||
|
|
||||||
async def async_select_option(self, option: str) -> None:
|
async def async_select_option(self, option: str) -> None:
|
||||||
"""Change the selected option."""
|
"""Change the selected option."""
|
||||||
self.raise_for_scope()
|
self.raise_for_scope(Scope.ENERGY_CMDS)
|
||||||
await handle_command(self.api.operation(option))
|
await handle_command(self.api.operation(option))
|
||||||
self._attr_current_option = option
|
self._attr_current_option = option
|
||||||
self.async_write_ha_state()
|
self.async_write_ha_state()
|
||||||
@ -256,7 +256,7 @@ class TeslemetryExportRuleSelectEntity(TeslemetryEnergyInfoEntity, SelectEntity)
|
|||||||
|
|
||||||
async def async_select_option(self, option: str) -> None:
|
async def async_select_option(self, option: str) -> None:
|
||||||
"""Change the selected option."""
|
"""Change the selected option."""
|
||||||
self.raise_for_scope()
|
self.raise_for_scope(Scope.ENERGY_CMDS)
|
||||||
await handle_command(
|
await handle_command(
|
||||||
self.api.grid_import_export(customer_preferred_export_rule=option)
|
self.api.grid_import_export(customer_preferred_export_rule=option)
|
||||||
)
|
)
|
||||||
|
@ -567,8 +567,26 @@
|
|||||||
"no_energy_site_data_for_device": {
|
"no_energy_site_data_for_device": {
|
||||||
"message": "No energy site data for device ID: {device_id}"
|
"message": "No energy site data for device ID: {device_id}"
|
||||||
},
|
},
|
||||||
|
"command_exception": {
|
||||||
|
"message": "Command returned exception: {message}"
|
||||||
|
},
|
||||||
"command_error": {
|
"command_error": {
|
||||||
"message": "Command returned error: {error}"
|
"message": "Command returned error: {error}"
|
||||||
|
},
|
||||||
|
"command_reason": {
|
||||||
|
"message": "Command was rejected: {reason}"
|
||||||
|
},
|
||||||
|
"command_no_result": {
|
||||||
|
"message": "Command had no result"
|
||||||
|
},
|
||||||
|
"wake_up_failed": {
|
||||||
|
"message": "Failed to wake up vehicle: {message}"
|
||||||
|
},
|
||||||
|
"wake_up_timeout": {
|
||||||
|
"message": "Timed out trying to wake up vehicle"
|
||||||
|
},
|
||||||
|
"missing_scope": {
|
||||||
|
"message": "Missing required scope: {scope}"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"services": {
|
"services": {
|
||||||
|
@ -157,7 +157,7 @@ class TeslemetryVehicleSwitchEntity(TeslemetryVehicleEntity, TeslemetrySwitchEnt
|
|||||||
|
|
||||||
async def async_turn_on(self, **kwargs: Any) -> None:
|
async def async_turn_on(self, **kwargs: Any) -> None:
|
||||||
"""Turn on the Switch."""
|
"""Turn on the Switch."""
|
||||||
self.raise_for_scope()
|
self.raise_for_scope(self.entity_description.scopes[0])
|
||||||
await self.wake_up_if_asleep()
|
await self.wake_up_if_asleep()
|
||||||
await handle_vehicle_command(self.entity_description.on_func(self.api))
|
await handle_vehicle_command(self.entity_description.on_func(self.api))
|
||||||
self._attr_is_on = True
|
self._attr_is_on = True
|
||||||
@ -165,7 +165,7 @@ class TeslemetryVehicleSwitchEntity(TeslemetryVehicleEntity, TeslemetrySwitchEnt
|
|||||||
|
|
||||||
async def async_turn_off(self, **kwargs: Any) -> None:
|
async def async_turn_off(self, **kwargs: Any) -> None:
|
||||||
"""Turn off the Switch."""
|
"""Turn off the Switch."""
|
||||||
self.raise_for_scope()
|
self.raise_for_scope(self.entity_description.scopes[0])
|
||||||
await self.wake_up_if_asleep()
|
await self.wake_up_if_asleep()
|
||||||
await handle_vehicle_command(self.entity_description.off_func(self.api))
|
await handle_vehicle_command(self.entity_description.off_func(self.api))
|
||||||
self._attr_is_on = False
|
self._attr_is_on = False
|
||||||
@ -207,7 +207,7 @@ class TeslemetryChargeFromGridSwitchEntity(
|
|||||||
|
|
||||||
async def async_turn_on(self, **kwargs: Any) -> None:
|
async def async_turn_on(self, **kwargs: Any) -> None:
|
||||||
"""Turn on the Switch."""
|
"""Turn on the Switch."""
|
||||||
self.raise_for_scope()
|
self.raise_for_scope(Scope.ENERGY_CMDS)
|
||||||
await handle_command(
|
await handle_command(
|
||||||
self.api.grid_import_export(
|
self.api.grid_import_export(
|
||||||
disallow_charge_from_grid_with_solar_installed=False
|
disallow_charge_from_grid_with_solar_installed=False
|
||||||
@ -218,7 +218,7 @@ class TeslemetryChargeFromGridSwitchEntity(
|
|||||||
|
|
||||||
async def async_turn_off(self, **kwargs: Any) -> None:
|
async def async_turn_off(self, **kwargs: Any) -> None:
|
||||||
"""Turn off the Switch."""
|
"""Turn off the Switch."""
|
||||||
self.raise_for_scope()
|
self.raise_for_scope(Scope.ENERGY_CMDS)
|
||||||
await handle_command(
|
await handle_command(
|
||||||
self.api.grid_import_export(
|
self.api.grid_import_export(
|
||||||
disallow_charge_from_grid_with_solar_installed=True
|
disallow_charge_from_grid_with_solar_installed=True
|
||||||
@ -249,14 +249,14 @@ class TeslemetryStormModeSwitchEntity(
|
|||||||
|
|
||||||
async def async_turn_on(self, **kwargs: Any) -> None:
|
async def async_turn_on(self, **kwargs: Any) -> None:
|
||||||
"""Turn on the Switch."""
|
"""Turn on the Switch."""
|
||||||
self.raise_for_scope()
|
self.raise_for_scope(Scope.ENERGY_CMDS)
|
||||||
await handle_command(self.api.storm_mode(enabled=True))
|
await handle_command(self.api.storm_mode(enabled=True))
|
||||||
self._attr_is_on = True
|
self._attr_is_on = True
|
||||||
self.async_write_ha_state()
|
self.async_write_ha_state()
|
||||||
|
|
||||||
async def async_turn_off(self, **kwargs: Any) -> None:
|
async def async_turn_off(self, **kwargs: Any) -> None:
|
||||||
"""Turn off the Switch."""
|
"""Turn off the Switch."""
|
||||||
self.raise_for_scope()
|
self.raise_for_scope(Scope.ENERGY_CMDS)
|
||||||
await handle_command(self.api.storm_mode(enabled=False))
|
await handle_command(self.api.storm_mode(enabled=False))
|
||||||
self._attr_is_on = False
|
self._attr_is_on = False
|
||||||
self.async_write_ha_state()
|
self.async_write_ha_state()
|
||||||
|
@ -103,7 +103,7 @@ class TeslemetryUpdateEntity(TeslemetryVehicleEntity, UpdateEntity):
|
|||||||
self, version: str | None, backup: bool, **kwargs: Any
|
self, version: str | None, backup: bool, **kwargs: Any
|
||||||
) -> None:
|
) -> None:
|
||||||
"""Install an update."""
|
"""Install an update."""
|
||||||
self.raise_for_scope()
|
self.raise_for_scope(Scope.ENERGY_CMDS)
|
||||||
await self.wake_up_if_asleep()
|
await self.wake_up_if_asleep()
|
||||||
await handle_vehicle_command(self.api.schedule_software_update(offset_sec=60))
|
await handle_vehicle_command(self.api.schedule_software_update(offset_sec=60))
|
||||||
self._attr_in_progress = True
|
self._attr_in_progress = True
|
||||||
|
@ -2,7 +2,7 @@
|
|||||||
|
|
||||||
from unittest.mock import patch
|
from unittest.mock import patch
|
||||||
|
|
||||||
from syrupy import SnapshotAssertion
|
from syrupy.assertion import SnapshotAssertion
|
||||||
|
|
||||||
from homeassistant.components.teslemetry.const import DOMAIN
|
from homeassistant.components.teslemetry.const import DOMAIN
|
||||||
from homeassistant.const import Platform
|
from homeassistant.const import Platform
|
||||||
|
@ -1,4 +1,10 @@
|
|||||||
# serializer version: 1
|
# serializer version: 1
|
||||||
|
# name: test_asleep_or_offline[HomeAssistantError]
|
||||||
|
'Timed out trying to wake up vehicle'
|
||||||
|
# ---
|
||||||
|
# name: test_asleep_or_offline[InvalidCommand]
|
||||||
|
'Failed to wake up vehicle: The data request or command is unknown.'
|
||||||
|
# ---
|
||||||
# name: test_climate[climate.test_cabin_overheat_protection-entry]
|
# name: test_climate[climate.test_cabin_overheat_protection-entry]
|
||||||
EntityRegistryEntrySnapshot({
|
EntityRegistryEntrySnapshot({
|
||||||
'aliases': set({
|
'aliases': set({
|
||||||
@ -499,3 +505,6 @@
|
|||||||
'state': 'unknown',
|
'state': 'unknown',
|
||||||
})
|
})
|
||||||
# ---
|
# ---
|
||||||
|
# name: test_invalid_error[error]
|
||||||
|
'Command returned exception: The data request or command is unknown.'
|
||||||
|
# ---
|
||||||
|
@ -1,8 +1,10 @@
|
|||||||
"""Test the Teslemetry binary sensor platform."""
|
"""Test the Teslemetry binary sensor platform."""
|
||||||
|
|
||||||
|
from unittest.mock import AsyncMock
|
||||||
|
|
||||||
from freezegun.api import FrozenDateTimeFactory
|
from freezegun.api import FrozenDateTimeFactory
|
||||||
import pytest
|
import pytest
|
||||||
from syrupy import SnapshotAssertion
|
from syrupy.assertion import SnapshotAssertion
|
||||||
from tesla_fleet_api.exceptions import VehicleOffline
|
from tesla_fleet_api.exceptions import VehicleOffline
|
||||||
|
|
||||||
from homeassistant.components.teslemetry.coordinator import VEHICLE_INTERVAL
|
from homeassistant.components.teslemetry.coordinator import VEHICLE_INTERVAL
|
||||||
@ -33,7 +35,7 @@ async def test_binary_sensor_refresh(
|
|||||||
hass: HomeAssistant,
|
hass: HomeAssistant,
|
||||||
snapshot: SnapshotAssertion,
|
snapshot: SnapshotAssertion,
|
||||||
entity_registry: er.EntityRegistry,
|
entity_registry: er.EntityRegistry,
|
||||||
mock_vehicle_data,
|
mock_vehicle_data: AsyncMock,
|
||||||
freezer: FrozenDateTimeFactory,
|
freezer: FrozenDateTimeFactory,
|
||||||
) -> None:
|
) -> None:
|
||||||
"""Tests that the binary sensor entities are correct."""
|
"""Tests that the binary sensor entities are correct."""
|
||||||
@ -51,7 +53,7 @@ async def test_binary_sensor_refresh(
|
|||||||
|
|
||||||
async def test_binary_sensor_offline(
|
async def test_binary_sensor_offline(
|
||||||
hass: HomeAssistant,
|
hass: HomeAssistant,
|
||||||
mock_vehicle_data,
|
mock_vehicle_data: AsyncMock,
|
||||||
) -> None:
|
) -> None:
|
||||||
"""Tests that the binary sensor entities are correct when offline."""
|
"""Tests that the binary sensor entities are correct when offline."""
|
||||||
|
|
||||||
|
@ -3,7 +3,7 @@
|
|||||||
from unittest.mock import patch
|
from unittest.mock import patch
|
||||||
|
|
||||||
import pytest
|
import pytest
|
||||||
from syrupy import SnapshotAssertion
|
from syrupy.assertion import SnapshotAssertion
|
||||||
|
|
||||||
from homeassistant.components.button import DOMAIN as BUTTON_DOMAIN, SERVICE_PRESS
|
from homeassistant.components.button import DOMAIN as BUTTON_DOMAIN, SERVICE_PRESS
|
||||||
from homeassistant.const import ATTR_ENTITY_ID, Platform
|
from homeassistant.const import ATTR_ENTITY_ID, Platform
|
||||||
|
@ -4,7 +4,7 @@ from unittest.mock import AsyncMock, patch
|
|||||||
|
|
||||||
from freezegun.api import FrozenDateTimeFactory
|
from freezegun.api import FrozenDateTimeFactory
|
||||||
import pytest
|
import pytest
|
||||||
from syrupy import SnapshotAssertion
|
from syrupy.assertion import SnapshotAssertion
|
||||||
from tesla_fleet_api.exceptions import InvalidCommand, VehicleOffline
|
from tesla_fleet_api.exceptions import InvalidCommand, VehicleOffline
|
||||||
|
|
||||||
from homeassistant.components.climate import (
|
from homeassistant.components.climate import (
|
||||||
@ -196,7 +196,7 @@ async def test_climate_alt(
|
|||||||
hass: HomeAssistant,
|
hass: HomeAssistant,
|
||||||
snapshot: SnapshotAssertion,
|
snapshot: SnapshotAssertion,
|
||||||
entity_registry: er.EntityRegistry,
|
entity_registry: er.EntityRegistry,
|
||||||
mock_vehicle_data,
|
mock_vehicle_data: AsyncMock,
|
||||||
) -> None:
|
) -> None:
|
||||||
"""Tests that the climate entity is correct."""
|
"""Tests that the climate entity is correct."""
|
||||||
|
|
||||||
@ -210,7 +210,7 @@ async def test_climate_offline(
|
|||||||
hass: HomeAssistant,
|
hass: HomeAssistant,
|
||||||
snapshot: SnapshotAssertion,
|
snapshot: SnapshotAssertion,
|
||||||
entity_registry: er.EntityRegistry,
|
entity_registry: er.EntityRegistry,
|
||||||
mock_vehicle_data,
|
mock_vehicle_data: AsyncMock,
|
||||||
) -> None:
|
) -> None:
|
||||||
"""Tests that the climate entity is correct."""
|
"""Tests that the climate entity is correct."""
|
||||||
|
|
||||||
@ -219,7 +219,7 @@ async def test_climate_offline(
|
|||||||
assert_entities(hass, entry.entry_id, entity_registry, snapshot)
|
assert_entities(hass, entry.entry_id, entity_registry, snapshot)
|
||||||
|
|
||||||
|
|
||||||
async def test_invalid_error(hass: HomeAssistant) -> None:
|
async def test_invalid_error(hass: HomeAssistant, snapshot: SnapshotAssertion) -> None:
|
||||||
"""Tests service error is handled."""
|
"""Tests service error is handled."""
|
||||||
|
|
||||||
await setup_platform(hass, platforms=[Platform.CLIMATE])
|
await setup_platform(hass, platforms=[Platform.CLIMATE])
|
||||||
@ -239,10 +239,7 @@ async def test_invalid_error(hass: HomeAssistant) -> None:
|
|||||||
blocking=True,
|
blocking=True,
|
||||||
)
|
)
|
||||||
mock_on.assert_called_once()
|
mock_on.assert_called_once()
|
||||||
assert (
|
assert str(error.value) == snapshot(name="error")
|
||||||
str(error.value)
|
|
||||||
== "Teslemetry command failed, The data request or command is unknown."
|
|
||||||
)
|
|
||||||
|
|
||||||
|
|
||||||
@pytest.mark.parametrize("response", COMMAND_ERRORS)
|
@pytest.mark.parametrize("response", COMMAND_ERRORS)
|
||||||
@ -291,10 +288,11 @@ async def test_ignored_error(
|
|||||||
@pytest.mark.usefixtures("entity_registry_enabled_by_default")
|
@pytest.mark.usefixtures("entity_registry_enabled_by_default")
|
||||||
async def test_asleep_or_offline(
|
async def test_asleep_or_offline(
|
||||||
hass: HomeAssistant,
|
hass: HomeAssistant,
|
||||||
mock_vehicle_data,
|
mock_vehicle_data: AsyncMock,
|
||||||
mock_wake_up,
|
mock_wake_up: AsyncMock,
|
||||||
mock_vehicle,
|
mock_vehicle: AsyncMock,
|
||||||
freezer: FrozenDateTimeFactory,
|
freezer: FrozenDateTimeFactory,
|
||||||
|
snapshot: SnapshotAssertion,
|
||||||
) -> None:
|
) -> None:
|
||||||
"""Tests asleep is handled."""
|
"""Tests asleep is handled."""
|
||||||
|
|
||||||
@ -320,7 +318,7 @@ async def test_asleep_or_offline(
|
|||||||
{ATTR_ENTITY_ID: [entity_id]},
|
{ATTR_ENTITY_ID: [entity_id]},
|
||||||
blocking=True,
|
blocking=True,
|
||||||
)
|
)
|
||||||
assert str(error.value) == "The data request or command is unknown."
|
assert str(error.value) == snapshot(name="InvalidCommand")
|
||||||
mock_wake_up.assert_called_once()
|
mock_wake_up.assert_called_once()
|
||||||
|
|
||||||
mock_wake_up.side_effect = None
|
mock_wake_up.side_effect = None
|
||||||
@ -339,7 +337,7 @@ async def test_asleep_or_offline(
|
|||||||
{ATTR_ENTITY_ID: [entity_id]},
|
{ATTR_ENTITY_ID: [entity_id]},
|
||||||
blocking=True,
|
blocking=True,
|
||||||
)
|
)
|
||||||
assert str(error.value) == "Could not wake up vehicle"
|
assert str(error.value) == snapshot(name="HomeAssistantError")
|
||||||
mock_wake_up.assert_called_once()
|
mock_wake_up.assert_called_once()
|
||||||
mock_vehicle.assert_called()
|
mock_vehicle.assert_called()
|
||||||
|
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
"""Test the Teslemetry config flow."""
|
"""Test the Teslemetry config flow."""
|
||||||
|
|
||||||
from unittest.mock import patch
|
from unittest.mock import AsyncMock, patch
|
||||||
|
|
||||||
from aiohttp import ClientConnectionError
|
from aiohttp import ClientConnectionError
|
||||||
import pytest
|
import pytest
|
||||||
@ -60,7 +60,10 @@ async def test_form(
|
|||||||
],
|
],
|
||||||
)
|
)
|
||||||
async def test_form_errors(
|
async def test_form_errors(
|
||||||
hass: HomeAssistant, side_effect, error, mock_metadata
|
hass: HomeAssistant,
|
||||||
|
side_effect: TeslaFleetError,
|
||||||
|
error: dict[str, str],
|
||||||
|
mock_metadata: AsyncMock,
|
||||||
) -> None:
|
) -> None:
|
||||||
"""Test errors are handled."""
|
"""Test errors are handled."""
|
||||||
|
|
||||||
@ -86,7 +89,7 @@ async def test_form_errors(
|
|||||||
assert result3["type"] is FlowResultType.CREATE_ENTRY
|
assert result3["type"] is FlowResultType.CREATE_ENTRY
|
||||||
|
|
||||||
|
|
||||||
async def test_reauth(hass: HomeAssistant, mock_metadata) -> None:
|
async def test_reauth(hass: HomeAssistant, mock_metadata: AsyncMock) -> None:
|
||||||
"""Test reauth flow."""
|
"""Test reauth flow."""
|
||||||
|
|
||||||
mock_entry = MockConfigEntry(
|
mock_entry = MockConfigEntry(
|
||||||
@ -127,7 +130,10 @@ async def test_reauth(hass: HomeAssistant, mock_metadata) -> None:
|
|||||||
],
|
],
|
||||||
)
|
)
|
||||||
async def test_reauth_errors(
|
async def test_reauth_errors(
|
||||||
hass: HomeAssistant, mock_metadata, side_effect, error
|
hass: HomeAssistant,
|
||||||
|
mock_metadata: AsyncMock,
|
||||||
|
side_effect: TeslaFleetError,
|
||||||
|
error: dict[str, str],
|
||||||
) -> None:
|
) -> None:
|
||||||
"""Test reauth flows that fail."""
|
"""Test reauth flows that fail."""
|
||||||
|
|
||||||
@ -178,7 +184,7 @@ async def test_unique_id_abort(
|
|||||||
assert result2["type"] is FlowResultType.ABORT
|
assert result2["type"] is FlowResultType.ABORT
|
||||||
|
|
||||||
|
|
||||||
async def test_migrate_from_1_1(hass: HomeAssistant, mock_metadata) -> None:
|
async def test_migrate_from_1_1(hass: HomeAssistant, mock_metadata: AsyncMock) -> None:
|
||||||
"""Test config migration."""
|
"""Test config migration."""
|
||||||
|
|
||||||
mock_entry = MockConfigEntry(
|
mock_entry = MockConfigEntry(
|
||||||
@ -199,7 +205,9 @@ async def test_migrate_from_1_1(hass: HomeAssistant, mock_metadata) -> None:
|
|||||||
assert entry.unique_id == METADATA["uid"]
|
assert entry.unique_id == METADATA["uid"]
|
||||||
|
|
||||||
|
|
||||||
async def test_migrate_error_from_1_1(hass: HomeAssistant, mock_metadata) -> None:
|
async def test_migrate_error_from_1_1(
|
||||||
|
hass: HomeAssistant, mock_metadata: AsyncMock
|
||||||
|
) -> None:
|
||||||
"""Test config migration handles errors."""
|
"""Test config migration handles errors."""
|
||||||
|
|
||||||
mock_metadata.side_effect = TeslaFleetError
|
mock_metadata.side_effect = TeslaFleetError
|
||||||
@ -220,7 +228,9 @@ async def test_migrate_error_from_1_1(hass: HomeAssistant, mock_metadata) -> Non
|
|||||||
assert entry.state is ConfigEntryState.MIGRATION_ERROR
|
assert entry.state is ConfigEntryState.MIGRATION_ERROR
|
||||||
|
|
||||||
|
|
||||||
async def test_migrate_error_from_future(hass: HomeAssistant, mock_metadata) -> None:
|
async def test_migrate_error_from_future(
|
||||||
|
hass: HomeAssistant, mock_metadata: AsyncMock
|
||||||
|
) -> None:
|
||||||
"""Test a future version isn't migrated."""
|
"""Test a future version isn't migrated."""
|
||||||
|
|
||||||
mock_metadata.side_effect = TeslaFleetError
|
mock_metadata.side_effect = TeslaFleetError
|
||||||
|
@ -1,9 +1,9 @@
|
|||||||
"""Test the Teslemetry cover platform."""
|
"""Test the Teslemetry cover platform."""
|
||||||
|
|
||||||
from unittest.mock import patch
|
from unittest.mock import AsyncMock, patch
|
||||||
|
|
||||||
import pytest
|
import pytest
|
||||||
from syrupy import SnapshotAssertion
|
from syrupy.assertion import SnapshotAssertion
|
||||||
from tesla_fleet_api.exceptions import VehicleOffline
|
from tesla_fleet_api.exceptions import VehicleOffline
|
||||||
|
|
||||||
from homeassistant.components.cover import (
|
from homeassistant.components.cover import (
|
||||||
@ -43,7 +43,7 @@ async def test_cover_alt(
|
|||||||
hass: HomeAssistant,
|
hass: HomeAssistant,
|
||||||
snapshot: SnapshotAssertion,
|
snapshot: SnapshotAssertion,
|
||||||
entity_registry: er.EntityRegistry,
|
entity_registry: er.EntityRegistry,
|
||||||
mock_vehicle_data,
|
mock_vehicle_data: AsyncMock,
|
||||||
) -> None:
|
) -> None:
|
||||||
"""Tests that the cover entities are correct with alternate values."""
|
"""Tests that the cover entities are correct with alternate values."""
|
||||||
|
|
||||||
@ -57,7 +57,7 @@ async def test_cover_noscope(
|
|||||||
hass: HomeAssistant,
|
hass: HomeAssistant,
|
||||||
snapshot: SnapshotAssertion,
|
snapshot: SnapshotAssertion,
|
||||||
entity_registry: er.EntityRegistry,
|
entity_registry: er.EntityRegistry,
|
||||||
mock_metadata,
|
mock_metadata: AsyncMock,
|
||||||
) -> None:
|
) -> None:
|
||||||
"""Tests that the cover entities are correct without scopes."""
|
"""Tests that the cover entities are correct without scopes."""
|
||||||
|
|
||||||
@ -68,7 +68,7 @@ async def test_cover_noscope(
|
|||||||
|
|
||||||
async def test_cover_offline(
|
async def test_cover_offline(
|
||||||
hass: HomeAssistant,
|
hass: HomeAssistant,
|
||||||
mock_vehicle_data,
|
mock_vehicle_data: AsyncMock,
|
||||||
) -> None:
|
) -> None:
|
||||||
"""Tests that the cover entities are correct when offline."""
|
"""Tests that the cover entities are correct when offline."""
|
||||||
|
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
"""Test the Teslemetry device tracker platform."""
|
"""Test the Teslemetry device tracker platform."""
|
||||||
|
|
||||||
from syrupy import SnapshotAssertion
|
from syrupy.assertion import SnapshotAssertion
|
||||||
from tesla_fleet_api.exceptions import VehicleOffline
|
from tesla_fleet_api.exceptions import VehicleOffline
|
||||||
|
|
||||||
from homeassistant.const import STATE_UNKNOWN, Platform
|
from homeassistant.const import STATE_UNKNOWN, Platform
|
||||||
|
@ -4,7 +4,7 @@ from unittest.mock import AsyncMock
|
|||||||
|
|
||||||
from freezegun.api import FrozenDateTimeFactory
|
from freezegun.api import FrozenDateTimeFactory
|
||||||
import pytest
|
import pytest
|
||||||
from syrupy import SnapshotAssertion
|
from syrupy.assertion import SnapshotAssertion
|
||||||
from tesla_fleet_api.exceptions import (
|
from tesla_fleet_api.exceptions import (
|
||||||
InvalidToken,
|
InvalidToken,
|
||||||
SubscriptionRequired,
|
SubscriptionRequired,
|
||||||
@ -48,7 +48,10 @@ async def test_load_unload(hass: HomeAssistant) -> None:
|
|||||||
|
|
||||||
@pytest.mark.parametrize(("side_effect", "state"), ERRORS)
|
@pytest.mark.parametrize(("side_effect", "state"), ERRORS)
|
||||||
async def test_init_error(
|
async def test_init_error(
|
||||||
hass: HomeAssistant, mock_products, side_effect, state
|
hass: HomeAssistant,
|
||||||
|
mock_products: AsyncMock,
|
||||||
|
side_effect: TeslaFleetError,
|
||||||
|
state: ConfigEntryState,
|
||||||
) -> None:
|
) -> None:
|
||||||
"""Test init with errors."""
|
"""Test init with errors."""
|
||||||
|
|
||||||
@ -86,7 +89,7 @@ async def test_vehicle_refresh_asleep(
|
|||||||
|
|
||||||
|
|
||||||
async def test_vehicle_refresh_offline(
|
async def test_vehicle_refresh_offline(
|
||||||
hass: HomeAssistant, mock_vehicle_data, freezer: FrozenDateTimeFactory
|
hass: HomeAssistant, mock_vehicle_data: AsyncMock, freezer: FrozenDateTimeFactory
|
||||||
) -> None:
|
) -> None:
|
||||||
"""Test coordinator refresh with an error."""
|
"""Test coordinator refresh with an error."""
|
||||||
entry = await setup_platform(hass, [Platform.CLIMATE])
|
entry = await setup_platform(hass, [Platform.CLIMATE])
|
||||||
@ -103,7 +106,10 @@ async def test_vehicle_refresh_offline(
|
|||||||
|
|
||||||
@pytest.mark.parametrize(("side_effect", "state"), ERRORS)
|
@pytest.mark.parametrize(("side_effect", "state"), ERRORS)
|
||||||
async def test_vehicle_refresh_error(
|
async def test_vehicle_refresh_error(
|
||||||
hass: HomeAssistant, mock_vehicle_data, side_effect, state
|
hass: HomeAssistant,
|
||||||
|
mock_vehicle_data: AsyncMock,
|
||||||
|
side_effect: TeslaFleetError,
|
||||||
|
state: ConfigEntryState,
|
||||||
) -> None:
|
) -> None:
|
||||||
"""Test coordinator refresh with an error."""
|
"""Test coordinator refresh with an error."""
|
||||||
mock_vehicle_data.side_effect = side_effect
|
mock_vehicle_data.side_effect = side_effect
|
||||||
@ -112,7 +118,7 @@ async def test_vehicle_refresh_error(
|
|||||||
|
|
||||||
|
|
||||||
async def test_vehicle_sleep(
|
async def test_vehicle_sleep(
|
||||||
hass: HomeAssistant, mock_vehicle_data, freezer: FrozenDateTimeFactory
|
hass: HomeAssistant, mock_vehicle_data: AsyncMock, freezer: FrozenDateTimeFactory
|
||||||
) -> None:
|
) -> None:
|
||||||
"""Test coordinator refresh with an error."""
|
"""Test coordinator refresh with an error."""
|
||||||
await setup_platform(hass, [Platform.CLIMATE])
|
await setup_platform(hass, [Platform.CLIMATE])
|
||||||
@ -171,7 +177,10 @@ async def test_vehicle_sleep(
|
|||||||
# Test Energy Live Coordinator
|
# Test Energy Live Coordinator
|
||||||
@pytest.mark.parametrize(("side_effect", "state"), ERRORS)
|
@pytest.mark.parametrize(("side_effect", "state"), ERRORS)
|
||||||
async def test_energy_live_refresh_error(
|
async def test_energy_live_refresh_error(
|
||||||
hass: HomeAssistant, mock_live_status, side_effect, state
|
hass: HomeAssistant,
|
||||||
|
mock_live_status: AsyncMock,
|
||||||
|
side_effect: TeslaFleetError,
|
||||||
|
state: ConfigEntryState,
|
||||||
) -> None:
|
) -> None:
|
||||||
"""Test coordinator refresh with an error."""
|
"""Test coordinator refresh with an error."""
|
||||||
mock_live_status.side_effect = side_effect
|
mock_live_status.side_effect = side_effect
|
||||||
@ -182,7 +191,10 @@ async def test_energy_live_refresh_error(
|
|||||||
# Test Energy Site Coordinator
|
# Test Energy Site Coordinator
|
||||||
@pytest.mark.parametrize(("side_effect", "state"), ERRORS)
|
@pytest.mark.parametrize(("side_effect", "state"), ERRORS)
|
||||||
async def test_energy_site_refresh_error(
|
async def test_energy_site_refresh_error(
|
||||||
hass: HomeAssistant, mock_site_info, side_effect, state
|
hass: HomeAssistant,
|
||||||
|
mock_site_info: AsyncMock,
|
||||||
|
side_effect: TeslaFleetError,
|
||||||
|
state: ConfigEntryState,
|
||||||
) -> None:
|
) -> None:
|
||||||
"""Test coordinator refresh with an error."""
|
"""Test coordinator refresh with an error."""
|
||||||
mock_site_info.side_effect = side_effect
|
mock_site_info.side_effect = side_effect
|
||||||
|
@ -1,9 +1,9 @@
|
|||||||
"""Test the Teslemetry lock platform."""
|
"""Test the Teslemetry lock platform."""
|
||||||
|
|
||||||
from unittest.mock import patch
|
from unittest.mock import AsyncMock, patch
|
||||||
|
|
||||||
import pytest
|
import pytest
|
||||||
from syrupy import SnapshotAssertion
|
from syrupy.assertion import SnapshotAssertion
|
||||||
from tesla_fleet_api.exceptions import VehicleOffline
|
from tesla_fleet_api.exceptions import VehicleOffline
|
||||||
|
|
||||||
from homeassistant.components.lock import (
|
from homeassistant.components.lock import (
|
||||||
@ -34,7 +34,7 @@ async def test_lock(
|
|||||||
|
|
||||||
async def test_lock_offline(
|
async def test_lock_offline(
|
||||||
hass: HomeAssistant,
|
hass: HomeAssistant,
|
||||||
mock_vehicle_data,
|
mock_vehicle_data: AsyncMock,
|
||||||
) -> None:
|
) -> None:
|
||||||
"""Tests that the lock entities are correct when offline."""
|
"""Tests that the lock entities are correct when offline."""
|
||||||
|
|
||||||
|
@ -1,8 +1,8 @@
|
|||||||
"""Test the Teslemetry media player platform."""
|
"""Test the Teslemetry media player platform."""
|
||||||
|
|
||||||
from unittest.mock import patch
|
from unittest.mock import AsyncMock, patch
|
||||||
|
|
||||||
from syrupy import SnapshotAssertion
|
from syrupy.assertion import SnapshotAssertion
|
||||||
from tesla_fleet_api.exceptions import VehicleOffline
|
from tesla_fleet_api.exceptions import VehicleOffline
|
||||||
|
|
||||||
from homeassistant.components.media_player import (
|
from homeassistant.components.media_player import (
|
||||||
@ -38,7 +38,7 @@ async def test_media_player_alt(
|
|||||||
hass: HomeAssistant,
|
hass: HomeAssistant,
|
||||||
snapshot: SnapshotAssertion,
|
snapshot: SnapshotAssertion,
|
||||||
entity_registry: er.EntityRegistry,
|
entity_registry: er.EntityRegistry,
|
||||||
mock_vehicle_data,
|
mock_vehicle_data: AsyncMock,
|
||||||
) -> None:
|
) -> None:
|
||||||
"""Tests that the media player entities are correct."""
|
"""Tests that the media player entities are correct."""
|
||||||
|
|
||||||
@ -49,7 +49,7 @@ async def test_media_player_alt(
|
|||||||
|
|
||||||
async def test_media_player_offline(
|
async def test_media_player_offline(
|
||||||
hass: HomeAssistant,
|
hass: HomeAssistant,
|
||||||
mock_vehicle_data,
|
mock_vehicle_data: AsyncMock,
|
||||||
) -> None:
|
) -> None:
|
||||||
"""Tests that the media player entities are correct when offline."""
|
"""Tests that the media player entities are correct when offline."""
|
||||||
|
|
||||||
@ -63,7 +63,7 @@ async def test_media_player_noscope(
|
|||||||
hass: HomeAssistant,
|
hass: HomeAssistant,
|
||||||
snapshot: SnapshotAssertion,
|
snapshot: SnapshotAssertion,
|
||||||
entity_registry: er.EntityRegistry,
|
entity_registry: er.EntityRegistry,
|
||||||
mock_metadata,
|
mock_metadata: AsyncMock,
|
||||||
) -> None:
|
) -> None:
|
||||||
"""Tests that the media player entities are correct without required scope."""
|
"""Tests that the media player entities are correct without required scope."""
|
||||||
|
|
||||||
|
@ -1,9 +1,9 @@
|
|||||||
"""Test the Teslemetry number platform."""
|
"""Test the Teslemetry number platform."""
|
||||||
|
|
||||||
from unittest.mock import patch
|
from unittest.mock import AsyncMock, patch
|
||||||
|
|
||||||
import pytest
|
import pytest
|
||||||
from syrupy import SnapshotAssertion
|
from syrupy.assertion import SnapshotAssertion
|
||||||
from tesla_fleet_api.exceptions import VehicleOffline
|
from tesla_fleet_api.exceptions import VehicleOffline
|
||||||
|
|
||||||
from homeassistant.components.number import (
|
from homeassistant.components.number import (
|
||||||
@ -33,7 +33,7 @@ async def test_number(
|
|||||||
|
|
||||||
async def test_number_offline(
|
async def test_number_offline(
|
||||||
hass: HomeAssistant,
|
hass: HomeAssistant,
|
||||||
mock_vehicle_data,
|
mock_vehicle_data: AsyncMock,
|
||||||
) -> None:
|
) -> None:
|
||||||
"""Tests that the number entities are correct when offline."""
|
"""Tests that the number entities are correct when offline."""
|
||||||
|
|
||||||
@ -44,7 +44,9 @@ async def test_number_offline(
|
|||||||
|
|
||||||
|
|
||||||
@pytest.mark.usefixtures("entity_registry_enabled_by_default")
|
@pytest.mark.usefixtures("entity_registry_enabled_by_default")
|
||||||
async def test_number_services(hass: HomeAssistant, mock_vehicle_data) -> None:
|
async def test_number_services(
|
||||||
|
hass: HomeAssistant, mock_vehicle_data: AsyncMock
|
||||||
|
) -> None:
|
||||||
"""Tests that the number services work."""
|
"""Tests that the number services work."""
|
||||||
mock_vehicle_data.return_value = VEHICLE_DATA_ALT
|
mock_vehicle_data.return_value = VEHICLE_DATA_ALT
|
||||||
await setup_platform(hass, [Platform.NUMBER])
|
await setup_platform(hass, [Platform.NUMBER])
|
||||||
|
@ -1,9 +1,9 @@
|
|||||||
"""Test the Teslemetry select platform."""
|
"""Test the Teslemetry select platform."""
|
||||||
|
|
||||||
from unittest.mock import patch
|
from unittest.mock import AsyncMock, patch
|
||||||
|
|
||||||
import pytest
|
import pytest
|
||||||
from syrupy import SnapshotAssertion
|
from syrupy.assertion import SnapshotAssertion
|
||||||
from tesla_fleet_api.const import EnergyExportMode, EnergyOperationMode
|
from tesla_fleet_api.const import EnergyExportMode, EnergyOperationMode
|
||||||
from tesla_fleet_api.exceptions import VehicleOffline
|
from tesla_fleet_api.exceptions import VehicleOffline
|
||||||
|
|
||||||
@ -35,7 +35,7 @@ async def test_select(
|
|||||||
|
|
||||||
async def test_select_offline(
|
async def test_select_offline(
|
||||||
hass: HomeAssistant,
|
hass: HomeAssistant,
|
||||||
mock_vehicle_data,
|
mock_vehicle_data: AsyncMock,
|
||||||
) -> None:
|
) -> None:
|
||||||
"""Tests that the select entities are correct when offline."""
|
"""Tests that the select entities are correct when offline."""
|
||||||
|
|
||||||
|
@ -1,8 +1,10 @@
|
|||||||
"""Test the Teslemetry sensor platform."""
|
"""Test the Teslemetry sensor platform."""
|
||||||
|
|
||||||
|
from unittest.mock import AsyncMock
|
||||||
|
|
||||||
from freezegun.api import FrozenDateTimeFactory
|
from freezegun.api import FrozenDateTimeFactory
|
||||||
import pytest
|
import pytest
|
||||||
from syrupy import SnapshotAssertion
|
from syrupy.assertion import SnapshotAssertion
|
||||||
|
|
||||||
from homeassistant.components.teslemetry.coordinator import VEHICLE_INTERVAL
|
from homeassistant.components.teslemetry.coordinator import VEHICLE_INTERVAL
|
||||||
from homeassistant.const import Platform
|
from homeassistant.const import Platform
|
||||||
@ -21,7 +23,7 @@ async def test_sensors(
|
|||||||
snapshot: SnapshotAssertion,
|
snapshot: SnapshotAssertion,
|
||||||
entity_registry: er.EntityRegistry,
|
entity_registry: er.EntityRegistry,
|
||||||
freezer: FrozenDateTimeFactory,
|
freezer: FrozenDateTimeFactory,
|
||||||
mock_vehicle_data,
|
mock_vehicle_data: AsyncMock,
|
||||||
) -> None:
|
) -> None:
|
||||||
"""Tests that the sensor entities are correct."""
|
"""Tests that the sensor entities are correct."""
|
||||||
|
|
||||||
|
@ -1,9 +1,9 @@
|
|||||||
"""Test the Teslemetry switch platform."""
|
"""Test the Teslemetry switch platform."""
|
||||||
|
|
||||||
from unittest.mock import patch
|
from unittest.mock import AsyncMock, patch
|
||||||
|
|
||||||
import pytest
|
import pytest
|
||||||
from syrupy import SnapshotAssertion
|
from syrupy.assertion import SnapshotAssertion
|
||||||
from tesla_fleet_api.exceptions import VehicleOffline
|
from tesla_fleet_api.exceptions import VehicleOffline
|
||||||
|
|
||||||
from homeassistant.components.switch import (
|
from homeassistant.components.switch import (
|
||||||
@ -40,7 +40,7 @@ async def test_switch_alt(
|
|||||||
hass: HomeAssistant,
|
hass: HomeAssistant,
|
||||||
snapshot: SnapshotAssertion,
|
snapshot: SnapshotAssertion,
|
||||||
entity_registry: er.EntityRegistry,
|
entity_registry: er.EntityRegistry,
|
||||||
mock_vehicle_data,
|
mock_vehicle_data: AsyncMock,
|
||||||
) -> None:
|
) -> None:
|
||||||
"""Tests that the switch entities are correct."""
|
"""Tests that the switch entities are correct."""
|
||||||
|
|
||||||
@ -51,7 +51,7 @@ async def test_switch_alt(
|
|||||||
|
|
||||||
async def test_switch_offline(
|
async def test_switch_offline(
|
||||||
hass: HomeAssistant,
|
hass: HomeAssistant,
|
||||||
mock_vehicle_data,
|
mock_vehicle_data: AsyncMock,
|
||||||
) -> None:
|
) -> None:
|
||||||
"""Tests that the switch entities are correct when offline."""
|
"""Tests that the switch entities are correct when offline."""
|
||||||
|
|
||||||
|
@ -1,10 +1,10 @@
|
|||||||
"""Test the Teslemetry update platform."""
|
"""Test the Teslemetry update platform."""
|
||||||
|
|
||||||
import copy
|
import copy
|
||||||
from unittest.mock import patch
|
from unittest.mock import AsyncMock, patch
|
||||||
|
|
||||||
from freezegun.api import FrozenDateTimeFactory
|
from freezegun.api import FrozenDateTimeFactory
|
||||||
from syrupy import SnapshotAssertion
|
from syrupy.assertion import SnapshotAssertion
|
||||||
from tesla_fleet_api.exceptions import VehicleOffline
|
from tesla_fleet_api.exceptions import VehicleOffline
|
||||||
|
|
||||||
from homeassistant.components.teslemetry.coordinator import VEHICLE_INTERVAL
|
from homeassistant.components.teslemetry.coordinator import VEHICLE_INTERVAL
|
||||||
@ -35,7 +35,7 @@ async def test_update_alt(
|
|||||||
hass: HomeAssistant,
|
hass: HomeAssistant,
|
||||||
snapshot: SnapshotAssertion,
|
snapshot: SnapshotAssertion,
|
||||||
entity_registry: er.EntityRegistry,
|
entity_registry: er.EntityRegistry,
|
||||||
mock_vehicle_data,
|
mock_vehicle_data: AsyncMock,
|
||||||
) -> None:
|
) -> None:
|
||||||
"""Tests that the update entities are correct."""
|
"""Tests that the update entities are correct."""
|
||||||
|
|
||||||
@ -46,7 +46,7 @@ async def test_update_alt(
|
|||||||
|
|
||||||
async def test_update_offline(
|
async def test_update_offline(
|
||||||
hass: HomeAssistant,
|
hass: HomeAssistant,
|
||||||
mock_vehicle_data,
|
mock_vehicle_data: AsyncMock,
|
||||||
) -> None:
|
) -> None:
|
||||||
"""Tests that the update entities are correct when offline."""
|
"""Tests that the update entities are correct when offline."""
|
||||||
|
|
||||||
@ -58,7 +58,7 @@ async def test_update_offline(
|
|||||||
|
|
||||||
async def test_update_services(
|
async def test_update_services(
|
||||||
hass: HomeAssistant,
|
hass: HomeAssistant,
|
||||||
mock_vehicle_data,
|
mock_vehicle_data: AsyncMock,
|
||||||
freezer: FrozenDateTimeFactory,
|
freezer: FrozenDateTimeFactory,
|
||||||
snapshot: SnapshotAssertion,
|
snapshot: SnapshotAssertion,
|
||||||
) -> None:
|
) -> None:
|
||||||
|
Loading…
x
Reference in New Issue
Block a user