hyundai-kia-connect-api 3.17.10__py2.py3-none-any.whl → 3.18.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.
@@ -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(self, token: Token) -> dict:
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": self.ccu_ccs2_protocol_support,
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 = self.get_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
- self.get_last_updated_at(
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")
@@ -640,28 +640,3 @@ class HyundaiBlueLinkAPIUSA(ApiImpl):
640
640
 
641
641
  def stop_charge(self, token: Token, vehicle: Vehicle) -> None:
642
642
  pass
643
-
644
- def get_last_updated_at(self, value) -> dt.datetime:
645
- _LOGGER.debug(f"{DOMAIN} - last_updated_at - before {value}")
646
- if value is None:
647
- value = dt.datetime(2000, 1, 1, tzinfo=self.data_timezone)
648
- else:
649
- value = (
650
- value.replace("-", "")
651
- .replace("T", "")
652
- .replace(":", "")
653
- .replace("Z", "")
654
- )
655
- m = re.match(r"(\d{4})(\d{2})(\d{2})(\d{2})(\d{2})(\d{2})", value)
656
- value = dt.datetime(
657
- year=int(m.group(1)),
658
- month=int(m.group(2)),
659
- day=int(m.group(3)),
660
- hour=int(m.group(4)),
661
- minute=int(m.group(5)),
662
- second=int(m.group(6)),
663
- tzinfo=self.data_timezone,
664
- )
665
-
666
- _LOGGER.debug(f"{DOMAIN} - last_updated_at - after {value}")
667
- return value
@@ -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 = self.get_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
- self.get_last_updated_at(
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
- status = self._get_cached_vehicle_state(token, vehicle)
232
- location = self._get_location(token, vehicle)
233
- self._update_vehicle_properties(
234
- vehicle,
235
- {
236
- "status": status,
237
- "vehicleLocation": location,
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
- else:
257
- self._update_vehicle_drive_info(vehicle, state)
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 = self.get_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
- self.get_last_updated_at(
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
 
@@ -5,7 +5,6 @@
5
5
  import datetime as dt
6
6
  import json
7
7
  import logging
8
- import re
9
8
 
10
9
  import pytz
11
10
  import requests
@@ -35,6 +34,7 @@ from .utils import (
35
34
  get_child_value,
36
35
  get_hex_temp_into_index,
37
36
  get_index_into_hex_temp,
37
+ parse_datetime,
38
38
  )
39
39
 
40
40
  import ssl
@@ -202,8 +202,8 @@ class KiaUvoApiCA(ApiImpl):
202
202
 
203
203
  # Calculate offset between vehicle last_updated_at and UTC
204
204
  self.vehicle_timezone = vehicle.timezone
205
- last_updated_at = self.get_last_updated_at(
206
- get_child_value(state, "status.lastStatusDate")
205
+ last_updated_at = parse_datetime(
206
+ get_child_value(state, "status.lastStatusDate"), self.data_timezone
207
207
  )
208
208
  now_utc: dt = dt.datetime.now(pytz.utc)
209
209
  offset = round((last_updated_at - now_utc).total_seconds() / 3600)
@@ -238,8 +238,8 @@ class KiaUvoApiCA(ApiImpl):
238
238
  def _update_vehicle_properties_base(self, vehicle: Vehicle, state: dict) -> None:
239
239
  _LOGGER.debug(f"{DOMAIN} - Old Vehicle Last Updated: {vehicle.last_updated_at}")
240
240
  self.vehicle_timezone = vehicle.timezone
241
- vehicle.last_updated_at = self.get_last_updated_at(
242
- get_child_value(state, "status.lastStatusDate")
241
+ vehicle.last_updated_at = parse_datetime(
242
+ get_child_value(state, "status.lastStatusDate"), self.data_timezone
243
243
  )
244
244
  _LOGGER.debug(
245
245
  f"{DOMAIN} - Current Vehicle Last Updated: {vehicle.last_updated_at}"
@@ -426,29 +426,10 @@ class KiaUvoApiCA(ApiImpl):
426
426
  vehicle.location = (
427
427
  get_child_value(state, "coord.lat"),
428
428
  get_child_value(state, "coord.lon"),
429
- self.get_last_updated_at(get_child_value(state, "time")),
429
+ parse_datetime(get_child_value(state, "time"), self.data_timezone),
430
430
  )
431
431
  vehicle.data["vehicleLocation"] = state
432
432
 
433
- def get_last_updated_at(self, value) -> dt.datetime:
434
- _LOGGER.debug(f"{DOMAIN} - last_updated_at - before {value}")
435
- if value is None:
436
- value = dt.datetime(2000, 1, 1, tzinfo=self.vehicle_timezone)
437
- else:
438
- m = re.match(r"(\d{4})(\d{2})(\d{2})(\d{2})(\d{2})(\d{2})", value)
439
- value = dt.datetime(
440
- year=int(m.group(1)),
441
- month=int(m.group(2)),
442
- day=int(m.group(3)),
443
- hour=int(m.group(4)),
444
- minute=int(m.group(5)),
445
- second=int(m.group(6)),
446
- tzinfo=self.vehicle_timezone,
447
- )
448
-
449
- _LOGGER.debug(f"{DOMAIN} - last_updated_at - after {value}")
450
- return value
451
-
452
433
  def _get_cached_vehicle_state(self, token: Token, vehicle: Vehicle) -> dict:
453
434
  # Vehicle Status Call
454
435
  url = self.API_URL + "lstvhclsts"
@@ -5,7 +5,6 @@
5
5
  import datetime as dt
6
6
  import math
7
7
  import logging
8
- import re
9
8
  import uuid
10
9
  from time import sleep
11
10
  from urllib.parse import parse_qs, urlparse
@@ -56,6 +55,7 @@ from .utils import (
56
55
  get_child_value,
57
56
  get_index_into_hex_temp,
58
57
  get_hex_temp_into_index,
58
+ parse_datetime,
59
59
  )
60
60
 
61
61
  _LOGGER = logging.getLogger(__name__)
@@ -212,25 +212,6 @@ class KiaUvoApiCN(ApiImplType1):
212
212
  result.append(vehicle)
213
213
  return result
214
214
 
215
- def get_last_updated_at(self, value) -> dt.datetime:
216
- _LOGGER.debug(f"{DOMAIN} - last_updated_at - before {value}")
217
- if value is None:
218
- value = dt.datetime(2000, 1, 1, tzinfo=self.data_timezone)
219
- else:
220
- m = re.match(r"(\d{4})(\d{2})(\d{2})(\d{2})(\d{2})(\d{2})", value)
221
- value = dt.datetime(
222
- year=int(m.group(1)),
223
- month=int(m.group(2)),
224
- day=int(m.group(3)),
225
- hour=int(m.group(4)),
226
- minute=int(m.group(5)),
227
- second=int(m.group(6)),
228
- tzinfo=self.data_timezone,
229
- )
230
-
231
- _LOGGER.debug(f"{DOMAIN} - last_updated_at - after {value}")
232
- return value
233
-
234
215
  def _get_time_from_string(self, value, timesection) -> dt.datetime.time:
235
216
  if value is not None:
236
217
  lastTwo = int(value[-2:])
@@ -293,8 +274,8 @@ class KiaUvoApiCN(ApiImplType1):
293
274
 
294
275
  def _update_vehicle_properties(self, vehicle: Vehicle, state: dict) -> None:
295
276
  if get_child_value(state, "status.time"):
296
- vehicle.last_updated_at = self.get_last_updated_at(
297
- get_child_value(state, "status.time")
277
+ vehicle.last_updated_at = parse_datetime(
278
+ get_child_value(state, "status.time"), self.data_timezone
298
279
  )
299
280
  else:
300
281
  vehicle.last_updated_at = dt.datetime.now(self.data_timezone)
@@ -644,8 +625,8 @@ class KiaUvoApiCN(ApiImplType1):
644
625
  vehicle.location = (
645
626
  get_child_value(state, "vehicleLocation.coord.lat"),
646
627
  get_child_value(state, "vehicleLocation.coord.lon"),
647
- self.get_last_updated_at(
648
- get_child_value(state, "vehicleLocation.time")
628
+ parse_datetime(
629
+ get_child_value(state, "vehicleLocation.time"), self.data_timezone
649
630
  ),
650
631
  )
651
632
  vehicle.data = state
@@ -6,7 +6,6 @@ import base64
6
6
  import random
7
7
  import datetime as dt
8
8
  import logging
9
- import re
10
9
  import uuid
11
10
  from time import sleep
12
11
  from urllib.parse import parse_qs, urlparse
@@ -60,6 +59,7 @@ from .utils import (
60
59
  get_child_value,
61
60
  get_index_into_hex_temp,
62
61
  get_hex_temp_into_index,
62
+ parse_datetime,
63
63
  )
64
64
 
65
65
  _LOGGER = logging.getLogger(__name__)
@@ -134,7 +134,6 @@ class KiaUvoApiEU(ApiImplType1):
134
134
  temperature_range = [x * 0.5 for x in range(28, 60)]
135
135
 
136
136
  def __init__(self, region: int, brand: int, language: str) -> None:
137
- self.ccu_ccs2_protocol_support = None
138
137
  language = language.lower()
139
138
  # Strip language variants (e.g. en-Gb)
140
139
  if len(language) > 2:
@@ -296,25 +295,6 @@ class KiaUvoApiEU(ApiImplType1):
296
295
  result.append(vehicle)
297
296
  return result
298
297
 
299
- def get_last_updated_at(self, value) -> dt.datetime:
300
- _LOGGER.debug(f"{DOMAIN} - last_updated_at - before {value}")
301
- if value is None:
302
- value = dt.datetime(2000, 1, 1, tzinfo=self.data_timezone)
303
- else:
304
- m = re.match(r"(\d{4})(\d{2})(\d{2})(\d{2})(\d{2})(\d{2})", value)
305
- value = dt.datetime(
306
- year=int(m.group(1)),
307
- month=int(m.group(2)),
308
- day=int(m.group(3)),
309
- hour=int(m.group(4)),
310
- minute=int(m.group(5)),
311
- second=int(m.group(6)),
312
- tzinfo=self.data_timezone,
313
- )
314
-
315
- _LOGGER.debug(f"{DOMAIN} - last_updated_at - after {value}")
316
- return value
317
-
318
298
  def _get_time_from_string(self, value, timesection) -> dt.datetime.time:
319
299
  if value is not None:
320
300
  lastTwo = int(value[-2:])
@@ -330,12 +310,29 @@ class KiaUvoApiEU(ApiImplType1):
330
310
  return value
331
311
 
332
312
  def update_vehicle_with_cached_state(self, token: Token, vehicle: Vehicle) -> None:
333
- state = self._get_cached_vehicle_state(token, vehicle)
334
- self.ccu_ccs2_protocol_support = str(vehicle.ccu_ccs2_protocol_support)
313
+ url = self.SPA_API_URL + "vehicles/" + vehicle.id
314
+ is_ccs2 = vehicle.ccu_ccs2_protocol_support != 0
315
+ if is_ccs2:
316
+ url += "/ccs2/carstatus/latest"
317
+ else:
318
+ url += "/status/latest"
319
+
320
+ response = requests.get(
321
+ url,
322
+ headers=self._get_authenticated_headers(
323
+ token, vehicle.ccu_ccs2_protocol_support
324
+ ),
325
+ ).json()
326
+
327
+ _LOGGER.debug(f"{DOMAIN} - get_cached_vehicle_status response: {response}")
328
+ _check_response_for_errors(response)
335
329
 
336
330
  if vehicle.ccu_ccs2_protocol_support == 0:
337
- self._update_vehicle_properties(vehicle, state)
331
+ self._update_vehicle_properties(
332
+ vehicle, response["resMsg"]["vehicleStatusInfo"]
333
+ )
338
334
  else:
335
+ state = response["resMsg"]["state"]["Vehicle"]
339
336
  self._update_vehicle_properties_ccs2(vehicle, state)
340
337
 
341
338
  if (
@@ -385,281 +382,10 @@ class KiaUvoApiEU(ApiImplType1):
385
382
  else:
386
383
  self._update_vehicle_drive_info(vehicle, state)
387
384
 
388
- def _update_vehicle_properties_ccs2(self, vehicle: Vehicle, state: dict) -> None:
389
- if get_child_value(state, "Date"):
390
- vehicle.last_updated_at = self.get_last_updated_at(
391
- get_child_value(state, "Date")
392
- )
393
- else:
394
- vehicle.last_updated_at = dt.datetime.now(self.data_timezone)
395
-
396
- vehicle.odometer = (
397
- get_child_value(state, "Drivetrain.Odometer"),
398
- DISTANCE_UNITS[1],
399
- )
400
- vehicle.car_battery_percentage = get_child_value(
401
- state, "Electronics.Battery.Level"
402
- )
403
-
404
- vehicle.engine_is_running = get_child_value(state, "DrivingReady")
405
-
406
- air_temp = get_child_value(
407
- state,
408
- "Cabin.HVAC.Row1.Driver.Temperature.Value",
409
- )
410
-
411
- if air_temp != "OFF":
412
- vehicle.air_temperature = (air_temp, TEMPERATURE_UNITS[1])
413
-
414
- defrost_is_on = get_child_value(state, "Body.Windshield.Front.Defog.State")
415
- if defrost_is_on in [0, 2]:
416
- vehicle.defrost_is_on = False
417
- elif defrost_is_on == 1:
418
- vehicle.defrost_is_on = True
419
-
420
- steer_wheel_heat = get_child_value(state, "Cabin.SteeringWheel.Heat.State")
421
- if steer_wheel_heat in [0, 2]:
422
- vehicle.steering_wheel_heater_is_on = False
423
- elif steer_wheel_heat == 1:
424
- vehicle.steering_wheel_heater_is_on = True
425
-
426
- defrost_rear_is_on = get_child_value(state, "Body.Windshield.Rear.Defog.State")
427
- if defrost_rear_is_on in [0, 2]:
428
- vehicle.back_window_heater_is_on = False
429
- elif defrost_rear_is_on == 1:
430
- vehicle.back_window_heater_is_on = True
431
-
432
- # TODO: status.sideMirrorHeat
433
-
434
- vehicle.front_left_seat_status = SEAT_STATUS[
435
- get_child_value(state, "Cabin.Seat.Row1.Driver.Climate.State")
436
- ]
437
-
438
- vehicle.front_right_seat_status = SEAT_STATUS[
439
- get_child_value(state, "Cabin.Seat.Row1.Passenger.Climate.State")
440
- ]
441
-
442
- vehicle.rear_left_seat_status = SEAT_STATUS[
443
- get_child_value(state, "Cabin.Seat.Row2.Left.Climate.State")
444
- ]
445
-
446
- vehicle.rear_right_seat_status = SEAT_STATUS[
447
- get_child_value(state, "Cabin.Seat.Row2.Right.Climate.State")
448
- ]
449
-
450
- # TODO: status.doorLock
451
-
452
- vehicle.front_left_door_is_open = get_child_value(
453
- state, "Cabin.Door.Row1.Driver.Open"
454
- )
455
- vehicle.front_right_door_is_open = get_child_value(
456
- state, "Cabin.Door.Row1.Passenger.Open"
457
- )
458
- vehicle.back_left_door_is_open = get_child_value(
459
- state, "Cabin.Door.Row2.Left.Open"
460
- )
461
- vehicle.back_right_door_is_open = get_child_value(
462
- state, "Cabin.Door.Row2.Right.Open"
463
- )
464
-
465
- # TODO: should the windows and trunc also be checked?
466
- vehicle.is_locked = not (
467
- vehicle.front_left_door_is_open
468
- or vehicle.front_right_door_is_open
469
- or vehicle.back_left_door_is_open
470
- or vehicle.back_right_door_is_open
471
- )
472
-
473
- vehicle.hood_is_open = get_child_value(state, "Body.Hood.Open")
474
- vehicle.front_left_window_is_open = get_child_value(
475
- state, "Cabin.Window.Row1.Driver.Open"
476
- )
477
- vehicle.front_right_window_is_open = get_child_value(
478
- state, "Cabin.Window.Row1.Passenger.Open"
479
- )
480
- vehicle.back_left_window_is_open = get_child_value(
481
- state, "Cabin.Window.Row2.Left.Open"
482
- )
483
- vehicle.back_right_window_is_open = get_child_value(
484
- state, "Cabin.Window.Row2.Right.Open"
485
- )
486
- vehicle.tire_pressure_rear_left_warning_is_on = bool(
487
- get_child_value(state, "Chassis.Axle.Row2.Left.Tire.PressureLow")
488
- )
489
- vehicle.tire_pressure_front_left_warning_is_on = bool(
490
- get_child_value(state, "Chassis.Axle.Row1.Left.Tire.PressureLow")
491
- )
492
- vehicle.tire_pressure_front_right_warning_is_on = bool(
493
- get_child_value(state, "Chassis.Axle.Row1.Right.Tire.PressureLow")
494
- )
495
- vehicle.tire_pressure_rear_right_warning_is_on = bool(
496
- get_child_value(state, "Chassis.Axle.Row2.Right.Tire.PressureLow")
497
- )
498
- vehicle.tire_pressure_all_warning_is_on = bool(
499
- get_child_value(state, "Chassis.Axle.Tire.PressureLow")
500
- )
501
- vehicle.trunk_is_open = get_child_value(state, "Body.Trunk.Open")
502
-
503
- vehicle.ev_battery_percentage = get_child_value(
504
- state, "Green.BatteryManagement.BatteryRemain.Ratio"
505
- )
506
- vehicle.ev_battery_remain = get_child_value(
507
- state, "Green.BatteryManagement.BatteryRemain.Value"
508
- )
509
- vehicle.ev_battery_capacity = get_child_value(
510
- state, "Green.BatteryManagement.BatteryCapacity.Value"
511
- )
512
- vehicle.ev_battery_soh_percentage = get_child_value(
513
- state, "Green.BatteryManagement.SoH.Ratio"
514
- )
515
- vehicle.ev_battery_is_plugged_in = get_child_value(
516
- state, "Green.ChargingInformation.ElectricCurrentLevel.State"
517
- )
518
- vehicle.ev_battery_is_plugged_in = get_child_value(
519
- state, "Green.ChargingInformation.ConnectorFastening.State"
520
- )
521
- charging_door_state = get_child_value(state, "Green.ChargingDoor.State")
522
- if charging_door_state in [0, 2]:
523
- vehicle.ev_charge_port_door_is_open = False
524
- elif charging_door_state == 1:
525
- vehicle.ev_charge_port_door_is_open = True
526
-
527
- vehicle.total_driving_range = (
528
- float(
529
- get_child_value(
530
- state,
531
- "Drivetrain.FuelSystem.DTE.Total", # noqa
532
- )
533
- ),
534
- DISTANCE_UNITS[
535
- get_child_value(
536
- state,
537
- "Drivetrain.FuelSystem.DTE.Unit", # noqa
538
- )
539
- ],
540
- )
541
-
542
- if vehicle.engine_type == ENGINE_TYPES.EV:
543
- # ev_driving_range is the same as total_driving_range for pure EV
544
- vehicle.ev_driving_range = (
545
- vehicle.total_driving_range,
546
- vehicle.total_driving_range_unit,
547
- )
548
- # TODO: vehicle.ev_driving_range for non EV
549
-
550
- vehicle.washer_fluid_warning_is_on = get_child_value(
551
- state, "Body.Windshield.Front.WasherFluid.LevelLow"
552
- )
553
-
554
- vehicle.ev_estimated_current_charge_duration = (
555
- get_child_value(state, "Green.ChargingInformation.Charging.RemainTime"),
556
- "m",
557
- )
558
- vehicle.ev_estimated_fast_charge_duration = (
559
- get_child_value(state, "Green.ChargingInformation.EstimatedTime.Standard"),
560
- "m",
561
- )
562
- vehicle.ev_estimated_portable_charge_duration = (
563
- get_child_value(state, "Green.ChargingInformation.EstimatedTime.ICCB"),
564
- "m",
565
- )
566
- vehicle.ev_estimated_station_charge_duration = (
567
- get_child_value(state, "Green.ChargingInformation.EstimatedTime.Quick"),
568
- "m",
569
- )
570
- vehicle.ev_charge_limits_ac = get_child_value(
571
- state, "Green.ChargingInformation.TargetSoC.Standard"
572
- )
573
- vehicle.ev_charge_limits_dc = get_child_value(
574
- state, "Green.ChargingInformation.TargetSoC.Quick"
575
- )
576
- vehicle.ev_v2l_discharge_limit = get_child_value(
577
- state, "Green.Electric.SmartGrid.VehicleToLoad.DischargeLimitation.SoC"
578
- )
579
- vehicle.ev_target_range_charge_AC = (
580
- get_child_value(
581
- state,
582
- "Green.ChargingInformation.DTE.TargetSoC.Standard", # noqa
583
- ),
584
- DISTANCE_UNITS[
585
- get_child_value(
586
- state,
587
- "Drivetrain.FuelSystem.DTE.Unit", # noqa
588
- )
589
- ],
590
- )
591
- vehicle.ev_target_range_charge_DC = (
592
- get_child_value(
593
- state,
594
- "Green.ChargingInformation.DTE.TargetSoC.Quick", # noqa
595
- ),
596
- DISTANCE_UNITS[
597
- get_child_value(
598
- state,
599
- "Drivetrain.FuelSystem.DTE.Unit", # noqa
600
- )
601
- ],
602
- )
603
- vehicle.ev_first_departure_enabled = bool(
604
- get_child_value(state, "Green.Reservation.Departure.Schedule1.Enable")
605
- )
606
-
607
- vehicle.ev_second_departure_enabled = bool(
608
- get_child_value(state, "Green.Reservation.Departure.Schedule2.Enable")
609
- )
610
-
611
- # TODO: vehicle.ev_first_departure_days --> Green.Reservation.Departure.Schedule1.(Mon,Tue,Wed,Thu,Fri,Sat,Sun) # noqa
612
- # TODO: vehicle.ev_second_departure_days --> Green.Reservation.Departure.Schedule2.(Mon,Tue,Wed,Thu,Fri,Sat,Sun) # noqa
613
- # TODO: vehicle.ev_first_departure_time --> Green.Reservation.Departure.Schedule1.(Min,Hour) # noqa
614
- # TODO: vehicle.ev_second_departure_time --> Green.Reservation.Departure.Schedule2.(Min,Hour) # noqa
615
- # TODO: vehicle.ev_off_peak_charge_only_enabled --> unknown settings are in --> Green.Reservation.OffPeakTime and OffPeakTime2 # noqa
616
-
617
- vehicle.washer_fluid_warning_is_on = get_child_value(
618
- state, "Body.Windshield.Front.WasherFluid.LevelLow"
619
- )
620
- vehicle.brake_fluid_warning_is_on = get_child_value(
621
- state, "Chassis.Brake.Fluid.Warning"
622
- )
623
-
624
- vehicle.fuel_level = get_child_value(state, "Drivetrain.FuelSystem.FuelLevel")
625
- vehicle.fuel_level_is_low = get_child_value(
626
- state, "Drivetrain.FuelSystem.LowFuelWarning"
627
- )
628
- vehicle.air_control_is_on = get_child_value(
629
- state, "Cabin.HVAC.Row1.Driver.Blower.SpeedLevel"
630
- )
631
- vehicle.smart_key_battery_warning_is_on = bool(
632
- get_child_value(state, "Electronics.FOB.LowBattery")
633
- )
634
-
635
- if get_child_value(state, "Location.GeoCoord.Latitude"):
636
- location_last_updated_at = dt.datetime(
637
- 2000, 1, 1, tzinfo=self.data_timezone
638
- )
639
- timestamp = get_child_value(state, "Location.TimeStamp")
640
- if timestamp is not None:
641
- location_last_updated_at = dt.datetime(
642
- year=int(get_child_value(timestamp, "Year")),
643
- month=int(get_child_value(timestamp, "Mon")),
644
- day=int(get_child_value(timestamp, "Day")),
645
- hour=int(get_child_value(timestamp, "Hour")),
646
- minute=int(get_child_value(timestamp, "Min")),
647
- second=int(get_child_value(timestamp, "Sec")),
648
- tzinfo=self.data_timezone,
649
- )
650
-
651
- vehicle.location = (
652
- get_child_value(state, "Location.GeoCoord.Latitude"),
653
- get_child_value(state, "Location.GeoCoord.Longitude"),
654
- location_last_updated_at,
655
- )
656
-
657
- vehicle.data = state
658
-
659
385
  def _update_vehicle_properties(self, vehicle: Vehicle, state: dict) -> None:
660
386
  if get_child_value(state, "vehicleStatus.time"):
661
- vehicle.last_updated_at = self.get_last_updated_at(
662
- get_child_value(state, "vehicleStatus.time")
387
+ vehicle.last_updated_at = parse_datetime(
388
+ get_child_value(state, "vehicleStatus.time"), self.data_timezone
663
389
  )
664
390
  else:
665
391
  vehicle.last_updated_at = dt.datetime.now(self.data_timezone)
@@ -855,7 +581,7 @@ class KiaUvoApiEU(ApiImplType1):
855
581
  vehicle.ev_charge_limits_dc = [
856
582
  x["targetSOClevel"] for x in target_soc_list if x["plugType"] == 0
857
583
  ][-1]
858
- except:
584
+ except Exception:
859
585
  _LOGGER.debug(f"{DOMAIN} - SOC Levels couldn't be found. May not be an EV.")
860
586
  if (
861
587
  get_child_value(
@@ -1011,8 +737,8 @@ class KiaUvoApiEU(ApiImplType1):
1011
737
  vehicle.location = (
1012
738
  get_child_value(state, "vehicleLocation.coord.lat"),
1013
739
  get_child_value(state, "vehicleLocation.coord.lon"),
1014
- self.get_last_updated_at(
1015
- get_child_value(state, "vehicleLocation.time")
740
+ parse_datetime(
741
+ get_child_value(state, "vehicleLocation.time"), self.data_timezone
1016
742
  ),
1017
743
  )
1018
744
  vehicle.data = state
@@ -1030,7 +756,10 @@ class KiaUvoApiEU(ApiImplType1):
1030
756
  else:
1031
757
  url = url + "/ccs2/carstatus/latest"
1032
758
  response = requests.get(
1033
- url, headers=self._get_authenticated_headers(token)
759
+ url,
760
+ headers=self._get_authenticated_headers(
761
+ token, vehicle.ccu_ccs2_protocol_support
762
+ ),
1034
763
  ).json()
1035
764
  _LOGGER.debug(f"{DOMAIN} - get_cached_vehicle_status response: {response}")
1036
765
  _check_response_for_errors(response)
@@ -1050,7 +779,7 @@ class KiaUvoApiEU(ApiImplType1):
1050
779
  _LOGGER.debug(f"{DOMAIN} - _get_location response: {response}")
1051
780
  _check_response_for_errors(response)
1052
781
  return response["resMsg"]["gpsDetail"]
1053
- except:
782
+ except Exception:
1054
783
  _LOGGER.warning(f"{DOMAIN} - _get_location failed")
1055
784
  return None
1056
785
 
@@ -7,7 +7,7 @@ import typing
7
7
  from dataclasses import dataclass, field
8
8
 
9
9
  from .utils import get_float
10
- from .const import *
10
+ from .const import DISTANCE_UNITS
11
11
 
12
12
  _LOGGER = logging.getLogger(__name__)
13
13
 
@@ -1,16 +1,19 @@
1
1
  # pylint:disable=bare-except,missing-function-docstring,invalid-name
2
2
  """utils.py"""
3
3
 
4
+ import datetime
5
+ import re
6
+
4
7
 
5
8
  def get_child_value(data, key):
6
9
  value = data
7
10
  for x in key.split("."):
8
11
  try:
9
12
  value = value[x]
10
- except:
13
+ except Exception:
11
14
  try:
12
15
  value = value[int(x)]
13
- except:
16
+ except Exception:
14
17
  value = None
15
18
  return value
16
19
 
@@ -47,3 +50,20 @@ def get_index_into_hex_temp(value):
47
50
  return value
48
51
  else:
49
52
  return None
53
+
54
+
55
+ def parse_datetime(value, timezone) -> datetime.datetime:
56
+ if value is None:
57
+ return datetime.datetime(2000, 1, 1, tzinfo=timezone)
58
+
59
+ value = value.replace("-", "").replace("T", "").replace(":", "").replace("Z", "")
60
+ m = re.match(r"(\d{4})(\d{2})(\d{2})(\d{2})(\d{2})(\d{2})", value)
61
+ return datetime.datetime(
62
+ year=int(m.group(1)),
63
+ month=int(m.group(2)),
64
+ day=int(m.group(3)),
65
+ hour=int(m.group(4)),
66
+ minute=int(m.group(5)),
67
+ second=int(m.group(6)),
68
+ tzinfo=timezone,
69
+ )
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: hyundai_kia_connect_api
3
- Version: 3.17.10
3
+ Version: 3.18.0
4
4
  Summary: Python Boilerplate contains all the boilerplate you need to create a Python package.
5
5
  Home-page: https://github.com/fuatakgun/hyundai_kia_connect_api
6
6
  Author: Fuat Akgun
@@ -0,0 +1,21 @@
1
+ hyundai_kia_connect_api/ApiImpl.py,sha256=rH2nePqBaH8_aBWqnBKR4lM-fdrhW9c1brqsBWW9xDc,5057
2
+ hyundai_kia_connect_api/ApiImplType1.py,sha256=bKvU2IMdr-rT9CCEljM3Qk1c_vKaSMQxSPMeISZq8JQ,11998
3
+ hyundai_kia_connect_api/HyundaiBlueLinkAPIUSA.py,sha256=n6d14uP0TV4OxoSShE69KtxvxN1qoXztWQLtKjI4g30,25889
4
+ hyundai_kia_connect_api/KiaUvoAPIUSA.py,sha256=TnypwnLUIdQxc2ksMT05om2RtWHNYpI2agCNm0owV60,30546
5
+ hyundai_kia_connect_api/KiaUvoApiAU.py,sha256=FeK502Zysgcg3Yx31mjTh4rivFRuGB2sS07TldBzchk,48014
6
+ hyundai_kia_connect_api/KiaUvoApiCA.py,sha256=4gglRrGj6y4cw0ekRx0ELhIjfkPlbjmJyKUZwQbUFpU,29681
7
+ hyundai_kia_connect_api/KiaUvoApiCN.py,sha256=cW9YRmt5CPUTB9dHEO7B1ev8SnLjeyzuLN9o50V7JXc,46852
8
+ hyundai_kia_connect_api/KiaUvoApiEU.py,sha256=oYntYtV31h_ktLcxOB0_MAmGqR034W3BKudAg5jHvSQ,57754
9
+ hyundai_kia_connect_api/Token.py,sha256=ZsPvXh1ID7FUTGHAqhZUZyrKT7xVbOtIn6FRJn4Ygf0,370
10
+ hyundai_kia_connect_api/Vehicle.py,sha256=s1o2G1ge18UH3qfbF41UniO44UofkCRSU203S2DHHqc,13658
11
+ hyundai_kia_connect_api/VehicleManager.py,sha256=JdJ8tUCVGciVC1SJubmMQqEZ7KXp6DlI_UiOQPkDeN4,9654
12
+ hyundai_kia_connect_api/__init__.py,sha256=nqODLee6fwh8EwA6gzRrTN8hQP1SBFqfYRmvMIQtT0w,518
13
+ hyundai_kia_connect_api/const.py,sha256=ofi_ZfGxJYo0FWIcGFbIMSMRdKRtaK4GUDhFiQRvZeI,2007
14
+ hyundai_kia_connect_api/exceptions.py,sha256=m7gyDnvA5OVAK4EXSP_ZwE0s0uV8HsGUV0tiYwqofK0,1343
15
+ hyundai_kia_connect_api/utils.py,sha256=54O8Y9Xma0SqeK2c_mqX4AJGJXQWma7POZJizFPPlvo,1711
16
+ hyundai_kia_connect_api-3.18.0.dist-info/AUTHORS.rst,sha256=T77OE1hrQF6YyDE6NbdMKyL66inHt7dnjHAzblwuk2A,155
17
+ hyundai_kia_connect_api-3.18.0.dist-info/LICENSE,sha256=49hmc755oyMwKdZ-2epiorjStRB0PfcZR1w5_NXZPgs,1068
18
+ hyundai_kia_connect_api-3.18.0.dist-info/METADATA,sha256=PqNOfhiNl4ePJsy4iRugbLqFq7a4GJjVbi3GDZwr0t8,6010
19
+ hyundai_kia_connect_api-3.18.0.dist-info/WHEEL,sha256=DZajD4pwLWue70CAfc7YaxT1wLUciNBvN_TTcvXpltE,110
20
+ hyundai_kia_connect_api-3.18.0.dist-info/top_level.txt,sha256=otZ7J_fN-s3EW4jD-kAearIo2OIzhQLR8DNEHIaFfds,24
21
+ hyundai_kia_connect_api-3.18.0.dist-info/RECORD,,
@@ -1,21 +0,0 @@
1
- hyundai_kia_connect_api/ApiImpl.py,sha256=8qy1OPFzPv2fvj513Eq7OwW8TWB3ZBffQwuuDA_kQB0,5155
2
- hyundai_kia_connect_api/ApiImplType1.py,sha256=u6ulHCGw7bqkoOnqSUyDZHtXzf3QoXvlloMHGl9O-nM,754
3
- hyundai_kia_connect_api/HyundaiBlueLinkAPIUSA.py,sha256=FVWDzmkO_jsc_r4WzufgxaJkeVYhf9UAw9A6r37b-Dc,26750
4
- hyundai_kia_connect_api/KiaUvoAPIUSA.py,sha256=kQo3PA_FktsAHhdugZi0lrpMcp96WNXcvBJPbIJIcfY,31217
5
- hyundai_kia_connect_api/KiaUvoApiAU.py,sha256=VlWIXPeA4GHpJfYRX2cgEGhhky8dqb1MuDD8MnGC97w,48403
6
- hyundai_kia_connect_api/KiaUvoApiCA.py,sha256=BqlN837TirQzlxDPTFKZrkTtAJEOtvim_ubQw9JL1vc,30378
7
- hyundai_kia_connect_api/KiaUvoApiCN.py,sha256=0XzOk24L_IukSgU7Iv33RsaTJsZekHetCxTPdich20Y,47553
8
- hyundai_kia_connect_api/KiaUvoApiEU.py,sha256=QaQORCY5dBG-s9Bn3Bz7Uvh5f7KBq6yKThqrMT7-Fl4,68816
9
- hyundai_kia_connect_api/Token.py,sha256=ZsPvXh1ID7FUTGHAqhZUZyrKT7xVbOtIn6FRJn4Ygf0,370
10
- hyundai_kia_connect_api/Vehicle.py,sha256=glJ87IiCWFyJM5WG7zXdewfuMyCjDGe-nsRZmjD01BA,13645
11
- hyundai_kia_connect_api/VehicleManager.py,sha256=JdJ8tUCVGciVC1SJubmMQqEZ7KXp6DlI_UiOQPkDeN4,9654
12
- hyundai_kia_connect_api/__init__.py,sha256=nqODLee6fwh8EwA6gzRrTN8hQP1SBFqfYRmvMIQtT0w,518
13
- hyundai_kia_connect_api/const.py,sha256=ofi_ZfGxJYo0FWIcGFbIMSMRdKRtaK4GUDhFiQRvZeI,2007
14
- hyundai_kia_connect_api/exceptions.py,sha256=m7gyDnvA5OVAK4EXSP_ZwE0s0uV8HsGUV0tiYwqofK0,1343
15
- hyundai_kia_connect_api/utils.py,sha256=rfhERPXkzqelsaieLtiAyN9xDDTheNyKX5aBPRLrHf4,1117
16
- hyundai_kia_connect_api-3.17.10.dist-info/AUTHORS.rst,sha256=T77OE1hrQF6YyDE6NbdMKyL66inHt7dnjHAzblwuk2A,155
17
- hyundai_kia_connect_api-3.17.10.dist-info/LICENSE,sha256=49hmc755oyMwKdZ-2epiorjStRB0PfcZR1w5_NXZPgs,1068
18
- hyundai_kia_connect_api-3.17.10.dist-info/METADATA,sha256=jJoQgpt0MwCdlxgaLMl4QCOYrb2hPxfYggiD_y8vxSo,6011
19
- hyundai_kia_connect_api-3.17.10.dist-info/WHEEL,sha256=DZajD4pwLWue70CAfc7YaxT1wLUciNBvN_TTcvXpltE,110
20
- hyundai_kia_connect_api-3.17.10.dist-info/top_level.txt,sha256=otZ7J_fN-s3EW4jD-kAearIo2OIzhQLR8DNEHIaFfds,24
21
- hyundai_kia_connect_api-3.17.10.dist-info/RECORD,,