Skip to content

Commit

Permalink
Merge branch 'main' into release/1.9.0
Browse files Browse the repository at this point in the history
  • Loading branch information
jschlyter committed Nov 11, 2024
2 parents 244f99d + e78b9f9 commit e5efb4d
Show file tree
Hide file tree
Showing 6 changed files with 34 additions and 74 deletions.
1 change: 0 additions & 1 deletion custom_components/polestar_api/const.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,6 @@
DOMAIN = "polestar_api"
TIMEOUT = 90

CACHE_TIME = 600
DEFAULT_SCAN_INTERVAL = timedelta(seconds=60)

CONF_VIN: Final[str] = "vin"
1 change: 0 additions & 1 deletion custom_components/polestar_api/image.py
Original file line number Diff line number Diff line change
Expand Up @@ -86,7 +86,6 @@ async def async_update_image_url(self) -> None:
value = self.car.get_value(
query=self.entity_description.query,
field_name=self.entity_description.field_name,
skip_cache=True,
)
if value is None:
_LOGGER.debug("No image URL found")
Expand Down
14 changes: 5 additions & 9 deletions custom_components/polestar_api/polestar.py
Original file line number Diff line number Diff line change
Expand Up @@ -53,12 +53,6 @@ def get_device_info(self) -> DeviceInfo:
serial_number=self.vin,
)

def get_latest_data(self, query: str, field_name: str):
"""Get the latest data from the Polestar API."""
return self.polestar_api.get_latest_data(
vin=self.vin, query=query, field_name=field_name
)

async def async_update(self) -> None:
"""Update data from Polestar."""
try:
Expand All @@ -85,10 +79,12 @@ async def async_update(self) -> None:
self.polestar_api.next_update = datetime.now() + timedelta(seconds=60)
self.polestar_api.latest_call_code_v2 = 500

def get_value(self, query: str, field_name: str, skip_cache: bool = False):
def get_value(self, query: str, field_name: str):
"""Get the latest value from the Polestar API."""
data = self.polestar_api.get_cache_data(
vin=self.vin, query=query, field_name=field_name, skip_cache=skip_cache
if query is None or field_name is None:
return None
data = self.polestar_api.get_latest_data(
vin=self.vin, query=query, field_name=field_name
)
if data is None:
# if amp and voltage can be null, so we will return 0
Expand Down
2 changes: 0 additions & 2 deletions custom_components/polestar_api/pypolestar/const.py
Original file line number Diff line number Diff line change
@@ -1,7 +1,5 @@
"""Constants for Polestar."""

CACHE_TIME = 30

CAR_INFO_DATA = "getConsumerCarsV2"
ODO_METER_DATA = "getOdometerData"
BATTERY_DATA = "getBatteryData"
Expand Down
75 changes: 27 additions & 48 deletions custom_components/polestar_api/pypolestar/polestar.py
Original file line number Diff line number Diff line change
Expand Up @@ -11,14 +11,7 @@
from graphql import DocumentNode

from .auth import PolestarAuth
from .const import (
BASE_URL,
BASE_URL_V2,
BATTERY_DATA,
CACHE_TIME,
CAR_INFO_DATA,
ODO_METER_DATA,
)
from .const import BASE_URL, BASE_URL_V2, BATTERY_DATA, CAR_INFO_DATA, ODO_METER_DATA
from .exception import (
PolestarApiException,
PolestarAuthException,
Expand Down Expand Up @@ -55,9 +48,7 @@ def __init__(
self.latest_call_code = None
self.latest_call_code_2 = None
self.next_update = None
self.car_data_by_vin: dict[str, dict] = {}
self.cache_data_by_vin: dict[str, dict] = defaultdict(dict)
self.cache_ttl = timedelta(seconds=CACHE_TIME)
self.data_by_vin: dict[str, dict] = defaultdict(dict)
self.next_update_delay = timedelta(seconds=5)
self.configured_vins = set(vins) if vins else None
self.logger = _LOGGER.getChild(unique_id) if unique_id else _LOGGER
Expand All @@ -83,26 +74,33 @@ async def async_init(self, verbose: bool = False) -> None:
vin = data["vin"]
if self.configured_vins and vin not in self.configured_vins:
continue
self.car_data_by_vin[vin] = data
self.cache_data_by_vin[vin][CAR_INFO_DATA] = {
"data": self.car_data_by_vin[vin],
self.data_by_vin[vin][CAR_INFO_DATA] = {
"data": data,
"timestamp": datetime.now(),
}
self.logger.debug("API setup for VIN %s", vin)

@property
def vins(self) -> list[str]:
return list(self.car_data_by_vin.keys())
return list(self.data_by_vin.keys())

def get_latest_data(
self, vin: str, query: str, field_name: str
) -> dict or bool or None:
def get_latest_data(self, vin: str, query: str, field_name: str) -> dict | None:
"""Get the latest data from the Polestar API."""
if self.cache_data_by_vin and self.cache_data_by_vin[vin][query]:
data = self.cache_data_by_vin[vin][query]["data"]
if data is None:
return False
self.logger.debug(
"get_latest_data %s %s %s",
vin,
query,
field_name,
)
query_result = self.data_by_vin[vin].get(query)
if query_result and (data := query_result.get("data")) is not None:
return self._get_field_name_value(field_name, data)
self.logger.debug(
"get_latest_data returning None for %s %s %s",
vin,
query,
field_name,
)
return None

async def get_ev_data(self, vin: str) -> None:
Expand Down Expand Up @@ -152,31 +150,8 @@ async def call_api(func):
t2 = time.perf_counter()
self.logger.debug("Update took %.2f seconds", t2 - t1)

def get_cache_data(
self, vin: str, query: str, field_name: str, skip_cache: bool = False
) -> dict | None:
"""Get the latest data from the cache."""
if query is None:
return None
self.logger.debug(
"get_cache_data %s %s %s%s",
vin,
query,
field_name,
" (skip_cache)" if skip_cache else "",
)
if self.cache_data_by_vin and self.cache_data_by_vin[vin].get(query):
cache_entry = self.cache_data_by_vin[vin][query]
data = cache_entry["data"]
if data is not None and (
skip_cache is True
or cache_entry["timestamp"] + self.cache_ttl > datetime.now()
):
return self._get_field_name_value(field_name, data)
return None

@staticmethod
def _get_field_name_value(field_name: str, data: dict) -> str or bool or None:
def _get_field_name_value(field_name: str, data: dict) -> str | bool | None:
if field_name is None or data is None:
return None

Expand All @@ -203,23 +178,27 @@ async def _get_odometer_data(self, vin: str) -> None:
variable_values={"vin": vin},
)

self.cache_data_by_vin[vin][ODO_METER_DATA] = {
res = self.data_by_vin[vin][ODO_METER_DATA] = {
"data": result[ODO_METER_DATA],
"timestamp": datetime.now(),
}

self.logger.debug("Received odometer data: %s", res)

async def _get_battery_data(self, vin: str) -> None:
result = await self._query_graph_ql(
url=BASE_URL_V2,
query=QUERY_GET_BATTERY_DATA,
variable_values={"vin": vin},
)

self.cache_data_by_vin[vin][BATTERY_DATA] = {
res = self.data_by_vin[vin][BATTERY_DATA] = {
"data": result[BATTERY_DATA],
"timestamp": datetime.now(),
}

self.logger.debug("Received battery data: %s", res)

async def _get_vehicle_data(self, verbose: bool = False) -> dict | None:
"""Get the latest vehicle data from the Polestar API."""
result = await self._query_graph_ql(
Expand Down
15 changes: 2 additions & 13 deletions custom_components/polestar_api/sensor.py
Original file line number Diff line number Diff line change
Expand Up @@ -519,7 +519,6 @@ def __init__(
self._attr_native_value = self.car.get_value(
self.entity_description.query,
self.entity_description.field_name,
self.get_skip_cache(),
)

if entity_description.round_digits is not None:
Expand All @@ -532,21 +531,12 @@ def __init__(
if self.car is not None and self.car.get_latest_call_code() == 200:
self._async_update_attrs()

def get_skip_cache(self) -> bool:
"""Get the skip cache."""
return self.entity_description.key in (
"vin",
"registration_number",
"model_name",
)

@callback
def _async_update_attrs(self) -> None:
"""Update the state and attributes."""
self._sensor_data = self.car.get_value(
self.entity_description.query,
self.entity_description.field_name,
self.get_skip_cache(),
)

@property
Expand Down Expand Up @@ -592,10 +582,10 @@ def state(self) -> StateType:
return None

if self.entity_description.key in ("estimate_full_charge_range"):
battery_level = self.car.get_latest_data(
battery_level = self.car.get_value(
self.entity_description.query, "batteryChargeLevelPercentage"
)
estimate_range = self.car.get_latest_data(
estimate_range = self.car.get_value(
self.entity_description.query, self.entity_description.field_name
)

Expand Down Expand Up @@ -730,7 +720,6 @@ async def async_update(self) -> None:
value = self.car.get_value(
self.entity_description.query,
self.entity_description.field_name,
self.get_skip_cache(),
)

if value is not None:
Expand Down

0 comments on commit e5efb4d

Please sign in to comment.