spotifywebapiPython 1.0.52__py3-none-any.whl → 1.0.54__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 spotifywebapiPython might be problematic. Click here for more details.

Files changed (22) hide show
  1. {spotifywebapiPython-1.0.52.dist-info → spotifywebapiPython-1.0.54.dist-info}/METADATA +1 -1
  2. {spotifywebapiPython-1.0.52.dist-info → spotifywebapiPython-1.0.54.dist-info}/RECORD +22 -22
  3. spotifywebapipython/const.py +1 -1
  4. spotifywebapipython/docs/__init__.html +15 -2
  5. spotifywebapipython/docs/index.html +2 -2
  6. spotifywebapipython/docs/search.js +1 -1
  7. spotifywebapipython/docs/spotifywebapiPython/const.html +3 -3
  8. spotifywebapipython/docs/spotifywebapiPython/saappmessages.html +2 -2
  9. spotifywebapipython/docs/spotifywebapiPython/sautils.html +29 -2
  10. spotifywebapipython/docs/spotifywebapiPython/spotifyapierror.html +2 -2
  11. spotifywebapipython/docs/spotifywebapiPython/spotifyapimessage.html +2 -2
  12. spotifywebapipython/docs/spotifywebapiPython/spotifyauthtoken.html +2 -2
  13. spotifywebapipython/docs/spotifywebapiPython/spotifyclient.html +42 -7
  14. spotifywebapipython/docs/spotifywebapiPython/spotifydiscovery.html +2 -2
  15. spotifywebapipython/docs/spotifywebapiPython/spotifywebapiauthenticationerror.html +2 -2
  16. spotifywebapipython/docs/spotifywebapiPython/spotifywebapierror.html +2 -2
  17. spotifywebapipython/sautils.py +31 -0
  18. spotifywebapipython/spotifyclient.py +99 -89
  19. spotifywebapipython/zeroconfapi/zeroconfconnect.py +52 -13
  20. {spotifywebapiPython-1.0.52.dist-info → spotifywebapiPython-1.0.54.dist-info}/LICENSE +0 -0
  21. {spotifywebapiPython-1.0.52.dist-info → spotifywebapiPython-1.0.54.dist-info}/WHEEL +0 -0
  22. {spotifywebapiPython-1.0.52.dist-info → spotifywebapiPython-1.0.54.dist-info}/top_level.txt +0 -0
@@ -15,7 +15,7 @@ from zeroconf import Zeroconf
15
15
  from .oauthcli import AuthClient
16
16
  from .models import *
17
17
  from .models import UserProfile as UserProfileCurrentUser
18
- from .sautils import export, GetUnixTimestampMSFromUtcNow, _xmlGetInnerText
18
+ from .sautils import export, GetUnixTimestampMSFromUtcNow, _xmlGetInnerText, validateDelay
19
19
  from .saappmessages import SAAppMessages
20
20
  from .spotifyapierror import SpotifyApiError
21
21
  from .spotifyapimessage import SpotifyApiMessage
@@ -631,32 +631,6 @@ class SpotifyClient:
631
631
  return result
632
632
 
633
633
 
634
- def _ValidateDelay(self, delay:float, default:float=0.5, maxDelay:float=10) -> float:
635
- """
636
- Validates a delay value.
637
-
638
- Args:
639
- delay (int):
640
- The delay value to validate.
641
- default (int):
642
- The default delay value to set if the user-input delay is not valid.
643
- maxDelay (int):
644
- The maximum delay value allowed.
645
- Default is 10.
646
- """
647
- if (isinstance(delay,int)):
648
- delay = float(delay)
649
-
650
- if (not isinstance(delay,float)) or (delay < 0):
651
- result = default
652
- elif (delay > maxDelay):
653
- result = maxDelay
654
- else:
655
- result = delay
656
-
657
- return result
658
-
659
-
660
634
  def _ValidateMarket(self,
661
635
  market:str,
662
636
  ) -> str:
@@ -5945,10 +5919,10 @@ class SpotifyClient:
5945
5919
  def PlayerActivateDevices(
5946
5920
  self,
5947
5921
  verifyUserContext:bool=False,
5948
- delay:float=0.50,
5922
+ delay:float=0.25
5949
5923
  ) -> str:
5950
5924
  """
5951
- Activates all Spotify Connect player devices, and (optionally) switches the active user
5925
+ Activates all static Spotify Connect player devices, and (optionally) switches the active user
5952
5926
  context to the current user context.
5953
5927
 
5954
5928
  Args:
@@ -5961,7 +5935,7 @@ class SpotifyClient:
5961
5935
  Time delay (in seconds) to wait AFTER issuing the final Connect command (if necessary).
5962
5936
  This delay will give the spotify web api time to process the device list change before
5963
5937
  another command is issued.
5964
- Default is 0.50; value range is 0 - 10.
5938
+ Default is 0.25; value range is 0 - 10.
5965
5939
 
5966
5940
  Returns:
5967
5941
  A string that contains status text.
@@ -5985,6 +5959,10 @@ class SpotifyClient:
5985
5959
  The user context switch is bypassed if the `verifyUserContext` argument is False. If the user context
5986
5960
  is to be switched, then a Disconnect will be issued if a user context is active on the device followed
5987
5961
  by a Connect to the user context specified on the class constructor.
5962
+
5963
+ Dynamic Spotify Connect devices are not processed by this method, as they are temporary devices and are
5964
+ already active and in the device list. These devices are not found in Zeroconf discovery process, and only
5965
+ exist in the player device list. These are usually Spotify Connect web or mobile players with temporary device id's.
5988
5966
 
5989
5967
  <details>
5990
5968
  <summary>Sample Code</summary>
@@ -6012,7 +5990,7 @@ class SpotifyClient:
6012
5990
  raise SpotifyZeroconfApiError(SAAppMessages.ARGUMENT_REQUIRED_ERROR % (apiMethodName, 'SpotifyConnectUsername'), logsi=_logsi)
6013
5991
 
6014
5992
  # validations.
6015
- delay = self._ValidateDelay(delay, 0.50, 10)
5993
+ delay = validateDelay(delay, 0.25, 10)
6016
5994
  if (not isinstance(verifyUserContext, bool)):
6017
5995
  verifyUserContext = False
6018
5996
 
@@ -6049,7 +6027,7 @@ class SpotifyClient:
6049
6027
 
6050
6028
  # does our Spotify Connect user account need to take control of the device?
6051
6029
  # if not, then we are done.
6052
- elif (deviceActiveUser == self._SpotifyConnectUsername.lower()): # or (deviceActiveUser == self.UserProfile.Id.lower()):
6030
+ elif (deviceActiveUser == self._SpotifyConnectUsername.lower()) or (deviceActiveUser == self.UserProfile.Id.lower()):
6053
6031
  _logsi.LogVerbose("Spotify Connect user context '%s' was verified for Device id '%s'; switch not necessary" % (deviceActiveUser, deviceIdResult))
6054
6032
  status = status + "user context switch not needed"
6055
6033
 
@@ -6072,23 +6050,18 @@ class SpotifyClient:
6072
6050
  # the current user context before connecting a different user.
6073
6051
  if (info.HasActiveUser):
6074
6052
  _logsi.LogVerbose("Spotify Connect user context '%s' is being disconnected for Device id '%s'" % (deviceActiveUser, deviceIdResult))
6075
- zcfResult = zconn.Disconnect()
6053
+ zcfResult = zconn.Disconnect(delay)
6076
6054
  status = status + 'disconnected from user context "%s";' % deviceActiveUser
6077
-
6055
+
6078
6056
  # connect the device to OUR Spotify Connect user context.
6079
6057
  # note that the result here only indicates that the connect was submitted - NOT that it was successful!
6080
6058
  _logsi.LogVerbose("Spotify Connect user context '%s' is being connected for Device id '%s'" % (self._SpotifyConnectUsername, deviceIdResult))
6081
- zcfResult = zconn.Connect(self._SpotifyConnectUsername, self._SpotifyConnectPassword)
6059
+ zcfResult = zconn.Connect(self._SpotifyConnectUsername, self._SpotifyConnectPassword, delay)
6082
6060
  status = status + 'connected to user context "%s"' % self._SpotifyConnectUsername
6083
6061
 
6084
6062
  # trace.
6085
6063
  _logsi.LogVerbose("Spotify Connect user context switch from '%s' to '%s' was requested for Device id '%s'" % (deviceActiveUser, self._SpotifyConnectUsername, deviceIdResult))
6086
6064
 
6087
- # give spotify web api time to process the change and add the device to the device list.
6088
- if delay > 0:
6089
- _logsi.LogVerbose(TRACE_MSG_DELAY_DEVICE % delay)
6090
- time.sleep(delay)
6091
-
6092
6065
  # append device status to results.
6093
6066
  result = "%s%s\n" % (result, MSG_RESULT % (info.RemoteName, info.DeviceId, info.ActiveUser, status))
6094
6067
 
@@ -6243,6 +6216,11 @@ class SpotifyClient:
6243
6216
  SpotifApiError:
6244
6217
  If the method fails for any other reason.
6245
6218
 
6219
+ Note that this method will only return the devices for which the current user
6220
+ context has control of, or other available devices that do not have an active
6221
+ user context assigned. Use the `GetSpotifyConnectDevices` method to retrieve
6222
+ a complete list of devices that are available to all users.
6223
+
6246
6224
  The `ConfigurationCache` is updated with the results of this method. Use the
6247
6225
  `refresh` argument (with False value) to retrieve the cached value and avoid
6248
6226
  the spotify web api request. This results in better performance.
@@ -7899,10 +7877,18 @@ class SpotifyClient:
7899
7877
 
7900
7878
  def GetSpotifyConnectDevices(
7901
7879
  self,
7880
+ refresh:bool=True
7902
7881
  ) -> SpotifyConnectDevices:
7903
7882
  """
7904
7883
  Get information about all available Spotify Connect player devices.
7905
7884
 
7885
+ This method requires the `user-read-playback-state` scope.
7886
+
7887
+ Args:
7888
+ refresh (bool):
7889
+ True (default) to return real-time information from the spotify zeroconf api and
7890
+ update the cache; otherwise, False to just return the cached value.
7891
+
7906
7892
  Returns:
7907
7893
  A `SpotifyConnectDevices` object that contain the discovery results
7908
7894
  as well as the `getInfo` result for each found device.
@@ -7925,6 +7911,10 @@ class SpotifyClient:
7925
7911
  process, but still exist in the player device list. These are usually Spotify Connect
7926
7912
  web or mobile players with temporary device id's.
7927
7913
 
7914
+ The `ConfigurationCache` is updated with the results of this method. Use the
7915
+ `refresh` argument (with False value) to retrieve the cached value and avoid
7916
+ the spotify web api request. This results in better performance.
7917
+
7928
7918
  <details>
7929
7919
  <summary>Sample Code</summary>
7930
7920
  ```python
@@ -7934,50 +7924,62 @@ class SpotifyClient:
7934
7924
  """
7935
7925
  apiMethodName:str = 'GetSpotifyConnectDevices'
7936
7926
  result:SpotifyConnectDevices = SpotifyConnectDevices()
7927
+ cacheDesc:str = CACHE_SOURCE_CURRENT
7937
7928
 
7938
7929
  try:
7939
7930
 
7940
7931
  # trace.
7941
7932
  _logsi.EnterMethod(SILevel.Debug, apiMethodName)
7942
7933
 
7943
- # discover Spotify Connect devices on the network, waiting up to the specified timeout
7944
- # for all devices to be discovered. this will return all Spotify Connect devices that
7945
- # are currently powered on, and are registered to Zeroconf / mDNS.
7946
- _logsi.LogVerbose("Discovering Spotify Connect devices on the local network")
7947
- discovery:SpotifyDiscovery = SpotifyDiscovery(self._ZeroconfClient, printToConsole=False)
7948
- discovery.DiscoverDevices(timeout=self._SpotifyConnectDiscoveryTimeout)
7934
+ # can we use the cached value?
7935
+ if (not refresh) and (apiMethodName in self._ConfigurationCache):
7936
+
7937
+ result = self._ConfigurationCache[apiMethodName]
7938
+ cacheDesc = CACHE_SOURCE_CACHED
7939
+
7940
+ else:
7941
+
7942
+ # discover Spotify Connect devices on the network, waiting up to the specified timeout
7943
+ # for all devices to be discovered. this will return all Spotify Connect devices that
7944
+ # are currently powered on, and are registered to Zeroconf / mDNS.
7945
+ _logsi.LogVerbose("Discovering Spotify Connect devices on the local network")
7946
+ discovery:SpotifyDiscovery = SpotifyDiscovery(self._ZeroconfClient, printToConsole=False)
7947
+ discovery.DiscoverDevices(timeout=self._SpotifyConnectDiscoveryTimeout)
7949
7948
 
7950
- # process all discovered devices.
7951
- discoverResult:ZeroconfDiscoveryResult
7952
- for discoverResult in discovery.DiscoveryResults:
7953
-
7954
- # get the id from the device via the zeroconf API getInfo endpoint, as the id is not
7955
- # returned in the zeroconf discovery result.
7956
- zconn:ZeroconfConnect = ZeroconfConnect(discoverResult.HostIpv4Address,
7957
- discoverResult.HostIpPort,
7958
- discoverResult.SpotifyConnectCPath,
7959
- useSSL=False)
7960
- info:ZeroconfGetInfo = zconn.GetInformation()
7961
-
7962
- # create new spotify connect device object.
7963
- scDevice:SpotifyConnectDevice = SpotifyConnectDevice()
7964
- scDevice.DiscoveryResult = discoverResult
7965
- scDevice.DeviceInfo = info
7966
- result.Items.append(scDevice)
7967
-
7968
- # we will also call the GetPlayerDevices method, in case we have any dynamic devices.
7969
- # dynamic devices are Spotify Connect devices that are not found in Zeroconf discovery
7970
- # process, but still exist in the player device list. these are usually Spotify Connect
7971
- # web or mobile players with temporary device id's.
7972
- devices:list[Device] = self.GetPlayerDevices(True)
7949
+ # process all discovered devices.
7950
+ discoverResult:ZeroconfDiscoveryResult
7951
+ for discoverResult in discovery.DiscoveryResults:
7952
+
7953
+ # get the id from the device via the zeroconf API getInfo endpoint, as the id is not
7954
+ # returned in the zeroconf discovery result.
7955
+ zconn:ZeroconfConnect = ZeroconfConnect(discoverResult.HostIpv4Address,
7956
+ discoverResult.HostIpPort,
7957
+ discoverResult.SpotifyConnectCPath,
7958
+ useSSL=False)
7959
+ info:ZeroconfGetInfo = zconn.GetInformation()
7960
+
7961
+ # create new spotify connect device object.
7962
+ scDevice:SpotifyConnectDevice = SpotifyConnectDevice()
7963
+ scDevice.DiscoveryResult = discoverResult
7964
+ scDevice.DeviceInfo = info
7965
+ result.Items.append(scDevice)
7966
+
7967
+ # we will also call the GetPlayerDevices method, in case we have any dynamic devices.
7968
+ # dynamic devices are Spotify Connect devices that are not found in Zeroconf discovery
7969
+ # process, but still exist in the player device list. these are usually Spotify Connect
7970
+ # web or mobile players with temporary device id's.
7971
+ devices:list[Device] = self.GetPlayerDevices(True)
7973
7972
 
7974
- device:Device
7975
- for device in devices:
7976
- if not result.ContainsDeviceId(device.Id):
7977
- result.AddDynamicDevice(device, self.UserProfile.Id)
7973
+ device:Device
7974
+ for device in devices:
7975
+ if not result.ContainsDeviceId(device.Id):
7976
+ result.AddDynamicDevice(device, self.UserProfile.Id)
7977
+
7978
+ # update cache.
7979
+ self._ConfigurationCache[apiMethodName] = result
7978
7980
 
7979
7981
  # trace.
7980
- _logsi.LogArray(SILevel.Verbose, TRACE_METHOD_RESULT_TYPE % (apiMethodName, type(result).__name__), result)
7982
+ _logsi.LogArray(SILevel.Verbose, TRACE_METHOD_RESULT_TYPE_CACHED % (apiMethodName, type(result).__name__, cacheDesc), result)
7981
7983
  return result
7982
7984
 
7983
7985
  except SpotifyZeroconfApiError: raise # pass handled exceptions on thru
@@ -9422,7 +9424,7 @@ class SpotifyClient:
9422
9424
  _logsi.LogMethodParmList(SILevel.Verbose, "Spotify Connect device pause playback", apiMethodParms)
9423
9425
 
9424
9426
  # validations.
9425
- delay = self._ValidateDelay(delay, 0.50, 10)
9427
+ delay = validateDelay(delay, 0.50, 10)
9426
9428
 
9427
9429
  # check for device name; convert to an id if a name was supplied.
9428
9430
  deviceId = self.PlayerConvertDeviceNameToId(deviceId)
@@ -9555,7 +9557,7 @@ class SpotifyClient:
9555
9557
  _logsi.LogMethodParmList(SILevel.Verbose, "Spotify Connect device play context", apiMethodParms)
9556
9558
 
9557
9559
  # validations.
9558
- delay = self._ValidateDelay(delay, 0.50, 10)
9560
+ delay = validateDelay(delay, 0.50, 10)
9559
9561
 
9560
9562
  # check for device name; convert to an id if a name was supplied.
9561
9563
  #deviceId = self.PlayerConvertDeviceNameToId(deviceId)
@@ -9663,7 +9665,7 @@ class SpotifyClient:
9663
9665
  _logsi.LogMethodParmList(SILevel.Verbose, "Spotify Connect device play track favorites", apiMethodParms)
9664
9666
 
9665
9667
  # validations.
9666
- delay = self._ValidateDelay(delay, 0.50, 10)
9668
+ delay = validateDelay(delay, 0.50, 10)
9667
9669
 
9668
9670
  # get current users favorite tracks.
9669
9671
  tracks:TrackPageSaved = self.GetTrackFavorites(limitTotal=200)
@@ -9774,7 +9776,7 @@ class SpotifyClient:
9774
9776
  _logsi.LogMethodParmList(SILevel.Verbose, "Spotify Connect device play tracks", apiMethodParms)
9775
9777
 
9776
9778
  # validations.
9777
- delay = self._ValidateDelay(delay, 0.50, 10)
9779
+ delay = validateDelay(delay, 0.50, 10)
9778
9780
 
9779
9781
  # build a list of all item uri's.
9780
9782
  # remove any leading / trailing spaces in case user put a space between the items.
@@ -9885,7 +9887,7 @@ class SpotifyClient:
9885
9887
  _logsi.LogMethodParmList(SILevel.Verbose, "Spotify Connect device resume playback", apiMethodParms)
9886
9888
 
9887
9889
  # validations.
9888
- delay = self._ValidateDelay(delay, 0.50, 10)
9890
+ delay = validateDelay(delay, 0.50, 10)
9889
9891
 
9890
9892
  # check for device name; convert to an id if a name was supplied.
9891
9893
  deviceId = self.PlayerConvertDeviceNameToId(deviceId)
@@ -9982,7 +9984,7 @@ class SpotifyClient:
9982
9984
  _logsi.LogMethodParmList(SILevel.Verbose, "Spotify Connect device seek position", apiMethodParms)
9983
9985
 
9984
9986
  # validations.
9985
- delay = self._ValidateDelay(delay, 0.50, 10)
9987
+ delay = validateDelay(delay, 0.50, 10)
9986
9988
 
9987
9989
  # check for device name; convert to an id if a name was supplied.
9988
9990
  deviceId = self.PlayerConvertDeviceNameToId(deviceId)
@@ -10074,7 +10076,7 @@ class SpotifyClient:
10074
10076
  _logsi.LogMethodParmList(SILevel.Verbose, "Spotify Connect device skip next", apiMethodParms)
10075
10077
 
10076
10078
  # validations.
10077
- delay = self._ValidateDelay(delay, 0.50, 10)
10079
+ delay = validateDelay(delay, 0.50, 10)
10078
10080
 
10079
10081
  # check for device name; convert to an id if a name was supplied.
10080
10082
  deviceId = self.PlayerConvertDeviceNameToId(deviceId)
@@ -10163,7 +10165,7 @@ class SpotifyClient:
10163
10165
  _logsi.LogMethodParmList(SILevel.Verbose, "Spotify Connect device skip previous", apiMethodParms)
10164
10166
 
10165
10167
  # validations.
10166
- delay = self._ValidateDelay(delay, 0.50, 10)
10168
+ delay = validateDelay(delay, 0.50, 10)
10167
10169
 
10168
10170
  # check for device name; convert to an id if a name was supplied.
10169
10171
  deviceId = self.PlayerConvertDeviceNameToId(deviceId)
@@ -10206,6 +10208,7 @@ class SpotifyClient:
10206
10208
  deviceValue:str,
10207
10209
  verifyUserContext:bool=True,
10208
10210
  verifyTimeout:float=5.0,
10211
+ delay:float=0.25
10209
10212
  ) -> str:
10210
10213
  """
10211
10214
  Resolves a Spotify Connect device identifier from a specified device id, name, alias id,
@@ -10225,6 +10228,11 @@ class SpotifyClient:
10225
10228
  Connect device list. This value is only used if a Connect command has to be
10226
10229
  issued to activate the device.
10227
10230
  Default is 5; value range is 0 - 10.
10231
+ delay (float):
10232
+ Time delay (in seconds) to wait AFTER issuing any command to the device.
10233
+ This delay will give the spotify zeroconf api time to process the change before
10234
+ another command is issued.
10235
+ Default is 0.25; value range is 0 - 10.
10228
10236
 
10229
10237
  Returns:
10230
10238
  A device Id for the deviceValue if one could be resolved;
@@ -10273,6 +10281,7 @@ class SpotifyClient:
10273
10281
  apiMethodParms.AppendKeyValue("deviceValue", deviceValue)
10274
10282
  apiMethodParms.AppendKeyValue("verifyUserContext", verifyUserContext)
10275
10283
  apiMethodParms.AppendKeyValue("verifyTimeout", verifyTimeout)
10284
+ apiMethodParms.AppendKeyValue("delay", delay)
10276
10285
  _logsi.LogMethodParmList(SILevel.Verbose, "Resolving Spotify Connect Player Device Id", apiMethodParms)
10277
10286
 
10278
10287
  # if device value not specified then we are done.
@@ -10281,7 +10290,8 @@ class SpotifyClient:
10281
10290
  return None
10282
10291
 
10283
10292
  # validations.
10284
- verifyTimeout = self._ValidateDelay(verifyTimeout, 5, 10)
10293
+ delay = validateDelay(delay, 0.25, 10)
10294
+ verifyTimeout = validateDelay(verifyTimeout, 5, 10)
10285
10295
  if (not isinstance(verifyUserContext, bool)):
10286
10296
  verifyUserContext = True
10287
10297
 
@@ -10376,7 +10386,7 @@ class SpotifyClient:
10376
10386
  # the current user context before connecting a different user.
10377
10387
  if (info.HasActiveUser):
10378
10388
  _logsi.LogVerbose("Spotify Connect user context '%s' is being disconnected for Device id '%s'" % (deviceActiveUser, deviceIdResult))
10379
- zcfResult = zconn.Disconnect()
10389
+ zcfResult = zconn.Disconnect(delay)
10380
10390
 
10381
10391
  # connect the device to OUR Spotify Connect user context.
10382
10392
  # note that the result here only indicates that the connect was submitted - NOT that it was successful!
@@ -10490,7 +10500,7 @@ class SpotifyClient:
10490
10500
  _logsi.LogMethodParmList(SILevel.Verbose, "Set Spotify Connect device set repeat mode", apiMethodParms)
10491
10501
 
10492
10502
  # validations.
10493
- delay = self._ValidateDelay(delay, 0.50, 10)
10503
+ delay = validateDelay(delay, 0.50, 10)
10494
10504
 
10495
10505
  # check for device name; convert to an id if a name was supplied.
10496
10506
  deviceId = self.PlayerConvertDeviceNameToId(deviceId)
@@ -10589,7 +10599,7 @@ class SpotifyClient:
10589
10599
  _logsi.LogMethodParmList(SILevel.Verbose, "Set Spotify Connect device set shuffle mode", apiMethodParms)
10590
10600
 
10591
10601
  # validations.
10592
- delay = self._ValidateDelay(delay, 0.50, 10)
10602
+ delay = validateDelay(delay, 0.50, 10)
10593
10603
 
10594
10604
  # check for device name; convert to an id if a name was supplied.
10595
10605
  deviceId = self.PlayerConvertDeviceNameToId(deviceId)
@@ -10687,7 +10697,7 @@ class SpotifyClient:
10687
10697
  _logsi.LogMethodParmList(SILevel.Verbose, "Set Spotify Connect device set volume level", apiMethodParms)
10688
10698
 
10689
10699
  # validations.
10690
- delay = self._ValidateDelay(delay, 0.50, 10)
10700
+ delay = validateDelay(delay, 0.50, 10)
10691
10701
 
10692
10702
  # check for device name; convert to an id if a name was supplied.
10693
10703
  deviceId = self.PlayerConvertDeviceNameToId(deviceId)
@@ -10785,7 +10795,7 @@ class SpotifyClient:
10785
10795
  _logsi.LogMethodParmList(SILevel.Verbose, "Transfer playback to a new Spotify Connect device", apiMethodParms)
10786
10796
 
10787
10797
  # validations.
10788
- delay = self._ValidateDelay(delay, 0.50, 10)
10798
+ delay = validateDelay(delay, 0.50, 10)
10789
10799
 
10790
10800
  # check for device name; convert to an id if a name was supplied.
10791
10801
  #deviceId = self.PlayerConvertDeviceNameToId(deviceId)
@@ -10891,7 +10901,7 @@ class SpotifyClient:
10891
10901
  _logsi.LogMethodParmList(SILevel.Verbose, "Checks if a Spotify Connect device is active, and activate one if not", apiMethodParms)
10892
10902
 
10893
10903
  # validations.
10894
- delay = self._ValidateDelay(delay, 0.50, 10)
10904
+ delay = validateDelay(delay, 0.50, 10)
10895
10905
 
10896
10906
  # get current Spotify Connect player state.
10897
10907
  result = self.GetPlayerPlaybackState()
@@ -12,8 +12,11 @@ from .spotifyzeroconfapierror import SpotifyZeroconfApiError
12
12
  from .zeroconfresponse import ZeroconfResponse
13
13
  from .zeroconfgetinfo import ZeroconfGetInfo
14
14
  from ..saappmessages import SAAppMessages
15
- from ..sautils import export
15
+ from ..sautils import export, validateDelay
16
16
  from ..spotifyapierror import SpotifyApiError
17
+ from ..const import (
18
+ TRACE_MSG_DELAY_DEVICE,
19
+ )
17
20
 
18
21
  # get smartinspect logger reference; create a new session for this module name.
19
22
  from smartinspectpython.siauto import SIAuto, SILevel, SISession, SIMethodParmListContext, SISourceId
@@ -261,10 +264,12 @@ class ZeroconfConnect:
261
264
  return responseData
262
265
 
263
266
 
264
- def Connect(self,
265
- username:str,
266
- password:str,
267
- ) -> ZeroconfResponse:
267
+ def Connect(
268
+ self,
269
+ username:str,
270
+ password:str,
271
+ delay:float=0.50
272
+ ) -> ZeroconfResponse:
268
273
  """
269
274
  Calls the `addUser` Spotify Zeroconf API endpoint to issue a call to SpConnectionLoginBlob. If successful,
270
275
  the associated device id is added to the Spotify Connect active device list for the specified user account.
@@ -277,6 +282,11 @@ class ZeroconfConnect:
277
282
  on the manufacturer device.
278
283
  password (str):
279
284
  Spotify Connect user password to login with.
285
+ delay (float):
286
+ Time delay (in seconds) to wait AFTER issuing the command to the device.
287
+ This delay will give the spotify zeroconf api time to process the change before
288
+ another command is issued.
289
+ Default is 0.50; value range is 0 - 10.
280
290
 
281
291
  Returns:
282
292
  A `ZeroconfResponse` object that indicates success or failure (see notes below).
@@ -321,6 +331,7 @@ class ZeroconfConnect:
321
331
  apiMethodParms.AppendKeyValue("Version", self._Version)
322
332
  apiMethodParms.AppendKeyValue("Uri", self._Uri)
323
333
  apiMethodParms.AppendKeyValue("username", username)
334
+ apiMethodParms.AppendKeyValue("delay", delay)
324
335
  _logsi.LogMethodParmList(SILevel.Verbose, "Connecting device to Spotify Connect using specified Username and Password", apiMethodParms)
325
336
 
326
337
  # validations.
@@ -328,6 +339,7 @@ class ZeroconfConnect:
328
339
  raise SpotifyApiError(SAAppMessages.ARGUMENT_REQUIRED_ERROR % (apiMethodName, 'username'), logsi=_logsi)
329
340
  if (password is None) or (not isinstance(password,str)):
330
341
  raise SpotifyApiError(SAAppMessages.ARGUMENT_REQUIRED_ERROR % (apiMethodName, 'password'), logsi=_logsi)
342
+ delay = validateDelay(delay, 0.50, 10)
331
343
 
332
344
  # get the current device id from the device via Spotify ZeroConf API `getInfo` endpoint.
333
345
  info:ZeroconfGetInfo = self.GetInformation()
@@ -342,7 +354,8 @@ class ZeroconfConnect:
342
354
  self._Uri,
343
355
  timeout=10,
344
356
  headers={
345
- 'Content-Type': 'application/x-www-form-urlencoded'
357
+ 'Content-Type': 'application/x-www-form-urlencoded',
358
+ 'Connection': 'close'
346
359
  },
347
360
  data={
348
361
  'action': 'addUser',
@@ -361,6 +374,13 @@ class ZeroconfConnect:
361
374
 
362
375
  # trace.
363
376
  _logsi.LogObject(SILevel.Verbose, '%s result - type="%s"' % (apiMethodName, type(result).__name__), result, excludeNonPublic=True)
377
+
378
+ # give spotify zeroconf api time to process the change.
379
+ if delay > 0:
380
+ _logsi.LogVerbose(TRACE_MSG_DELAY_DEVICE % delay)
381
+ time.sleep(delay)
382
+
383
+ # return result to caller.
364
384
  return result
365
385
 
366
386
  except SpotifyZeroconfApiError: raise # pass handled exceptions on thru
@@ -380,10 +400,20 @@ class ZeroconfConnect:
380
400
  _logsi.LeaveMethod(SILevel.Debug, apiMethodName)
381
401
 
382
402
 
383
- def Disconnect(self) -> ZeroconfResponse:
403
+ def Disconnect(
404
+ self,
405
+ delay:float=0.50
406
+ ) -> ZeroconfResponse:
384
407
  """
385
408
  Calls the `resetUsers` Spotify Zeroconf API endpoint to issue a call to SpConnectionLogout.
386
409
 
410
+ Args:
411
+ delay (float):
412
+ Time delay (in seconds) to wait AFTER issuing the command to the device.
413
+ This delay will give the spotify zeroconf api time to process the change before
414
+ another command is issued.
415
+ Default is 0.50; value range is 0 - 10.
416
+
387
417
  Returns:
388
418
  A `ZeroconfResponse` object that indicates success or failure (see notes below).
389
419
 
@@ -415,14 +445,19 @@ class ZeroconfConnect:
415
445
  apiMethodParms.AppendKeyValue("CPath", self._CPath)
416
446
  apiMethodParms.AppendKeyValue("Version", self._Version)
417
447
  apiMethodParms.AppendKeyValue("Uri", self._Uri)
448
+ apiMethodParms.AppendKeyValue("delay", delay)
418
449
  _logsi.LogMethodParmList(SILevel.Verbose, "Disconnecting device from Spotify Connect", apiMethodParms)
419
450
 
451
+ # validations.
452
+ delay = validateDelay(delay, 0.50, 10)
453
+
420
454
  # execute spotify zeroconf api request.
421
455
  response = requests.post(
422
456
  self._Uri,
423
457
  timeout=10,
424
458
  headers={
425
- 'Content-Type': 'application/x-www-form-urlencoded'
459
+ 'Content-Type': 'application/x-www-form-urlencoded',
460
+ 'Connection': 'close'
426
461
  },
427
462
  data={
428
463
  'action': 'resetUsers',
@@ -436,12 +471,15 @@ class ZeroconfConnect:
436
471
  # process results.
437
472
  result = ZeroconfResponse(root=responseData)
438
473
 
439
- # just in case user tries to issue a connect immediately after this, give the device
440
- # a little time to reset the connection so the subsequent connect does not fail.
441
- time.sleep(0.5)
442
-
443
474
  # trace.
444
475
  _logsi.LogObject(SILevel.Verbose, '%s result - type="%s"' % (apiMethodName, type(result).__name__), result, excludeNonPublic=True)
476
+
477
+ # give spotify zeroconf api time to process the change.
478
+ if delay > 0:
479
+ _logsi.LogVerbose(TRACE_MSG_DELAY_DEVICE % delay)
480
+ time.sleep(delay)
481
+
482
+ # return result to caller.
445
483
  return result
446
484
 
447
485
  except SpotifyZeroconfApiError: raise # pass handled exceptions on thru
@@ -520,7 +558,8 @@ class ZeroconfConnect:
520
558
  self._Uri,
521
559
  timeout=10,
522
560
  headers={
523
- 'Content-Type': 'application/x-www-form-urlencoded'
561
+ 'Content-Type': 'application/x-www-form-urlencoded',
562
+ 'Connection': 'close'
524
563
  },
525
564
  params={
526
565
  'action': 'getInfo',