pycupra 0.0.3__tar.gz → 0.0.5__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -5,4 +5,5 @@ build/
5
5
  dist/
6
6
  __pycache__/
7
7
  *.json
8
+ *.txt
8
9
  www/
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: pycupra
3
- Version: 0.0.3
3
+ Version: 0.0.5
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
@@ -28,6 +28,7 @@ PRINTRESPONSE = True
28
28
  INTERVAL = 5
29
29
  TOKEN_FILE_NAME_AND_PATH='./cupra_token.json'
30
30
  CREDENTIALS_FILE_NAME_AND_PATH='./cupra_credentials.json'
31
+ ALL_ATTRIBUTES_FILE_NAME_AND_PATH='./cupra_all_attributes.txt'
31
32
 
32
33
 
33
34
  COMPONENTS = {
@@ -142,6 +143,16 @@ def exportToCSV(vehicle, csvFileName, dataType='short'):
142
143
  df.to_csv(csvFileName)
143
144
  return True
144
145
 
146
+ def exportAllAttributes(vehicle, exportFileName):
147
+ try:
148
+ with open(exportFileName, "w") as f:
149
+ print(vehicle.attrs, file=f)
150
+ f.close()
151
+ return True
152
+ except Exception as e:
153
+ _LOGGER.warning(f'exportAllAttributes() not successful. Error: {e}')
154
+ return False
155
+
145
156
  async def demo_set_charger(vehicle, action="start"):
146
157
  print('########################################')
147
158
  print('# Start/Stop charging #')
@@ -461,8 +472,11 @@ async def main():
461
472
  print(txt.center(40, '#'))
462
473
  await vehicle.get_trip_statistic()
463
474
  print('')
464
- print('Updates complete')"""
475
+ print('Updates complete')
465
476
 
477
+ print(f"Sleeping for {INTERVAL} seconds")
478
+ await asyncio.sleep(INTERVAL)"""
479
+
466
480
  print('########################################')
467
481
  print('# Export driving data to csv #')
468
482
  print(txt.center(40, '#'))
@@ -470,9 +484,6 @@ async def main():
470
484
  print('')
471
485
  print('Export of driving data to csv complete')
472
486
 
473
- print(f"Sleeping for {INTERVAL} seconds")
474
- await asyncio.sleep(INTERVAL)
475
-
476
487
  # Examples for using set functions:
477
488
 
478
489
  #await demo_set_charger(vehicle, action = "start") # action = "start" or "stop"
@@ -502,8 +513,18 @@ async def main():
502
513
 
503
514
  #await demo_send_destination(vehicle) # arguments can be found in the demo function
504
515
 
505
- print(f"Sleeping for {5*INTERVAL} seconds")
506
- await asyncio.sleep(5*INTERVAL)
516
+ print('########################################')
517
+ print('# Export all attributes to file #')
518
+ print(txt.center(40, '#'))
519
+ rc= exportAllAttributes(vehicle, ALL_ATTRIBUTES_FILE_NAME_AND_PATH)
520
+ print('')
521
+ if rc:
522
+ print('Export of all attributes successfully completed')
523
+ else:
524
+ print('Export of all attributes failed')
525
+
526
+ print(f"Sleeping for {INTERVAL} seconds")
527
+ await asyncio.sleep(INTERVAL)
507
528
 
508
529
  exit
509
530
 
@@ -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.3"
6
+ __version__ = "0.0.5"
@@ -15,6 +15,8 @@ import string
15
15
  import secrets
16
16
  import xmltodict
17
17
 
18
+ from PIL import Image
19
+ from io import BytesIO
18
20
  from sys import version_info, argv
19
21
  from datetime import timedelta, datetime, timezone
20
22
  from urllib.parse import urljoin, parse_qs, urlparse, urlencode
@@ -153,6 +155,7 @@ class Connection:
153
155
  if os.path.isfile(self._tokenFile):
154
156
  with open(self._tokenFile, "r") as f:
155
157
  tokenString=f.read()
158
+ f.close()
156
159
  tokens=json.loads(tokenString)
157
160
  self._session_tokens[brand]=tokens
158
161
  self._user_id=tokens['user_id']
@@ -171,6 +174,7 @@ class Connection:
171
174
  try:
172
175
  with open(self._tokenFile, "w") as f:
173
176
  f.write(json.dumps(self._session_tokens[brand]))
177
+ f.close()
174
178
  return True
175
179
  except Exception as e:
176
180
  _LOGGER.warning(f'writeTokenFile() not successful. Error: {e}')
@@ -193,6 +197,7 @@ class Connection:
193
197
  with open(f'./www/image_{imageName}.png', "wb") as f:
194
198
  f.write(imageData)
195
199
  imageDict[imageName]=f'/local/image_{imageName}.png'
200
+ f.close()
196
201
  return True
197
202
  except:
198
203
  _LOGGER.warning('writeImageFile() not successful. Ignoring this problem.')
@@ -937,6 +942,26 @@ class Connection:
937
942
  if len(pic)>0:
938
943
  loop = asyncio.get_running_loop()
939
944
  await loop.run_in_executor(None, self.writeImageFile, pos,pic, images)
945
+ if pos=='front':
946
+ # Crop the front image to a square format
947
+ try:
948
+ im= Image.open(BytesIO(pic))
949
+ width, height = im.size
950
+ if height>width:
951
+ width, height = height, width
952
+ # Setting the points for cropped image
953
+ left = (width-height)/2
954
+ top = 0
955
+ right = height+(width-height)/2
956
+ bottom = height
957
+ # Cropped image of above dimension
958
+ im1 = im.crop((left, top, right, bottom))
959
+ byteIO = BytesIO()
960
+ im1.save(byteIO, format='PNG')
961
+ await loop.run_in_executor(None, self.writeImageFile, pos+'_cropped',byteIO.getvalue(), images)
962
+ except:
963
+ _LOGGER.warning('Cropping front image to square format failed.')
964
+
940
965
  _LOGGER.debug('Read images from web site and wrote them to file.')
941
966
  response['images']=images
942
967
  return response
@@ -711,8 +711,8 @@ class DepartureTimer1(Switch):
711
711
 
712
712
  @property
713
713
  def state(self):
714
- status = self.vehicle.departure1.get("timerProgrammedStatus", "")
715
- if status == "programmed":
714
+ status = self.vehicle.departure1.get("enabled", "")
715
+ if status:
716
716
  return True
717
717
  else:
718
718
  return False
@@ -743,8 +743,8 @@ class DepartureTimer2(Switch):
743
743
 
744
744
  @property
745
745
  def state(self):
746
- status = self.vehicle.departure2.get("timerProgrammedStatus", "")
747
- if status == "programmed":
746
+ status = self.vehicle.departure2.get("enabled", "")
747
+ if status:
748
748
  return True
749
749
  else:
750
750
  return False
@@ -774,8 +774,8 @@ class DepartureTimer3(Switch):
774
774
 
775
775
  @property
776
776
  def state(self):
777
- status = self.vehicle.departure3.get("timerProgrammedStatus", "")
778
- if status == "programmed":
777
+ status = self.vehicle.departure3.get("enabled", "")
778
+ if status:
779
779
  return True
780
780
  else:
781
781
  return False
@@ -122,7 +122,7 @@ class Vehicle:
122
122
  self.get_charger(),
123
123
  self.get_timerprogramming(),
124
124
  self.get_basiccardata(),
125
- self.get_modelimageurl(),
125
+ #self.get_modelimageurl(), #commented out because getting the images once in discover() should be sufficient
126
126
  return_exceptions=True
127
127
  )
128
128
  except:
@@ -147,16 +147,15 @@ class Vehicle:
147
147
  async def get_preheater(self):
148
148
  """Fetch pre-heater data if function is enabled."""
149
149
  _LOGGER.info('get_preheater() not implemented yet')
150
- raise
151
- if self._relevantCapabilties.get('#dont know the name for the preheater capability', {}).get('active', False):
152
- if not await self.expired('rheating_v1'):
153
- data = await self._connection.getPreHeater(self.vin, self._apibase)
154
- if data:
155
- self._states.update(data)
156
- else:
157
- _LOGGER.debug('Could not fetch preheater data')
158
- else:
159
- self._requests.pop('preheater', None)
150
+ #if self._relevantCapabilties.get('#dont know the name for the preheater capability', {}).get('active', False):
151
+ # if not await self.expired('rheating_v1'):
152
+ # data = await self._connection.getPreHeater(self.vin, self._apibase)
153
+ # if data:
154
+ # self._states.update(data)
155
+ # else:
156
+ # _LOGGER.debug('Could not fetch preheater data')
157
+ #else:
158
+ # self._requests.pop('preheater', None)
160
159
 
161
160
  async def get_climater(self):
162
161
  """Fetch climater data if function is enabled."""
@@ -913,7 +912,7 @@ class Vehicle:
913
912
  if expired > timestamp:
914
913
  self._requests.get('refresh', {}).pop('id')
915
914
  else:
916
- raise SeatRequestInProgressException('A data refresh request is already in progress')
915
+ raise SeatRequestInProgressException('Last data refresh request less than 3 minutes ago')
917
916
  try:
918
917
  self._requests['latest'] = 'Refresh'
919
918
  response = await self._connection.setRefresh(self.vin, self._apibase)
@@ -1028,18 +1027,19 @@ class Vehicle:
1028
1027
  @property
1029
1028
  def model_image_small(self):
1030
1029
  """Return URL for model image"""
1031
- return self._modelimages.get('images','').get('front','')
1030
+ return self._modelimages.get('images','').get('front_cropped','')
1032
1031
 
1033
1032
  @property
1034
1033
  def is_model_image_small_supported(self):
1035
1034
  """Return true if model image url is not None."""
1036
1035
  if self._modelimages is not None:
1037
- return True
1036
+ if self._modelimages.get('images','').get('front_cropped','')!='':
1037
+ return True
1038
1038
 
1039
1039
  @property
1040
1040
  def model_image_large(self):
1041
1041
  """Return URL for model image"""
1042
- return self._modelimages.get('images','').get('side', '')
1042
+ return self._modelimages.get('images','').get('front', '')
1043
1043
 
1044
1044
  @property
1045
1045
  def is_model_image_large_supported(self):
@@ -2452,11 +2452,12 @@ class Vehicle:
2452
2452
  @property
2453
2453
  def refresh_data(self):
2454
2454
  """Get state of data refresh"""
2455
- if self._requests.get('refresh', {}).get('id', False):
2456
- timestamp = self._requests.get('refresh', {}).get('timestamp', DATEZERO)
2457
- expired = datetime.now() - timedelta(minutes=2)
2458
- if expired < timestamp:
2459
- return True
2455
+ #if self._requests.get('refresh', {}).get('id', False):
2456
+ # timestamp = self._requests.get('refresh', {}).get('timestamp', DATEZERO)
2457
+ # expired = datetime.now() - timedelta(minutes=2)
2458
+ # if expired < timestamp:
2459
+ # return True
2460
+ #State is always false
2460
2461
  return False
2461
2462
 
2462
2463
  @property
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: pycupra
3
- Version: 0.0.3
3
+ Version: 0.0.5
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
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes