From 01aab31a6606ed8ae1b9c606a2f98bd3552a57cc Mon Sep 17 00:00:00 2001 From: Tuen Lee Date: Mon, 27 Nov 2023 23:19:24 +0100 Subject: [PATCH] add status code to know if the api is up or down --- custom_components/polestar_api/config_flow.py | 7 +++++ .../polestar_api/polestar_api.py | 7 +++++ custom_components/polestar_api/sensor.py | 28 ++++++++++++++----- custom_components/polestar_api/strings.json | 3 +- .../polestar_api/translations/en.json | 3 +- 5 files changed, 39 insertions(+), 9 deletions(-) diff --git a/custom_components/polestar_api/config_flow.py b/custom_components/polestar_api/config_flow.py index 978c2eb..a576a92 100644 --- a/custom_components/polestar_api/config_flow.py +++ b/custom_components/polestar_api/config_flow.py @@ -48,6 +48,13 @@ async def _create_device(self, username: str, password: str, vin: str, vcc_api_k ) with timeout(TIMEOUT): await device.init() + + # check if we have a token, otherwise throw exception + if device.access_token is None: + _LOGGER.exception( + "No token, Could be wrong credentials (invalid email or password))") + return self.async_abort(reason="no_token") + except asyncio.TimeoutError: return self.async_abort(reason="api_timeout") except ClientError: diff --git a/custom_components/polestar_api/polestar_api.py b/custom_components/polestar_api/polestar_api.py index e47f56d..29912cc 100644 --- a/custom_components/polestar_api/polestar_api.py +++ b/custom_components/polestar_api/polestar_api.py @@ -41,6 +41,7 @@ def __init__(self, self.vin = vin self.vcc_api_key = vcc_api_key self.cache_data = None + self.latest_call_code = None disable_warnings() async def init(self): @@ -89,6 +90,8 @@ def get_latest_data(self, path: str, reponse_path: str = None) -> dict or bool o def get_cache_data(self, path: str, reponse_path: str = None) -> dict or bool or None: # replace the string {vin} with the actual vin + if path is None: + return None path = path.replace('{vin}', self.vin) if self.cache_data and self.cache_data[path]: @@ -102,6 +105,9 @@ def get_cache_data(self, path: str, reponse_path: str = None) -> dict or bool or return data async def get_data(self, path: str, reponse_path: str = None) -> dict or bool or None: + if path is None: + return None + path = path.replace('{vin}', self.vin) cache_data = self.get_cache_data(path, reponse_path) @@ -130,6 +136,7 @@ async def get_data(self, path: str, reponse_path: str = None) -> dict or bool or headers=headers ) _LOGGER.debug(f"Response {response}") + self.latest_call_code = response.status if response.status == 401: await self.get_token() return diff --git a/custom_components/polestar_api/sensor.py b/custom_components/polestar_api/sensor.py index e98e1c2..9721442 100644 --- a/custom_components/polestar_api/sensor.py +++ b/custom_components/polestar_api/sensor.py @@ -69,6 +69,12 @@ class PolestarSensorDescription( "CHARGING_SYSTEM_FAULT": "Fault", } +API_STATUS_DICT = { + 200: "OK", + 401: "Unauthorized", + 404: "API Down" +} + POLESTAR_SENSOR_TYPES: Final[tuple[PolestarSensorDescription, ...]] = ( PolestarSensorDescription( @@ -184,6 +190,16 @@ class PolestarSensorDescription( round_digits=None, max_value=None, ), + PolestarSensorDescription( + key="api_status_code", + name="API status", + icon="mdi:heart", + path=None, + response_path=None, + unit=None, + round_digits=None, + max_value=None, + ), ) @@ -279,7 +295,11 @@ def native_unit_of_measurement(self) -> str | None: @property def state(self) -> StateType: """Return the state of the sensor.""" - if self._attr_native_value is None: + + if self.entity_description.key == 'api_status_code': + return API_STATUS_DICT.get(self._device.latest_call_code, "Error") + + if self._attr_native_value in (None, False): return None # parse the long text with a shorter one from the dict @@ -338,12 +358,6 @@ def state(self) -> StateType: return estimate_range if self.entity_description.key == 'electric_range_miles': - if self._attr_native_value is None: - return None - - if self._attr_native_value is False: - return None - self._attr_native_value = int(self._attr_native_value) miles = round(self._attr_native_value / 1.609344, self.entity_description.round_digits if self.entity_description.round_digits is not None else 0) diff --git a/custom_components/polestar_api/strings.json b/custom_components/polestar_api/strings.json index a46f505..669f8e3 100644 --- a/custom_components/polestar_api/strings.json +++ b/custom_components/polestar_api/strings.json @@ -16,7 +16,8 @@ "abort": { "api_timeout": "Timeout connecting to the api.", "api_failed": "Unexpected error creating api.", - "already_configured": "Polestar API is already configured" + "already_configured": "Polestar API is already configured", + "no_token": "No token found in response. Please check your credentials." } } } diff --git a/custom_components/polestar_api/translations/en.json b/custom_components/polestar_api/translations/en.json index a46f505..669f8e3 100644 --- a/custom_components/polestar_api/translations/en.json +++ b/custom_components/polestar_api/translations/en.json @@ -16,7 +16,8 @@ "abort": { "api_timeout": "Timeout connecting to the api.", "api_failed": "Unexpected error creating api.", - "already_configured": "Polestar API is already configured" + "already_configured": "Polestar API is already configured", + "no_token": "No token found in response. Please check your credentials." } } }