carconnectivity-connector-skoda 0.1a19__py3-none-any.whl → 0.1a21__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.

@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.2
2
2
  Name: carconnectivity-connector-skoda
3
- Version: 0.1a19
3
+ Version: 0.1a21
4
4
  Summary: CarConnectivity connector for Skoda services
5
5
  Author: Till Steinbach
6
6
  License: MIT License
@@ -1,12 +1,12 @@
1
1
  carconnectivity_connectors/skoda/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
2
- carconnectivity_connectors/skoda/_version.py,sha256=aeCFhA4z1zQM56Os0M87SAzNslmAdFOPIN0S12RtpgI,409
2
+ carconnectivity_connectors/skoda/_version.py,sha256=-vcE8ACd4f4xkWjtAIGu7OmA4mHDuj0tWUvm5MRRZ38,409
3
3
  carconnectivity_connectors/skoda/capability.py,sha256=JlNEaisVYF8qWv0wNDHTaas36uIpTIQ3NVR69wesiYQ,4513
4
- carconnectivity_connectors/skoda/charging.py,sha256=wkwZG4m-aZn2TGX7BzzZ0J8-mRnSsPmxcFmT0bXy0WU,6669
4
+ carconnectivity_connectors/skoda/charging.py,sha256=rG_GoDPetjyjWCyV6l65hgEDU6ths6MkMQ0KL25rbVU,6663
5
5
  carconnectivity_connectors/skoda/climatization.py,sha256=-Nk4tO5C5_YYNQfUIUWBL7mGgR6-J0_pOZplLK8p_ms,1627
6
- carconnectivity_connectors/skoda/connector.py,sha256=ULF57ZCNk5co04tEeM7_zrpI5xBeoFFRPt1y6VIeql4,105676
6
+ carconnectivity_connectors/skoda/connector.py,sha256=KWQWWz1KIf_Sx2t_wqYCb1yz2FywijI9yXhsWYouLRU,109729
7
7
  carconnectivity_connectors/skoda/error.py,sha256=EnzzDxxJ1fswYT5QnMOVSebfoAcqoPmHKcG5i0Tqk3E,2405
8
- carconnectivity_connectors/skoda/mqtt_client.py,sha256=QUdpjWaEe2zVHS1yZAqfFsmGGcXAkpKUcyeG29StJ5E,37325
9
- carconnectivity_connectors/skoda/vehicle.py,sha256=FbrhxZF-5TOUiPzUvryeFZrT-ie1XIyjRO4RbMymlJs,3115
8
+ carconnectivity_connectors/skoda/mqtt_client.py,sha256=oLmITkh_KKtFyaf2TLxqh2M-nSsKaO0n0t5Vnwd50Sk,37576
9
+ carconnectivity_connectors/skoda/vehicle.py,sha256=JKLqb6F4RyJ4C3D_sc6kcsdlqxZSlmdJNQfW04m7u78,3204
10
10
  carconnectivity_connectors/skoda/auth/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
11
11
  carconnectivity_connectors/skoda/auth/auth_util.py,sha256=dGLUbUre0HBsTg_Ii5vW34f8DLrCykYJYCyzEvUBBEE,4434
12
12
  carconnectivity_connectors/skoda/auth/my_skoda_session.py,sha256=lSh23SFJs8opjmPwHTv-KNIKDep_WY4aItSP4Zq7bT8,10396
@@ -14,8 +14,8 @@ carconnectivity_connectors/skoda/auth/openid_session.py,sha256=LusWi2FZZIL3buodG
14
14
  carconnectivity_connectors/skoda/auth/session_manager.py,sha256=Uf1vujuDBYUCAXhYToOsZkgbTtfmY3Qe0ICTfwomBpI,2899
15
15
  carconnectivity_connectors/skoda/auth/skoda_web_session.py,sha256=cjzMkzx473Sh-4RgZAQULeRRcxB1MboddldCVM_y5LE,10640
16
16
  carconnectivity_connectors/skoda/auth/helpers/blacklist_retry.py,sha256=f3wsiY5bpHDBxp7Va1Mv9nKJ4u3qnCHZZmDu78_AhMk,1251
