carconnectivity-connector-skoda 0.4a8__py3-none-any.whl → 0.5__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 carconnectivity-connector-skoda might be problematic. Click here for more details.
- {carconnectivity_connector_skoda-0.4a8.dist-info → carconnectivity_connector_skoda-0.5.dist-info}/METADATA +5 -4
- {carconnectivity_connector_skoda-0.4a8.dist-info → carconnectivity_connector_skoda-0.5.dist-info}/RECORD +10 -10
- {carconnectivity_connector_skoda-0.4a8.dist-info → carconnectivity_connector_skoda-0.5.dist-info}/WHEEL +1 -1
- carconnectivity_connectors/skoda/_version.py +2 -2
- carconnectivity_connectors/skoda/capability.py +11 -4
- carconnectivity_connectors/skoda/charging.py +4 -4
- carconnectivity_connectors/skoda/connector.py +245 -17
- carconnectivity_connectors/skoda/vehicle.py +8 -7
- {carconnectivity_connector_skoda-0.4a8.dist-info → carconnectivity_connector_skoda-0.5.dist-info/licenses}/LICENSE +0 -0
- {carconnectivity_connector_skoda-0.4a8.dist-info → carconnectivity_connector_skoda-0.5.dist-info}/top_level.txt +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
Metadata-Version: 2.
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
2
|
Name: carconnectivity-connector-skoda
|
|
3
|
-
Version: 0.
|
|
3
|
+
Version: 0.5
|
|
4
4
|
Summary: CarConnectivity connector for Skoda services
|
|
5
5
|
Author: Till Steinbach
|
|
6
6
|
License: MIT License
|
|
@@ -37,15 +37,16 @@ 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.
|
|
40
|
+
Requires-Dist: carconnectivity>=0.5
|
|
41
41
|
Requires-Dist: oauthlib~=3.2.2
|
|
42
42
|
Requires-Dist: requests~=2.32.3
|
|
43
43
|
Requires-Dist: jwt~=1.3.1
|
|
44
44
|
Requires-Dist: paho-mqtt~=2.1.0
|
|
45
|
+
Dynamic: license-file
|
|
45
46
|
|
|
46
47
|
|
|
47
48
|
|
|
48
|
-
# CarConnectivity Connector for
|
|
49
|
+
# CarConnectivity Connector for Skoda Vehicles
|
|
49
50
|
[](https://github.com/tillsteinbach/CarConnectivity-connector-skoda/)
|
|
50
51
|
[](https://github.com/tillsteinbach/CarConnectivity-connector-skoda/releases/latest)
|
|
51
52
|
[](https://github.com/tillsteinbach/CarConnectivity-connector-skoda/blob/master/LICENSE)
|
|
@@ -1,13 +1,14 @@
|
|
|
1
|
+
carconnectivity_connector_skoda-0.5.dist-info/licenses/LICENSE,sha256=PIwI1alwDyOfvEQHdGCm2u9uf_mGE8030xZDfun0xTo,1071
|
|
1
2
|
carconnectivity_connectors/skoda/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
2
|
-
carconnectivity_connectors/skoda/_version.py,sha256=
|
|
3
|
-
carconnectivity_connectors/skoda/capability.py,sha256=
|
|
4
|
-
carconnectivity_connectors/skoda/charging.py,sha256=
|
|
3
|
+
carconnectivity_connectors/skoda/_version.py,sha256=6KN8_fYf4OIoH3z85tggP3fkMDQc76t8Gz3ntWifnNk,506
|
|
4
|
+
carconnectivity_connectors/skoda/capability.py,sha256=wH563-XUb_TnT8di1qDjnj-cY-cNHcAT6z7mx21LhSQ,4770
|
|
5
|
+
carconnectivity_connectors/skoda/charging.py,sha256=7DPNiTWFhxiiEFKVnbIIU2TCmkpmcMWx_zsHXGXFpAQ,6856
|
|
5
6
|
carconnectivity_connectors/skoda/climatization.py,sha256=Jut468SkxjPBDTqroWFvDifVPfJBxGjsFed5pc4kZkg,1768
|
|
6
7
|
carconnectivity_connectors/skoda/command_impl.py,sha256=vgno5Qb5To0hCHOEBWSG8UOwCY9kT5fz1e2y0b6zF7U,3047
|
|
7
|
-
carconnectivity_connectors/skoda/connector.py,sha256=
|
|
8
|
+
carconnectivity_connectors/skoda/connector.py,sha256=wp3GXooqn1-O-TR4PxUdNR846EKrghBPCp3lN_5_UeE,144975
|
|
8
9
|
carconnectivity_connectors/skoda/error.py,sha256=ffxzvjmci7vtp9Q1K4DR1kBF0kTJxN5Gluci3kDBkEI,2459
|
|
9
10
|
carconnectivity_connectors/skoda/mqtt_client.py,sha256=RkZ43NG1Z_TUmc2hUZS0yYUfwewzfut63zZUhQR1xug,39101
|
|
10
|
-
carconnectivity_connectors/skoda/vehicle.py,sha256=
|
|
11
|
+
carconnectivity_connectors/skoda/vehicle.py,sha256=q5gwe-_yPfE_-aEc17UQ-Q0Z46IN7PCpNG5jLw5PZl0,3981
|
|
11
12
|
carconnectivity_connectors/skoda/auth/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
12
13
|
carconnectivity_connectors/skoda/auth/auth_util.py,sha256=dGLUbUre0HBsTg_Ii5vW34f8DLrCykYJYCyzEvUBBEE,4434
|
|
13
14
|
carconnectivity_connectors/skoda/auth/my_skoda_session.py,sha256=lSh23SFJs8opjmPwHTv-KNIKDep_WY4aItSP4Zq7bT8,10396
|
|
@@ -16,8 +17,7 @@ carconnectivity_connectors/skoda/auth/session_manager.py,sha256=Uf1vujuDBYUCAXhY
|
|
|
16
17
|
carconnectivity_connectors/skoda/auth/skoda_web_session.py,sha256=tapjCRRPBu3tHrDoKmtuAlQhgxktib3oWTB8MHEzZTY,10816
|
|
17
18
|
carconnectivity_connectors/skoda/auth/helpers/blacklist_retry.py,sha256=f3wsiY5bpHDBxp7Va1Mv9nKJ4u3qnCHZZmDu78_AhMk,1251
|
|
18
19
|
carconnectivity_connectors/skoda/ui/connector_ui.py,sha256=2Gywhyki52IxIZXV6DhWhzrBLn2293LlUMhK1Rxnw9w,1376
|
|
19
|
-
carconnectivity_connector_skoda-0.
|
|
20
|
-
carconnectivity_connector_skoda-0.
|
|
21
|
-
carconnectivity_connector_skoda-0.
|
|
22
|
-
carconnectivity_connector_skoda-0.
|
|
23
|
-
carconnectivity_connector_skoda-0.4a8.dist-info/RECORD,,
|
|
20
|
+
carconnectivity_connector_skoda-0.5.dist-info/METADATA,sha256=NmEpTszVOGvqRN5lGNyxdOTneA0-lvH5WndA1zdPp6Q,5378
|
|
21
|
+
carconnectivity_connector_skoda-0.5.dist-info/WHEEL,sha256=1tXe9gY0PYatrMPMDd6jXqjfpz_B-Wqm32CPfRC58XU,91
|
|
22
|
+
carconnectivity_connector_skoda-0.5.dist-info/top_level.txt,sha256=KqA8GviZsDH4PtmnwSQsz0HB_w-TWkeEHLIRNo5dTaI,27
|
|
23
|
+
carconnectivity_connector_skoda-0.5.dist-info/RECORD,,
|
|
@@ -5,7 +5,7 @@ from typing import TYPE_CHECKING
|
|
|
5
5
|
from enum import IntEnum
|
|
6
6
|
|
|
7
7
|
from carconnectivity.objects import GenericObject
|
|
8
|
-
from carconnectivity.attributes import StringAttribute
|
|
8
|
+
from carconnectivity.attributes import StringAttribute, GenericAttribute
|
|
9
9
|
|
|
10
10
|
if TYPE_CHECKING:
|
|
11
11
|
from typing import Dict, Optional
|
|
@@ -77,7 +77,7 @@ class Capabilities(GenericObject):
|
|
|
77
77
|
"""
|
|
78
78
|
return self.__capabilities.get(capability_id)
|
|
79
79
|
|
|
80
|
-
def has_capability(self, capability_id: str) -> bool:
|
|
80
|
+
def has_capability(self, capability_id: str, check_status_ok=False) -> bool:
|
|
81
81
|
"""
|
|
82
82
|
Check if the Capabilities contains a capability with the specified ID.
|
|
83
83
|
|
|
@@ -87,7 +87,14 @@ class Capabilities(GenericObject):
|
|
|
87
87
|
Returns:
|
|
88
88
|
bool: True if the capability exists, otherwise False.
|
|
89
89
|
"""
|
|
90
|
-
|
|
90
|
+
if check_status_ok:
|
|
91
|
+
if capability_id in self.__capabilities and self.__capabilities[capability_id].enabled:
|
|
92
|
+
capability: Capability = self.__capabilities[capability_id]
|
|
93
|
+
if capability.status.enabled and capability.status.value is not None and len(capability.status.value) > 0:
|
|
94
|
+
return False
|
|
95
|
+
return True
|
|
96
|
+
return False
|
|
97
|
+
return capability_id in self.__capabilities and self.__capabilities[capability_id].enabled
|
|
91
98
|
|
|
92
99
|
|
|
93
100
|
class Capability(GenericObject):
|
|
@@ -103,7 +110,7 @@ class Capability(GenericObject):
|
|
|
103
110
|
super().__init__(object_id=capability_id, parent=capabilities)
|
|
104
111
|
self.delay_notifications = True
|
|
105
112
|
self.capability_id = StringAttribute("id", self, capability_id, tags={'connector_custom'})
|
|
106
|
-
self.
|
|
113
|
+
self.status = GenericAttribute("status", self, value=[], tags={'connector_custom'})
|
|
107
114
|
self.enabled = True
|
|
108
115
|
self.delay_notifications = False
|
|
109
116
|
|
|
@@ -26,11 +26,11 @@ class SkodaCharging(Charging): # pylint: disable=too-many-instance-attributes
|
|
|
26
26
|
"""
|
|
27
27
|
def __init__(self, vehicle: ElectricVehicle | None = None, origin: Optional[Charging] = None) -> None:
|
|
28
28
|
if origin is not None:
|
|
29
|
-
super().__init__(origin=origin)
|
|
30
|
-
self.settings: Charging.Settings = SkodaCharging.Settings(origin=origin.settings)
|
|
29
|
+
super().__init__(vehicle=vehicle, origin=origin)
|
|
30
|
+
self.settings: Charging.Settings = SkodaCharging.Settings(parent=self, origin=origin.settings)
|
|
31
31
|
else:
|
|
32
32
|
super().__init__(vehicle=vehicle)
|
|
33
|
-
self.settings: Charging.Settings = SkodaCharging.Settings(origin=self.settings)
|
|
33
|
+
self.settings: Charging.Settings = SkodaCharging.Settings(parent=self, origin=self.settings)
|
|
34
34
|
self.errors: Dict[str, Error] = {}
|
|
35
35
|
self.is_in_saved_location: BooleanAttribute = BooleanAttribute("is_in_saved_location", parent=self, tags={'connector_custom'})
|
|
36
36
|
|
|
@@ -40,7 +40,7 @@ class SkodaCharging(Charging): # pylint: disable=too-many-instance-attributes
|
|
|
40
40
|
"""
|
|
41
41
|
def __init__(self, parent: Optional[GenericObject] = None, origin: Optional[Charging.Settings] = None) -> None:
|
|
42
42
|
if origin is not None:
|
|
43
|
-
super().__init__(origin=origin)
|
|
43
|
+
super().__init__(parent=parent, origin=origin)
|
|
44
44
|
else:
|
|
45
45
|
super().__init__(parent=parent)
|
|
46
46
|
self.preferred_charge_mode: EnumAttribute = EnumAttribute("preferred_charge_mode", parent=self, tags={'connector_custom'})
|
|
@@ -23,14 +23,17 @@ from carconnectivity.doors import Doors
|
|
|
23
23
|
from carconnectivity.windows import Windows
|
|
24
24
|
from carconnectivity.lights import Lights
|
|
25
25
|
from carconnectivity.drive import GenericDrive, ElectricDrive, CombustionDrive
|
|
26
|
-
from carconnectivity.attributes import
|
|
26
|
+
from carconnectivity.attributes import BooleanAttribute, DurationAttribute, TemperatureAttribute, EnumAttribute, LevelAttribute, \
|
|
27
|
+
CurrentAttribute
|
|
27
28
|
from carconnectivity.charging import Charging
|
|
28
29
|
from carconnectivity.position import Position
|
|
29
30
|
from carconnectivity.climatization import Climatization
|
|
30
31
|
from carconnectivity.charging_connector import ChargingConnector
|
|
31
32
|
from carconnectivity.commands import Commands
|
|
32
|
-
from carconnectivity.command_impl import ClimatizationStartStopCommand, ChargingStartStopCommand, HonkAndFlashCommand, LockUnlockCommand, WakeSleepCommand
|
|
33
|
+
from carconnectivity.command_impl import ClimatizationStartStopCommand, ChargingStartStopCommand, HonkAndFlashCommand, LockUnlockCommand, WakeSleepCommand, \
|
|
34
|
+
WindowHeatingStartStopCommand
|
|
33
35
|
from carconnectivity.enums import ConnectionState
|
|
36
|
+
from carconnectivity.window_heating import WindowHeatings
|
|
34
37
|
|
|
35
38
|
from carconnectivity_connectors.base.connector import BaseConnector
|
|
36
39
|
from carconnectivity_connectors.skoda.auth.session_manager import SessionManager, SessionUser, Service
|
|
@@ -373,15 +376,15 @@ class Connector(BaseConnector):
|
|
|
373
376
|
vehicle_to_update = self.fetch_vehicle_status(vehicle_to_update)
|
|
374
377
|
vehicle_to_update = self.fetch_driving_range(vehicle_to_update)
|
|
375
378
|
if vehicle_to_update.capabilities is not None and vehicle_to_update.capabilities.enabled:
|
|
376
|
-
if vehicle_to_update.capabilities.has_capability('READINESS'):
|
|
379
|
+
if vehicle_to_update.capabilities.has_capability('READINESS', check_status_ok=True):
|
|
377
380
|
vehicle_to_update = self.fetch_connection_status(vehicle_to_update)
|
|
378
|
-
if vehicle_to_update.capabilities.has_capability('PARKING_POSITION'):
|
|
381
|
+
if vehicle_to_update.capabilities.has_capability('PARKING_POSITION', check_status_ok=True):
|
|
379
382
|
vehicle_to_update = self.fetch_position(vehicle_to_update)
|
|
380
|
-
if vehicle_to_update.capabilities.has_capability('CHARGING') and isinstance(vehicle_to_update, SkodaElectricVehicle):
|
|
383
|
+
if vehicle_to_update.capabilities.has_capability('CHARGING', check_status_ok=True) and isinstance(vehicle_to_update, SkodaElectricVehicle):
|
|
381
384
|
vehicle_to_update = self.fetch_charging(vehicle_to_update)
|
|
382
|
-
if vehicle_to_update.capabilities.has_capability('AIR_CONDITIONING'):
|
|
385
|
+
if vehicle_to_update.capabilities.has_capability('AIR_CONDITIONING', check_status_ok=True):
|
|
383
386
|
vehicle_to_update = self.fetch_air_conditioning(vehicle_to_update)
|
|
384
|
-
if vehicle_to_update.capabilities.has_capability('VEHICLE_HEALTH_INSPECTION'):
|
|
387
|
+
if vehicle_to_update.capabilities.has_capability('VEHICLE_HEALTH_INSPECTION', check_status_ok=True):
|
|
385
388
|
vehicle_to_update = self.fetch_maintenance(vehicle_to_update)
|
|
386
389
|
vehicle_to_update = self.decide_state(vehicle_to_update)
|
|
387
390
|
self.car_connectivity.transaction_end()
|
|
@@ -507,14 +510,24 @@ class Connector(BaseConnector):
|
|
|
507
510
|
if 'settings' in data and data['settings'] is not None:
|
|
508
511
|
if 'targetStateOfChargeInPercent' in data['settings'] and data['settings']['targetStateOfChargeInPercent'] is not None \
|
|
509
512
|
and vehicle.charging is not None and vehicle.charging.settings is not None:
|
|
513
|
+
vehicle.charging.settings.target_level.minimum = 50.0
|
|
514
|
+
vehicle.charging.settings.target_level.maximum = 100.0
|
|
515
|
+
vehicle.charging.settings.target_level.precision = 10.0
|
|
516
|
+
vehicle.charging.settings.target_level._add_on_set_hook(self.__on_charging_target_level_change) # pylint: disable=protected-access
|
|
517
|
+
vehicle.charging.settings.target_level._is_changeable = True # pylint: disable=protected-access
|
|
510
518
|
# pylint: disable-next=protected-access
|
|
511
519
|
vehicle.charging.settings.target_level._set_value(value=data['settings']['targetStateOfChargeInPercent'], measured=captured_at)
|
|
512
520
|
else:
|
|
513
521
|
vehicle.charging.settings.target_level._set_value(None, measured=captured_at) # pylint: disable=protected-access
|
|
514
522
|
if 'maxChargeCurrentAc' in data['settings'] and data['settings']['maxChargeCurrentAc'] is not None \
|
|
515
523
|
and vehicle.charging is not None and vehicle.charging.settings is not None:
|
|
524
|
+
vehicle.charging.settings.maximum_current.minimum = 6.0
|
|
525
|
+
vehicle.charging.settings.maximum_current.maximum = 16.0
|
|
526
|
+
vehicle.charging.settings.maximum_current.precision = 1.0
|
|
527
|
+
vehicle.charging.settings.maximum_current._add_on_set_hook(self.__on_charging_maximum_current_change) # pylint: disable=protected-access
|
|
528
|
+
vehicle.charging.settings.maximum_current._is_changeable = True # pylint: disable=protected-access
|
|
516
529
|
if data['settings']['maxChargeCurrentAc'] == 'MAXIMUM':
|
|
517
|
-
vehicle.charging.settings.maximum_current._set_value(value=
|
|
530
|
+
vehicle.charging.settings.maximum_current._set_value(value=16, measured=captured_at) # pylint: disable=protected-access
|
|
518
531
|
elif data['settings']['maxChargeCurrentAc'] == 'REDUCED':
|
|
519
532
|
vehicle.charging.settings.maximum_current._set_value(value=6, measured=captured_at) # pylint: disable=protected-access
|
|
520
533
|
else:
|
|
@@ -523,6 +536,8 @@ class Connector(BaseConnector):
|
|
|
523
536
|
else:
|
|
524
537
|
vehicle.charging.settings.maximum_current._set_value(None, measured=captured_at) # pylint: disable=protected-access
|
|
525
538
|
if 'autoUnlockPlugWhenCharged' in data['settings'] and data['settings']['autoUnlockPlugWhenCharged'] is not None:
|
|
539
|
+
vehicle.charging.settings.auto_unlock._add_on_set_hook(self.__on_charging_auto_unlock_change) # pylint: disable=protected-access
|
|
540
|
+
vehicle.charging.settings.auto_unlock._is_changeable = True # pylint: disable=protected-access
|
|
526
541
|
if data['settings']['autoUnlockPlugWhenCharged'] in ['ON', 'PERMANENT']:
|
|
527
542
|
vehicle.charging.settings.auto_unlock._set_value(True, measured=captured_at) # pylint: disable=protected-access
|
|
528
543
|
elif data['settings']['autoUnlockPlugWhenCharged'] == 'OFF':
|
|
@@ -646,7 +661,7 @@ class Connector(BaseConnector):
|
|
|
646
661
|
vehicle.in_motion._set_value(data['inMotion']) # pylint: disable=protected-access
|
|
647
662
|
else:
|
|
648
663
|
vehicle.in_motion._set_value(None) # pylint: disable=protected-access
|
|
649
|
-
log_extra_keys(LOG_API, 'connection status', data, {'unreachable'})
|
|
664
|
+
log_extra_keys(LOG_API, 'connection status', data, {'unreachable', 'inMotion'})
|
|
650
665
|
return vehicle
|
|
651
666
|
|
|
652
667
|
def fetch_position(self, vehicle: SkodaVehicle, no_cache: bool = False) -> SkodaVehicle:
|
|
@@ -701,6 +716,10 @@ class Connector(BaseConnector):
|
|
|
701
716
|
vehicle.position.latitude._set_value(None) # pylint: disable=protected-access
|
|
702
717
|
vehicle.position.longitude._set_value(None) # pylint: disable=protected-access
|
|
703
718
|
vehicle.position.position_type._set_value(None) # pylint: disable=protected-access
|
|
719
|
+
else:
|
|
720
|
+
vehicle.position.latitude._set_value(None) # pylint: disable=protected-access
|
|
721
|
+
vehicle.position.longitude._set_value(None) # pylint: disable=protected-access
|
|
722
|
+
vehicle.position.position_type._set_value(None) # pylint: disable=protected-access
|
|
704
723
|
return vehicle
|
|
705
724
|
|
|
706
725
|
def fetch_maintenance(self, vehicle: SkodaVehicle, no_cache: bool = False) -> SkodaVehicle:
|
|
@@ -969,7 +988,44 @@ class Connector(BaseConnector):
|
|
|
969
988
|
# pylint: disable-next=protected-access
|
|
970
989
|
vehicle.charging.connector.lock_state._set_value(value=None, measured=captured_at)
|
|
971
990
|
if 'windowHeatingState' in data and data['windowHeatingState'] is not None:
|
|
972
|
-
|
|
991
|
+
heating_on: bool = False
|
|
992
|
+
all_heating_invalid: bool = True
|
|
993
|
+
for window_id, state in data['windowHeatingState'].items():
|
|
994
|
+
if window_id != 'unspecified':
|
|
995
|
+
if window_id in vehicle.window_heatings.windows:
|
|
996
|
+
window: WindowHeatings.WindowHeating = vehicle.window_heatings.windows[window_id]
|
|
997
|
+
else:
|
|
998
|
+
window = WindowHeatings.WindowHeating(window_id=window_id, window_heatings=vehicle.window_heatings)
|
|
999
|
+
vehicle.window_heatings.windows[window_id] = window
|
|
1000
|
+
|
|
1001
|
+
if state.lower() in [item.value for item in WindowHeatings.HeatingState]:
|
|
1002
|
+
window_heating_state: WindowHeatings.HeatingState = WindowHeatings.HeatingState(state.lower())
|
|
1003
|
+
if window_heating_state == WindowHeatings.HeatingState.ON:
|
|
1004
|
+
heating_on = True
|
|
1005
|
+
if window_heating_state in [WindowHeatings.HeatingState.ON,
|
|
1006
|
+
WindowHeatings.HeatingState.OFF]:
|
|
1007
|
+
all_heating_invalid = False
|
|
1008
|
+
window.heating_state._set_value(window_heating_state, measured=captured_at) # pylint: disable=protected-access
|
|
1009
|
+
else:
|
|
1010
|
+
LOG_API.info('Unknown window heating state %s not in %s', state.lower(), str(WindowHeatings.HeatingState))
|
|
1011
|
+
# pylint: disable-next=protected-access
|
|
1012
|
+
window.heating_state._set_value(WindowHeatings.HeatingState.UNKNOWN, measured=captured_at)
|
|
1013
|
+
if all_heating_invalid:
|
|
1014
|
+
# pylint: disable-next=protected-access
|
|
1015
|
+
vehicle.window_heatings.heating_state._set_value(WindowHeatings.HeatingState.INVALID, measured=captured_at)
|
|
1016
|
+
else:
|
|
1017
|
+
if heating_on:
|
|
1018
|
+
# pylint: disable-next=protected-access
|
|
1019
|
+
vehicle.window_heatings.heating_state._set_value(WindowHeatings.HeatingState.ON, measured=captured_at)
|
|
1020
|
+
else:
|
|
1021
|
+
# pylint: disable-next=protected-access
|
|
1022
|
+
vehicle.window_heatings.heating_state._set_value(WindowHeatings.HeatingState.OFF, measured=captured_at)
|
|
1023
|
+
if vehicle.window_heatings is not None and vehicle.window_heatings.commands is not None \
|
|
1024
|
+
and not vehicle.window_heatings.commands.contains_command('start-stop'):
|
|
1025
|
+
start_stop_command = WindowHeatingStartStopCommand(parent=vehicle.window_heatings.commands)
|
|
1026
|
+
start_stop_command._add_on_set_hook(self.__on_window_heating_start_stop) # pylint: disable=protected-access
|
|
1027
|
+
start_stop_command.enabled = True
|
|
1028
|
+
vehicle.window_heatings.commands.add_command(start_stop_command)
|
|
973
1029
|
if 'errors' in data and data['errors'] is not None:
|
|
974
1030
|
found_errors: Set[str] = set()
|
|
975
1031
|
if not isinstance(vehicle.climatization, SkodaClimatization):
|
|
@@ -998,7 +1054,7 @@ class Connector(BaseConnector):
|
|
|
998
1054
|
log_extra_keys(LOG_API, 'air-condition', data, {'carCapturedTimestamp', 'state', 'estimatedDateTimeToReachTargetTemperature',
|
|
999
1055
|
'targetTemperature', 'outsideTemperature', 'chargerConnectionState',
|
|
1000
1056
|
'chargerLockState', 'airConditioningAtUnlock', 'steeringWheelPosition',
|
|
1001
|
-
'windowHeatingEnabled', 'seatHeatingActivated', 'errors'})
|
|
1057
|
+
'windowHeatingEnabled', 'seatHeatingActivated', 'windowHeatingState', 'errors'})
|
|
1002
1058
|
return vehicle
|
|
1003
1059
|
|
|
1004
1060
|
def fetch_vehicle_details(self, vehicle: SkodaVehicle, no_cache: bool = False) -> SkodaVehicle:
|
|
@@ -1034,6 +1090,20 @@ class Connector(BaseConnector):
|
|
|
1034
1090
|
else:
|
|
1035
1091
|
capability = Capability(capability_id=capability_id, capabilities=vehicle.capabilities)
|
|
1036
1092
|
vehicle.capabilities.add_capability(capability_id, capability)
|
|
1093
|
+
if 'statuses' in capability_dict and capability_dict['statuses'] is not None:
|
|
1094
|
+
statuses = capability_dict['statuses']
|
|
1095
|
+
if isinstance(statuses, list):
|
|
1096
|
+
for status in statuses:
|
|
1097
|
+
if status in [item.name for item in Capability.Status]:
|
|
1098
|
+
capability.status.value.append(Capability.Status[status])
|
|
1099
|
+
else:
|
|
1100
|
+
LOG_API.warning('Capability status unkown %s', status)
|
|
1101
|
+
capability.status.value.append(Capability.Status.UNKNOWN)
|
|
1102
|
+
else:
|
|
1103
|
+
LOG_API.warning('Capability status not a list in %s', statuses)
|
|
1104
|
+
else:
|
|
1105
|
+
capability.status.value.clear()
|
|
1106
|
+
log_extra_keys(LOG_API, 'capability', capability_dict, {'id', 'statuses'})
|
|
1037
1107
|
else:
|
|
1038
1108
|
raise APIError('Could not parse capability, id missing')
|
|
1039
1109
|
for capability_id in vehicle.capabilities.capabilities.keys() - found_capabilities:
|
|
@@ -1043,7 +1113,7 @@ class Connector(BaseConnector):
|
|
|
1043
1113
|
else:
|
|
1044
1114
|
vehicle.capabilities.clear_capabilities()
|
|
1045
1115
|
|
|
1046
|
-
if vehicle.capabilities.has_capability('VEHICLE_WAKE_UP_TRIGGER'):
|
|
1116
|
+
if vehicle.capabilities.has_capability('VEHICLE_WAKE_UP_TRIGGER', check_status_ok=True):
|
|
1047
1117
|
if vehicle.commands is not None and vehicle.commands.commands is not None \
|
|
1048
1118
|
and not vehicle.commands.contains_command('wake-sleep'):
|
|
1049
1119
|
wake_sleep_command = WakeSleepCommand(parent=vehicle.commands)
|
|
@@ -1052,7 +1122,8 @@ class Connector(BaseConnector):
|
|
|
1052
1122
|
vehicle.commands.add_command(wake_sleep_command)
|
|
1053
1123
|
|
|
1054
1124
|
# Add HONK_AND_FLASH command if necessary capabilities are available
|
|
1055
|
-
if vehicle.capabilities.has_capability('HONK_AND_FLASH')
|
|
1125
|
+
if vehicle.capabilities.has_capability('HONK_AND_FLASH', check_status_ok=True) \
|
|
1126
|
+
and vehicle.capabilities.has_capability('PARKING_POSITION', check_status_ok=True):
|
|
1056
1127
|
if vehicle.commands is not None and vehicle.commands.commands is not None \
|
|
1057
1128
|
and not vehicle.commands.contains_command('honk-flash'):
|
|
1058
1129
|
honk_flash_command = HonkAndFlashCommand(parent=vehicle.commands)
|
|
@@ -1061,7 +1132,7 @@ class Connector(BaseConnector):
|
|
|
1061
1132
|
vehicle.commands.add_command(honk_flash_command)
|
|
1062
1133
|
|
|
1063
1134
|
# Add lock and unlock command
|
|
1064
|
-
if vehicle.capabilities.has_capability('ACCESS'):
|
|
1135
|
+
if vehicle.capabilities.has_capability('ACCESS', check_status_ok=True):
|
|
1065
1136
|
if vehicle.doors is not None and vehicle.doors.commands is not None and vehicle.doors.commands.commands is not None \
|
|
1066
1137
|
and not vehicle.doors.commands.contains_command('lock-unlock'):
|
|
1067
1138
|
lock_unlock_command = LockUnlockCommand(parent=vehicle.doors.commands)
|
|
@@ -1167,6 +1238,8 @@ class Connector(BaseConnector):
|
|
|
1167
1238
|
url = f'https://mysmob.api.connect.skoda-auto.cz/api/v2/vehicle-status/{vin}/driving-range'
|
|
1168
1239
|
range_data: Dict[str, Any] | None = self._fetch_data(url=url, session=self.session, no_cache=no_cache)
|
|
1169
1240
|
if range_data:
|
|
1241
|
+
if 'carCapturedTimestamp' not in range_data or range_data['carCapturedTimestamp'] is None:
|
|
1242
|
+
raise APIError('Could not fetch driving range, carCapturedTimestamp missing')
|
|
1170
1243
|
captured_at: datetime = robust_time_parse(range_data['carCapturedTimestamp'])
|
|
1171
1244
|
# Check vehicle type and if it does not match the current vehicle type, create a new vehicle object using copy constructor
|
|
1172
1245
|
if 'carType' in range_data and range_data['carType'] is not None:
|
|
@@ -1174,7 +1247,7 @@ class Connector(BaseConnector):
|
|
|
1174
1247
|
car_type = GenericVehicle.Type(range_data['carType'])
|
|
1175
1248
|
if car_type == GenericVehicle.Type.ELECTRIC and not isinstance(vehicle, SkodaElectricVehicle):
|
|
1176
1249
|
LOG.debug('Promoting %s to SkodaElectricVehicle object for %s', vehicle.__class__.__name__, vin)
|
|
1177
|
-
vehicle = SkodaElectricVehicle(origin=vehicle)
|
|
1250
|
+
vehicle = SkodaElectricVehicle(garage=self.car_connectivity.garage, origin=vehicle)
|
|
1178
1251
|
self.car_connectivity.garage.replace_vehicle(vin, vehicle)
|
|
1179
1252
|
elif car_type in [GenericVehicle.Type.FUEL,
|
|
1180
1253
|
GenericVehicle.Type.GASOLINE,
|
|
@@ -1184,11 +1257,11 @@ class Connector(BaseConnector):
|
|
|
1184
1257
|
GenericVehicle.Type.LPG] \
|
|
1185
1258
|
and not isinstance(vehicle, SkodaCombustionVehicle):
|
|
1186
1259
|
LOG.debug('Promoting %s to SkodaCombustionVehicle object for %s', vehicle.__class__.__name__, vin)
|
|
1187
|
-
vehicle = SkodaCombustionVehicle(origin=vehicle)
|
|
1260
|
+
vehicle = SkodaCombustionVehicle(garage=self.car_connectivity.garage, origin=vehicle)
|
|
1188
1261
|
self.car_connectivity.garage.replace_vehicle(vin, vehicle)
|
|
1189
1262
|
elif car_type == GenericVehicle.Type.HYBRID and not isinstance(vehicle, SkodaHybridVehicle):
|
|
1190
1263
|
LOG.debug('Promoting %s to SkodaHybridVehicle object for %s', vehicle.__class__.__name__, vin)
|
|
1191
|
-
vehicle = SkodaHybridVehicle(origin=vehicle)
|
|
1264
|
+
vehicle = SkodaHybridVehicle(garage=self.car_connectivity.garage, origin=vehicle)
|
|
1192
1265
|
self.car_connectivity.garage.replace_vehicle(vin, vehicle)
|
|
1193
1266
|
except ValueError:
|
|
1194
1267
|
LOG_API.warning('Unknown car type %s', range_data['carType'])
|
|
@@ -1791,5 +1864,160 @@ class Connector(BaseConnector):
|
|
|
1791
1864
|
raise CommandError(f'Retrying failed: {retry_error}') from retry_error
|
|
1792
1865
|
return command_arguments
|
|
1793
1866
|
|
|
1867
|
+
def __on_window_heating_start_stop(self, start_stop_command: WindowHeatingStartStopCommand, command_arguments: Union[str, Dict[str, Any]]) \
|
|
1868
|
+
-> Union[str, Dict[str, Any]]:
|
|
1869
|
+
if start_stop_command.parent is None or start_stop_command.parent.parent is None \
|
|
1870
|
+
or start_stop_command.parent.parent.parent is None or not isinstance(start_stop_command.parent.parent.parent, SkodaVehicle):
|
|
1871
|
+
raise CommandError('Object hierarchy is not as expected')
|
|
1872
|
+
if not isinstance(command_arguments, dict):
|
|
1873
|
+
raise CommandError('Command arguments are not a dictionary')
|
|
1874
|
+
vehicle: SkodaVehicle = start_stop_command.parent.parent.parent
|
|
1875
|
+
vin: Optional[str] = vehicle.vin.value
|
|
1876
|
+
if vin is None:
|
|
1877
|
+
raise CommandError('VIN in object hierarchy missing')
|
|
1878
|
+
if 'command' not in command_arguments:
|
|
1879
|
+
raise CommandError('Command argument missing')
|
|
1880
|
+
try:
|
|
1881
|
+
if command_arguments['command'] == WindowHeatingStartStopCommand.Command.START:
|
|
1882
|
+
url = f'https://mysmob.api.connect.skoda-auto.cz/api/v2/air-conditioning/{vin}/start-window-heating'
|
|
1883
|
+
command_response: requests.Response = self.session.post(url, allow_redirects=True)
|
|
1884
|
+
elif command_arguments['command'] == WindowHeatingStartStopCommand.Command.STOP:
|
|
1885
|
+
url = f'https://mysmob.api.connect.skoda-auto.cz/api/v2/air-conditioning/{vin}/stop-window-heating'
|
|
1886
|
+
|
|
1887
|
+
command_response: requests.Response = self.session.post(url, allow_redirects=True)
|
|
1888
|
+
else:
|
|
1889
|
+
raise CommandError(f'Unknown command {command_arguments["command"]}')
|
|
1890
|
+
|
|
1891
|
+
if command_response.status_code != requests.codes['accepted']:
|
|
1892
|
+
LOG.error('Could not start/stop window heating (%s: %s)', command_response.status_code, command_response.text)
|
|
1893
|
+
raise CommandError(f'Could not start/stop window heating ({command_response.status_code}: {command_response.text})')
|
|
1894
|
+
except requests.exceptions.ConnectionError as connection_error:
|
|
1895
|
+
raise CommandError(f'Connection error: {connection_error}.'
|
|
1896
|
+
' If this happens frequently, please check if other applications communicate with the Skoda server.') from connection_error
|
|
1897
|
+
except requests.exceptions.ChunkedEncodingError as chunked_encoding_error:
|
|
1898
|
+
raise CommandError(f'Error: {chunked_encoding_error}') from chunked_encoding_error
|
|
1899
|
+
except requests.exceptions.ReadTimeout as timeout_error:
|
|
1900
|
+
raise CommandError(f'Timeout during read: {timeout_error}') from timeout_error
|
|
1901
|
+
except requests.exceptions.RetryError as retry_error:
|
|
1902
|
+
raise CommandError(f'Retrying failed: {retry_error}') from retry_error
|
|
1903
|
+
return command_arguments
|
|
1904
|
+
|
|
1905
|
+
def __on_charging_target_level_change(self, level_attribute: LevelAttribute, target_level: float) -> float:
|
|
1906
|
+
"""
|
|
1907
|
+
Callback for the charging target level change.
|
|
1908
|
+
|
|
1909
|
+
Args:
|
|
1910
|
+
level_attribute (LevelAttribute): The level attribute that changed.
|
|
1911
|
+
target_level (float): The new target level.
|
|
1912
|
+
"""
|
|
1913
|
+
if level_attribute.parent is None or level_attribute.parent.parent is None \
|
|
1914
|
+
or level_attribute.parent.parent.parent is None or not isinstance(level_attribute.parent.parent.parent, SkodaVehicle):
|
|
1915
|
+
raise SetterError('Object hierarchy is not as expected')
|
|
1916
|
+
vehicle: SkodaVehicle = level_attribute.parent.parent.parent
|
|
1917
|
+
vin: Optional[str] = vehicle.vin.value
|
|
1918
|
+
if vin is None:
|
|
1919
|
+
raise SetterError('VIN in object hierarchy missing')
|
|
1920
|
+
precision: float = level_attribute.precision if level_attribute.precision is not None else 10.0
|
|
1921
|
+
target_level = round(target_level / precision) * precision
|
|
1922
|
+
setting_dict = {}
|
|
1923
|
+
setting_dict['targetSOCInPercent'] = target_level
|
|
1924
|
+
|
|
1925
|
+
url = f'https://mysmob.api.connect.skoda-auto.cz/api/v1/charging/{vin}/set-charge-limit'
|
|
1926
|
+
try:
|
|
1927
|
+
settings_response: requests.Response = self.session.put(url, data=json.dumps(setting_dict), allow_redirects=True)
|
|
1928
|
+
if settings_response.status_code != requests.codes['accepted']:
|
|
1929
|
+
LOG.error('Could not set target level (%s)', settings_response.status_code)
|
|
1930
|
+
raise SetterError(f'Could not set value ({settings_response.status_code})')
|
|
1931
|
+
except requests.exceptions.ConnectionError as connection_error:
|
|
1932
|
+
raise SetterError(f'Connection error: {connection_error}.'
|
|
1933
|
+
' If this happens frequently, please check if other applications communicate with the Skoda server.') from connection_error
|
|
1934
|
+
except requests.exceptions.ChunkedEncodingError as chunked_encoding_error:
|
|
1935
|
+
raise SetterError(f'Error: {chunked_encoding_error}') from chunked_encoding_error
|
|
1936
|
+
except requests.exceptions.ReadTimeout as timeout_error:
|
|
1937
|
+
raise SetterError(f'Timeout during read: {timeout_error}') from timeout_error
|
|
1938
|
+
except requests.exceptions.RetryError as retry_error:
|
|
1939
|
+
raise SetterError(f'Retrying failed: {retry_error}') from retry_error
|
|
1940
|
+
return target_level
|
|
1941
|
+
|
|
1942
|
+
def __on_charging_maximum_current_change(self, current_attribute: CurrentAttribute, maximum_current: float) -> float:
|
|
1943
|
+
"""
|
|
1944
|
+
Callback for the charging target level change.
|
|
1945
|
+
|
|
1946
|
+
Args:
|
|
1947
|
+
current_attribute (CurrentAttribute): The current attribute that changed.
|
|
1948
|
+
maximum_current (float): The new maximum current.
|
|
1949
|
+
"""
|
|
1950
|
+
if current_attribute.parent is None or current_attribute.parent.parent is None \
|
|
1951
|
+
or current_attribute.parent.parent.parent is None or not isinstance(current_attribute.parent.parent.parent, SkodaVehicle):
|
|
1952
|
+
raise SetterError('Object hierarchy is not as expected')
|
|
1953
|
+
vehicle: SkodaVehicle = current_attribute.parent.parent.parent
|
|
1954
|
+
vin: Optional[str] = vehicle.vin.value
|
|
1955
|
+
if vin is None:
|
|
1956
|
+
raise SetterError('VIN in object hierarchy missing')
|
|
1957
|
+
setting_dict = {}
|
|
1958
|
+
precision: float = current_attribute.precision if current_attribute.precision is not None else 1.0
|
|
1959
|
+
maximum_current = round(maximum_current / precision) * precision
|
|
1960
|
+
if maximum_current < 16:
|
|
1961
|
+
setting_dict['chargingCurrent'] = "REDUCED"
|
|
1962
|
+
maximum_current = 6.0
|
|
1963
|
+
else:
|
|
1964
|
+
setting_dict['chargingCurrent'] = "MAXIMUM"
|
|
1965
|
+
maximum_current = 16.0
|
|
1966
|
+
|
|
1967
|
+
url = f'https://mysmob.api.connect.skoda-auto.cz/api/v1/charging/{vin}/set-charging-current'
|
|
1968
|
+
try:
|
|
1969
|
+
settings_response: requests.Response = self.session.put(url, data=json.dumps(setting_dict), allow_redirects=True)
|
|
1970
|
+
if settings_response.status_code != requests.codes['accepted']:
|
|
1971
|
+
LOG.error('Could not set target charging current (%s)', settings_response.status_code)
|
|
1972
|
+
raise SetterError(f'Could not set value ({settings_response.status_code})')
|
|
1973
|
+
except requests.exceptions.ConnectionError as connection_error:
|
|
1974
|
+
raise SetterError(f'Connection error: {connection_error}.'
|
|
1975
|
+
' If this happens frequently, please check if other applications communicate with the Skoda server.') from connection_error
|
|
1976
|
+
except requests.exceptions.ChunkedEncodingError as chunked_encoding_error:
|
|
1977
|
+
raise SetterError(f'Error: {chunked_encoding_error}') from chunked_encoding_error
|
|
1978
|
+
except requests.exceptions.ReadTimeout as timeout_error:
|
|
1979
|
+
raise SetterError(f'Timeout during read: {timeout_error}') from timeout_error
|
|
1980
|
+
except requests.exceptions.RetryError as retry_error:
|
|
1981
|
+
raise SetterError(f'Retrying failed: {retry_error}') from retry_error
|
|
1982
|
+
return maximum_current
|
|
1983
|
+
|
|
1984
|
+
def __on_charging_auto_unlock_change(self, boolean_attribute: BooleanAttribute, auto_unlock: bool) -> bool:
|
|
1985
|
+
"""
|
|
1986
|
+
Callback for the charging target level change.
|
|
1987
|
+
|
|
1988
|
+
Args:
|
|
1989
|
+
boolean_attribute (BooleanAttribute): The boolean attribute that changed.
|
|
1990
|
+
auto_unlock (float): The new auto_unlock setting.
|
|
1991
|
+
"""
|
|
1992
|
+
if boolean_attribute.parent is None or boolean_attribute.parent.parent is None \
|
|
1993
|
+
or boolean_attribute.parent.parent.parent is None or not isinstance(boolean_attribute.parent.parent.parent, SkodaVehicle):
|
|
1994
|
+
raise SetterError('Object hierarchy is not as expected')
|
|
1995
|
+
vehicle: SkodaVehicle = boolean_attribute.parent.parent.parent
|
|
1996
|
+
vin: Optional[str] = vehicle.vin.value
|
|
1997
|
+
if vin is None:
|
|
1998
|
+
raise SetterError('VIN in object hierarchy missing')
|
|
1999
|
+
setting_dict = {}
|
|
2000
|
+
if auto_unlock:
|
|
2001
|
+
setting_dict['autoUnlockPlug'] = "PERMANENT"
|
|
2002
|
+
else:
|
|
2003
|
+
setting_dict['autoUnlockPlug'] = "OFF"
|
|
2004
|
+
|
|
2005
|
+
url = f'https://mysmob.api.connect.skoda-auto.cz/api/v1/charging/{vin}/set-auto-unlock-plug'
|
|
2006
|
+
try:
|
|
2007
|
+
settings_response: requests.Response = self.session.put(url, data=json.dumps(setting_dict), allow_redirects=True)
|
|
2008
|
+
if settings_response.status_code != requests.codes['accepted']:
|
|
2009
|
+
LOG.error('Could not set auto unlock setting (%s)', settings_response.status_code)
|
|
2010
|
+
raise SetterError(f'Could not set value ({settings_response.status_code})')
|
|
2011
|
+
except requests.exceptions.ConnectionError as connection_error:
|
|
2012
|
+
raise SetterError(f'Connection error: {connection_error}.'
|
|
2013
|
+
' If this happens frequently, please check if other applications communicate with the Skoda server.') from connection_error
|
|
2014
|
+
except requests.exceptions.ChunkedEncodingError as chunked_encoding_error:
|
|
2015
|
+
raise SetterError(f'Error: {chunked_encoding_error}') from chunked_encoding_error
|
|
2016
|
+
except requests.exceptions.ReadTimeout as timeout_error:
|
|
2017
|
+
raise SetterError(f'Timeout during read: {timeout_error}') from timeout_error
|
|
2018
|
+
except requests.exceptions.RetryError as retry_error:
|
|
2019
|
+
raise SetterError(f'Retrying failed: {retry_error}') from retry_error
|
|
2020
|
+
return auto_unlock
|
|
2021
|
+
|
|
1794
2022
|
def get_name(self) -> str:
|
|
1795
2023
|
return "Skoda Connector"
|
|
@@ -30,7 +30,7 @@ class SkodaVehicle(GenericVehicle): # pylint: disable=too-many-instance-attribu
|
|
|
30
30
|
def __init__(self, vin: Optional[str] = None, garage: Optional[Garage] = None, managing_connector: Optional[BaseConnector] = None,
|
|
31
31
|
origin: Optional[SkodaVehicle] = None) -> None:
|
|
32
32
|
if origin is not None:
|
|
33
|
-
super().__init__(origin=origin)
|
|
33
|
+
super().__init__(garage=garage, origin=origin)
|
|
34
34
|
self.capabilities: Capabilities = origin.capabilities
|
|
35
35
|
self.capabilities.parent = self
|
|
36
36
|
self.in_motion: BooleanAttribute = origin.in_motion
|
|
@@ -55,13 +55,14 @@ class SkodaElectricVehicle(ElectricVehicle, SkodaVehicle):
|
|
|
55
55
|
def __init__(self, vin: Optional[str] = None, garage: Optional[Garage] = None, managing_connector: Optional[BaseConnector] = None,
|
|
56
56
|
origin: Optional[SkodaVehicle] = None) -> None:
|
|
57
57
|
if origin is not None:
|
|
58
|
-
super().__init__(origin=origin)
|
|
58
|
+
super().__init__(garage=garage, origin=origin)
|
|
59
59
|
if isinstance(origin, ElectricVehicle):
|
|
60
|
-
self.charging: Charging = SkodaCharging(origin=origin.charging)
|
|
61
|
-
|
|
60
|
+
self.charging: Charging = SkodaCharging(vehicle=self, origin=origin.charging)
|
|
61
|
+
else:
|
|
62
|
+
self.charging: Charging = SkodaCharging(vehicle=self, origin=self.charging)
|
|
62
63
|
else:
|
|
63
64
|
super().__init__(vin=vin, garage=garage, managing_connector=managing_connector)
|
|
64
|
-
self.charging: Charging = SkodaCharging(vehicle=self)
|
|
65
|
+
self.charging: Charging = SkodaCharging(vehicle=self, origin=self.charging)
|
|
65
66
|
|
|
66
67
|
|
|
67
68
|
class SkodaCombustionVehicle(CombustionVehicle, SkodaVehicle):
|
|
@@ -71,7 +72,7 @@ class SkodaCombustionVehicle(CombustionVehicle, SkodaVehicle):
|
|
|
71
72
|
def __init__(self, vin: Optional[str] = None, garage: Optional[Garage] = None, managing_connector: Optional[BaseConnector] = None,
|
|
72
73
|
origin: Optional[SkodaVehicle] = None) -> None:
|
|
73
74
|
if origin is not None:
|
|
74
|
-
super().__init__(origin=origin)
|
|
75
|
+
super().__init__(garage=garage, origin=origin)
|
|
75
76
|
else:
|
|
76
77
|
super().__init__(vin=vin, garage=garage, managing_connector=managing_connector)
|
|
77
78
|
|
|
@@ -83,6 +84,6 @@ class SkodaHybridVehicle(HybridVehicle, SkodaVehicle):
|
|
|
83
84
|
def __init__(self, vin: Optional[str] = None, garage: Optional[Garage] = None, managing_connector: Optional[BaseConnector] = None,
|
|
84
85
|
origin: Optional[SkodaVehicle] = None) -> None:
|
|
85
86
|
if origin is not None:
|
|
86
|
-
super().__init__(origin=origin)
|
|
87
|
+
super().__init__(garage=garage, origin=origin)
|
|
87
88
|
else:
|
|
88
89
|
super().__init__(vin=vin, garage=garage, managing_connector=managing_connector)
|
|
File without changes
|
|
File without changes
|