pycupra 0.0.13__py3-none-any.whl → 0.0.14__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.
pycupra/__version__.py CHANGED
@@ -3,4 +3,4 @@ pycupra - A Python 3 library for interacting with the My Cupra/My Seat portal.
3
3
 
4
4
  For more details and documentation, visit the github page at https://github.com/WulfgarW/pycupra
5
5
  """
6
- __version__ = "0.0.13"
6
+ __version__ = "0.0.14"
pycupra/connection.py CHANGED
@@ -108,11 +108,12 @@ TIMEOUT = timedelta(seconds=90)
108
108
  class Connection:
109
109
  """ Connection to Connect services """
110
110
  # Init connection class
111
- def __init__(self, session, brand='cupra', username='', password='', fulldebug=False, **optional):
111
+ def __init__(self, session, brand='cupra', username='', password='', fulldebug=False, nightlyUpdateReduction=False, **optional):
112
112
  """ Initialize """
113
113
  self._session = session
114
114
  self._lock = asyncio.Lock()
115
115
  self._session_fulldebug = fulldebug
116
+ self._session_nightlyUpdateReduction = nightlyUpdateReduction
116
117
  self._session_headers = HEADERS_SESSION.get(brand).copy()
117
118
  self._session_base = BASE_SESSION
118
119
  self._session_auth_headers = HEADERS_AUTH.copy()
@@ -1369,6 +1370,8 @@ class Connection:
1369
1370
  if mode in {'start', 'stop'}:
1370
1371
  capability='charging'
1371
1372
  return await self._setViaAPI(eval(f"f'{API_REQUESTS}/{mode}'"))
1373
+ elif mode=='settings':
1374
+ return await self._setViaAPI(eval(f"f'{API_CHARGING}/{mode}'"), json=data)
1372
1375
  else:
1373
1376
  _LOGGER.error(f'Not yet implemented. Mode: {mode}. Command ignored')
1374
1377
  raise
pycupra/dashboard.py CHANGED
@@ -948,11 +948,14 @@ class ChargingState(BinarySensor):
948
948
  @property
949
949
  def attributes(self):
950
950
  attr = {}
951
- state = self.vehicle.attrs.get('charging', {}).get('status', {}).get('state', '')
951
+ #state = self.vehicle.attrs.get('charging', {}).get('status', {}).get('state', '')
952
+ #type = self.vehicle.attrs.get('charging', {}).get('status', {}).get('charging', {}).get('type', '')
953
+ #mode = self.vehicle.attrs.get('charging', {}).get('status', {}).get('charging', {}).get('mode', '')
954
+ state = self.vehicle.attrs.get('mycar', {}).get('services', {}).get('charging', {}).get('status', '')
952
955
  type = self.vehicle.attrs.get('charging', {}).get('status', {}).get('charging', {}).get('type', '')
953
- mode = self.vehicle.attrs.get('charging', {}).get('status', {}).get('charging', {}).get('mode', '')
954
- if state in {'charging', 'conservation'}:
955
- attr['state']=state
956
+ mode = self.vehicle.attrs.get('mycar', {}).get('services', {}).get('charging', {}).get('chargeMode', '')
957
+ if state in {'charging','Charging', 'conservation','Conservation'}:
958
+ attr['state']=state.lower()
956
959
  if type != '':
957
960
  attr['type']=type
958
961
  if mode != '':
@@ -1110,8 +1113,8 @@ def create_instruments():
1110
1113
  attr="charge_max_ampere",
1111
1114
  name="Charger max ampere",
1112
1115
  icon="mdi:flash",
1113
- unit="A",
1114
- device_class="current"
1116
+ #unit="A",
1117
+ #device_class="current"
1115
1118
  ),
1116
1119
  Sensor(
1117
1120
  attr="climatisation_target_temperature",
pycupra/vehicle.py CHANGED
@@ -129,9 +129,20 @@ class Vehicle:
129
129
  # Fetch all data if car is not deactivated
130
130
  if not self.deactivated:
131
131
  try:
132
+ if self._connection._session_nightlyUpdateReduction:
133
+ # nightlyUpdateReduction is activated
134
+ if datetime.now(tz=None).hour<5 or datetime.now(tz=None).hour>=22:
135
+ # current time is within the night interval
136
+ fullUpdateExpired = datetime.now(tz=None) - timedelta(seconds= 1100)
137
+ if hasattr(self, '_last_full_update'):
138
+ _LOGGER.debug(f'last_full_update= {self._last_full_update}, fullUpdateExpired= {fullUpdateExpired}.')
139
+ if updateType!=1 and (hasattr(self, '_last_full_update') and self._last_full_update>fullUpdateExpired):
140
+ _LOGGER.debug('Nightly update reduction is active and current time within 22:00 and 5:00. So we skip small update.')
141
+ return True
142
+
132
143
  # Data to be updated most often
133
144
  await asyncio.gather(
134
- self.get_charger(),
145
+ #self.get_charger(),
135
146
  self.get_basiccardata(),
136
147
  self.get_statusreport(),
137
148
  return_exceptions=True
@@ -146,6 +157,8 @@ class Vehicle:
146
157
 
147
158
  # Data to be updated less often
148
159
  await asyncio.gather(
160
+ #self.get_statusreport(),
161
+ self.get_charger(),
149
162
  self.get_preheater(),
150
163
  self.get_climater(),
151
164
  self.get_trip_statistic(),
@@ -320,7 +333,11 @@ class Vehicle:
320
333
  if 1 <= int(value) <= 255:
321
334
  # VW-Group API charger current request
322
335
  if self._relevantCapabilties.get('charging', {}).get('active', False):
323
- data = {'action': {'settings': {'maxChargeCurrentAC': int(value)}, 'type': 'setSettings'}}
336
+ data = {'maxChargeCurrentAc': int(value)}
337
+ if int(value)==252:
338
+ data = {'maxChargeCurrentAc': 'reduced'}
339
+ if int(value)==254:
340
+ data = {'maxChargeCurrentAc': 'maximum'}
324
341
  else:
325
342
  _LOGGER.error(f'Set charger maximum current to {value} is not supported.')
326
343
  raise SeatInvalidRequestException(f'Set charger maximum current to {value} is not supported.')
@@ -330,9 +347,7 @@ class Vehicle:
330
347
  # VW-Group API charger current request
331
348
  if self._relevantCapabilties.get('charging', {}).get('active', False):
332
349
  value = 'maximum' if value in ['Maximum', 'maximum', 'Max', 'max'] else 'reduced'
333
- data = {'settings':
334
- {'maxChargeCurrentAC': value}
335
- }
350
+ data = {'maxChargeCurrentAc': value}
336
351
  else:
337
352
  _LOGGER.error(f'Set charger maximum current to {value} is not supported.')
338
353
  raise SeatInvalidRequestException(f'Set charger maximum current to {value} is not supported.')
@@ -344,7 +359,7 @@ class Vehicle:
344
359
  _LOGGER.error('No charger support.')
345
360
  raise SeatInvalidRequestException('No charger support.')
346
361
 
347
- async def set_charger(self, action, **data):
362
+ async def set_charger(self, action, data=None):
348
363
  """Charging actions."""
349
364
  if not self._relevantCapabilties.get('charging', {}).get('active', False):
350
365
  _LOGGER.info('Remote start/stop of charger is not supported.')
@@ -361,7 +376,7 @@ class Vehicle:
361
376
  mode='start'
362
377
  elif action in ['stop', 'Stop', 'Off', 'off']:
363
378
  mode='stop'
364
- elif isinstance(action.get('action', None), dict):
379
+ elif action=='settings':
365
380
  mode=action
366
381
  else:
367
382
  _LOGGER.error(f'Invalid charger action: {action}. Must be either start, stop or setSettings')
@@ -386,6 +401,7 @@ class Vehicle:
386
401
  while not actionSuccessful and retry < 2:
387
402
  await asyncio.sleep(15)
388
403
  await self.get_charger()
404
+ await self.get_basiccardata() # We get both, get_charger() and get_basiccardata()
389
405
  if mode == 'start':
390
406
  if self.charging:
391
407
  actionSuccessful = True
@@ -393,7 +409,7 @@ class Vehicle:
393
409
  if not self.charging:
394
410
  actionSuccessful = True
395
411
  elif mode == 'settings':
396
- if data.get('settings',0).get('maxChargeCurrentAC','') == self.charge_max_ampere:
412
+ if data.get('maxChargeCurrentAc','') == self.charge_max_ampere:
397
413
  actionSuccessful = True
398
414
  else:
399
415
  _LOGGER.error(f'Missing code in vehicle._set_charger() for mode {mode}')
@@ -1473,16 +1489,22 @@ class Vehicle:
1473
1489
  @property
1474
1490
  def charging(self):
1475
1491
  """Return battery level"""
1476
- cstate = self.attrs.get('charging').get('status').get('charging').get('state','')
1492
+ #cstate = self.attrs.get('charging').get('status').get('charging').get('state','')
1493
+ cstate = self.attrs.get('mycar',{}).get('services',{}).get('charging',{}).get('status','')
1477
1494
  return 1 if cstate in ['charging', 'Charging'] else 0
1478
1495
 
1479
1496
  @property
1480
1497
  def is_charging_supported(self):
1481
1498
  """Return true if charging is supported"""
1482
- if self.attrs.get('charging', False):
1483
- if 'status' in self.attrs.get('charging', {}):
1484
- if 'charging' in self.attrs.get('charging')['status']:
1485
- if 'state' in self.attrs.get('charging')['status']['charging']:
1499
+ #if self.attrs.get('charging', False):
1500
+ # if 'status' in self.attrs.get('charging', {}):
1501
+ # if 'charging' in self.attrs.get('charging')['status']:
1502
+ # if 'state' in self.attrs.get('charging')['status']['charging']:
1503
+ # return True
1504
+ if self.attrs.get('mycar', False):
1505
+ if 'services' in self.attrs.get('mycar', {}):
1506
+ if 'charging' in self.attrs.get('mycar')['services']:
1507
+ if 'status' in self.attrs.get('mycar')['services']['charging']:
1486
1508
  return True
1487
1509
  return False
1488
1510
 
@@ -1504,26 +1526,33 @@ class Vehicle:
1504
1526
  @property
1505
1527
  def battery_level(self):
1506
1528
  """Return battery level"""
1507
- if self.attrs.get('charging', False):
1508
- return int(self.attrs.get('charging').get('status', {}).get('battery', {}).get('currentSocPercentage', 0))
1529
+ #if self.attrs.get('charging', False):
1530
+ # return int(self.attrs.get('charging').get('status', {}).get('battery', {}).get('currentSocPercentage', 0))
1531
+ if self.attrs.get('mycar', False):
1532
+ return int(self.attrs.get('mycar',{}).get('services', {}).get('charging', {}).get('currentPct', 0))
1509
1533
  else:
1510
1534
  return 0
1511
1535
 
1512
1536
  @property
1513
1537
  def is_battery_level_supported(self):
1514
1538
  """Return true if battery level is supported"""
1515
- if self.attrs.get('charging', False):
1516
- if 'status' in self.attrs.get('charging'):
1517
- if 'battery' in self.attrs.get('charging')['status']:
1518
- if 'currentSocPercentage' in self.attrs.get('charging')['status']['battery']:
1539
+ #if self.attrs.get('charging', False):
1540
+ # if 'status' in self.attrs.get('charging'):
1541
+ # if 'battery' in self.attrs.get('charging')['status']:
1542
+ # if 'currentSocPercentage' in self.attrs.get('charging')['status']['battery']:
1543
+ # return True
1544
+ if self.attrs.get('mycar', False):
1545
+ if 'services' in self.attrs.get('mycar'):
1546
+ if 'charging' in self.attrs.get('mycar')['services']:
1547
+ if 'currentPct' in self.attrs.get('mycar')['services']['charging']:
1519
1548
  return True
1520
1549
  return False
1521
1550
 
1522
1551
  @property
1523
1552
  def charge_max_ampere(self):
1524
1553
  """Return charger max ampere setting."""
1525
- if self.attrs.get('charger', False):
1526
- return self.attrs.get('charger').get('info').get('settings').get('maxChargeCurrentAC')
1554
+ if self.attrs.get('charging', False):
1555
+ return self.attrs.get('charging').get('info').get('settings').get('maxChargeCurrentAc')
1527
1556
  return 0
1528
1557
 
1529
1558
  @property
@@ -1532,7 +1561,7 @@ class Vehicle:
1532
1561
  if self.attrs.get('charging', False):
1533
1562
  if 'info' in self.attrs.get('charging', {}):
1534
1563
  if 'settings' in self.attrs.get('charging')['info']:
1535
- if 'maxChargeCurrentAC' in self.attrs.get('charging', {})['info']['settings']:
1564
+ if 'maxChargeCurrentAc' in self.attrs.get('charging', {})['info']['settings']:
1536
1565
  return True
1537
1566
  return False
1538
1567
 
@@ -1575,9 +1604,12 @@ class Vehicle:
1575
1604
  @property
1576
1605
  def charging_time_left(self):
1577
1606
  """Return minutes to charging complete"""
1578
- if self.external_power:
1579
- if self.attrs.get('charging', {}).get('status', {}).get('charging', {}).get('remainingTimeInMinutes', False):
1580
- minutes = int(self.attrs.get('charging', {}).get('status', {}).get('charging', {}).get('remainingTimeInMinutes', 0))
1607
+ #if self.external_power:
1608
+ if self.charging:
1609
+ #if self.attrs.get('charging', {}).get('status', {}).get('charging', {}).get('remainingTimeInMinutes', False):
1610
+ # minutes = int(self.attrs.get('charging', {}).get('status', {}).get('charging', {}).get('remainingTimeInMinutes', 0))
1611
+ if self.attrs.get('mycar', {}).get('services', {}).get('charging', {}).get('remainingTime', False):
1612
+ minutes = int(self.attrs.get('mycar', {}).get('services', {}).get('charging', {}).get('remainingTime', 0))
1581
1613
  else:
1582
1614
  minutes = 0
1583
1615
  return minutes
@@ -1646,8 +1678,9 @@ class Vehicle:
1646
1678
  @property
1647
1679
  def charging_state(self):
1648
1680
  """Return true if vehicle is charging."""
1649
- check = self.attrs.get('charging', {}).get('status', {}).get('state', '')
1650
- if check == 'charging':
1681
+ #check = self.attrs.get('charging', {}).get('status', {}).get('state', '')
1682
+ check = self.attrs.get('mycar',{}).get('services',{}).get('charging',{}).get('status','')
1683
+ if check in ('charging','Charging'):
1651
1684
  return True
1652
1685
  else:
1653
1686
  return False
@@ -1655,17 +1688,23 @@ class Vehicle:
1655
1688
  @property
1656
1689
  def is_charging_state_supported(self):
1657
1690
  """Charging state supported."""
1658
- if self.attrs.get('charging', {}).get('status', {}).get('state', False):
1659
- return True
1691
+ #if self.attrs.get('charging', {}).get('status', {}).get('state', False):
1692
+ # return True
1693
+ if self.attrs.get('mycar', False):
1694
+ if 'services' in self.attrs.get('mycar', {}):
1695
+ if 'charging' in self.attrs.get('mycar')['services']:
1696
+ if 'status' in self.attrs.get('mycar')['services']['charging']:
1697
+ return True
1660
1698
 
1661
1699
  @property
1662
1700
  def energy_flow(self):
1663
1701
  """Return true if energy is flowing to (i.e. charging) or from (i.e. climating with battery power) the battery."""
1664
1702
  if self.charging_state:
1665
1703
  return True
1666
- check = self.attrs.get('charging', {}).get('status', {}).get('state', '')
1704
+ #check = self.attrs.get('charging', {}).get('status', {}).get('state', '')
1705
+ check = self.attrs.get('mycar',{}).get('services',{}).get('charging',{}).get('status','')
1667
1706
  if self.is_electric_climatisation_supported:
1668
- if self.electric_climatisation and check not in {'charging', 'conservation'}:
1707
+ if self.electric_climatisation and check not in {'charging','Charging', 'conservation','Conservation'}:
1669
1708
  # electric climatisation is on and car is not charging or conserving power
1670
1709
  return True
1671
1710
  return False
@@ -2921,7 +2960,8 @@ class Vehicle:
2921
2960
  @property
2922
2961
  def is_request_results_supported(self):
2923
2962
  """Request results is supported if in progress is supported."""
2924
- return self.is_request_in_progress_supported
2963
+ return False # deactivated because it provides no usefull information
2964
+ #return self.is_request_in_progress_supported
2925
2965
 
2926
2966
  @property
2927
2967
  def requests_remaining(self):
@@ -2937,8 +2977,9 @@ class Vehicle:
2937
2977
 
2938
2978
  @property
2939
2979
  def is_requests_remaining_supported(self):
2940
- if self.is_request_in_progress_supported:
2941
- return True if self._requests.get('remaining', False) else False
2980
+ return False # deactivated because it provides no usefull information
2981
+ #if self.is_request_in_progress_supported:
2982
+ # return True if self._requests.get('remaining', False) else False
2942
2983
 
2943
2984
  #### Helper functions ####
2944
2985
  def __str__(self):
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: pycupra
3
- Version: 0.0.13
3
+ Version: 0.0.14
4
4
  Summary: A library to read and send vehicle data via Cupra/Seat portal using the same API calls as the MyCupra/MySeat mobile app.
5
5
  Home-page: https://github.com/WulfgarW/pycupra
6
6
  Author: WulfgarW
@@ -0,0 +1,13 @@
1
+ pycupra/__init__.py,sha256=VPzUfKd5mBFD1UERNV61FbGHih5dQPupLgIfYtmIUi4,230
2
+ pycupra/__version__.py,sha256=qY5o8F0qE8xC3RpWzlzulBbikrc7tq6TO-V5LlAJV5s,208
3
+ pycupra/connection.py,sha256=0SA-2UcL_uJhKMfluzyw_N4ZCqmsNEg3jU18XacMm5w,82641
4
+ pycupra/const.py,sha256=mgl29DcZz_J5hSzxknteu0ocDOXmQAgP0x17kvVSSi0,10234
5
+ pycupra/dashboard.py,sha256=3f4yBBBOMrXGiLdjO-2-1Ts2BVuQBw0wKa-2bhwid0c,42807
6
+ pycupra/exceptions.py,sha256=Nq_F79GP8wjHf5lpvPy9TbSIrRHAJrFMo0T1N9TcgSQ,2917
7
+ pycupra/utilities.py,sha256=cH4MiIzT2WlHgmnl_E7rR0R5LvCXfDNvirJolct50V8,2563
8
+ pycupra/vehicle.py,sha256=W1pQ8IkEmirSY6nha9OwSDFJyE2fcPGgeO_cVZAhgqg,135505
9
+ pycupra-0.0.14.dist-info/licenses/LICENSE,sha256=HrhfyXIkWY2tGFK11kg7vPCqhgh5DcxleloqdhrpyMY,11558
10
+ pycupra-0.0.14.dist-info/METADATA,sha256=9txUYXQVhWep4acCAthlWizfMKKy19BCaiLPCdg0Wdk,2579
11
+ pycupra-0.0.14.dist-info/WHEEL,sha256=CmyFI0kx5cdEMTLiONQRbGQwjIoR1aIYB7eCAQ4KPJ0,91
12
+ pycupra-0.0.14.dist-info/top_level.txt,sha256=9Lbj_jG4JvpGwt6K3AwhWFc0XieDnuHFOP4x44wSXSQ,8
13
+ pycupra-0.0.14.dist-info/RECORD,,
@@ -1,13 +0,0 @@
1
- pycupra/__init__.py,sha256=VPzUfKd5mBFD1UERNV61FbGHih5dQPupLgIfYtmIUi4,230
2
- pycupra/__version__.py,sha256=TaTBX6INREWajim6xVOUYCFZYeyoJA-OFOU2qeaT5nk,208
3
- pycupra/connection.py,sha256=_bTo1sBsUUDEf6Q8-u4H079KT_IN5sW5vlYI26ZB9mc,82423
4
- pycupra/const.py,sha256=mgl29DcZz_J5hSzxknteu0ocDOXmQAgP0x17kvVSSi0,10234
5
- pycupra/dashboard.py,sha256=FYheQ_U_mJ6BpgGq0auzcL-MsGOzSIlRo9vPvjf2pGQ,42434
6
- pycupra/exceptions.py,sha256=Nq_F79GP8wjHf5lpvPy9TbSIrRHAJrFMo0T1N9TcgSQ,2917
7
- pycupra/utilities.py,sha256=cH4MiIzT2WlHgmnl_E7rR0R5LvCXfDNvirJolct50V8,2563
8
- pycupra/vehicle.py,sha256=DTbUzd31lyXON77_6no1mCrw5uajx24K5qDKA70PL9M,132533
9
- pycupra-0.0.13.dist-info/licenses/LICENSE,sha256=HrhfyXIkWY2tGFK11kg7vPCqhgh5DcxleloqdhrpyMY,11558
10
- pycupra-0.0.13.dist-info/METADATA,sha256=8xEMN1iXZC6Cc5sIOp_5dkzEpN9YXhdF_YoD07cFjLs,2579
11
- pycupra-0.0.13.dist-info/WHEEL,sha256=CmyFI0kx5cdEMTLiONQRbGQwjIoR1aIYB7eCAQ4KPJ0,91
12
- pycupra-0.0.13.dist-info/top_level.txt,sha256=9Lbj_jG4JvpGwt6K3AwhWFc0XieDnuHFOP4x44wSXSQ,8
13
- pycupra-0.0.13.dist-info/RECORD,,