carconnectivity-connector-skoda 0.4a3__tar.gz → 0.4a4__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.4a3 → carconnectivity_connector_skoda-0.4a4}/PKG-INFO +2 -2
  2. {carconnectivity_connector_skoda-0.4a3 → carconnectivity_connector_skoda-0.4a4}/pyproject.toml +1 -1
  3. {carconnectivity_connector_skoda-0.4a3 → carconnectivity_connector_skoda-0.4a4}/src/carconnectivity_connector_skoda.egg-info/PKG-INFO +2 -2
  4. {carconnectivity_connector_skoda-0.4a3 → carconnectivity_connector_skoda-0.4a4}/src/carconnectivity_connector_skoda.egg-info/requires.txt +1 -1
  5. {carconnectivity_connector_skoda-0.4a3 → carconnectivity_connector_skoda-0.4a4}/src/carconnectivity_connectors/skoda/_version.py +1 -1
  6. {carconnectivity_connector_skoda-0.4a3 → carconnectivity_connector_skoda-0.4a4}/src/carconnectivity_connectors/skoda/auth/skoda_web_session.py +2 -0
  7. {carconnectivity_connector_skoda-0.4a3 → carconnectivity_connector_skoda-0.4a4}/src/carconnectivity_connectors/skoda/connector.py +72 -2
  8. {carconnectivity_connector_skoda-0.4a3 → carconnectivity_connector_skoda-0.4a4}/src/carconnectivity_connectors/skoda/vehicle.py +4 -0
  9. {carconnectivity_connector_skoda-0.4a3 → carconnectivity_connector_skoda-0.4a4}/.flake8 +0 -0
  10. {carconnectivity_connector_skoda-0.4a3 → carconnectivity_connector_skoda-0.4a4}/.github/ISSUE_TEMPLATE/bug_report.md +0 -0
  11. {carconnectivity_connector_skoda-0.4a3 → carconnectivity_connector_skoda-0.4a4}/.github/ISSUE_TEMPLATE/feature_request.md +0 -0
  12. {carconnectivity_connector_skoda-0.4a3 → carconnectivity_connector_skoda-0.4a4}/.github/dependabot.yml +0 -0
  13. {carconnectivity_connector_skoda-0.4a3 → carconnectivity_connector_skoda-0.4a4}/.github/workflows/build.yml +0 -0
  14. {carconnectivity_connector_skoda-0.4a3 → carconnectivity_connector_skoda-0.4a4}/.github/workflows/build_and_publish.yml +0 -0
  15. {carconnectivity_connector_skoda-0.4a3 → carconnectivity_connector_skoda-0.4a4}/.github/workflows/codeql-analysis.yml +0 -0
  16. {carconnectivity_connector_skoda-0.4a3 → carconnectivity_connector_skoda-0.4a4}/.gitignore +0 -0
  17. {carconnectivity_connector_skoda-0.4a3 → carconnectivity_connector_skoda-0.4a4}/CHANGELOG.md +0 -0
  18. {carconnectivity_connector_skoda-0.4a3 → carconnectivity_connector_skoda-0.4a4}/LICENSE +0 -0
  19. {carconnectivity_connector_skoda-0.4a3 → carconnectivity_connector_skoda-0.4a4}/Makefile +0 -0
  20. {carconnectivity_connector_skoda-0.4a3 → carconnectivity_connector_skoda-0.4a4}/README.md +0 -0
  21. {carconnectivity_connector_skoda-0.4a3 → carconnectivity_connector_skoda-0.4a4}/doc/Config.md +0 -0
  22. {carconnectivity_connector_skoda-0.4a3 → carconnectivity_connector_skoda-0.4a4}/setup.cfg +0 -0
  23. {carconnectivity_connector_skoda-0.4a3 → carconnectivity_connector_skoda-0.4a4}/setup_requirements.txt +0 -0
  24. {carconnectivity_connector_skoda-0.4a3 → carconnectivity_connector_skoda-0.4a4}/src/carconnectivity_connector_skoda.egg-info/SOURCES.txt +0 -0
  25. {carconnectivity_connector_skoda-0.4a3 → carconnectivity_connector_skoda-0.4a4}/src/carconnectivity_connector_skoda.egg-info/dependency_links.txt +0 -0
  26. {carconnectivity_connector_skoda-0.4a3 → carconnectivity_connector_skoda-0.4a4}/src/carconnectivity_connector_skoda.egg-info/top_level.txt +0 -0
  27. {carconnectivity_connector_skoda-0.4a3 → carconnectivity_connector_skoda-0.4a4}/src/carconnectivity_connectors/skoda/__init__.py +0 -0
  28. {carconnectivity_connector_skoda-0.4a3 → carconnectivity_connector_skoda-0.4a4}/src/carconnectivity_connectors/skoda/auth/__init__.py +0 -0
  29. {carconnectivity_connector_skoda-0.4a3 → carconnectivity_connector_skoda-0.4a4}/src/carconnectivity_connectors/skoda/auth/auth_util.py +0 -0
  30. {carconnectivity_connector_skoda-0.4a3 → carconnectivity_connector_skoda-0.4a4}/src/carconnectivity_connectors/skoda/auth/helpers/blacklist_retry.py +0 -0
  31. {carconnectivity_connector_skoda-0.4a3 → carconnectivity_connector_skoda-0.4a4}/src/carconnectivity_connectors/skoda/auth/my_skoda_session.py +0 -0
  32. {carconnectivity_connector_skoda-0.4a3 → carconnectivity_connector_skoda-0.4a4}/src/carconnectivity_connectors/skoda/auth/openid_session.py +0 -0
  33. {carconnectivity_connector_skoda-0.4a3 → carconnectivity_connector_skoda-0.4a4}/src/carconnectivity_connectors/skoda/auth/session_manager.py +0 -0
  34. {carconnectivity_connector_skoda-0.4a3 → carconnectivity_connector_skoda-0.4a4}/src/carconnectivity_connectors/skoda/capability.py +0 -0
  35. {carconnectivity_connector_skoda-0.4a3 → carconnectivity_connector_skoda-0.4a4}/src/carconnectivity_connectors/skoda/charging.py +0 -0
  36. {carconnectivity_connector_skoda-0.4a3 → carconnectivity_connector_skoda-0.4a4}/src/carconnectivity_connectors/skoda/climatization.py +0 -0
  37. {carconnectivity_connector_skoda-0.4a3 → carconnectivity_connector_skoda-0.4a4}/src/carconnectivity_connectors/skoda/command_impl.py +0 -0
  38. {carconnectivity_connector_skoda-0.4a3 → carconnectivity_connector_skoda-0.4a4}/src/carconnectivity_connectors/skoda/error.py +0 -0
  39. {carconnectivity_connector_skoda-0.4a3 → carconnectivity_connector_skoda-0.4a4}/src/carconnectivity_connectors/skoda/mqtt_client.py +0 -0
  40. {carconnectivity_connector_skoda-0.4a3 → carconnectivity_connector_skoda-0.4a4}/src/carconnectivity_connectors/skoda/ui/connector_ui.py +0 -0
  41. {carconnectivity_connector_skoda-0.4a3 → carconnectivity_connector_skoda-0.4a4}/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.4a3
3
+ Version: 0.4a4
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.4a4
40
+ Requires-Dist: carconnectivity>=0.4a6
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.4a4",
17
+ "carconnectivity>=0.4a6",
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.4a3
3
+ Version: 0.4a4
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.4a4
40
+ Requires-Dist: carconnectivity>=0.4a6
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.4a4
1
+ carconnectivity>=0.4a6
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.4a3'
20
+ __version__ = version = '0.4a4'
21
21
  __version_tuple__ = version_tuple = (0, 4)
@@ -121,6 +121,8 @@ class SkodaWebSession(OpenIDSession):
121
121
  raise RetrievalError('Temporary server error during login')
122
122
 
123
123
  if 'Location' not in response.headers:
124
+ if 'consent' in url:
125
+ raise AuthenticationError('Could not find Location in headers, probably due to missing consent. Try visiting: ' + url)
124
126
  raise APICompatibilityError('Forwarding without Location in headers')
125
127
 
126
128
  url = response.headers['Location']
@@ -22,7 +22,7 @@ from carconnectivity.doors import Doors
22
22
  from carconnectivity.windows import Windows
23
23
  from carconnectivity.lights import Lights
24
24
  from carconnectivity.drive import GenericDrive, ElectricDrive, CombustionDrive
25
- from carconnectivity.attributes import BooleanAttribute, DurationAttribute, TemperatureAttribute
25
+ from carconnectivity.attributes import GenericAttribute, BooleanAttribute, DurationAttribute, TemperatureAttribute
26
26
  from carconnectivity.charging import Charging
