diff --git a/src/controller/python/ChipDeviceController-ScriptBinding.cpp b/src/controller/python/ChipDeviceController-ScriptBinding.cpp index 355a233561e9b6..f181f3273da52b 100644 --- a/src/controller/python/ChipDeviceController-ScriptBinding.cpp +++ b/src/controller/python/ChipDeviceController-ScriptBinding.cpp @@ -109,7 +109,7 @@ chip::NodeId kDefaultLocalDeviceId = chip::kTestControllerNodeId; chip::NodeId kRemoteDeviceId = chip::kTestDeviceNodeId; extern "C" { -ChipError::StorageType pychip_DeviceController_StackInit(uint32_t bluetoothAdapterId); +ChipError::StorageType pychip_DeviceController_StackInit(); ChipError::StorageType pychip_DeviceController_StackShutdown(); ChipError::StorageType pychip_DeviceController_NewDeviceController(chip::Controller::DeviceCommissioner ** outDevCtrl, @@ -222,17 +222,10 @@ chip::Controller::Python::StorageAdapter * pychip_Storage_GetStorageAdapter() return sStorageAdapter; } -ChipError::StorageType pychip_DeviceController_StackInit(uint32_t bluetoothAdapterId) +ChipError::StorageType pychip_DeviceController_StackInit() { VerifyOrDie(sStorageAdapter != nullptr); -#if CHIP_DEVICE_LAYER_TARGET_LINUX && CHIP_DEVICE_CONFIG_ENABLE_CHIPOBLE - // By default, Linux device is configured as a BLE peripheral while the controller needs a BLE central. - CHIP_ERROR err = - chip::DeviceLayer::Internal::BLEMgrImpl().ConfigureBle(/* BLE adapter ID */ bluetoothAdapterId, /* BLE central */ true); - VerifyOrReturnError(err == CHIP_NO_ERROR, err.AsInteger()); -#endif - FactoryInitParams factoryParams; factoryParams.fabricIndependentStorage = sStorageAdapter; diff --git a/src/controller/python/chip/ChipReplStartup.py b/src/controller/python/chip/ChipReplStartup.py index 3fe949c174c30a..91ac26337480bf 100644 --- a/src/controller/python/chip/ChipReplStartup.py +++ b/src/controller/python/chip/ChipReplStartup.py @@ -12,6 +12,7 @@ import argparse import builtins import chip.FabricAdmin +import chip.native from chip.utils import CommissioningBuildingBlocks import atexit @@ -140,6 +141,8 @@ def mattersetdebug(enableDebugMode: bool = True): "-d", "--debug", help="Set default logging level to debug.", action="store_true") args = parser.parse_args() +chip.native.Init() + ReplInit(args.debug) chipStack = ChipStack(persistentStoragePath=args.storagepath) fabricAdmins = LoadFabricAdmins() diff --git a/src/controller/python/chip/ChipStack.py b/src/controller/python/chip/ChipStack.py index ffae3d2b04fd25..ffe321a5fc4bdf 100644 --- a/src/controller/python/chip/ChipStack.py +++ b/src/controller/python/chip/ChipStack.py @@ -265,11 +265,8 @@ def HandleChipThreadRun(callback): # self._persistentStorage = PersistentStorage(persistentStoragePath) - if (bluetoothAdapter is None): - bluetoothAdapter = 0 - # Initialize the chip stack. - res = self._ChipStackLib.pychip_DeviceController_StackInit(bluetoothAdapter) + res = self._ChipStackLib.pychip_DeviceController_StackInit() if res != 0: raise self.ErrorToException(res) @@ -440,7 +437,7 @@ def _loadLib(self): self._ChipStackLib = chip.native.GetLibraryHandle() self._chipDLLPath = chip.native.FindNativeLibraryPath() - self._ChipStackLib.pychip_DeviceController_StackInit.argtypes = [c_uint32] + self._ChipStackLib.pychip_DeviceController_StackInit.argtypes = [] self._ChipStackLib.pychip_DeviceController_StackInit.restype = c_uint32 self._ChipStackLib.pychip_DeviceController_StackShutdown.argtypes = [] self._ChipStackLib.pychip_DeviceController_StackShutdown.restype = c_uint32 diff --git a/src/controller/python/chip/FabricAdmin.py b/src/controller/python/chip/FabricAdmin.py index cd0a5f7b7aa81c..f1ab5f7b746834 100644 --- a/src/controller/python/chip/FabricAdmin.py +++ b/src/controller/python/chip/FabricAdmin.py @@ -64,13 +64,16 @@ class FabricAdmin: boot for a given fabric and ensuring it automatically picks up the right ICAC/RCAC details as well. ''' - _handle = chip.native.GetLibraryHandle() _isActive = False activeFabricIndexList = set() activeFabricIdList = set() activeAdmins = set() vendorId = None + @classmethod + def _Handle(cls): + return chip.native.GetLibraryHandle() + def AllocateNextFabricIndex(self): ''' Allocate the next un-used fabric index. ''' @@ -133,10 +136,10 @@ def __init__(self, vendorId: int, rcac: bytes = None, icac: bytes = None, fabric print( f"New FabricAdmin: FabricId: {self._fabricId}({self._fabricIndex}), VendorId = {hex(self.vendorId)}") - self._handle.pychip_OpCreds_InitializeDelegate.restype = c_void_p + self._Handle().pychip_OpCreds_InitializeDelegate.restype = c_void_p self.closure = builtins.chipStack.Call( - lambda: self._handle.pychip_OpCreds_InitializeDelegate( + lambda: self._Handle().pychip_OpCreds_InitializeDelegate( ctypes.py_object(self), ctypes.c_uint32(self._fabricIndex)) ) @@ -195,7 +198,7 @@ def Shutdown(self, deleteFromStorage: bool = True): ''' if (self._isActive): builtins.chipStack.Call( - lambda: self._handle.pychip_OpCreds_FreeDelegate( + lambda: self._Handle().pychip_OpCreds_FreeDelegate( ctypes.c_void_p(self.closure)) ) diff --git a/src/controller/python/chip/native/CommonStackInit.cpp b/src/controller/python/chip/native/CommonStackInit.cpp index 5fa470713b2079..ef1dca2c875c5d 100644 --- a/src/controller/python/chip/native/CommonStackInit.cpp +++ b/src/controller/python/chip/native/CommonStackInit.cpp @@ -38,14 +38,29 @@ #include #include -static_assert(std::is_same::value, "python assumes CHIP_ERROR maps to c_uint32"); +using namespace chip; + +static_assert(std::is_same::value, "python assumes CHIP_ERROR maps to c_uint32"); extern "C" { -chip::ChipError::StorageType pychip_CommonStackInit() +struct __attribute__((packed)) PyCommonStackInitParams +{ + uint32_t mBluetoothAdapterId; +}; + +ChipError::StorageType pychip_CommonStackInit(const PyCommonStackInitParams * aParams) { - ReturnErrorOnFailure(chip::Platform::MemoryInit().AsInteger()); - ReturnErrorOnFailure(chip::DeviceLayer::PlatformMgr().InitChipStack().AsInteger()); + ReturnErrorOnFailure(Platform::MemoryInit().AsInteger()); + +#if CHIP_DEVICE_LAYER_TARGET_LINUX && CHIP_DEVICE_CONFIG_ENABLE_CHIPOBLE + // By default, Linux device is configured as a BLE peripheral while the controller needs a BLE central. + ReturnErrorOnFailure( + DeviceLayer::Internal::BLEMgrImpl().ConfigureBle(aParams->mBluetoothAdapterId, /* BLE central */ true).AsInteger()); +#endif + + ReturnErrorOnFailure(DeviceLayer::PlatformMgr().InitChipStack().AsInteger()); + return CHIP_NO_ERROR.AsInteger(); } @@ -55,7 +70,7 @@ void pychip_CommonStackShutdown() // We cannot actually call this because the destructor for the MdnsContexts singleton on Darwin only gets called // on termination of the program, and that unfortunately makes a bunch of Platform::MemoryFree calls. // - chip::Platform::MemoryShutdown(); + Platform::MemoryShutdown(); #endif } }; diff --git a/src/controller/python/chip/native/__init__.py b/src/controller/python/chip/native/__init__.py index 44b4ccd89f015e..f0c175237e7b8a 100644 --- a/src/controller/python/chip/native/__init__.py +++ b/src/controller/python/chip/native/__init__.py @@ -2,6 +2,7 @@ import glob import os import platform +import construct NATIVE_LIBRARY_BASE_NAME = "_ChipDeviceCtrl.so" @@ -69,19 +70,30 @@ def Set(self, methodName: str, resultType, argumentTypes: list): _nativeLibraryHandle: ctypes.CDLL = None -def GetLibraryHandle() -> ctypes.CDLL: +def _GetLibraryHandle(shouldInit: bool) -> ctypes.CDLL: """Get a memoized handle to the chip native code dll.""" global _nativeLibraryHandle if _nativeLibraryHandle is None: + if shouldInit: + raise Exception("Common stack has not been initialized!") _nativeLibraryHandle = ctypes.CDLL(FindNativeLibraryPath()) setter = NativeLibraryHandleMethodArguments(_nativeLibraryHandle) - setter.Set("pychip_CommonStackInit", ctypes.c_uint32, []) - - # - # We've a split initialization model with some init happening here and some other - # bits of init happening in ChipStack. #20437 tracks consolidating those. - # - _nativeLibraryHandle.pychip_CommonStackInit() + setter.Set("pychip_CommonStackInit", ctypes.c_uint32, [ctypes.c_char_p]) return _nativeLibraryHandle + + +def Init(bluetoothAdapter: int = None): + CommonStackParams = construct.Struct( + "BluetoothAdapterId" / construct.Int32ul, + ) + params = CommonStackParams.parse(b'\x00' * CommonStackParams.sizeof()) + params.BluetoothAdapterId = bluetoothAdapter if bluetoothAdapter is not None else 0 + params = CommonStackParams.build(params) + + _GetLibraryHandle(False).pychip_CommonStackInit(ctypes.c_char_p(params)) + + +def GetLibraryHandle(): + return _GetLibraryHandle(True) diff --git a/src/controller/python/test/test_scripts/base.py b/src/controller/python/test/test_scripts/base.py index 6cd812371f32c2..1e34098e890997 100644 --- a/src/controller/python/test/test_scripts/base.py +++ b/src/controller/python/test/test_scripts/base.py @@ -34,6 +34,7 @@ import chip.clusters.Attribute as Attribute from chip.utils import CommissioningBuildingBlocks from chip.ChipStack import * +import chip.native import chip.FabricAdmin import copy import secrets @@ -170,6 +171,8 @@ def assertValueEqual(self, expected): class BaseTestHelper: def __init__(self, nodeid: int, paaTrustStorePath: str, testCommissioner: bool = False): + chip.native.Init() + self.chipStack = ChipStack('/tmp/repl_storage.json') self.fabricAdmin = chip.FabricAdmin.FabricAdmin(vendorId=0XFFF1, fabricId=1, fabricIndex=1)