Skip to content

Commit

Permalink
Add better logging (#68)
Browse files Browse the repository at this point in the history
* Add better logging

* Bump version
  • Loading branch information
DurgNomis-drol authored Sep 27, 2021
1 parent bc06866 commit 5701d8a
Show file tree
Hide file tree
Showing 8 changed files with 71 additions and 13 deletions.
4 changes: 1 addition & 3 deletions mytoyota/api.py
Original file line number Diff line number Diff line change
Expand Up @@ -11,9 +11,7 @@
class Api:
"""Controller class."""

def __init__( # pylint: disable=too-many-arguments
self, controller: Controller
) -> None:
def __init__(self, controller: Controller) -> None:
"""Toyota Controller"""

self.controller = controller
Expand Down
23 changes: 21 additions & 2 deletions mytoyota/client.py
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,7 @@
class MyT:
"""Toyota Connected Services API class."""

def __init__( # pylint: disable=too-many-arguments
def __init__(
self,
username: str,
password: str,
Expand Down Expand Up @@ -78,6 +78,7 @@ def get_supported_regions() -> list:

async def login(self) -> None:
"""Login to Toyota services"""
_LOGGER.debug("Performing first login")
await self.api.controller.first_login()

async def get_uuid(self) -> str:
Expand All @@ -86,14 +87,17 @@ async def get_uuid(self) -> str:

async def set_alias(self, vehicle_id: int, new_alias: str) -> dict:
"""Sets a new alias for the car"""
_LOGGER.debug(
f"Setting new alias: {new_alias} for vehicle with id: {vehicle_id}"
)
result = await self.api.set_vehicle_alias_endpoint(
vehicle_id=vehicle_id, new_alias=new_alias
)
return result

async def get_vehicles(self) -> list:
"""Return list of vehicles with basic information about them"""

_LOGGER.debug("Getting list of vehicles associated with the account")
vehicles = await self.api.get_vehicles_endpoint()
if vehicles:
return vehicles
Expand All @@ -102,11 +106,13 @@ async def get_vehicles_json(self) -> str:
"""Return vehicle list as json"""
vehicles = await self.get_vehicles()

_LOGGER.debug("Returning it as json...")
json_string = json.dumps(vehicles, indent=3)
return json_string

async def get_vehicle_status(self, vehicle: dict) -> Vehicle:
"""Return information for given vehicle"""
_LOGGER.debug(f"Getting status for vehicle - {vehicle}...")

vin = vehicle["vin"]
data = await asyncio.gather(
Expand All @@ -118,6 +124,8 @@ async def get_vehicle_status(self, vehicle: dict) -> Vehicle:
]
)

_LOGGER.debug("Presenting information as an object...")

car = Vehicle(
vehicle_info=vehicle,
connected_services=data[0],
Expand All @@ -132,6 +140,7 @@ async def get_vehicle_status_json(self, vehicle: dict) -> str:
"""Return vehicle information as json"""
vehicle = await self.get_vehicle_status(vehicle)

_LOGGER.debug("Returning it as json")
json_string = json.dumps(vehicle.as_dict(), indent=3)
return json_string

Expand All @@ -157,6 +166,9 @@ async def get_driving_statistics( # pylint: disable=too-many-branches
This is due to a Toyota API limitation.
"""

_LOGGER.debug(f"Getting statistics for {vin}...")
_LOGGER.debug(f"Interval: {interval} - from_date: {from_date} - unit: {unit}")

if interval not in INTERVAL_SUPPORTED:
return [{"error_mesg": "Invalid interval provided!", "error_code": 1}]

Expand Down Expand Up @@ -215,6 +227,10 @@ async def get_driving_statistics( # pylint: disable=too-many-branches
today = arrow.now().format(DATE_FORMAT)

if from_date == today:
_LOGGER.debug(
"Aborting getting statistics because day is on the first of the week,"
" month or year"
)
raw_statistics = None

else:
Expand Down Expand Up @@ -243,6 +259,8 @@ async def get_driving_statistics( # pylint: disable=too-many-branches
imperial = True
use_liters = True

_LOGGER.debug("Parse statistics into the statistics object for formatting...")

statistics = Statistics(
raw_statistics=raw_statistics,
interval=interval,
Expand All @@ -256,6 +274,7 @@ async def get_driving_statistics_json(
self, vin: str, interval: str = MONTH, from_date: str = None
) -> str:
"""Return driving statistics in json"""
_LOGGER.debug("Returning it as json...")
return json.dumps(
await self.get_driving_statistics(vin, interval, from_date), indent=3
)
25 changes: 23 additions & 2 deletions mytoyota/controller.py
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,7 @@ class Controller:
_token: str = None
_token_expiration: datetime = None

def __init__( # pylint: disable=too-many-arguments
def __init__(
self,
locale: str,
region: str,
Expand Down Expand Up @@ -72,13 +72,16 @@ async def first_login(self) -> None:
@staticmethod
def _has_expired(creation_dt: datetime, duration: int) -> bool:
"""Checks if an specified token/object has expired"""
_LOGGER.debug("Checking if token has expired...")
return datetime.now().timestamp() - creation_dt.timestamp() > duration

async def _update_token(self) -> None:
"""Performs login to toyota servers and retrieves token and uuid for the account."""

# Cannot authenticate with aiohttp (returns 415),
# but it works with httpx.

_LOGGER.debug("Getting new token...")
async with httpx.AsyncClient() as client:
response = await client.post(
self._get_auth_endpoint(),
Expand All @@ -91,12 +94,16 @@ async def _update_token(self) -> None:
if TOKEN not in result or UUID not in result[CUSTOMERPROFILE]:
raise ToyotaLoginError("Could not get token or UUID from result")

_LOGGER.debug("Extracting token from result")

token = result.get(TOKEN)
uuid = result[CUSTOMERPROFILE][UUID]

if is_valid_token(token):
_LOGGER.debug("Token is the correct format")
self._uuid = uuid
self._token = token
_LOGGER.debug("Saving token and uuid")
self._token_expiration = datetime.now()
else:
raise ToyotaLoginError(
Expand All @@ -106,6 +113,7 @@ async def _update_token(self) -> None:
async def _is_token_valid(self) -> bool:
"""Checks if token is valid"""

_LOGGER.debug("Checking if token is still valid...")
async with httpx.AsyncClient() as client:
response = await client.post(
self._get_auth_valid_endpoint(),
Expand All @@ -115,12 +123,14 @@ async def _is_token_valid(self) -> bool:
result = response.json()

if result["valid"]:
_LOGGER.debug("Token is still valid")
return True
_LOGGER.debug("Token is not valid anymore")
return False

raise ToyotaLoginError(f"Error when trying to check token: {response.text}")

async def request( # pylint: disable=too-many-arguments
async def request(
self,
method: str,
endpoint: str,
Expand All @@ -146,6 +156,8 @@ async def request( # pylint: disable=too-many-arguments
else:
url = endpoint

_LOGGER.debug("Constructing additional headers...")

headers.update(
{
"X-TME-LC": self._locale,
Expand All @@ -162,9 +174,16 @@ async def request( # pylint: disable=too-many-arguments
}
)

_LOGGER.debug(f"Additional headers: {headers}")

# Cannot authenticate with aiohttp (returns 415),
# but it works with httpx.
_LOGGER.debug("Creating client...")
_LOGGER.debug(f"Base headers: {BASE_HEADERS} - Timeout: {TIMEOUT}")
async with httpx.AsyncClient(headers=BASE_HEADERS, timeout=TIMEOUT) as client:
_LOGGER.debug(
f"Requesting {url} - Method: {method} - Body: {body} - Parameters: {params}"
)
response = await client.request(
method, url, headers=headers, json=body, params=params
)
Expand Down Expand Up @@ -192,4 +211,6 @@ async def request( # pylint: disable=too-many-arguments
"HTTP: " + str(response.status_code) + " - " + response.text
)

_LOGGER.debug(f"Raw result: {result}")

return result
2 changes: 1 addition & 1 deletion mytoyota/hvac.py
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
"""HVAC representation for mytoyota"""


class Hvac: # pylint: disable=too-many-instance-attributes)
class Hvac:
"""Representation of the HVAC system in the car"""

current_temperature: int = None
Expand Down
10 changes: 9 additions & 1 deletion mytoyota/statistics.py
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@
_LOGGER: logging.Logger = logging.getLogger(__package__)


class Statistics: # pylint: disable=too-few-public-methods)
class Statistics:
"""Class to hold statistical information."""

def __init__(
Expand Down Expand Up @@ -63,16 +63,20 @@ def _convert_to_imperial(data: list, use_liters: bool) -> list:
corrects these values and adds the possibility to show them in MPG also.
"""

_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 = [
Expand All @@ -93,13 +97,15 @@ def convert_to_mpg(liters_per_100_km: float) -> float:
for attribute in attributes_to_convert:
if attribute in periode[DATA]:
if attribute == "totalFuelConsumedInL":
_LOGGER.debug(f"Converting attribute {attribute}...")
periode[DATA][attribute] = (
convert_to_liter_per_100_miles(periode[DATA][attribute])
if use_liters
else convert_to_mpg(periode[DATA][attribute])
)
continue

_LOGGER.debug(f"Converting attribute {attribute} to miles...")
periode[DATA][attribute] = convert_to_miles(
periode[DATA][attribute]
)
Expand All @@ -108,6 +114,8 @@ def convert_to_mpg(liters_per_100_km: float) -> float:
def _add_bucket(self, data: dict, interval: str) -> list:
"""Add bucket and return statistics in a uniform way."""

_LOGGER.debug("Updating bucket for statistics....")

if interval is DAY:
for day in data[HISTOGRAM]:
year = day[BUCKET][YEAR]
Expand Down
2 changes: 1 addition & 1 deletion mytoyota/status.py
Original file line number Diff line number Diff line change
Expand Up @@ -66,7 +66,7 @@ def as_dict(self) -> dict:
}


class Energy: # pylint: disable=too-many-instance-attributes
class Energy:
"""Represents fuel level, battery capacity and range"""

level: Optional[int] = None
Expand Down
4 changes: 2 additions & 2 deletions mytoyota/vehicle.py
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@ def as_dict(self) -> dict:
return vars(self)


class Vehicle: # pylint: disable=too-many-instance-attributes
class Vehicle:
"""Vehicle representation"""

id: int = 0
Expand All @@ -41,7 +41,7 @@ class Vehicle: # pylint: disable=too-many-instance-attributes
sensors: Optional[Sensors] = None
statistics: VehicleStatistics = VehicleStatistics()

def __init__( # pylint: disable=too-many-arguments
def __init__(
self,
vehicle_info: dict,
connected_services: Optional[dict],
Expand Down
14 changes: 13 additions & 1 deletion pyproject.toml
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ description = "Python client for Toyota Connected Services."
authors = ["Simon Grud Hansen <[email protected]>"]
license = "MIT"
readme = "README.md"
version = "0.6.3"
version = "0.7.0"
classifiers = [
"Development Status :: 4 - Beta",
"License :: OSI Approved :: MIT License",
Expand Down Expand Up @@ -40,6 +40,18 @@ pylint = "^2.7.2"
isort = "^5.7.0"
codespell = "^2.0.0"

[tool.pylint.messages_control]
# Reasons disabled:
# too-many-* - not enforced for the sake of readability
# too-few-* - same as too-many-*
disable = [
"too-few-public-methods",
"too-many-arguments",
"too-many-instance-attributes",
"duplicate-code",
"logging-fstring-interpolation",
]

[tool.pylint.format]
max-line-length = 99

Expand Down

0 comments on commit 5701d8a

Please sign in to comment.