From 79d1c1dcc676592bec2e5cc50347ad36e6ad4368 Mon Sep 17 00:00:00 2001 From: Simon Hansen <67142049+DurgNomis-drol@users.noreply.github.com> Date: Mon, 4 Oct 2021 13:46:26 +0200 Subject: [PATCH] Add range conversion to miles if car reports in miles (#72) * Add range conversion to miles if car reports in miles * Add missing parameter * Add logging --- .gitignore | 2 +- mytoyota/statistics.py | 19 +++++-------------- mytoyota/status.py | 34 ++++++++++++++++++++++++++++++---- mytoyota/utils.py | 22 ++++++++++++++++++++++ mytoyota/vehicle.py | 16 +++++++++------- 5 files changed, 67 insertions(+), 26 deletions(-) diff --git a/.gitignore b/.gitignore index 8b31ad91..5be292d7 100644 --- a/.gitignore +++ b/.gitignore @@ -129,6 +129,6 @@ dmypy.json .pyre/ -/test.py .myt_app/ tests/ +/blahblah.py diff --git a/mytoyota/statistics.py b/mytoyota/statistics.py index df2712bb..99dad6b1 100644 --- a/mytoyota/statistics.py +++ b/mytoyota/statistics.py @@ -24,6 +24,11 @@ WEEK, YEAR, ) +from mytoyota.utils import ( + convert_to_liter_per_100_miles, + convert_to_miles, + convert_to_mpg, +) _LOGGER: logging.Logger = logging.getLogger(__package__) @@ -65,20 +70,6 @@ def _convert_to_imperial(data: list, use_liters: bool) -> list: _LOGGER.debug("Converting statistics to imperial...") - def convert_to_miles(kilometers: float) -> float: - """Convert kilometers to miles""" - return round(kilometers * 0.621371192, 4) - - def convert_to_liter_per_100_miles(liters: float) -> float: - """Convert liters per 100 km to liters per 100 miles""" - _LOGGER.debug("Converting to L/100miles...") - return round(liters * 1.609344, 4) - - def convert_to_mpg(liters_per_100_km: float) -> float: - """Convert to miles per UK gallon (MPG)""" - _LOGGER.debug("Converting to MPG...") - return round(282.5 / liters_per_100_km, 4) - attributes_to_convert = [ "evDistanceInKm", "totalDistanceInKm", diff --git a/mytoyota/status.py b/mytoyota/status.py index 564b52e7..27497419 100644 --- a/mytoyota/status.py +++ b/mytoyota/status.py @@ -4,6 +4,7 @@ from mytoyota.const import DOORS, HOOD, KEY, LIGHTS, WINDOWS from mytoyota.sensors import Doors, Hood, Key, Lights, Windows +from mytoyota.utils import convert_to_miles _LOGGER: logging.Logger = logging.getLogger(__package__) @@ -78,7 +79,14 @@ class Energy: chargeinfo: dict = None - def __init__(self, data: Union[list, dict] = None, legacy: bool = False): + _is_imperial: bool = False + + def __init__( + self, data: Union[list, dict] = None, unit: str = "km", legacy: bool = False + ): + + if unit == "mi": + self._is_imperial = True # Support for old endpoint for fuel level. Some cars still uses this. if legacy: @@ -95,8 +103,15 @@ def as_dict(self) -> dict: def _set(self, data: list) -> None: """Set attributes""" + + range_in_km = data[0].get("remainingRange", None) + self.level = data[0].get("level", None) - self.range = data[0].get("remainingRange", None) + self.range = ( + convert_to_miles(range_in_km) + if range_in_km is not None and self._is_imperial + else range_in_km + ) self.type = data[0].get("type", "Unknown").capitalize() self.last_updated = data[0].get("timestamp", None) @@ -109,8 +124,19 @@ def _set_legacy(self, data: dict) -> None: def set_battery_attributes(self, data: dict) -> None: """Set charge info from legacy endpoint""" - self.range = data.get("EvDistanceInKm", None) - self.range_with_aircon = data.get("EvDistanceWithAirCoInKm", None) + range_in_km = data.get("EvDistanceInKm", None) + range_in_km_with_aircon = data.get("EvDistanceWithAirCoInKm", None) + + self.range = ( + convert_to_miles(range_in_km) + if range_in_km is not None and self._is_imperial + else range_in_km + ) + self.range_with_aircon = ( + convert_to_miles(range_in_km_with_aircon) + if range_in_km_with_aircon is not None and self._is_imperial + else range_in_km_with_aircon + ) self.chargeinfo = { "status": data.get("ChargingStatus", None), diff --git a/mytoyota/utils.py b/mytoyota/utils.py index 81ede2a4..6cfede9c 100644 --- a/mytoyota/utils.py +++ b/mytoyota/utils.py @@ -1,9 +1,13 @@ """Toyota Connected Services API.""" +import logging + from langcodes import Language from .const import TOKEN_LENGTH from .exceptions import ToyotaInvalidToken +_LOGGER: logging.Logger = logging.getLogger(__package__) + def is_valid_locale(locale: str) -> bool: """Is locale string valid.""" @@ -27,3 +31,21 @@ def format_odometer(raw: list) -> dict: instruments[instrument["type"] + "_unit"] = instrument["unit"] return instruments + + +def convert_to_miles(kilometers: float) -> float: + """Convert kilometers to miles""" + _LOGGER.debug(f"Converting {kilometers} to miles...") + return round(kilometers * 0.621371192, 4) + + +def convert_to_liter_per_100_miles(liters: float) -> float: + """Convert liters per 100 km to liters per 100 miles""" + _LOGGER.debug("Converting to L/100miles...") + return round(liters * 1.609344, 4) + + +def convert_to_mpg(liters_per_100_km: float) -> float: + """Convert to miles per UK gallon (MPG)""" + _LOGGER.debug("Converting to MPG...") + return round(282.5 / liters_per_100_km, 4) diff --git a/mytoyota/vehicle.py b/mytoyota/vehicle.py index 33e88655..8ee928de 100644 --- a/mytoyota/vehicle.py +++ b/mytoyota/vehicle.py @@ -76,14 +76,21 @@ def __init__( remote_control_info = remote_control.get("VehicleInfo", {}) + # Extract mileage and if the car reports in km or mi + self.odometer = ( + Odometer(format_odometer(odometer)) if odometer else Odometer({}) + ) + # Extract fuel level/Energy capacity information from status. if "energy" in status: _LOGGER.debug("Using energy data: %s", str(status.get("energy"))) - self.energy = Energy(status.get("energy")) + self.energy = Energy(status.get("energy"), self.odometer.unit) # Use legacy odometer to get fuel level. Older cars still uses this. elif odometer: _LOGGER.debug("Using legacy odometer data: %s", str(odometer)) - self.energy = Energy(format_odometer(odometer), True) + self.energy = Energy( + format_odometer(odometer), self.odometer.unit, True + ) fueltype = self.details.get("fuel", "Unknown") # PATCH: Toyota Aygo reports wrong type. if fueltype == "1.0P": @@ -95,11 +102,6 @@ def __init__( remote_control_info.get("ChargeInfo", {}) ) - # Extract mileage and if the car reports in km or mi - self.odometer = ( - Odometer(format_odometer(odometer)) if odometer else Odometer({}) - ) - # Extract parking information from status. self.parking = ParkingLocation(status.get("event", {}))