17
- carconnectivity_connector_skoda-0.1a19.dist-info/LICENSE,sha256=PIwI1alwDyOfvEQHdGCm2u9uf_mGE8030xZDfun0xTo,1071
18
- carconnectivity_connector_skoda-0.1a19.dist-info/METADATA,sha256=YxflkB35eOkKtS7D4nT67RG5Wqw689dGB5toDCb3pY0,5327
19
- carconnectivity_connector_skoda-0.1a19.dist-info/WHEEL,sha256=In9FTNxeP60KnTkGw7wk6mJPYd_dQSjEZmXdBdMCI-8,91
20
- carconnectivity_connector_skoda-0.1a19.dist-info/top_level.txt,sha256=KqA8GviZsDH4PtmnwSQsz0HB_w-TWkeEHLIRNo5dTaI,27
21
- carconnectivity_connector_skoda-0.1a19.dist-info/RECORD,,
17
+ carconnectivity_connector_skoda-0.1a21.dist-info/LICENSE,sha256=PIwI1alwDyOfvEQHdGCm2u9uf_mGE8030xZDfun0xTo,1071
18
+ carconnectivity_connector_skoda-0.1a21.dist-info/METADATA,sha256=bue0YMrsf7JVL00eAshzG1RcLlz1Xh54HZAMz9F2SbE,5327
19
+ carconnectivity_connector_skoda-0.1a21.dist-info/WHEEL,sha256=In9FTNxeP60KnTkGw7wk6mJPYd_dQSjEZmXdBdMCI-8,91
20
+ carconnectivity_connector_skoda-0.1a21.dist-info/top_level.txt,sha256=KqA8GviZsDH4PtmnwSQsz0HB_w-TWkeEHLIRNo5dTaI,27
21
+ carconnectivity_connector_skoda-0.1a21.dist-info/RECORD,,
@@ -12,5 +12,5 @@ __version__: str
12
12
  __version_tuple__: VERSION_TUPLE
13
13
  version_tuple: VERSION_TUPLE
14
14
 
15
- __version__ = version = '0.1a19'
15
+ __version__ = version = '0.1a21'
16
16
  __version_tuple__ = version_tuple = (0, 1)
@@ -69,7 +69,7 @@ class SkodaCharging(Charging): # pylint: disable=too-many-instance-attributes
69
69
  CONNECT_CABLE = 'connectCable'
70
70
  READY_FOR_CHARGING = 'readyForCharging'
71
71
  NOT_READY_FOR_CHARGING = 'notReadyForCharging'
72
- CONSERVATION = 'conservation'
72
+ CONSERVING = 'conserving'
73
73
  CHARGE_PURPOSE_REACHED_NOT_CONSERVATION_CHARGING = 'chargePurposeReachedAndNotConservationCharging'
74
74
  CHARGE_PURPOSE_REACHED_CONSERVATION = 'chargePurposeReachedAndConservation'
75
75
  CHARGING = 'charging'
@@ -126,7 +126,7 @@ mapping_skoda_charging_state: Dict[SkodaCharging.SkodaChargingState, Charging.Ch
126
126
  SkodaCharging.SkodaChargingState.CONNECT_CABLE: Charging.ChargingState.OFF,
127
127
  SkodaCharging.SkodaChargingState.READY_FOR_CHARGING: Charging.ChargingState.READY_FOR_CHARGING,
128
128
  SkodaCharging.SkodaChargingState.NOT_READY_FOR_CHARGING: Charging.ChargingState.OFF,
129
- SkodaCharging.SkodaChargingState.CONSERVATION: Charging.ChargingState.CONSERVATION,
129
+ SkodaCharging.SkodaChargingState.CONSERVING: Charging.ChargingState.CONSERVATION,
130
130
  SkodaCharging.SkodaChargingState.CHARGE_PURPOSE_REACHED_NOT_CONSERVATION_CHARGING: Charging.ChargingState.READY_FOR_CHARGING,
131
131
  SkodaCharging.SkodaChargingState.CHARGE_PURPOSE_REACHED_CONSERVATION: Charging.ChargingState.CONSERVATION,
132
132
  SkodaCharging.SkodaChargingState.CHARGING: Charging.ChargingState.CHARGING,
@@ -27,7 +27,7 @@ from carconnectivity.charging import Charging
27
27
  from carconnectivity.position import Position
28
28
  from carconnectivity.climatization import Climatization
29
29
  from carconnectivity.charging_connector import ChargingConnector
30
- from carconnectivity.command_impl import ClimatizationStartStopCommand
30
+ from carconnectivity.command_impl import ClimatizationStartStopCommand, ChargingStartStopCommand
31
31
 
32
32
  from carconnectivity_connectors.base.connector import BaseConnector
33
33
  from carconnectivity_connectors.skoda.auth.session_manager import SessionManager, SessionUser, Service
@@ -75,20 +75,20 @@ class Connector(BaseConnector):
75
75
  # Configure logging
76
76
  if 'log_level' in config and config['log_level'] is not None:
77
77
  config['log_level'] = config['log_level'].upper()
78
- if config['log_level'] in logging.getLevelNamesMapping():
78
+ if config['log_level'] in logging._nameToLevel:
79
79
  LOG.setLevel(config['log_level'])
80
80
  self.log_level._set_value(config['log_level']) # pylint: disable=protected-access
81
81
  logging.getLogger('requests').setLevel(config['log_level'])
82
82
  logging.getLogger('urllib3').setLevel(config['log_level'])
83
83
  logging.getLogger('oauthlib').setLevel(config['log_level'])
84
84
  else:
85
- raise ConfigurationError(f'Invalid log level: "{config["log_level"]}" not in {list(logging.getLevelNamesMapping().keys())}')
85
+ raise ConfigurationError(f'Invalid log level: "{config["log_level"]}" not in {list(logging._nameToLevel.keys())}')
86
86
  if 'api_log_level' in config and config['api_log_level'] is not None:
87
87
  config['api_log_level'] = config['api_log_level'].upper()
88
- if config['api_log_level'] in logging.getLevelNamesMapping():
88
+ if config['api_log_level'] in logging._nameToLevel:
89
89
  LOG_API.setLevel(config['api_log_level'])
90
90
  else:
91
- raise ConfigurationError(f'Invalid log level: "{config["log_level"]}" not in {list(logging.getLevelNamesMapping().keys())}')
91
+ raise ConfigurationError(f'Invalid log level: "{config["log_level"]}" not in {list(logging._nameToLevel.keys())}')
92
92
  LOG.info("Loading skoda connector with config %s", config_remove_credentials(self.config))
93
93
 
94
94
  username: Optional[str] = None
@@ -287,7 +287,12 @@ class Connector(BaseConnector):
287
287
  else:
288
288
  vehicle.license_plate._set_value(None) # pylint: disable=protected-access
289
289
 
290
- log_extra_keys(LOG_API, 'vehicles', vehicle_dict, {'vin', 'licensePlate'})
290
+ if 'name' in vehicle_dict and vehicle_dict['name'] is not None:
291
+ vehicle.name._set_value(vehicle_dict['name']) # pylint: disable=protected-access
292
+ else:
293
+ vehicle.name._set_value(None) # pylint: disable=protected-access
294
+
295
+ log_extra_keys(LOG_API, 'vehicles', vehicle_dict, {'vin', 'licensePlate', 'name'})
291
296
 
292
297
  vehicle = self.fetch_vehicle_details(vehicle)
293
298
  else:
@@ -343,6 +348,10 @@ class Connector(BaseConnector):
343
348
  url = f'https://mysmob.api.connect.skoda-auto.cz/api/v1/charging/{vin}'
344
349
  data: Dict[str, Any] | None = self._fetch_data(url=url, session=self.session, no_cache=no_cache)
345
350
  if data is not None:
351
+ start_stop_command: ChargingStartStopCommand = ChargingStartStopCommand(parent=vehicle.charging.commands)
352
+ start_stop_command._add_on_set_hook(self.__on_charging_start_stop) # pylint: disable=protected-access
353
+ start_stop_command.enabled = True
354
+ vehicle.charging.commands.add_command(start_stop_command)
346
355
  if 'carCapturedTimestamp' in data and data['carCapturedTimestamp'] is not None:
347
356
  captured_at: datetime = robust_time_parse(data['carCapturedTimestamp'])
348
357
  else:
@@ -1000,7 +1009,10 @@ class Connector(BaseConnector):
1000
1009
  url = f'https://mysmob.api.connect.skoda-auto.cz/api/v2/vehicle-status/{vin}'
1001
1010
  vehicle_status_data: Dict[str, Any] | None = self._fetch_data(url=url, session=self.session, no_cache=no_cache)
1002
1011
  if vehicle_status_data:
1003
- captured_at: datetime = robust_time_parse(vehicle_status_data['carCapturedTimestamp'])
1012
+ if 'carCapturedTimestamp' in vehicle_status_data and vehicle_status_data['carCapturedTimestamp'] is not None:
1013
+ captured_at: Optional[datetime] = robust_time_parse(vehicle_status_data['carCapturedTimestamp'])
1014
+ else:
1015
+ captured_at: Optional[datetime] = None
1004
1016
  if 'overall' in vehicle_status_data and vehicle_status_data['overall'] is not None:
1005
1017
  if 'doorsLocked' in vehicle_status_data['overall'] and vehicle_status_data['overall']['doorsLocked'] is not None \
1006
1018
  and vehicle.doors is not None:
@@ -1421,11 +1433,24 @@ class Connector(BaseConnector):
1421
1433
  raise SetterError(f'Unknown temperature unit {command_arguments['target_temperature_unit']}')
1422
1434
  else:
1423
1435
  command_dict['targetTemperature']['unitInCar'] = 'CELSIUS'
1436
+ elif start_stop_command.parent is not None and (climatization := start_stop_command.parent.parent) is not None \
1437
+ and isinstance(climatization, Climatization) and climatization.settings is not None \
1438
+ and climatization.settings.target_temperature is not None and climatization.settings.target_temperature.enabled \
1439
+ and climatization.settings.target_temperature.value is not None: # pylint: disable=too-many-boolean-expressions
1440
+ # Round target temperature to nearest 0.5
1441
+ command_dict['targetTemperature']['temperatureValue'] = round(climatization.settings.target_temperature.value * 2) / 2
1442
+ if climatization.settings.target_temperature.unit == Temperature.C:
1443
+ command_dict['targetTemperature']['unitInCar'] = 'CELSIUS'
1444
+ elif climatization.settings.target_temperature.unit == Temperature.F:
1445
+ command_dict['targetTemperature']['unitInCar'] = 'FAHRENHEIT'
1446
+ elif climatization.settings.target_temperature.unit == Temperature.K:
1447
+ command_dict['targetTemperature']['unitInCar'] = 'KELVIN'
1448
+ else:
1449
+ raise SetterError(f'Unknown temperature unit {climatization.settings.target_temperature.unit}')
1424
1450
  else:
1425
1451
  command_dict['targetTemperature']['temperatureValue'] = 25.0
1426
1452
  command_dict['targetTemperature']['unitInCar'] = 'CELSIUS'
1427
1453
  url = f'https://mysmob.api.connect.skoda-auto.cz/api/v2/air-conditioning/{vin}/start'
1428
- print(json.dumps(command_dict))
1429
1454
  settings_response: requests.Response = self.session.post(url, data=json.dumps(command_dict), allow_redirects=True)
1430
1455
  elif command_arguments['command'] == ClimatizationStartStopCommand.Command.STOP:
1431
1456
  url = f'https://mysmob.api.connect.skoda-auto.cz/api/v2/air-conditioning/{vin}/stop'
@@ -1437,3 +1462,30 @@ class Connector(BaseConnector):
1437
1462
  LOG.error('Could not start/stop air conditioning (%s: %s)', settings_response.status_code, settings_response.text)
1438
1463
  raise SetterError(f'Could not start/stop air conditioning ({settings_response.status_code}: {settings_response.text})')
1439
1464
  return command_arguments
1465
+
1466
+ def __on_charging_start_stop(self, start_stop_command: ChargingStartStopCommand, command_arguments: Union[str, Dict[str, Any]]) \
1467
+ -> Union[str, Dict[str, Any]]:
1468
+ if start_stop_command.parent is None or start_stop_command.parent.parent is None \
1469
+ or start_stop_command.parent.parent.parent is None or not isinstance(start_stop_command.parent.parent.parent, SkodaVehicle):
1470
+ raise SetterError('Object hierarchy is not as expected')
1471
+ if not isinstance(command_arguments, dict):
1472
+ raise SetterError('Command arguments are not a dictionary')
1473
+ vehicle: SkodaVehicle = start_stop_command.parent.parent.parent
1474
+ vin: Optional[str] = vehicle.vin.value
1475
+ if vin is None:
1476
+ raise SetterError('VIN in object hierarchy missing')
1477
+ if 'command' not in command_arguments:
1478
+ raise SetterError('Command argument missing')
1479
+ if command_arguments['command'] == ChargingStartStopCommand.Command.START:
1480
+ url = f'https://mysmob.api.connect.skoda-auto.cz/api/v1/charging/{vin}/start'
1481
+ settings_response: requests.Response = self.session.post(url, allow_redirects=True)
1482
+ elif command_arguments['command'] == ChargingStartStopCommand.Command.STOP:
1483
+ url = f'https://mysmob.api.connect.skoda-auto.cz/api/v1/charging/{vin}/stop'
1484
+ settings_response: requests.Response = self.session.post(url, allow_redirects=True)
1485
+ else:
1486
+ raise SetterError(f'Unknown command {command_arguments["command"]}')
1487
+
1488
+ if settings_response.status_code != requests.codes['accepted']:
1489
+ LOG.error('Could not start/stop charging (%s: %s)', settings_response.status_code, settings_response.text)
1490
+ raise SetterError(f'Could not start/stop charging ({settings_response.status_code}: {settings_response.text})')
1491
+ return command_arguments
@@ -530,7 +530,7 @@ class SkodaMQTTClient(Client): # pylint: disable=too-many-instance-attributes
530
530
  try:
531
531
  self._skoda_connector.fetch_air_conditioning(vehicle, no_cache=True)
532
532
  except CarConnectivityError as e:
533
- LOG.error('Error while fetching charging: %s', e)
533
+ LOG.error('Error while fetching air conditioning: %s', e)
534
534
  elif 'name' in data and data['name'] == 'climatisation-completed':
535
535
  if 'data' in data and data['data'] is not None:
536
536
  vehicle: Optional[GenericVehicle] = self._skoda_connector.car_connectivity.garage.get_vehicle(vin)
@@ -628,7 +628,7 @@ class SkodaMQTTClient(Client): # pylint: disable=too-many-instance-attributes
628
628
  elif data['status'] == 'IN_PROGRESS':
629
629
  LOG.debug('Received %s operation request for vehicle %s from user %s', operation_request, vin, user_id)
630
630
  return
631
- if operation_request == 'charging/start-stop-charging' \
631
+ elif operation_request == 'charging/start-stop-charging' \
632
632
  or operation_request == 'charging/update-battery-support' \
633
633
  or operation_request == 'charging/update-auto-unlock-plug' \
634
634
  or operation_request == 'charging/update-care-mode' \
@@ -645,6 +645,9 @@ class SkodaMQTTClient(Client): # pylint: disable=too-many-instance-attributes
645
645
  except CarConnectivityError as e:
646
646
  LOG.error('Error while fetching charging: %s', e)
647
647
  return
648
+ elif data['status'] == 'IN_PROGRESS':
649
+ LOG.debug('Received %s operation request for vehicle %s from user %s', operation_request, vin, user_id)
650
+ return
648
651
  LOG_API.info('Received unknown operation request %s for vehicle %s from user %s: %s', operation_request, vin, user_id, msg.payload)
649
652
  return
650
653
  LOG_API.info('I don\'t understand message %s: %s', msg.topic, msg.payload)
@@ -27,6 +27,7 @@ class SkodaVehicle(GenericVehicle): # pylint: disable=too-many-instance-attribu
27
27
  else:
28
28
  super().__init__(vin=vin, garage=garage, managing_connector=managing_connector)
29
29
  self.capabilities = Capabilities(vehicle=self)
30
+ self.manufacturer._set_value(value='Škoda') # pylint: disable=protected-access
30
31
 
31
32
  def __str__(self) -> str:
32
33
  return_string: str = f'\t{self.capabilities}\n'