Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

refactor(Hyundai USA): Migration from climate actions methods to engine action methods #434

Draft
wants to merge 8 commits into
base: master
Choose a base branch
from
10 changes: 10 additions & 0 deletions hyundai_kia_connect_api/ApiImpl.py
Original file line number Diff line number Diff line change
Expand Up @@ -104,6 +104,16 @@ def lock_action(self, token: Token, vehicle: Vehicle, action: str) -> str:
"""Lock or unlocks a vehicle. Returns the tracking ID"""
pass

def engine_control_action(
self,
token: Token,
vehicle: Vehicle,
action: VEHICLE_ENGINE_CONTROL_ACTION,
options: ClimateRequestOptions,
) -> str:
"""Starts or stops an engine depending on the action provided."""
pass

def start_climate(
self, token: Token, vehicle: Vehicle, options: ClimateRequestOptions
) -> str:
Expand Down
128 changes: 85 additions & 43 deletions hyundai_kia_connect_api/HyundaiBlueLinkAPIUSA.py
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@
import requests
from requests.adapters import HTTPAdapter
from urllib3.util.ssl_ import create_urllib3_context
from dataclasses import fields

from .const import (
DOMAIN,
Expand All @@ -17,6 +18,7 @@
DISTANCE_UNITS,
TEMPERATURE_UNITS,
ENGINE_TYPES,
VEHICLE_ENGINE_CONTROL_ACTION,
)
from .utils import get_child_value
from .ApiImpl import ApiImpl, ClimateRequestOptions
Expand Down Expand Up @@ -511,8 +513,85 @@ def lock_action(self, token: Token, vehicle: Vehicle, action) -> None:
)
_LOGGER.debug(f"{DOMAIN} - Received lock_action response: {response.text}")

def engine_control_action(
self,
token: Token,
vehicle: Vehicle,
action: VEHICLE_ENGINE_CONTROL_ACTION,
options: ClimateRequestOptions,
) -> str:
_LOGGER.debug(f"{DOMAIN} - {action.value} engine..")

match action:
case VEHICLE_ENGINE_CONTROL_ACTION.START:
self.start_engine(token, vehicle, options)
case VEHICLE_ENGINE_CONTROL_ACTION.STOP:
self.stop_engine(token, vehicle)

def _determine_climate_options(
self, options: ClimateRequestOptions
) -> ClimateRequestOptions:
if not options:
options = ClimateRequestOptions()
# Iterate over every field
for field in fields(options):
# Get the value of the field
field_value = getattr(options, field.name)
# If there isn't a field value set, set it
if not field_value:
match field.name:
case "climate":
options.climate = True
case "set_temp":
options.set_temp = 70
case "duration":
options.duration = 5
case "heating":
options.heating = 0
case "defrost":
options.defrost = False
case "front_left_seat":
options.front_left_seat = 0
case "front_right_seat":
options.front_right_seat = 0
case "rear_left_seat":
options.rear_left_seat = 0
case "rear_right_seat":
options.rear_right_seat = 0
return options

def _determine_data_payload(
self, token: Token, options: ClimateRequestOptions, vehicle: Vehicle
):
data = {
"airCtrl": int(options.climate),
"heating1": int(options.heating),
"defrost": options.defrost,
}
match vehicle.engine_type:
case ENGINE_TYPES.EV:
data["airTemp"] = {"value": str(options.set_temp), "unit": 1}
case _:
data["Ims"] = 0
data["airTemp"] = {"unit": 1, "value": options.set_temp}
data["igniOnDuration"] = options.duration
data["seatHeaterVentInfo"] = {
"drvSeatHeatState": options.front_left_seat,
"astSeatHeatState": options.front_right_seat,
"rlSeatHeatState": options.rear_left_seat,
"rrSeatHeatState": options.rear_right_seat,
}
data["username"] = token.username
data["vin"] = vehicle.id
return data

def start_climate(
self, token: Token, vehicle: Vehicle, options: ClimateRequestOptions
) -> str:
self.start_engine(token, vehicle, options)

def start_engine(
self, token: Token, vehicle: Vehicle, options: ClimateRequestOptions
) -> str:
_LOGGER.debug(f"{DOMAIN} - Start engine..")
if vehicle.engine_type == ENGINE_TYPES.EV:
Expand All @@ -523,49 +602,9 @@ def start_climate(
headers = self._get_vehicle_headers(token, vehicle)
_LOGGER.debug(f"{DOMAIN} - Start engine headers: {headers}")

if options.climate is None:
options.climate = True
if options.set_temp is None:
options.set_temp = 70
if options.duration is None:
options.duration = 5
if options.heating is None:
options.heating = 0
if options.defrost is None:
options.defrost = False
if options.front_left_seat is None:
options.front_left_seat = 0
if options.front_right_seat is None:
options.front_right_seat = 0
if options.rear_left_seat is None:
options.rear_left_seat = 0
if options.rear_right_seat is None:
options.rear_right_seat = 0
determined_climate_options = self._determine_climate_options(options)
data = self._determine_data_payload(token, determined_climate_options, vehicle)

if vehicle.engine_type == ENGINE_TYPES.EV:
data = {
"airCtrl": int(options.climate),
"airTemp": {"value": str(options.set_temp), "unit": 1},
"defrost": options.defrost,
"heating1": int(options.heating),
}
else:
data = {
"Ims": 0,
"airCtrl": int(options.climate),
"airTemp": {"unit": 1, "value": options.set_temp},
"defrost": options.defrost,
"heating1": int(options.heating),
"igniOnDuration": options.duration,
"seatHeaterVentInfo": {
"drvSeatHeatState": options.front_left_seat,
"astSeatHeatState": options.front_right_seat,
"rlSeatHeatState": options.rear_left_seat,
"rrSeatHeatState": options.rear_right_seat,
},
"username": token.username,
"vin": vehicle.id,
}
_LOGGER.debug(f"{DOMAIN} - Start engine data: {data}")

response = self.sessions.post(url, json=data, headers=headers)
Expand All @@ -574,7 +613,7 @@ def start_climate(
)
_LOGGER.debug(f"{DOMAIN} - Start engine response: {response.text}")

def stop_climate(self, token: Token, vehicle: Vehicle) -> None:
def stop_engine(self, token: Token, vehicle: Vehicle) -> None:
_LOGGER.debug(f"{DOMAIN} - Stop engine..")

if vehicle.engine_type == ENGINE_TYPES.EV:
Expand All @@ -592,6 +631,9 @@ def stop_climate(self, token: Token, vehicle: Vehicle) -> None:
)
_LOGGER.debug(f"{DOMAIN} - Stop engine response: {response.text}")

def stop_climate(self, token: Token, vehicle: Vehicle) -> None:
self.stop_engine(token, vehicle)

def start_charge(self, token: Token, vehicle: Vehicle) -> None:
pass

Expand Down
1 change: 1 addition & 0 deletions hyundai_kia_connect_api/VehicleManager.py
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@
REGION_CHINA,
REGIONS,
VEHICLE_LOCK_ACTION,
VEHICLE_ENGINE_CONTROL_ACTION,
CHARGE_PORT_ACTION,
OrderStatus,
)
Expand Down
5 changes: 5 additions & 0 deletions hyundai_kia_connect_api/const.py
Original file line number Diff line number Diff line change
Expand Up @@ -62,6 +62,11 @@ class ENGINE_TYPES(Enum):
HEV = "HEV"


class VEHICLE_ENGINE_CONTROL_ACTION(Enum):
START = "start"
STOP = "stop"


class VEHICLE_LOCK_ACTION(Enum):
LOCK = "close"
UNLOCK = "open"
Expand Down