hyundai-kia-connect-api 3.17.9__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.
- hyundai_kia_connect_api/ApiImpl.py +1 -5
- hyundai_kia_connect_api/ApiImplType1.py +291 -2
- hyundai_kia_connect_api/HyundaiBlueLinkAPIUSA.py +6 -31
- hyundai_kia_connect_api/KiaUvoAPIUSA.py +7 -25
- hyundai_kia_connect_api/KiaUvoApiAU.py +52 -59
- hyundai_kia_connect_api/KiaUvoApiCA.py +8 -27
- hyundai_kia_connect_api/KiaUvoApiCN.py +20 -37
- hyundai_kia_connect_api/KiaUvoApiEU.py +46 -315
- hyundai_kia_connect_api/Vehicle.py +2 -1
- hyundai_kia_connect_api/const.py +7 -1
- hyundai_kia_connect_api/utils.py +22 -2
- {hyundai_kia_connect_api-3.17.9.dist-info → hyundai_kia_connect_api-3.18.0.dist-info}/LICENSE +0 -1
- {hyundai_kia_connect_api-3.17.9.dist-info → hyundai_kia_connect_api-3.18.0.dist-info}/METADATA +1 -1
- hyundai_kia_connect_api-3.18.0.dist-info/RECORD +21 -0
- hyundai_kia_connect_api-3.17.9.dist-info/RECORD +0 -21
- {hyundai_kia_connect_api-3.17.9.dist-info → hyundai_kia_connect_api-3.18.0.dist-info}/AUTHORS.rst +0 -0
- {hyundai_kia_connect_api-3.17.9.dist-info → hyundai_kia_connect_api-3.18.0.dist-info}/WHEEL +0 -0
- {hyundai_kia_connect_api-3.17.9.dist-info → hyundai_kia_connect_api-3.18.0.dist-info}/top_level.txt +0 -0
@@ -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 =
|
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 =
|
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
|
-
|
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"
|
@@ -509,7 +490,7 @@ class KiaUvoApiCA(ApiImpl):
|
|
509
490
|
if response["responseHeader"]["responseCode"] != 0:
|
510
491
|
raise APIError("No Location Located")
|
511
492
|
return response["result"]
|
512
|
-
except:
|
493
|
+
except Exception:
|
513
494
|
_LOGGER.warning(f"{DOMAIN} - Get vehicle location failed")
|
514
495
|
return None
|
515
496
|
|
@@ -717,7 +698,7 @@ class KiaUvoApiCA(ApiImpl):
|
|
717
698
|
vehicle.ev_charge_limits_dc = [
|
718
699
|
x["level"] for x in state if x["plugType"] == 0
|
719
700
|
][-1]
|
720
|
-
except:
|
701
|
+
except Exception:
|
721
702
|
_LOGGER.debug(f"{DOMAIN} - SOC Levels couldn't be found. May not be an EV.")
|
722
703
|
|
723
704
|
def _get_charge_limits(self, token: Token, vehicle: Vehicle) -> dict:
|
@@ -5,14 +5,12 @@
|
|
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
|
12
11
|
|
13
12
|
import pytz
|
14
13
|
import requests
|
15
|
-
from bs4 import BeautifulSoup
|
16
14
|
from dateutil import tz
|
17
15
|
|
18
16
|
from .ApiImpl import (
|
@@ -43,22 +41,28 @@ from .const import (
|
|
43
41
|
TEMPERATURE_UNITS,
|
44
42
|
VEHICLE_LOCK_ACTION,
|
45
43
|
)
|
46
|
-
from .exceptions import
|
44
|
+
from .exceptions import (
|
45
|
+
AuthenticationError,
|
46
|
+
DuplicateRequestError,
|
47
|
+
RequestTimeoutError,
|
48
|
+
ServiceTemporaryUnavailable,
|
49
|
+
NoDataFound,
|
50
|
+
InvalidAPIResponseError,
|
51
|
+
APIError,
|
52
|
+
RateLimitingError,
|
53
|
+
)
|
47
54
|
from .utils import (
|
48
55
|
get_child_value,
|
49
56
|
get_index_into_hex_temp,
|
50
57
|
get_hex_temp_into_index,
|
58
|
+
parse_datetime,
|
51
59
|
)
|
52
60
|
|
53
61
|
_LOGGER = logging.getLogger(__name__)
|
54
62
|
|
55
63
|
USER_AGENT_OK_HTTP: str = "okhttp/3.12.0"
|
56
|
-
USER_AGENT_MOZILLA: str = (
|
57
|
-
|
58
|
-
)
|
59
|
-
ACCEPT_HEADER_ALL: str = (
|
60
|
-
"text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.9" # noqa
|
61
|
-
)
|
64
|
+
USER_AGENT_MOZILLA: str = "Mozilla/5.0 (Linux; Android 4.1.1; Galaxy Nexus Build/JRO03C) AppleWebKit/535.19 (KHTML, like Gecko) Chrome/18.0.1025.166 Mobile Safari/535.19" # noqa
|
65
|
+
ACCEPT_HEADER_ALL: str = "text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.9" # noqa
|
62
66
|
|
63
67
|
|
64
68
|
def _check_response_for_errors(response: dict) -> None:
|
@@ -108,9 +112,7 @@ class KiaUvoApiCN(ApiImplType1):
|
|
108
112
|
self.BASE_DOMAIN: str = "prd.cn-ccapi.kia.com"
|
109
113
|
self.CCSP_SERVICE_ID: str = "9d5df92a-06ae-435f-b459-8304f2efcc67"
|
110
114
|
self.APP_ID: str = "eea8762c-adfc-4ee4-8d7a-6e2452ddf342"
|
111
|
-
self.BASIC_AUTHORIZATION: str =
|
112
|
-
"Basic OWQ1ZGY5MmEtMDZhZS00MzVmLWI0NTktODMwNGYyZWZjYzY3OnRzWGRrVWcwOEF2MlpaelhPZ1d6Snl4VVQ2eWVTbk5OUWtYWFBSZEtXRUFOd2wxcA=="
|
113
|
-
)
|
115
|
+
self.BASIC_AUTHORIZATION: str = "Basic OWQ1ZGY5MmEtMDZhZS00MzVmLWI0NTktODMwNGYyZWZjYzY3OnRzWGRrVWcwOEF2MlpaelhPZ1d6Snl4VVQ2eWVTbk5OUWtYWFBSZEtXRUFOd2wxcA=="
|
114
116
|
elif BRANDS[brand] == BRAND_HYUNDAI:
|
115
117
|
self.BASE_DOMAIN: str = "prd.cn-ccapi.hyundai.com"
|
116
118
|
self.CCSP_SERVICE_ID: str = "72b3d019-5bc7-443d-a437-08f307cf06e2"
|
@@ -210,25 +212,6 @@ class KiaUvoApiCN(ApiImplType1):
|
|
210
212
|
result.append(vehicle)
|
211
213
|
return result
|
212
214
|
|
213
|
-
def get_last_updated_at(self, value) -> dt.datetime:
|
214
|
-
_LOGGER.debug(f"{DOMAIN} - last_updated_at - before {value}")
|
215
|
-
if value is None:
|
216
|
-
value = dt.datetime(2000, 1, 1, tzinfo=self.data_timezone)
|
217
|
-
else:
|
218
|
-
m = re.match(r"(\d{4})(\d{2})(\d{2})(\d{2})(\d{2})(\d{2})", value)
|
219
|
-
value = dt.datetime(
|
220
|
-
year=int(m.group(1)),
|
221
|
-
month=int(m.group(2)),
|
222
|
-
day=int(m.group(3)),
|
223
|
-
hour=int(m.group(4)),
|
224
|
-
minute=int(m.group(5)),
|
225
|
-
second=int(m.group(6)),
|
226
|
-
tzinfo=self.data_timezone,
|
227
|
-
)
|
228
|
-
|
229
|
-
_LOGGER.debug(f"{DOMAIN} - last_updated_at - after {value}")
|
230
|
-
return value
|
231
|
-
|
232
215
|
def _get_time_from_string(self, value, timesection) -> dt.datetime.time:
|
233
216
|
if value is not None:
|
234
217
|
lastTwo = int(value[-2:])
|
@@ -291,8 +274,8 @@ class KiaUvoApiCN(ApiImplType1):
|
|
291
274
|
|
292
275
|
def _update_vehicle_properties(self, vehicle: Vehicle, state: dict) -> None:
|
293
276
|
if get_child_value(state, "status.time"):
|
294
|
-
vehicle.last_updated_at =
|
295
|
-
get_child_value(state, "status.time")
|
277
|
+
vehicle.last_updated_at = parse_datetime(
|
278
|
+
get_child_value(state, "status.time"), self.data_timezone
|
296
279
|
)
|
297
280
|
else:
|
298
281
|
vehicle.last_updated_at = dt.datetime.now(self.data_timezone)
|
@@ -486,7 +469,7 @@ class KiaUvoApiCN(ApiImplType1):
|
|
486
469
|
vehicle.ev_charge_limits_dc = [
|
487
470
|
x["targetSOClevel"] for x in target_soc_list if x["plugType"] == 0
|
488
471
|
][-1]
|
489
|
-
except:
|
472
|
+
except Exception:
|
490
473
|
_LOGGER.debug(f"{DOMAIN} - SOC Levels couldn't be found. May not be an EV.")
|
491
474
|
if (
|
492
475
|
get_child_value(
|
@@ -642,8 +625,8 @@ class KiaUvoApiCN(ApiImplType1):
|
|
642
625
|
vehicle.location = (
|
643
626
|
get_child_value(state, "vehicleLocation.coord.lat"),
|
644
627
|
get_child_value(state, "vehicleLocation.coord.lon"),
|
645
|
-
|
646
|
-
get_child_value(state, "vehicleLocation.time")
|
628
|
+
parse_datetime(
|
629
|
+
get_child_value(state, "vehicleLocation.time"), self.data_timezone
|
647
630
|
),
|
648
631
|
)
|
649
632
|
vehicle.data = state
|
@@ -675,7 +658,7 @@ class KiaUvoApiCN(ApiImplType1):
|
|
675
658
|
_LOGGER.debug(f"{DOMAIN} - _get_location response: {response}")
|
676
659
|
_check_response_for_errors(response)
|
677
660
|
return response["resMsg"]
|
678
|
-
except:
|
661
|
+
except Exception:
|
679
662
|
_LOGGER.debug(f"{DOMAIN} - _get_location failed")
|
680
663
|
return None
|
681
664
|
|
@@ -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
|
@@ -45,22 +44,29 @@ from .const import (
|
|
45
44
|
TEMPERATURE_UNITS,
|
46
45
|
VEHICLE_LOCK_ACTION,
|
47
46
|
)
|
48
|
-
from .exceptions import
|
47
|
+
from .exceptions import (
|
48
|
+
AuthenticationError,
|
49
|
+
DuplicateRequestError,
|
50
|
+
RequestTimeoutError,
|
51
|
+
ServiceTemporaryUnavailable,
|
52
|
+
NoDataFound,
|
53
|
+
InvalidAPIResponseError,
|
54
|
+
APIError,
|
55
|
+
RateLimitingError,
|
56
|
+
DeviceIDError,
|
57
|
+
)
|
49
58
|
from .utils import (
|
50
59
|
get_child_value,
|
51
60
|
get_index_into_hex_temp,
|
52
61
|
get_hex_temp_into_index,
|
62
|
+
parse_datetime,
|
53
63
|
)
|
54
64
|
|
55
65
|
_LOGGER = logging.getLogger(__name__)
|
56
66
|
|
57
67
|
USER_AGENT_OK_HTTP: str = "okhttp/3.12.0"
|
58
|
-
USER_AGENT_MOZILLA: str = (
|
59
|
-
|
60
|
-
)
|
61
|
-
ACCEPT_HEADER_ALL: str = (
|
62
|
-
"text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.9" # noqa
|
63
|
-
)
|
68
|
+
USER_AGENT_MOZILLA: str = "Mozilla/5.0 (Linux; Android 4.1.1; Galaxy Nexus Build/JRO03C) AppleWebKit/535.19 (KHTML, like Gecko) Chrome/18.0.1025.166 Mobile Safari/535.19" # noqa
|
69
|
+
ACCEPT_HEADER_ALL: str = "text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.9" # noqa
|
64
70
|
|
65
71
|
SUPPORTED_LANGUAGES_LIST = [
|
66
72
|
"en", # English
|
@@ -128,7 +134,6 @@ class KiaUvoApiEU(ApiImplType1):
|
|
128
134
|
temperature_range = [x * 0.5 for x in range(28, 60)]
|
129
135
|
|
130
136
|
def __init__(self, region: int, brand: int, language: str) -> None:
|
131
|
-
self.ccu_ccs2_protocol_support = None
|
132
137
|
language = language.lower()
|
133
138
|
# Strip language variants (e.g. en-Gb)
|
134
139
|
if len(language) > 2:
|
@@ -160,9 +165,7 @@ class KiaUvoApiEU(ApiImplType1):
|
|
160
165
|
self.CFB: str = base64.b64decode(
|
161
166
|
"RFtoRq/vDXJmRndoZaZQyfOot7OrIqGVFj96iY2WL3yyH5Z/pUvlUhqmCxD2t+D65SQ="
|
162
167
|
)
|
163
|
-
self.BASIC_AUTHORIZATION: str =
|
164
|
-
"Basic NmQ0NzdjMzgtM2NhNC00Y2YzLTk1NTctMmExOTI5YTk0NjU0OktVeTQ5WHhQekxwTHVvSzB4aEJDNzdXNlZYaG10UVI5aVFobUlGampvWTRJcHhzVg==" # noqa
|
165
|
-
)
|
168
|
+
self.BASIC_AUTHORIZATION: str = "Basic NmQ0NzdjMzgtM2NhNC00Y2YzLTk1NTctMmExOTI5YTk0NjU0OktVeTQ5WHhQekxwTHVvSzB4aEJDNzdXNlZYaG10UVI5aVFobUlGampvWTRJcHhzVg==" # noqa
|
166
169
|
self.LOGIN_FORM_HOST = "eu-account.hyundai.com"
|
167
170
|
self.PUSH_TYPE = "GCM"
|
168
171
|
elif BRANDS[self.brand] == BRAND_GENESIS:
|
@@ -173,9 +176,7 @@ class KiaUvoApiEU(ApiImplType1):
|
|
173
176
|
self.CFB: str = base64.b64decode(
|
174
177
|
"RFtoRq/vDXJmRndoZaZQyYo3/qFLtVReW8P7utRPcc0ZxOzOELm9mexvviBk/qqIp4A="
|
175
178
|
)
|
176
|
-
self.BASIC_AUTHORIZATION: str =
|
177
|
-
"Basic NmQ0NzdjMzgtM2NhNC00Y2YzLTk1NTctMmExOTI5YTk0NjU0OktVeTQ5WHhQekxwTHVvSzB4aEJDNzdXNlZYaG10UVI5aVFobUlGampvWTRJcHhzVg==" # noqa
|
178
|
-
)
|
179
|
+
self.BASIC_AUTHORIZATION: str = "Basic NmQ0NzdjMzgtM2NhNC00Y2YzLTk1NTctMmExOTI5YTk0NjU0OktVeTQ5WHhQekxwTHVvSzB4aEJDNzdXNlZYaG10UVI5aVFobUlGampvWTRJcHhzVg==" # noqa
|
179
180
|
self.LOGIN_FORM_HOST = "accounts-eu.genesis.com"
|
180
181
|
self.PUSH_TYPE = "GCM"
|
181
182
|
|
@@ -294,25 +295,6 @@ class KiaUvoApiEU(ApiImplType1):
|
|
294
295
|
result.append(vehicle)
|
295
296
|
return result
|
296
297
|
|
297
|
-
def get_last_updated_at(self, value) -> dt.datetime:
|
298
|
-
_LOGGER.debug(f"{DOMAIN} - last_updated_at - before {value}")
|
299
|
-
if value is None:
|
300
|
-
value = dt.datetime(2000, 1, 1, tzinfo=self.data_timezone)
|
301
|
-
else:
|
302
|
-
m = re.match(r"(\d{4})(\d{2})(\d{2})(\d{2})(\d{2})(\d{2})", value)
|
303
|
-
value = dt.datetime(
|
304
|
-
year=int(m.group(1)),
|
305
|
-
month=int(m.group(2)),
|
306
|
-
day=int(m.group(3)),
|
307
|
-
hour=int(m.group(4)),
|
308
|
-
minute=int(m.group(5)),
|
309
|
-
second=int(m.group(6)),
|
310
|
-
tzinfo=self.data_timezone,
|
311
|
-
)
|
312
|
-
|
313
|
-
_LOGGER.debug(f"{DOMAIN} - last_updated_at - after {value}")
|
314
|
-
return value
|
315
|
-
|
316
298
|
def _get_time_from_string(self, value, timesection) -> dt.datetime.time:
|
317
299
|
if value is not None:
|
318
300
|
lastTwo = int(value[-2:])
|
@@ -328,12 +310,29 @@ class KiaUvoApiEU(ApiImplType1):
|
|
328
310
|
return value
|
329
311
|
|
330
312
|
def update_vehicle_with_cached_state(self, token: Token, vehicle: Vehicle) -> None:
|
331
|
-
|
332
|
-
|
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)
|
333
329
|
|
334
330
|
if vehicle.ccu_ccs2_protocol_support == 0:
|
335
|
-
self._update_vehicle_properties(
|
331
|
+
self._update_vehicle_properties(
|
332
|
+
vehicle, response["resMsg"]["vehicleStatusInfo"]
|
333
|
+
)
|
336
334
|
else:
|
335
|
+
state = response["resMsg"]["state"]["Vehicle"]
|
337
336
|
self._update_vehicle_properties_ccs2(vehicle, state)
|
338
337
|
|
339
338
|
if (
|
@@ -383,281 +382,10 @@ class KiaUvoApiEU(ApiImplType1):
|
|
383
382
|
else:
|
384
383
|
self._update_vehicle_drive_info(vehicle, state)
|
385
384
|
|
386
|
-
def _update_vehicle_properties_ccs2(self, vehicle: Vehicle, state: dict) -> None:
|
387
|
-
if get_child_value(state, "Date"):
|
388
|
-
vehicle.last_updated_at = self.get_last_updated_at(
|
389
|
-
get_child_value(state, "Date")
|
390
|
-
)
|
391
|
-
else:
|
392
|
-
vehicle.last_updated_at = dt.datetime.now(self.data_timezone)
|
393
|
-
|
394
|
-
vehicle.odometer = (
|
395
|
-
get_child_value(state, "Drivetrain.Odometer"),
|
396
|
-
DISTANCE_UNITS[1],
|
397
|
-
)
|
398
|
-
vehicle.car_battery_percentage = get_child_value(
|
399
|
-
state, "Electronics.Battery.Level"
|
400
|
-
)
|
401
|
-
|
402
|
-
vehicle.engine_is_running = get_child_value(state, "DrivingReady")
|
403
|
-
|
404
|
-
air_temp = get_child_value(
|
405
|
-
state,
|
406
|
-
"Cabin.HVAC.Row1.Driver.Temperature.Value",
|
407
|
-
)
|
408
|
-
|
409
|
-
if air_temp != "OFF":
|
410
|
-
vehicle.air_temperature = (air_temp, TEMPERATURE_UNITS[1])
|
411
|
-
|
412
|
-
defrost_is_on = get_child_value(state, "Body.Windshield.Front.Defog.State")
|
413
|
-
if defrost_is_on in [0, 2]:
|
414
|
-
vehicle.defrost_is_on = False
|
415
|
-
elif defrost_is_on == 1:
|
416
|
-
vehicle.defrost_is_on = True
|
417
|
-
|
418
|
-
steer_wheel_heat = get_child_value(state, "Cabin.SteeringWheel.Heat.State")
|
419
|
-
if steer_wheel_heat in [0, 2]:
|
420
|
-
vehicle.steering_wheel_heater_is_on = False
|
421
|
-
elif steer_wheel_heat == 1:
|
422
|
-
vehicle.steering_wheel_heater_is_on = True
|
423
|
-
|
424
|
-
defrost_rear_is_on = get_child_value(state, "Body.Windshield.Rear.Defog.State")
|
425
|
-
if defrost_rear_is_on in [0, 2]:
|
426
|
-
vehicle.back_window_heater_is_on = False
|
427
|
-
elif defrost_rear_is_on == 1:
|
428
|
-
vehicle.back_window_heater_is_on = True
|
429
|
-
|
430
|
-
# TODO: status.sideMirrorHeat
|
431
|
-
|
432
|
-
vehicle.front_left_seat_status = SEAT_STATUS[
|
433
|
-
get_child_value(state, "Cabin.Seat.Row1.Driver.Climate.State")
|
434
|
-
]
|
435
|
-
|
436
|
-
vehicle.front_right_seat_status = SEAT_STATUS[
|
437
|
-
get_child_value(state, "Cabin.Seat.Row1.Passenger.Climate.State")
|
438
|
-
]
|
439
|
-
|
440
|
-
vehicle.rear_left_seat_status = SEAT_STATUS[
|
441
|
-
get_child_value(state, "Cabin.Seat.Row2.Left.Climate.State")
|
442
|
-
]
|
443
|
-
|
444
|
-
vehicle.rear_right_seat_status = SEAT_STATUS[
|
445
|
-
get_child_value(state, "Cabin.Seat.Row2.Right.Climate.State")
|
446
|
-
]
|
447
|
-
|
448
|
-
# TODO: status.doorLock
|
449
|
-
|
450
|
-
vehicle.front_left_door_is_open = get_child_value(
|
451
|
-
state, "Cabin.Door.Row1.Driver.Open"
|
452
|
-
)
|
453
|
-
vehicle.front_right_door_is_open = get_child_value(
|
454
|
-
state, "Cabin.Door.Row1.Passenger.Open"
|
455
|
-
)
|
456
|
-
vehicle.back_left_door_is_open = get_child_value(
|
457
|
-
state, "Cabin.Door.Row2.Left.Open"
|
458
|
-
)
|
459
|
-
vehicle.back_right_door_is_open = get_child_value(
|
460
|
-
state, "Cabin.Door.Row2.Right.Open"
|
461
|
-
)
|
462
|
-
|
463
|
-
# TODO: should the windows and trunc also be checked?
|
464
|
-
vehicle.is_locked = not (
|
465
|
-
vehicle.front_left_door_is_open
|
466
|
-
or vehicle.front_right_door_is_open
|
467
|
-
or vehicle.back_left_door_is_open
|
468
|
-
or vehicle.back_right_door_is_open
|
469
|
-
)
|
470
|
-
|
471
|
-
vehicle.hood_is_open = get_child_value(state, "Body.Hood.Open")
|
472
|
-
vehicle.front_left_window_is_open = get_child_value(
|
473
|
-
state, "Cabin.Window.Row1.Driver.Open"
|
474
|
-
)
|
475
|
-
vehicle.front_right_window_is_open = get_child_value(
|
476
|
-
state, "Cabin.Window.Row1.Passenger.Open"
|
477
|
-
)
|
478
|
-
vehicle.back_left_window_is_open = get_child_value(
|
479
|
-
state, "Cabin.Window.Row2.Left.Open"
|
480
|
-
)
|
481
|
-
vehicle.back_right_window_is_open = get_child_value(
|
482
|
-
state, "Cabin.Window.Row2.Right.Open"
|
483
|
-
)
|
484
|
-
vehicle.tire_pressure_rear_left_warning_is_on = bool(
|
485
|
-
get_child_value(state, "Chassis.Axle.Row2.Left.Tire.PressureLow")
|
486
|
-
)
|
487
|
-
vehicle.tire_pressure_front_left_warning_is_on = bool(
|
488
|
-
get_child_value(state, "Chassis.Axle.Row1.Left.Tire.PressureLow")
|
489
|
-
)
|
490
|
-
vehicle.tire_pressure_front_right_warning_is_on = bool(
|
491
|
-
get_child_value(state, "Chassis.Axle.Row1.Right.Tire.PressureLow")
|
492
|
-
)
|
493
|
-
vehicle.tire_pressure_rear_right_warning_is_on = bool(
|
494
|
-
get_child_value(state, "Chassis.Axle.Row2.Right.Tire.PressureLow")
|
495
|
-
)
|
496
|
-
vehicle.tire_pressure_all_warning_is_on = bool(
|
497
|
-
get_child_value(state, "Chassis.Axle.Tire.PressureLow")
|
498
|
-
)
|
499
|
-
vehicle.trunk_is_open = get_child_value(state, "Body.Trunk.Open")
|
500
|
-
|
501
|
-
vehicle.ev_battery_percentage = get_child_value(
|
502
|
-
state, "Green.BatteryManagement.BatteryRemain.Ratio"
|
503
|
-
)
|
504
|
-
vehicle.ev_battery_remain = get_child_value(
|
505
|
-
state, "Green.BatteryManagement.BatteryRemain.Value"
|
506
|
-
)
|
507
|
-
vehicle.ev_battery_capacity = get_child_value(
|
508
|
-
state, "Green.BatteryManagement.BatteryCapacity.Value"
|
509
|
-
)
|
510
|
-
vehicle.ev_battery_soh_percentage = get_child_value(
|
511
|
-
state, "Green.BatteryManagement.SoH.Ratio"
|
512
|
-
)
|
513
|
-
vehicle.ev_battery_is_plugged_in = get_child_value(
|
514
|
-
state, "Green.ChargingInformation.ElectricCurrentLevel.State"
|
515
|
-
)
|
516
|
-
vehicle.ev_battery_is_plugged_in = get_child_value(
|
517
|
-
state, "Green.ChargingInformation.ConnectorFastening.State"
|
518
|
-
)
|
519
|
-
charging_door_state = get_child_value(state, "Green.ChargingDoor.State")
|
520
|
-
if charging_door_state in [0, 2]:
|
521
|
-
vehicle.ev_charge_port_door_is_open = False
|
522
|
-
elif charging_door_state == 1:
|
523
|
-
vehicle.ev_charge_port_door_is_open = True
|
524
|
-
|
525
|
-
vehicle.total_driving_range = (
|
526
|
-
float(
|
527
|
-
get_child_value(
|
528
|
-
state,
|
529
|
-
"Drivetrain.FuelSystem.DTE.Total", # noqa
|
530
|
-
)
|
531
|
-
),
|
532
|
-
DISTANCE_UNITS[
|
533
|
-
get_child_value(
|
534
|
-
state,
|
535
|
-
"Drivetrain.FuelSystem.DTE.Unit", # noqa
|
536
|
-
)
|
537
|
-
],
|
538
|
-
)
|
539
|
-
|
540
|
-
if vehicle.engine_type == ENGINE_TYPES.EV:
|
541
|
-
# ev_driving_range is the same as total_driving_range for pure EV
|
542
|
-
vehicle.ev_driving_range = (
|
543
|
-
vehicle.total_driving_range,
|
544
|
-
vehicle.total_driving_range_unit,
|
545
|
-
)
|
546
|
-
# TODO: vehicle.ev_driving_range for non EV
|
547
|
-
|
548
|
-
vehicle.washer_fluid_warning_is_on = get_child_value(
|
549
|
-
state, "Body.Windshield.Front.WasherFluid.LevelLow"
|
550
|
-
)
|
551
|
-
|
552
|
-
vehicle.ev_estimated_current_charge_duration = (
|
553
|
-
get_child_value(state, "Green.ChargingInformation.Charging.RemainTime"),
|
554
|
-
"m",
|
555
|
-
)
|
556
|
-
vehicle.ev_estimated_fast_charge_duration = (
|
557
|
-
get_child_value(state, "Green.ChargingInformation.EstimatedTime.Standard"),
|
558
|
-
"m",
|
559
|
-
)
|
560
|
-
vehicle.ev_estimated_portable_charge_duration = (
|
561
|
-
get_child_value(state, "Green.ChargingInformation.EstimatedTime.ICCB"),
|
562
|
-
"m",
|
563
|
-
)
|
564
|
-
vehicle.ev_estimated_station_charge_duration = (
|
565
|
-
get_child_value(state, "Green.ChargingInformation.EstimatedTime.Quick"),
|
566
|
-
"m",
|
567
|
-
)
|
568
|
-
vehicle.ev_charge_limits_ac = get_child_value(
|
569
|
-
state, "Green.ChargingInformation.TargetSoC.Standard"
|
570
|
-
)
|
571
|
-
vehicle.ev_charge_limits_dc = get_child_value(
|
572
|
-
state, "Green.ChargingInformation.TargetSoC.Quick"
|
573
|
-
)
|
574
|
-
vehicle.ev_v2l_discharge_limit = get_child_value(
|
575
|
-
state, "Green.Electric.SmartGrid.VehicleToLoad.DischargeLimitation.SoC"
|
576
|
-
)
|
577
|
-
vehicle.ev_target_range_charge_AC = (
|
578
|
-
get_child_value(
|
579
|
-
state,
|
580
|
-
"Green.ChargingInformation.DTE.TargetSoC.Standard", # noqa
|
581
|
-
),
|
582
|
-
DISTANCE_UNITS[
|
583
|
-
get_child_value(
|
584
|
-
state,
|
585
|
-
"Drivetrain.FuelSystem.DTE.Unit", # noqa
|
586
|
-
)
|
587
|
-
],
|
588
|
-
)
|
589
|
-
vehicle.ev_target_range_charge_DC = (
|
590
|
-
get_child_value(
|
591
|
-
state,
|
592
|
-
"Green.ChargingInformation.DTE.TargetSoC.Quick", # noqa
|
593
|
-
),
|
594
|
-
DISTANCE_UNITS[
|
595
|
-
get_child_value(
|
596
|
-
state,
|
597
|
-
"Drivetrain.FuelSystem.DTE.Unit", # noqa
|
598
|
-
)
|
599
|
-
],
|
600
|
-
)
|
601
|
-
vehicle.ev_first_departure_enabled = bool(
|
602
|
-
get_child_value(state, "Green.Reservation.Departure.Schedule1.Enable")
|
603
|
-
)
|
604
|
-
|
605
|
-
vehicle.ev_second_departure_enabled = bool(
|
606
|
-
get_child_value(state, "Green.Reservation.Departure.Schedule2.Enable")
|
607
|
-
)
|
608
|
-
|
609
|
-
# TODO: vehicle.ev_first_departure_days --> Green.Reservation.Departure.Schedule1.(Mon,Tue,Wed,Thu,Fri,Sat,Sun) # noqa
|
610
|
-
# TODO: vehicle.ev_second_departure_days --> Green.Reservation.Departure.Schedule2.(Mon,Tue,Wed,Thu,Fri,Sat,Sun) # noqa
|
611
|
-
# TODO: vehicle.ev_first_departure_time --> Green.Reservation.Departure.Schedule1.(Min,Hour) # noqa
|
612
|
-
# TODO: vehicle.ev_second_departure_time --> Green.Reservation.Departure.Schedule2.(Min,Hour) # noqa
|
613
|
-
# TODO: vehicle.ev_off_peak_charge_only_enabled --> unknown settings are in --> Green.Reservation.OffPeakTime and OffPeakTime2 # noqa
|
614
|
-
|
615
|
-
vehicle.washer_fluid_warning_is_on = get_child_value(
|
616
|
-
state, "Body.Windshield.Front.WasherFluid.LevelLow"
|
617
|
-
)
|
618
|
-
vehicle.brake_fluid_warning_is_on = get_child_value(
|
619
|
-
state, "Chassis.Brake.Fluid.Warning"
|
620
|
-
)
|
621
|
-
|
622
|
-
vehicle.fuel_level = get_child_value(state, "Drivetrain.FuelSystem.FuelLevel")
|
623
|
-
vehicle.fuel_level_is_low = get_child_value(
|
624
|
-
state, "Drivetrain.FuelSystem.LowFuelWarning"
|
625
|
-
)
|
626
|
-
vehicle.air_control_is_on = get_child_value(
|
627
|
-
state, "Cabin.HVAC.Row1.Driver.Blower.SpeedLevel"
|
628
|
-
)
|
629
|
-
vehicle.smart_key_battery_warning_is_on = bool(
|
630
|
-
get_child_value(state, "Electronics.FOB.LowBattery")
|
631
|
-
)
|
632
|
-
|
633
|
-
if get_child_value(state, "Location.GeoCoord.Latitude"):
|
634
|
-
location_last_updated_at = dt.datetime(
|
635
|
-
2000, 1, 1, tzinfo=self.data_timezone
|
636
|
-
)
|
637
|
-
timestamp = get_child_value(state, "Location.TimeStamp")
|
638
|
-
if timestamp is not None:
|
639
|
-
location_last_updated_at = dt.datetime(
|
640
|
-
year=int(get_child_value(timestamp, "Year")),
|
641
|
-
month=int(get_child_value(timestamp, "Mon")),
|
642
|
-
day=int(get_child_value(timestamp, "Day")),
|
643
|
-
hour=int(get_child_value(timestamp, "Hour")),
|
644
|
-
minute=int(get_child_value(timestamp, "Min")),
|
645
|
-
second=int(get_child_value(timestamp, "Sec")),
|
646
|
-
tzinfo=self.data_timezone,
|
647
|
-
)
|
648
|
-
|
649
|
-
vehicle.location = (
|
650
|
-
get_child_value(state, "Location.GeoCoord.Latitude"),
|
651
|
-
get_child_value(state, "Location.GeoCoord.Longitude"),
|
652
|
-
location_last_updated_at,
|
653
|
-
)
|
654
|
-
|
655
|
-
vehicle.data = state
|
656
|
-
|
657
385
|
def _update_vehicle_properties(self, vehicle: Vehicle, state: dict) -> None:
|
658
386
|
if get_child_value(state, "vehicleStatus.time"):
|
659
|
-
vehicle.last_updated_at =
|
660
|
-
get_child_value(state, "vehicleStatus.time")
|
387
|
+
vehicle.last_updated_at = parse_datetime(
|
388
|
+
get_child_value(state, "vehicleStatus.time"), self.data_timezone
|
661
389
|
)
|
662
390
|
else:
|
663
391
|
vehicle.last_updated_at = dt.datetime.now(self.data_timezone)
|
@@ -853,7 +581,7 @@ class KiaUvoApiEU(ApiImplType1):
|
|
853
581
|
vehicle.ev_charge_limits_dc = [
|
854
582
|
x["targetSOClevel"] for x in target_soc_list if x["plugType"] == 0
|
855
583
|
][-1]
|
856
|
-
except:
|
584
|
+
except Exception:
|
857
585
|
_LOGGER.debug(f"{DOMAIN} - SOC Levels couldn't be found. May not be an EV.")
|
858
586
|
if (
|
859
587
|
get_child_value(
|
@@ -1009,8 +737,8 @@ class KiaUvoApiEU(ApiImplType1):
|
|
1009
737
|
vehicle.location = (
|
1010
738
|
get_child_value(state, "vehicleLocation.coord.lat"),
|
1011
739
|
get_child_value(state, "vehicleLocation.coord.lon"),
|
1012
|
-
|
1013
|
-
get_child_value(state, "vehicleLocation.time")
|
740
|
+
parse_datetime(
|
741
|
+
get_child_value(state, "vehicleLocation.time"), self.data_timezone
|
1014
742
|
),
|
1015
743
|
)
|
1016
744
|
vehicle.data = state
|
@@ -1028,7 +756,10 @@ class KiaUvoApiEU(ApiImplType1):
|
|
1028
756
|
else:
|
1029
757
|
url = url + "/ccs2/carstatus/latest"
|
1030
758
|
response = requests.get(
|
1031
|
-
url,
|
759
|
+
url,
|
760
|
+
headers=self._get_authenticated_headers(
|
761
|
+
token, vehicle.ccu_ccs2_protocol_support
|
762
|
+
),
|
1032
763
|
).json()
|
1033
764
|
_LOGGER.debug(f"{DOMAIN} - get_cached_vehicle_status response: {response}")
|
1034
765
|
_check_response_for_errors(response)
|
@@ -1048,7 +779,7 @@ class KiaUvoApiEU(ApiImplType1):
|
|
1048
779
|
_LOGGER.debug(f"{DOMAIN} - _get_location response: {response}")
|
1049
780
|
_check_response_for_errors(response)
|
1050
781
|
return response["resMsg"]["gpsDetail"]
|
1051
|
-
except:
|
782
|
+
except Exception:
|
1052
783
|
_LOGGER.warning(f"{DOMAIN} - _get_location failed")
|
1053
784
|
return None
|
1054
785
|
|
@@ -1,12 +1,13 @@
|
|
1
1
|
# pylint:disable=missing-class-docstring,missing-function-docstring,wildcard-import,unused-wildcard-import,invalid-name
|
2
2
|
"""Vehicle class"""
|
3
|
+
|
3
4
|
import logging
|
4
5
|
import datetime
|
5
6
|
import typing
|
6
7
|
from dataclasses import dataclass, field
|
7
8
|
|
8
9
|
from .utils import get_float
|
9
|
-
from .const import
|
10
|
+
from .const import DISTANCE_UNITS
|
10
11
|
|
11
12
|
_LOGGER = logging.getLogger(__name__)
|
12
13
|
|