Skip to content

Commit

Permalink
Migrate Charging to pydantic
Browse files Browse the repository at this point in the history
  • Loading branch information
Prior99 committed Sep 13, 2024
1 parent f51d090 commit dda4451
Show file tree
Hide file tree
Showing 4 changed files with 87 additions and 57 deletions.
20 changes: 11 additions & 9 deletions myskoda/cli.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,8 @@
from termcolor import colored
import asyncclick as click

from myskoda.models.charging import MaxChargeCurrent
from myskoda.models.common import OnOffState
from myskoda.myskoda import MySkodaHub
from . import idk_authorize

Expand Down Expand Up @@ -149,23 +151,23 @@ async def charging(vin):
await hub.authenticate(username, password)
charging = await hub.get_charging(vin)

print(f"{colored("battery charge:", "blue")} {charging.battery_percent}%")
print(f"{colored("target:", "blue")} {charging.target_percent}%")
print(f"{colored("battery charge:", "blue")} {charging.status.battery.state_of_charge_in_percent}%")
print(f"{colored("target:", "blue")} {charging.settings.target_state_of_charge_in_percent}%")
print(
f"{colored("remaining distance:", "blue")} {charging.remaining_distance_m / 1000}km"
f"{colored("remaining distance:", "blue")} {charging.status.battery.remaining_cruising_range_in_meters / 1000}km"
)
print(f"{colored("charging power:", "blue")} {charging.charging_power_kw}kw")
print(f"{colored("charging power:", "blue")} {charging.charge_power_in_kw}kw")
print(f"{colored("charger type:", "blue")} {charging.charge_type}")
print(
f"{colored("charging rate:", "blue")} {charging.charging_rate_in_km_h}km/h"
f"{colored("charging rate:", "blue")} {charging.charging_rate_in_kilometers_per_hour}km/h"
)
print(f"{colored("remaining time:", "blue")} {charging.remaining_time_min}min")
print(f"{colored("state:", "blue")} {charging.state}")
print(f"{colored("remaining time:", "blue")} {charging.remaining_time_to_fully_charged_in_minutes}min")
print(f"{colored("state:", "blue")} {charging.status.state}")
print(
f"{colored("battery care mode:", "blue")} {on(charging.charging_care_mode)}"
f"{colored("battery care mode:", "blue")} {on(charging.settings.charging_care_mode is OnOffState.ON)}"
)
print(
f"{colored("reduced current:", "blue")} {on(charging.use_reduced_current)}"
f"{colored("reduced current:", "blue")} {on(charging.settings.max_charge_current_ac is MaxChargeCurrent.REDUCED)}"
)


Expand Down
60 changes: 60 additions & 0 deletions myskoda/models/charging.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,60 @@
from datetime import datetime
from enum import Enum
from pydantic import BaseModel, Field
from typing import Any

from .common import ActiveState, EnabledState

class ChargeMode(str, Enum):
MANUAL = "MANUAL"

class MaxChargeCurrent(str, Enum):
MAXIMUM = "MAXIMUM"
REDUCED = "REDUCED"

class ChargingState(str, Enum):
READY_FOR_CHARGING = "READY_FOR_CHARGING"
CONNECT_CABLE = "CONNECT_CABLE"
CONSERVING = "CONSERVING"
CHARGING = "CHARGING"

class ChargeType(str, Enum):
AC = "AC"

class PlugUnlockMode(str, Enum):
PERMANENT = "PERMANENT"
ON = "ON"
OFF = "OFF"

class Settings(BaseModel):
available_charge_modes: list[ChargeMode] = Field(None, alias="availableChargeModes")
battery_support: EnabledState = Field(None, alias="batterySupport")
charging_care_mode: ActiveState = Field(None, alias="chargingCareMode")
max_charge_current_ac: MaxChargeCurrent = Field(None, alias="maxChargeCurrentAc")
preferred_charge_mode: ChargeMode = Field(None, alias="preferredChargeMode")
target_state_of_charge_in_percent: int = Field(None, alias="targetStateOfChargeInPercent")
auto_unlock_plug_when_charged: PlugUnlockMode = Field(None, alias="autoUnlockPlugWhenCharged")

class Battery(BaseModel):
remaining_cruising_range_in_meters: int = Field(None, alias="remainingCruisingRangeInMeters")
state_of_charge_in_percent: int = Field(None, alias="stateOfChargeInPercent")

class Status(BaseModel):
battery: Battery
charge_power_in_kw: float | None = Field(None, alias="chargePowerInKw")
charging_rate_in_kilometers_per_hour: float = Field(None, alias="chargingRateInKilometersPerHour")
remaining_time_to_fully_charged_in_minutes: int = Field(None, alias="remainingTimeToFullyChargedInMinutes")
state: ChargingState

class Charging(BaseModel):
"""Information related to charging an EV."""

car_captured_timestamp: datetime = Field(None, alias="carCapturedTimestamp")
errors: list[Any]
is_vehicle_in_saved_location: bool = Field(None, alias="isVehicleInSavedLocation")
settings: Settings
status: Status
charging_rate_in_kilometers_per_hour: float | None = Field(None, alias="chargingRateInKilometersPerHour")
remaining_time_to_fully_charged_in_minutes: int | None = Field(None, alias="remainingTimeToFullyChargedInMinutes")
charge_type: ChargeType | None = Field(None, alias="chargeType")
charge_power_in_kw: float | None = Field(None, alias="chargePowerInKw")
13 changes: 13 additions & 0 deletions myskoda/models/common.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
from enum import Enum

class OnOffState(str, Enum):
ON = "ON"
OFF = "OFF"

class EnabledState(str, Enum):
ENABLED = "ENABLED"
DISABLED = "DISABLED"

class ActiveState(str, Enum):
ACTIVATED = "ACTIVATED"
DEACTIVATED = "DEACTIVATED"
51 changes: 3 additions & 48 deletions myskoda/myskoda.py
Original file line number Diff line number Diff line change
Expand Up @@ -8,56 +8,12 @@

from .authorization import IDKSession, idk_authorize
from .const import BASE_URL_SKODA
from .models.charging import Charging
from .models.info import Info

_LOGGER = logging.getLogger(__name__)


class Charging:
"""Information related to charging an EV."""

remaining_distance_m: int
battery_percent: int
charging_care_mode: bool
charging_power_kw: float
charge_type: str
charging_rate_in_km_h: float
remaining_time_min: str
state: str
target_percent: int
use_reduced_current: bool

def __init__(self, data): # noqa: D107
self.target_percent = data.get("settings", {}).get(
"targetStateOfChargeInPercent"
)
self.charging_care_mode = (
data.get("settings", {}).get("chargingCareMode") == "ACTIVATED"
)
self.use_reduced_current = (
data.get("settings", {}).get("maxChargeCurrentAc") == "REDUCED"
)

data = data.get("status")
self.remaining_distance_m = data.get("battery", {}).get(
"remainingCruisingRangeInMeters"
)
self.battery_percent = data.get("battery", {}).get("stateOfChargeInPercent")
self.charging_power_kw = data.get("chargePowerInKw")

# "AC"
self.charge_type = data.get("chargeType")

self.charging_rate_in_km_h = data.get("chargingRateInKilometersPerHour")
self.remaining_time_min = data.get("remainingTimeToFullyChargedInMinutes")

# "CONNECT_CABLE": Not connected
# "READY_FOR_CHARGING": Connected, but full
# "CONSERVING": Connected, but full
# "CHARGING": Connected and charging
self.state = data.get("state")


class Status:
"""Current status information for a vehicle."""

Expand Down Expand Up @@ -210,16 +166,15 @@ async def get_info(self, vin):
headers=await self._headers(),
) as response:
_LOGGER.debug("vin %s: Received basic info", vin)
data = await response.json()
return Info(**data)
return Info(**await response.json())

async def get_charging(self, vin):
"""Retrieve information related to charging for the specified vehicle."""
async with self.session.get(
f"{BASE_URL_SKODA}/api/v1/charging/{vin}", headers=await self._headers()
) as response:
_LOGGER.debug("Received charging info")
return Charging(await response.json())
return Charging(**await response.json())

async def get_status(self, vin):
"""Retrieve the current status for the specified vehicle."""
Expand Down

0 comments on commit dda4451

Please sign in to comment.