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