27
27
  from carconnectivity.position import Position
28
28
  from carconnectivity.climatization import Climatization
@@ -81,6 +81,16 @@ class Connector(BaseConnector):
81
81
 
82
82
  self.connected: BooleanAttribute = BooleanAttribute(name="connected", parent=self, tags={'connector_custom'})
83
83
  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
+
91
+ self.interval._is_changeable = True # pylint: disable=protected-access
92
+ self.interval._add_on_set_hook(__check_interval) # pylint: disable=protected-access
93
+
84
94
  self.commands: Commands = Commands(parent=self)
85
95
 
86
96
  self.user_id: Optional[str] = None
@@ -154,9 +164,11 @@ class Connector(BaseConnector):
154
164
  self._stop_event.clear()
155
165
  # Start background thread for Rest API polling
156
166
  self._background_thread = threading.Thread(target=self._background_loop, daemon=False)
167
+ self._background_thread.name = 'carconnectivity.connectors.skoda-background'
157
168
  self._background_thread.start()
158
169
  # Start background thread for MQTT connection
159
170
  self._background_connect_thread = threading.Thread(target=self._background_connect_loop, daemon=False)
171
+ self._background_connect_thread.name = 'carconnectivity.connectors.skoda-background_connect'
160
172
  self._background_connect_thread.start()
161
173
  # Start MQTT thread
162
174
  self._mqtt_client.loop_start()
@@ -236,12 +248,12 @@ class Connector(BaseConnector):
236
248
  self.car_connectivity.garage.remove_vehicle(vehicle.id)
237
249
  vehicle.enabled = False
238
250
  self._stop_event.set()
251
+ self.session.close()
239
252
  if self._background_thread is not None:
240
253
  self._background_thread.join()
241
254
  if self._background_connect_thread is not None:
242
255
  self._background_connect_thread.join()
243
256
  self.persist()
244
- self.session.close()
245
257
  return super().shutdown()
246
258
 
247
259
  def fetch_all(self) -> None:
@@ -339,6 +351,8 @@ class Connector(BaseConnector):
339
351
  vehicle_to_update = self.fetch_vehicle_status(vehicle_to_update)
340
352
  vehicle_to_update = self.fetch_driving_range(vehicle_to_update)
341
353
  if vehicle_to_update.capabilities is not None and vehicle_to_update.capabilities.enabled:
354
+ if vehicle_to_update.capabilities.has_capability('READINESS'):
355
+ vehicle_to_update = self.fetch_connection_status(vehicle_to_update)
342
356
  if vehicle_to_update.capabilities.has_capability('PARKING_POSITION'):
343
357
  vehicle_to_update = self.fetch_position(vehicle_to_update)
344
358
  if vehicle_to_update.capabilities.has_capability('CHARGING') and isinstance(vehicle_to_update, SkodaElectricVehicle):
@@ -347,6 +361,27 @@ class Connector(BaseConnector):
347
361
  vehicle_to_update = self.fetch_air_conditioning(vehicle_to_update)
348
362
  if vehicle_to_update.capabilities.has_capability('VEHICLE_HEALTH_INSPECTION'):
349
363
  vehicle_to_update = self.fetch_maintenance(vehicle_to_update)
364
+ vehicle_to_update = self.decide_state(vehicle_to_update)
365
+
366
+ def decide_state(self, vehicle: SkodaVehicle) -> SkodaVehicle:
367
+ """
368
+ Decides the state of the vehicle based on the current data.
369
+
370
+ Args:
371
+ vehicle (SkodaVehicle): The Skoda vehicle object.
372
+
373
+ Returns:
374
+ SkodaVehicle: The Skoda vehicle object with the updated state.
375
+ """
376
+ if vehicle is not None:
377
+ if vehicle.in_motion is not None and vehicle.in_motion.enabled and vehicle.in_motion.value:
378
+ vehicle.state._set_value(GenericVehicle.State.IGNITION_ON) # pylint: disable=protected-access
379
+ elif vehicle.position is not None and vehicle.position.enabled and vehicle.position.position_type is not None \
380
+ and vehicle.position.position_type.enabled and vehicle.position.position_type.value == Position.PositionType.PARKING:
381
+ vehicle.state._set_value(GenericVehicle.State.PARKED) # pylint: disable=protected-access
382
+ else:
383
+ vehicle.state._set_value(None) # pylint: disable=protected-access
384
+ return vehicle
350
385
 
