carconnectivity-connector-skoda 0.4a4__tar.gz → 0.4a6__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.

Potentially problematic release.


This version of carconnectivity-connector-skoda might be problematic. Click here for more details.

Files changed (41) hide show
  1. {carconnectivity_connector_skoda-0.4a4 → carconnectivity_connector_skoda-0.4a6}/PKG-INFO +2 -2
  2. {carconnectivity_connector_skoda-0.4a4 → carconnectivity_connector_skoda-0.4a6}/pyproject.toml +1 -1
  3. {carconnectivity_connector_skoda-0.4a4 → carconnectivity_connector_skoda-0.4a6}/src/carconnectivity_connector_skoda.egg-info/PKG-INFO +2 -2
  4. {carconnectivity_connector_skoda-0.4a4 → carconnectivity_connector_skoda-0.4a6}/src/carconnectivity_connector_skoda.egg-info/requires.txt +1 -1
  5. {carconnectivity_connector_skoda-0.4a4 → carconnectivity_connector_skoda-0.4a6}/src/carconnectivity_connectors/skoda/_version.py +1 -1
  6. {carconnectivity_connector_skoda-0.4a4 → carconnectivity_connector_skoda-0.4a6}/src/carconnectivity_connectors/skoda/command_impl.py +4 -2
  7. {carconnectivity_connector_skoda-0.4a4 → carconnectivity_connector_skoda-0.4a6}/src/carconnectivity_connectors/skoda/connector.py +28 -10
  8. {carconnectivity_connector_skoda-0.4a4 → carconnectivity_connector_skoda-0.4a6}/src/carconnectivity_connectors/skoda/mqtt_client.py +7 -1
  9. {carconnectivity_connector_skoda-0.4a4 → carconnectivity_connector_skoda-0.4a6}/.flake8 +0 -0
  10. {carconnectivity_connector_skoda-0.4a4 → carconnectivity_connector_skoda-0.4a6}/.github/ISSUE_TEMPLATE/bug_report.md +0 -0
  11. {carconnectivity_connector_skoda-0.4a4 → carconnectivity_connector_skoda-0.4a6}/.github/ISSUE_TEMPLATE/feature_request.md +0 -0
  12. {carconnectivity_connector_skoda-0.4a4 → carconnectivity_connector_skoda-0.4a6}/.github/dependabot.yml +0 -0
  13. {carconnectivity_connector_skoda-0.4a4 → carconnectivity_connector_skoda-0.4a6}/.github/workflows/build.yml +0 -0
  14. {carconnectivity_connector_skoda-0.4a4 → carconnectivity_connector_skoda-0.4a6}/.github/workflows/build_and_publish.yml +0 -0
  15. {carconnectivity_connector_skoda-0.4a4 → carconnectivity_connector_skoda-0.4a6}/.github/workflows/codeql-analysis.yml +0 -0
  16. {carconnectivity_connector_skoda-0.4a4 → carconnectivity_connector_skoda-0.4a6}/.gitignore +0 -0
  17. {carconnectivity_connector_skoda-0.4a4 → carconnectivity_connector_skoda-0.4a6}/CHANGELOG.md +0 -0
  18. {carconnectivity_connector_skoda-0.4a4 → carconnectivity_connector_skoda-0.4a6}/LICENSE +0 -0
  19. {carconnectivity_connector_skoda-0.4a4 → carconnectivity_connector_skoda-0.4a6}/Makefile +0 -0
  20. {carconnectivity_connector_skoda-0.4a4 → carconnectivity_connector_skoda-0.4a6}/README.md +0 -0
  21. {carconnectivity_connector_skoda-0.4a4 → carconnectivity_connector_skoda-0.4a6}/doc/Config.md +0 -0
  22. {carconnectivity_connector_skoda-0.4a4 → carconnectivity_connector_skoda-0.4a6}/setup.cfg +0 -0
  23. {carconnectivity_connector_skoda-0.4a4 → carconnectivity_connector_skoda-0.4a6}/setup_requirements.txt +0 -0
  24. {carconnectivity_connector_skoda-0.4a4 → carconnectivity_connector_skoda-0.4a6}/src/carconnectivity_connector_skoda.egg-info/SOURCES.txt +0 -0
  25. {carconnectivity_connector_skoda-0.4a4 → carconnectivity_connector_skoda-0.4a6}/src/carconnectivity_connector_skoda.egg-info/dependency_links.txt +0 -0
  26. {carconnectivity_connector_skoda-0.4a4 → carconnectivity_connector_skoda-0.4a6}/src/carconnectivity_connector_skoda.egg-info/top_level.txt +0 -0
  27. {carconnectivity_connector_skoda-0.4a4 → carconnectivity_connector_skoda-0.4a6}/src/carconnectivity_connectors/skoda/__init__.py +0 -0
  28. {carconnectivity_connector_skoda-0.4a4 → carconnectivity_connector_skoda-0.4a6}/src/carconnectivity_connectors/skoda/auth/__init__.py +0 -0
  29. {carconnectivity_connector_skoda-0.4a4 → carconnectivity_connector_skoda-0.4a6}/src/carconnectivity_connectors/skoda/auth/auth_util.py +0 -0
  30. {carconnectivity_connector_skoda-0.4a4 → carconnectivity_connector_skoda-0.4a6}/src/carconnectivity_connectors/skoda/auth/helpers/blacklist_retry.py +0 -0
  31. {carconnectivity_connector_skoda-0.4a4 → carconnectivity_connector_skoda-0.4a6}/src/carconnectivity_connectors/skoda/auth/my_skoda_session.py +0 -0
  32. {carconnectivity_connector_skoda-0.4a4 → carconnectivity_connector_skoda-0.4a6}/src/carconnectivity_connectors/skoda/auth/openid_session.py +0 -0
  33. {carconnectivity_connector_skoda-0.4a4 → carconnectivity_connector_skoda-0.4a6}/src/carconnectivity_connectors/skoda/auth/session_manager.py +0 -0
  34. {carconnectivity_connector_skoda-0.4a4 → carconnectivity_connector_skoda-0.4a6}/src/carconnectivity_connectors/skoda/auth/skoda_web_session.py +0 -0
  35. {carconnectivity_connector_skoda-0.4a4 → carconnectivity_connector_skoda-0.4a6}/src/carconnectivity_connectors/skoda/capability.py +0 -0
  36. {carconnectivity_connector_skoda-0.4a4 → carconnectivity_connector_skoda-0.4a6}/src/carconnectivity_connectors/skoda/charging.py +0 -0
  37. {carconnectivity_connector_skoda-0.4a4 → carconnectivity_connector_skoda-0.4a6}/src/carconnectivity_connectors/skoda/climatization.py +0 -0
  38. {carconnectivity_connector_skoda-0.4a4 → carconnectivity_connector_skoda-0.4a6}/src/carconnectivity_connectors/skoda/error.py +0 -0
  39. {carconnectivity_connector_skoda-0.4a4 → carconnectivity_connector_skoda-0.4a6}/src/carconnectivity_connectors/skoda/ui/connector_ui.py +0 -0
  40. {carconnectivity_connector_skoda-0.4a4 → carconnectivity_connector_skoda-0.4a6}/src/carconnectivity_connectors/skoda/vehicle.py +0 -0
  41. {carconnectivity_connector_skoda-0.4a4 → carconnectivity_connector_skoda-0.4a6}/test/integration_test/carConnectivity.json +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.2
