38
38
import logging
39
39
import secrets
40
40
import threading
41
- import time
42
41
import typing
43
42
from ctypes import (CDLL , CFUNCTYPE , POINTER , Structure , byref , c_bool , c_char , c_char_p , c_int , c_int32 , c_size_t , c_uint8 ,
44
43
c_uint16 , c_uint32 , c_uint64 , c_void_p , create_string_buffer , pointer , py_object , resize , string_at )
@@ -729,8 +728,8 @@ def GetAddressAndPort(self, nodeid):
729
728
730
729
return (address .value .decode (), port .value ) if error == 0 else None
731
730
732
- def DiscoverCommissionableNodes (self , filterType : discovery .FilterType = discovery .FilterType .NONE , filter : typing .Any = None ,
733
- stopOnFirst : bool = False , timeoutSecond : int = 5 ) -> typing .Union [None , CommissionableNode , typing .List [CommissionableNode ]]:
731
+ async def DiscoverCommissionableNodes (self , filterType : discovery .FilterType = discovery .FilterType .NONE , filter : typing .Any = None ,
732
+ stopOnFirst : bool = False , timeoutSecond : int = 5 ) -> typing .Union [None , CommissionableNode , typing .List [CommissionableNode ]]:
734
733
''' Discover commissionable nodes via DNS-SD with specified filters.
735
734
Supported filters are:
736
735
@@ -752,27 +751,36 @@ def DiscoverCommissionableNodes(self, filterType: discovery.FilterType = discove
752
751
if isinstance (filter , int ):
753
752
filter = str (filter )
754
753
755
- self ._ChipStack .Call (
756
- lambda : self ._dmLib .pychip_DeviceController_DiscoverCommissionableNodes (
757
- self .devCtrl , int (filterType ), str (filter ).encode ("utf-8" ))).raise_on_error ()
758
-
759
- if timeoutSecond != 0 :
760
- if stopOnFirst :
761
- target = time .time () + timeoutSecond
762
- while time .time () < target :
763
- if self ._ChipStack .Call (
764
- lambda : self ._dmLib .pychip_DeviceController_HasDiscoveredCommissionableNode (self .devCtrl )):
765
- break
766
- time .sleep (0.1 )
767
- else :
768
- time .sleep (timeoutSecond )
769
-
770
- self ._ChipStack .Call (
771
- lambda : self ._dmLib .pychip_DeviceController_StopCommissionableDiscovery (self .devCtrl )).raise_on_error ()
754
+ # Discovery is also used during commissioning. Make sure this manual discovery
755
+ # and commissioning attempts do not interfere with each other.
756
+ async with self ._commissioning_lock :
757
+ res = await self ._ChipStack .CallAsync (
758
+ lambda : self ._dmLib .pychip_DeviceController_DiscoverCommissionableNodes (
759
+ self .devCtrl , int (filterType ), str (filter ).encode ("utf-8" )))
760
+ res .raise_on_error ()
772
761
773
- return self .GetDiscoveredDevices ()
762
+ async def _wait_discovery ():
763
+ while not await self ._ChipStack .CallAsync (
764
+ lambda : self ._dmLib .pychip_DeviceController_HasDiscoveredCommissionableNode (self .devCtrl )):
765
+ await asyncio .sleep (0.1 )
766
+ return
774
767
775
- def GetDiscoveredDevices (self ):
768
+ try :
769
+ if stopOnFirst :
770
+ await asyncio .wait_for (_wait_discovery (), timeoutSecond )
771
+ else :
772
+ await asyncio .sleep (timeoutSecond )
773
+ except TimeoutError :
774
+ # Expected timeout, do nothing
775
+ pass
776
+ finally :
777
+ res = await self ._ChipStack .CallAsync (
778
+ lambda : self ._dmLib .pychip_DeviceController_StopCommissionableDiscovery (self .devCtrl ))
779
+ res .raise_on_error ()
780
+
781
+ return await self .GetDiscoveredDevices ()
782
+
783
+ async def GetDiscoveredDevices (self ):
776
784
def GetDevices (devCtrl ):
777
785
devices = []
778
786
@@ -786,7 +794,7 @@ def HandleDevice(deviceJson, deviceJsonLen):
786
794
self ._dmLib .pychip_DeviceController_IterateDiscoveredCommissionableNodes (devCtrl .devCtrl , HandleDevice )
787
795
return devices
788
796
789
- return self ._ChipStack .Call (lambda : GetDevices (self ))
797
+ return await self ._ChipStack .CallAsync (lambda : GetDevices (self ))
790
798
791
799
def GetIPForDiscoveredDevice (self , idx , addrStr , length ):
792
800
self .CheckIsActive ()
0 commit comments