hyundai-kia-connect-api 3.17.10__tar.gz → 3.19.0__tar.gz

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.
Files changed (47) hide show
  1. {hyundai_kia_connect_api-3.17.10 → hyundai_kia_connect_api-3.19.0}/PKG-INFO +1 -1
  2. {hyundai_kia_connect_api-3.17.10 → hyundai_kia_connect_api-3.19.0}/hyundai_kia_connect_api/ApiImpl.py +1 -5
  3. hyundai_kia_connect_api-3.19.0/hyundai_kia_connect_api/ApiImplType1.py +314 -0
  4. {hyundai_kia_connect_api-3.17.10 → hyundai_kia_connect_api-3.19.0}/hyundai_kia_connect_api/HyundaiBlueLinkAPIUSA.py +64 -31
  5. {hyundai_kia_connect_api-3.17.10 → hyundai_kia_connect_api-3.19.0}/hyundai_kia_connect_api/KiaUvoAPIUSA.py +7 -25
  6. {hyundai_kia_connect_api-3.17.10 → hyundai_kia_connect_api-3.19.0}/hyundai_kia_connect_api/KiaUvoApiAU.py +39 -49
  7. {hyundai_kia_connect_api-3.17.10 → hyundai_kia_connect_api-3.19.0}/hyundai_kia_connect_api/KiaUvoApiCA.py +6 -25
  8. {hyundai_kia_connect_api-3.17.10 → hyundai_kia_connect_api-3.19.0}/hyundai_kia_connect_api/KiaUvoApiCN.py +5 -24
  9. {hyundai_kia_connect_api-3.17.10 → hyundai_kia_connect_api-3.19.0}/hyundai_kia_connect_api/KiaUvoApiEU.py +31 -302
  10. {hyundai_kia_connect_api-3.17.10 → hyundai_kia_connect_api-3.19.0}/hyundai_kia_connect_api/Vehicle.py +1 -1
  11. {hyundai_kia_connect_api-3.17.10 → hyundai_kia_connect_api-3.19.0}/hyundai_kia_connect_api/utils.py +22 -2
  12. {hyundai_kia_connect_api-3.17.10 → hyundai_kia_connect_api-3.19.0}/hyundai_kia_connect_api.egg-info/PKG-INFO +1 -1
  13. {hyundai_kia_connect_api-3.17.10 → hyundai_kia_connect_api-3.19.0}/setup.py +1 -1
  14. hyundai_kia_connect_api-3.17.10/hyundai_kia_connect_api/ApiImplType1.py +0 -25
  15. {hyundai_kia_connect_api-3.17.10 → hyundai_kia_connect_api-3.19.0}/AUTHORS.rst +0 -0
  16. {hyundai_kia_connect_api-3.17.10 → hyundai_kia_connect_api-3.19.0}/CONTRIBUTING.rst +0 -0
  17. {hyundai_kia_connect_api-3.17.10 → hyundai_kia_connect_api-3.19.0}/HISTORY.rst +0 -0
  18. {hyundai_kia_connect_api-3.17.10 → hyundai_kia_connect_api-3.19.0}/LICENSE +0 -0
  19. {hyundai_kia_connect_api-3.17.10 → hyundai_kia_connect_api-3.19.0}/MANIFEST.in +0 -0
  20. {hyundai_kia_connect_api-3.17.10 → hyundai_kia_connect_api-3.19.0}/README.rst +0 -0
  21. {hyundai_kia_connect_api-3.17.10 → hyundai_kia_connect_api-3.19.0}/docs/Makefile +0 -0
  22. {hyundai_kia_connect_api-3.17.10 → hyundai_kia_connect_api-3.19.0}/docs/authors.rst +0 -0
  23. {hyundai_kia_connect_api-3.17.10 → hyundai_kia_connect_api-3.19.0}/docs/conf.py +0 -0
  24. {hyundai_kia_connect_api-3.17.10 → hyundai_kia_connect_api-3.19.0}/docs/contributing.rst +0 -0
  25. {hyundai_kia_connect_api-3.17.10 → hyundai_kia_connect_api-3.19.0}/docs/history.rst +0 -0
  26. {hyundai_kia_connect_api-3.17.10 → hyundai_kia_connect_api-3.19.0}/docs/index.rst +0 -0
  27. {hyundai_kia_connect_api-3.17.10 → hyundai_kia_connect_api-3.19.0}/docs/installation.rst +0 -0
  28. {hyundai_kia_connect_api-3.17.10 → hyundai_kia_connect_api-3.19.0}/docs/make.bat +0 -0
  29. {hyundai_kia_connect_api-3.17.10 → hyundai_kia_connect_api-3.19.0}/docs/readme.rst +0 -0
  30. {hyundai_kia_connect_api-3.17.10 → hyundai_kia_connect_api-3.19.0}/docs/usage.rst +0 -0
  31. {hyundai_kia_connect_api-3.17.10 → hyundai_kia_connect_api-3.19.0}/hyundai_kia_connect_api/Token.py +0 -0
  32. {hyundai_kia_connect_api-3.17.10 → hyundai_kia_connect_api-3.19.0}/hyundai_kia_connect_api/VehicleManager.py +0 -0
  33. {hyundai_kia_connect_api-3.17.10 → hyundai_kia_connect_api-3.19.0}/hyundai_kia_connect_api/__init__.py +0 -0
  34. {hyundai_kia_connect_api-3.17.10 → hyundai_kia_connect_api-3.19.0}/hyundai_kia_connect_api/const.py +0 -0
  35. {hyundai_kia_connect_api-3.17.10 → hyundai_kia_connect_api-3.19.0}/hyundai_kia_connect_api/exceptions.py +0 -0
  36. {hyundai_kia_connect_api-3.17.10 → hyundai_kia_connect_api-3.19.0}/hyundai_kia_connect_api.egg-info/SOURCES.txt +0 -0
  37. {hyundai_kia_connect_api-3.17.10 → hyundai_kia_connect_api-3.19.0}/hyundai_kia_connect_api.egg-info/dependency_links.txt +0 -0
  38. {hyundai_kia_connect_api-3.17.10 → hyundai_kia_connect_api-3.19.0}/hyundai_kia_connect_api.egg-info/not-zip-safe +0 -0
  39. {hyundai_kia_connect_api-3.17.10 → hyundai_kia_connect_api-3.19.0}/hyundai_kia_connect_api.egg-info/requires.txt +0 -0
  40. {hyundai_kia_connect_api-3.17.10 → hyundai_kia_connect_api-3.19.0}/hyundai_kia_connect_api.egg-info/top_level.txt +0 -0
  41. {hyundai_kia_connect_api-3.17.10 → hyundai_kia_connect_api-3.19.0}/requirements.txt +0 -0
  42. {hyundai_kia_connect_api-3.17.10 → hyundai_kia_connect_api-3.19.0}/setup.cfg +0 -0
  43. {hyundai_kia_connect_api-3.17.10 → hyundai_kia_connect_api-3.19.0}/tests/__init__.py +0 -0
  44. {hyundai_kia_connect_api-3.17.10 → hyundai_kia_connect_api-3.19.0}/tests/au_login_test.py +0 -0
  45. {hyundai_kia_connect_api-3.17.10 → hyundai_kia_connect_api-3.19.0}/tests/ca_login_test.py +0 -0
  46. {hyundai_kia_connect_api-3.17.10 → hyundai_kia_connect_api-3.19.0}/tests/eu_check_response_for_errors_test.py +0 -0
  47. {hyundai_kia_connect_api-3.17.10 → hyundai_kia_connect_api-3.19.0}/tests/eu_login_test.py +0 -0
@@ -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.19.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
@@ -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
@@ -0,0 +1,314 @@
1
+ import datetime as dt
2
+ from typing import Optional
3
+
4
+ from .ApiImpl import (
5
+ ApiImpl,
6
+ )
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
+ )
21
+
22
+ USER_AGENT_OK_HTTP: str = "okhttp/3.12.0"
23
+
24
+
25
+ class ApiImplType1(ApiImpl):
26
+ def __init__(self) -> None:
27
+ """Initialize."""
28
+
29
+ def _get_authenticated_headers(
30
+ self, token: Token, ccs2_support: Optional[int] = None
31
+ ) -> dict:
32
+ return {
33
+ "Authorization": token.access_token,
34
+ "ccsp-service-id": self.CCSP_SERVICE_ID,
35
+ "ccsp-application-id": self.APP_ID,
36
+ "Stamp": self._get_stamp(),
37
+ "ccsp-device-id": token.device_id,
38
+ "Host": self.BASE_URL,
39
+ "Connection": "Keep-Alive",
40
+ "Accept-Encoding": "gzip",
41
+ "Ccuccs2protocolsupport": str(ccs2_support or 0),
42
+ "User-Agent": USER_AGENT_OK_HTTP,
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")
@@ -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
- pass
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
- pass
655
+ if vehicle.engine_type != ENGINE_TYPES.EV:
656
+ return {}
643
657
 
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
- )
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
- _LOGGER.debug(f"{DOMAIN} - last_updated_at - after {value}")
667
- return value
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 = 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