hyundai-kia-connect-api 3.17.10__py2.py3-none-any.whl → 3.19.0__py2.py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- hyundai_kia_connect_api/ApiImpl.py +1 -5
- hyundai_kia_connect_api/ApiImplType1.py +291 -2
- hyundai_kia_connect_api/HyundaiBlueLinkAPIUSA.py +64 -31
- hyundai_kia_connect_api/KiaUvoAPIUSA.py +7 -25
- hyundai_kia_connect_api/KiaUvoApiAU.py +39 -49
- hyundai_kia_connect_api/KiaUvoApiCA.py +6 -25
- hyundai_kia_connect_api/KiaUvoApiCN.py +5 -24
- hyundai_kia_connect_api/KiaUvoApiEU.py +31 -302
- hyundai_kia_connect_api/Vehicle.py +1 -1
- hyundai_kia_connect_api/utils.py +22 -2
- {hyundai_kia_connect_api-3.17.10.dist-info → hyundai_kia_connect_api-3.19.0.dist-info}/METADATA +1 -1
- hyundai_kia_connect_api-3.19.0.dist-info/RECORD +21 -0
- hyundai_kia_connect_api-3.17.10.dist-info/RECORD +0 -21
- {hyundai_kia_connect_api-3.17.10.dist-info → hyundai_kia_connect_api-3.19.0.dist-info}/AUTHORS.rst +0 -0
- {hyundai_kia_connect_api-3.17.10.dist-info → hyundai_kia_connect_api-3.19.0.dist-info}/LICENSE +0 -0
- {hyundai_kia_connect_api-3.17.10.dist-info → hyundai_kia_connect_api-3.19.0.dist-info}/WHEEL +0 -0
- {hyundai_kia_connect_api-3.17.10.dist-info → hyundai_kia_connect_api-3.19.0.dist-info}/top_level.txt +0 -0
@@ -10,7 +10,7 @@ import requests
|
|
10
10
|
|
11
11
|
from .Token import Token
|
12
12
|
from .Vehicle import Vehicle
|
13
|
-
from .const import
|
13
|
+
from .const import WINDOW_STATE, CHARGE_PORT_ACTION, OrderStatus
|
14
14
|
from .utils import get_child_value
|
15
15
|
|
16
16
|
_LOGGER = logging.getLogger(__name__)
|
@@ -57,10 +57,6 @@ class ApiImpl:
|
|
57
57
|
Required for Kia USA as key is session specific"""
|
58
58
|
return vehicles
|
59
59
|
|
60
|
-
def get_last_updated_at(self, value) -> dt.datetime:
|
61
|
-
"""Convert last updated value of vehicle into into datetime"""
|
62
|
-
pass
|
63
|
-
|
64
60
|
def update_vehicle_with_cached_state(self, token: Token, vehicle: Vehicle) -> None:
|
65
61
|
"""Get cached vehicle data and update Vehicle instance with it"""
|
66
62
|
pass
|
@@ -1,7 +1,23 @@
|
|
1
|
+
import datetime as dt
|
2
|
+
from typing import Optional
|
3
|
+
|
1
4
|
from .ApiImpl import (
|
2
5
|
ApiImpl,
|
3
6
|
)
|
4
7
|
from .Token import Token
|
8
|
+
from .Vehicle import Vehicle
|
9
|
+
|
10
|
+
from .utils import (
|
11
|
+
get_child_value,
|
12
|
+
parse_datetime,
|
13
|
+
)
|
14
|
+
|
15
|
+
from .const import (
|
16
|
+
DISTANCE_UNITS,
|
17
|
+
ENGINE_TYPES,
|
18
|
+
SEAT_STATUS,
|
19
|
+
TEMPERATURE_UNITS,
|
20
|
+
)
|
5
21
|
|
6
22
|
USER_AGENT_OK_HTTP: str = "okhttp/3.12.0"
|
7
23
|
|
@@ -10,7 +26,9 @@ class ApiImplType1(ApiImpl):
|
|
10
26
|
def __init__(self) -> None:
|
11
27
|
"""Initialize."""
|
12
28
|
|
13
|
-
def _get_authenticated_headers(
|
29
|
+
def _get_authenticated_headers(
|
30
|
+
self, token: Token, ccs2_support: Optional[int] = None
|
31
|
+
) -> dict:
|
14
32
|
return {
|
15
33
|
"Authorization": token.access_token,
|
16
34
|
"ccsp-service-id": self.CCSP_SERVICE_ID,
|
@@ -20,6 +38,277 @@ class ApiImplType1(ApiImpl):
|
|
20
38
|
"Host": self.BASE_URL,
|
21
39
|
"Connection": "Keep-Alive",
|
22
40
|
"Accept-Encoding": "gzip",
|
23
|
-
"Ccuccs2protocolsupport":
|
41
|
+
"Ccuccs2protocolsupport": str(ccs2_support or 0),
|
24
42
|
"User-Agent": USER_AGENT_OK_HTTP,
|
25
43
|
}
|
44
|
+
|
45
|
+
def _update_vehicle_properties_ccs2(self, vehicle: Vehicle, state: dict) -> None:
|
46
|
+
if get_child_value(state, "Date"):
|
47
|
+
vehicle.last_updated_at = parse_datetime(
|
48
|
+
get_child_value(state, "Date"), self.data_timezone
|
49
|
+
)
|
50
|
+
else:
|
51
|
+
vehicle.last_updated_at = dt.datetime.now(self.data_timezone)
|
52
|
+
|
53
|
+
vehicle.odometer = (
|
54
|
+
get_child_value(state, "Drivetrain.Odometer"),
|
55
|
+
DISTANCE_UNITS[1],
|
56
|
+
)
|
57
|
+
vehicle.car_battery_percentage = get_child_value(
|
58
|
+
state, "Electronics.Battery.Level"
|
59
|
+
)
|
60
|
+
|
61
|
+
vehicle.engine_is_running = get_child_value(state, "DrivingReady")
|
62
|
+
|
63
|
+
air_temp = get_child_value(
|
64
|
+
state,
|
65
|
+
"Cabin.HVAC.Row1.Driver.Temperature.Value",
|
66
|
+
)
|
67
|
+
|
68
|
+
if air_temp != "OFF":
|
69
|
+
vehicle.air_temperature = (air_temp, TEMPERATURE_UNITS[1])
|
70
|
+
|
71
|
+
defrost_is_on = get_child_value(state, "Body.Windshield.Front.Defog.State")
|
72
|
+
if defrost_is_on in [0, 2]:
|
73
|
+
vehicle.defrost_is_on = False
|
74
|
+
elif defrost_is_on == 1:
|
75
|
+
vehicle.defrost_is_on = True
|
76
|
+
|
77
|
+
steer_wheel_heat = get_child_value(state, "Cabin.SteeringWheel.Heat.State")
|
78
|
+
if steer_wheel_heat in [0, 2]:
|
79
|
+
vehicle.steering_wheel_heater_is_on = False
|
80
|
+
elif steer_wheel_heat == 1:
|
81
|
+
vehicle.steering_wheel_heater_is_on = True
|
82
|
+
|
83
|
+
defrost_rear_is_on = get_child_value(state, "Body.Windshield.Rear.Defog.State")
|
84
|
+
if defrost_rear_is_on in [0, 2]:
|
85
|
+
vehicle.back_window_heater_is_on = False
|
86
|
+
elif defrost_rear_is_on == 1:
|
87
|
+
vehicle.back_window_heater_is_on = True
|
88
|
+
|
89
|
+
# TODO: status.sideMirrorHeat
|
90
|
+
|
91
|
+
vehicle.front_left_seat_status = SEAT_STATUS[
|
92
|
+
get_child_value(state, "Cabin.Seat.Row1.Driver.Climate.State")
|
93
|
+
]
|
94
|
+
|
95
|
+
vehicle.front_right_seat_status = SEAT_STATUS[
|
96
|
+
get_child_value(state, "Cabin.Seat.Row1.Passenger.Climate.State")
|
97
|
+
]
|
98
|
+
|
99
|
+
vehicle.rear_left_seat_status = SEAT_STATUS[
|
100
|
+
get_child_value(state, "Cabin.Seat.Row2.Left.Climate.State")
|
101
|
+
]
|
102
|
+
|
103
|
+
vehicle.rear_right_seat_status = SEAT_STATUS[
|
104
|
+
get_child_value(state, "Cabin.Seat.Row2.Right.Climate.State")
|
105
|
+
]
|
106
|
+
|
107
|
+
# TODO: status.doorLock
|
108
|
+
|
109
|
+
vehicle.front_left_door_is_open = get_child_value(
|
110
|
+
state, "Cabin.Door.Row1.Driver.Open"
|
111
|
+
)
|
112
|
+
vehicle.front_right_door_is_open = get_child_value(
|
113
|
+
state, "Cabin.Door.Row1.Passenger.Open"
|
114
|
+
)
|
115
|
+
vehicle.back_left_door_is_open = get_child_value(
|
116
|
+
state, "Cabin.Door.Row2.Left.Open"
|
117
|
+
)
|
118
|
+
vehicle.back_right_door_is_open = get_child_value(
|
119
|
+
state, "Cabin.Door.Row2.Right.Open"
|
120
|
+
)
|
121
|
+
|
122
|
+
# TODO: should the windows and trunc also be checked?
|
123
|
+
vehicle.is_locked = not (
|
124
|
+
vehicle.front_left_door_is_open
|
125
|
+
or vehicle.front_right_door_is_open
|
126
|
+
or vehicle.back_left_door_is_open
|
127
|
+
or vehicle.back_right_door_is_open
|
128
|
+
)
|
129
|
+
|
130
|
+
vehicle.hood_is_open = get_child_value(state, "Body.Hood.Open")
|
131
|
+
vehicle.front_left_window_is_open = get_child_value(
|
132
|
+
state, "Cabin.Window.Row1.Driver.Open"
|
133
|
+
)
|
134
|
+
vehicle.front_right_window_is_open = get_child_value(
|
135
|
+
state, "Cabin.Window.Row1.Passenger.Open"
|
136
|
+
)
|
137
|
+
vehicle.back_left_window_is_open = get_child_value(
|
138
|
+
state, "Cabin.Window.Row2.Left.Open"
|
139
|
+
)
|
140
|
+
vehicle.back_right_window_is_open = get_child_value(
|
141
|
+
state, "Cabin.Window.Row2.Right.Open"
|
142
|
+
)
|
143
|
+
vehicle.tire_pressure_rear_left_warning_is_on = bool(
|
144
|
+
get_child_value(state, "Chassis.Axle.Row2.Left.Tire.PressureLow")
|
145
|
+
)
|
146
|
+
vehicle.tire_pressure_front_left_warning_is_on = bool(
|
147
|
+
get_child_value(state, "Chassis.Axle.Row1.Left.Tire.PressureLow")
|
148
|
+
)
|
149
|
+
vehicle.tire_pressure_front_right_warning_is_on = bool(
|
150
|
+
get_child_value(state, "Chassis.Axle.Row1.Right.Tire.PressureLow")
|
151
|
+
)
|
152
|
+
vehicle.tire_pressure_rear_right_warning_is_on = bool(
|
153
|
+
get_child_value(state, "Chassis.Axle.Row2.Right.Tire.PressureLow")
|
154
|
+
)
|
155
|
+
vehicle.tire_pressure_all_warning_is_on = bool(
|
156
|
+
get_child_value(state, "Chassis.Axle.Tire.PressureLow")
|
157
|
+
)
|
158
|
+
vehicle.trunk_is_open = get_child_value(state, "Body.Trunk.Open")
|
159
|
+
|
160
|
+
vehicle.ev_battery_percentage = get_child_value(
|
161
|
+
state, "Green.BatteryManagement.BatteryRemain.Ratio"
|
162
|
+
)
|
163
|
+
vehicle.ev_battery_remain = get_child_value(
|
164
|
+
state, "Green.BatteryManagement.BatteryRemain.Value"
|
165
|
+
)
|
166
|
+
vehicle.ev_battery_capacity = get_child_value(
|
167
|
+
state, "Green.BatteryManagement.BatteryCapacity.Value"
|
168
|
+
)
|
169
|
+
vehicle.ev_battery_soh_percentage = get_child_value(
|
170
|
+
state, "Green.BatteryManagement.SoH.Ratio"
|
171
|
+
)
|
172
|
+
vehicle.ev_battery_is_plugged_in = get_child_value(
|
173
|
+
state, "Green.ChargingInformation.ElectricCurrentLevel.State"
|
174
|
+
)
|
175
|
+
vehicle.ev_battery_is_plugged_in = get_child_value(
|
176
|
+
state, "Green.ChargingInformation.ConnectorFastening.State"
|
177
|
+
)
|
178
|
+
charging_door_state = get_child_value(state, "Green.ChargingDoor.State")
|
179
|
+
if charging_door_state in [0, 2]:
|
180
|
+
vehicle.ev_charge_port_door_is_open = False
|
181
|
+
elif charging_door_state == 1:
|
182
|
+
vehicle.ev_charge_port_door_is_open = True
|
183
|
+
|
184
|
+
vehicle.total_driving_range = (
|
185
|
+
float(
|
186
|
+
get_child_value(
|
187
|
+
state,
|
188
|
+
"Drivetrain.FuelSystem.DTE.Total", # noqa
|
189
|
+
)
|
190
|
+
),
|
191
|
+
DISTANCE_UNITS[
|
192
|
+
get_child_value(
|
193
|
+
state,
|
194
|
+
"Drivetrain.FuelSystem.DTE.Unit", # noqa
|
195
|
+
)
|
196
|
+
],
|
197
|
+
)
|
198
|
+
|
199
|
+
if vehicle.engine_type == ENGINE_TYPES.EV:
|
200
|
+
# ev_driving_range is the same as total_driving_range for pure EV
|
201
|
+
vehicle.ev_driving_range = (
|
202
|
+
vehicle.total_driving_range,
|
203
|
+
vehicle.total_driving_range_unit,
|
204
|
+
)
|
205
|
+
# TODO: vehicle.ev_driving_range for non EV
|
206
|
+
|
207
|
+
vehicle.washer_fluid_warning_is_on = get_child_value(
|
208
|
+
state, "Body.Windshield.Front.WasherFluid.LevelLow"
|
209
|
+
)
|
210
|
+
|
211
|
+
vehicle.ev_estimated_current_charge_duration = (
|
212
|
+
get_child_value(state, "Green.ChargingInformation.Charging.RemainTime"),
|
213
|
+
"m",
|
214
|
+
)
|
215
|
+
vehicle.ev_estimated_fast_charge_duration = (
|
216
|
+
get_child_value(state, "Green.ChargingInformation.EstimatedTime.Standard"),
|
217
|
+
"m",
|
218
|
+
)
|
219
|
+
vehicle.ev_estimated_portable_charge_duration = (
|
220
|
+
get_child_value(state, "Green.ChargingInformation.EstimatedTime.ICCB"),
|
221
|
+
"m",
|
222
|
+
)
|
223
|
+
vehicle.ev_estimated_station_charge_duration = (
|
224
|
+
get_child_value(state, "Green.ChargingInformation.EstimatedTime.Quick"),
|
225
|
+
"m",
|
226
|
+
)
|
227
|
+
vehicle.ev_charge_limits_ac = get_child_value(
|
228
|
+
state, "Green.ChargingInformation.TargetSoC.Standard"
|
229
|
+
)
|
230
|
+
vehicle.ev_charge_limits_dc = get_child_value(
|
231
|
+
state, "Green.ChargingInformation.TargetSoC.Quick"
|
232
|
+
)
|
233
|
+
vehicle.ev_v2l_discharge_limit = get_child_value(
|
234
|
+
state, "Green.Electric.SmartGrid.VehicleToLoad.DischargeLimitation.SoC"
|
235
|
+
)
|
236
|
+
vehicle.ev_target_range_charge_AC = (
|
237
|
+
get_child_value(
|
238
|
+
state,
|
239
|
+
"Green.ChargingInformation.DTE.TargetSoC.Standard", # noqa
|
240
|
+
),
|
241
|
+
DISTANCE_UNITS[
|
242
|
+
get_child_value(
|
243
|
+
state,
|
244
|
+
"Drivetrain.FuelSystem.DTE.Unit", # noqa
|
245
|
+
)
|
246
|
+
],
|
247
|
+
)
|
248
|
+
vehicle.ev_target_range_charge_DC = (
|
249
|
+
get_child_value(
|
250
|
+
state,
|
251
|
+
"Green.ChargingInformation.DTE.TargetSoC.Quick", # noqa
|
252
|
+
),
|
253
|
+
DISTANCE_UNITS[
|
254
|
+
get_child_value(
|
255
|
+
state,
|
256
|
+
"Drivetrain.FuelSystem.DTE.Unit", # noqa
|
257
|
+
)
|
258
|
+
],
|
259
|
+
)
|
260
|
+
vehicle.ev_first_departure_enabled = bool(
|
261
|
+
get_child_value(state, "Green.Reservation.Departure.Schedule1.Enable")
|
262
|
+
)
|
263
|
+
|
264
|
+
vehicle.ev_second_departure_enabled = bool(
|
265
|
+
get_child_value(state, "Green.Reservation.Departure.Schedule2.Enable")
|
266
|
+
)
|
267
|
+
|
268
|
+
# TODO: vehicle.ev_first_departure_days --> Green.Reservation.Departure.Schedule1.(Mon,Tue,Wed,Thu,Fri,Sat,Sun) # noqa
|
269
|
+
# TODO: vehicle.ev_second_departure_days --> Green.Reservation.Departure.Schedule2.(Mon,Tue,Wed,Thu,Fri,Sat,Sun) # noqa
|
270
|
+
# TODO: vehicle.ev_first_departure_time --> Green.Reservation.Departure.Schedule1.(Min,Hour) # noqa
|
271
|
+
# TODO: vehicle.ev_second_departure_time --> Green.Reservation.Departure.Schedule2.(Min,Hour) # noqa
|
272
|
+
# TODO: vehicle.ev_off_peak_charge_only_enabled --> unknown settings are in --> Green.Reservation.OffPeakTime and OffPeakTime2 # noqa
|
273
|
+
|
274
|
+
vehicle.washer_fluid_warning_is_on = get_child_value(
|
275
|
+
state, "Body.Windshield.Front.WasherFluid.LevelLow"
|
276
|
+
)
|
277
|
+
vehicle.brake_fluid_warning_is_on = get_child_value(
|
278
|
+
state, "Chassis.Brake.Fluid.Warning"
|
279
|
+
)
|
280
|
+
|
281
|
+
vehicle.fuel_level = get_child_value(state, "Drivetrain.FuelSystem.FuelLevel")
|
282
|
+
vehicle.fuel_level_is_low = get_child_value(
|
283
|
+
state, "Drivetrain.FuelSystem.LowFuelWarning"
|
284
|
+
)
|
285
|
+
vehicle.air_control_is_on = get_child_value(
|
286
|
+
state, "Cabin.HVAC.Row1.Driver.Blower.SpeedLevel"
|
287
|
+
)
|
288
|
+
vehicle.smart_key_battery_warning_is_on = bool(
|
289
|
+
get_child_value(state, "Electronics.FOB.LowBattery")
|
290
|
+
)
|
291
|
+
|
292
|
+
if get_child_value(state, "Location.GeoCoord.Latitude"):
|
293
|
+
location_last_updated_at = dt.datetime(
|
294
|
+
2000, 1, 1, tzinfo=self.data_timezone
|
295
|
+
)
|
296
|
+
timestamp = get_child_value(state, "Location.TimeStamp")
|
297
|
+
if timestamp is not None:
|
298
|
+
location_last_updated_at = dt.datetime(
|
299
|
+
year=int(get_child_value(timestamp, "Year")),
|
300
|
+
month=int(get_child_value(timestamp, "Mon")),
|
301
|
+
day=int(get_child_value(timestamp, "Day")),
|
302
|
+
hour=int(get_child_value(timestamp, "Hour")),
|
303
|
+
minute=int(get_child_value(timestamp, "Min")),
|
304
|
+
second=int(get_child_value(timestamp, "Sec")),
|
305
|
+
tzinfo=self.data_timezone,
|
306
|
+
)
|
307
|
+
|
308
|
+
vehicle.location = (
|
309
|
+
get_child_value(state, "Location.GeoCoord.Latitude"),
|
310
|
+
get_child_value(state, "Location.GeoCoord.Longitude"),
|
311
|
+
location_last_updated_at,
|
312
|
+
)
|
313
|
+
|
314
|
+
vehicle.data = state
|
@@ -4,7 +4,6 @@
|
|
4
4
|
|
5
5
|
import logging
|
6
6
|
import time
|
7
|
-
import re
|
8
7
|
import datetime as dt
|
9
8
|
import pytz
|
10
9
|
import requests
|
@@ -19,7 +18,7 @@ from .const import (
|
|
19
18
|
TEMPERATURE_UNITS,
|
20
19
|
ENGINE_TYPES,
|
21
20
|
)
|
22
|
-
from .utils import get_child_value, get_float
|
21
|
+
from .utils import get_child_value, get_float, parse_datetime
|
23
22
|
from .ApiImpl import ApiImpl, ClimateRequestOptions
|
24
23
|
from .Token import Token
|
25
24
|
from .Vehicle import DailyDrivingStats, Vehicle
|
@@ -235,8 +234,8 @@ class HyundaiBlueLinkAPIUSA(ApiImpl):
|
|
235
234
|
return None
|
236
235
|
|
237
236
|
def _update_vehicle_properties(self, vehicle: Vehicle, state: dict) -> None:
|
238
|
-
vehicle.last_updated_at =
|
239
|
-
get_child_value(state, "vehicleStatus.dateTime")
|
237
|
+
vehicle.last_updated_at = parse_datetime(
|
238
|
+
get_child_value(state, "vehicleStatus.dateTime"), self.data_timezone
|
240
239
|
)
|
241
240
|
vehicle.total_driving_range = (
|
242
241
|
get_child_value(
|
@@ -428,8 +427,9 @@ class HyundaiBlueLinkAPIUSA(ApiImpl):
|
|
428
427
|
vehicle.location = (
|
429
428
|
get_child_value(state, "vehicleStatus.vehicleLocation.coord.lat"),
|
430
429
|
get_child_value(state, "vehicleStatus.vehicleLocation.coord.lon"),
|
431
|
-
|
432
|
-
get_child_value(state, "vehicleStatus.vehicleLocation.time")
|
430
|
+
parse_datetime(
|
431
|
+
get_child_value(state, "vehicleStatus.vehicleLocation.time"),
|
432
|
+
self.data_timezone,
|
433
433
|
),
|
434
434
|
)
|
435
435
|
vehicle.air_control_is_on = get_child_value(state, "vehicleStatus.airCtrlOn")
|
@@ -636,32 +636,65 @@ class HyundaiBlueLinkAPIUSA(ApiImpl):
|
|
636
636
|
_LOGGER.debug(f"{DOMAIN} - Stop engine response: {response.text}")
|
637
637
|
|
638
638
|
def start_charge(self, token: Token, vehicle: Vehicle) -> None:
|
639
|
-
|
639
|
+
if vehicle.engine_type != ENGINE_TYPES.EV:
|
640
|
+
return {}
|
641
|
+
|
642
|
+
_LOGGER.debug(f"{DOMAIN} - Start charging..")
|
643
|
+
|
644
|
+
url = self.API_URL + "evc/charge/start"
|
645
|
+
headers = self._get_vehicle_headers(token, vehicle)
|
646
|
+
_LOGGER.debug(f"{DOMAIN} - Start charging headers: {headers}")
|
647
|
+
|
648
|
+
response = self.sessions.post(url, headers=headers)
|
649
|
+
_LOGGER.debug(
|
650
|
+
f"{DOMAIN} - Start charge response status code: {response.status_code}"
|
651
|
+
)
|
652
|
+
_LOGGER.debug(f"{DOMAIN} - Start charge response: {response.text}")
|
640
653
|
|
641
654
|
def stop_charge(self, token: Token, vehicle: Vehicle) -> None:
|
642
|
-
|
655
|
+
if vehicle.engine_type != ENGINE_TYPES.EV:
|
656
|
+
return {}
|
643
657
|
|
644
|
-
|
645
|
-
|
646
|
-
|
647
|
-
|
648
|
-
|
649
|
-
|
650
|
-
|
651
|
-
|
652
|
-
|
653
|
-
|
654
|
-
|
655
|
-
|
656
|
-
|
657
|
-
|
658
|
-
|
659
|
-
|
660
|
-
|
661
|
-
|
662
|
-
|
663
|
-
|
664
|
-
|
658
|
+
_LOGGER.debug(f"{DOMAIN} - Stop charging..")
|
659
|
+
|
660
|
+
url = self.API_URL + "evc/charge/stop"
|
661
|
+
headers = self._get_vehicle_headers(token, vehicle)
|
662
|
+
_LOGGER.debug(f"{DOMAIN} - Stop charging headers: {headers}")
|
663
|
+
|
664
|
+
response = self.sessions.post(url, headers=headers)
|
665
|
+
_LOGGER.debug(
|
666
|
+
f"{DOMAIN} - Stop charge response status code: {response.status_code}"
|
667
|
+
)
|
668
|
+
_LOGGER.debug(f"{DOMAIN} - Stop charge response: {response.text}")
|
669
|
+
|
670
|
+
def set_charge_limits(
|
671
|
+
self, token: Token, vehicle: Vehicle, ac: int, dc: int
|
672
|
+
) -> str:
|
673
|
+
if vehicle.engine_type != ENGINE_TYPES.EV:
|
674
|
+
return {}
|
675
|
+
|
676
|
+
_LOGGER.debug(f"{DOMAIN} - Setting charge limits..")
|
677
|
+
url = self.API_URL + "evc/charge/targetsoc/set"
|
678
|
+
headers = self._get_vehicle_headers(token, vehicle)
|
679
|
+
_LOGGER.debug(f"{DOMAIN} - Setting charge limits: {headers}")
|
665
680
|
|
666
|
-
|
667
|
-
|
681
|
+
data = {
|
682
|
+
"targetSOClist": [
|
683
|
+
{
|
684
|
+
"plugType": 0,
|
685
|
+
"targetSOClevel": int(dc),
|
686
|
+
},
|
687
|
+
{
|
688
|
+
"plugType": 1,
|
689
|
+
"targetSOClevel": int(ac),
|
690
|
+
},
|
691
|
+
]
|
692
|
+
}
|
693
|
+
|
694
|
+
_LOGGER.debug(f"{DOMAIN} - Setting charge limits body: {data}")
|
695
|
+
|
696
|
+
response = self.sessions.post(url, json=data, headers=headers)
|
697
|
+
_LOGGER.debug(
|
698
|
+
f"{DOMAIN} - Setting charge limits response status code: {response.status_code}"
|
699
|
+
)
|
700
|
+
_LOGGER.debug(f"{DOMAIN} - Setting charge limits: {response.text}")
|
@@ -4,7 +4,6 @@
|
|
4
4
|
import datetime as dt
|
5
5
|
import logging
|
6
6
|
import random
|
7
|
-
import re
|
8
7
|
import secrets
|
9
8
|
import ssl
|
10
9
|
import string
|
@@ -29,7 +28,7 @@ from .const import (
|
|
29
28
|
TEMPERATURE_UNITS,
|
30
29
|
VEHICLE_LOCK_ACTION,
|
31
30
|
)
|
32
|
-
from .utils import get_child_value
|
31
|
+
from .utils import get_child_value, parse_datetime
|
33
32
|
|
34
33
|
_LOGGER = logging.getLogger(__name__)
|
35
34
|
|
@@ -278,10 +277,11 @@ class KiaUvoAPIUSA(ApiImpl):
|
|
278
277
|
|
279
278
|
def _update_vehicle_properties(self, vehicle: Vehicle, state: dict) -> None:
|
280
279
|
"""Get cached vehicle data and update Vehicle instance with it"""
|
281
|
-
vehicle.last_updated_at =
|
280
|
+
vehicle.last_updated_at = parse_datetime(
|
282
281
|
get_child_value(
|
283
282
|
state, "lastVehicleInfo.vehicleStatusRpt.vehicleStatus.syncDate.utc"
|
284
|
-
)
|
283
|
+
),
|
284
|
+
self.data_timezone,
|
285
285
|
)
|
286
286
|
vehicle.odometer = (
|
287
287
|
get_child_value(state, "vehicleConfig.vehicleDetail.vehicle.mileage"),
|
@@ -515,8 +515,9 @@ class KiaUvoAPIUSA(ApiImpl):
|
|
515
515
|
vehicle.location = (
|
516
516
|
get_child_value(state, "lastVehicleInfo.location.coord.lat"),
|
517
517
|
get_child_value(state, "lastVehicleInfo.location.coord.lon"),
|
518
|
-
|
519
|
-
get_child_value(state, "lastVehicleInfo.location.syncDate.utc")
|
518
|
+
parse_datetime(
|
519
|
+
get_child_value(state, "lastVehicleInfo.location.syncDate.utc"),
|
520
|
+
self.data_timezone,
|
520
521
|
),
|
521
522
|
)
|
522
523
|
|
@@ -534,25 +535,6 @@ class KiaUvoAPIUSA(ApiImpl):
|
|
534
535
|
|
535
536
|
vehicle.data = state
|
536
537
|
|
537
|
-
def get_last_updated_at(self, value) -> dt.datetime:
|
538
|
-
_LOGGER.debug(f"{DOMAIN} - last_updated_at - before {value}")
|
539
|
-
if value is None:
|
540
|
-
value = dt.datetime(2000, 1, 1, tzinfo=self.data_timezone)
|
541
|
-
else:
|
542
|
-
m = re.match(r"(\d{4})(\d{2})(\d{2})(\d{2})(\d{2})(\d{2})", value)
|
543
|
-
value = dt.datetime(
|
544
|
-
year=int(m.group(1)),
|
545
|
-
month=int(m.group(2)),
|
546
|
-
day=int(m.group(3)),
|
547
|
-
hour=int(m.group(4)),
|
548
|
-
minute=int(m.group(5)),
|
549
|
-
second=int(m.group(6)),
|
550
|
-
tzinfo=self.data_timezone,
|
551
|
-
)
|
552
|
-
|
553
|
-
_LOGGER.debug(f"{DOMAIN} - last_updated_at - after {value}")
|
554
|
-
return value
|
555
|
-
|
556
538
|
def _get_cached_vehicle_state(self, token: Token, vehicle: Vehicle) -> dict:
|
557
539
|
url = self.API_URL + "cmm/gvi"
|
558
540
|
|
@@ -7,7 +7,6 @@ import datetime as dt
|
|
7
7
|
import math
|
8
8
|
import logging
|
9
9
|
import random
|
10
|
-
import re
|
11
10
|
import uuid
|
12
11
|
from time import sleep
|
13
12
|
from urllib.parse import parse_qs, urlparse
|
@@ -57,6 +56,7 @@ from .utils import (
|
|
57
56
|
get_child_value,
|
58
57
|
get_index_into_hex_temp,
|
59
58
|
get_hex_temp_into_index,
|
59
|
+
parse_datetime,
|
60
60
|
)
|
61
61
|
|
62
62
|
_LOGGER = logging.getLogger(__name__)
|
@@ -190,29 +190,11 @@ class KiaUvoApiAU(ApiImplType1):
|
|
190
190
|
VIN=entry["vin"],
|
191
191
|
timezone=self.data_timezone,
|
192
192
|
engine_type=entry_engine_type,
|
193
|
+
ccu_ccs2_protocol_support=entry["ccuCCS2ProtocolSupport"],
|
193
194
|
)
|
194
195
|
result.append(vehicle)
|
195
196
|
return result
|
196
197
|
|
197
|
-
def get_last_updated_at(self, value) -> dt.datetime:
|
198
|
-
_LOGGER.debug(f"{DOMAIN} - last_updated_at - before {value}")
|
199
|
-
if value is None:
|
200
|
-
value = dt.datetime(2000, 1, 1, tzinfo=self.data_timezone)
|
201
|
-
else:
|
202
|
-
m = re.match(r"(\d{4})(\d{2})(\d{2})(\d{2})(\d{2})(\d{2})", value)
|
203
|
-
value = dt.datetime(
|
204
|
-
year=int(m.group(1)),
|
205
|
-
month=int(m.group(2)),
|
206
|
-
day=int(m.group(3)),
|
207
|
-
hour=int(m.group(4)),
|
208
|
-
minute=int(m.group(5)),
|
209
|
-
second=int(m.group(6)),
|
210
|
-
tzinfo=self.data_timezone,
|
211
|
-
)
|
212
|
-
|
213
|
-
_LOGGER.debug(f"{DOMAIN} - last_updated_at - after {value}")
|
214
|
-
return value
|
215
|
-
|
216
198
|
def _get_time_from_string(self, value, timesection) -> dt.datetime.time:
|
217
199
|
if value is not None:
|
218
200
|
lastTwo = int(value[-2:])
|
@@ -228,15 +210,35 @@ class KiaUvoApiAU(ApiImplType1):
|
|
228
210
|
return value
|
229
211
|
|
230
212
|
def update_vehicle_with_cached_state(self, token: Token, vehicle: Vehicle) -> None:
|
231
|
-
|
232
|
-
|
233
|
-
|
234
|
-
|
235
|
-
|
236
|
-
|
237
|
-
|
238
|
-
|
239
|
-
|
213
|
+
url = self.SPA_API_URL + "vehicles/" + vehicle.id
|
214
|
+
is_ccs2 = vehicle.ccu_ccs2_protocol_support != 0
|
215
|
+
if is_ccs2:
|
216
|
+
url += "/ccs2/carstatus/latest"
|
217
|
+
else:
|
218
|
+
url += "/status/latest"
|
219
|
+
|
220
|
+
response = requests.get(
|
221
|
+
url,
|
222
|
+
headers=self._get_authenticated_headers(
|
223
|
+
token, vehicle.ccu_ccs2_protocol_support
|
224
|
+
),
|
225
|
+
).json()
|
226
|
+
|
227
|
+
_LOGGER.debug(f"{DOMAIN} - get_cached_vehicle_status response: {response}")
|
228
|
+
_check_response_for_errors(response)
|
229
|
+
|
230
|
+
if is_ccs2:
|
231
|
+
state = response["resMsg"]["state"]["Vehicle"]
|
232
|
+
self._update_vehicle_properties_ccs2(vehicle, state)
|
233
|
+
else:
|
234
|
+
location = self._get_location(token, vehicle)
|
235
|
+
self._update_vehicle_properties(
|
236
|
+
vehicle,
|
237
|
+
{
|
238
|
+
"status": response["resMsg"],
|
239
|
+
"vehicleLocation": location,
|
240
|
+
},
|
241
|
+
)
|
240
242
|
|
241
243
|
if vehicle.engine_type == ENGINE_TYPES.EV:
|
242
244
|
try:
|
@@ -253,8 +255,8 @@ class KiaUvoApiAU(ApiImplType1):
|
|
253
255
|
""",
|
254
256
|
exc_info=e,
|
255
257
|
)
|
256
|
-
|
257
|
-
|
258
|
+
else:
|
259
|
+
self._update_vehicle_drive_info(vehicle, state)
|
258
260
|
|
259
261
|
def force_refresh_vehicle_state(self, token: Token, vehicle: Vehicle) -> None:
|
260
262
|
status = self._get_forced_vehicle_state(token, vehicle)
|
@@ -287,8 +289,8 @@ class KiaUvoApiAU(ApiImplType1):
|
|
287
289
|
|
288
290
|
def _update_vehicle_properties(self, vehicle: Vehicle, state: dict) -> None:
|
289
291
|
if get_child_value(state, "status.time"):
|
290
|
-
vehicle.last_updated_at =
|
291
|
-
get_child_value(state, "status.time")
|
292
|
+
vehicle.last_updated_at = parse_datetime(
|
293
|
+
get_child_value(state, "status.time"), self.data_timezone
|
292
294
|
)
|
293
295
|
else:
|
294
296
|
vehicle.last_updated_at = dt.datetime.now(self.data_timezone)
|
@@ -480,7 +482,7 @@ class KiaUvoApiAU(ApiImplType1):
|
|
480
482
|
vehicle.ev_charge_limits_dc = [
|
481
483
|
x["targetSOClevel"] for x in target_soc_list if x["plugType"] == 0
|
482
484
|
][-1]
|
483
|
-
except:
|
485
|
+
except Exception:
|
484
486
|
_LOGGER.debug(f"{DOMAIN} - SOC Levels couldn't be found. May not be an EV.")
|
485
487
|
if (
|
486
488
|
get_child_value(
|
@@ -636,8 +638,8 @@ class KiaUvoApiAU(ApiImplType1):
|
|
636
638
|
vehicle.location = (
|
637
639
|
get_child_value(state, "vehicleLocation.coord.lat"),
|
638
640
|
get_child_value(state, "vehicleLocation.coord.lon"),
|
639
|
-
|
640
|
-
get_child_value(state, "vehicleLocation.time")
|
641
|
+
parse_datetime(
|
642
|
+
get_child_value(state, "vehicleLocation.time"), self.data_timezone
|
641
643
|
),
|
642
644
|
)
|
643
645
|
vehicle.data = state
|
@@ -647,18 +649,6 @@ class KiaUvoApiAU(ApiImplType1):
|
|
647
649
|
vehicle.power_consumption_30d = get_child_value(state, "consumption30d")
|
648
650
|
vehicle.daily_stats = get_child_value(state, "dailyStats")
|
649
651
|
|
650
|
-
def _get_cached_vehicle_state(self, token: Token, vehicle: Vehicle) -> dict:
|
651
|
-
url = self.SPA_API_URL + "vehicles/" + vehicle.id + "/status/latest"
|
652
|
-
|
653
|
-
response = requests.get(
|
654
|
-
url, headers=self._get_authenticated_headers(token)
|
655
|
-
).json()
|
656
|
-
_LOGGER.debug(f"{DOMAIN} - get_cached_vehicle_status response: {response}")
|
657
|
-
_check_response_for_errors(response)
|
658
|
-
response = response["resMsg"]
|
659
|
-
|
660
|
-
return response
|
661
|
-
|
662
652
|
def _get_location(self, token: Token, vehicle: Vehicle) -> dict:
|
663
653
|
url = self.SPA_API_URL + "vehicles/" + vehicle.id + "/location/park"
|
664
654
|
|
@@ -669,7 +659,7 @@ class KiaUvoApiAU(ApiImplType1):
|
|
669
659
|
_LOGGER.debug(f"{DOMAIN} - _get_location response: {response}")
|
670
660
|
_check_response_for_errors(response)
|
671
661
|
return response["resMsg"]["gpsDetail"]
|
672
|
-
except:
|
662
|
+
except Exception:
|
673
663
|
_LOGGER.debug(f"{DOMAIN} - _get_location failed")
|
674
664
|
return None
|
675
665
|
|