pycupra 0.1.3__tar.gz → 0.1.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.
Files changed (37) hide show
  1. {pycupra-0.1.3/pycupra.egg-info → pycupra-0.1.5}/PKG-INFO +1 -1
  2. {pycupra-0.1.3 → pycupra-0.1.5}/example/PyCupra.py +26 -14
  3. {pycupra-0.1.3 → pycupra-0.1.5}/pycupra/__version__.py +1 -1
  4. {pycupra-0.1.3 → pycupra-0.1.5}/pycupra/connection.py +30 -13
  5. {pycupra-0.1.3 → pycupra-0.1.5}/pycupra/dashboard.py +2 -0
  6. {pycupra-0.1.3 → pycupra-0.1.5}/pycupra/firebase_messaging/__init__.py +10 -3
  7. {pycupra-0.1.3 → pycupra-0.1.5}/pycupra/firebase_messaging/fcmpushclient.py +1 -1
  8. {pycupra-0.1.3 → pycupra-0.1.5}/pycupra/firebase_messaging/fcmregister.py +2 -2
  9. {pycupra-0.1.3 → pycupra-0.1.5}/pycupra/vehicle.py +39 -5
  10. {pycupra-0.1.3 → pycupra-0.1.5/pycupra.egg-info}/PKG-INFO +1 -1
  11. {pycupra-0.1.3 → pycupra-0.1.5}/pycupra.egg-info/SOURCES.txt +10 -10
  12. {pycupra-0.1.3 → pycupra-0.1.5}/.gitignore +0 -0
  13. {pycupra-0.1.3 → pycupra-0.1.5}/LICENSE +0 -0
  14. {pycupra-0.1.3 → pycupra-0.1.5}/README.md +0 -0
  15. {pycupra-0.1.3 → pycupra-0.1.5}/pycupra/__init__.py +0 -0
  16. {pycupra-0.1.3 → pycupra-0.1.5}/pycupra/const.py +0 -0
  17. {pycupra-0.1.3 → pycupra-0.1.5}/pycupra/exceptions.py +0 -0
  18. {pycupra-0.1.3 → pycupra-0.1.5}/pycupra/firebase.py +0 -0
  19. {pycupra-0.1.3/pycupra/firebase_messaging/proto → pycupra-0.1.5/pycupra/firebase_messaging}/android_checkin.proto +0 -0
  20. {pycupra-0.1.3/pycupra/firebase_messaging/proto → pycupra-0.1.5/pycupra/firebase_messaging}/android_checkin_pb2.py +0 -0
  21. {pycupra-0.1.3/pycupra/firebase_messaging/proto → pycupra-0.1.5/pycupra/firebase_messaging}/android_checkin_pb2.pyi +0 -0
  22. {pycupra-0.1.3/pycupra/firebase_messaging/proto → pycupra-0.1.5/pycupra/firebase_messaging}/checkin.proto +0 -0
  23. {pycupra-0.1.3/pycupra/firebase_messaging/proto → pycupra-0.1.5/pycupra/firebase_messaging}/checkin_pb2.py +0 -0
  24. {pycupra-0.1.3/pycupra/firebase_messaging/proto → pycupra-0.1.5/pycupra/firebase_messaging}/checkin_pb2.pyi +0 -0
  25. {pycupra-0.1.3 → pycupra-0.1.5}/pycupra/firebase_messaging/const.py +0 -0
  26. {pycupra-0.1.3/pycupra/firebase_messaging/proto → pycupra-0.1.5/pycupra/firebase_messaging}/mcs.proto +0 -0
  27. {pycupra-0.1.3/pycupra/firebase_messaging/proto → pycupra-0.1.5/pycupra/firebase_messaging}/mcs_pb2.py +0 -0
  28. {pycupra-0.1.3/pycupra/firebase_messaging/proto → pycupra-0.1.5/pycupra/firebase_messaging}/mcs_pb2.pyi +0 -0
  29. {pycupra-0.1.3 → pycupra-0.1.5}/pycupra/firebase_messaging/py.typed +0 -0
  30. {pycupra-0.1.3 → pycupra-0.1.5}/pycupra/utilities.py +0 -0
  31. {pycupra-0.1.3 → pycupra-0.1.5}/pycupra.egg-info/dependency_links.txt +0 -0
  32. {pycupra-0.1.3 → pycupra-0.1.5}/pycupra.egg-info/requires.txt +0 -0
  33. {pycupra-0.1.3 → pycupra-0.1.5}/pycupra.egg-info/top_level.txt +0 -0
  34. {pycupra-0.1.3 → pycupra-0.1.5}/pycupra_credentials.json.demo +0 -0
  35. {pycupra-0.1.3 → pycupra-0.1.5}/requirements.txt +0 -0
  36. {pycupra-0.1.3 → pycupra-0.1.5}/setup.cfg +0 -0
  37. {pycupra-0.1.3 → pycupra-0.1.5}/setup.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: pycupra
3
- Version: 0.1.3
3
+ Version: 0.1.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
@@ -177,7 +177,18 @@ async def demo_set_charger_current(vehicle, value="reduced"):
177
177
  print('########################################')
178
178
  print('# Change charging current #')
179
179
  print('########################################')
180
- success= await vehicle.set_charger_current(value) # value = "max" or "reduced".
180
+ success= await vehicle.set_charger_current(value)
181
+ if success:
182
+ print(" Request completed successfully.")
183
+ else:
184
+ print(" Request failed.")
185
+ return success
186
+
187
+ async def demo_set_charger_target_soc(vehicle, value=80):
188
+ print('########################################')
189
+ print('# Change target state of charge #')
190
+ print('########################################')
191
+ success= await vehicle.set_charger_target_soc(value)
181
192
  if success:
182
193
  print(" Request completed successfully.")
183
194
  else:
@@ -532,35 +543,36 @@ async def main():
532
543
 
533
544
  # Examples for using set functions:
534
545
 
535
- #await demo_set_charger(vehicle, action = "start") # action = "start" or "stop"
536
- #await demo_set_charger_current(vehicle, value='reduced') # value = 1-255/Maximum/Reduced (PHEV: 252 for reduced and 254 for max, EV: Maximum/Reduced)
546
+ #await demo_set_charger(vehicle, action = "start") # action = "start" or "stop"
547
+ #await demo_set_charger_current(vehicle, value='reduced') # value = 1-255/Maximum/Reduced (PHEV: 252 for reduced and 254 for max, EV: Maximum/Reduced)
548
+ #await demo_set_charger_target_soc(vehicle, value=70) # value = 1-100
537
549
 
538
- #await demo_set_climatisation(vehicle, action = "start", temp=18.0) # action = "auxilliary", "electric" or "off". spin is S-PIN and only needed for aux heating
539
- #await demo_set_climatisation_temp(vehicle, temp = 18.0) # temp = integer from 16 to 30
550
+ #await demo_set_climatisation(vehicle, action = "start", temp=18.0) # action = "auxilliary", "electric" or "off". spin is S-PIN and only needed for aux heating
551
+ #await demo_set_climatisation_temp(vehicle, temp = 18.0) # temp = integer from 16 to 30
540
552
  #await demo_set_battery_climatisation(vehicle, mode=False) # mode = False or True
541
- #await demo_set_windowheating(vehicle, action = "stop") # action = "start" or "stop"
553
+ #await demo_set_windowheating(vehicle, action = "stop") # action = "start" or "stop"
542
554
 
543
- #await demo_set_timer_schedule(vehicle) # arguments id and schedule can be found in the demo function
544
- #await demo_set_timer_active(vehicle, id=3, action="off") # id = 1, 2, 3, action = "on" or "off".
545
- #await demo_set_charge_limit(vehicle, 30) # limit = PHEV: 0/10/20/30/40/50, EV: 50/60/70/80/90/100
555
+ #await demo_set_timer_schedule(vehicle) # arguments id and schedule can be found in the demo function
556
+ #await demo_set_timer_active(vehicle, id=3, action="off") # id = 1, 2, 3, action = "on" or "off".
557
+ #await demo_set_charge_limit(vehicle, 30) # limit = PHEV: 0/10/20/30/40/50, EV: 50/60/70/80/90/100
546
558
 
547
- #await demo_set_departure_profile_schedule(vehicle) # arguments id and schedule can be found in the demo function
559
+ #await demo_set_departure_profile_schedule(vehicle) # arguments id and schedule can be found in the demo function
548
560
  #await demo_set_departure_profile_active(vehicle, id=3, action="off") # id = 1, 2, 3, action = "on" or "off".
549
561
 
550
562
  #await demo_set_lock(vehicle,action = "lock",
551
563
  # spin = credentials.get('spin','')) # action = "unlock" or "lock". spin = SPIN, needed for both
552
564
 
553
- #await vehicle.set_pheater(mode = "heating", spin = "1234") # action = "heating", "ventilation" or "off". spin = SPIN, not needed for off
565
+ #await vehicle.set_pheater(mode = "heating", spin = "1234") # action = "heating", "ventilation" or "off". spin = SPIN, not needed for off
554
566
 
555
- #await demo_set_honkandflash(vehicle, action="flash") # action = "honkandflash" or "flash"
567
+ #await demo_set_honkandflash(vehicle, action="flash") # action = "honkandflash" or "flash"
556
568
 
557
- #await vehicle.set_refresh() # Takes no arguments, will trigger forced update
569
+ #await vehicle.set_refresh() # Takes no arguments, will trigger forced update
558
570
 
559
571
  #print(f"Sleeping for {2*INTERVAL} seconds")
560
572
  #await asyncio.sleep(2*INTERVAL)
561
573
  #await demo_show_last_honkandflash_info(vehicle) # Returns the info of the last honkandflash_action
562
574
 
563
- #await demo_send_destination(vehicle) # arguments can be found in the demo function
575
+ #await demo_send_destination(vehicle) # arguments can be found in the demo function
564
576
 
565
577
  print('########################################')
566
578
  print('# Export all attributes to file #')
@@ -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.1.3"
6
+ __version__ = "0.1.5"
@@ -1151,10 +1151,11 @@ class Connection:
1151
1151
  _LOGGER.warning(f'Could not fetch departure profiles, error: {error}')
1152
1152
  return False
1153
1153
 
1154
- async def getClimater(self, vin, baseurl):
1154
+ async def getClimater(self, vin, baseurl, oldClimatingData):
1155
1155
  """Get climatisation data."""
1156
- data={}
1157
- data['climater']={}
1156
+ #data={}
1157
+ #data['climater']={}
1158
+ data = {'climater': oldClimatingData}
1158
1159
  await self.set_token(self._session_auth_brand)
1159
1160
  try:
1160
1161
  response = await self.get(eval(f"f'{API_CLIMATER_STATUS}'"))
@@ -1180,12 +1181,14 @@ class Connection:
1180
1181
  return False
1181
1182
  return data
1182
1183
 
1183
- async def getCharger(self, vin, baseurl):
1184
+ async def getCharger(self, vin, baseurl, oldChargingData):
1184
1185
  """Get charger data."""
1185
1186
  await self.set_token(self._session_auth_brand)
1186
1187
  try:
1187
1188
  chargingStatus = {}
1188
1189
  chargingInfo = {}
1190
+ #chargingModes = {}
1191
+ #chargingProfiles = {}
1189
1192
  response = await self.get(eval(f"f'{API_CHARGING}/status'"))
1190
1193
  if response.get('battery', {}):
1191
1194
  chargingStatus = response
@@ -1207,16 +1210,30 @@ class Connection:
1207
1210
  _LOGGER.warning(f'Could not fetch charging modes, HTTP status code: {response.get("status_code")}')
1208
1211
  else:
1209
1212
  _LOGGER.info('Unhandled error while trying to fetch charging modes')"""
1210
- if chargingStatus != {} and chargingInfo != {}:
1211
- data = {'charging': {
1212
- 'status': chargingStatus,
1213
- 'info' : chargingInfo,
1214
- #'modes' : chargingModes,
1215
- }
1216
- }
1213
+ """response = await self.get(eval(f"f'{API_CHARGING}/profiles'"))
1214
+ if response.get('profiles', {}):
1215
+ chargingProfiles = response
1216
+ elif response.get('status_code', {}):
1217
+ _LOGGER.warning(f'Could not fetch charging profiles, HTTP status code: {response.get("status_code")}')
1218
+ else:
1219
+ _LOGGER.info('Unhandled error while trying to fetch charging profiles')"""
1220
+ data = {'charging': oldChargingData}
1221
+ if chargingStatus != {}:
1222
+ data['charging']['status'] = chargingStatus
1223
+ else:
1224
+ _LOGGER.warning(f'getCharger() got no valid data for charging status')
1225
+ if chargingInfo != {}:
1226
+ data['charging']['info'] = chargingInfo
1217
1227
  else:
1218
- _LOGGER.warning(f'getCharger() got no valid data. Returning None')
1219
- return None
1228
+ _LOGGER.warning(f'getCharger() got no valid data for charging info')
1229
+ #if chargingModes != {}:
1230
+ # data['charging']['modes'] = chargingModes
1231
+ #else:
1232
+ # _LOGGER.warning(f'getCharger() got no valid data for charging modes')
1233
+ #if chargingProfiles != {}:
1234
+ # data['charging']['profiles'] = chargingProfiles
1235
+ #else:
1236
+ # _LOGGER.warning(f'getCharger() got no valid data for charging profiles')
1220
1237
  return data
1221
1238
  except Exception as error:
1222
1239
  _LOGGER.warning(f'Could not fetch charger, error: {error}')
@@ -453,6 +453,7 @@ class RequestRefresh(Switch):
453
453
  return self.vehicle.refresh_data
454
454
 
455
455
  async def turn_on(self):
456
+ _LOGGER.debug('User has called RequestRefresh().')
456
457
  await self.vehicle.set_refresh()
457
458
  await self.vehicle.update(updateType=1) #full update after set_refresh
458
459
  if self.callback is not None:
@@ -479,6 +480,7 @@ class RequestUpdate(Switch):
479
480
  return False #self.vehicle.update
480
481
 
481
482
  async def turn_on(self):
483
+ _LOGGER.debug('User has called RequestUpdate().')
482
484
  await self.vehicle.update(updateType=1) #full update after set_refresh
483
485
  if self.callback is not None:
484
486
  self.callback()
@@ -1,6 +1,6 @@
1
1
  from .fcmpushclient import FcmPushClient, FcmPushClientConfig, FcmPushClientRunState
2
2
  from .fcmregister import FcmRegisterConfig
3
- from .proto.mcs_pb2 import ( # pylint: disable=no-name-in-module
3
+ from .mcs_pb2 import ( # pylint: disable=no-name-in-module
4
4
  Close,
5
5
  DataMessageStanza,
6
6
  HeartbeatAck,
@@ -12,8 +12,15 @@ from .proto.mcs_pb2 import ( # pylint: disable=no-name-in-module
12
12
  StreamErrorStanza,
13
13
  )
14
14
 
15
- from .proto import android_checkin_pb2
16
- from .proto import checkin_pb2
15
+ from .android_checkin_pb2 import (
16
+ DEVICE_CHROME_BROWSER,
17
+ AndroidCheckinProto,
18
+ ChromeBuildProto,
19
+ )
20
+ from .checkin_pb2 import (
21
+ AndroidCheckinRequest,
22
+ AndroidCheckinResponse,
23
+ )
17
24
 
18
25
  __all__ = [
19
26
  "FcmPushClientConfig",
@@ -31,7 +31,7 @@ from .const import (
31
31
  MCS_VERSION,
32
32
  )
33
33
  from .fcmregister import FcmRegister, FcmRegisterConfig
34
- from .proto.mcs_pb2 import ( # pylint: disable=no-name-in-module
34
+ from .mcs_pb2 import ( # pylint: disable=no-name-in-module
35
35
  Close,
36
36
  DataMessageStanza,
37
37
  HeartbeatAck,
@@ -26,12 +26,12 @@ from .const import (
26
26
  GCM_SERVER_KEY_B64,
27
27
  SDK_VERSION,
28
28
  )
29
- from .proto.android_checkin_pb2 import (
29
+ from .android_checkin_pb2 import (
30
30
  DEVICE_CHROME_BROWSER,
31
31
  AndroidCheckinProto,
32
32
  ChromeBuildProto,
33
33
  )
34
- from .proto.checkin_pb2 import (
34
+ from .checkin_pb2 import (
35
35
  AndroidCheckinRequest,
36
36
  AndroidCheckinResponse,
37
37
  )
@@ -76,6 +76,7 @@ class Vehicle:
76
76
  'vehicleHealthWarnings': {'active': False, 'reason': 'not supported'},
77
77
  'state': {'active': False, 'reason': 'not supported'},
78
78
  'charging': {'active': False, 'reason': 'not supported', 'supportsTargetStateOfCharge': False},
79
+ 'chargingProfiles': {'active': False, 'reason': 'not supported', "supportsTimerClimatisation": False,"supportsVehiclePositionedInProfileID": False,"supportsSingleTimer": False},
79
80
  'honkAndFlash': {'active': False, 'reason': 'not supported'},
80
81
  'parkingPosition': {'active': False, 'reason': 'not supported'},
81
82
  'departureTimers': {'active': False, 'reason': 'not supported', 'supportsSingleTimer': False},
@@ -121,6 +122,10 @@ class Vehicle:
121
122
  data['supportsTargetStateOfCharge']=True
122
123
  if capa['parameters'].get('supportsSingleTimer',False)==True or capa['parameters'].get('supportsSingleTimer',False)=='true':
123
124
  data['supportsSingleTimer']=True
125
+ if capa['parameters'].get('supportsVehiclePositionedInProfileID',False)==True or capa['parameters'].get('supportsVehiclePositionedInProfileID',False)=='true':
126
+ data['supportsVehiclePositionedInProfileID']=True
127
+ if capa['parameters'].get('supportsTimerClimatisation',False)==True or capa['parameters'].get('supportsTimerClimatisation',False)=='true':
128
+ data['supportsTimerClimatisation']=True
124
129
  self._relevantCapabilties[id].update(data)
125
130
 
126
131
 
@@ -245,7 +250,7 @@ class Vehicle:
245
250
  async def get_climater(self):
246
251
  """Fetch climater data if function is enabled."""
247
252
  if self._relevantCapabilties.get('climatisation', {}).get('active', False):
248
- data = await self._connection.getClimater(self.vin, self._apibase)
253
+ data = await self._connection.getClimater(self.vin, self._apibase, deepcopy(self.attrs.get('climater',{})))
249
254
  if data:
250
255
  self._states.update(data)
251
256
  self._last_get_climater = datetime.now(tz=None)
@@ -311,7 +316,7 @@ class Vehicle:
311
316
  async def get_charger(self):
312
317
  """Fetch charger data if function is enabled."""
313
318
  if self._relevantCapabilties.get('charging', {}).get('active', False):
314
- data = await self._connection.getCharger(self.vin, self._apibase)
319
+ data = await self._connection.getCharger(self.vin, self._apibase, deepcopy(self.attrs.get('charging',{})))
315
320
  if data:
316
321
  self._states.update(data)
317
322
  self._last_get_charger = datetime.now(tz=None)
@@ -396,6 +401,33 @@ class Vehicle:
396
401
  _LOGGER.error('No charger support.')
397
402
  raise SeatInvalidRequestException('No charger support.')
398
403
 
404
+ async def set_charger_target_soc(self, value):
405
+ """Set target state of charge"""
406
+ if self.is_charging_supported:
407
+ if isinstance(value, int):
408
+ if 1 <= int(value) <= 100:
409
+ # VW-Group API charger current request
410
+ if self._relevantCapabilties.get('charging', {}).get('active', False) and self._relevantCapabilties.get('charging', {}).get('supportsTargetStateOfCharge', False):
411
+ data= deepcopy(self.attrs.get('charging',{}).get('info',{}).get('settings',{}))
412
+ if data=={}:
413
+ _LOGGER.error(f'Can not set target soc, because currently no charging settings are present.')
414
+ raise SeatInvalidRequestException(f'Set target soc not possible. Charging settings not present.')
415
+ data['targetSoc'] = int(value)
416
+ else:
417
+ _LOGGER.warning(f'Can not set target soc, because vehicle does not support this feature.')
418
+ return False
419
+ else:
420
+ _LOGGER.error(f'Set target soc to {value} is not supported.')
421
+ raise SeatInvalidRequestException(f'Set target soc to {value} is not supported.')
422
+ # Mimick app and set charger max ampere to Maximum/Reduced
423
+ else:
424
+ _LOGGER.error(f'Data type passed is invalid.')
425
+ raise SeatInvalidRequestException(f'Invalid data type.')
426
+ return await self.set_charger('settings', data)
427
+ else:
428
+ _LOGGER.error('No charger support.')
429
+ raise SeatInvalidRequestException('No charger support.')
430
+
399
431
  async def set_charger(self, action, data=None):
400
432
  """Charging actions."""
401
433
  if not self._relevantCapabilties.get('charging', {}).get('active', False):
@@ -450,9 +482,11 @@ class Vehicle:
450
482
  if not self.charging:
451
483
  actionSuccessful = True
452
484
  elif mode == 'settings':
485
+ if data.get('targetSoc',0) == self.target_soc: # In case targetSoc is changed
486
+ actionSuccessful = True
453
487
  if data.get('maxChargeCurrentAc','') == self.charge_max_ampere: # In case 'maximum', 'reduced'
454
488
  actionSuccessful = True
455
- if data.get('maxChargeCurrentAcInAmperes',0) == self.charge_max_ampere: # In case of a numerical value
489
+ if data.get('maxChargeCurrentAcInAmperes',0) == self.charge_max_ampere: # In case of a numerical value for charge current
456
490
  actionSuccessful = True
457
491
  else:
458
492
  _LOGGER.error(f'Missing code in vehicle._set_charger() for mode {mode}')
@@ -3150,7 +3184,7 @@ class Vehicle:
3150
3184
  self.storeFirebaseNotifications(obj, notification, data_message)
3151
3185
 
3152
3186
  if self.firebaseStatus != FIREBASE_STATUS_ACTIVATED:
3153
- _LOGGER.info(f'While firebase is not fully activated, received notifications are just acknoledged.')
3187
+ _LOGGER.info(f'While firebase is not fully activated, received notifications are just acknowledged.')
3154
3188
  # As long as the firebase status is not set to activated, ignore the notifications
3155
3189
  return False
3156
3190
 
@@ -3200,7 +3234,7 @@ class Vehicle:
3200
3234
  await self.get_departure_profiles()
3201
3235
  if self.updateCallback:
3202
3236
  await self.updateCallback(2)
3203
- elif type in ('charging-status-changed', 'charging-started', 'charging-stopped'):
3237
+ elif type in ('charging-status-changed', 'charging-started', 'charging-stopped', 'charging-settings-updated'):
3204
3238
  if self._requests.get('batterycharge', {}).get('id', None):
3205
3239
  openRequest= self._requests.get('batterycharge', {}).get('id', None)
3206
3240
  if openRequest == requestId:
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: pycupra
3
- Version: 0.1.3
3
+ Version: 0.1.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
@@ -21,16 +21,16 @@ pycupra.egg-info/dependency_links.txt
21
21
  pycupra.egg-info/requires.txt
22
22
  pycupra.egg-info/top_level.txt
23
23
  pycupra/firebase_messaging/__init__.py
24
+ pycupra/firebase_messaging/android_checkin.proto
25
+ pycupra/firebase_messaging/android_checkin_pb2.py
26
+ pycupra/firebase_messaging/android_checkin_pb2.pyi
27
+ pycupra/firebase_messaging/checkin.proto
28
+ pycupra/firebase_messaging/checkin_pb2.py
29
+ pycupra/firebase_messaging/checkin_pb2.pyi
24
30
  pycupra/firebase_messaging/const.py
25
31
  pycupra/firebase_messaging/fcmpushclient.py
26
32
  pycupra/firebase_messaging/fcmregister.py
27
- pycupra/firebase_messaging/py.typed
28
- pycupra/firebase_messaging/proto/android_checkin.proto
29
- pycupra/firebase_messaging/proto/android_checkin_pb2.py
30
- pycupra/firebase_messaging/proto/android_checkin_pb2.pyi
31
- pycupra/firebase_messaging/proto/checkin.proto
32
- pycupra/firebase_messaging/proto/checkin_pb2.py
33
- pycupra/firebase_messaging/proto/checkin_pb2.pyi
34
- pycupra/firebase_messaging/proto/mcs.proto
35
- pycupra/firebase_messaging/proto/mcs_pb2.py
36
- pycupra/firebase_messaging/proto/mcs_pb2.pyi
33
+ pycupra/firebase_messaging/mcs.proto
34
+ pycupra/firebase_messaging/mcs_pb2.py
35
+ pycupra/firebase_messaging/mcs_pb2.pyi
36
+ pycupra/firebase_messaging/py.typed
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
File without changes
File without changes