hyundai-kia-connect-api 3.17.6__py2.py3-none-any.whl → 3.32.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.
@@ -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
@@ -17,10 +16,10 @@ import requests
17
16
  from dateutil import tz
18
17
 
19
18
  from .ApiImpl import (
20
- ApiImpl,
21
19
  ClimateRequestOptions,
22
20
  WindowRequestOptions,
23
21
  )
22
+ from .ApiImplType1 import ApiImplType1
24
23
  from .Token import Token
25
24
  from .Vehicle import (
26
25
  Vehicle,
@@ -43,19 +42,27 @@ from .const import (
43
42
  ENGINE_TYPES,
44
43
  OrderStatus,
45
44
  )
46
- from .exceptions import *
45
+ from .exceptions import (
46
+ AuthenticationError,
47
+ DuplicateRequestError,
48
+ RequestTimeoutError,
49
+ ServiceTemporaryUnavailable,
50
+ NoDataFound,
51
+ InvalidAPIResponseError,
52
+ APIError,
53
+ RateLimitingError,
54
+ )
47
55
  from .utils import (
48
56
  get_child_value,
49
57
  get_index_into_hex_temp,
50
58
  get_hex_temp_into_index,
59
+ parse_datetime,
51
60
  )
52
61
 
53
62
  _LOGGER = logging.getLogger(__name__)
54
63
 
55
64
  USER_AGENT_OK_HTTP: str = "okhttp/3.12.0"
56
- USER_AGENT_MOZILLA: str = (
57
- "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
58
- )
65
+ 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
59
66
 
60
67
 
61
68
  def _check_response_for_errors(response: dict) -> None:
@@ -96,7 +103,7 @@ def _check_response_for_errors(response: dict) -> None:
96
103
  raise APIError(f"Server returned: '{response['resMsg']}'")
97
104
 
98
105
 
99
- class KiaUvoApiAU(ApiImpl):
106
+ class KiaUvoApiAU(ApiImplType1):
100
107
  data_timezone = tz.gettz("Australia/Sydney")
101
108
  temperature_range = [x * 0.5 for x in range(34, 54)]
102
109
 
@@ -106,35 +113,18 @@ class KiaUvoApiAU(ApiImpl):
106
113
  self.BASE_URL: str = "au-apigw.ccs.kia.com.au:8082"
107
114
  self.CCSP_SERVICE_ID: str = "8acb778a-b918-4a8d-8624-73a0beb64289"
108
115
  self.APP_ID: str = "4ad4dcde-be23-48a8-bc1c-91b94f5c06f8" # Android app ID
109
- self.BASIC_AUTHORIZATION: str = (
110
- "Basic OGFjYjc3OGEtYjkxOC00YThkLTg2MjQtNzNhMGJlYjY0Mjg5OjdTY01NbTZmRVlYZGlFUEN4YVBhUW1nZVlkbFVyZndvaDRBZlhHT3pZSVMyQ3U5VA=="
111
- )
116
+ self.BASIC_AUTHORIZATION: str = "Basic OGFjYjc3OGEtYjkxOC00YThkLTg2MjQtNzNhMGJlYjY0Mjg5OjdTY01NbTZmRVlYZGlFUEN4YVBhUW1nZVlkbFVyZndvaDRBZlhHT3pZSVMyQ3U5VA==" # noqa
112
117
  elif BRANDS[brand] == BRAND_HYUNDAI:
113
118
  self.BASE_URL: str = "au-apigw.ccs.hyundai.com.au:8080"
114
119
  self.CCSP_SERVICE_ID: str = "855c72df-dfd7-4230-ab03-67cbf902bb1c"
115
120
  self.APP_ID: str = "f9ccfdac-a48d-4c57-bd32-9116963c24ed" # Android app ID
116
- self.BASIC_AUTHORIZATION: str = (
117
- "Basic ODU1YzcyZGYtZGZkNy00MjMwLWFiMDMtNjdjYmY5MDJiYjFjOmU2ZmJ3SE0zMllOYmhRbDBwdmlhUHAzcmY0dDNTNms5MWVjZUEzTUpMZGJkVGhDTw=="
118
- )
121
+ self.BASIC_AUTHORIZATION: str = "Basic ODU1YzcyZGYtZGZkNy00MjMwLWFiMDMtNjdjYmY5MDJiYjFjOmU2ZmJ3SE0zMllOYmhRbDBwdmlhUHAzcmY0dDNTNms5MWVjZUEzTUpMZGJkVGhDTw==" # noqa
119
122
 
120
123
  self.USER_API_URL: str = "https://" + self.BASE_URL + "/api/v1/user/"
121
124
  self.SPA_API_URL: str = "https://" + self.BASE_URL + "/api/v1/spa/"
122
125
  self.SPA_API_URL_V2: str = "https://" + self.BASE_URL + "/api/v2/spa/"
123
126
  self.CLIENT_ID: str = self.CCSP_SERVICE_ID
124
127
 
125
- def _get_authenticated_headers(self, token: Token) -> dict:
126
- return {
127
- "Authorization": token.access_token,
128
- "ccsp-service-id": self.CCSP_SERVICE_ID,
129
- "ccsp-application-id": self.APP_ID,
130
- "ccsp-device-id": token.device_id,
131
- "Stamp": self._get_stamp(),
132
- "Host": self.BASE_URL,
133
- "Connection": "Keep-Alive",
134
- "Accept-Encoding": "gzip",
135
- "User-Agent": USER_AGENT_OK_HTTP,
136
- }
137
-
138
128
  def _get_control_headers(self, token: Token) -> dict:
139
129
  control_token, _ = self._get_control_token(token)
140
130
  authenticated_headers = self._get_authenticated_headers(token)
@@ -200,29 +190,11 @@ class KiaUvoApiAU(ApiImpl):
200
190
  VIN=entry["vin"],
201
191
  timezone=self.data_timezone,
202
192
  engine_type=entry_engine_type,
193
+ ccu_ccs2_protocol_support=entry["ccuCCS2ProtocolSupport"],
203
194
  )
204
195
  result.append(vehicle)
205
196
  return result
206
197
 
207
- def get_last_updated_at(self, value) -> dt.datetime:
208
- _LOGGER.debug(f"{DOMAIN} - last_updated_at - before {value}")
209
- if value is None:
210
- value = dt.datetime(2000, 1, 1, tzinfo=self.data_timezone)
211
- else:
212
- m = re.match(r"(\d{4})(\d{2})(\d{2})(\d{2})(\d{2})(\d{2})", value)
213
- value = dt.datetime(
214
- year=int(m.group(1)),
215
- month=int(m.group(2)),
216
- day=int(m.group(3)),
217
- hour=int(m.group(4)),
218
- minute=int(m.group(5)),
219
- second=int(m.group(6)),
220
- tzinfo=self.data_timezone,
221
- )
222
-
223
- _LOGGER.debug(f"{DOMAIN} - last_updated_at - after {value}")
224
- return value
225
-
226
198
  def _get_time_from_string(self, value, timesection) -> dt.datetime.time:
227
199
  if value is not None:
228
200
  lastTwo = int(value[-2:])
@@ -238,17 +210,40 @@ class KiaUvoApiAU(ApiImpl):
238
210
  return value
239
211
 
240
212
  def update_vehicle_with_cached_state(self, token: Token, vehicle: Vehicle) -> None:
241
- status = self._get_cached_vehicle_state(token, vehicle)
242
- location = self._get_location(token, vehicle)
243
- self._update_vehicle_properties(
244
- vehicle,
245
- {
246
- "status": status,
247
- "vehicleLocation": location,
248
- },
249
- )
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
+ )
250
242
 
251
- if vehicle.engine_type == ENGINE_TYPES.EV:
243
+ if (
244
+ vehicle.engine_type == ENGINE_TYPES.EV
245
+ or vehicle.engine_type == ENGINE_TYPES.PHEV
246
+ ):
252
247
  try:
253
248
  state = self._get_driving_info(token, vehicle)
254
249
  except Exception as e:
@@ -278,15 +273,19 @@ class KiaUvoApiAU(ApiImpl):
278
273
  )
279
274
  # Only call for driving info on cars we know have a chance of supporting it.
280
275
  # Could be expanded if other types do support it.
281
- if vehicle.engine_type == ENGINE_TYPES.EV:
276
+ if (
277
+ vehicle.engine_type == ENGINE_TYPES.EV
278
+ or vehicle.engine_type == ENGINE_TYPES.PHEV
279
+ ):
282
280
  try:
283
281
  state = self._get_driving_info(token, vehicle)
284
282
  except Exception as e:
285
- # we don't know if all car types provide this information.
286
- # we also don't know what the API returns if the info is unavailable.
287
- # so, catch any exception and move on.
283
+ # we don't know if all car types (ex: ICE cars) provide this
284
+ # information. We also don't know what the API returns if
285
+ # the info is unavailable. So, catch any exception and move on.
288
286
  _LOGGER.exception(
289
287
  """Failed to parse driving info. Possible reasons:
288
+ - incompatible vehicle (ICE)
290
289
  - new API format
291
290
  - API outage
292
291
  """,
@@ -297,21 +296,22 @@ class KiaUvoApiAU(ApiImpl):
297
296
 
298
297
  def _update_vehicle_properties(self, vehicle: Vehicle, state: dict) -> None:
299
298
  if get_child_value(state, "status.time"):
300
- vehicle.last_updated_at = self.get_last_updated_at(
301
- get_child_value(state, "status.time")
299
+ vehicle.last_updated_at = parse_datetime(
300
+ get_child_value(state, "status.time"), self.data_timezone
302
301
  )
303
302
  else:
304
303
  vehicle.last_updated_at = dt.datetime.now(self.data_timezone)
305
304
 
306
- vehicle.odometer = (
307
- get_child_value(state, "status.odometer.value"),
308
- DISTANCE_UNITS[
309
- get_child_value(
310
- state,
311
- "status.odometer.unit",
312
- )
313
- ],
314
- )
305
+ if get_child_value(state, "status.odometer.value"):
306
+ vehicle.odometer = (
307
+ get_child_value(state, "status.odometer.value"),
308
+ DISTANCE_UNITS[
309
+ get_child_value(
310
+ state,
311
+ "status.odometer.unit",
312
+ )
313
+ ],
314
+ )
315
315
  vehicle.car_battery_percentage = get_child_value(state, "status.battery.batSoc")
316
316
  vehicle.engine_is_running = get_child_value(state, "status.engine")
317
317
 
@@ -490,7 +490,7 @@ class KiaUvoApiAU(ApiImpl):
490
490
  vehicle.ev_charge_limits_dc = [
491
491
  x["targetSOClevel"] for x in target_soc_list if x["plugType"] == 0
492
492
  ][-1]
493
- except:
493
+ except Exception:
494
494
  _LOGGER.debug(f"{DOMAIN} - SOC Levels couldn't be found. May not be an EV.")
495
495
  if (
496
496
  get_child_value(
@@ -646,8 +646,8 @@ class KiaUvoApiAU(ApiImpl):
646
646
  vehicle.location = (
647
647
  get_child_value(state, "vehicleLocation.coord.lat"),
648
648
  get_child_value(state, "vehicleLocation.coord.lon"),
649
- self.get_last_updated_at(
650
- get_child_value(state, "vehicleLocation.time")
649
+ parse_datetime(
650
+ get_child_value(state, "vehicleLocation.time"), self.data_timezone
651
651
  ),
652
652
  )
653
653
  vehicle.data = state
@@ -657,18 +657,6 @@ class KiaUvoApiAU(ApiImpl):
657
657
  vehicle.power_consumption_30d = get_child_value(state, "consumption30d")
658
658
  vehicle.daily_stats = get_child_value(state, "dailyStats")
659
659
 
660
- def _get_cached_vehicle_state(self, token: Token, vehicle: Vehicle) -> dict:
661
- url = self.SPA_API_URL + "vehicles/" + vehicle.id + "/status/latest"
662
-
663
- response = requests.get(
664
- url, headers=self._get_authenticated_headers(token)
665
- ).json()
666
- _LOGGER.debug(f"{DOMAIN} - get_cached_vehicle_status response: {response}")
667
- _check_response_for_errors(response)
668
- response = response["resMsg"]
669
-
670
- return response
671
-
672
660
  def _get_location(self, token: Token, vehicle: Vehicle) -> dict:
673
661
  url = self.SPA_API_URL + "vehicles/" + vehicle.id + "/location/park"
674
662
 
@@ -679,7 +667,7 @@ class KiaUvoApiAU(ApiImpl):
679
667
  _LOGGER.debug(f"{DOMAIN} - _get_location response: {response}")
680
668
  _check_response_for_errors(response)
681
669
  return response["resMsg"]["gpsDetail"]
682
- except:
670
+ except Exception:
683
671
  _LOGGER.debug(f"{DOMAIN} - _get_location failed")
684
672
  return None
685
673
 
@@ -867,7 +855,7 @@ class KiaUvoApiAU(ApiImpl):
867
855
  yyyymm_string,
868
856
  ) -> None:
869
857
  """
870
- Europe feature only.
858
+ feature only available for some regions.
871
859
  Updates the vehicle.month_trip_info for the specified month.
872
860
 
873
861
  Default this information is None:
@@ -911,7 +899,7 @@ class KiaUvoApiAU(ApiImpl):
911
899
  yyyymmdd_string,
912
900
  ) -> None:
913
901
  """
914
- Europe feature only.
902
+ feature only available for some regions.
915
903
  Updates the vehicle.day_trip_info information for the specified day.
916
904
 
917
905
  Default this information is None:
@@ -985,6 +973,7 @@ class KiaUvoApiAU(ApiImpl):
985
973
  battery_care_consumption=day["batteryMgPwrCsp"],
986
974
  regenerated_energy=day["regenPwr"],
987
975
  distance=day["calculativeOdo"],
976
+ distance_unit=vehicle.odometer_unit,
988
977
  )
989
978
  drivingInfo["dailyStats"].append(processedDay)
990
979
 
@@ -2,10 +2,10 @@
2
2
 
3
3
  # pylint:disable=unused-argument,missing-timeout,logging-fstring-interpolation,bare-except,invalid-name,missing-function-docstring
4
4
 
5
+ import time
5
6
  import datetime as dt
6
7
  import json
7
8
  import logging
8
- import re
9
9
 
10
10
  import pytz
11
11
  import requests
@@ -35,6 +35,7 @@ from .utils import (
35
35
  get_child_value,
36
36
  get_hex_temp_into_index,
37
37
  get_index_into_hex_temp,
38
+ parse_datetime,
38
39
  )
39
40
 
40
41
  import ssl
@@ -69,6 +70,7 @@ class KiaUvoApiCA(ApiImpl):
69
70
  def __init__(self, region: int, brand: int, language: str) -> None:
70
71
  self.vehicle_timezone = self.data_timezone
71
72
  self.LANGUAGE: str = language
73
+ self.brand = brand
72
74
  if BRANDS[brand] == BRAND_KIA:
73
75
  self.BASE_URL: str = "kiaconnect.ca"
74
76
  elif BRANDS[brand] == BRAND_HYUNDAI:
@@ -94,8 +96,14 @@ class KiaUvoApiCA(ApiImpl):
94
96
  "sec-fetch-mode": "cors",
95
97
  "sec-fetch-site": "same-origin",
96
98
  }
97
- self.sessions = requests.Session()
98
- self.sessions.mount("https://" + self.BASE_URL, cipherAdapter())
99
+ self._sessions = None
100
+
101
+ @property
102
+ def sessions(self):
103
+ if not self._sessions:
104
+ self._sessions = requests.Session()
105
+ self._sessions.mount("https://" + self.BASE_URL, cipherAdapter())
106
+ return self._sessions
99
107
 
100
108
  def _check_response_for_errors(self, response: dict) -> None:
101
109
  """
@@ -202,8 +210,8 @@ class KiaUvoApiCA(ApiImpl):
202
210
 
203
211
  # Calculate offset between vehicle last_updated_at and UTC
204
212
  self.vehicle_timezone = vehicle.timezone
205
- last_updated_at = self.get_last_updated_at(
206
- get_child_value(state, "status.lastStatusDate")
213
+ last_updated_at = parse_datetime(
214
+ get_child_value(state, "status.lastStatusDate"), self.data_timezone
207
215
  )
208
216
  now_utc: dt = dt.datetime.now(pytz.utc)
209
217
  offset = round((last_updated_at - now_utc).total_seconds() / 3600)
@@ -238,15 +246,19 @@ class KiaUvoApiCA(ApiImpl):
238
246
  def _update_vehicle_properties_base(self, vehicle: Vehicle, state: dict) -> None:
239
247
  _LOGGER.debug(f"{DOMAIN} - Old Vehicle Last Updated: {vehicle.last_updated_at}")
240
248
  self.vehicle_timezone = vehicle.timezone
241
- vehicle.last_updated_at = self.get_last_updated_at(
242
- get_child_value(state, "status.lastStatusDate")
249
+ vehicle.last_updated_at = parse_datetime(
250
+ get_child_value(state, "status.lastStatusDate"), self.data_timezone
243
251
  )
244
252
  _LOGGER.debug(
245
253
  f"{DOMAIN} - Current Vehicle Last Updated: {vehicle.last_updated_at}"
246
254
  )
247
255
  # Converts temp to usable number. Currently only support celsius.
248
256
  # Future to do is check unit in case the care itself is set to F.
249
- if get_child_value(state, "status.airTemp.value") != "OFF":
257
+ if (
258
+ get_child_value(state, "status.airTemp.value") is not None
259
+ and get_child_value(state, "status.airTemp.value") != "OFF"
260
+ and get_child_value(state, "status.airTemp.value")[-1] == "H"
261
+ ):
250
262
  tempIndex = get_hex_temp_into_index(
251
263
  get_child_value(state, "status.airTemp.value")
252
264
  )
@@ -426,29 +438,10 @@ class KiaUvoApiCA(ApiImpl):
426
438
  vehicle.location = (
427
439
  get_child_value(state, "coord.lat"),
428
440
  get_child_value(state, "coord.lon"),
429
- self.get_last_updated_at(get_child_value(state, "time")),
441
+ parse_datetime(get_child_value(state, "time"), self.data_timezone),
430
442
  )
431
443
  vehicle.data["vehicleLocation"] = state
432
444
 
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
445
  def _get_cached_vehicle_state(self, token: Token, vehicle: Vehicle) -> dict:
453
446
  # Vehicle Status Call
454
447
  url = self.API_URL + "lstvhclsts"
@@ -509,7 +502,7 @@ class KiaUvoApiCA(ApiImpl):
509
502
  if response["responseHeader"]["responseCode"] != 0:
510
503
  raise APIError("No Location Located")
511
504
  return response["result"]
512
- except:
505
+ except Exception:
513
506
  _LOGGER.warning(f"{DOMAIN} - Get vehicle location failed")
514
507
  return None
515
508
 
@@ -590,18 +583,33 @@ class KiaUvoApiCA(ApiImpl):
590
583
  )
591
584
  if vehicle.engine_type == ENGINE_TYPES.EV:
592
585
  payload = {
593
- "hvacInfo": {
594
- "airCtrl": int(options.climate),
595
- "defrost": options.defrost,
596
- "heating1": options.heating,
597
- "airTemp": {
598
- "value": hex_set_temp,
599
- "unit": 0,
600
- "hvacTempType": 1,
601
- },
602
- },
603
586
  "pin": token.pin,
604
587
  }
588
+ climate_settings = {
589
+ "airCtrl": int(options.climate),
590
+ "defrost": options.defrost,
591
+ "heating1": options.heating,
592
+ "airTemp": {
593
+ "value": hex_set_temp,
594
+ "unit": 0,
595
+ "hvacTempType": 1,
596
+ },
597
+ }
598
+ if BRANDS[self.brand] == BRAND_KIA:
599
+ payload["remoteControl"] = climate_settings
600
+ payload["remoteControl"].update(
601
+ {
602
+ "igniOnDuration": options.duration,
603
+ "seatHeaterVentCMD": {
604
+ "drvSeatOptCmd": options.front_left_seat,
605
+ "astSeatOptCmd": options.front_right_seat,
606
+ "rlSeatOptCmd": options.rear_left_seat,
607
+ "rrSeatOptCmd": options.rear_right_seat,
608
+ },
609
+ }
610
+ )
611
+ else:
612
+ payload["hvacInfo"] = climate_settings
605
613
  else:
606
614
  payload = {
607
615
  "setting": {
@@ -656,6 +664,10 @@ class KiaUvoApiCA(ApiImpl):
656
664
  synchronous: bool = False,
657
665
  timeout: int = 0,
658
666
  ) -> OrderStatus:
667
+ if timeout < 0:
668
+ return OrderStatus.TIMEOUT
669
+ start_time = dt.datetime.now()
670
+
659
671
  url = self.API_URL + "rmtsts"
660
672
  headers = self.API_HEADERS
661
673
  headers["accessToken"] = token.access_token
@@ -668,10 +680,27 @@ class KiaUvoApiCA(ApiImpl):
668
680
  last_action_completed = (
669
681
  response["result"]["transaction"]["apiStatusCode"] != "null"
670
682
  )
683
+
671
684
  if last_action_completed:
672
685
  action_status = response["result"]["transaction"]["apiStatusCode"]
673
686
  _LOGGER.debug(f"{DOMAIN} - Last action_status: {action_status}")
674
- return last_action_completed
687
+
688
+ if response["responseHeader"]["responseCode"] == 1:
689
+ return OrderStatus.FAILED
690
+ elif response["result"]["transaction"]["apiResult"] == "C":
691
+ return OrderStatus.SUCCESS
692
+ elif response["result"]["transaction"]["apiResult"] == "P":
693
+ if not synchronous:
694
+ return OrderStatus.PENDING
695
+ else:
696
+ timedelta = dt.datetime.now() - start_time
697
+ time_left = timeout - timedelta.seconds - 10
698
+ time.sleep(10)
699
+ return self.check_action_status(
700
+ token, vehicle, action_id, synchronous, time_left
701
+ )
702
+
703
+ return OrderStatus.FAILED
675
704
 
676
705
  def start_charge(self, token: Token, vehicle: Vehicle) -> str:
677
706
  url = self.API_URL + "evc/rcstrt"
@@ -717,7 +746,7 @@ class KiaUvoApiCA(ApiImpl):
717
746
  vehicle.ev_charge_limits_dc = [
718
747
  x["level"] for x in state if x["plugType"] == 0
719
748
  ][-1]
720
- except:
749
+ except Exception:
721
750
  _LOGGER.debug(f"{DOMAIN} - SOC Levels couldn't be found. May not be an EV.")
722
751
 
723
752
  def _get_charge_limits(self, token: Token, vehicle: Vehicle) -> dict: