carconnectivity-connector-seatcupra 0.1a9__py3-none-any.whl → 0.1a11__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.
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.2
2
2
  Name: carconnectivity-connector-seatcupra
3
- Version: 0.1a9
3
+ Version: 0.1a11
4
4
  Summary: CarConnectivity connector for Seat and Cupra services
5
5
  Author: Till Steinbach
6
6
  License: MIT License
@@ -1,10 +1,10 @@
1
1
  carconnectivity_connectors/seatcupra/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
2
- carconnectivity_connectors/seatcupra/_version.py,sha256=rlAEvHjbUbB_6ulox6umdIibeWKto1PkQr90bInTEUk,508
2
+ carconnectivity_connectors/seatcupra/_version.py,sha256=8hC_LLpTTiKrt81VVDKjTD0LIQ0Qtf_-ak-wISSul2I,509
3
3
  carconnectivity_connectors/seatcupra/capability.py,sha256=Oe9tC_u69bj6VmOuNJ21RKoETe2j3QyZCoz-VgcZPQ0,4523
4
4
  carconnectivity_connectors/seatcupra/charging.py,sha256=BJe_5GEB0JkP78tpU6kyKpwuwjDZHvm-kt3PTlpQHeU,3336
5
5
  carconnectivity_connectors/seatcupra/climatization.py,sha256=0xxWlxrheAPzkVT8WRQtbm6ExZmVdgW7lUdOXyS_qWY,1695
6
6
  carconnectivity_connectors/seatcupra/command_impl.py,sha256=mtw8ZwJLmf79fPDZ1N3ImLfB8Gt9JPbzjMuIo2y5v3M,2879
7
- carconnectivity_connectors/seatcupra/connector.py,sha256=MQ5zGNO051feTZUt23J-TJLQUKdOlzG3pYyeOVAGsaw,99318
7
+ carconnectivity_connectors/seatcupra/connector.py,sha256=fmn62rMBt7IKRv-fLU0UpjMLSADCK_DzAeRP9ry_IwY,100546
8
8
  carconnectivity_connectors/seatcupra/vehicle.py,sha256=kiFVbJgq5VQOzf-vSli_2NsMgY0x4pwvJsjPWLGdr1g,3404
9
9
  carconnectivity_connectors/seatcupra/auth/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
10
10
  carconnectivity_connectors/seatcupra/auth/auth_util.py,sha256=Y81h8fGOMSMgPtE4wI_TI9WgE_s43uaPjRLBBINhj4g,4433
@@ -14,8 +14,8 @@ carconnectivity_connectors/seatcupra/auth/session_manager.py,sha256=ZIDvC848T3fy
14
14
  carconnectivity_connectors/seatcupra/auth/vw_web_session.py,sha256=CcI6m68IyRs6WsMDu-IsW3Dj85vyGiMmxvFqNETMHO0,10929
15
15
  carconnectivity_connectors/seatcupra/auth/helpers/blacklist_retry.py,sha256=f3wsiY5bpHDBxp7Va1Mv9nKJ4u3qnCHZZmDu78_AhMk,1251
16
16
  carconnectivity_connectors/seatcupra/ui/connector_ui.py,sha256=SNYnlcGJpbWhuLiIHD2l6H9IfSiMz3IgmvXsdossDnE,1412
17
- carconnectivity_connector_seatcupra-0.1a9.dist-info/LICENSE,sha256=PIwI1alwDyOfvEQHdGCm2u9uf_mGE8030xZDfun0xTo,1071
18
- carconnectivity_connector_seatcupra-0.1a9.dist-info/METADATA,sha256=kyYnObMmCNMI6P-UffPUKDtadkObQHCb8TVf_jWQ4Vw,5640
19
- carconnectivity_connector_seatcupra-0.1a9.dist-info/WHEEL,sha256=nn6H5-ilmfVryoAQl3ZQ2l8SH5imPWFpm1A5FgEuFV4,91
20
- carconnectivity_connector_seatcupra-0.1a9.dist-info/top_level.txt,sha256=KqA8GviZsDH4PtmnwSQsz0HB_w-TWkeEHLIRNo5dTaI,27
21
- carconnectivity_connector_seatcupra-0.1a9.dist-info/RECORD,,
17
+ carconnectivity_connector_seatcupra-0.1a11.dist-info/LICENSE,sha256=PIwI1alwDyOfvEQHdGCm2u9uf_mGE8030xZDfun0xTo,1071
18
+ carconnectivity_connector_seatcupra-0.1a11.dist-info/METADATA,sha256=Kdviy1kwi2S9KrNRWfyf-GGfsPdBYcD5dBOkCQh6WRw,5641
19
+ carconnectivity_connector_seatcupra-0.1a11.dist-info/WHEEL,sha256=nn6H5-ilmfVryoAQl3ZQ2l8SH5imPWFpm1A5FgEuFV4,91
20
+ carconnectivity_connector_seatcupra-0.1a11.dist-info/top_level.txt,sha256=KqA8GviZsDH4PtmnwSQsz0HB_w-TWkeEHLIRNo5dTaI,27
21
+ carconnectivity_connector_seatcupra-0.1a11.dist-info/RECORD,,
@@ -17,5 +17,5 @@ __version__: str
17
17
  __version_tuple__: VERSION_TUPLE
18
18
  version_tuple: VERSION_TUPLE
19
19
 
20
- __version__ = version = '0.1a9'
20
+ __version__ = version = '0.1a11'
21
21
  __version_tuple__ = version_tuple = (0, 1)
@@ -252,8 +252,8 @@ class Connector(BaseConnector):
252
252
  Updates the status of all vehicles in the garage managed by this connector.
253
253
 
254
254
  This method iterates through all vehicle VINs in the garage, and for each vehicle that is
255
- managed by this connector and is an instance of SkodaVehicle, it updates the vehicle's status
256
- by fetching data from various APIs. If the vehicle is an instance of SkodaElectricVehicle,
255
+ managed by this connector and is an instance of Seat/CupraVehicle, it updates the vehicle's status
256
+ by fetching data from various APIs. If the vehicle is an instance of Seat/CupraElectricVehicle,
257
257
  it also fetches charging information.
258
258
 
259
259
  Returns:
@@ -277,8 +277,8 @@ class Connector(BaseConnector):
277
277
 
278
278
  def fetch_vehicles(self) -> None:
279
279
  """
280
- Fetches the list of vehicles from the Skoda Connect API and updates the garage with new vehicles.
281
- This method sends a request to the Skoda Connect API to retrieve the list of vehicles associated with the user's account.
280
+ Fetches the list of vehicles from the Seat/Cupra Connect API and updates the garage with new vehicles.
281
+ This method sends a request to the Seat/Cupra Connect API to retrieve the list of vehicles associated with the user's account.
282
282
  If new vehicles are found in the response, they are added to the garage.
283
283
 
284
284
  Returns:
@@ -688,10 +688,10 @@ class Connector(BaseConnector):
688
688
  Fetches the position of the given vehicle and updates its position attributes.
689
689
 
690
690
  Args:
691
- vehicle (SkodaVehicle): The vehicle object containing the VIN and position attributes.
691
+ vehicle (Seat/CupraVehicle): The vehicle object containing the VIN and position attributes.
692
692
 
693
693
  Returns:
694
- SkodaVehicle: The updated vehicle object with the fetched position data.
694
+ Seat/CupraVehicle: The updated vehicle object with the fetched position data.
695
695
 
696
696
  Raises:
697
697
  APIError: If the VIN is missing.
@@ -728,10 +728,10 @@ class Connector(BaseConnector):
728
728
  Fetches the mileage of the given vehicle and updates its mileage attributes.
729
729
 
730
730
  Args:
731
- vehicle (SkodaVehicle): The vehicle object containing the VIN and mileage attributes.
731
+ vehicle (Seat/CupraVehicle): The vehicle object containing the VIN and mileage attributes.
732
732
 
733
733
  Returns:
734
- SkodaVehicle: The updated vehicle object with the fetched mileage data.
734
+ Seat/CupraVehicle: The updated vehicle object with the fetched mileage data.
735
735
 
736
736
  Raises:
737
737
  APIError: If the VIN is missing.
@@ -793,10 +793,10 @@ class Connector(BaseConnector):
793
793
  Fetches the mileage of the given vehicle and updates its mileage attributes.
794
794
 
795
795
  Args:
796
- vehicle (SkodaVehicle): The vehicle object containing the VIN and mileage attributes.
796
+ vehicle (Seat/CupraVehicle): The vehicle object containing the VIN and mileage attributes.
797
797
 
798
798
  Returns:
799
- SkodaVehicle: The updated vehicle object with the fetched mileage data.
799
+ Seat/CupraVehicle: The updated vehicle object with the fetched mileage data.
800
800
 
801
801
  Raises:
802
802
  APIError: If the VIN is missing.
@@ -876,10 +876,10 @@ class Connector(BaseConnector):
876
876
  Fetches the mileage of the given vehicle and updates its mileage attributes.
877
877
 
878
878
  Args:
879
- vehicle (SkodaVehicle): The vehicle object containing the VIN and mileage attributes.
879
+ vehicle (Seat/CupraVehicle): The vehicle object containing the VIN and mileage attributes.
880
880
 
881
881
  Returns:
882
- SkodaVehicle: The updated vehicle object with the fetched mileage data.
882
+ Seat/CupraVehicle: The updated vehicle object with the fetched mileage data.
883
883
 
884
884
  Raises:
885
885
  APIError: If the VIN is missing.
@@ -1074,7 +1074,7 @@ class Connector(BaseConnector):
1074
1074
  raise RetrievalError(f'Could not fetch data. Status Code was: {status_response.status_code}')
1075
1075
  except requests.exceptions.ConnectionError as connection_error:
1076
1076
  raise RetrievalError(f'Connection error: {connection_error}.'
1077
- ' If this happens frequently, please check if other applications communicate with the Skoda server.') from connection_error
1077
+ ' If this happens frequently, please check if other applications communicate with the Seat/Cupra server.') from connection_error
1078
1078
  except requests.exceptions.ChunkedEncodingError as chunked_encoding_error:
1079
1079
  raise RetrievalError(f'Error: {chunked_encoding_error}') from chunked_encoding_error
1080
1080
  except requests.exceptions.ReadTimeout as timeout_error:
@@ -1126,7 +1126,7 @@ class Connector(BaseConnector):
1126
1126
  raise CommandError(f'Could not start/stop charging ({command_response.status_code}: {command_response.text})')
1127
1127
  except requests.exceptions.ConnectionError as connection_error:
1128
1128
  raise CommandError(f'Connection error: {connection_error}.'
1129
- ' If this happens frequently, please check if other applications communicate with the Skoda server.') from connection_error
1129
+ ' If this happens frequently, please check if other applications communicate with the Seat/Cupra server.') from connection_error
1130
1130
  except requests.exceptions.ChunkedEncodingError as chunked_encoding_error:
1131
1131
  raise CommandError(f'Error: {chunked_encoding_error}') from chunked_encoding_error
1132
1132
  except requests.exceptions.ReadTimeout as timeout_error:
@@ -1185,7 +1185,7 @@ class Connector(BaseConnector):
1185
1185
  raise CommandError(f'Could not start/stop air conditioning ({command_response.status_code}: {command_response.text})')
1186
1186
  except requests.exceptions.ConnectionError as connection_error:
1187
1187
  raise CommandError(f'Connection error: {connection_error}.'
1188
- ' If this happens frequently, please check if other applications communicate with the Skoda server.') from connection_error
1188
+ ' If this happens frequently, please check if other applications communicate with the Seat/Cupra server.') from connection_error
1189
1189
  except requests.exceptions.ChunkedEncodingError as chunked_encoding_error:
1190
1190
  raise CommandError(f'Error: {chunked_encoding_error}') from chunked_encoding_error
1191
1191
  except requests.exceptions.ReadTimeout as timeout_error:
@@ -1194,6 +1194,23 @@ class Connector(BaseConnector):
1194
1194
  raise CommandError(f'Retrying failed: {retry_error}') from retry_error
1195
1195
  return command_arguments
1196
1196
 
1197
+ def __fetchSecurityToken(self, spin: str) -> str:
1198
+ """
1199
+ Fetches the security token from the server.
1200
+
1201
+ Returns:
1202
+ str: The security token.
1203
+ """
1204
+ command_dict = {'spin': spin}
1205
+ url = f'https://ola.prod.code.seat.cloud.vwgroup.com/v2/users/{self.session.user_id}/spin/verify'
1206
+ spin_verify_response: requests.Response = self.session.post(url, data=json.dumps(command_dict), allow_redirects=True)
1207
+ if spin_verify_response.status_code != requests.codes['created']:
1208
+ raise AuthenticationError(f'Could not fetch security token ({spin_verify_response.status_code}: {spin_verify_response.text})')
1209
+ data = spin_verify_response.json()
1210
+ if 'securityToken' in data:
1211
+ return data['securityToken']
1212
+ raise AuthenticationError('Could not fetch security token')
1213
+
1197
1214
  def __on_spin(self, spin_command: SpinCommand, command_arguments: Union[str, Dict[str, Any]]) \
1198
1215
  -> Union[str, Dict[str, Any]]:
1199
1216
  del spin_command
@@ -1216,14 +1233,14 @@ class Connector(BaseConnector):
1216
1233
  raise CommandError(f'Unknown command {command_arguments["command"]}')
1217
1234
  try:
1218
1235
  command_response: requests.Response = self.session.post(url, data=json.dumps(command_dict), allow_redirects=True)
1219
- if command_response.status_code != requests.codes['ok']:
1236
+ if command_response.status_code != requests.codes['created']:
1220
1237
  LOG.error('Could not execute spin command (%s: %s)', command_response.status_code, command_response.text)
1221
1238
  raise CommandError(f'Could not execute spin command ({command_response.status_code}: {command_response.text})')
1222
1239
  else:
1223
1240
  LOG.info('Spin verify command executed successfully')
1224
1241
  except requests.exceptions.ConnectionError as connection_error:
1225
1242
  raise CommandError(f'Connection error: {connection_error}.'
1226
- ' If this happens frequently, please check if other applications communicate with the Skoda server.') from connection_error
1243
+ ' If this happens frequently, please check if other applications communicate with the Seat/Cupra server.') from connection_error
1227
1244
  except requests.exceptions.ChunkedEncodingError as chunked_encoding_error:
1228
1245
  raise CommandError(f'Error: {chunked_encoding_error}') from chunked_encoding_error
1229
1246
  except requests.exceptions.ReadTimeout as timeout_error:
@@ -1255,7 +1272,7 @@ class Connector(BaseConnector):
1255
1272
  raise CommandError(f'Could not execute wake command ({command_response.status_code}: {command_response.text})')
1256
1273
  except requests.exceptions.ConnectionError as connection_error:
1257
1274
  raise CommandError(f'Connection error: {connection_error}.'
1258
- ' If this happens frequently, please check if other applications communicate with the Skoda server.') from connection_error
1275
+ ' If this happens frequently, please check if other applications communicate with the Seat/Cupra server.') from connection_error
1259
1276
  except requests.exceptions.ChunkedEncodingError as chunked_encoding_error:
1260
1277
  raise CommandError(f'Error: {chunked_encoding_error}') from chunked_encoding_error
1261
1278
  except requests.exceptions.ReadTimeout as timeout_error:
@@ -1304,7 +1321,7 @@ class Connector(BaseConnector):
1304
1321
  raise CommandError(f'Could not execute honk or flash command ({command_response.status_code}: {command_response.text})')
1305
1322
  except requests.exceptions.ConnectionError as connection_error:
1306
1323
  raise CommandError(f'Connection error: {connection_error}.'
1307
- ' If this happens frequently, please check if other applications communicate with the Skoda server.') from connection_error
1324
+ ' If this happens frequently, please check if other applications communicate with the Seat/Cupra server.') from connection_error
1308
1325
  except requests.exceptions.ChunkedEncodingError as chunked_encoding_error:
1309
1326
  raise CommandError(f'Error: {chunked_encoding_error}') from chunked_encoding_error
1310
1327
  except requests.exceptions.ReadTimeout as timeout_error:
@@ -1330,11 +1347,12 @@ class Connector(BaseConnector):
1330
1347
  raise CommandError('Command argument missing')
1331
1348
  command_dict = {}
1332
1349
  if 'spin' in command_arguments:
1333
- command_dict['spin'] = command_arguments['spin']
1350
+ spin = command_arguments['spin']
1334
1351
  else:
1335
1352
  if self.active_config['spin'] is None:
1336
1353
  raise CommandError('S-PIN is missing, please add S-PIN to your configuration or .netrc file')
1337
- command_dict['spin'] = self.active_config['spin']
1354
+ spin = self.active_config['spin']
1355
+ sec_token = self.__fetchSecurityToken(spin)
1338
1356
  if command_arguments['command'] == LockUnlockCommand.Command.LOCK:
1339
1357
  url = f'https://ola.prod.code.seat.cloud.vwgroup.com/v1/vehicles/{vin}/access/lock'
1340
1358
  elif command_arguments['command'] == LockUnlockCommand.Command.UNLOCK:
@@ -1342,19 +1360,23 @@ class Connector(BaseConnector):
1342
1360
  else:
1343
1361
  raise CommandError(f'Unknown command {command_arguments["command"]}')
1344
1362
  try:
1345
- command_response: requests.Response = self.session.post(url, data=json.dumps(command_dict), allow_redirects=True)
1363
+ headers = self.session.headers.copy()
1364
+ headers['SecToken'] = sec_token
1365
+ command_response: requests.Response = self.session.post(url, data=json.dumps(command_dict), allow_redirects=True, headers=headers)
1346
1366
  if command_response.status_code != requests.codes['ok']:
1347
1367
  LOG.error('Could not execute locking command (%s: %s)', command_response.status_code, command_response.text)
1348
1368
  raise CommandError(f'Could not execute locking command ({command_response.status_code}: {command_response.text})')
1349
1369
  except requests.exceptions.ConnectionError as connection_error:
1350
1370
  raise CommandError(f'Connection error: {connection_error}.'
1351
- ' If this happens frequently, please check if other applications communicate with the Skoda server.') from connection_error
1371
+ ' If this happens frequently, please check if other applications communicate with the Seat/Cupra server.') from connection_error
1352
1372
  except requests.exceptions.ChunkedEncodingError as chunked_encoding_error:
1353
1373
  raise CommandError(f'Error: {chunked_encoding_error}') from chunked_encoding_error
1354
1374
  except requests.exceptions.ReadTimeout as timeout_error:
1355
1375
  raise CommandError(f'Timeout during read: {timeout_error}') from timeout_error
1356
1376
  except requests.exceptions.RetryError as retry_error:
1357
1377
  raise CommandError(f'Retrying failed: {retry_error}') from retry_error
1378
+ except AuthenticationError as auth_error:
1379
+ raise CommandError(f'Authentication error: {auth_error}') from auth_error
1358
1380
  return command_arguments
1359
1381
 
1360
1382
  def __on_air_conditioning_settings_change(self, attribute: GenericAttribute, value: Any) -> Any:
@@ -1397,7 +1419,7 @@ class Connector(BaseConnector):
1397
1419
  raise SetterError(f'Could not set value ({settings_response.status_code}): {settings_response.text}')
1398
1420
  except requests.exceptions.ConnectionError as connection_error:
1399
1421
  raise SetterError(f'Connection error: {connection_error}.'
1400
- ' If this happens frequently, please check if other applications communicate with the Skoda server.') from connection_error
1422
+ ' If this happens frequently, please check if other applications communicate with the Seat/Cupra server.') from connection_error
1401
1423
  except requests.exceptions.ChunkedEncodingError as chunked_encoding_error:
1402
1424
  raise SetterError(f'Error: {chunked_encoding_error}') from chunked_encoding_error
1403
1425
  except requests.exceptions.ReadTimeout as timeout_error: