volkswagencarnet 5.0.0b3__py3-none-any.whl → 5.0.0b4__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.

Potentially problematic release.


This version of volkswagencarnet might be problematic. Click here for more details.

@@ -1,15 +1,14 @@
1
1
  #!/usr/bin/env python3
2
- """Vehicle class for Volkswagen Connect."""
3
-
2
+ """Vehicle class for We Connect."""
4
3
  from __future__ import annotations
5
4
 
6
5
  import asyncio
6
+ import logging
7
7
  from collections import OrderedDict
8
- from datetime import UTC, datetime, timedelta
8
+ from datetime import datetime, timedelta, timezone
9
9
  from json import dumps as to_json
10
- import logging
11
10
 
12
- from .vw_const import Services, VehicleStatusParameter as P
11
+ from .vw_const import VehicleStatusParameter as P, Services
13
12
  from .vw_utilities import find_path, is_valid_path
14
13
 
15
14
  # TODO
@@ -25,21 +24,15 @@ _LOGGER = logging.getLogger(__name__)
25
24
  ENGINE_TYPE_ELECTRIC = "electric"
26
25
  ENGINE_TYPE_DIESEL = "diesel"
27
26
  ENGINE_TYPE_GASOLINE = "gasoline"
28
- ENGINE_TYPE_CNG = "cng"
29
27
  ENGINE_TYPE_HYBRID = "hybrid"
30
- ENGINE_TYPE_COMBUSTION = [
31
- ENGINE_TYPE_DIESEL,
32
- ENGINE_TYPE_GASOLINE,
33
- ENGINE_TYPE_CNG,
34
- ]
35
- ENGINE_TYPE_GAS = [ENGINE_TYPE_CNG]
28
+ ENGINE_TYPE_COMBUSTION = [ENGINE_TYPE_DIESEL, ENGINE_TYPE_GASOLINE]
36
29
  DEFAULT_TARGET_TEMP = 24
37
30
 
38
31
 
39
32
  class Vehicle:
40
33
  """Vehicle contains the state of sensors and methods for interacting with the car."""
41
34
 
42
- def __init__(self, conn, url) -> None:
35
+ def __init__(self, conn, url):
43
36
  """Initialize the Vehicle with default values."""
44
37
  self._connection = conn
45
38
  self._url = url
@@ -47,17 +40,18 @@ class Vehicle:
47
40
  self._discovered = False
48
41
  self._states = {}
49
42
  self._requests: dict[str, object] = {
50
- "departuretimer": {"status": "", "timestamp": datetime.now(UTC)},
51
- "batterycharge": {"status": "", "timestamp": datetime.now(UTC)},
52
- "climatisation": {"status": "", "timestamp": datetime.now(UTC)},
53
- "refresh": {"status": "", "timestamp": datetime.now(UTC)},
54
- "lock": {"status": "", "timestamp": datetime.now(UTC)},
43
+ "departuretimer": {"status": "", "timestamp": datetime.now(timezone.utc)},
44
+ "batterycharge": {"status": "", "timestamp": datetime.now(timezone.utc)},
45
+ "climatisation": {"status": "", "timestamp": datetime.now(timezone.utc)},
46
+ "refresh": {"status": "", "timestamp": datetime.now(timezone.utc)},
47
+ "lock": {"status": "", "timestamp": datetime.now(timezone.utc)},
55
48
  "latest": "",
56
49
  "state": "",
57
50
  }
58
51
 
59
52
  # API Endpoints that might be enabled for car (that we support)
60
53
  self._services: dict[str, dict[str, object]] = {
54
+ # TODO needs a complete rework...
61
55
  Services.ACCESS: {"active": False},
62
56
  Services.BATTERY_CHARGING_CARE: {"active": False},
63
57
  Services.BATTERY_SUPPORT: {"active": False},
@@ -79,50 +73,33 @@ class Vehicle:
79
73
  """Check if request is already in progress."""
80
74
  if self._requests.get(topic, {}).get("id", False):
81
75
  timestamp = self._requests.get(topic, {}).get(
82
- "timestamp",
83
- datetime.now(UTC) - timedelta(minutes=unknown_offset),
76
+ "timestamp", datetime.now(timezone.utc) - timedelta(minutes=unknown_offset)
84
77
  )
85
- if timestamp + timedelta(minutes=3) < datetime.now(UTC):
78
+ if timestamp + timedelta(minutes=3) < datetime.now(timezone.utc):
86
79
  self._requests.get(topic, {}).pop("id")
87
80
  else:
88
- _LOGGER.info("Action (%s) already in progress", topic)
81
+ _LOGGER.info(f"Action ({topic}) already in progress")
89
82
  return True
90
83
  return False
91
84
 
92
- async def _handle_response(
93
- self, response, topic: str, error_msg: str | None = None
94
- ) -> bool:
85
+ async def _handle_response(self, response, topic: str, error_msg: str | None = None) -> bool:
95
86
  """Handle errors in response and get requests remaining."""
96
87
  if not response:
88
+ self._requests[topic] = {"status": "Failed", "timestamp": datetime.now(timezone.utc)}
89
+ _LOGGER.error(error_msg if error_msg is not None else f"Failed to perform {topic} action")
90
+ raise Exception(error_msg if error_msg is not None else f"Failed to perform {topic} action")
91
+ else:
97
92
  self._requests[topic] = {
98
- "status": "Failed",
99
- "timestamp": datetime.now(UTC),
93
+ "timestamp": datetime.now(timezone.utc),
94
+ "status": response.get("state", "Unknown"),
95
+ "id": response.get("id", 0),
100
96
  }
101
- _LOGGER.error(
102
- error_msg
103
- if error_msg is not None
104
- else f"Failed to perform {topic} action"
105
- )
106
- # pylint: disable=broad-exception-raised
107
- raise Exception(
108
- error_msg
109
- if error_msg is not None
110
- else f"Failed to perform {topic} action"
111
- )
112
- self._requests[topic] = {
113
- "timestamp": datetime.now(UTC),
114
- "status": response.get("state", "Unknown"),
115
- "id": response.get("id", 0),
116
- }
117
- if response.get("state", None) == "Throttled":
118
- status = "Throttled"
119
- _LOGGER.warning("Request throttled (%s)", topic)
120
- else:
121
- status = await self.wait_for_request(request=response.get("id", 0))
122
- self._requests[topic] = {
123
- "status": status,
124
- "timestamp": datetime.now(UTC),
125
- }
97
+ if response.get("state", None) == "Throttled":
98
+ status = "Throttled"
99
+ _LOGGER.warning(f"Request throttled ({topic}")
100
+ else:
101
+ status = await self.wait_for_request(request=response.get("id", 0))
102
+ self._requests[topic] = {"status": status, "timestamp": datetime.now(timezone.utc)}
126
103
  return True
127
104
 
128
105
  # API get and set functions #
@@ -130,64 +107,43 @@ class Vehicle:
130
107
  async def discover(self):
131
108
  """Discover vehicle and initial data."""
132
109
 
133
- _LOGGER.debug("Attempting discovery of supported API endpoints for vehicle")
134
-
110
+ _LOGGER.debug("Attempting discovery of supported API endpoints for vehicle.")
135
111
  capabilities_response = await self._connection.getOperationList(self.vin)
136
112
  parameters_list = capabilities_response.get("parameters", {})
137
113
  capabilities_list = capabilities_response.get("capabilities", {})
138
-
139
- # Update services with parameters
140
114
  if parameters_list:
141
115
  self._services[Services.PARAMETERS].update(parameters_list)
142
-
143
- # If there are no capabilities, log a warning
144
- if not capabilities_list:
145
- _LOGGER.warning(
146
- "Could not determine available API endpoints for %s", self.vin
147
- )
148
- self._discovered = True
149
- return
150
-
151
- for service_id, service in capabilities_list.items():
152
- if service_id not in self._services:
153
- continue
154
-
155
- service_name = service.get("id", "Unknown Service")
156
- data = {}
157
-
158
- if service.get("isEnabled", False):
159
- data["active"] = True
160
- _LOGGER.debug("Discovered enabled service: %s", service_name)
161
-
162
- expiration_date = service.get("expirationDate", None)
163
- if expiration_date:
164
- data["expiration"] = expiration_date
165
-
166
- operations = service.get("operations", {})
167
- data["operations"] = [op.get("id", None) for op in operations.values()]
168
-
169
- parameters = service.get("parameters", [])
170
- data["parameters"] = parameters
171
-
172
- else:
173
- reason = service.get("status", "Unknown reason")
174
- _LOGGER.debug(
175
- "Service: %s is disabled due to: %s", service_name, reason
176
- )
177
- data["active"] = False
178
-
179
- # Update the service data
180
- try:
181
- self._services[service_name].update(data)
182
- except Exception as error: # pylint: disable=broad-exception-caught
183
- _LOGGER.warning(
184
- 'Exception "%s" while updating service "%s": %s',
185
- error,
186
- service_name,
187
- data,
188
- )
189
-
190
- _LOGGER.debug("API endpoints: %s", self._services)
116
+ if capabilities_list:
117
+ for service_id in capabilities_list.keys():
118
+ try:
119
+ if service_id in self._services.keys():
120
+ service = capabilities_list[service_id]
121
+ data = {}
122
+ service_name = service.get("id", None)
123
+ if service.get("isEnabled", False):
124
+ _LOGGER.debug(f"Discovered enabled service: {service_name}")
125
+ data["active"] = True
126
+ if service.get("expirationDate", False):
127
+ data["expiration"] = service.get("expirationDate", None)
128
+ if service.get("operations", False):
129
+ data.update({"operations": []})
130
+ for operation_id in service.get("operations", []).keys():
131
+ operation = service.get("operations").get(operation_id)
132
+ data["operations"].append(operation.get("id", None))
133
+ if service.get("parameters", False):
134
+ data.update({"parameters": []})
135
+ for parameter in service.get("parameters", []):
136
+ data["parameters"].append(parameter)
137
+ else:
138
+ reason = service.get("status", "Unknown")
139
+ _LOGGER.debug(f"Service: {service_name} is disabled because of reason: {reason}")
140
+ data["active"] = False
141
+ self._services[service_name].update(data)
142
+ except Exception as error:
143
+ _LOGGER.warning(f'Encountered exception: "{error}" while parsing service item: {service}')
144
+ else:
145
+ _LOGGER.warning(f"Could not determine available API endpoints for {self.vin}")
146
+ _LOGGER.debug(f"API endpoints: {self._services}")
191
147
  self._discovered = True
192
148
 
193
149
  async def update(self):
@@ -219,7 +175,7 @@ class Vehicle:
219
175
  )
220
176
  await asyncio.gather(self.get_service_status())
221
177
  else:
222
- _LOGGER.info("Vehicle with VIN %s is deactivated", self.vin)
178
+ _LOGGER.info(f"Vehicle with VIN {self.vin} is deactivated.")
223
179
 
224
180
  # Data collection functions
225
181
  async def get_selectivestatus(self, services):
@@ -258,28 +214,26 @@ class Vehicle:
258
214
  """Update status of outstanding requests."""
259
215
  retry_count -= 1
260
216
  if retry_count == 0:
261
- _LOGGER.info("Timeout while waiting for result of %s", request.requestId)
217
+ _LOGGER.info(f"Timeout while waiting for result of {request.requestId}.")
262
218
  return "Timeout"
263
219
  try:
264
220
  status = await self._connection.get_request_status(self.vin, request)
265
- _LOGGER.debug("Request ID %s: %s", request, status)
221
+ _LOGGER.debug(f"Request ID {request}: {status}")
266
222
  self._requests["state"] = status
267
223
  if status == "In Progress":
268
224
  await asyncio.sleep(10)
269
225
  return await self.wait_for_request(request, retry_count)
270
- except Exception as error: # pylint: disable=broad-exception-caught
271
- _LOGGER.warning(
272
- "Exception encountered while waiting for request status: %s", error
273
- )
226
+ else:
227
+ return status
228
+ except Exception as error:
229
+ _LOGGER.warning(f"Exception encountered while waiting for request status: {error}")
274
230
  return "Exception"
275
- else:
276
- return status
277
231
 
278
232
  async def wait_for_data_refresh(self, retry_count=18):
279
233
  """Update status of outstanding requests."""
280
234
  retry_count -= 1
281
235
  if retry_count == 0:
282
- _LOGGER.info("Timeout while waiting for data refresh")
236
+ _LOGGER.info("Timeout while waiting for data refresh.")
283
237
  return "Timeout"
284
238
  try:
285
239
  await self.get_selectivestatus([Services.MEASUREMENTS])
@@ -287,32 +241,41 @@ class Vehicle:
287
241
  if self.last_connected < refresh_trigger_time:
288
242
  await asyncio.sleep(10)
289
243
  return await self.wait_for_data_refresh(retry_count)
290
-
291
- except Exception as error: # pylint: disable=broad-exception-caught
292
- _LOGGER.warning(
293
- "Exception encountered while waiting for data refresh: %s", error
294
- )
244
+ else:
245
+ return "successful"
246
+ except Exception as error:
247
+ _LOGGER.warning(f"Exception encountered while waiting for data refresh: {error}")
295
248
  return "Exception"
296
- else:
297
- return "successful"
298
249
 
299
250
  # Data set functions
300
251
  # Charging (BATTERYCHARGE)
252
+ async def set_charger_current(self, value):
253
+ """Set charger current."""
254
+ if self.is_charging_supported:
255
+ if 1 <= int(value) <= 255:
256
+ data = {"action": {"settings": {"maxChargeCurrent": int(value)}, "type": "setSettings"}}
257
+ else:
258
+ _LOGGER.error(f"Set charger maximum current to {value} is not supported.")
259
+ raise Exception(f"Set charger maximum current to {value} is not supported.")
260
+ return await self.set_charger(data)
261
+ else:
262
+ _LOGGER.error("No charger support.")
263
+ raise Exception("No charger support.")
264
+
301
265
  async def set_charger(self, action) -> bool:
302
266
  """Turn on/off charging."""
303
267
  if self.is_charging_supported:
304
268
  if action not in ["start", "stop"]:
305
- _LOGGER.error('Charging action "%s" is not supported', action)
306
- raise Exception(f'Charging action "{action}" is not supported.') # pylint: disable=broad-exception-raised
269
+ _LOGGER.error(f'Charging action "{action}" is not supported.')
270
+ raise Exception(f'Charging action "{action}" is not supported.')
307
271
  self._requests["latest"] = "Batterycharge"
308
272
  response = await self._connection.setCharging(self.vin, (action == "start"))
309
273
  return await self._handle_response(
310
- response=response,
311
- topic="charging",
312
- error_msg=f"Failed to {action} charging",
274
+ response=response, topic="charging", error_msg=f"Failed to {action} charging"
313
275
  )
314
- _LOGGER.error("No charging support")
315
- raise Exception("No charging support.") # pylint: disable=broad-exception-raised
276
+ else:
277
+ _LOGGER.error("No charging support.")
278
+ raise Exception("No charging support.")
316
279
 
317
280
  async def set_charging_settings(self, setting, value):
318
281
  """Set charging settings."""
@@ -320,96 +283,62 @@ class Vehicle:
320
283
  self.is_charge_max_ac_setting_supported
321
284
  or self.is_auto_release_ac_connector_supported
322
285
  or self.is_battery_target_charge_level_supported
323
- or self.is_charge_max_ac_ampere_supported
324
286
  ):
325
287
  if setting == "reduced_ac_charging" and value not in ["reduced", "maximum"]:
326
- _LOGGER.error('Charging setting "%s" is not supported', value)
327
- raise Exception(f'Charging setting "{value}" is not supported.') # pylint: disable=broad-exception-raised
328
- if setting == "max_charge_amperage" and int(value) not in [5, 10, 13, 32]:
329
- _LOGGER.error(
330
- "Setting maximum charge amperage to %s is not supported", value
331
- )
332
- # pylint: disable=broad-exception-raised
333
- raise Exception(
334
- f"Setting maximum charge amperage to {value} is not supported."
335
- )
288
+ _LOGGER.error(f'Charging setting "{value}" is not supported.')
289
+ raise Exception(f'Charging setting "{value}" is not supported.')
336
290
  data = {}
337
- if (
338
- self.is_charge_max_ac_setting_supported
339
- and setting != "max_charge_amperage"
340
- ):
341
- data["maxChargeCurrentAC"] = (
342
- value
343
- if setting == "reduced_ac_charging"
344
- else self.charge_max_ac_setting
345
- )
291
+ if self.is_charge_max_ac_setting_supported:
292
+ data["maxChargeCurrentAC"] = value if setting == "reduced_ac_charging" else self.charge_max_ac_setting
346
293
  if self.is_auto_release_ac_connector_supported:
347
294
  data["autoUnlockPlugWhenChargedAC"] = (
348
- value
349
- if setting == "auto_release_ac_connector"
350
- else self.auto_release_ac_connector_state
295
+ value if setting == "auto_release_ac_connector" else self.auto_release_ac_connector_state
351
296
  )
352
297
  if self.is_battery_target_charge_level_supported:
353
- self.battery_target_charge_level = value
298
+ self._battery_target_charge_level = value
354
299
  data["targetSOC_pct"] = (
355
- value
356
- if setting == "battery_target_charge_level"
357
- else self.battery_target_charge_level
358
- )
359
- if (
360
- self.is_charge_max_ac_ampere_supported
361
- and setting != "reduced_ac_charging"
362
- ):
363
- data["maxChargeCurrentAC_A"] = (
364
- int(value)
365
- if setting == "max_charge_amperage"
366
- else self.charge_max_ac_ampere
300
+ value if setting == "battery_target_charge_level" else self.battery_target_charge_level
367
301
  )
368
302
  self._requests["latest"] = "Batterycharge"
369
303
  response = await self._connection.setChargingSettings(self.vin, data)
370
304
  return await self._handle_response(
371
- response=response,
372
- topic="charging",
373
- error_msg="Failed to change charging settings",
305
+ response=response, topic="charging", error_msg="Failed to change charging settings"
374
306
  )
375
- _LOGGER.error("Charging settings are not supported")
376
- raise Exception("Charging settings are not supported.") # pylint: disable=broad-exception-raised
307
+ else:
308
+ _LOGGER.error("Charging settings are not supported.")
309
+ raise Exception("Charging settings are not supported.")
377
310
 
378
311
  async def set_charging_care_settings(self, value):
379
312
  """Set charging care settings."""
380
313
  if self.is_battery_care_mode_supported:
381
314
  if value not in ["activated", "deactivated"]:
382
- _LOGGER.error('Charging care mode "%s" is not supported', value)
383
- raise Exception(f'Charging care mode "{value}" is not supported.') # pylint: disable=broad-exception-raised
315
+ _LOGGER.error(f'Charging care mode "{value}" is not supported.')
316
+ raise Exception(f'Charging care mode "{value}" is not supported.')
384
317
  data = {"batteryCareMode": value}
385
318
  self._requests["latest"] = "Batterycharge"
386
- response = await self._connection.setChargingCareModeSettings(
387
- self.vin, data
388
- )
319
+ response = await self._connection.setChargingCareModeSettings(self.vin, data)
389
320
  return await self._handle_response(
390
- response=response,
391
- topic="charging",
392
- error_msg="Failed to change charging care settings",
321
+ response=response, topic="charging", error_msg="Failed to change charging care settings"
393
322
  )
394
- _LOGGER.error("Charging care settings are not supported")
395
- raise Exception("Charging care settings are not supported.") # pylint: disable=broad-exception-raised
323
+ else:
324
+ _LOGGER.error("Charging care settings are not supported.")
325
+ raise Exception("Charging care settings are not supported.")
396
326
 
397
327
  async def set_readiness_battery_support(self, value):
398
328
  """Set readiness battery support settings."""
399
329
  if self.is_optimised_battery_use_supported:
400
330
  if value not in [True, False]:
401
- _LOGGER.error('Battery support mode "%s" is not supported', value)
402
- raise Exception(f'Battery support mode "{value}" is not supported.') # pylint: disable=broad-exception-raised
331
+ _LOGGER.error(f'Battery support mode "{value}" is not supported.')
332
+ raise Exception(f'Battery support mode "{value}" is not supported.')
403
333
  data = {"batterySupportEnabled": value}
404
334
  self._requests["latest"] = "Batterycharge"
405
335
  response = await self._connection.setReadinessBatterySupport(self.vin, data)
406
336
  return await self._handle_response(
407
- response=response,
408
- topic="charging",
409
- error_msg="Failed to change battery support settings",
337
+ response=response, topic="charging", error_msg="Failed to change battery support settings"
410
338
  )
411
- _LOGGER.error("Battery support settings are not supported")
412
- raise Exception("Battery support settings are not supported.") # pylint: disable=broad-exception-raised
339
+ else:
340
+ _LOGGER.error("Battery support settings are not supported.")
341
+ raise Exception("Battery support settings are not supported.")
413
342
 
414
343
  # Climatisation electric/auxiliary/windows (CLIMATISATION)
415
344
  async def set_climatisation_settings(self, setting, value):
@@ -456,26 +385,16 @@ class Vehicle:
456
385
  )
457
386
  if self.is_auxiliary_air_conditioning_supported:
458
387
  data["climatizationAtUnlock"] = (
459
- value
460
- if setting == "auxiliary_air_conditioning"
461
- else self.auxiliary_air_conditioning
388
+ value if setting == "auxiliary_air_conditioning" else self.auxiliary_air_conditioning
462
389
  )
463
390
  if self.is_automatic_window_heating_supported:
464
391
  data["windowHeatingEnabled"] = (
465
- value
466
- if setting == "automatic_window_heating"
467
- else self.automatic_window_heating
392
+ value if setting == "automatic_window_heating" else self.automatic_window_heating
468
393
  )
469
394
  if self.is_zone_front_left_supported:
470
- data["zoneFrontLeftEnabled"] = (
471
- value if setting == "zone_front_left" else self.zone_front_left
472
- )
395
+ data["zoneFrontLeftEnabled"] = value if setting == "zone_front_left" else self.zone_front_left
473
396
  if self.is_zone_front_right_supported:
474
- data["zoneFrontRightEnabled"] = (
475
- value
476
- if setting == "zone_front_right"
477
- else self.zone_front_right
478
- )
397
+ data["zoneFrontRightEnabled"] = value if setting == "zone_front_right" else self.zone_front_right
479
398
  self._requests["latest"] = "Climatisation"
480
399
  response = await self._connection.setClimaterSettings(self.vin, data)
481
400
  return await self._handle_response(
@@ -483,28 +402,27 @@ class Vehicle:
483
402
  topic="climatisation",
484
403
  error_msg="Failed to set climatisation settings",
485
404
  )
486
- _LOGGER.error('Set climatisation setting to "%s" is not supported', value)
487
- raise Exception(f'Set climatisation setting to "{value}" is not supported.') # pylint: disable=broad-exception-raised
488
- _LOGGER.error("Climatisation settings are not supported")
489
- raise Exception("Climatisation settings are not supported.") # pylint: disable=broad-exception-raised
405
+ else:
406
+ _LOGGER.error(f'Set climatisation setting to "{value}" is not supported.')
407
+ raise Exception(f'Set climatisation setting to "{value}" is not supported.')
408
+ else:
409
+ _LOGGER.error("Climatisation settings are not supported.")
410
+ raise Exception("Climatisation settings are not supported.")
490
411
 
491
412
  async def set_window_heating(self, action="stop"):
492
413
  """Turn on/off window heater."""
493
414
  if self.is_window_heater_supported:
494
415
  if action not in ["start", "stop"]:
495
- _LOGGER.error('Window heater action "%s" is not supported', action)
496
- raise Exception(f'Window heater action "{action}" is not supported.') # pylint: disable=broad-exception-raised
416
+ _LOGGER.error(f'Window heater action "{action}" is not supported.')
417
+ raise Exception(f'Window heater action "{action}" is not supported.')
497
418
  self._requests["latest"] = "Climatisation"
498
- response = await self._connection.setWindowHeater(
499
- self.vin, (action == "start")
500
- )
419
+ response = await self._connection.setWindowHeater(self.vin, (action == "start"))
501
420
  return await self._handle_response(
502
- response=response,
503
- topic="climatisation",
504
- error_msg=f"Failed to {action} window heating",
421
+ response=response, topic="climatisation", error_msg=f"Failed to {action} window heating"
505
422
  )
506
- _LOGGER.error("No climatisation support")
507
- raise Exception("No climatisation support.") # pylint: disable=broad-exception-raised
423
+ else:
424
+ _LOGGER.error("No climatisation support.")
425
+ raise Exception("No climatisation support.")
508
426
 
509
427
  async def set_climatisation(self, action="stop"):
510
428
  """Turn on/off climatisation with electric heater."""
@@ -515,9 +433,7 @@ class Vehicle:
515
433
  "targetTemperatureUnit": "celsius",
516
434
  }
517
435
  if self.is_climatisation_without_external_power_supported:
518
- data["climatisationWithoutExternalPower"] = (
519
- self.climatisation_without_external_power
520
- )
436
+ data["climatisationWithoutExternalPower"] = self.climatisation_without_external_power
521
437
  if self.is_auxiliary_air_conditioning_supported:
522
438
  data["climatizationAtUnlock"] = self.auxiliary_air_conditioning
523
439
  if self.is_automatic_window_heating_supported:
@@ -529,19 +445,18 @@ class Vehicle:
529
445
  elif action == "stop":
530
446
  data = {}
531
447
  else:
532
- _LOGGER.error("Invalid climatisation action: %s", action)
533
- raise Exception(f"Invalid climatisation action: {action}") # pylint: disable=broad-exception-raised
448
+ _LOGGER.error(f"Invalid climatisation action: {action}")
449
+ raise Exception(f"Invalid climatisation action: {action}")
534
450
  self._requests["latest"] = "Climatisation"
535
- response = await self._connection.setClimater(
536
- self.vin, data, (action == "start")
537
- )
451
+ response = await self._connection.setClimater(self.vin, data, (action == "start"))
538
452
  return await self._handle_response(
539
453
  response=response,
540
454
  topic="climatisation",
541
455
  error_msg=f"Failed to {action} climatisation with electric heater.",
542
456
  )
543
- _LOGGER.error("No climatisation support")
544
- raise Exception("No climatisation support.") # pylint: disable=broad-exception-raised
457
+ else:
458
+ _LOGGER.error("No climatisation support.")
459
+ raise Exception("No climatisation support.")
545
460
 
546
461
  async def set_auxiliary_climatisation(self, action, spin):
547
462
  """Turn on/off climatisation with auxiliary heater."""
@@ -553,102 +468,72 @@ class Vehicle:
553
468
  elif action == "stop":
554
469
  data = {}
555
470
  else:
556
- _LOGGER.error("Invalid auxiliary heater action: %s", action)
557
- raise Exception(f"Invalid auxiliary heater action: {action}") # pylint: disable=broad-exception-raised
471
+ _LOGGER.error(f"Invalid auxiliary heater action: {action}")
472
+ raise Exception(f"Invalid auxiliary heater action: {action}")
558
473
  self._requests["latest"] = "Climatisation"
559
- response = await self._connection.setAuxiliary(
560
- self.vin, data, (action == "start")
561
- )
474
+ response = await self._connection.setAuxiliary(self.vin, data, (action == "start"))
562
475
  return await self._handle_response(
563
476
  response=response,
564
477
  topic="climatisation",
565
478
  error_msg=f"Failed to {action} climatisation with auxiliary heater.",
566
479
  )
567
- _LOGGER.error("No climatisation support")
568
- raise Exception("No climatisation support.") # pylint: disable=broad-exception-raised
480
+ else:
481
+ _LOGGER.error("No climatisation support.")
482
+ raise Exception("No climatisation support.")
569
483
 
570
484
  async def set_departure_timer(self, timer_id, spin, enable) -> bool:
571
485
  """Turn on/off departure timer."""
572
486
  if self.is_departure_timer_supported(timer_id):
573
- if not isinstance(enable, bool):
574
- _LOGGER.error("Charging departure timers setting is not supported")
575
- raise Exception("Charging departure timers setting is not supported.") # pylint: disable=broad-exception-raised
487
+ if type(enable) is not bool:
488
+ _LOGGER.error("Charging departure timers setting is not supported.")
489
+ raise Exception("Charging departure timers setting is not supported.")
576
490
  data = None
577
491
  response = None
578
492
  if is_valid_path(
579
- self.attrs,
580
- f"{Services.DEPARTURE_PROFILES}.departureProfilesStatus.value.timers",
581
- ) and is_valid_path(
582
- self.attrs,
583
- f"{Services.DEPARTURE_PROFILES}.departureProfilesStatus.value.profiles",
584
- ):
585
- timers = find_path(
586
- self.attrs,
587
- f"{Services.DEPARTURE_PROFILES}.departureProfilesStatus.value.timers",
588
- )
493
+ self.attrs, f"{Services.DEPARTURE_PROFILES}.departureProfilesStatus.value.timers"
494
+ ) and is_valid_path(self.attrs, f"{Services.DEPARTURE_PROFILES}.departureProfilesStatus.value.profiles"):
495
+ timers = find_path(self.attrs, f"{Services.DEPARTURE_PROFILES}.departureProfilesStatus.value.timers")
589
496
  profiles = find_path(
590
- self.attrs,
591
- f"{Services.DEPARTURE_PROFILES}.departureProfilesStatus.value.profiles",
497
+ self.attrs, f"{Services.DEPARTURE_PROFILES}.departureProfilesStatus.value.profiles"
592
498
  )
593
- for index, timer in enumerate(timers):
594
- if timer.get("id", 0) == timer_id:
595
- timers[index]["enabled"] = enable
499
+ for i in range(len(timers)):
500
+ if timers[i].get("id", 0) == timer_id:
501
+ timers[i]["enabled"] = enable
596
502
  data = {"timers": timers, "profiles": profiles}
597
503
  response = await self._connection.setDepartureProfiles(self.vin, data)
598
- if is_valid_path(
599
- self.attrs,
600
- f"{Services.CLIMATISATION_TIMERS}.auxiliaryHeatingTimersStatus.value.timers",
601
- ):
504
+ if is_valid_path(self.attrs, f"{Services.CLIMATISATION_TIMERS}.auxiliaryHeatingTimersStatus.value.timers"):
602
505
  timers = find_path(
603
- self.attrs,
604
- f"{Services.CLIMATISATION_TIMERS}.auxiliaryHeatingTimersStatus.value.timers",
506
+ self.attrs, f"{Services.CLIMATISATION_TIMERS}.auxiliaryHeatingTimersStatus.value.timers"
605
507
  )
606
- for index, timer in enumerate(timers):
607
- if timer.get("id", 0) == timer_id:
608
- timers[index]["enabled"] = enable
508
+ for i in range(len(timers)):
509
+ if timers[i].get("id", 0) == timer_id:
510
+ timers[i]["enabled"] = enable
609
511
  data = {"spin": spin, "timers": timers}
610
- response = await self._connection.setAuxiliaryHeatingTimers(
611
- self.vin, data
612
- )
613
- if is_valid_path(
614
- self.attrs,
615
- f"{Services.DEPARTURE_TIMERS}.departureTimersStatus.value.timers",
616
- ):
617
- timers = find_path(
618
- self.attrs,
619
- f"{Services.DEPARTURE_TIMERS}.departureTimersStatus.value.timers",
620
- )
621
- for index, timer in enumerate(timers):
622
- if timer.get("id", 0) == timer_id:
623
- timers[index]["enabled"] = enable
512
+ response = await self._connection.setAuxiliaryHeatingTimers(self.vin, data)
513
+ if is_valid_path(self.attrs, f"{Services.DEPARTURE_TIMERS}.departureTimersStatus.value.timers"):
514
+ timers = find_path(self.attrs, f"{Services.DEPARTURE_TIMERS}.departureTimersStatus.value.timers")
515
+ for i in range(len(timers)):
516
+ if timers[i].get("id", 0) == timer_id:
517
+ timers[i]["enabled"] = enable
624
518
  data = {"timers": timers}
625
519
  response = await self._connection.setDepartureTimers(self.vin, data)
626
520
  return await self._handle_response(
627
- response=response,
628
- topic="departuretimer",
629
- error_msg="Failed to change departure timers setting.",
521
+ response=response, topic="departuretimer", error_msg="Failed to change departure timers setting."
630
522
  )
631
- _LOGGER.error("Departure timers are not supported")
632
- raise Exception("Departure timers are not supported.") # pylint: disable=broad-exception-raised
523
+ else:
524
+ _LOGGER.error("Departure timers are not supported.")
525
+ raise Exception("Departure timers are not supported.")
633
526
 
634
527
  async def set_ac_departure_timer(self, timer_id, enable) -> bool:
635
528
  """Turn on/off ac departure timer."""
636
529
  if self.is_ac_departure_timer_supported(timer_id):
637
- if not isinstance(enable, bool):
638
- _LOGGER.error(
639
- "Charging climatisation departure timers setting is not supported"
640
- )
641
- # pylint: disable=broad-exception-raised
642
- raise Exception(
643
- "Charging climatisation departure timers setting is not supported."
644
- )
645
- timers = find_path(
646
- self.attrs,
647
- f"{Services.CLIMATISATION_TIMERS}.climatisationTimersStatus.value.timers",
648
- )
649
- for index, timer in enumerate(timers):
650
- if timer.get("id", 0) == timer_id:
651
- timers[index]["enabled"] = enable
530
+ if type(enable) is not bool:
531
+ _LOGGER.error("Charging climatisation departure timers setting is not supported.")
532
+ raise Exception("Charging climatisation departure timers setting is not supported.")
533
+ timers = find_path(self.attrs, f"{Services.CLIMATISATION_TIMERS}.climatisationTimersStatus.value.timers")
534
+ for i in range(len(timers)):
535
+ if timers[i].get("id", 0) == timer_id:
536
+ timers[i]["enabled"] = enable
652
537
  data = {"timers": timers}
653
538
  response = await self._connection.setClimatisationTimers(self.vin, data)
654
539
  return await self._handle_response(
@@ -656,38 +541,32 @@ class Vehicle:
656
541
  topic="departuretimer",
657
542
  error_msg="Failed to change climatisation departure timers setting.",
658
543
  )
659
- _LOGGER.error("Climatisation departure timers are not supported")
660
- raise Exception("Climatisation departure timers are not supported.") # pylint: disable=broad-exception-raised
544
+ else:
545
+ _LOGGER.error("Climatisation departure timers are not supported.")
546
+ raise Exception("Climatisation departure timers are not supported.")
661
547
 
662
548
  # Lock (RLU)
663
549
  async def set_lock(self, action, spin):
664
550
  """Remote lock and unlock actions."""
665
551
  if not self._services.get(Services.ACCESS, {}).get("active", False):
666
- _LOGGER.info("Remote lock/unlock is not supported")
667
- raise Exception("Remote lock/unlock is not supported.") # pylint: disable=broad-exception-raised
552
+ _LOGGER.info("Remote lock/unlock is not supported.")
553
+ raise Exception("Remote lock/unlock is not supported.")
668
554
  if self._in_progress("lock", unknown_offset=-5):
669
555
  return False
670
556
  if action not in ["lock", "unlock"]:
671
- _LOGGER.error("Invalid lock action: %s", action)
672
- raise Exception(f"Invalid lock action: {action}") # pylint: disable=broad-exception-raised
557
+ _LOGGER.error(f"Invalid lock action: {action}")
558
+ raise Exception(f"Invalid lock action: {action}")
673
559
 
674
560
  try:
675
561
  self._requests["latest"] = "Lock"
676
- response = await self._connection.setLock(
677
- self.vin, (action == "lock"), spin
678
- )
562
+ response = await self._connection.setLock(self.vin, (action == "lock"), spin)
679
563
  return await self._handle_response(
680
- response=response,
681
- topic="access",
682
- error_msg=f"Failed to {action} vehicle",
564
+ response=response, topic="access", error_msg=f"Failed to {action} vehicle"
683
565
  )
684
- except Exception as error: # pylint: disable=broad-exception-caught
685
- _LOGGER.warning("Failed to %s vehicle - %s", action, error)
686
- self._requests["lock"] = {
687
- "status": "Exception",
688
- "timestamp": datetime.now(UTC),
689
- }
690
- raise Exception("Lock action failed") # pylint: disable=broad-exception-raised
566
+ except Exception as error:
567
+ _LOGGER.warning(f"Failed to {action} vehicle - {error}")
568
+ self._requests["lock"] = {"status": "Exception", "timestamp": datetime.now(timezone.utc)}
569
+ raise Exception("Lock action failed")
691
570
 
692
571
  # Refresh vehicle data (VSR)
693
572
  async def set_refresh(self):
@@ -701,46 +580,40 @@ class Vehicle:
701
580
  if response.status == 204:
702
581
  self._requests["state"] = "in_progress"
703
582
  self._requests["refresh"] = {
704
- "timestamp": datetime.now(UTC),
583
+ "timestamp": datetime.now(timezone.utc),
705
584
  "status": "in_progress",
706
585
  "id": 0,
707
586
  }
708
587
  status = await self.wait_for_data_refresh()
709
588
  elif response.status == 429:
710
589
  status = "Throttled"
711
- _LOGGER.debug("Server side throttled. Try again later")
590
+ _LOGGER.debug("Server side throttled. Try again later.")
712
591
  else:
713
- _LOGGER.debug(
714
- "Unable to refresh the data. Incorrect response code: %s",
715
- response.status,
716
- )
592
+ _LOGGER.debug(f"Unable to refresh the data. Incorrect response code: {response.status}")
717
593
  self._requests["state"] = status
718
- self._requests["refresh"] = {
719
- "status": status,
720
- "timestamp": datetime.now(UTC),
721
- }
594
+ self._requests["refresh"] = {"status": status, "timestamp": datetime.now(timezone.utc)}
722
595
  return True
723
- _LOGGER.debug("Unable to refresh the data")
724
- except Exception as error: # pylint: disable=broad-exception-caught
725
- _LOGGER.warning("Failed to execute data refresh - %s", error)
726
- self._requests["refresh"] = {
727
- "status": "Exception",
728
- "timestamp": datetime.now(UTC),
729
- }
730
- raise Exception("Data refresh failed") # pylint: disable=broad-exception-raised
596
+ else:
597
+ _LOGGER.debug("Unable to refresh the data.")
598
+ except Exception as error:
599
+ _LOGGER.warning(f"Failed to execute data refresh - {error}")
600
+ self._requests["refresh"] = {"status": "Exception", "timestamp": datetime.now(timezone.utc)}
601
+ raise Exception("Data refresh failed")
731
602
 
732
603
  # Vehicle class helpers #
733
604
  # Vehicle info
734
605
  @property
735
606
  def attrs(self):
736
- """Return all attributes.
607
+ """
608
+ Return all attributes.
737
609
 
738
610
  :return:
739
611
  """
740
612
  return self._states
741
613
 
742
614
  def has_attr(self, attr) -> bool:
743
- """Return true if attribute exists.
615
+ """
616
+ Return true if attribute exists.
744
617
 
745
618
  :param attr:
746
619
  :return:
@@ -748,7 +621,8 @@ class Vehicle:
748
621
  return is_valid_path(self.attrs, attr)
749
622
 
750
623
  def get_attr(self, attr):
751
- """Return a specific attribute.
624
+ """
625
+ Return a specific attribute.
752
626
 
753
627
  :param attr:
754
628
  :return:
@@ -758,44 +632,41 @@ class Vehicle:
758
632
  async def expired(self, service):
759
633
  """Check if access to service has expired."""
760
634
  try:
761
- now = datetime.now(UTC)
635
+ now = datetime.utcnow()
762
636
  if self._services.get(service, {}).get("expiration", False):
763
637
  expiration = self._services.get(service, {}).get("expiration", False)
764
638
  if not expiration:
765
- expiration = datetime.neow(UTC) + timedelta(days=1)
639
+ expiration = datetime.utcnow() + timedelta(days=1)
766
640
  else:
767
- _LOGGER.debug(
768
- "Could not determine end of access for service %s, assuming it is valid",
769
- service,
770
- )
771
- expiration = datetime.now(UTC) + timedelta(days=1)
641
+ _LOGGER.debug(f"Could not determine end of access for service {service}, assuming it is valid")
642
+ expiration = datetime.utcnow() + timedelta(days=1)
772
643
  expiration = expiration.replace(tzinfo=None)
773
644
  if now >= expiration:
774
- _LOGGER.warning("Access to %s has expired!", service)
645
+ _LOGGER.warning(f"Access to {service} has expired!")
775
646
  self._discovered = False
776
647
  return True
777
- except Exception: # pylint: disable=broad-exception-caught
778
- _LOGGER.debug(
779
- "Exception. Could not determine end of access for service %s, assuming it is valid",
780
- service,
781
- )
782
- return False
783
- else:
648
+ else:
649
+ return False
650
+ except Exception:
651
+ _LOGGER.debug(f"Exception. Could not determine end of access for service {service}, assuming it is valid")
784
652
  return False
785
653
 
786
654
  def dashboard(self, **config):
787
- """Return dashboard with specified configuration.
655
+ """
656
+ Return dashboard with specified configuration.
788
657
 
789
658
  :param config:
790
659
  :return:
791
660
  """
792
- from .vw_dashboard import Dashboard # pylint: disable=import-outside-toplevel
661
+ # Classic python notation
662
+ from .vw_dashboard import Dashboard
793
663
 
794
664
  return Dashboard(self, **config)
795
665
 
796
666
  @property
797
667
  def vin(self) -> str:
798
- """Vehicle identification number.
668
+ """
669
+ Vehicle identification number.
799
670
 
800
671
  :return:
801
672
  """
@@ -803,7 +674,8 @@ class Vehicle:
803
674
 
804
675
  @property
805
676
  def unique_id(self) -> str:
806
- """Return unique id for the vehicle (vin).
677
+ """
678
+ Return unique id for the vehicle (vin).
807
679
 
808
680
  :return:
809
681
  """
@@ -813,7 +685,8 @@ class Vehicle:
813
685
  # Car information
814
686
  @property
815
687
  def nickname(self) -> str | None:
816
- """Return nickname of the vehicle.
688
+ """
689
+ Return nickname of the vehicle.
817
690
 
818
691
  :return:
819
692
  """
@@ -821,7 +694,8 @@ class Vehicle:
821
694
 
822
695
  @property
823
696
  def is_nickname_supported(self) -> bool:
824
- """Return true if naming the vehicle is supported.
697
+ """
698
+ Return true if naming the vehicle is supported.
825
699
 
826
700
  :return:
827
701
  """
@@ -829,7 +703,8 @@ class Vehicle:
829
703
 
830
704
  @property
831
705
  def deactivated(self) -> bool | None:
832
- """Return true if service is deactivated.
706
+ """
707
+ Return true if service is deactivated.
833
708
 
834
709
  :return:
835
710
  """
@@ -837,7 +712,8 @@ class Vehicle:
837
712
 
838
713
  @property
839
714
  def is_deactivated_supported(self) -> bool:
840
- """Return true if service deactivation status is supported.
715
+ """
716
+ Return true if service deactivation status is supported.
841
717
 
842
718
  :return:
843
719
  """
@@ -871,7 +747,8 @@ class Vehicle:
871
747
 
872
748
  @property
873
749
  def is_model_image_supported(self) -> bool:
874
- """Return true if vehicle model image is supported.
750
+ """
751
+ Return true if vehicle model image is supported.
875
752
 
876
753
  :return:
877
754
  """
@@ -882,27 +759,17 @@ class Vehicle:
882
759
  @property
883
760
  def parking_light(self) -> bool:
884
761
  """Return true if parking light is on."""
885
- lights = (
886
- self.attrs.get(Services.VEHICLE_LIGHTS)
887
- .get("lightsStatus")
888
- .get("value")
889
- .get("lights")
890
- )
762
+ lights = self.attrs.get(Services.VEHICLE_LIGHTS).get("lightsStatus").get("value").get("lights")
891
763
  lights_on_count = 0
892
764
  for light in lights:
893
765
  if light["status"] == "on":
894
766
  lights_on_count = lights_on_count + 1
895
- return lights_on_count == 2
767
+ return lights_on_count == 1
896
768
 
897
769
  @property
898
770
  def parking_light_last_updated(self) -> datetime:
899
771
  """Return attribute last updated timestamp."""
900
- return (
901
- self.attrs.get(Services.VEHICLE_LIGHTS)
902
- .get("lightsStatus")
903
- .get("value")
904
- .get("carCapturedTimestamp")
905
- )
772
+ return self.attrs.get(Services.VEHICLE_LIGHTS).get("lightsStatus").get("value").get("carCapturedTimestamp")
906
773
 
907
774
  @property
908
775
  def is_parking_light_supported(self) -> bool:
@@ -918,35 +785,33 @@ class Vehicle:
918
785
  # this field is only a dirty hack, because there is no overarching information for the car anymore,
919
786
  # only information per service, so we just use the one for fuelStatus.rangeStatus when car is ideling
920
787
  # and charing.batteryStatus when electic car is charging
921
- # Return attribute last updated timestamp.
788
+ """Return attribute last updated timestamp."""
922
789
  if self.is_battery_level_supported and self.charging:
923
790
  return self.battery_level_last_updated
924
- if self.is_distance_supported:
925
- if isinstance(self.distance_last_updated, str):
791
+ elif self.is_distance_supported:
792
+ if type(self.distance_last_updated) is str:
926
793
  return (
927
- datetime.strptime(
928
- self.distance_last_updated, "%Y-%m-%dT%H:%M:%S.%fZ"
929
- )
794
+ datetime.strptime(self.distance_last_updated, "%Y-%m-%dT%H:%M:%S.%fZ")
930
795
  .replace(microsecond=0)
931
- .replace(tzinfo=UTC)
796
+ .replace(tzinfo=timezone.utc)
932
797
  )
933
- return self.distance_last_updated
798
+ else:
799
+ return self.distance_last_updated
934
800
 
935
801
  @property
936
802
  def last_connected_last_updated(self) -> datetime:
937
803
  """Return attribute last updated timestamp."""
938
804
  if self.is_battery_level_supported and self.charging:
939
805
  return self.battery_level_last_updated
940
- if self.is_distance_supported:
941
- if isinstance(self.distance_last_updated, str):
806
+ elif self.is_distance_supported:
807
+ if type(self.distance_last_updated) is str:
942
808
  return (
943
- datetime.strptime(
944
- self.distance_last_updated, "%Y-%m-%dT%H:%M:%S.%fZ"
945
- )
809
+ datetime.strptime(self.distance_last_updated, "%Y-%m-%dT%H:%M:%S.%fZ")
946
810
  .replace(microsecond=0)
947
- .replace(tzinfo=UTC)
811
+ .replace(tzinfo=timezone.utc)
948
812
  )
949
- return self.distance_last_updated
813
+ else:
814
+ return self.distance_last_updated
950
815
 
951
816
  @property
952
817
  def is_last_connected_supported(self) -> bool:
@@ -957,495 +822,326 @@ class Vehicle:
957
822
  @property
958
823
  def distance(self) -> int | None:
959
824
  """Return vehicle odometer."""
960
- return find_path(
961
- self.attrs, f"{Services.MEASUREMENTS}.odometerStatus.value.odometer"
962
- )
825
+ return find_path(self.attrs, f"{Services.MEASUREMENTS}.odometerStatus.value.odometer")
963
826
 
964
827
  @property
965
828
  def distance_last_updated(self) -> datetime:
966
829
  """Return last updated timestamp."""
967
- return find_path(
968
- self.attrs,
969
- f"{Services.MEASUREMENTS}.odometerStatus.value.carCapturedTimestamp",
970
- )
830
+ return find_path(self.attrs, f"{Services.MEASUREMENTS}.odometerStatus.value.carCapturedTimestamp")
971
831
 
972
832
  @property
973
833
  def is_distance_supported(self) -> bool:
974
834
  """Return true if odometer is supported."""
975
- return is_valid_path(
976
- self.attrs, f"{Services.MEASUREMENTS}.odometerStatus.value.odometer"
977
- )
835
+ return is_valid_path(self.attrs, f"{Services.MEASUREMENTS}.odometerStatus.value.odometer")
978
836
 
979
837
  @property
980
838
  def service_inspection(self):
981
839
  """Return time left for service inspection."""
982
- return find_path(
983
- self.attrs,
984
- f"{Services.VEHICLE_HEALTH_INSPECTION}.maintenanceStatus.value.inspectionDue_days",
985
- )
840
+ return find_path(self.attrs, f"{Services.VEHICLE_HEALTH_INSPECTION}.maintenanceStatus.value.inspectionDue_days")
986
841
 
987
842
  @property
988
843
  def service_inspection_last_updated(self) -> datetime:
989
844
  """Return attribute last updated timestamp."""
990
845
  return find_path(
991
- self.attrs,
992
- f"{Services.VEHICLE_HEALTH_INSPECTION}.maintenanceStatus.value.carCapturedTimestamp",
846
+ self.attrs, f"{Services.VEHICLE_HEALTH_INSPECTION}.maintenanceStatus.value.carCapturedTimestamp"
993
847
  )
994
848
 
995
849
  @property
996
850
  def is_service_inspection_supported(self) -> bool:
997
- """Return true if days to service inspection is supported.
851
+ """
852
+ Return true if days to service inspection is supported.
998
853
 
999
854
  :return:
1000
855
  """
1001
856
  return is_valid_path(
1002
- self.attrs,
1003
- f"{Services.VEHICLE_HEALTH_INSPECTION}.maintenanceStatus.value.inspectionDue_days",
857
+ self.attrs, f"{Services.VEHICLE_HEALTH_INSPECTION}.maintenanceStatus.value.inspectionDue_days"
1004
858
  )
1005
859
 
1006
860
  @property
1007
861
  def service_inspection_distance(self):
1008
862
  """Return distance left for service inspection."""
1009
- return find_path(
1010
- self.attrs,
1011
- f"{Services.VEHICLE_HEALTH_INSPECTION}.maintenanceStatus.value.inspectionDue_km",
1012
- )
863
+ return find_path(self.attrs, f"{Services.VEHICLE_HEALTH_INSPECTION}.maintenanceStatus.value.inspectionDue_km")
1013
864
 
1014
865
  @property
1015
866
  def service_inspection_distance_last_updated(self) -> datetime:
1016
867
  """Return attribute last updated timestamp."""
1017
868
  return find_path(
1018
- self.attrs,
1019
- f"{Services.VEHICLE_HEALTH_INSPECTION}.maintenanceStatus.value.carCapturedTimestamp",
869
+ self.attrs, f"{Services.VEHICLE_HEALTH_INSPECTION}.maintenanceStatus.value.carCapturedTimestamp"
1020
870
  )
1021
871
 
1022
872
  @property
1023
873
  def is_service_inspection_distance_supported(self) -> bool:
1024
- """Return true if distance to service inspection is supported.
874
+ """
875
+ Return true if distance to service inspection is supported.
1025
876
 
1026
877
  :return:
1027
878
  """
1028
879
  return is_valid_path(
1029
- self.attrs,
1030
- f"{Services.VEHICLE_HEALTH_INSPECTION}.maintenanceStatus.value.inspectionDue_km",
880
+ self.attrs, f"{Services.VEHICLE_HEALTH_INSPECTION}.maintenanceStatus.value.inspectionDue_km"
1031
881
  )
1032
882
 
1033
883
  @property
1034
884
  def oil_inspection(self):
1035
885
  """Return time left for oil inspection."""
1036
- return find_path(
1037
- self.attrs,
1038
- f"{Services.VEHICLE_HEALTH_INSPECTION}.maintenanceStatus.value.oilServiceDue_days",
1039
- )
886
+ return find_path(self.attrs, f"{Services.VEHICLE_HEALTH_INSPECTION}.maintenanceStatus.value.oilServiceDue_days")
1040
887
 
1041
888
  @property
1042
889
  def oil_inspection_last_updated(self) -> datetime:
1043
890
  """Return attribute last updated timestamp."""
1044
891
  return find_path(
1045
- self.attrs,
1046
- f"{Services.VEHICLE_HEALTH_INSPECTION}.maintenanceStatus.value.carCapturedTimestamp",
892
+ self.attrs, f"{Services.VEHICLE_HEALTH_INSPECTION}.maintenanceStatus.value.carCapturedTimestamp"
1047
893
  )
1048
894
 
1049
895
  @property
1050
896
  def is_oil_inspection_supported(self) -> bool:
1051
- """Return true if days to oil inspection is supported.
897
+ """
898
+ Return true if days to oil inspection is supported.
1052
899
 
1053
900
  :return:
1054
901
  """
1055
902
  if not self.has_combustion_engine:
1056
903
  return False
1057
904
  return is_valid_path(
1058
- self.attrs,
1059
- f"{Services.VEHICLE_HEALTH_INSPECTION}.maintenanceStatus.value.oilServiceDue_days",
905
+ self.attrs, f"{Services.VEHICLE_HEALTH_INSPECTION}.maintenanceStatus.value.oilServiceDue_days"
1060
906
  )
1061
907
 
1062
908
  @property
1063
909
  def oil_inspection_distance(self):
1064
910
  """Return distance left for oil inspection."""
1065
- return find_path(
1066
- self.attrs,
1067
- f"{Services.VEHICLE_HEALTH_INSPECTION}.maintenanceStatus.value.oilServiceDue_km",
1068
- )
911
+ return find_path(self.attrs, f"{Services.VEHICLE_HEALTH_INSPECTION}.maintenanceStatus.value.oilServiceDue_km")
1069
912
 
1070
913
  @property
1071
914
  def oil_inspection_distance_last_updated(self) -> datetime:
1072
915
  """Return attribute last updated timestamp."""
1073
916
  return find_path(
1074
- self.attrs,
1075
- f"{Services.VEHICLE_HEALTH_INSPECTION}.maintenanceStatus.value.carCapturedTimestamp",
917
+ self.attrs, f"{Services.VEHICLE_HEALTH_INSPECTION}.maintenanceStatus.value.carCapturedTimestamp"
1076
918
  )
1077
919
 
1078
920
  @property
1079
921
  def is_oil_inspection_distance_supported(self) -> bool:
1080
- """Return true if oil inspection distance is supported.
922
+ """
923
+ Return true if oil inspection distance is supported.
1081
924
 
1082
925
  :return:
1083
926
  """
1084
927
  if not self.has_combustion_engine:
1085
928
  return False
1086
929
  return is_valid_path(
1087
- self.attrs,
1088
- f"{Services.VEHICLE_HEALTH_INSPECTION}.maintenanceStatus.value.oilServiceDue_km",
930
+ self.attrs, f"{Services.VEHICLE_HEALTH_INSPECTION}.maintenanceStatus.value.oilServiceDue_km"
1089
931
  )
1090
932
 
1091
933
  @property
1092
934
  def adblue_level(self) -> int:
1093
935
  """Return adblue level."""
1094
- return find_path(
1095
- self.attrs, f"{Services.MEASUREMENTS}.rangeStatus.value.adBlueRange"
1096
- )
936
+ return find_path(self.attrs, f"{Services.MEASUREMENTS}.rangeStatus.value.adBlueRange")
1097
937
 
1098
938
  @property
1099
939
  def adblue_level_last_updated(self) -> datetime:
1100
940
  """Return attribute last updated timestamp."""
1101
- return find_path(
1102
- self.attrs,
1103
- f"{Services.MEASUREMENTS}.rangeStatus.value.carCapturedTimestamp",
1104
- )
941
+ return find_path(self.attrs, f"{Services.MEASUREMENTS}.rangeStatus.value.carCapturedTimestamp")
1105
942
 
1106
943
  @property
1107
944
  def is_adblue_level_supported(self) -> bool:
1108
945
  """Return true if adblue level is supported."""
1109
- return is_valid_path(
1110
- self.attrs, f"{Services.MEASUREMENTS}.rangeStatus.value.adBlueRange"
1111
- )
946
+ return is_valid_path(self.attrs, f"{Services.MEASUREMENTS}.rangeStatus.value.adBlueRange")
1112
947
 
1113
948
  # Charger related states for EV and PHEV
1114
949
  @property
1115
950
  def charging(self) -> bool:
1116
951
  """Return charging state."""
1117
- cstate = find_path(
1118
- self.attrs, f"{Services.CHARGING}.chargingStatus.value.chargingState"
1119
- )
952
+ cstate = find_path(self.attrs, f"{Services.CHARGING}.chargingStatus.value.chargingState")
1120
953
  return cstate == "charging"
1121
954
 
1122
955
  @property
1123
956
  def charging_last_updated(self) -> datetime:
1124
957
  """Return attribute last updated timestamp."""
1125
- return find_path(
1126
- self.attrs, f"{Services.CHARGING}.chargingStatus.value.carCapturedTimestamp"
1127
- )
958
+ return find_path(self.attrs, f"{Services.CHARGING}.chargingStatus.value.carCapturedTimestamp")
1128
959
 
1129
960
  @property
1130
961
  def is_charging_supported(self) -> bool:
1131
962
  """Return true if charging is supported."""
1132
- return is_valid_path(
1133
- self.attrs, f"{Services.CHARGING}.chargingStatus.value.chargingState"
1134
- )
963
+ return is_valid_path(self.attrs, f"{Services.CHARGING}.chargingStatus.value.chargingState")
1135
964
 
1136
965
  @property
1137
966
  def charging_power(self) -> int:
1138
967
  """Return charging power."""
1139
- return find_path(
1140
- self.attrs, f"{Services.CHARGING}.chargingStatus.value.chargePower_kW"
1141
- )
968
+ return find_path(self.attrs, f"{Services.CHARGING}.chargingStatus.value.chargePower_kW")
1142
969
 
1143
970
  @property
1144
971
  def charging_power_last_updated(self) -> datetime:
1145
972
  """Return attribute last updated timestamp."""
1146
- return find_path(
1147
- self.attrs, f"{Services.CHARGING}.chargingStatus.value.carCapturedTimestamp"
1148
- )
973
+ return find_path(self.attrs, f"{Services.CHARGING}.chargingStatus.value.carCapturedTimestamp")
1149
974
 
1150
975
  @property
1151
976
  def is_charging_power_supported(self) -> bool:
1152
977
  """Return true if charging power is supported."""
1153
- return is_valid_path(
1154
- self.attrs, f"{Services.CHARGING}.chargingStatus.value.chargePower_kW"
1155
- )
978
+ return is_valid_path(self.attrs, f"{Services.CHARGING}.chargingStatus.value.chargePower_kW")
1156
979
 
1157
980
  @property
1158
981
  def charging_rate(self) -> int:
1159
982
  """Return charging rate."""
1160
- return find_path(
1161
- self.attrs, f"{Services.CHARGING}.chargingStatus.value.chargeRate_kmph"
1162
- )
983
+ return find_path(self.attrs, f"{Services.CHARGING}.chargingStatus.value.chargeRate_kmph")
1163
984
 
1164
985
  @property
1165
986
  def charging_rate_last_updated(self) -> datetime:
1166
987
  """Return attribute last updated timestamp."""
1167
- return find_path(
1168
- self.attrs, f"{Services.CHARGING}.chargingStatus.value.carCapturedTimestamp"
1169
- )
988
+ return find_path(self.attrs, f"{Services.CHARGING}.chargingStatus.value.carCapturedTimestamp")
1170
989
 
1171
990
  @property
1172
991
  def is_charging_rate_supported(self) -> bool:
1173
992
  """Return true if charging rate is supported."""
1174
- return is_valid_path(
1175
- self.attrs, f"{Services.CHARGING}.chargingStatus.value.chargeRate_kmph"
1176
- )
993
+ return is_valid_path(self.attrs, f"{Services.CHARGING}.chargingStatus.value.chargeRate_kmph")
1177
994
 
1178
995
  @property
1179
996
  def charger_type(self) -> str:
1180
997
  """Return charger type."""
1181
- charger_type = find_path(
1182
- self.attrs, f"{Services.CHARGING}.chargingStatus.value.chargeType"
1183
- )
998
+ charger_type = find_path(self.attrs, f"{Services.CHARGING}.chargingStatus.value.chargeType")
1184
999
  if charger_type == "ac":
1185
1000
  return "AC"
1186
- if charger_type == "dc":
1001
+ elif charger_type == "dc":
1187
1002
  return "DC"
1188
1003
  return "Unknown"
1189
1004
 
1190
1005
  @property
1191
1006
  def charger_type_last_updated(self) -> datetime:
1192
1007
  """Return attribute last updated timestamp."""
1193
- return find_path(
1194
- self.attrs, f"{Services.CHARGING}.chargingStatus.value.carCapturedTimestamp"
1195
- )
1008
+ return find_path(self.attrs, f"{Services.CHARGING}.chargingStatus.value.carCapturedTimestamp")
1196
1009
 
1197
1010
  @property
1198
1011
  def is_charger_type_supported(self) -> bool:
1199
1012
  """Return true if charger type is supported."""
1200
- return is_valid_path(
1201
- self.attrs, f"{Services.CHARGING}.chargingStatus.value.chargeType"
1202
- )
1013
+ return is_valid_path(self.attrs, f"{Services.CHARGING}.chargingStatus.value.chargeType")
1203
1014
 
1204
1015
  @property
1205
1016
  def battery_level(self) -> int:
1206
1017
  """Return battery level."""
1207
- return find_path(
1208
- self.attrs, f"{Services.CHARGING}.batteryStatus.value.currentSOC_pct"
1209
- )
1018
+ return find_path(self.attrs, f"{Services.CHARGING}.batteryStatus.value.currentSOC_pct")
1210
1019
 
1211
1020
  @property
1212
1021
  def battery_level_last_updated(self) -> datetime:
1213
1022
  """Return attribute last updated timestamp."""
1214
- return find_path(
1215
- self.attrs, f"{Services.CHARGING}.batteryStatus.value.carCapturedTimestamp"
1216
- )
1023
+ return find_path(self.attrs, f"{Services.CHARGING}.batteryStatus.value.carCapturedTimestamp")
1217
1024
 
1218
1025
  @property
1219
1026
  def is_battery_level_supported(self) -> bool:
1220
1027
  """Return true if battery level is supported."""
1221
- return is_valid_path(
1222
- self.attrs, f"{Services.CHARGING}.batteryStatus.value.currentSOC_pct"
1223
- )
1028
+ return is_valid_path(self.attrs, f"{Services.CHARGING}.batteryStatus.value.currentSOC_pct")
1224
1029
 
1225
1030
  @property
1226
1031
  def battery_target_charge_level(self) -> int:
1227
1032
  """Return target charge level."""
1228
- return find_path(
1229
- self.attrs, f"{Services.CHARGING}.chargingSettings.value.targetSOC_pct"
1230
- )
1033
+ return find_path(self.attrs, f"{Services.CHARGING}.chargingSettings.value.targetSOC_pct")
1231
1034
 
1232
1035
  @property
1233
1036
  def battery_target_charge_level_last_updated(self) -> datetime:
1234
1037
  """Return attribute last updated timestamp."""
1235
- return find_path(
1236
- self.attrs,
1237
- f"{Services.CHARGING}.chargingSettings.value.carCapturedTimestamp",
1238
- )
1038
+ return find_path(self.attrs, f"{Services.CHARGING}.chargingSettings.value.carCapturedTimestamp")
1239
1039
 
1240
1040
  @property
1241
1041
  def is_battery_target_charge_level_supported(self) -> bool:
1242
1042
  """Return true if target charge level is supported."""
1243
- return is_valid_path(
1244
- self.attrs, f"{Services.CHARGING}.chargingSettings.value.targetSOC_pct"
1245
- )
1246
-
1247
- @property
1248
- def hv_battery_min_temperature(self) -> int:
1249
- """Return HV battery min temperature."""
1250
- return (
1251
- float(
1252
- find_path(
1253
- self.attrs,
1254
- f"{Services.MEASUREMENTS}.temperatureBatteryStatus.value.temperatureHvBatteryMin_K",
1255
- )
1256
- )
1257
- - 273.15
1258
- )
1259
-
1260
- @property
1261
- def hv_battery_min_temperature_last_updated(self) -> datetime:
1262
- """Return attribute last updated timestamp."""
1263
- return find_path(
1264
- self.attrs,
1265
- f"{Services.MEASUREMENTS}.temperatureBatteryStatus.value.carCapturedTimestamp",
1266
- )
1267
-
1268
- @property
1269
- def is_hv_battery_min_temperature_supported(self) -> bool:
1270
- """Return true if HV battery min temperature is supported."""
1271
- return is_valid_path(
1272
- self.attrs,
1273
- f"{Services.MEASUREMENTS}.temperatureBatteryStatus.value.temperatureHvBatteryMin_K",
1274
- )
1275
-
1276
- @property
1277
- def hv_battery_max_temperature(self) -> int:
1278
- """Return HV battery max temperature."""
1279
- return (
1280
- float(
1281
- find_path(
1282
- self.attrs,
1283
- f"{Services.MEASUREMENTS}.temperatureBatteryStatus.value.temperatureHvBatteryMax_K",
1284
- )
1285
- )
1286
- - 273.15
1287
- )
1288
-
1289
- @property
1290
- def hv_battery_max_temperature_last_updated(self) -> datetime:
1291
- """Return attribute last updated timestamp."""
1292
- return find_path(
1293
- self.attrs,
1294
- f"{Services.MEASUREMENTS}.temperatureBatteryStatus.value.carCapturedTimestamp",
1295
- )
1296
-
1297
- @property
1298
- def is_hv_battery_max_temperature_supported(self) -> bool:
1299
- """Return true if HV battery max temperature is supported."""
1300
- return is_valid_path(
1301
- self.attrs,
1302
- f"{Services.MEASUREMENTS}.temperatureBatteryStatus.value.temperatureHvBatteryMax_K",
1303
- )
1043
+ return is_valid_path(self.attrs, f"{Services.CHARGING}.chargingSettings.value.targetSOC_pct")
1304
1044
 
1305
1045
  @property
1306
1046
  def charge_max_ac_setting(self) -> str | int:
1307
1047
  """Return charger max ampere setting."""
1308
- return find_path(
1309
- self.attrs, f"{Services.CHARGING}.chargingSettings.value.maxChargeCurrentAC"
1310
- )
1048
+ value = find_path(self.attrs, f"{Services.CHARGING}.chargingSettings.value.maxChargeCurrentAC")
1049
+ return value
1311
1050
 
1312
1051
  @property
1313
1052
  def charge_max_ac_setting_last_updated(self) -> datetime:
1314
1053
  """Return charger max ampere last updated."""
1315
- return find_path(
1316
- self.attrs,
1317
- f"{Services.CHARGING}.chargingSettings.value.carCapturedTimestamp",
1318
- )
1054
+ return find_path(self.attrs, f"{Services.CHARGING}.chargingSettings.value.carCapturedTimestamp")
1319
1055
 
1320
1056
  @property
1321
1057
  def is_charge_max_ac_setting_supported(self) -> bool:
1322
1058
  """Return true if Charger Max Ampere is supported."""
1323
- if is_valid_path(
1324
- self.attrs, f"{Services.CHARGING}.chargingSettings.value.maxChargeCurrentAC"
1325
- ):
1326
- value = find_path(
1327
- self.attrs,
1328
- f"{Services.CHARGING}.chargingSettings.value.maxChargeCurrentAC",
1329
- )
1059
+ if is_valid_path(self.attrs, f"{Services.CHARGING}.chargingSettings.value.maxChargeCurrentAC"):
1060
+ value = find_path(self.attrs, f"{Services.CHARGING}.chargingSettings.value.maxChargeCurrentAC")
1330
1061
  return value in ["reduced", "maximum", "invalid"]
1331
1062
  return False
1332
1063
 
1333
1064
  @property
1334
1065
  def charge_max_ac_ampere(self) -> str | int:
1335
1066
  """Return charger max ampere setting."""
1336
- return find_path(
1337
- self.attrs,
1338
- f"{Services.CHARGING}.chargingSettings.value.maxChargeCurrentAC_A",
1339
- )
1067
+ return find_path(self.attrs, f"{Services.CHARGING}.chargingSettings.value.maxChargeCurrentAC_A")
1340
1068
 
1341
1069
  @property
1342
1070
  def charge_max_ac_ampere_last_updated(self) -> datetime:
1343
1071
  """Return charger max ampere last updated."""
1344
- return find_path(
1345
- self.attrs,
1346
- f"{Services.CHARGING}.chargingSettings.value.carCapturedTimestamp",
1347
- )
1072
+ return find_path(self.attrs, f"{Services.CHARGING}.chargingSettings.value.carCapturedTimestamp")
1348
1073
 
1349
1074
  @property
1350
1075
  def is_charge_max_ac_ampere_supported(self) -> bool:
1351
1076
  """Return true if Charger Max Ampere is supported."""
1352
- return is_valid_path(
1353
- self.attrs,
1354
- f"{Services.CHARGING}.chargingSettings.value.maxChargeCurrentAC_A",
1355
- )
1077
+ return is_valid_path(self.attrs, f"{Services.CHARGING}.chargingSettings.value.maxChargeCurrentAC_A")
1356
1078
 
1357
1079
  @property
1358
1080
  def charging_cable_locked(self) -> bool:
1359
1081
  """Return plug locked state."""
1360
- response = find_path(
1361
- self.attrs, f"{Services.CHARGING}.plugStatus.value.plugLockState"
1362
- )
1082
+ response = find_path(self.attrs, f"{Services.CHARGING}.plugStatus.value.plugLockState")
1363
1083
  return response == "locked"
1364
1084
 
1365
1085
  @property
1366
1086
  def charging_cable_locked_last_updated(self) -> datetime:
1367
1087
  """Return plug locked state."""
1368
- return find_path(
1369
- self.attrs, f"{Services.CHARGING}.plugStatus.value.carCapturedTimestamp"
1370
- )
1088
+ return find_path(self.attrs, f"{Services.CHARGING}.plugStatus.value.carCapturedTimestamp")
1371
1089
 
1372
1090
  @property
1373
1091
  def is_charging_cable_locked_supported(self) -> bool:
1374
1092
  """Return true if plug locked state is supported."""
1375
- return is_valid_path(
1376
- self.attrs, f"{Services.CHARGING}.plugStatus.value.plugLockState"
1377
- )
1093
+ return is_valid_path(self.attrs, f"{Services.CHARGING}.plugStatus.value.plugLockState")
1378
1094
 
1379
1095
  @property
1380
1096
  def charging_cable_connected(self) -> bool:
1381
1097
  """Return plug connected state."""
1382
- response = find_path(
1383
- self.attrs, f"{Services.CHARGING}.plugStatus.value.plugConnectionState"
1384
- )
1098
+ response = find_path(self.attrs, f"{Services.CHARGING}.plugStatus.value.plugConnectionState")
1385
1099
  return response == "connected"
1386
1100
 
1387
1101
  @property
1388
1102
  def charging_cable_connected_last_updated(self) -> datetime:
1389
1103
  """Return plug connected state last updated."""
1390
- return find_path(
1391
- self.attrs, f"{Services.CHARGING}.plugStatus.value.carCapturedTimestamp"
1392
- )
1104
+ return find_path(self.attrs, f"{Services.CHARGING}.plugStatus.value.carCapturedTimestamp")
1393
1105
 
1394
1106
  @property
1395
1107
  def is_charging_cable_connected_supported(self) -> bool:
1396
1108
  """Return true if supported."""
1397
- return is_valid_path(
1398
- self.attrs, f"{Services.CHARGING}.plugStatus.value.plugConnectionState"
1399
- )
1109
+ return is_valid_path(self.attrs, f"{Services.CHARGING}.plugStatus.value.plugConnectionState")
1400
1110
 
1401
1111
  @property
1402
1112
  def charging_time_left(self) -> int:
1403
1113
  """Return minutes to charging complete."""
1404
- if is_valid_path(
1405
- self.attrs,
1406
- f"{Services.CHARGING}.chargingStatus.value.remainingChargingTimeToComplete_min",
1407
- ):
1114
+ if is_valid_path(self.attrs, f"{Services.CHARGING}.chargingStatus.value.remainingChargingTimeToComplete_min"):
1408
1115
  return find_path(
1409
- self.attrs,
1410
- f"{Services.CHARGING}.chargingStatus.value.remainingChargingTimeToComplete_min",
1116
+ self.attrs, f"{Services.CHARGING}.chargingStatus.value.remainingChargingTimeToComplete_min"
1411
1117
  )
1412
1118
  return None
1413
1119
 
1414
1120
  @property
1415
1121
  def charging_time_left_last_updated(self) -> datetime:
1416
1122
  """Return minutes to charging complete last updated."""
1417
- return find_path(
1418
- self.attrs, f"{Services.CHARGING}.chargingStatus.value.carCapturedTimestamp"
1419
- )
1123
+ return find_path(self.attrs, f"{Services.CHARGING}.chargingStatus.value.carCapturedTimestamp")
1420
1124
 
1421
1125
  @property
1422
1126
  def is_charging_time_left_supported(self) -> bool:
1423
1127
  """Return true if charging is supported."""
1424
- return is_valid_path(
1425
- self.attrs, f"{Services.CHARGING}.chargingStatus.value.chargingState"
1426
- )
1128
+ return is_valid_path(self.attrs, f"{Services.CHARGING}.chargingStatus.value.chargingState")
1427
1129
 
1428
1130
  @property
1429
1131
  def external_power(self) -> bool:
1430
1132
  """Return true if external power is connected."""
1431
- check = find_path(
1432
- self.attrs, f"{Services.CHARGING}.plugStatus.value.externalPower"
1433
- )
1133
+ check = find_path(self.attrs, f"{Services.CHARGING}.plugStatus.value.externalPower")
1434
1134
  return check in ["stationConnected", "available", "ready"]
1435
1135
 
1436
1136
  @property
1437
1137
  def external_power_last_updated(self) -> datetime:
1438
1138
  """Return external power last updated."""
1439
- return find_path(
1440
- self.attrs, f"{Services.CHARGING}.plugStatus.value.carCapturedTimestamp"
1441
- )
1139
+ return find_path(self.attrs, f"{Services.CHARGING}.plugStatus.value.carCapturedTimestamp")
1442
1140
 
1443
1141
  @property
1444
1142
  def is_external_power_supported(self) -> bool:
1445
1143
  """External power supported."""
1446
- return is_valid_path(
1447
- self.attrs, f"{Services.CHARGING}.plugStatus.value.externalPower"
1448
- )
1144
+ return is_valid_path(self.attrs, f"{Services.CHARGING}.plugStatus.value.externalPower")
1449
1145
 
1450
1146
  @property
1451
1147
  def reduced_ac_charging(self) -> bool:
@@ -1465,89 +1161,64 @@ class Vehicle:
1465
1161
  @property
1466
1162
  def auto_release_ac_connector_state(self) -> str:
1467
1163
  """Return auto release ac connector state value."""
1468
- return find_path(
1469
- self.attrs,
1470
- f"{Services.CHARGING}.chargingSettings.value.autoUnlockPlugWhenChargedAC",
1471
- )
1164
+ return find_path(self.attrs, f"{Services.CHARGING}.chargingSettings.value.autoUnlockPlugWhenChargedAC")
1472
1165
 
1473
1166
  @property
1474
1167
  def auto_release_ac_connector(self) -> bool:
1475
1168
  """Return auto release ac connector state."""
1476
1169
  return (
1477
- find_path(
1478
- self.attrs,
1479
- f"{Services.CHARGING}.chargingSettings.value.autoUnlockPlugWhenChargedAC",
1480
- )
1170
+ find_path(self.attrs, f"{Services.CHARGING}.chargingSettings.value.autoUnlockPlugWhenChargedAC")
1481
1171
  == "permanent"
1482
1172
  )
1483
1173
 
1484
1174
  @property
1485
1175
  def auto_release_ac_connector_last_updated(self) -> datetime:
1486
1176
  """Return attribute last updated timestamp."""
1487
- return find_path(
1488
- self.attrs,
1489
- f"{Services.CHARGING}.chargingSettings.value.carCapturedTimestamp",
1490
- )
1177
+ return find_path(self.attrs, f"{Services.CHARGING}.chargingSettings.value.carCapturedTimestamp")
1491
1178
 
1492
1179
  @property
1493
1180
  def is_auto_release_ac_connector_supported(self) -> bool:
1494
1181
  """Return true if auto release ac connector is supported."""
1495
- return is_valid_path(
1496
- self.attrs,
1497
- f"{Services.CHARGING}.chargingSettings.value.autoUnlockPlugWhenChargedAC",
1498
- )
1182
+ return is_valid_path(self.attrs, f"{Services.CHARGING}.chargingSettings.value.autoUnlockPlugWhenChargedAC")
1499
1183
 
1500
1184
  @property
1501
1185
  def battery_care_mode(self) -> bool:
1502
1186
  """Return battery care mode state."""
1503
1187
  return (
1504
- find_path(
1505
- self.attrs,
1506
- f"{Services.BATTERY_CHARGING_CARE}.chargingCareSettings.value.batteryCareMode",
1507
- )
1188
+ find_path(self.attrs, f"{Services.BATTERY_CHARGING_CARE}.chargingCareSettings.value.batteryCareMode")
1508
1189
  == "activated"
1509
1190
  )
1510
1191
 
1511
1192
  @property
1512
1193
  def battery_care_mode_last_updated(self) -> datetime:
1513
1194
  """Return attribute last updated timestamp."""
1514
- return datetime.now(UTC)
1195
+ return datetime.now(timezone.utc)
1515
1196
 
1516
1197
  @property
1517
1198
  def is_battery_care_mode_supported(self) -> bool:
1518
1199
  """Return true if battery care mode is supported."""
1519
- return is_valid_path(
1520
- self.attrs,
1521
- f"{Services.BATTERY_CHARGING_CARE}.chargingCareSettings.value.batteryCareMode",
1522
- )
1200
+ return is_valid_path(self.attrs, f"{Services.BATTERY_CHARGING_CARE}.chargingCareSettings.value.batteryCareMode")
1523
1201
 
1524
1202
  @property
1525
1203
  def optimised_battery_use(self) -> bool:
1526
1204
  """Return optimised battery use state."""
1527
1205
  return (
1528
- find_path(
1529
- self.attrs,
1530
- f"{Services.BATTERY_SUPPORT}.batterySupportStatus.value.batterySupport",
1531
- )
1532
- == "enabled"
1206
+ find_path(self.attrs, f"{Services.BATTERY_SUPPORT}.batterySupportStatus.value.batterySupport") == "enabled"
1533
1207
  )
1534
1208
 
1535
1209
  @property
1536
1210
  def optimised_battery_use_last_updated(self) -> datetime:
1537
1211
  """Return attribute last updated timestamp."""
1538
- return datetime.now(UTC)
1212
+ return datetime.now(timezone.utc)
1539
1213
 
1540
1214
  @property
1541
1215
  def is_optimised_battery_use_supported(self) -> bool:
1542
1216
  """Return true if optimised battery use is supported."""
1543
- return is_valid_path(
1544
- self.attrs,
1545
- f"{Services.BATTERY_SUPPORT}.batterySupportStatus.value.batterySupport",
1546
- )
1217
+ return is_valid_path(self.attrs, f"{Services.BATTERY_SUPPORT}.batterySupportStatus.value.batterySupport")
1547
1218
 
1548
1219
  @property
1549
1220
  def energy_flow(self):
1550
- # TODO untouched # pylint: disable=fixme
1221
+ # TODO untouched
1551
1222
  """Return true if energy is flowing through charging port."""
1552
1223
  check = (
1553
1224
  self.attrs.get("charger", {})
@@ -1560,7 +1231,7 @@ class Vehicle:
1560
1231
 
1561
1232
  @property
1562
1233
  def energy_flow_last_updated(self) -> datetime:
1563
- # TODO untouched # pylint: disable=fixme
1234
+ # TODO untouched
1564
1235
  """Return energy flow last updated."""
1565
1236
  return (
1566
1237
  self.attrs.get("charger", {})
@@ -1572,14 +1243,9 @@ class Vehicle:
1572
1243
 
1573
1244
  @property
1574
1245
  def is_energy_flow_supported(self) -> bool:
1575
- # TODO untouched # pylint: disable=fixme
1246
+ # TODO untouched
1576
1247
  """Energy flow supported."""
1577
- return (
1578
- self.attrs.get("charger", {})
1579
- .get("status", {})
1580
- .get("chargingStatusData", {})
1581
- .get("energyFlow", False)
1582
- )
1248
+ return self.attrs.get("charger", {}).get("status", {}).get("chargingStatusData", {}).get("energyFlow", False)
1583
1249
 
1584
1250
  # Vehicle location states
1585
1251
  @property
@@ -1592,11 +1258,9 @@ class Vehicle:
1592
1258
  else:
1593
1259
  lat = float(find_path(self.attrs, "parkingposition.lat"))
1594
1260
  lng = float(find_path(self.attrs, "parkingposition.lon"))
1595
- parking_time = find_path(
1596
- self.attrs, "parkingposition.carCapturedTimestamp"
1597
- )
1261
+ parking_time = find_path(self.attrs, "parkingposition.carCapturedTimestamp")
1598
1262
  output = {"lat": lat, "lng": lng, "timestamp": parking_time}
1599
- except Exception: # pylint: disable=broad-exception-caught
1263
+ except Exception:
1600
1264
  output = {
1601
1265
  "lat": "?",
1602
1266
  "lng": "?",
@@ -1606,16 +1270,12 @@ class Vehicle:
1606
1270
  @property
1607
1271
  def position_last_updated(self) -> datetime:
1608
1272
  """Return position last updated."""
1609
- return self.attrs.get("parkingposition", {}).get(
1610
- "carCapturedTimestamp", "Unknown"
1611
- )
1273
+ return self.attrs.get("parkingposition", {}).get("carCapturedTimestamp", "Unknown")
1612
1274
 
1613
1275
  @property
1614
1276
  def is_position_supported(self) -> bool:
1615
1277
  """Return true if position is available."""
1616
- return is_valid_path(
1617
- self.attrs, "parkingposition.carCapturedTimestamp"
1618
- ) or self.attrs.get("isMoving", False)
1278
+ return is_valid_path(self.attrs, "parkingposition.carCapturedTimestamp") or self.attrs.get("isMoving", False)
1619
1279
 
1620
1280
  @property
1621
1281
  def vehicle_moving(self) -> bool:
@@ -1653,64 +1313,43 @@ class Vehicle:
1653
1313
  # Vehicle fuel level and range
1654
1314
  @property
1655
1315
  def electric_range(self) -> int:
1656
- """Return electric range.
1316
+ """
1317
+ Return electric range.
1657
1318
 
1658
1319
  :return:
1659
1320
  """
1660
- if is_valid_path(
1661
- self.attrs, f"{Services.MEASUREMENTS}.rangeStatus.value.electricRange"
1662
- ):
1663
- return find_path(
1664
- self.attrs, f"{Services.MEASUREMENTS}.rangeStatus.value.electricRange"
1665
- )
1666
- return find_path(
1667
- self.attrs,
1668
- f"{Services.FUEL_STATUS}.rangeStatus.value.primaryEngine.remainingRange_km",
1669
- )
1321
+ if is_valid_path(self.attrs, f"{Services.MEASUREMENTS}.rangeStatus.value.electricRange"):
1322
+ return find_path(self.attrs, f"{Services.MEASUREMENTS}.rangeStatus.value.electricRange")
1323
+ return find_path(self.attrs, f"{Services.FUEL_STATUS}.rangeStatus.value.primaryEngine.remainingRange_km")
1670
1324
 
1671
1325
  @property
1672
1326
  def electric_range_last_updated(self) -> datetime:
1673
1327
  """Return electric range last updated."""
1674
- if is_valid_path(
1675
- self.attrs,
1676
- f"{Services.MEASUREMENTS}.rangeStatus.value.carCapturedTimestamp",
1677
- ):
1678
- return find_path(
1679
- self.attrs,
1680
- f"{Services.MEASUREMENTS}.rangeStatus.value.carCapturedTimestamp",
1681
- )
1682
- return find_path(
1683
- self.attrs, f"{Services.FUEL_STATUS}.rangeStatus.value.carCapturedTimestamp"
1684
- )
1328
+ if is_valid_path(self.attrs, f"{Services.MEASUREMENTS}.rangeStatus.value.carCapturedTimestamp"):
1329
+ return find_path(self.attrs, f"{Services.MEASUREMENTS}.rangeStatus.value.carCapturedTimestamp")
1330
+ return find_path(self.attrs, f"{Services.FUEL_STATUS}.rangeStatus.value.carCapturedTimestamp")
1685
1331
 
1686
1332
  @property
1687
1333
  def is_electric_range_supported(self) -> bool:
1688
- """Return true if electric range is supported.
1334
+ """
1335
+ Return true if electric range is supported.
1689
1336
 
1690
1337
  :return:
1691
1338
  """
1692
- return is_valid_path(
1693
- self.attrs, f"{Services.MEASUREMENTS}.rangeStatus.value.electricRange"
1694
- ) or (
1339
+ return is_valid_path(self.attrs, f"{Services.MEASUREMENTS}.rangeStatus.value.electricRange") or (
1695
1340
  self.is_car_type_electric
1696
- and is_valid_path(
1697
- self.attrs,
1698
- f"{Services.FUEL_STATUS}.rangeStatus.value.primaryEngine.remainingRange_km",
1699
- )
1341
+ and is_valid_path(self.attrs, f"{Services.FUEL_STATUS}.rangeStatus.value.primaryEngine.remainingRange_km")
1700
1342
  )
1701
1343
 
1702
1344
  @property
1703
1345
  def combustion_range(self) -> int:
1704
- """Return combustion engine range.
1346
+ """
1347
+ Return combustion engine range.
1705
1348
 
1706
1349
  :return:
1707
1350
  """
1708
1351
  DIESEL_RANGE = f"{Services.MEASUREMENTS}.rangeStatus.value.dieselRange"
1709
1352
  GASOLINE_RANGE = f"{Services.MEASUREMENTS}.rangeStatus.value.gasolineRange"
1710
- CNG_RANGE = f"{Services.MEASUREMENTS}.rangeStatus.value.cngRange"
1711
- TOTAL_RANGE = f"{Services.MEASUREMENTS}.rangeStatus.value.totalRange_km"
1712
- if is_valid_path(self.attrs, CNG_RANGE):
1713
- return find_path(self.attrs, TOTAL_RANGE)
1714
1353
  if is_valid_path(self.attrs, DIESEL_RANGE):
1715
1354
  return find_path(self.attrs, DIESEL_RANGE)
1716
1355
  if is_valid_path(self.attrs, GASOLINE_RANGE):
@@ -1720,179 +1359,83 @@ class Vehicle:
1720
1359
  @property
1721
1360
  def combustion_range_last_updated(self) -> datetime | None:
1722
1361
  """Return combustion engine range last updated."""
1723
- return find_path(
1724
- self.attrs,
1725
- f"{Services.MEASUREMENTS}.rangeStatus.value.carCapturedTimestamp",
1726
- )
1362
+ return find_path(self.attrs, f"{Services.MEASUREMENTS}.rangeStatus.value.carCapturedTimestamp")
1727
1363
 
1728
1364
  @property
1729
1365
  def is_combustion_range_supported(self) -> bool:
1730
- """Return true if combustion range is supported, i.e. false for EVs.
1731
-
1732
- :return:
1733
1366
  """
1734
- return (
1735
- is_valid_path(
1736
- self.attrs, f"{Services.MEASUREMENTS}.rangeStatus.value.dieselRange"
1737
- )
1738
- or is_valid_path(
1739
- self.attrs, f"{Services.MEASUREMENTS}.rangeStatus.value.gasolineRange"
1740
- )
1741
- or is_valid_path(
1742
- self.attrs, f"{Services.MEASUREMENTS}.rangeStatus.value.cngRange"
1743
- )
1744
- )
1745
-
1746
- @property
1747
- def fuel_range(self) -> int:
1748
- """Return fuel engine range.
1367
+ Return true if combustion range is supported, i.e. false for EVs.
1749
1368
 
1750
1369
  :return:
1751
1370
  """
1752
- DIESEL_RANGE = f"{Services.MEASUREMENTS}.rangeStatus.value.dieselRange"
1753
- GASOLINE_RANGE = f"{Services.MEASUREMENTS}.rangeStatus.value.gasolineRange"
1754
- if is_valid_path(self.attrs, DIESEL_RANGE):
1755
- return find_path(self.attrs, DIESEL_RANGE)
1756
- if is_valid_path(self.attrs, GASOLINE_RANGE):
1757
- return find_path(self.attrs, GASOLINE_RANGE)
1758
- return -1
1759
-
1760
- @property
1761
- def fuel_range_last_updated(self) -> datetime | None:
1762
- """Return fuel engine range last updated."""
1763
- return find_path(
1764
- self.attrs,
1765
- f"{Services.MEASUREMENTS}.rangeStatus.value.carCapturedTimestamp",
1766
- )
1767
-
1768
- @property
1769
- def is_fuel_range_supported(self) -> bool:
1770
- """Return true if fuel range is supported, i.e. false for EVs.
1771
-
1772
- :return:
1773
- """
1774
- return is_valid_path(
1775
- self.attrs, f"{Services.MEASUREMENTS}.rangeStatus.value.dieselRange"
1776
- ) or is_valid_path(
1371
+ return is_valid_path(self.attrs, f"{Services.MEASUREMENTS}.rangeStatus.value.dieselRange") or is_valid_path(
1777
1372
  self.attrs, f"{Services.MEASUREMENTS}.rangeStatus.value.gasolineRange"
1778
1373
  )
1779
1374
 
1780
- @property
1781
- def gas_range(self) -> int:
1782
- """Return gas engine range.
1783
-
1784
- :return:
1785
- """
1786
- CNG_RANGE = f"{Services.MEASUREMENTS}.rangeStatus.value.cngRange"
1787
- if is_valid_path(self.attrs, CNG_RANGE):
1788
- return find_path(self.attrs, CNG_RANGE)
1789
- return -1
1790
-
1791
- @property
1792
- def gas_range_last_updated(self) -> datetime | None:
1793
- """Return gas engine range last updated."""
1794
- return find_path(
1795
- self.attrs,
1796
- f"{Services.MEASUREMENTS}.rangeStatus.value.carCapturedTimestamp",
1797
- )
1798
-
1799
- @property
1800
- def is_gas_range_supported(self) -> bool:
1801
- """Return true if gas range is supported, i.e. false for EVs.
1802
-
1803
- :return:
1804
- """
1805
- return is_valid_path(
1806
- self.attrs, f"{Services.MEASUREMENTS}.rangeStatus.value.cngRange"
1807
- )
1808
-
1809
1375
  @property
1810
1376
  def combined_range(self) -> int:
1811
- """Return combined range.
1377
+ """
1378
+ Return combined range.
1812
1379
 
1813
1380
  :return:
1814
1381
  """
1815
- return find_path(
1816
- self.attrs, f"{Services.MEASUREMENTS}.rangeStatus.value.totalRange_km"
1817
- )
1382
+ return find_path(self.attrs, f"{Services.MEASUREMENTS}.rangeStatus.value.totalRange_km")
1818
1383
 
1819
1384
  @property
1820
1385
  def combined_range_last_updated(self) -> datetime | None:
1821
1386
  """Return combined range last updated."""
1822
- return find_path(
1823
- self.attrs,
1824
- f"{Services.MEASUREMENTS}.rangeStatus.value.carCapturedTimestamp",
1825
- )
1387
+ return find_path(self.attrs, f"{Services.MEASUREMENTS}.rangeStatus.value.carCapturedTimestamp")
1826
1388
 
1827
1389
  @property
1828
1390
  def is_combined_range_supported(self) -> bool:
1829
- """Return true if combined range is supported.
1391
+ """
1392
+ Return true if combined range is supported.
1830
1393
 
1831
1394
  :return:
1832
1395
  """
1833
- if is_valid_path(
1834
- self.attrs, f"{Services.MEASUREMENTS}.rangeStatus.value.totalRange_km"
1835
- ):
1836
- return (
1837
- self.is_electric_range_supported and self.is_combustion_range_supported
1838
- )
1396
+ if is_valid_path(self.attrs, f"{Services.MEASUREMENTS}.rangeStatus.value.totalRange_km"):
1397
+ return self.is_electric_range_supported and self.is_combustion_range_supported
1839
1398
  return False
1840
1399
 
1841
1400
  @property
1842
1401
  def battery_cruising_range(self) -> int:
1843
- """Return battery cruising range.
1402
+ """
1403
+ Return battery cruising range.
1844
1404
 
1845
1405
  :return:
1846
1406
  """
1847
- return find_path(
1848
- self.attrs,
1849
- f"{Services.CHARGING}.batteryStatus.value.cruisingRangeElectric_km",
1850
- )
1407
+ return find_path(self.attrs, f"{Services.CHARGING}.batteryStatus.value.cruisingRangeElectric_km")
1851
1408
 
1852
1409
  @property
1853
1410
  def battery_cruising_range_last_updated(self) -> datetime | None:
1854
1411
  """Return battery cruising range last updated."""
1855
- return find_path(
1856
- self.attrs, f"{Services.CHARGING}.batteryStatus.value.carCapturedTimestamp"
1857
- )
1412
+ return find_path(self.attrs, f"{Services.CHARGING}.batteryStatus.value.carCapturedTimestamp")
1858
1413
 
1859
1414
  @property
1860
1415
  def is_battery_cruising_range_supported(self) -> bool:
1861
- """Return true if battery cruising range is supported.
1416
+ """
1417
+ Return true if battery cruising range is supported.
1862
1418
 
1863
1419
  :return:
1864
1420
  """
1865
- return is_valid_path(
1866
- self.attrs,
1867
- f"{Services.CHARGING}.batteryStatus.value.cruisingRangeElectric_km",
1868
- )
1421
+ return is_valid_path(self.attrs, f"{Services.CHARGING}.batteryStatus.value.cruisingRangeElectric_km")
1869
1422
 
1870
1423
  @property
1871
1424
  def fuel_level(self) -> int:
1872
- """Return fuel level.
1425
+ """
1426
+ Return fuel level.
1873
1427
 
1874
1428
  :return:
1875
1429
  """
1876
1430
  fuel_level_pct = ""
1877
- if (
1878
- is_valid_path(
1879
- self.attrs,
1880
- f"{Services.FUEL_STATUS}.rangeStatus.value.primaryEngine.currentFuelLevel_pct",
1881
- )
1882
- and not self.is_primary_drive_gas()
1883
- ):
1431
+ if is_valid_path(self.attrs, f"{Services.FUEL_STATUS}.rangeStatus.value.primaryEngine.currentFuelLevel_pct"):
1884
1432
  fuel_level_pct = find_path(
1885
- self.attrs,
1886
- f"{Services.FUEL_STATUS}.rangeStatus.value.primaryEngine.currentFuelLevel_pct",
1433
+ self.attrs, f"{Services.FUEL_STATUS}.rangeStatus.value.primaryEngine.currentFuelLevel_pct"
1887
1434
  )
1888
1435
 
1889
- if is_valid_path(
1890
- self.attrs,
1891
- f"{Services.MEASUREMENTS}.fuelLevelStatus.value.currentFuelLevel_pct",
1892
- ):
1436
+ if is_valid_path(self.attrs, f"{Services.MEASUREMENTS}.fuelLevelStatus.value.currentFuelLevel_pct"):
1893
1437
  fuel_level_pct = find_path(
1894
- self.attrs,
1895
- f"{Services.MEASUREMENTS}.fuelLevelStatus.value.currentFuelLevel_pct",
1438
+ self.attrs, f"{Services.MEASUREMENTS}.fuelLevelStatus.value.currentFuelLevel_pct"
1896
1439
  )
1897
1440
  return fuel_level_pct
1898
1441
 
@@ -1900,162 +1443,58 @@ class Vehicle:
1900
1443
  def fuel_level_last_updated(self) -> datetime:
1901
1444
  """Return fuel level last updated."""
1902
1445
  fuel_level_lastupdated = ""
1903
- if is_valid_path(
1904
- self.attrs, f"{Services.FUEL_STATUS}.rangeStatus.value.carCapturedTimestamp"
1905
- ):
1446
+ if is_valid_path(self.attrs, f"{Services.FUEL_STATUS}.rangeStatus.value.carCapturedTimestamp"):
1906
1447
  fuel_level_lastupdated = find_path(
1907
- self.attrs,
1908
- f"{Services.FUEL_STATUS}.rangeStatus.value.carCapturedTimestamp",
1448
+ self.attrs, f"{Services.FUEL_STATUS}.rangeStatus.value.carCapturedTimestamp"
1909
1449
  )
1910
1450
 
1911
- if is_valid_path(
1912
- self.attrs,
1913
- f"{Services.MEASUREMENTS}.fuelLevelStatus.value.carCapturedTimestamp",
1914
- ):
1451
+ if is_valid_path(self.attrs, f"{Services.MEASUREMENTS}.fuelLevelStatus.value.carCapturedTimestamp"):
1915
1452
  fuel_level_lastupdated = find_path(
1916
- self.attrs,
1917
- f"{Services.MEASUREMENTS}.fuelLevelStatus.value.carCapturedTimestamp",
1453
+ self.attrs, f"{Services.MEASUREMENTS}.fuelLevelStatus.value.carCapturedTimestamp"
1918
1454
  )
1919
1455
  return fuel_level_lastupdated
1920
1456
 
1921
1457
  @property
1922
1458
  def is_fuel_level_supported(self) -> bool:
1923
- """Return true if fuel level reporting is supported.
1924
-
1925
- :return:
1926
1459
  """
1927
- return (
1928
- is_valid_path(
1929
- self.attrs,
1930
- f"{Services.FUEL_STATUS}.rangeStatus.value.primaryEngine.currentFuelLevel_pct",
1931
- )
1932
- and not self.is_primary_drive_gas()
1933
- ) or is_valid_path(
1934
- self.attrs,
1935
- f"{Services.MEASUREMENTS}.fuelLevelStatus.value.currentFuelLevel_pct",
1936
- )
1937
-
1938
- @property
1939
- def gas_level(self) -> int:
1940
- """Return gas level.
1941
-
1942
- :return:
1943
- """
1944
- gas_level_pct = ""
1945
- if (
1946
- is_valid_path(
1947
- self.attrs,
1948
- f"{Services.FUEL_STATUS}.rangeStatus.value.primaryEngine.currentFuelLevel_pct",
1949
- )
1950
- and self.is_primary_drive_gas()
1951
- ):
1952
- gas_level_pct = find_path(
1953
- self.attrs,
1954
- f"{Services.FUEL_STATUS}.rangeStatus.value.primaryEngine.currentFuelLevel_pct",
1955
- )
1956
-
1957
- if is_valid_path(
1958
- self.attrs,
1959
- f"{Services.MEASUREMENTS}.fuelLevelStatus.value.currentCngLevel_pct",
1960
- ):
1961
- gas_level_pct = find_path(
1962
- self.attrs,
1963
- f"{Services.MEASUREMENTS}.fuelLevelStatus.value.currentCngLevel_pct",
1964
- )
1965
- return gas_level_pct
1966
-
1967
- @property
1968
- def gas_level_last_updated(self) -> datetime:
1969
- """Return gas level last updated."""
1970
- gas_level_lastupdated = ""
1971
- if (
1972
- is_valid_path(
1973
- self.attrs,
1974
- f"{Services.FUEL_STATUS}.rangeStatus.value.carCapturedTimestamp",
1975
- )
1976
- and self.is_primary_drive_gas()
1977
- ):
1978
- gas_level_lastupdated = find_path(
1979
- self.attrs,
1980
- f"{Services.FUEL_STATUS}.rangeStatus.value.carCapturedTimestamp",
1981
- )
1982
-
1983
- if is_valid_path(
1984
- self.attrs,
1985
- f"{Services.MEASUREMENTS}.fuelLevelStatus.value.carCapturedTimestamp",
1986
- ):
1987
- gas_level_lastupdated = find_path(
1988
- self.attrs,
1989
- f"{Services.MEASUREMENTS}.fuelLevelStatus.value.carCapturedTimestamp",
1990
- )
1991
- return gas_level_lastupdated
1992
-
1993
- @property
1994
- def is_gas_level_supported(self) -> bool:
1995
- """Return true if gas level reporting is supported.
1460
+ Return true if fuel level reporting is supported.
1996
1461
 
1997
1462
  :return:
1998
1463
  """
1999
- return (
2000
- is_valid_path(
2001
- self.attrs,
2002
- f"{Services.FUEL_STATUS}.rangeStatus.value.primaryEngine.currentFuelLevel_pct",
2003
- )
2004
- and self.is_primary_drive_gas()
2005
- ) or is_valid_path(
2006
- self.attrs,
2007
- f"{Services.MEASUREMENTS}.fuelLevelStatus.value.currentCngLevel_pct",
2008
- )
1464
+ return is_valid_path(
1465
+ self.attrs, f"{Services.MEASUREMENTS}.fuelLevelStatus.value.currentFuelLevel_pct"
1466
+ ) or is_valid_path(self.attrs, f"{Services.FUEL_STATUS}.rangeStatus.value.primaryEngine.currentFuelLevel_pct")
2009
1467
 
2010
1468
  @property
2011
1469
  def car_type(self) -> str:
2012
- """Return car type.
1470
+ """
1471
+ Return car type.
2013
1472
 
2014
1473
  :return:
2015
1474
  """
2016
- if is_valid_path(
2017
- self.attrs, f"{Services.FUEL_STATUS}.rangeStatus.value.carType"
2018
- ):
2019
- return find_path(
2020
- self.attrs, f"{Services.FUEL_STATUS}.rangeStatus.value.carType"
2021
- ).capitalize()
2022
- if is_valid_path(
2023
- self.attrs, f"{Services.MEASUREMENTS}.fuelLevelStatus.value.carType"
2024
- ):
2025
- return find_path(
2026
- self.attrs, f"{Services.MEASUREMENTS}.fuelLevelStatus.value.carType"
2027
- ).capitalize()
1475
+ if is_valid_path(self.attrs, f"{Services.FUEL_STATUS}.rangeStatus.value.carType"):
1476
+ return find_path(self.attrs, f"{Services.FUEL_STATUS}.rangeStatus.value.carType").capitalize()
1477
+ if is_valid_path(self.attrs, f"{Services.MEASUREMENTS}.fuelLevelStatus.value.carType"):
1478
+ return find_path(self.attrs, f"{Services.MEASUREMENTS}.fuelLevelStatus.value.carType").capitalize()
2028
1479
  return "Unknown"
2029
1480
 
2030
1481
  @property
2031
1482
  def car_type_last_updated(self) -> datetime | None:
2032
1483
  """Return car type last updated."""
2033
- if is_valid_path(
2034
- self.attrs, f"{Services.FUEL_STATUS}.rangeStatus.value.carCapturedTimestamp"
2035
- ):
2036
- return find_path(
2037
- self.attrs,
2038
- f"{Services.FUEL_STATUS}.rangeStatus.value.carCapturedTimestamp",
2039
- )
2040
- if is_valid_path(
2041
- self.attrs,
2042
- f"{Services.MEASUREMENTS}.fuelLevelStatus.value.carCapturedTimestamp",
2043
- ):
2044
- return find_path(
2045
- self.attrs,
2046
- f"{Services.MEASUREMENTS}.fuelLevelStatus.value.carCapturedTimestamp",
2047
- )
1484
+ if is_valid_path(self.attrs, f"{Services.FUEL_STATUS}.rangeStatus.value.carCapturedTimestamp"):
1485
+ return find_path(self.attrs, f"{Services.FUEL_STATUS}.rangeStatus.value.carCapturedTimestamp")
1486
+ if is_valid_path(self.attrs, f"{Services.MEASUREMENTS}.fuelLevelStatus.value.carCapturedTimestamp"):
1487
+ return find_path(self.attrs, f"{Services.MEASUREMENTS}.fuelLevelStatus.value.carCapturedTimestamp")
2048
1488
  return None
2049
1489
 
2050
1490
  @property
2051
1491
  def is_car_type_supported(self) -> bool:
2052
- """Return true if car type is supported.
1492
+ """
1493
+ Return true if car type is supported.
2053
1494
 
2054
1495
  :return:
2055
1496
  """
2056
- return is_valid_path(
2057
- self.attrs, f"{Services.FUEL_STATUS}.rangeStatus.value.carType"
2058
- ) or is_valid_path(
1497
+ return is_valid_path(self.attrs, f"{Services.FUEL_STATUS}.rangeStatus.value.carType") or is_valid_path(
2059
1498
  self.attrs, f"{Services.MEASUREMENTS}.fuelLevelStatus.value.carType"
2060
1499
  )
2061
1500
 
@@ -2063,167 +1502,109 @@ class Vehicle:
2063
1502
  @property
2064
1503
  def climatisation_target_temperature(self) -> float | None:
2065
1504
  """Return the target temperature from climater."""
2066
- # TODO should we handle Fahrenheit?? # pylint: disable=fixme
2067
- return float(
2068
- find_path(
2069
- self.attrs,
2070
- f"{Services.CLIMATISATION}.climatisationSettings.value.targetTemperature_C",
2071
- )
2072
- )
1505
+ # TODO should we handle Fahrenheit??
1506
+ return float(find_path(self.attrs, f"{Services.CLIMATISATION}.climatisationSettings.value.targetTemperature_C"))
2073
1507
 
2074
1508
  @property
2075
1509
  def climatisation_target_temperature_last_updated(self) -> datetime:
2076
1510
  """Return the target temperature from climater last updated."""
2077
- return find_path(
2078
- self.attrs,
2079
- f"{Services.CLIMATISATION}.climatisationSettings.value.carCapturedTimestamp",
2080
- )
1511
+ return find_path(self.attrs, f"{Services.CLIMATISATION}.climatisationSettings.value.carCapturedTimestamp")
2081
1512
 
2082
1513
  @property
2083
1514
  def is_climatisation_target_temperature_supported(self) -> bool:
2084
1515
  """Return true if climatisation target temperature is supported."""
2085
- return is_valid_path(
2086
- self.attrs,
2087
- f"{Services.CLIMATISATION}.climatisationSettings.value.targetTemperature_C",
2088
- )
1516
+ return is_valid_path(self.attrs, f"{Services.CLIMATISATION}.climatisationSettings.value.targetTemperature_C")
2089
1517
 
2090
1518
  @property
2091
1519
  def climatisation_without_external_power(self):
2092
1520
  """Return state of climatisation from battery power."""
2093
1521
  return find_path(
2094
- self.attrs,
2095
- f"{Services.CLIMATISATION}.climatisationSettings.value.climatisationWithoutExternalPower",
1522
+ self.attrs, f"{Services.CLIMATISATION}.climatisationSettings.value.climatisationWithoutExternalPower"
2096
1523
  )
2097
1524
 
2098
1525
  @property
2099
1526
  def climatisation_without_external_power_last_updated(self) -> datetime:
2100
1527
  """Return state of climatisation from battery power last updated."""
2101
- return find_path(
2102
- self.attrs,
2103
- f"{Services.CLIMATISATION}.climatisationSettings.value.carCapturedTimestamp",
2104
- )
1528
+ return find_path(self.attrs, f"{Services.CLIMATISATION}.climatisationSettings.value.carCapturedTimestamp")
2105
1529
 
2106
1530
  @property
2107
1531
  def is_climatisation_without_external_power_supported(self) -> bool:
2108
1532
  """Return true if climatisation on battery power is supported."""
2109
1533
  return is_valid_path(
2110
- self.attrs,
2111
- f"{Services.CLIMATISATION}.climatisationSettings.value.climatisationWithoutExternalPower",
1534
+ self.attrs, f"{Services.CLIMATISATION}.climatisationSettings.value.climatisationWithoutExternalPower"
2112
1535
  )
2113
1536
 
2114
1537
  @property
2115
1538
  def auxiliary_air_conditioning(self):
2116
1539
  """Return state of auxiliary air conditioning."""
2117
- return find_path(
2118
- self.attrs,
2119
- f"{Services.CLIMATISATION}.climatisationSettings.value.climatizationAtUnlock",
2120
- )
1540
+ return find_path(self.attrs, f"{Services.CLIMATISATION}.climatisationSettings.value.climatizationAtUnlock")
2121
1541
 
2122
1542
  @property
2123
1543
  def auxiliary_air_conditioning_last_updated(self) -> datetime:
2124
1544
  """Return state of auxiliary air conditioning last updated."""
2125
- return find_path(
2126
- self.attrs,
2127
- f"{Services.CLIMATISATION}.climatisationSettings.value.carCapturedTimestamp",
2128
- )
1545
+ return find_path(self.attrs, f"{Services.CLIMATISATION}.climatisationSettings.value.carCapturedTimestamp")
2129
1546
 
2130
1547
  @property
2131
1548
  def is_auxiliary_air_conditioning_supported(self) -> bool:
2132
1549
  """Return true if auxiliary air conditioning is supported."""
2133
- return is_valid_path(
2134
- self.attrs,
2135
- f"{Services.CLIMATISATION}.climatisationSettings.value.climatizationAtUnlock",
2136
- )
1550
+ return is_valid_path(self.attrs, f"{Services.CLIMATISATION}.climatisationSettings.value.climatizationAtUnlock")
2137
1551
 
2138
1552
  @property
2139
1553
  def automatic_window_heating(self):
2140
1554
  """Return state of automatic window heating."""
2141
- return find_path(
2142
- self.attrs,
2143
- f"{Services.CLIMATISATION}.climatisationSettings.value.windowHeatingEnabled",
2144
- )
1555
+ return find_path(self.attrs, f"{Services.CLIMATISATION}.climatisationSettings.value.windowHeatingEnabled")
2145
1556
 
2146
1557
  @property
2147
1558
  def automatic_window_heating_last_updated(self) -> datetime:
2148
1559
  """Return state of automatic window heating last updated."""
2149
- return find_path(
2150
- self.attrs,
2151
- f"{Services.CLIMATISATION}.climatisationSettings.value.carCapturedTimestamp",
2152
- )
1560
+ return find_path(self.attrs, f"{Services.CLIMATISATION}.climatisationSettings.value.carCapturedTimestamp")
2153
1561
 
2154
1562
  @property
2155
1563
  def is_automatic_window_heating_supported(self) -> bool:
2156
1564
  """Return true if automatic window heating is supported."""
2157
- return is_valid_path(
2158
- self.attrs,
2159
- f"{Services.CLIMATISATION}.climatisationSettings.value.windowHeatingEnabled",
2160
- )
1565
+ return is_valid_path(self.attrs, f"{Services.CLIMATISATION}.climatisationSettings.value.windowHeatingEnabled")
2161
1566
 
2162
1567
  @property
2163
1568
  def zone_front_left(self):
2164
1569
  """Return state of zone front left."""
2165
- return find_path(
2166
- self.attrs,
2167
- f"{Services.CLIMATISATION}.climatisationSettings.value.zoneFrontLeftEnabled",
2168
- )
1570
+ return find_path(self.attrs, f"{Services.CLIMATISATION}.climatisationSettings.value.zoneFrontLeftEnabled")
2169
1571
 
2170
1572
  @property
2171
1573
  def zone_front_left_last_updated(self) -> datetime:
2172
1574
  """Return state of zone front left last updated."""
2173
- return find_path(
2174
- self.attrs,
2175
- f"{Services.CLIMATISATION}.climatisationSettings.value.carCapturedTimestamp",
2176
- )
1575
+ return find_path(self.attrs, f"{Services.CLIMATISATION}.climatisationSettings.value.carCapturedTimestamp")
2177
1576
 
2178
1577
  @property
2179
1578
  def is_zone_front_left_supported(self) -> bool:
2180
1579
  """Return true if zone front left is supported."""
2181
- return is_valid_path(
2182
- self.attrs,
2183
- f"{Services.CLIMATISATION}.climatisationSettings.value.zoneFrontLeftEnabled",
2184
- )
1580
+ return is_valid_path(self.attrs, f"{Services.CLIMATISATION}.climatisationSettings.value.zoneFrontLeftEnabled")
2185
1581
 
2186
1582
  @property
2187
1583
  def zone_front_right(self):
2188
1584
  """Return state of zone front left."""
2189
- return find_path(
2190
- self.attrs,
2191
- f"{Services.CLIMATISATION}.climatisationSettings.value.zoneFrontRightEnabled",
2192
- )
1585
+ return find_path(self.attrs, f"{Services.CLIMATISATION}.climatisationSettings.value.zoneFrontRightEnabled")
2193
1586
 
2194
1587
  @property
2195
1588
  def zone_front_right_last_updated(self) -> datetime:
2196
1589
  """Return state of zone front left last updated."""
2197
- return find_path(
2198
- self.attrs,
2199
- f"{Services.CLIMATISATION}.climatisationSettings.value.carCapturedTimestamp",
2200
- )
1590
+ return find_path(self.attrs, f"{Services.CLIMATISATION}.climatisationSettings.value.carCapturedTimestamp")
2201
1591
 
2202
1592
  @property
2203
1593
  def is_zone_front_right_supported(self) -> bool:
2204
1594
  """Return true if zone front left is supported."""
2205
- return is_valid_path(
2206
- self.attrs,
2207
- f"{Services.CLIMATISATION}.climatisationSettings.value.zoneFrontRightEnabled",
2208
- )
1595
+ return is_valid_path(self.attrs, f"{Services.CLIMATISATION}.climatisationSettings.value.zoneFrontRightEnabled")
2209
1596
 
2210
1597
  # Climatisation, electric
2211
1598
  @property
2212
1599
  def electric_climatisation(self) -> bool:
2213
1600
  """Return status of climatisation."""
2214
- status = find_path(
2215
- self.attrs,
2216
- f"{Services.CLIMATISATION}.climatisationStatus.value.climatisationState",
2217
- )
1601
+ status = find_path(self.attrs, f"{Services.CLIMATISATION}.climatisationStatus.value.climatisationState")
2218
1602
  return status in ["ventilation", "heating", "cooling", "on"]
2219
1603
 
2220
1604
  @property
2221
1605
  def electric_climatisation_last_updated(self) -> datetime:
2222
1606
  """Return status of climatisation last updated."""
2223
- return find_path(
2224
- self.attrs,
2225
- f"{Services.CLIMATISATION}.climatisationStatus.value.carCapturedTimestamp",
2226
- )
1607
+ return find_path(self.attrs, f"{Services.CLIMATISATION}.climatisationStatus.value.carCapturedTimestamp")
2227
1608
 
2228
1609
  @property
2229
1610
  def is_electric_climatisation_supported(self) -> bool:
@@ -2242,45 +1623,32 @@ class Vehicle:
2242
1623
  def electric_remaining_climatisation_time(self) -> int:
2243
1624
  """Return remaining climatisation time for electric climatisation."""
2244
1625
  return find_path(
2245
- self.attrs,
2246
- f"{Services.CLIMATISATION}.climatisationStatus.value.remainingClimatisationTime_min",
1626
+ self.attrs, f"{Services.CLIMATISATION}.climatisationStatus.value.remainingClimatisationTime_min"
2247
1627
  )
2248
1628
 
2249
1629
  @property
2250
1630
  def electric_remaining_climatisation_time_last_updated(self) -> bool:
2251
1631
  """Return status of electric climatisation remaining climatisation time last updated."""
2252
- return find_path(
2253
- self.attrs,
2254
- f"{Services.CLIMATISATION}.climatisationStatus.value.carCapturedTimestamp",
2255
- )
1632
+ return find_path(self.attrs, f"{Services.CLIMATISATION}.climatisationStatus.value.carCapturedTimestamp")
2256
1633
 
2257
1634
  @property
2258
1635
  def is_electric_remaining_climatisation_time_supported(self) -> bool:
2259
1636
  """Return true if electric climatisation remaining climatisation time is supported."""
2260
1637
  return is_valid_path(
2261
- self.attrs,
2262
- f"{Services.CLIMATISATION}.climatisationStatus.value.remainingClimatisationTime_min",
1638
+ self.attrs, f"{Services.CLIMATISATION}.climatisationStatus.value.remainingClimatisationTime_min"
2263
1639
  )
2264
1640
 
2265
1641
  @property
2266
1642
  def auxiliary_climatisation(self) -> bool:
2267
1643
  """Return status of auxiliary climatisation."""
2268
1644
  climatisation_state = None
2269
- if is_valid_path(
2270
- self.attrs,
2271
- f"{Services.CLIMATISATION}.auxiliaryHeatingStatus.value.climatisationState",
2272
- ):
1645
+ if is_valid_path(self.attrs, f"{Services.CLIMATISATION}.auxiliaryHeatingStatus.value.climatisationState"):
2273
1646
  climatisation_state = find_path(
2274
- self.attrs,
2275
- f"{Services.CLIMATISATION}.auxiliaryHeatingStatus.value.climatisationState",
1647
+ self.attrs, f"{Services.CLIMATISATION}.auxiliaryHeatingStatus.value.climatisationState"
2276
1648
  )
2277
- if is_valid_path(
2278
- self.attrs,
2279
- f"{Services.CLIMATISATION}.climatisationStatus.value.climatisationState",
2280
- ):
1649
+ if is_valid_path(self.attrs, f"{Services.CLIMATISATION}.climatisationStatus.value.climatisationState"):
2281
1650
  climatisation_state = find_path(
2282
- self.attrs,
2283
- f"{Services.CLIMATISATION}.climatisationStatus.value.climatisationState",
1651
+ self.attrs, f"{Services.CLIMATISATION}.climatisationStatus.value.climatisationState"
2284
1652
  )
2285
1653
  if climatisation_state in ["heating", "heatingAuxiliary", "on"]:
2286
1654
  return True
@@ -2289,115 +1657,80 @@ class Vehicle:
2289
1657
  @property
2290
1658
  def auxiliary_climatisation_last_updated(self) -> datetime:
2291
1659
  """Return status of auxiliary climatisation last updated."""
2292
- if is_valid_path(
2293
- self.attrs,
2294
- f"{Services.CLIMATISATION}.auxiliaryHeatingStatus.value.carCapturedTimestamp",
2295
- ):
2296
- return find_path(
2297
- self.attrs,
2298
- f"{Services.CLIMATISATION}.auxiliaryHeatingStatus.value.carCapturedTimestamp",
2299
- )
2300
- if is_valid_path(
2301
- self.attrs,
2302
- f"{Services.CLIMATISATION}.climatisationStatus.value.carCapturedTimestamp",
2303
- ):
2304
- return find_path(
2305
- self.attrs,
2306
- f"{Services.CLIMATISATION}.climatisationStatus.value.carCapturedTimestamp",
2307
- )
1660
+ if is_valid_path(self.attrs, f"{Services.CLIMATISATION}.auxiliaryHeatingStatus.value.carCapturedTimestamp"):
1661
+ return find_path(self.attrs, f"{Services.CLIMATISATION}.auxiliaryHeatingStatus.value.carCapturedTimestamp")
1662
+ if is_valid_path(self.attrs, f"{Services.CLIMATISATION}.climatisationStatus.value.carCapturedTimestamp"):
1663
+ return find_path(self.attrs, f"{Services.CLIMATISATION}.climatisationStatus.value.carCapturedTimestamp")
2308
1664
  return None
2309
1665
 
2310
1666
  @property
2311
1667
  def is_auxiliary_climatisation_supported(self) -> bool:
2312
1668
  """Return true if vehicle has auxiliary climatisation."""
2313
- if is_valid_path(
2314
- self.attrs,
2315
- f"{Services.CLIMATISATION}.auxiliaryHeatingStatus.value.climatisationState",
2316
- ):
1669
+ if is_valid_path(self.attrs, f"{Services.CLIMATISATION}.auxiliaryHeatingStatus.value.climatisationState"):
2317
1670
  return True
2318
- if is_valid_path(
2319
- self.attrs, f"{Services.USER_CAPABILITIES}.capabilitiesStatus.value"
2320
- ):
2321
- capabilities = find_path(
2322
- self.attrs, f"{Services.USER_CAPABILITIES}.capabilitiesStatus.value"
2323
- )
1671
+ if is_valid_path(self.attrs, f"{Services.USER_CAPABILITIES}.capabilitiesStatus.value"):
1672
+ capabilities = find_path(self.attrs, f"{Services.USER_CAPABILITIES}.capabilitiesStatus.value")
2324
1673
  for capability in capabilities:
2325
1674
  if capability.get("id", None) == "hybridCarAuxiliaryHeating":
2326
1675
  if 1007 in capability.get("status", []):
2327
1676
  return False
2328
- return True
1677
+ else:
1678
+ return True
2329
1679
  return False
2330
1680
 
2331
1681
  @property
2332
1682
  def auxiliary_duration(self) -> int:
2333
1683
  """Return heating duration for auxiliary heater."""
2334
1684
  return find_path(
2335
- self.attrs,
2336
- f"{Services.CLIMATISATION}.climatisationSettings.value.auxiliaryHeatingSettings.duration_min",
1685
+ self.attrs, f"{Services.CLIMATISATION}.climatisationSettings.value.auxiliaryHeatingSettings.duration_min"
2337
1686
  )
2338
1687
 
2339
1688
  @property
2340
1689
  def auxiliary_duration_last_updated(self) -> bool:
2341
1690
  """Return status of auxiliary heater last updated."""
2342
- return find_path(
2343
- self.attrs,
2344
- f"{Services.CLIMATISATION}.climatisationSettings.value.carCapturedTimestamp",
2345
- )
1691
+ return find_path(self.attrs, f"{Services.CLIMATISATION}.climatisationSettings.value.carCapturedTimestamp")
2346
1692
 
2347
1693
  @property
2348
1694
  def is_auxiliary_duration_supported(self) -> bool:
2349
1695
  """Return true if auxiliary heater is supported."""
2350
1696
  return is_valid_path(
2351
- self.attrs,
2352
- f"{Services.CLIMATISATION}.climatisationSettings.value.auxiliaryHeatingSettings.duration_min",
1697
+ self.attrs, f"{Services.CLIMATISATION}.climatisationSettings.value.auxiliaryHeatingSettings.duration_min"
2353
1698
  )
2354
1699
 
2355
1700
  @property
2356
1701
  def auxiliary_remaining_climatisation_time(self) -> int:
2357
1702
  """Return remaining climatisation time for auxiliary heater."""
2358
1703
  return find_path(
2359
- self.attrs,
2360
- f"{Services.CLIMATISATION}.auxiliaryHeatingStatus.value.remainingClimatisationTime_min",
1704
+ self.attrs, f"{Services.CLIMATISATION}.auxiliaryHeatingStatus.value.remainingClimatisationTime_min"
2361
1705
  )
2362
1706
 
2363
1707
  @property
2364
1708
  def auxiliary_remaining_climatisation_time_last_updated(self) -> bool:
2365
1709
  """Return status of auxiliary heater remaining climatisation time last updated."""
2366
- return find_path(
2367
- self.attrs,
2368
- f"{Services.CLIMATISATION}.auxiliaryHeatingStatus.value.carCapturedTimestamp",
2369
- )
1710
+ return find_path(self.attrs, f"{Services.CLIMATISATION}.auxiliaryHeatingStatus.value.carCapturedTimestamp")
2370
1711
 
2371
1712
  @property
2372
1713
  def is_auxiliary_remaining_climatisation_time_supported(self) -> bool:
2373
1714
  """Return true if auxiliary heater remaining climatisation time is supported."""
2374
1715
  return is_valid_path(
2375
- self.attrs,
2376
- f"{Services.CLIMATISATION}.auxiliaryHeatingStatus.value.remainingClimatisationTime_min",
1716
+ self.attrs, f"{Services.CLIMATISATION}.auxiliaryHeatingStatus.value.remainingClimatisationTime_min"
2377
1717
  )
2378
1718
 
2379
1719
  @property
2380
1720
  def is_climatisation_supported(self) -> bool:
2381
1721
  """Return true if climatisation has State."""
2382
- return is_valid_path(
2383
- self.attrs,
2384
- f"{Services.CLIMATISATION}.climatisationStatus.value.climatisationState",
2385
- )
1722
+ return is_valid_path(self.attrs, f"{Services.CLIMATISATION}.climatisationStatus.value.climatisationState")
2386
1723
 
2387
1724
  @property
2388
1725
  def is_climatisation_supported_last_updated(self) -> datetime:
2389
1726
  """Return attribute last updated timestamp."""
2390
- return find_path(
2391
- self.attrs,
2392
- f"{Services.CLIMATISATION}.climatisationStatus.value.carCapturedTimestamp",
2393
- )
1727
+ return find_path(self.attrs, f"{Services.CLIMATISATION}.climatisationStatus.value.carCapturedTimestamp")
2394
1728
 
2395
1729
  @property
2396
1730
  def window_heater_front(self) -> bool:
2397
1731
  """Return status of front window heater."""
2398
1732
  window_heating_status = find_path(
2399
- self.attrs,
2400
- f"{Services.CLIMATISATION}.windowHeatingStatus.value.windowHeatingStatus",
1733
+ self.attrs, f"{Services.CLIMATISATION}.windowHeatingStatus.value.windowHeatingStatus"
2401
1734
  )
2402
1735
  for window_heating_state in window_heating_status:
2403
1736
  if window_heating_state["windowLocation"] == "front":
@@ -2408,25 +1741,18 @@ class Vehicle:
2408
1741
  @property
2409
1742
  def window_heater_front_last_updated(self) -> datetime:
2410
1743
  """Return front window heater last updated."""
2411
- return find_path(
2412
- self.attrs,
2413
- f"{Services.CLIMATISATION}.windowHeatingStatus.value.carCapturedTimestamp",
2414
- )
1744
+ return find_path(self.attrs, f"{Services.CLIMATISATION}.windowHeatingStatus.value.carCapturedTimestamp")
2415
1745
 
2416
1746
  @property
2417
1747
  def is_window_heater_front_supported(self) -> bool:
2418
1748
  """Return true if vehicle has heater."""
2419
- return is_valid_path(
2420
- self.attrs,
2421
- f"{Services.CLIMATISATION}.windowHeatingStatus.value.windowHeatingStatus",
2422
- )
1749
+ return is_valid_path(self.attrs, f"{Services.CLIMATISATION}.windowHeatingStatus.value.windowHeatingStatus")
2423
1750
 
2424
1751
  @property
2425
1752
  def window_heater_back(self) -> bool:
2426
1753
  """Return status of rear window heater."""
2427
1754
  window_heating_status = find_path(
2428
- self.attrs,
2429
- f"{Services.CLIMATISATION}.windowHeatingStatus.value.windowHeatingStatus",
1755
+ self.attrs, f"{Services.CLIMATISATION}.windowHeatingStatus.value.windowHeatingStatus"
2430
1756
  )
2431
1757
  for window_heating_state in window_heating_status:
2432
1758
  if window_heating_state["windowLocation"] == "rear":
@@ -2437,18 +1763,12 @@ class Vehicle:
2437
1763
  @property
2438
1764
  def window_heater_back_last_updated(self) -> datetime:
2439
1765
  """Return front window heater last updated."""
2440
- return find_path(
2441
- self.attrs,
2442
- f"{Services.CLIMATISATION}.windowHeatingStatus.value.carCapturedTimestamp",
2443
- )
1766
+ return find_path(self.attrs, f"{Services.CLIMATISATION}.windowHeatingStatus.value.carCapturedTimestamp")
2444
1767
 
2445
1768
  @property
2446
1769
  def is_window_heater_back_supported(self) -> bool:
2447
1770
  """Return true if vehicle has heater."""
2448
- return is_valid_path(
2449
- self.attrs,
2450
- f"{Services.CLIMATISATION}.windowHeatingStatus.value.windowHeatingStatus",
2451
- )
1771
+ return is_valid_path(self.attrs, f"{Services.CLIMATISATION}.windowHeatingStatus.value.windowHeatingStatus")
2452
1772
 
2453
1773
  @property
2454
1774
  def window_heater(self) -> bool:
@@ -2464,50 +1784,29 @@ class Vehicle:
2464
1784
  def is_window_heater_supported(self) -> bool:
2465
1785
  """Return true if vehicle has heater."""
2466
1786
  # ID models detection
2467
- if (
2468
- self._services.get(Services.PARAMETERS, {}).get(
2469
- "supportsStartWindowHeating", "false"
2470
- )
2471
- == "true"
2472
- ):
1787
+ if self._services.get(Services.PARAMETERS, {}).get("supportsStartWindowHeating", "false") == "true":
2473
1788
  return True
2474
1789
  # "Legacy" models detection
2475
- parameters = self._services.get(Services.CLIMATISATION, {}).get(
2476
- "parameters", None
2477
- )
1790
+ parameters = self._services.get(Services.CLIMATISATION, {}).get("parameters", None)
2478
1791
  if parameters:
2479
1792
  for parameter in parameters:
2480
- if (
2481
- parameter["key"] == "supportsStartWindowHeating"
2482
- and parameter["value"] == "true"
2483
- ):
1793
+ if parameter["key"] == "supportsStartWindowHeating" and parameter["value"] == "true":
2484
1794
  return True
2485
1795
  return False
2486
1796
 
2487
1797
  # Windows
2488
1798
  @property
2489
1799
  def windows_closed(self) -> bool:
2490
- """Return true if all supported windows are closed.
1800
+ """
1801
+ Return true if all supported windows are closed.
2491
1802
 
2492
1803
  :return:
2493
1804
  """
2494
1805
  return (
2495
- (
2496
- not self.is_window_closed_left_front_supported
2497
- or self.window_closed_left_front
2498
- )
2499
- and (
2500
- not self.is_window_closed_left_back_supported
2501
- or self.window_closed_left_back
2502
- )
2503
- and (
2504
- not self.is_window_closed_right_front_supported
2505
- or self.window_closed_right_front
2506
- )
2507
- and (
2508
- not self.is_window_closed_right_back_supported
2509
- or self.window_closed_right_back
2510
- )
1806
+ (not self.is_window_closed_left_front_supported or self.window_closed_left_front)
1807
+ and (not self.is_window_closed_left_back_supported or self.window_closed_left_back)
1808
+ and (not self.is_window_closed_right_front_supported or self.window_closed_right_front)
1809
+ and (not self.is_window_closed_right_back_supported or self.window_closed_right_back)
2511
1810
  )
2512
1811
 
2513
1812
  @property
@@ -2527,17 +1826,15 @@ class Vehicle:
2527
1826
 
2528
1827
  @property
2529
1828
  def window_closed_left_front(self) -> bool:
2530
- """Return left front window closed state.
1829
+ """
1830
+ Return left front window closed state.
2531
1831
 
2532
1832
  :return:
2533
1833
  """
2534
1834
  windows = find_path(self.attrs, f"{Services.ACCESS}.accessStatus.value.windows")
2535
1835
  for window in windows:
2536
1836
  if window["name"] == "frontLeft":
2537
- if not any(
2538
- valid_status in window["status"]
2539
- for valid_status in P.VALID_WINDOW_STATUS
2540
- ):
1837
+ if not any(valid_status in window["status"] for valid_status in P.VALID_WINDOW_STATUS):
2541
1838
  return None
2542
1839
  return "closed" in window["status"]
2543
1840
  return False
@@ -2545,38 +1842,29 @@ class Vehicle:
2545
1842
  @property
2546
1843
  def window_closed_left_front_last_updated(self) -> datetime:
2547
1844
  """Return attribute last updated timestamp."""
2548
- return find_path(
2549
- self.attrs, f"{Services.ACCESS}.accessStatus.value.carCapturedTimestamp"
2550
- )
1845
+ return find_path(self.attrs, f"{Services.ACCESS}.accessStatus.value.carCapturedTimestamp")
2551
1846
 
2552
1847
  @property
2553
1848
  def is_window_closed_left_front_supported(self) -> bool:
2554
1849
  """Return true if supported."""
2555
1850
  if is_valid_path(self.attrs, f"{Services.ACCESS}.accessStatus.value.windows"):
2556
- windows = find_path(
2557
- self.attrs, f"{Services.ACCESS}.accessStatus.value.windows"
2558
- )
1851
+ windows = find_path(self.attrs, f"{Services.ACCESS}.accessStatus.value.windows")
2559
1852
  for window in windows:
2560
- if (
2561
- window["name"] == "frontLeft"
2562
- and "unsupported" not in window["status"]
2563
- ):
1853
+ if window["name"] == "frontLeft" and "unsupported" not in window["status"]:
2564
1854
  return True
2565
1855
  return False
2566
1856
 
2567
1857
  @property
2568
1858
  def window_closed_right_front(self) -> bool:
2569
- """Return right front window closed state.
1859
+ """
1860
+ Return right front window closed state.
2570
1861
 
2571
1862
  :return:
2572
1863
  """
2573
1864
  windows = find_path(self.attrs, f"{Services.ACCESS}.accessStatus.value.windows")
2574
1865
  for window in windows:
2575
1866
  if window["name"] == "frontRight":
2576
- if not any(
2577
- valid_status in window["status"]
2578
- for valid_status in P.VALID_WINDOW_STATUS
2579
- ):
1867
+ if not any(valid_status in window["status"] for valid_status in P.VALID_WINDOW_STATUS):
2580
1868
  return None
2581
1869
  return "closed" in window["status"]
2582
1870
  return False
@@ -2584,38 +1872,29 @@ class Vehicle:
2584
1872
  @property
2585
1873
  def window_closed_right_front_last_updated(self) -> datetime:
2586
1874
  """Return attribute last updated timestamp."""
2587
- return find_path(
2588
- self.attrs, f"{Services.ACCESS}.accessStatus.value.carCapturedTimestamp"
2589
- )
1875
+ return find_path(self.attrs, f"{Services.ACCESS}.accessStatus.value.carCapturedTimestamp")
2590
1876
 
2591
1877
  @property
2592
1878
  def is_window_closed_right_front_supported(self) -> bool:
2593
1879
  """Return true if supported."""
2594
1880
  if is_valid_path(self.attrs, f"{Services.ACCESS}.accessStatus.value.windows"):
2595
- windows = find_path(
2596
- self.attrs, f"{Services.ACCESS}.accessStatus.value.windows"
2597
- )
1881
+ windows = find_path(self.attrs, f"{Services.ACCESS}.accessStatus.value.windows")
2598
1882
  for window in windows:
2599
- if (
2600
- window["name"] == "frontRight"
2601
- and "unsupported" not in window["status"]
2602
- ):
1883
+ if window["name"] == "frontRight" and "unsupported" not in window["status"]:
2603
1884
  return True
2604
1885
  return False
2605
1886
 
2606
1887
  @property
2607
1888
  def window_closed_left_back(self) -> bool:
2608
- """Return left back window closed state.
1889
+ """
1890
+ Return left back window closed state.
2609
1891
 
2610
1892
  :return:
2611
1893
  """
2612
1894
  windows = find_path(self.attrs, f"{Services.ACCESS}.accessStatus.value.windows")
2613
1895
  for window in windows:
2614
1896
  if window["name"] == "rearLeft":
2615
- if not any(
2616
- valid_status in window["status"]
2617
- for valid_status in P.VALID_WINDOW_STATUS
2618
- ):
1897
+ if not any(valid_status in window["status"] for valid_status in P.VALID_WINDOW_STATUS):
2619
1898
  return None
2620
1899
  return "closed" in window["status"]
2621
1900
  return False
@@ -2623,38 +1902,29 @@ class Vehicle:
2623
1902
  @property
2624
1903
  def window_closed_left_back_last_updated(self) -> datetime:
2625
1904
  """Return attribute last updated timestamp."""
2626
- return find_path(
2627
- self.attrs, f"{Services.ACCESS}.accessStatus.value.carCapturedTimestamp"
2628
- )
1905
+ return find_path(self.attrs, f"{Services.ACCESS}.accessStatus.value.carCapturedTimestamp")
2629
1906
 
2630
1907
  @property
2631
1908
  def is_window_closed_left_back_supported(self) -> bool:
2632
1909
  """Return true if supported."""
2633
1910
  if is_valid_path(self.attrs, f"{Services.ACCESS}.accessStatus.value.windows"):
2634
- windows = find_path(
2635
- self.attrs, f"{Services.ACCESS}.accessStatus.value.windows"
2636
- )
1911
+ windows = find_path(self.attrs, f"{Services.ACCESS}.accessStatus.value.windows")
2637
1912
  for window in windows:
2638
- if (
2639
- window["name"] == "rearLeft"
2640
- and "unsupported" not in window["status"]
2641
- ):
1913
+ if window["name"] == "rearLeft" and "unsupported" not in window["status"]:
2642
1914
  return True
2643
1915
  return False
2644
1916
 
2645
1917
  @property
2646
1918
  def window_closed_right_back(self) -> bool:
2647
- """Return right back window closed state.
1919
+ """
1920
+ Return right back window closed state.
2648
1921
 
2649
1922
  :return:
2650
1923
  """
2651
1924
  windows = find_path(self.attrs, f"{Services.ACCESS}.accessStatus.value.windows")
2652
1925
  for window in windows:
2653
1926
  if window["name"] == "rearRight":
2654
- if not any(
2655
- valid_status in window["status"]
2656
- for valid_status in P.VALID_WINDOW_STATUS
2657
- ):
1927
+ if not any(valid_status in window["status"] for valid_status in P.VALID_WINDOW_STATUS):
2658
1928
  return None
2659
1929
  return "closed" in window["status"]
2660
1930
  return False
@@ -2662,38 +1932,29 @@ class Vehicle:
2662
1932
  @property
2663
1933
  def window_closed_right_back_last_updated(self) -> datetime:
2664
1934
  """Return attribute last updated timestamp."""
2665
- return find_path(
2666
- self.attrs, f"{Services.ACCESS}.accessStatus.value.carCapturedTimestamp"
2667
- )
1935
+ return find_path(self.attrs, f"{Services.ACCESS}.accessStatus.value.carCapturedTimestamp")
2668
1936
 
2669
1937
  @property
2670
1938
  def is_window_closed_right_back_supported(self) -> bool:
2671
1939
  """Return true if supported."""
2672
1940
  if is_valid_path(self.attrs, f"{Services.ACCESS}.accessStatus.value.windows"):
2673
- windows = find_path(
2674
- self.attrs, f"{Services.ACCESS}.accessStatus.value.windows"
2675
- )
1941
+ windows = find_path(self.attrs, f"{Services.ACCESS}.accessStatus.value.windows")
2676
1942
  for window in windows:
2677
- if (
2678
- window["name"] == "rearRight"
2679
- and "unsupported" not in window["status"]
2680
- ):
1943
+ if window["name"] == "rearRight" and "unsupported" not in window["status"]:
2681
1944
  return True
2682
1945
  return False
2683
1946
 
2684
1947
  @property
2685
1948
  def sunroof_closed(self) -> bool:
2686
- """Return sunroof closed state.
1949
+ """
1950
+ Return sunroof closed state.
2687
1951
 
2688
1952
  :return:
2689
1953
  """
2690
1954
  windows = find_path(self.attrs, f"{Services.ACCESS}.accessStatus.value.windows")
2691
1955
  for window in windows:
2692
1956
  if window["name"] == "sunRoof":
2693
- if not any(
2694
- valid_status in window["status"]
2695
- for valid_status in P.VALID_WINDOW_STATUS
2696
- ):
1957
+ if not any(valid_status in window["status"] for valid_status in P.VALID_WINDOW_STATUS):
2697
1958
  return None
2698
1959
  return "closed" in window["status"]
2699
1960
  return False
@@ -2701,38 +1962,29 @@ class Vehicle:
2701
1962
  @property
2702
1963
  def sunroof_closed_last_updated(self) -> datetime:
2703
1964
  """Return attribute last updated timestamp."""
2704
- return find_path(
2705
- self.attrs, f"{Services.ACCESS}.accessStatus.value.carCapturedTimestamp"
2706
- )
1965
+ return find_path(self.attrs, f"{Services.ACCESS}.accessStatus.value.carCapturedTimestamp")
2707
1966
 
2708
1967
  @property
2709
1968
  def is_sunroof_closed_supported(self) -> bool:
2710
1969
  """Return true if supported."""
2711
1970
  if is_valid_path(self.attrs, f"{Services.ACCESS}.accessStatus.value.windows"):
2712
- windows = find_path(
2713
- self.attrs, f"{Services.ACCESS}.accessStatus.value.windows"
2714
- )
1971
+ windows = find_path(self.attrs, f"{Services.ACCESS}.accessStatus.value.windows")
2715
1972
  for window in windows:
2716
- if (
2717
- window["name"] == "sunRoof"
2718
- and "unsupported" not in window["status"]
2719
- ):
1973
+ if window["name"] == "sunRoof" and "unsupported" not in window["status"]:
2720
1974
  return True
2721
1975
  return False
2722
1976
 
2723
1977
  @property
2724
1978
  def sunroof_rear_closed(self) -> bool:
2725
- """Return sunroof rear closed state.
1979
+ """
1980
+ Return sunroof rear closed state.
2726
1981
 
2727
1982
  :return:
2728
1983
  """
2729
1984
  windows = find_path(self.attrs, f"{Services.ACCESS}.accessStatus.value.windows")
2730
1985
  for window in windows:
2731
1986
  if window["name"] == "sunRoofRear":
2732
- if not any(
2733
- valid_status in window["status"]
2734
- for valid_status in P.VALID_WINDOW_STATUS
2735
- ):
1987
+ if not any(valid_status in window["status"] for valid_status in P.VALID_WINDOW_STATUS):
2736
1988
  return None
2737
1989
  return "closed" in window["status"]
2738
1990
  return False
@@ -2740,38 +1992,29 @@ class Vehicle:
2740
1992
  @property
2741
1993
  def sunroof_rear_closed_last_updated(self) -> datetime:
2742
1994
  """Return attribute last updated timestamp."""
2743
- return find_path(
2744
- self.attrs, f"{Services.ACCESS}.accessStatus.value.carCapturedTimestamp"
2745
- )
1995
+ return find_path(self.attrs, f"{Services.ACCESS}.accessStatus.value.carCapturedTimestamp")
2746
1996
 
2747
1997
  @property
2748
1998
  def is_sunroof_rear_closed_supported(self) -> bool:
2749
1999
  """Return true if supported."""
2750
2000
  if is_valid_path(self.attrs, f"{Services.ACCESS}.accessStatus.value.windows"):
2751
- windows = find_path(
2752
- self.attrs, f"{Services.ACCESS}.accessStatus.value.windows"
2753
- )
2001
+ windows = find_path(self.attrs, f"{Services.ACCESS}.accessStatus.value.windows")
2754
2002
  for window in windows:
2755
- if (
2756
- window["name"] == "sunRoofRear"
2757
- and "unsupported" not in window["status"]
2758
- ):
2003
+ if window["name"] == "sunRoofRear" and "unsupported" not in window["status"]:
2759
2004
  return True
2760
2005
  return False
2761
2006
 
2762
2007
  @property
2763
2008
  def roof_cover_closed(self) -> bool:
2764
- """Return roof cover closed state.
2009
+ """
2010
+ Return roof cover closed state.
2765
2011
 
2766
2012
  :return:
2767
2013
  """
2768
2014
  windows = find_path(self.attrs, f"{Services.ACCESS}.accessStatus.value.windows")
2769
2015
  for window in windows:
2770
2016
  if window["name"] == "roofCover":
2771
- if not any(
2772
- valid_status in window["status"]
2773
- for valid_status in P.VALID_WINDOW_STATUS
2774
- ):
2017
+ if not any(valid_status in window["status"] for valid_status in P.VALID_WINDOW_STATUS):
2775
2018
  return None
2776
2019
  return "closed" in window["status"]
2777
2020
  return False
@@ -2779,22 +2022,15 @@ class Vehicle:
2779
2022
  @property
2780
2023
  def roof_cover_closed_last_updated(self) -> datetime:
2781
2024
  """Return attribute last updated timestamp."""
2782
- return find_path(
2783
- self.attrs, f"{Services.ACCESS}.accessStatus.value.carCapturedTimestamp"
2784
- )
2025
+ return find_path(self.attrs, f"{Services.ACCESS}.accessStatus.value.carCapturedTimestamp")
2785
2026
 
2786
2027
  @property
2787
2028
  def is_roof_cover_closed_supported(self) -> bool:
2788
2029
  """Return true if supported."""
2789
2030
  if is_valid_path(self.attrs, f"{Services.ACCESS}.accessStatus.value.doors"):
2790
- windows = find_path(
2791
- self.attrs, f"{Services.ACCESS}.accessStatus.value.windows"
2792
- )
2031
+ windows = find_path(self.attrs, f"{Services.ACCESS}.accessStatus.value.windows")
2793
2032
  for window in windows:
2794
- if (
2795
- window["name"] == "roofCover"
2796
- and "unsupported" not in window["status"]
2797
- ):
2033
+ if window["name"] == "roofCover" and "unsupported" not in window["status"]:
2798
2034
  return True
2799
2035
  return False
2800
2036
 
@@ -2806,60 +2042,51 @@ class Vehicle:
2806
2042
 
2807
2043
  @property
2808
2044
  def door_locked(self) -> bool:
2809
- """Return true if all doors are locked.
2045
+ """
2046
+ Return true if all doors are locked.
2810
2047
 
2811
2048
  :return:
2812
2049
  """
2813
- return (
2814
- find_path(
2815
- self.attrs, f"{Services.ACCESS}.accessStatus.value.doorLockStatus"
2816
- )
2817
- == "locked"
2818
- )
2050
+ return find_path(self.attrs, f"{Services.ACCESS}.accessStatus.value.doorLockStatus") == "locked"
2819
2051
 
2820
2052
  @property
2821
2053
  def door_locked_last_updated(self) -> datetime:
2822
2054
  """Return door lock last updated."""
2823
- return find_path(
2824
- self.attrs, f"{Services.ACCESS}.accessStatus.value.carCapturedTimestamp"
2825
- )
2055
+ return find_path(self.attrs, f"{Services.ACCESS}.accessStatus.value.carCapturedTimestamp")
2826
2056
 
2827
2057
  @property
2828
2058
  def door_locked_sensor_last_updated(self) -> datetime:
2829
2059
  """Return door lock last updated."""
2830
- return find_path(
2831
- self.attrs, f"{Services.ACCESS}.accessStatus.value.carCapturedTimestamp"
2832
- )
2060
+ return find_path(self.attrs, f"{Services.ACCESS}.accessStatus.value.carCapturedTimestamp")
2833
2061
 
2834
2062
  @property
2835
2063
  def is_door_locked_supported(self) -> bool:
2836
- """Return true if supported.
2064
+ """
2065
+ Return true if supported.
2837
2066
 
2838
2067
  :return:
2839
2068
  """
2840
2069
  # First check that the service is actually enabled
2841
2070
  if not self._services.get(Services.ACCESS, {}).get("active", False):
2842
2071
  return False
2843
- return is_valid_path(
2844
- self.attrs, f"{Services.ACCESS}.accessStatus.value.doorLockStatus"
2845
- )
2072
+ return is_valid_path(self.attrs, f"{Services.ACCESS}.accessStatus.value.doorLockStatus")
2846
2073
 
2847
2074
  @property
2848
2075
  def is_door_locked_sensor_supported(self) -> bool:
2849
- """Return true if supported.
2076
+ """
2077
+ Return true if supported.
2850
2078
 
2851
2079
  :return:
2852
2080
  """
2853
2081
  # Use real lock if the service is actually enabled
2854
2082
  if self._services.get(Services.ACCESS, {}).get("active", False):
2855
2083
  return False
2856
- return is_valid_path(
2857
- self.attrs, f"{Services.ACCESS}.accessStatus.value.doorLockStatus"
2858
- )
2084
+ return is_valid_path(self.attrs, f"{Services.ACCESS}.accessStatus.value.doorLockStatus")
2859
2085
 
2860
2086
  @property
2861
2087
  def trunk_locked(self) -> bool:
2862
- """Return trunk locked state.
2088
+ """
2089
+ Return trunk locked state.
2863
2090
 
2864
2091
  :return:
2865
2092
  """
@@ -2872,13 +2099,12 @@ class Vehicle:
2872
2099
  @property
2873
2100
  def trunk_locked_last_updated(self) -> datetime:
2874
2101
  """Return attribute last updated timestamp."""
2875
- return find_path(
2876
- self.attrs, f"{Services.ACCESS}.accessStatus.value.carCapturedTimestamp"
2877
- )
2102
+ return find_path(self.attrs, f"{Services.ACCESS}.accessStatus.value.carCapturedTimestamp")
2878
2103
 
2879
2104
  @property
2880
2105
  def is_trunk_locked_supported(self) -> bool:
2881
- """Return true if supported.
2106
+ """
2107
+ Return true if supported.
2882
2108
 
2883
2109
  :return:
2884
2110
  """
@@ -2893,7 +2119,8 @@ class Vehicle:
2893
2119
 
2894
2120
  @property
2895
2121
  def trunk_locked_sensor(self) -> bool:
2896
- """Return trunk locked state.
2122
+ """
2123
+ Return trunk locked state.
2897
2124
 
2898
2125
  :return:
2899
2126
  """
@@ -2906,13 +2133,12 @@ class Vehicle:
2906
2133
  @property
2907
2134
  def trunk_locked_sensor_last_updated(self) -> datetime:
2908
2135
  """Return attribute last updated timestamp."""
2909
- return find_path(
2910
- self.attrs, f"{Services.ACCESS}.accessStatus.value.carCapturedTimestamp"
2911
- )
2136
+ return find_path(self.attrs, f"{Services.ACCESS}.accessStatus.value.carCapturedTimestamp")
2912
2137
 
2913
2138
  @property
2914
2139
  def is_trunk_locked_sensor_supported(self) -> bool:
2915
- """Return true if supported.
2140
+ """
2141
+ Return true if supported.
2916
2142
 
2917
2143
  :return:
2918
2144
  """
@@ -2928,17 +2154,15 @@ class Vehicle:
2928
2154
  # Doors, hood and trunk
2929
2155
  @property
2930
2156
  def hood_closed(self) -> bool:
2931
- """Return hood closed state.
2157
+ """
2158
+ Return hood closed state.
2932
2159
 
2933
2160
  :return:
2934
2161
  """
2935
2162
  doors = find_path(self.attrs, f"{Services.ACCESS}.accessStatus.value.doors")
2936
2163
  for door in doors:
2937
2164
  if door["name"] == "bonnet":
2938
- if not any(
2939
- valid_status in door["status"]
2940
- for valid_status in P.VALID_DOOR_STATUS
2941
- ):
2165
+ if not any(valid_status in door["status"] for valid_status in P.VALID_DOOR_STATUS):
2942
2166
  return None
2943
2167
  return "closed" in door["status"]
2944
2168
  return False
@@ -2946,9 +2170,7 @@ class Vehicle:
2946
2170
  @property
2947
2171
  def hood_closed_last_updated(self) -> datetime:
2948
2172
  """Return attribute last updated timestamp."""
2949
- return find_path(
2950
- self.attrs, f"{Services.ACCESS}.accessStatus.value.carCapturedTimestamp"
2951
- )
2173
+ return find_path(self.attrs, f"{Services.ACCESS}.accessStatus.value.carCapturedTimestamp")
2952
2174
 
2953
2175
  @property
2954
2176
  def is_hood_closed_supported(self) -> bool:
@@ -2962,17 +2184,15 @@ class Vehicle:
2962
2184
 
2963
2185
  @property
2964
2186
  def door_closed_left_front(self) -> bool:
2965
- """Return left front door closed state.
2187
+ """
2188
+ Return left front door closed state.
2966
2189
 
2967
2190
  :return:
2968
2191
  """
2969
2192
  doors = find_path(self.attrs, f"{Services.ACCESS}.accessStatus.value.doors")
2970
2193
  for door in doors:
2971
2194
  if door["name"] == "frontLeft":
2972
- if not any(
2973
- valid_status in door["status"]
2974
- for valid_status in P.VALID_DOOR_STATUS
2975
- ):
2195
+ if not any(valid_status in door["status"] for valid_status in P.VALID_DOOR_STATUS):
2976
2196
  return None
2977
2197
  return "closed" in door["status"]
2978
2198
  return False
@@ -2980,9 +2200,7 @@ class Vehicle:
2980
2200
  @property
2981
2201
  def door_closed_left_front_last_updated(self) -> datetime:
2982
2202
  """Return attribute last updated timestamp."""
2983
- return find_path(
2984
- self.attrs, f"{Services.ACCESS}.accessStatus.value.carCapturedTimestamp"
2985
- )
2203
+ return find_path(self.attrs, f"{Services.ACCESS}.accessStatus.value.carCapturedTimestamp")
2986
2204
 
2987
2205
  @property
2988
2206
  def is_door_closed_left_front_supported(self) -> bool:
@@ -2996,17 +2214,15 @@ class Vehicle:
2996
2214
 
2997
2215
  @property
2998
2216
  def door_closed_right_front(self) -> bool:
2999
- """Return right front door closed state.
2217
+ """
2218
+ Return right front door closed state.
3000
2219
 
3001
2220
  :return:
3002
2221
  """
3003
2222
  doors = find_path(self.attrs, f"{Services.ACCESS}.accessStatus.value.doors")
3004
2223
  for door in doors:
3005
2224
  if door["name"] == "frontRight":
3006
- if not any(
3007
- valid_status in door["status"]
3008
- for valid_status in P.VALID_DOOR_STATUS
3009
- ):
2225
+ if not any(valid_status in door["status"] for valid_status in P.VALID_DOOR_STATUS):
3010
2226
  return None
3011
2227
  return "closed" in door["status"]
3012
2228
  return False
@@ -3014,9 +2230,7 @@ class Vehicle:
3014
2230
  @property
3015
2231
  def door_closed_right_front_last_updated(self) -> datetime:
3016
2232
  """Return attribute last updated timestamp."""
3017
- return find_path(
3018
- self.attrs, f"{Services.ACCESS}.accessStatus.value.carCapturedTimestamp"
3019
- )
2233
+ return find_path(self.attrs, f"{Services.ACCESS}.accessStatus.value.carCapturedTimestamp")
3020
2234
 
3021
2235
  @property
3022
2236
  def is_door_closed_right_front_supported(self) -> bool:
@@ -3030,17 +2244,15 @@ class Vehicle:
3030
2244
 
3031
2245
  @property
3032
2246
  def door_closed_left_back(self) -> bool:
3033
- """Return left back door closed state.
2247
+ """
2248
+ Return left back door closed state.
3034
2249
 
3035
2250
  :return:
3036
2251
  """
3037
2252
  doors = find_path(self.attrs, f"{Services.ACCESS}.accessStatus.value.doors")
3038
2253
  for door in doors:
3039
2254
  if door["name"] == "rearLeft":
3040
- if not any(
3041
- valid_status in door["status"]
3042
- for valid_status in P.VALID_DOOR_STATUS
3043
- ):
2255
+ if not any(valid_status in door["status"] for valid_status in P.VALID_DOOR_STATUS):
3044
2256
  return None
3045
2257
  return "closed" in door["status"]
3046
2258
  return False
@@ -3048,9 +2260,7 @@ class Vehicle:
3048
2260
  @property
3049
2261
  def door_closed_left_back_last_updated(self) -> datetime:
3050
2262
  """Return attribute last updated timestamp."""
3051
- return find_path(
3052
- self.attrs, f"{Services.ACCESS}.accessStatus.value.carCapturedTimestamp"
3053
- )
2263
+ return find_path(self.attrs, f"{Services.ACCESS}.accessStatus.value.carCapturedTimestamp")
3054
2264
 
3055
2265
  @property
3056
2266
  def is_door_closed_left_back_supported(self) -> bool:
@@ -3064,17 +2274,15 @@ class Vehicle:
3064
2274
 
3065
2275
  @property
3066
2276
  def door_closed_right_back(self) -> bool:
3067
- """Return right back door closed state.
2277
+ """
2278
+ Return right back door closed state.
3068
2279
 
3069
2280
  :return:
3070
2281
  """
3071
2282
  doors = find_path(self.attrs, f"{Services.ACCESS}.accessStatus.value.doors")
3072
2283
  for door in doors:
3073
2284
  if door["name"] == "rearRight":
3074
- if not any(
3075
- valid_status in door["status"]
3076
- for valid_status in P.VALID_DOOR_STATUS
3077
- ):
2285
+ if not any(valid_status in door["status"] for valid_status in P.VALID_DOOR_STATUS):
3078
2286
  return None
3079
2287
  return "closed" in door["status"]
3080
2288
  return False
@@ -3082,9 +2290,7 @@ class Vehicle:
3082
2290
  @property
3083
2291
  def door_closed_right_back_last_updated(self) -> datetime:
3084
2292
  """Return attribute last updated timestamp."""
3085
- return find_path(
3086
- self.attrs, f"{Services.ACCESS}.accessStatus.value.carCapturedTimestamp"
3087
- )
2293
+ return find_path(self.attrs, f"{Services.ACCESS}.accessStatus.value.carCapturedTimestamp")
3088
2294
 
3089
2295
  @property
3090
2296
  def is_door_closed_right_back_supported(self) -> bool:
@@ -3098,7 +2304,8 @@ class Vehicle:
3098
2304
 
3099
2305
  @property
3100
2306
  def trunk_closed(self) -> bool:
3101
- """Return trunk closed state.
2307
+ """
2308
+ Return trunk closed state.
3102
2309
 
3103
2310
  :return:
3104
2311
  """
@@ -3111,9 +2318,7 @@ class Vehicle:
3111
2318
  @property
3112
2319
  def trunk_closed_last_updated(self) -> datetime:
3113
2320
  """Return attribute last updated timestamp."""
3114
- return find_path(
3115
- self.attrs, f"{Services.ACCESS}.accessStatus.value.carCapturedTimestamp"
3116
- )
2321
+ return find_path(self.attrs, f"{Services.ACCESS}.accessStatus.value.carCapturedTimestamp")
3117
2322
 
3118
2323
  @property
3119
2324
  def is_trunk_closed_supported(self) -> bool:
@@ -3145,28 +2350,20 @@ class Vehicle:
3145
2350
  def departure_timer1_last_updated(self) -> datetime:
3146
2351
  """Return last updated timestamp."""
3147
2352
  if is_valid_path(
3148
- self.attrs,
3149
- f"{Services.DEPARTURE_PROFILES}.departureProfilesStatus.value.carCapturedTimestamp",
2353
+ self.attrs, f"{Services.DEPARTURE_PROFILES}.departureProfilesStatus.value.carCapturedTimestamp"
3150
2354
  ):
3151
2355
  return find_path(
3152
- self.attrs,
3153
- f"{Services.DEPARTURE_PROFILES}.departureProfilesStatus.value.carCapturedTimestamp",
2356
+ self.attrs, f"{Services.DEPARTURE_PROFILES}.departureProfilesStatus.value.carCapturedTimestamp"
3154
2357
  )
3155
2358
  if is_valid_path(
3156
- self.attrs,
3157
- f"{Services.CLIMATISATION_TIMERS}.auxiliaryHeatingTimersStatus.value.carCapturedTimestamp",
2359
+ self.attrs, f"{Services.CLIMATISATION_TIMERS}.auxiliaryHeatingTimersStatus.value.carCapturedTimestamp"
3158
2360
  ):
3159
2361
  return find_path(
3160
- self.attrs,
3161
- f"{Services.CLIMATISATION_TIMERS}.auxiliaryHeatingTimersStatus.value.carCapturedTimestamp",
2362
+ self.attrs, f"{Services.CLIMATISATION_TIMERS}.auxiliaryHeatingTimersStatus.value.carCapturedTimestamp"
3162
2363
  )
3163
- if is_valid_path(
3164
- self.attrs,
3165
- f"{Services.DEPARTURE_TIMERS}.departureTimersStatus.value.carCapturedTimestamp",
3166
- ):
2364
+ if is_valid_path(self.attrs, f"{Services.DEPARTURE_TIMERS}.departureTimersStatus.value.carCapturedTimestamp"):
3167
2365
  return find_path(
3168
- self.attrs,
3169
- f"{Services.DEPARTURE_TIMERS}.departureTimersStatus.value.carCapturedTimestamp",
2366
+ self.attrs, f"{Services.DEPARTURE_TIMERS}.departureTimersStatus.value.carCapturedTimestamp"
3170
2367
  )
3171
2368
  return None
3172
2369
 
@@ -3213,61 +2410,40 @@ class Vehicle:
3213
2410
  if timer.get("singleTimer", None):
3214
2411
  timer_type = "single"
3215
2412
  if timer.get("singleTimer", None).get("startDateTime", None):
3216
- start_date_time = timer.get("singleTimer", None).get(
3217
- "startDateTime", None
3218
- )
2413
+ start_date_time = timer.get("singleTimer", None).get("startDateTime", None)
3219
2414
  start_time = (
3220
- start_date_time.replace(tzinfo=UTC)
3221
- .astimezone(tz=None)
3222
- .strftime("%Y-%m-%dT%H:%M:%S")
2415
+ start_date_time.replace(tzinfo=timezone.utc).astimezone(tz=None).strftime("%Y-%m-%dT%H:%M:%S")
3223
2416
  )
3224
2417
  if timer.get("singleTimer", None).get("startDateTimeLocal", None):
3225
- start_date_time = timer.get("singleTimer", None).get(
3226
- "startDateTimeLocal", None
3227
- )
3228
- if isinstance(start_date_time, str):
3229
- start_date_time = datetime.strptime(
3230
- start_date_time, "%Y-%m-%dT%H:%M:%S"
3231
- )
2418
+ start_date_time = timer.get("singleTimer", None).get("startDateTimeLocal", None)
2419
+ if type(start_date_time) is str:
2420
+ start_date_time = datetime.strptime(start_date_time, "%Y-%m-%dT%H:%M:%S")
3232
2421
  start_time = start_date_time
3233
2422
  if timer.get("singleTimer", None).get("departureDateTimeLocal", None):
3234
- start_date_time = timer.get("singleTimer", None).get(
3235
- "departureDateTimeLocal", None
3236
- )
3237
- if isinstance(start_date_time, str):
3238
- start_date_time = datetime.strptime(
3239
- start_date_time, "%Y-%m-%dT%H:%M:%S"
3240
- )
2423
+ start_date_time = timer.get("singleTimer", None).get("departureDateTimeLocal", None)
2424
+ if type(start_date_time) is str:
2425
+ start_date_time = datetime.strptime(start_date_time, "%Y-%m-%dT%H:%M:%S")
3241
2426
  start_time = start_date_time
3242
2427
  elif timer.get("recurringTimer", None):
3243
2428
  timer_type = "recurring"
3244
2429
  if timer.get("recurringTimer", None).get("startTime", None):
3245
- start_date_time = timer.get("recurringTimer", None).get(
3246
- "startTime", None
3247
- )
2430
+ start_date_time = timer.get("recurringTimer", None).get("startTime", None)
3248
2431
  start_time = (
3249
2432
  datetime.strptime(start_date_time, "%H:%M")
3250
- .replace(tzinfo=UTC)
2433
+ .replace(tzinfo=timezone.utc)
3251
2434
  .astimezone(tz=None)
3252
2435
  .strftime("%H:%M")
3253
2436
  )
3254
2437
  if timer.get("recurringTimer", None).get("startTimeLocal", None):
3255
- start_date_time = timer.get("recurringTimer", None).get(
3256
- "startTimeLocal", None
3257
- )
3258
- start_time = datetime.strptime(start_date_time, "%H:%M").strftime(
3259
- "%H:%M"
3260
- )
2438
+ start_date_time = timer.get("recurringTimer", None).get("startTimeLocal", None)
2439
+ start_time = datetime.strptime(start_date_time, "%H:%M").strftime("%H:%M")
3261
2440
  if timer.get("recurringTimer", None).get("departureTimeLocal", None):
3262
- start_date_time = timer.get("recurringTimer", None).get(
3263
- "departureTimeLocal", None
3264
- )
3265
- start_time = datetime.strptime(start_date_time, "%H:%M").strftime(
3266
- "%H:%M"
3267
- )
2441
+ start_date_time = timer.get("recurringTimer", None).get("departureTimeLocal", None)
2442
+ start_time = datetime.strptime(start_date_time, "%H:%M").strftime("%H:%M")
3268
2443
  recurring_days = timer.get("recurringTimer", None).get("recurringOn", None)
3269
- recurring_days = timer.get("recurringTimer", {}).get("recurringOn", {})
3270
- recurring_on = [day for day in recurring_days if recurring_days.get(day)]
2444
+ for day in recurring_days:
2445
+ if recurring_days.get(day) is True:
2446
+ recurring_on.append(day)
3271
2447
  data = {
3272
2448
  "timer_id": timer.get("id", None),
3273
2449
  "timer_type": timer_type,
@@ -3287,46 +2463,24 @@ class Vehicle:
3287
2463
  data["climatisation_enabled"] = timer.get("climatisation", False)
3288
2464
  if timer.get("preferredChargingTimes", None):
3289
2465
  preferred_charging_times = timer.get("preferredChargingTimes", None)[0]
3290
- data["preferred_charging_start_time"] = preferred_charging_times.get(
3291
- "startTimeLocal", None
3292
- )
3293
- data["preferred_charging_end_time"] = preferred_charging_times.get(
3294
- "endTimeLocal", None
3295
- )
2466
+ data["preferred_charging_start_time"] = preferred_charging_times.get("startTimeLocal", None)
2467
+ data["preferred_charging_end_time"] = preferred_charging_times.get("endTimeLocal", None)
3296
2468
  return data
3297
2469
 
3298
2470
  def departure_timer(self, timer_id: str | int):
3299
2471
  """Return departure timer."""
3300
- if is_valid_path(
3301
- self.attrs,
3302
- f"{Services.DEPARTURE_PROFILES}.departureProfilesStatus.value.timers",
3303
- ):
3304
- timers = find_path(
3305
- self.attrs,
3306
- f"{Services.DEPARTURE_PROFILES}.departureProfilesStatus.value.timers",
3307
- )
2472
+ if is_valid_path(self.attrs, f"{Services.DEPARTURE_PROFILES}.departureProfilesStatus.value.timers"):
2473
+ timers = find_path(self.attrs, f"{Services.DEPARTURE_PROFILES}.departureProfilesStatus.value.timers")
3308
2474
  for timer in timers:
3309
2475
  if timer.get("id", 0) == timer_id:
3310
2476
  return timer
3311
- if is_valid_path(
3312
- self.attrs,
3313
- f"{Services.CLIMATISATION_TIMERS}.auxiliaryHeatingTimersStatus.value.timers",
3314
- ):
3315
- timers = find_path(
3316
- self.attrs,
3317
- f"{Services.CLIMATISATION_TIMERS}.auxiliaryHeatingTimersStatus.value.timers",
3318
- )
2477
+ if is_valid_path(self.attrs, f"{Services.CLIMATISATION_TIMERS}.auxiliaryHeatingTimersStatus.value.timers"):
2478
+ timers = find_path(self.attrs, f"{Services.CLIMATISATION_TIMERS}.auxiliaryHeatingTimersStatus.value.timers")
3319
2479
  for timer in timers:
3320
2480
  if timer.get("id", 0) == timer_id:
3321
2481
  return timer
3322
- if is_valid_path(
3323
- self.attrs,
3324
- f"{Services.DEPARTURE_TIMERS}.departureTimersStatus.value.timers",
3325
- ):
3326
- timers = find_path(
3327
- self.attrs,
3328
- f"{Services.DEPARTURE_TIMERS}.departureTimersStatus.value.timers",
3329
- )
2482
+ if is_valid_path(self.attrs, f"{Services.DEPARTURE_TIMERS}.departureTimersStatus.value.timers"):
2483
+ timers = find_path(self.attrs, f"{Services.DEPARTURE_TIMERS}.departureTimersStatus.value.timers")
3330
2484
  for timer in timers:
3331
2485
  if timer.get("id", 0) == timer_id:
3332
2486
  return timer
@@ -3334,14 +2488,8 @@ class Vehicle:
3334
2488
 
3335
2489
  def departure_profile(self, profile_id: str | int):
3336
2490
  """Return departure profile."""
3337
- if is_valid_path(
3338
- self.attrs,
3339
- f"{Services.DEPARTURE_PROFILES}.departureProfilesStatus.value.profiles",
3340
- ):
3341
- profiles = find_path(
3342
- self.attrs,
3343
- f"{Services.DEPARTURE_PROFILES}.departureProfilesStatus.value.profiles",
3344
- )
2491
+ if is_valid_path(self.attrs, f"{Services.DEPARTURE_PROFILES}.departureProfilesStatus.value.profiles"):
2492
+ profiles = find_path(self.attrs, f"{Services.DEPARTURE_PROFILES}.departureProfilesStatus.value.profiles")
3345
2493
  for profile in profiles:
3346
2494
  if profile.get("id", 0) == profile_id:
3347
2495
  return profile
@@ -3362,8 +2510,7 @@ class Vehicle:
3362
2510
  def ac_departure_timer1_last_updated(self) -> datetime:
3363
2511
  """Return last updated timestamp."""
3364
2512
  return find_path(
3365
- self.attrs,
3366
- f"{Services.CLIMATISATION_TIMERS}.climatisationTimersStatus.value.carCapturedTimestamp",
2513
+ self.attrs, f"{Services.CLIMATISATION_TIMERS}.climatisationTimersStatus.value.carCapturedTimestamp"
3367
2514
  )
3368
2515
 
3369
2516
  @property
@@ -3391,14 +2538,8 @@ class Vehicle:
3391
2538
 
3392
2539
  def ac_departure_timer(self, timer_id: str | int):
3393
2540
  """Return ac departure timer."""
3394
- if is_valid_path(
3395
- self.attrs,
3396
- f"{Services.CLIMATISATION_TIMERS}.climatisationTimersStatus.value.timers",
3397
- ):
3398
- timers = find_path(
3399
- self.attrs,
3400
- f"{Services.CLIMATISATION_TIMERS}.climatisationTimersStatus.value.timers",
3401
- )
2541
+ if is_valid_path(self.attrs, f"{Services.CLIMATISATION_TIMERS}.climatisationTimersStatus.value.timers"):
2542
+ timers = find_path(self.attrs, f"{Services.CLIMATISATION_TIMERS}.climatisationTimersStatus.value.timers")
3402
2543
  for timer in timers:
3403
2544
  if timer.get("id", 0) == timer_id:
3404
2545
  return timer
@@ -3413,33 +2554,33 @@ class Vehicle:
3413
2554
  if timer.get("singleTimer", None):
3414
2555
  timer_type = "single"
3415
2556
  start_date_time = timer.get("singleTimer", None).get("startDateTime", None)
3416
- start_time = (
3417
- start_date_time.replace(tzinfo=UTC)
3418
- .astimezone(tz=None)
3419
- .strftime("%Y-%m-%dT%H:%M:%S")
3420
- )
2557
+ start_time = start_date_time.replace(tzinfo=timezone.utc).astimezone(tz=None).strftime("%Y-%m-%dT%H:%M:%S")
3421
2558
  elif timer.get("recurringTimer", None):
3422
2559
  timer_type = "recurring"
3423
2560
  start_date_time = timer.get("recurringTimer", None).get("startTime", None)
3424
2561
  start_time = (
3425
2562
  datetime.strptime(start_date_time, "%H:%M")
3426
- .replace(tzinfo=UTC)
2563
+ .replace(tzinfo=timezone.utc)
3427
2564
  .astimezone(tz=None)
3428
2565
  .strftime("%H:%M")
3429
2566
  )
3430
2567
  recurring_days = timer.get("recurringTimer", None).get("recurringOn", None)
3431
- recurring_on = [day for day in recurring_days if recurring_days.get(day)]
3432
- return {
2568
+ for day in recurring_days:
2569
+ if recurring_days.get(day) is True:
2570
+ recurring_on.append(day)
2571
+ data = {
3433
2572
  "timer_id": timer.get("id", None),
3434
2573
  "timer_type": timer_type,
3435
2574
  "start_time": start_time,
3436
2575
  "recurring_on": recurring_on,
3437
2576
  }
2577
+ return data
3438
2578
 
3439
2579
  # Trip data
3440
2580
  @property
3441
2581
  def trip_last_entry(self):
3442
- """Return last trip data entry.
2582
+ """
2583
+ Return last trip data entry.
3443
2584
 
3444
2585
  :return:
3445
2586
  """
@@ -3447,7 +2588,8 @@ class Vehicle:
3447
2588
 
3448
2589
  @property
3449
2590
  def trip_last_average_speed(self):
3450
- """Return last trip average speed.
2591
+ """
2592
+ Return last trip average speed.
3451
2593
 
3452
2594
  :return:
3453
2595
  """
@@ -3460,25 +2602,23 @@ class Vehicle:
3460
2602
 
3461
2603
  @property
3462
2604
  def is_trip_last_average_speed_supported(self) -> bool:
3463
- """Return true if supported.
2605
+ """
2606
+ Return true if supported.
3464
2607
 
3465
2608
  :return:
3466
2609
  """
3467
- return is_valid_path(
3468
- self.attrs, f"{Services.TRIP_LAST}.averageSpeed_kmph"
3469
- ) and type(
2610
+ return is_valid_path(self.attrs, f"{Services.TRIP_LAST}.averageSpeed_kmph") and type(
3470
2611
  find_path(self.attrs, f"{Services.TRIP_LAST}.averageSpeed_kmph")
3471
2612
  ) in (float, int)
3472
2613
 
3473
2614
  @property
3474
2615
  def trip_last_average_electric_engine_consumption(self):
3475
- """Return last trip average electric consumption.
2616
+ """
2617
+ Return last trip average electric consumption.
3476
2618
 
3477
2619
  :return:
3478
2620
  """
3479
- return float(
3480
- find_path(self.attrs, f"{Services.TRIP_LAST}.averageElectricConsumption")
3481
- )
2621
+ return float(find_path(self.attrs, f"{Services.TRIP_LAST}.averageElectricConsumption"))
3482
2622
 
3483
2623
  @property
3484
2624
  def trip_last_average_electric_engine_consumption_last_updated(self) -> datetime:
@@ -3487,25 +2627,23 @@ class Vehicle:
3487
2627
 
3488
2628
  @property
3489
2629
  def is_trip_last_average_electric_engine_consumption_supported(self) -> bool:
3490
- """Return true if supported.
2630
+ """
2631
+ Return true if supported.
3491
2632
 
3492
2633
  :return:
3493
2634
  """
3494
- return is_valid_path(
3495
- self.attrs, f"{Services.TRIP_LAST}.averageElectricConsumption"
3496
- ) and type(
2635
+ return is_valid_path(self.attrs, f"{Services.TRIP_LAST}.averageElectricConsumption") and type(
3497
2636
  find_path(self.attrs, f"{Services.TRIP_LAST}.averageElectricConsumption")
3498
2637
  ) in (float, int)
3499
2638
 
3500
2639
  @property
3501
2640
  def trip_last_average_fuel_consumption(self):
3502
- """Return last trip average fuel consumption.
2641
+ """
2642
+ Return last trip average fuel consumption.
3503
2643
 
3504
2644
  :return:
3505
2645
  """
3506
- return float(
3507
- find_path(self.attrs, f"{Services.TRIP_LAST}.averageFuelConsumption")
3508
- )
2646
+ return float(find_path(self.attrs, f"{Services.TRIP_LAST}.averageFuelConsumption"))
3509
2647
 
3510
2648
  @property
3511
2649
  def trip_last_average_fuel_consumption_last_updated(self) -> datetime:
@@ -3514,46 +2652,19 @@ class Vehicle:
3514
2652
 
3515
2653
  @property
3516
2654
  def is_trip_last_average_fuel_consumption_supported(self) -> bool:
3517
- """Return true if supported.
3518
-
3519
- :return:
3520
- """
3521
- return is_valid_path(
3522
- self.attrs, f"{Services.TRIP_LAST}.averageFuelConsumption"
3523
- ) and type(
3524
- find_path(self.attrs, f"{Services.TRIP_LAST}.averageFuelConsumption")
3525
- ) in (float, int)
3526
-
3527
- @property
3528
- def trip_last_average_gas_consumption(self):
3529
- """Return last trip average gas consumption.
3530
-
3531
- :return:
3532
2655
  """
3533
- return float(
3534
- find_path(self.attrs, f"{Services.TRIP_LAST}.averageGasConsumption")
3535
- )
3536
-
3537
- @property
3538
- def trip_last_average_gas_consumption_last_updated(self) -> datetime:
3539
- """Return last updated timestamp."""
3540
- return find_path(self.attrs, f"{Services.TRIP_LAST}.tripEndTimestamp")
3541
-
3542
- @property
3543
- def is_trip_last_average_gas_consumption_supported(self) -> bool:
3544
- """Return true if supported.
2656
+ Return true if supported.
3545
2657
 
3546
2658
  :return:
3547
2659
  """
3548
- return is_valid_path(
3549
- self.attrs, f"{Services.TRIP_LAST}.averageGasConsumption"
3550
- ) and type(
3551
- find_path(self.attrs, f"{Services.TRIP_LAST}.averageGasConsumption")
2660
+ return is_valid_path(self.attrs, f"{Services.TRIP_LAST}.averageFuelConsumption") and type(
2661
+ find_path(self.attrs, f"{Services.TRIP_LAST}.averageFuelConsumption")
3552
2662
  ) in (float, int)
3553
2663
 
3554
2664
  @property
3555
2665
  def trip_last_average_auxillary_consumption(self):
3556
- """Return last trip average auxiliary consumption.
2666
+ """
2667
+ Return last trip average auxiliary consumption.
3557
2668
 
3558
2669
  :return:
3559
2670
  """
@@ -3567,19 +2678,19 @@ class Vehicle:
3567
2678
 
3568
2679
  @property
3569
2680
  def is_trip_last_average_auxillary_consumption_supported(self) -> bool:
3570
- """Return true if supported.
2681
+ """
2682
+ Return true if supported.
3571
2683
 
3572
2684
  :return:
3573
2685
  """
3574
- return is_valid_path(
3575
- self.attrs, f"{Services.TRIP_LAST}.averageAuxiliaryConsumption"
3576
- ) and type(
2686
+ return is_valid_path(self.attrs, f"{Services.TRIP_LAST}.averageAuxiliaryConsumption") and type(
3577
2687
  find_path(self.attrs, f"{Services.TRIP_LAST}.averageAuxiliaryConsumption")
3578
2688
  ) in (float, int)
3579
2689
 
3580
2690
  @property
3581
2691
  def trip_last_average_aux_consumer_consumption(self):
3582
- """Return last trip average auxiliary consumer consumption.
2692
+ """
2693
+ Return last trip average auxiliary consumer consumption.
3583
2694
 
3584
2695
  :return:
3585
2696
  """
@@ -3593,19 +2704,19 @@ class Vehicle:
3593
2704
 
3594
2705
  @property
3595
2706
  def is_trip_last_average_aux_consumer_consumption_supported(self) -> bool:
3596
- """Return true if supported.
2707
+ """
2708
+ Return true if supported.
3597
2709
 
3598
2710
  :return:
3599
2711
  """
3600
- return is_valid_path(
3601
- self.attrs, f"{Services.TRIP_LAST}.averageAuxConsumerConsumption"
3602
- ) and type(
2712
+ return is_valid_path(self.attrs, f"{Services.TRIP_LAST}.averageAuxConsumerConsumption") and type(
3603
2713
  find_path(self.attrs, f"{Services.TRIP_LAST}.averageAuxConsumerConsumption")
3604
2714
  ) in (float, int)
3605
2715
 
3606
2716
  @property
3607
2717
  def trip_last_duration(self):
3608
- """Return last trip duration in minutes(?).
2718
+ """
2719
+ Return last trip duration in minutes(?).
3609
2720
 
3610
2721
  :return:
3611
2722
  """
@@ -3618,7 +2729,8 @@ class Vehicle:
3618
2729
 
3619
2730
  @property
3620
2731
  def is_trip_last_duration_supported(self) -> bool:
3621
- """Return true if supported.
2732
+ """
2733
+ Return true if supported.
3622
2734
 
3623
2735
  :return:
3624
2736
  """
@@ -3628,7 +2740,8 @@ class Vehicle:
3628
2740
 
3629
2741
  @property
3630
2742
  def trip_last_length(self):
3631
- """Return last trip length.
2743
+ """
2744
+ Return last trip length.
3632
2745
 
3633
2746
  :return:
3634
2747
  """
@@ -3641,7 +2754,8 @@ class Vehicle:
3641
2754
 
3642
2755
  @property
3643
2756
  def is_trip_last_length_supported(self) -> bool:
3644
- """Return true if supported.
2757
+ """
2758
+ Return true if supported.
3645
2759
 
3646
2760
  :return:
3647
2761
  """
@@ -3651,7 +2765,8 @@ class Vehicle:
3651
2765
 
3652
2766
  @property
3653
2767
  def trip_last_recuperation(self):
3654
- """Return last trip recuperation.
2768
+ """
2769
+ Return last trip recuperation.
3655
2770
 
3656
2771
  :return:
3657
2772
  """
@@ -3665,7 +2780,8 @@ class Vehicle:
3665
2780
 
3666
2781
  @property
3667
2782
  def is_trip_last_recuperation_supported(self) -> bool:
3668
- """Return true if supported.
2783
+ """
2784
+ Return true if supported.
3669
2785
 
3670
2786
  :return:
3671
2787
  """
@@ -3675,7 +2791,8 @@ class Vehicle:
3675
2791
 
3676
2792
  @property
3677
2793
  def trip_last_average_recuperation(self):
3678
- """Return last trip total recuperation.
2794
+ """
2795
+ Return last trip total recuperation.
3679
2796
 
3680
2797
  :return:
3681
2798
  """
@@ -3688,19 +2805,18 @@ class Vehicle:
3688
2805
 
3689
2806
  @property
3690
2807
  def is_trip_last_average_recuperation_supported(self) -> bool:
3691
- """Return true if supported.
2808
+ """
2809
+ Return true if supported.
3692
2810
 
3693
2811
  :return:
3694
2812
  """
3695
2813
  response = self.trip_last_entry
3696
- return response and type(response.get("averageRecuperation", None)) in (
3697
- float,
3698
- int,
3699
- )
2814
+ return response and type(response.get("averageRecuperation", None)) in (float, int)
3700
2815
 
3701
2816
  @property
3702
2817
  def trip_last_total_electric_consumption(self):
3703
- """Return last trip total electric consumption.
2818
+ """
2819
+ Return last trip total electric consumption.
3704
2820
 
3705
2821
  :return:
3706
2822
  """
@@ -3714,16 +2830,14 @@ class Vehicle:
3714
2830
 
3715
2831
  @property
3716
2832
  def is_trip_last_total_electric_consumption_supported(self) -> bool:
3717
- """Return true if supported.
2833
+ """
2834
+ Return true if supported.
3718
2835
 
3719
2836
  :return:
3720
2837
  """
3721
2838
  # Not implemented
3722
2839
  response = self.trip_last_entry
3723
- return response and type(response.get("totalElectricConsumption", None)) in (
3724
- float,
3725
- int,
3726
- )
2840
+ return response and type(response.get("totalElectricConsumption", None)) in (float, int)
3727
2841
 
3728
2842
  # Status of set data requests
3729
2843
  @property
@@ -3766,11 +2880,9 @@ class Vehicle:
3766
2880
  def request_in_progress(self) -> bool:
3767
2881
  """Check of any requests are currently in progress."""
3768
2882
  try:
3769
- return any(
3770
- isinstance(value, dict) and "id" in value and bool(value["id"])
3771
- for value in self._requests.values()
3772
- )
3773
- except Exception as e: # pylint: disable=broad-exception-caught
2883
+ for section in self._requests:
2884
+ return self._requests[section].get("id", False)
2885
+ except Exception as e:
3774
2886
  _LOGGER.warning(e)
3775
2887
  return False
3776
2888
 
@@ -3778,18 +2890,11 @@ class Vehicle:
3778
2890
  def request_in_progress_last_updated(self) -> datetime:
3779
2891
  """Return attribute last updated timestamp."""
3780
2892
  try:
3781
- # Get all timestamps in the dictionary
3782
- timestamps = [
3783
- item["timestamp"]
3784
- for item in self._requests.values()
3785
- if isinstance(item, dict) and "timestamp" in item
3786
- ]
3787
-
3788
- # Return the most recent timestamp
3789
- return max(timestamps) if timestamps else datetime.now(UTC)
3790
- except Exception as e: # pylint: disable=broad-exception-caught
2893
+ for section in self._requests:
2894
+ return self._requests[section].get("timestamp")
2895
+ except Exception as e:
3791
2896
  _LOGGER.warning(e)
3792
- return datetime.now(UTC)
2897
+ return datetime.now(timezone.utc)
3793
2898
 
3794
2899
  @property
3795
2900
  def is_request_in_progress_supported(self):
@@ -3799,18 +2904,9 @@ class Vehicle:
3799
2904
  @property
3800
2905
  def request_results(self) -> dict:
3801
2906
  """Get last request result."""
3802
- data = {
3803
- "latest": self._requests.get("latest", None),
3804
- "state": self._requests.get("state", None),
3805
- }
2907
+ data = {"latest": self._requests.get("latest", None), "state": self._requests.get("state", None)}
3806
2908
  for section in self._requests:
3807
- if section in [
3808
- "departuretimer",
3809
- "batterycharge",
3810
- "climatisation",
3811
- "refresh",
3812
- "lock",
3813
- ]:
2909
+ if section in ["departuretimer", "batterycharge", "climatisation", "refresh", "lock"]:
3814
2910
  data[section] = self._requests[section].get("status", "Unknown")
3815
2911
  return data
3816
2912
 
@@ -3818,18 +2914,10 @@ class Vehicle:
3818
2914
  def request_results_last_updated(self) -> datetime | None:
3819
2915
  """Get last updated time."""
3820
2916
  if self._requests.get("latest", "") != "":
3821
- return self._requests.get(str(self._requests.get("latest")), {}).get(
3822
- "timestamp"
3823
- )
2917
+ return self._requests.get(str(self._requests.get("latest")), {}).get("timestamp")
3824
2918
  # all requests should have more or less the same timestamp anyway, so
3825
2919
  # just return the first one
3826
- for section in [
3827
- "departuretimer",
3828
- "batterycharge",
3829
- "climatisation",
3830
- "refresh",
3831
- "lock",
3832
- ]:
2920
+ for section in ["departuretimer", "batterycharge", "climatisation", "refresh", "lock"]:
3833
2921
  if section in self._requests:
3834
2922
  return self._requests[section].get("timestamp")
3835
2923
  return None
@@ -3851,211 +2939,104 @@ class Vehicle:
3851
2939
 
3852
2940
  @property
3853
2941
  def json(self):
3854
- """Return vehicle data in JSON format.
2942
+ """
2943
+ Return vehicle data in JSON format.
3855
2944
 
3856
2945
  :return:
3857
2946
  """
3858
2947
 
3859
2948
  def serialize(obj):
3860
- """Convert datetime instances back to JSON compatible format.
2949
+ """
2950
+ Convert datetime instances back to JSON compatible format.
3861
2951
 
3862
2952
  :param obj:
3863
2953
  :return:
3864
2954
  """
3865
2955
  return obj.isoformat() if isinstance(obj, datetime) else obj
3866
2956
 
3867
- return to_json(
3868
- OrderedDict(sorted(self.attrs.items())), indent=4, default=serialize
3869
- )
2957
+ return to_json(OrderedDict(sorted(self.attrs.items())), indent=4, default=serialize)
3870
2958
 
3871
2959
  def is_primary_drive_electric(self):
3872
2960
  """Check if primary engine is electric."""
3873
2961
  return (
3874
- find_path(
3875
- self.attrs,
3876
- f"{Services.MEASUREMENTS}.fuelLevelStatus.value.primaryEngineType",
3877
- )
2962
+ find_path(self.attrs, f"{Services.MEASUREMENTS}.fuelLevelStatus.value.primaryEngineType")
3878
2963
  == ENGINE_TYPE_ELECTRIC
3879
2964
  )
3880
2965
 
3881
2966
  def is_secondary_drive_electric(self):
3882
2967
  """Check if secondary engine is electric."""
3883
2968
  return (
3884
- is_valid_path(
3885
- self.attrs,
3886
- f"{Services.MEASUREMENTS}.fuelLevelStatus.value.secondaryEngineType",
3887
- )
3888
- and find_path(
3889
- self.attrs,
3890
- f"{Services.MEASUREMENTS}.fuelLevelStatus.value.secondaryEngineType",
3891
- )
2969
+ is_valid_path(self.attrs, f"{Services.MEASUREMENTS}.fuelLevelStatus.value.primaryEngineType")
2970
+ and find_path(self.attrs, f"{Services.MEASUREMENTS}.fuelLevelStatus.value.primaryEngineType")
3892
2971
  == ENGINE_TYPE_ELECTRIC
3893
2972
  )
3894
2973
 
3895
2974
  def is_primary_drive_combustion(self):
3896
2975
  """Check if primary engine is combustion."""
3897
2976
  engine_type = ""
3898
- if is_valid_path(
3899
- self.attrs, f"{Services.FUEL_STATUS}.rangeStatus.value.primaryEngine.type"
3900
- ):
3901
- engine_type = find_path(
3902
- self.attrs,
3903
- f"{Services.FUEL_STATUS}.rangeStatus.value.primaryEngine.type",
3904
- )
2977
+ if is_valid_path(self.attrs, f"{Services.FUEL_STATUS}.rangeStatus.value.primaryEngine.type"):
2978
+ engine_type = find_path(self.attrs, f"{Services.FUEL_STATUS}.rangeStatus.value.primaryEngine.type")
3905
2979
 
3906
- if is_valid_path(
3907
- self.attrs,
3908
- f"{Services.MEASUREMENTS}.fuelLevelStatus.value.primaryEngineType",
3909
- ):
3910
- engine_type = find_path(
3911
- self.attrs,
3912
- f"{Services.MEASUREMENTS}.fuelLevelStatus.value.primaryEngineType",
3913
- )
2980
+ if is_valid_path(self.attrs, f"{Services.MEASUREMENTS}.fuelLevelStatus.value.primaryEngineType"):
2981
+ engine_type = find_path(self.attrs, f"{Services.MEASUREMENTS}.fuelLevelStatus.value.primaryEngineType")
3914
2982
 
3915
2983
  return engine_type in ENGINE_TYPE_COMBUSTION
3916
2984
 
3917
2985
  def is_secondary_drive_combustion(self):
3918
2986
  """Check if secondary engine is combustion."""
3919
2987
  engine_type = ""
3920
- if is_valid_path(
3921
- self.attrs, f"{Services.FUEL_STATUS}.rangeStatus.value.secondaryEngine.type"
3922
- ):
3923
- engine_type = find_path(
3924
- self.attrs,
3925
- f"{Services.FUEL_STATUS}.rangeStatus.value.secondaryEngine.type",
3926
- )
2988
+ if is_valid_path(self.attrs, f"{Services.FUEL_STATUS}.rangeStatus.value.secondaryEngine.type"):
2989
+ engine_type = find_path(self.attrs, f"{Services.FUEL_STATUS}.rangeStatus.value.secondaryEngine.type")
3927
2990
 
3928
- if is_valid_path(
3929
- self.attrs,
3930
- f"{Services.MEASUREMENTS}.fuelLevelStatus.value.secondaryEngineType",
3931
- ):
3932
- engine_type = find_path(
3933
- self.attrs,
3934
- f"{Services.MEASUREMENTS}.fuelLevelStatus.value.secondaryEngineType",
3935
- )
2991
+ if is_valid_path(self.attrs, f"{Services.MEASUREMENTS}.fuelLevelStatus.value.secondaryEngineType"):
2992
+ engine_type = find_path(self.attrs, f"{Services.MEASUREMENTS}.fuelLevelStatus.value.secondaryEngineType")
3936
2993
 
3937
2994
  return engine_type in ENGINE_TYPE_COMBUSTION
3938
2995
 
3939
- def is_primary_drive_gas(self):
3940
- """Check if primary engine is gas."""
3941
- if is_valid_path(
3942
- self.attrs, f"{Services.FUEL_STATUS}.rangeStatus.value.carType"
3943
- ):
3944
- return (
3945
- find_path(
3946
- self.attrs, f"{Services.FUEL_STATUS}.rangeStatus.value.carType"
3947
- )
3948
- == ENGINE_TYPE_GAS
3949
- )
3950
- if is_valid_path(
3951
- self.attrs, f"{Services.MEASUREMENTS}.fuelLevelStatus.value.carType"
3952
- ):
3953
- return (
3954
- find_path(
3955
- self.attrs, f"{Services.MEASUREMENTS}.fuelLevelStatus.value.carType"
3956
- )
3957
- == ENGINE_TYPE_GAS
3958
- )
3959
- return False
3960
-
3961
2996
  @property
3962
2997
  def is_car_type_electric(self):
3963
2998
  """Check if car type is electric."""
3964
- if is_valid_path(
3965
- self.attrs, f"{Services.FUEL_STATUS}.rangeStatus.value.carType"
3966
- ):
3967
- return (
3968
- find_path(
3969
- self.attrs, f"{Services.FUEL_STATUS}.rangeStatus.value.carType"
3970
- )
3971
- == ENGINE_TYPE_ELECTRIC
3972
- )
3973
- if is_valid_path(
3974
- self.attrs, f"{Services.MEASUREMENTS}.fuelLevelStatus.value.carType"
3975
- ):
2999
+ if is_valid_path(self.attrs, f"{Services.FUEL_STATUS}.rangeStatus.value.carType"):
3000
+ return find_path(self.attrs, f"{Services.FUEL_STATUS}.rangeStatus.value.carType") == ENGINE_TYPE_ELECTRIC
3001
+ if is_valid_path(self.attrs, f"{Services.MEASUREMENTS}.fuelLevelStatus.value.carType"):
3976
3002
  return (
3977
- find_path(
3978
- self.attrs, f"{Services.MEASUREMENTS}.fuelLevelStatus.value.carType"
3979
- )
3980
- == ENGINE_TYPE_ELECTRIC
3003
+ find_path(self.attrs, f"{Services.MEASUREMENTS}.fuelLevelStatus.value.carType") == ENGINE_TYPE_ELECTRIC
3981
3004
  )
3982
3005
  return False
3983
3006
 
3984
3007
  @property
3985
3008
  def is_car_type_diesel(self):
3986
3009
  """Check if car type is diesel."""
3987
- if is_valid_path(
3988
- self.attrs, f"{Services.FUEL_STATUS}.rangeStatus.value.carType"
3989
- ):
3990
- return (
3991
- find_path(
3992
- self.attrs, f"{Services.FUEL_STATUS}.rangeStatus.value.carType"
3993
- )
3994
- == ENGINE_TYPE_DIESEL
3995
- )
3996
- if is_valid_path(
3997
- self.attrs, f"{Services.MEASUREMENTS}.fuelLevelStatus.value.carType"
3998
- ):
3999
- return (
4000
- find_path(
4001
- self.attrs, f"{Services.MEASUREMENTS}.fuelLevelStatus.value.carType"
4002
- )
4003
- == ENGINE_TYPE_DIESEL
4004
- )
3010
+ if is_valid_path(self.attrs, f"{Services.FUEL_STATUS}.rangeStatus.value.carType"):
3011
+ return find_path(self.attrs, f"{Services.FUEL_STATUS}.rangeStatus.value.carType") == ENGINE_TYPE_DIESEL
3012
+ if is_valid_path(self.attrs, f"{Services.MEASUREMENTS}.fuelLevelStatus.value.carType"):
3013
+ return find_path(self.attrs, f"{Services.MEASUREMENTS}.fuelLevelStatus.value.carType") == ENGINE_TYPE_DIESEL
4005
3014
  return False
4006
3015
 
4007
3016
  @property
4008
3017
  def is_car_type_gasoline(self):
4009
3018
  """Check if car type is gasoline."""
4010
- if is_valid_path(
4011
- self.attrs, f"{Services.FUEL_STATUS}.rangeStatus.value.carType"
4012
- ):
4013
- return (
4014
- find_path(
4015
- self.attrs, f"{Services.FUEL_STATUS}.rangeStatus.value.carType"
4016
- )
4017
- == ENGINE_TYPE_GASOLINE
4018
- )
4019
- if is_valid_path(
4020
- self.attrs, f"{Services.MEASUREMENTS}.fuelLevelStatus.value.carType"
4021
- ):
3019
+ if is_valid_path(self.attrs, f"{Services.FUEL_STATUS}.rangeStatus.value.carType"):
3020
+ return find_path(self.attrs, f"{Services.FUEL_STATUS}.rangeStatus.value.carType") == ENGINE_TYPE_GASOLINE
3021
+ if is_valid_path(self.attrs, f"{Services.MEASUREMENTS}.fuelLevelStatus.value.carType"):
4022
3022
  return (
4023
- find_path(
4024
- self.attrs, f"{Services.MEASUREMENTS}.fuelLevelStatus.value.carType"
4025
- )
4026
- == ENGINE_TYPE_GASOLINE
3023
+ find_path(self.attrs, f"{Services.MEASUREMENTS}.fuelLevelStatus.value.carType") == ENGINE_TYPE_GASOLINE
4027
3024
  )
4028
3025
  return False
4029
3026
 
4030
3027
  @property
4031
3028
  def is_car_type_hybrid(self):
4032
3029
  """Check if car type is hybrid."""
4033
- if is_valid_path(
4034
- self.attrs, f"{Services.FUEL_STATUS}.rangeStatus.value.carType"
4035
- ):
4036
- return (
4037
- find_path(
4038
- self.attrs, f"{Services.FUEL_STATUS}.rangeStatus.value.carType"
4039
- )
4040
- == ENGINE_TYPE_HYBRID
4041
- )
4042
- if is_valid_path(
4043
- self.attrs, f"{Services.MEASUREMENTS}.fuelLevelStatus.value.carType"
4044
- ):
4045
- return (
4046
- find_path(
4047
- self.attrs, f"{Services.MEASUREMENTS}.fuelLevelStatus.value.carType"
4048
- )
4049
- == ENGINE_TYPE_HYBRID
4050
- )
3030
+ if is_valid_path(self.attrs, f"{Services.FUEL_STATUS}.rangeStatus.value.carType"):
3031
+ return find_path(self.attrs, f"{Services.FUEL_STATUS}.rangeStatus.value.carType") == ENGINE_TYPE_HYBRID
3032
+ if is_valid_path(self.attrs, f"{Services.MEASUREMENTS}.fuelLevelStatus.value.carType"):
3033
+ return find_path(self.attrs, f"{Services.MEASUREMENTS}.fuelLevelStatus.value.carType") == ENGINE_TYPE_HYBRID
4051
3034
  return False
4052
3035
 
4053
3036
  @property
4054
3037
  def has_combustion_engine(self):
4055
3038
  """Return true if car has a combustion engine."""
4056
- return (
4057
- self.is_primary_drive_combustion() or self.is_secondary_drive_combustion()
4058
- )
3039
+ return self.is_primary_drive_combustion() or self.is_secondary_drive_combustion()
4059
3040
 
4060
3041
  @property
4061
3042
  def api_vehicles_status(self) -> bool:
@@ -4065,7 +3046,7 @@ class Vehicle:
4065
3046
  @property
4066
3047
  def api_vehicles_status_last_updated(self) -> datetime:
4067
3048
  """Return attribute last updated timestamp."""
4068
- return datetime.now(UTC)
3049
+ return datetime.now(timezone.utc)
4069
3050
 
4070
3051
  @property
4071
3052
  def is_api_vehicles_status_supported(self):
@@ -4075,14 +3056,12 @@ class Vehicle:
4075
3056
  @property
4076
3057
  def api_capabilities_status(self) -> bool:
4077
3058
  """Check capabilities API status."""
4078
- return self.attrs.get(Services.SERVICE_STATUS, {}).get(
4079
- "capabilities", "Unknown"
4080
- )
3059
+ return self.attrs.get(Services.SERVICE_STATUS, {}).get("capabilities", "Unknown")
4081
3060
 
4082
3061
  @property
4083
3062
  def api_capabilities_status_last_updated(self) -> datetime:
4084
3063
  """Return attribute last updated timestamp."""
4085
- return datetime.now(UTC)
3064
+ return datetime.now(timezone.utc)
4086
3065
 
4087
3066
  @property
4088
3067
  def is_api_capabilities_status_supported(self):
@@ -4097,7 +3076,7 @@ class Vehicle:
4097
3076
  @property
4098
3077
  def api_trips_status_last_updated(self) -> datetime:
4099
3078
  """Return attribute last updated timestamp."""
4100
- return datetime.now(UTC)
3079
+ return datetime.now(timezone.utc)
4101
3080
 
4102
3081
  @property
4103
3082
  def is_api_trips_status_supported(self):
@@ -4109,14 +3088,12 @@ class Vehicle:
4109
3088
  @property
4110
3089
  def api_selectivestatus_status(self) -> bool:
4111
3090
  """Check selectivestatus API status."""
4112
- return self.attrs.get(Services.SERVICE_STATUS, {}).get(
4113
- "selectivestatus", "Unknown"
4114
- )
3091
+ return self.attrs.get(Services.SERVICE_STATUS, {}).get("selectivestatus", "Unknown")
4115
3092
 
4116
3093
  @property
4117
3094
  def api_selectivestatus_status_last_updated(self) -> datetime:
4118
3095
  """Return attribute last updated timestamp."""
4119
- return datetime.now(UTC)
3096
+ return datetime.now(timezone.utc)
4120
3097
 
4121
3098
  @property
4122
3099
  def is_api_selectivestatus_status_supported(self):
@@ -4126,14 +3103,12 @@ class Vehicle:
4126
3103
  @property
4127
3104
  def api_parkingposition_status(self) -> bool:
4128
3105
  """Check parkingposition API status."""
4129
- return self.attrs.get(Services.SERVICE_STATUS, {}).get(
4130
- "parkingposition", "Unknown"
4131
- )
3106
+ return self.attrs.get(Services.SERVICE_STATUS, {}).get("parkingposition", "Unknown")
4132
3107
 
4133
3108
  @property
4134
3109
  def api_parkingposition_status_last_updated(self) -> datetime:
4135
3110
  """Return attribute last updated timestamp."""
4136
- return datetime.now(UTC)
3111
+ return datetime.now(timezone.utc)
4137
3112
 
4138
3113
  @property
4139
3114
  def is_api_parkingposition_status_supported(self):
@@ -4150,7 +3125,7 @@ class Vehicle:
4150
3125
  @property
4151
3126
  def api_token_status_last_updated(self) -> datetime:
4152
3127
  """Return attribute last updated timestamp."""
4153
- return datetime.now(UTC)
3128
+ return datetime.now(timezone.utc)
4154
3129
 
4155
3130
  @property
4156
3131
  def is_api_token_status_supported(self):
@@ -4168,7 +3143,7 @@ class Vehicle:
4168
3143
  @property
4169
3144
  def last_data_refresh_last_updated(self) -> datetime:
4170
3145
  """Return attribute last updated timestamp."""
4171
- return datetime.now(UTC)
3146
+ return datetime.now(timezone.utc)
4172
3147
 
4173
3148
  @property
4174
3149
  def is_last_data_refresh_supported(self):