2
2
  Name: carconnectivity-connector-skoda
3
- Version: 0.4a4
3
+ Version: 0.4a6
4
4
  Summary: CarConnectivity connector for Skoda services
5
5
  Author: Till Steinbach
6
6
  License: MIT License
@@ -37,7 +37,7 @@ Classifier: Topic :: Software Development :: Libraries
37
37
  Requires-Python: >=3.8
38
38
  Description-Content-Type: text/markdown
39
39
  License-File: LICENSE
40
- Requires-Dist: carconnectivity>=0.4a6
40
+ Requires-Dist: carconnectivity>=0.4a10
41
41
  Requires-Dist: oauthlib~=3.2.2
42
42
  Requires-Dist: requests~=2.32.3
43
43
  Requires-Dist: jwt~=1.3.1
@@ -14,7 +14,7 @@ authors = [
14
14
  { name = "Till Steinbach" }
15
15
  ]
16
16
  dependencies = [
17
- "carconnectivity>=0.4a6",
17
+ "carconnectivity>=0.4a10",
18
18
  "oauthlib~=3.2.2",
19
19
  "requests~=2.32.3",
20
20
  "jwt~=1.3.1",
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.2
2
2
  Name: carconnectivity-connector-skoda
3
- Version: 0.4a4
3
+ Version: 0.4a6
4
4
  Summary: CarConnectivity connector for Skoda services
5
5
  Author: Till Steinbach
6
6
  License: MIT License
@@ -37,7 +37,7 @@ Classifier: Topic :: Software Development :: Libraries
37
37
  Requires-Python: >=3.8
38
38
  Description-Content-Type: text/markdown
39
39
  License-File: LICENSE
40
- Requires-Dist: carconnectivity>=0.4a6
40
+ Requires-Dist: carconnectivity>=0.4a10
41
41
  Requires-Dist: oauthlib~=3.2.2
42
42
  Requires-Dist: requests~=2.32.3
43
43
  Requires-Dist: jwt~=1.3.1
@@ -1,4 +1,4 @@
1
- carconnectivity>=0.4a6
1
+ carconnectivity>=0.4a10
2
2
  oauthlib~=3.2.2
3
3
  requests~=2.32.3
4
4
  jwt~=1.3.1
@@ -17,5 +17,5 @@ __version__: str
17
17
  __version_tuple__: VERSION_TUPLE
18
18
  version_tuple: VERSION_TUPLE
19
19
 
20
- __version__ = version = '0.4a4'
20
+ __version__ = version = '0.4a6'
21
21
  __version_tuple__ = version_tuple = (0, 4)
@@ -31,6 +31,8 @@ class SpinCommand(GenericCommand):
31
31
 
32
32
  @value.setter
33
33
  def value(self, new_value: Optional[Union[str, Dict]]) -> None:
34
+ # Execute early hooks before parsing the value
35
+ new_value = self._execute_on_set_hook(new_value, early_hook=True)
34
36
  if isinstance(new_value, str):
35
37
  parser = ThrowingArgumentParser(prog='', add_help=False, exit_on_error=False)
36
38
  parser.add_argument('command', help='Command to execute', type=SpinCommand.Command,
@@ -55,8 +57,8 @@ class SpinCommand(GenericCommand):
55
57
  raise ValueError('Invalid value for SpinCommand. '
56
58
  f'Command must be one of {SpinCommand.Command}')
57
59
  if self._is_changeable:
58
- for hook in self._on_set_hooks:
59
- new_value = hook(self, new_value)
60
+ # Execute late hooks before setting the value
61
+ new_value = self._execute_on_set_hook(new_value, early_hook=False)
60
62
  self._set_value(new_value)
61
63
  else:
62
64
  raise TypeError('You cannot set this attribute. Attribute is not mutable.')
@@ -4,6 +4,7 @@ from typing import TYPE_CHECKING
4
4
 
5
5
  import threading
6
6
  import os
7
+ import traceback
7
8
  import logging
8
9
  import netrc
9
10
  from datetime import datetime, timedelta, timezone
@@ -72,6 +73,7 @@ class Connector(BaseConnector):
72
73
  """
73
74
  def __init__(self, connector_id: str, car_connectivity: CarConnectivity, config: Dict) -> None:
74
75
  BaseConnector.__init__(self, connector_id=connector_id, car_connectivity=car_connectivity, config=config, log=LOG, api_log=LOG_API)
76
+ self._healthy = False
75
77
 
76
78
  self._mqtt_client: SkodaMQTTClient = SkodaMQTTClient(skoda_connector=self)
77
79
 
@@ -81,15 +83,8 @@ class Connector(BaseConnector):
81
83
 
82
84
  self.connected: BooleanAttribute = BooleanAttribute(name="connected", parent=self, tags={'connector_custom'})
83
85
  self.interval: DurationAttribute = DurationAttribute(name="interval", parent=self, tags={'connector_custom'})
84
-
85
- def __check_interval(attribute: GenericAttribute, value: Any) -> Any:
86
- del attribute
87
- if value is not None and value < timedelta(seconds=180):
88
- raise ValueError('Intervall must be at least 180 seconds')
89
- return value
90
-
86
+ self.interval.minimum = timedelta(seconds=180)
91
87
  self.interval._is_changeable = True # pylint: disable=protected-access
92
- self.interval._add_on_set_hook(__check_interval) # pylint: disable=protected-access
93
88
 
94
89
  self.commands: Commands = Commands(parent=self)
95
90
 
@@ -172,6 +167,7 @@ class Connector(BaseConnector):
172
167
  self._background_connect_thread.start()
173
168
  # Start MQTT thread
174
169
  self._mqtt_client.loop_start()
170
+ self._healthy = True
175
171
 
176
172
  def _background_connect_loop(self) -> None:
177
173
  while not self._stop_event.is_set():
@@ -216,6 +212,10 @@ class Connector(BaseConnector):
216
212
  except TemporaryAuthenticationError as err:
217
213
  LOG.error('Temporary authentification error during update (%s). Will try again after configured interval of %ss', str(err), interval)
218
214
  self._stop_event.wait(interval)
215
+ except Exception as err:
216
+ LOG.critical('Critical error during update: %s', traceback.format_exc())
217
+ self._healthy = False
218
+ raise err
219
219
  else:
220
220
  self._stop_event.wait(interval)
221
221
 
@@ -362,6 +362,7 @@ class Connector(BaseConnector):
362
362
  if vehicle_to_update.capabilities.has_capability('VEHICLE_HEALTH_INSPECTION'):
363
363
  vehicle_to_update = self.fetch_maintenance(vehicle_to_update)
364
364
  vehicle_to_update = self.decide_state(vehicle_to_update)
365
+ self.car_connectivity.transaction_end()
365
366
 
366
367
  def decide_state(self, vehicle: SkodaVehicle) -> SkodaVehicle:
367
368
  """
@@ -786,12 +787,19 @@ class Connector(BaseConnector):
786
787
  # pylint: disable-next=protected-access
787
788
  vehicle.climatization.settings.target_temperature._add_on_set_hook(self.__on_air_conditioning_target_temperature_change)
788
789
  vehicle.climatization.settings.target_temperature._is_changeable = True # pylint: disable=protected-access
790
+ precision: float = 0.5
791
+ min_temperature: Optional[float] = None
792
+ max_temperature: Optional[float] = None
789
793
  unit: Temperature = Temperature.UNKNOWN
790
794
  if 'unitInCar' in data['targetTemperature'] and data['targetTemperature']['unitInCar'] is not None:
791
795
  if data['targetTemperature']['unitInCar'] == 'CELSIUS':
792
796
  unit = Temperature.C
797
+ min_temperature: Optional[float] = 16
798
+ max_temperature: Optional[float] = 29.5
793
799
  elif data['targetTemperature']['unitInCar'] == 'FAHRENHEIT':
794
800
  unit = Temperature.F
801
+ min_temperature: Optional[float] = 61
802
+ max_temperature: Optional[float] = 85
795
803
  elif data['targetTemperature']['unitInCar'] == 'KELVIN':
796
804
  unit = Temperature.K
797
805
  else:
@@ -801,6 +809,10 @@ class Connector(BaseConnector):
801
809
  vehicle.climatization.settings.target_temperature._set_value(value=data['targetTemperature']['temperatureValue'],
802
810
  measured=captured_at,
803
811
  unit=unit)
812
+ vehicle.climatization.settings.target_temperature.precision = precision
813
+ vehicle.climatization.settings.target_temperature.minimum = min_temperature
814
+ vehicle.climatization.settings.target_temperature.maximum = max_temperature
815
+
804
816
  else:
805
817
  # pylint: disable-next=protected-access
806
818
  vehicle.climatization.settings.target_temperature._set_value(value=None, measured=captured_at, unit=unit)
@@ -1498,9 +1510,10 @@ class Connector(BaseConnector):
1498
1510
  if command_arguments['command'] == ClimatizationStartStopCommand.Command.START:
1499
1511
  command_dict['heaterSource'] = 'ELECTRIC'
1500
1512
  command_dict['targetTemperature'] = {}
1513
+ precision: float = 0.5
1501
1514
  if 'target_temperature' in command_arguments:
1502
1515
  # Round target temperature to nearest 0.5
1503
- command_dict['targetTemperature']['temperatureValue'] = round(command_arguments['target_temperature'] * 2) / 2
1516
+ command_dict['targetTemperature']['temperatureValue'] = round(command_arguments['target_temperature'] / precision) * precision
1504
1517
  if 'target_temperature_unit' in command_arguments:
1505
1518
  if not isinstance(command_arguments['target_temperature_unit'], Temperature):
1506
1519
  raise CommandError('Temperature unit is not of type Temperature')
@@ -1518,8 +1531,10 @@ class Connector(BaseConnector):
1518
1531
  and isinstance(climatization, Climatization) and climatization.settings is not None \
1519
1532
  and climatization.settings.target_temperature is not None and climatization.settings.target_temperature.enabled \
1520
1533
  and climatization.settings.target_temperature.value is not None: # pylint: disable=too-many-boolean-expressions
1534
+ if climatization.settings.target_temperature.precision is not None:
1535
+ precision = climatization.settings.target_temperature.precision
1521
1536
  # Round target temperature to nearest 0.5
1522
- command_dict['targetTemperature']['temperatureValue'] = round(climatization.settings.target_temperature.value * 2) / 2
1537
+ command_dict['targetTemperature']['temperatureValue'] = round(climatization.settings.target_temperature.value / precision) * precision
1523
1538
  if climatization.settings.target_temperature.unit == Temperature.C:
1524
1539
  command_dict['targetTemperature']['unitInCar'] = 'CELSIUS'
1525
1540
  elif climatization.settings.target_temperature.unit == Temperature.F:
@@ -1751,3 +1766,6 @@ class Connector(BaseConnector):
1751
1766
  except requests.exceptions.RetryError as retry_error:
1752
1767
  raise CommandError(f'Retrying failed: {retry_error}') from retry_error
1753
1768
  return command_arguments
1769
+
1770
+ def is_healthy(self) -> bool:
1771
+ return self._healthy and super().is_healthy()
@@ -469,7 +469,7 @@ class SkodaMQTTClient(Client): # pylint: disable=too-many-instance-attributes
469
469
  if 'data' in data and data['data'] is not None:
470
470
  vehicle: Optional[GenericVehicle] = self._skoda_connector.car_connectivity.garage.get_vehicle(vin)
471
471
  if isinstance(vehicle, SkodaElectricVehicle):
472
- electric_drive: ElectricDrive = vehicle.get_electric_drive()
472
+ electric_drive: Optional[ElectricDrive] = vehicle.get_electric_drive()
473
473
  if electric_drive is not None:
474
474
  charging_state: Optional[Charging.ChargingState] = vehicle.charging.state.value
475
475
  old_charging_state: Optional[Charging.ChargingState] = charging_state
@@ -509,6 +509,7 @@ class SkodaMQTTClient(Client): # pylint: disable=too-many-instance-attributes
509
509
  if old_charging_state != charging_state:
510
510
  try:
511
511
  self._skoda_connector.fetch_charging(vehicle, no_cache=True)
512
+ self._skoda_connector.car_connectivity.transaction_end()
512
513
  except CarConnectivityError as e:
513
514
  LOG.error('Error while fetching charging: %s', e)
514
515
  if 'timeToFinish' in data['data'] and data['data']['timeToFinish'] is not None \
@@ -536,6 +537,7 @@ class SkodaMQTTClient(Client): # pylint: disable=too-many-instance-attributes
536
537
  if isinstance(vehicle, SkodaVehicle):
537
538
  try:
538
539
  self._skoda_connector.fetch_air_conditioning(vehicle, no_cache=True)
540
+ self._skoda_connector.car_connectivity.transaction_end()
539
541
  except CarConnectivityError as e:
540
542
  LOG.error('Error while fetching air conditioning: %s', e)
541
543
  elif 'name' in data and data['name'] == 'climatisation-completed':
@@ -582,6 +584,7 @@ class SkodaMQTTClient(Client): # pylint: disable=too-many-instance-attributes
582
584
  self._skoda_connector.fetch_air_conditioning(vehicle, no_cache=True)
583
585
  except CarConnectivityError as e:
584
586
  LOG.error('Error while fetching air conditioning: %s', e)
587
+ self._skoda_connector.car_connectivity.transaction_end()
585
588
 
586
589
  if vin in self.delayed_access_function_timers:
587
590
  self.delayed_access_function_timers[vin].cancel()
@@ -598,6 +601,7 @@ class SkodaMQTTClient(Client): # pylint: disable=too-many-instance-attributes
598
601
  if isinstance(vehicle, SkodaVehicle):
599
602
  try:
600
603
  self._skoda_connector.fetch_vehicle_status(vehicle, no_cache=True)
604
+ self._skoda_connector.car_connectivity.transaction_end()
601
605
  except CarConnectivityError as e:
602
606
  LOG.error('Error while fetching vehicle status: %s', e)
603
607
 
@@ -629,6 +633,7 @@ class SkodaMQTTClient(Client): # pylint: disable=too-many-instance-attributes
629
633
  LOG.debug('Received %s operation request for vehicle %s from user %s', operation_request, vin, user_id)
630
634
  try:
631
635
  self._skoda_connector.fetch_air_conditioning(vehicle, no_cache=True)
636
+ self._skoda_connector.car_connectivity.transaction_end()
632
637
  except CarConnectivityError as e:
633
638
  LOG.error('Error while fetching air-conditioning: %s', e)
634
639
  return
@@ -649,6 +654,7 @@ class SkodaMQTTClient(Client): # pylint: disable=too-many-instance-attributes
649
654
  LOG.debug('Received %s operation request for vehicle %s from user %s', operation_request, vin, user_id)
650
655
  try:
651
656
  self._skoda_connector.fetch_charging(vehicle, no_cache=True)
657
+ self._skoda_connector.car_connectivity.transaction_end()
652
658
  except CarConnectivityError as e:
653
659
  LOG.error('Error while fetching charging: %s', e)
654
660
  return