99 lines
3.2 KiB
Python
99 lines
3.2 KiB
Python
"""Teslemetry Data Coordinator."""
|
|
from datetime import timedelta
|
|
from typing import Any
|
|
|
|
from tesla_fleet_api import EnergySpecific, VehicleSpecific
|
|
from tesla_fleet_api.exceptions import TeslaFleetError, VehicleOffline
|
|
|
|
from homeassistant.core import HomeAssistant
|
|
from homeassistant.exceptions import ConfigEntryNotReady
|
|
from homeassistant.helpers.update_coordinator import DataUpdateCoordinator, UpdateFailed
|
|
|
|
from .const import LOGGER, TeslemetryState
|
|
|
|
SYNC_INTERVAL = 60
|
|
|
|
|
|
class TeslemetryDataCoordinator(DataUpdateCoordinator[dict[str, Any]]):
|
|
"""Base class for Teslemetry Data Coordinators."""
|
|
|
|
name: str
|
|
|
|
def __init__(
|
|
self, hass: HomeAssistant, api: VehicleSpecific | EnergySpecific
|
|
) -> None:
|
|
"""Initialize Teslemetry Vehicle Update Coordinator."""
|
|
super().__init__(
|
|
hass,
|
|
LOGGER,
|
|
name=self.name,
|
|
update_interval=timedelta(seconds=SYNC_INTERVAL),
|
|
)
|
|
self.api = api
|
|
|
|
|
|
class TeslemetryVehicleDataCoordinator(TeslemetryDataCoordinator):
|
|
"""Class to manage fetching data from the Teslemetry API."""
|
|
|
|
name = "Teslemetry Vehicle"
|
|
|
|
async def async_config_entry_first_refresh(self) -> None:
|
|
"""Perform first refresh."""
|
|
try:
|
|
response = await self.api.wake_up()
|
|
if response["response"]["state"] != TeslemetryState.ONLINE:
|
|
# The first refresh will fail, so retry later
|
|
raise ConfigEntryNotReady("Vehicle is not online")
|
|
except TeslaFleetError as e:
|
|
# The first refresh will also fail, so retry later
|
|
raise ConfigEntryNotReady from e
|
|
await super().async_config_entry_first_refresh()
|
|
|
|
async def _async_update_data(self) -> dict[str, Any]:
|
|
"""Update vehicle data using Teslemetry API."""
|
|
|
|
try:
|
|
data = await self.api.vehicle_data()
|
|
except VehicleOffline:
|
|
self.data["state"] = TeslemetryState.OFFLINE
|
|
return self.data
|
|
except TeslaFleetError as e:
|
|
raise UpdateFailed(e.message) from e
|
|
|
|
return self._flatten(data["response"])
|
|
|
|
def _flatten(
|
|
self, data: dict[str, Any], parent: str | None = None
|
|
) -> dict[str, Any]:
|
|
"""Flatten the data structure."""
|
|
result = {}
|
|
for key, value in data.items():
|
|
if parent:
|
|
key = f"{parent}_{key}"
|
|
if isinstance(value, dict):
|
|
result.update(self._flatten(value, key))
|
|
else:
|
|
result[key] = value
|
|
return result
|
|
|
|
|
|
class TeslemetryEnergyDataCoordinator(TeslemetryDataCoordinator):
|
|
"""Class to manage fetching data from the Teslemetry API."""
|
|
|
|
name = "Teslemetry Energy Site"
|
|
|
|
async def _async_update_data(self) -> dict[str, Any]:
|
|
"""Update energy site data using Teslemetry API."""
|
|
|
|
try:
|
|
data = await self.api.live_status()
|
|
except TeslaFleetError as e:
|
|
raise UpdateFailed(e.message) from e
|
|
|
|
# Convert Wall Connectors from array to dict
|
|
data["response"]["wall_connectors"] = {
|
|
wc["din"]: wc for wc in data["response"].get("wall_connectors", [])
|
|
}
|
|
|
|
return data["response"]
|