351
386
  def fetch_charging(self, vehicle: SkodaElectricVehicle, no_cache: bool = False) -> SkodaElectricVehicle:
352
387
  """
@@ -555,6 +590,41 @@ class Connector(BaseConnector):
555
590
  vehicle.charging.errors.clear()
556
591
  log_extra_keys(LOG_API, 'charging data', data, {'carCapturedTimestamp', 'status', 'isVehicleInSavedLocation', 'errors', 'settings'})
557
592
  return vehicle
593
+
594
+ def fetch_connection_status(self, vehicle: SkodaVehicle, no_cache: bool = False) -> SkodaVehicle:
595
+ """
596
+ Fetches the connection status of the given Skoda vehicle and updates its connection attributes.
597
+
598
+ Args:
599
+ vehicle (SkodaVehicle): The Skoda vehicle object containing the VIN and connection attributes.
600
+
601
+ Returns:
602
+ SkodaVehicle: The updated Skoda vehicle object with the fetched connection data.
603
+
604
+ Raises:
605
+ APIError: If the VIN is missing.
606
+ ValueError: If the vehicle has no connection object.
607
+ """
608
+ vin = vehicle.vin.value
609
+ if vin is None:
610
+ raise APIError('VIN is missing')
611
+ url = f'https://mysmob.api.connect.skoda-auto.cz/api/v2/connection-status/{vin}/readiness'
612
+ data: Dict[str, Any] | None = self._fetch_data(url=url, session=self.session, no_cache=no_cache)
613
+ # {'unreachable': False, 'inMotion': False, 'batteryProtectionLimitOn': False}
614
+ if data is not None:
615
+ if 'unreachable' in data and data['unreachable'] is not None:
616
+ if data['unreachable']:
617
+ vehicle.connection_state._set_value(vehicle.ConnectionState.OFFLINE) # pylint: disable=protected-access
618
+ else:
619
+ vehicle.connection_state._set_value(vehicle.ConnectionState.REACHABLE) # pylint: disable=protected-access
620
+ else:
621
+ vehicle.connection_state._set_value(None) # pylint: disable=protected-access
622
+ if 'inMotion' in data and data['inMotion'] is not None:
623
+ vehicle.in_motion._set_value(data['inMotion']) # pylint: disable=protected-access
624
+ else:
625
+ vehicle.in_motion._set_value(None) # pylint: disable=protected-access
626
+ log_extra_keys(LOG_API, 'connection status', data, {'unreachable'})
627
+ return vehicle
558
628
 
559
629
  def fetch_position(self, vehicle: SkodaVehicle, no_cache: bool = False) -> SkodaVehicle:
560
630
  """
@@ -4,6 +4,7 @@ from typing import TYPE_CHECKING
4
4
 
5
5
  from carconnectivity.vehicle import GenericVehicle, ElectricVehicle, CombustionVehicle, HybridVehicle
6
6
  from carconnectivity.charging import Charging
7
+ from carconnectivity.attributes import BooleanAttribute
7
8
 
8
9
  from carconnectivity_connectors.skoda.capability import Capabilities
9
10
  from carconnectivity_connectors.skoda.charging import SkodaCharging
@@ -32,6 +33,8 @@ class SkodaVehicle(GenericVehicle): # pylint: disable=too-many-instance-attribu
32
33
  super().__init__(origin=origin)
33
34
  self.capabilities: Capabilities = origin.capabilities
34
35
  self.capabilities.parent = self
36
+ self.in_motion: BooleanAttribute = origin.in_motion
37
+ self.in_motion.parent = self
35
38
  if SUPPORT_IMAGES:
36
39
  self._car_images = origin._car_images
37
40
 
@@ -39,6 +42,7 @@ class SkodaVehicle(GenericVehicle): # pylint: disable=too-many-instance-attribu
39
42
  super().__init__(vin=vin, garage=garage, managing_connector=managing_connector)
40
43
  self.climatization = SkodaClimatization(vehicle=self, origin=self.climatization)
41
44
  self.capabilities = Capabilities(vehicle=self)
45
+ self.in_motion = BooleanAttribute(name='in_motion', parent=self, tags={'connector_custom'})
42
46
  if SUPPORT_IMAGES:
43
47
  self._car_images: Dict[str, Image.Image] = {}
44
48
  self.manufacturer._set_value(value='Škoda') # pylint: disable=protected-access