diff --git a/0020-Python-Drop-deprecated-discovery-APIs-33882.patch b/0020-Python-Drop-deprecated-discovery-APIs-33882.patch new file mode 100644 index 0000000..e1229f3 --- /dev/null +++ b/0020-Python-Drop-deprecated-discovery-APIs-33882.patch @@ -0,0 +1,401 @@ +From 75954f9f6c493726c004f31631c9c7baf30ffff4 Mon Sep 17 00:00:00 2001 +From: Stefan Agner +Date: Wed, 12 Jun 2024 19:49:51 +0200 +Subject: [PATCH] [Python] Drop deprecated discovery APIs (#33882) + +This change removes the deprecated discovery APIs from the Python +controller. The APIs that are removed are: +- DiscoverCommissionableNodesLongDiscriminator +- DiscoverCommissionableNodesShortDiscriminator +- DiscoverCommissionableNodesVendor +- DiscoverCommissionableNodesDeviceType +- DiscoverCommissionableNodesCommissioningEnabled +- PrintDiscoveredDevices +- DiscoverAllCommissioning + +All these APIs can be replaced with the DiscoverCommissionableNodes +and the appropriate filter flags. +--- + docs/testing/ChipDeviceCtrlAPI.md | 77 --------------- + .../python/ChipDeviceController-Discovery.cpp | 59 ----------- + .../ChipDeviceController-ScriptBinding.cpp | 53 ---------- + src/controller/python/chip/ChipDeviceCtrl.py | 99 ------------------- + 4 files changed, 288 deletions(-) + +diff --git a/docs/testing/ChipDeviceCtrlAPI.md b/docs/testing/ChipDeviceCtrlAPI.md +index 944c787d64..b1111aada5 100644 +--- a/docs/testing/ChipDeviceCtrlAPI.md ++++ b/docs/testing/ChipDeviceCtrlAPI.md +@@ -10,13 +10,6 @@ + - [ShutdownAll](#shutdownall) + - [ExpireSessions](#expiresessions) + - [DiscoverCommissionableNodes](#discovercommissionablenodes) +- - [DiscoverCommissionableNodesLongDiscriminator](#discovercommissionablenodeslongdiscriminator) +- - [DiscoverCommissionableNodesShortDiscriminator](#discovercommissionablenodesshortdiscriminator) +- - [DiscoverCommissionableNodesVendor](#discovercommissionablenodesvendor) +- - [DiscoverCommissionableNodesDeviceType](#discovercommissionablenodesdevicetype) +- - [DiscoverCommissionableNodesCommissioningEnabled](#discovercommissionablenodescommissioningenabled) +- - [PrintDiscoveredDevices](#printdiscovereddevices) +- - [DiscoverAllCommissioning](#discoverallcommissioning) + - [OpenCommissioningWindow](#opencommissioningwindow) + - [GetFabricIdInternal](#getfabricidinternal) + - [GetNodeIdInternal](#getnodeidinternal) +@@ -174,76 +167,6 @@ This function will always return a list of CommissionableDevice. When + stopOnFirst is set, this function will return when at least one device is + discovered or on timeout. + +- +- +-#### DiscoverCommissionableNodesLongDiscriminator +- +-```python +-def DiscoverCommissionableNodesLongDiscriminator(long_discriminator) +-``` +- +-Deprecated, use DiscoverCommissionableNodes +- +- +- +-#### DiscoverCommissionableNodesShortDiscriminator +- +-```python +-def DiscoverCommissionableNodesShortDiscriminator(short_discriminator) +-``` +- +-Deprecated, use DiscoverCommissionableNodes +- +- +- +-#### DiscoverCommissionableNodesVendor +- +-```python +-def DiscoverCommissionableNodesVendor(vendor) +-``` +- +-Deprecated, use DiscoverCommissionableNodes +- +- +- +-#### DiscoverCommissionableNodesDeviceType +- +-```python +-def DiscoverCommissionableNodesDeviceType(device_type) +-``` +- +-Deprecated, use DiscoverCommissionableNodes +- +- +- +-#### DiscoverCommissionableNodesCommissioningEnabled +- +-```python +-def DiscoverCommissionableNodesCommissioningEnabled() +-``` +- +-Deprecated, use DiscoverCommissionableNodes +- +- +- +-#### PrintDiscoveredDevices +- +-```python +-def PrintDiscoveredDevices() +-``` +- +-Deprecated, use GetCommissionableNodes +- +- +- +-#### DiscoverAllCommissioning +- +-```python +-def DiscoverAllCommissioning() +-``` +- +-Deprecated, use DiscoverCommissionableNodes +- + + + #### OpenCommissioningWindow +diff --git a/src/controller/python/ChipDeviceController-Discovery.cpp b/src/controller/python/ChipDeviceController-Discovery.cpp +index 7b502140a3..5690475567 100644 +--- a/src/controller/python/ChipDeviceController-Discovery.cpp ++++ b/src/controller/python/ChipDeviceController-Discovery.cpp +@@ -164,65 +164,6 @@ void pychip_DeviceController_IterateDiscoveredCommissionableNodes(Controller::De + } + } + +-void pychip_DeviceController_PrintDiscoveredDevices(Controller::DeviceCommissioner * devCtrl) +-{ +- for (int i = 0; i < devCtrl->GetMaxCommissionableNodesSupported(); ++i) +- { +- const Dnssd::DiscoveredNodeData * dnsSdInfo = devCtrl->GetDiscoveredDevice(i); +- if (dnsSdInfo == nullptr) +- { +- continue; +- } +- char rotatingId[Dnssd::kMaxRotatingIdLen * 2 + 1] = ""; +- Encoding::BytesToUppercaseHexString(dnsSdInfo->commissionData.rotatingId, dnsSdInfo->commissionData.rotatingIdLen, +- rotatingId, sizeof(rotatingId)); +- +- ChipLogProgress(Discovery, "Commissionable Node %d", i); +- ChipLogProgress(Discovery, "\tInstance name:\t\t%s", dnsSdInfo->commissionData.instanceName); +- ChipLogProgress(Discovery, "\tHost name:\t\t%s", dnsSdInfo->resolutionData.hostName); +- ChipLogProgress(Discovery, "\tPort:\t\t\t%u", dnsSdInfo->resolutionData.port); +- ChipLogProgress(Discovery, "\tLong discriminator:\t%u", dnsSdInfo->commissionData.longDiscriminator); +- ChipLogProgress(Discovery, "\tVendor ID:\t\t%u", dnsSdInfo->commissionData.vendorId); +- ChipLogProgress(Discovery, "\tProduct ID:\t\t%u", dnsSdInfo->commissionData.productId); +- ChipLogProgress(Discovery, "\tCommissioning Mode\t%u", dnsSdInfo->commissionData.commissioningMode); +- ChipLogProgress(Discovery, "\tDevice Type\t\t%u", dnsSdInfo->commissionData.deviceType); +- ChipLogProgress(Discovery, "\tDevice Name\t\t%s", dnsSdInfo->commissionData.deviceName); +- ChipLogProgress(Discovery, "\tRotating Id\t\t%s", rotatingId); +- ChipLogProgress(Discovery, "\tPairing Instruction\t%s", dnsSdInfo->commissionData.pairingInstruction); +- ChipLogProgress(Discovery, "\tPairing Hint\t\t%u", dnsSdInfo->commissionData.pairingHint); +- if (dnsSdInfo->resolutionData.GetMrpRetryIntervalIdle().HasValue()) +- { +- ChipLogProgress(Discovery, "\tMrp Interval idle\t%u", +- dnsSdInfo->resolutionData.GetMrpRetryIntervalIdle().Value().count()); +- } +- else +- { +- ChipLogProgress(Discovery, "\tMrp Interval idle\tNot present"); +- } +- if (dnsSdInfo->resolutionData.GetMrpRetryIntervalActive().HasValue()) +- { +- ChipLogProgress(Discovery, "\tMrp Interval active\t%u", +- dnsSdInfo->resolutionData.GetMrpRetryIntervalActive().Value().count()); +- } +- else +- { +- ChipLogProgress(Discovery, "\tMrp Interval active\tNot present"); +- } +- ChipLogProgress(Discovery, "\tSupports TCP\t\t%d", dnsSdInfo->resolutionData.supportsTcp); +- if (dnsSdInfo->resolutionData.isICDOperatingAsLIT.HasValue()) +- { +- ChipLogProgress(Discovery, "\tICD is operating as a\t%s", +- dnsSdInfo->resolutionData.isICDOperatingAsLIT.Value() ? "LIT" : "SIT"); +- } +- for (unsigned j = 0; j < dnsSdInfo->resolutionData.numIPs; ++j) +- { +- char buf[Inet::IPAddress::kMaxStringLength]; +- dnsSdInfo->resolutionData.ipAddress[j].ToString(buf); +- ChipLogProgress(Discovery, "\tAddress %d:\t\t%s", j, buf); +- } +- } +-} +- + bool pychip_DeviceController_GetIPForDiscoveredDevice(Controller::DeviceCommissioner * devCtrl, int idx, char * addrStr, + uint32_t len) + { +diff --git a/src/controller/python/ChipDeviceController-ScriptBinding.cpp b/src/controller/python/ChipDeviceController-ScriptBinding.cpp +index 728fd5801f..28bea5384a 100644 +--- a/src/controller/python/ChipDeviceController-ScriptBinding.cpp ++++ b/src/controller/python/ChipDeviceController-ScriptBinding.cpp +@@ -154,18 +154,6 @@ PyChipError pychip_DeviceController_EstablishPASESession(chip::Controller::Devic + chip::NodeId nodeid); + PyChipError pychip_DeviceController_Commission(chip::Controller::DeviceCommissioner * devCtrl, chip::NodeId nodeid); + +-PyChipError pychip_DeviceController_DiscoverCommissionableNodesLongDiscriminator(chip::Controller::DeviceCommissioner * devCtrl, +- uint16_t long_discriminator); +-PyChipError pychip_DeviceController_DiscoverAllCommissionableNodes(chip::Controller::DeviceCommissioner * devCtrl); +- +-PyChipError pychip_DeviceController_DiscoverCommissionableNodesShortDiscriminator(chip::Controller::DeviceCommissioner * devCtrl, +- uint16_t short_discriminator); +-PyChipError pychip_DeviceController_DiscoverCommissionableNodesVendor(chip::Controller::DeviceCommissioner * devCtrl, +- uint16_t vendor); +-PyChipError pychip_DeviceController_DiscoverCommissionableNodesDeviceType(chip::Controller::DeviceCommissioner * devCtrl, +- uint16_t device_type); +-PyChipError pychip_DeviceController_DiscoverCommissionableNodesCommissioningEnabled(chip::Controller::DeviceCommissioner * devCtrl); +- + PyChipError pychip_DeviceController_OnNetworkCommission(chip::Controller::DeviceCommissioner * devCtrl, + chip::Controller::ScriptDevicePairingDelegate * pairingDelegate, + uint64_t nodeId, uint32_t setupPasscode, const uint8_t filterType, +@@ -178,7 +166,6 @@ PyChipError pychip_DeviceController_OpenCommissioningWindow(chip::Controller::De + chip::NodeId nodeid, uint16_t timeout, uint32_t iteration, + uint16_t discriminator, uint8_t optionInt); + +-void pychip_DeviceController_PrintDiscoveredDevices(chip::Controller::DeviceCommissioner * devCtrl); + bool pychip_DeviceController_GetIPForDiscoveredDevice(chip::Controller::DeviceCommissioner * devCtrl, int idx, char * addrStr, + uint32_t len); + +@@ -617,46 +604,6 @@ PyChipError pychip_DeviceController_Commission(chip::Controller::DeviceCommissio + return ToPyChipError(devCtrl->Commission(nodeid, params)); + } + +-PyChipError pychip_DeviceController_DiscoverAllCommissionableNodes(chip::Controller::DeviceCommissioner * devCtrl) +-{ +- Dnssd::DiscoveryFilter filter(Dnssd::DiscoveryFilterType::kNone, static_cast(0)); +- return ToPyChipError(devCtrl->DiscoverCommissionableNodes(filter)); +-} +- +-PyChipError pychip_DeviceController_DiscoverCommissionableNodesLongDiscriminator(chip::Controller::DeviceCommissioner * devCtrl, +- uint16_t long_discriminator) +-{ +- Dnssd::DiscoveryFilter filter(Dnssd::DiscoveryFilterType::kLongDiscriminator, long_discriminator); +- return ToPyChipError(devCtrl->DiscoverCommissionableNodes(filter)); +-} +- +-PyChipError pychip_DeviceController_DiscoverCommissionableNodesShortDiscriminator(chip::Controller::DeviceCommissioner * devCtrl, +- uint16_t short_discriminator) +-{ +- Dnssd::DiscoveryFilter filter(Dnssd::DiscoveryFilterType::kShortDiscriminator, short_discriminator); +- return ToPyChipError(devCtrl->DiscoverCommissionableNodes(filter)); +-} +- +-PyChipError pychip_DeviceController_DiscoverCommissionableNodesVendor(chip::Controller::DeviceCommissioner * devCtrl, +- uint16_t vendor) +-{ +- Dnssd::DiscoveryFilter filter(Dnssd::DiscoveryFilterType::kVendorId, vendor); +- return ToPyChipError(devCtrl->DiscoverCommissionableNodes(filter)); +-} +- +-PyChipError pychip_DeviceController_DiscoverCommissionableNodesDeviceType(chip::Controller::DeviceCommissioner * devCtrl, +- uint16_t device_type) +-{ +- Dnssd::DiscoveryFilter filter(Dnssd::DiscoveryFilterType::kDeviceType, device_type); +- return ToPyChipError(devCtrl->DiscoverCommissionableNodes(filter)); +-} +- +-PyChipError pychip_DeviceController_DiscoverCommissionableNodesCommissioningEnabled(chip::Controller::DeviceCommissioner * devCtrl) +-{ +- Dnssd::DiscoveryFilter filter(Dnssd::DiscoveryFilterType::kCommissioningMode); +- return ToPyChipError(devCtrl->DiscoverCommissionableNodes(filter)); +-} +- + PyChipError pychip_ScriptDevicePairingDelegate_SetOpenWindowCompleteCallback( + chip::Controller::ScriptDevicePairingDelegate * pairingDelegate, + chip::Controller::DevicePairingDelegate_OnWindowOpenCompleteFunct callback) +diff --git a/src/controller/python/chip/ChipDeviceCtrl.py b/src/controller/python/chip/ChipDeviceCtrl.py +index acbbc88b3e..c2c502ce3a 100644 +--- a/src/controller/python/chip/ChipDeviceCtrl.py ++++ b/src/controller/python/chip/ChipDeviceCtrl.py +@@ -620,66 +620,6 @@ class ChipDeviceControllerBase(): + + return self.GetDiscoveredDevices() + +- def DiscoverCommissionableNodesLongDiscriminator(self, long_discriminator): +- ''' Deprecated, use DiscoverCommissionableNodes +- ''' +- self.CheckIsActive() +- +- self._ChipStack.Call( +- lambda: self._dmLib.pychip_DeviceController_DiscoverCommissionableNodesLongDiscriminator( +- self.devCtrl, long_discriminator) +- ).raise_on_error() +- +- def DiscoverCommissionableNodesShortDiscriminator(self, short_discriminator): +- ''' Deprecated, use DiscoverCommissionableNodes +- ''' +- self.CheckIsActive() +- +- self._ChipStack.Call( +- lambda: self._dmLib.pychip_DeviceController_DiscoverCommissionableNodesShortDiscriminator( +- self.devCtrl, short_discriminator) +- ).raise_on_error() +- +- def DiscoverCommissionableNodesVendor(self, vendor): +- ''' Deprecated, use DiscoverCommissionableNodes +- ''' +- self.CheckIsActive() +- +- self._ChipStack.Call( +- lambda: self._dmLib.pychip_DeviceController_DiscoverCommissionableNodesVendor( +- self.devCtrl, vendor) +- ).raise_on_error() +- +- def DiscoverCommissionableNodesDeviceType(self, device_type): +- ''' Deprecated, use DiscoverCommissionableNodes +- ''' +- self.CheckIsActive() +- +- self._ChipStack.Call( +- lambda: self._dmLib.pychip_DeviceController_DiscoverCommissionableNodesDeviceType( +- self.devCtrl, device_type) +- ).raise_on_error() +- +- def DiscoverCommissionableNodesCommissioningEnabled(self): +- ''' Deprecated, use DiscoverCommissionableNodes +- ''' +- self.CheckIsActive() +- +- self._ChipStack.Call( +- lambda: self._dmLib.pychip_DeviceController_DiscoverCommissionableNodesCommissioningEnabled( +- self.devCtrl) +- ).raise_on_error() +- +- def PrintDiscoveredDevices(self): +- ''' Deprecated, use GetCommissionableNodes +- ''' +- self.CheckIsActive() +- +- self._ChipStack.Call( +- lambda: self._dmLib.pychip_DeviceController_PrintDiscoveredDevices( +- self.devCtrl) +- ) +- + def GetDiscoveredDevices(self): + def GetDevices(devCtrl): + devices = [] +@@ -704,16 +644,6 @@ class ChipDeviceControllerBase(): + self.devCtrl, idx, addrStr, length) + ) + +- def DiscoverAllCommissioning(self): +- ''' Deprecated, use DiscoverCommissionableNodes +- ''' +- self.CheckIsActive() +- +- self._ChipStack.Call( +- lambda: self._dmLib.pychip_DeviceController_DiscoverAllCommissionableNodes( +- self.devCtrl) +- ).raise_on_error() +- + class CommissioningWindowPasscode(enum.IntEnum): + kOriginalSetupCode = 0, + kTokenWithRandomPin = 1, +@@ -1534,26 +1464,6 @@ class ChipDeviceControllerBase(): + c_void_p] + self._dmLib.pychip_DeviceController_StopCommissionableDiscovery.restype = PyChipError + +- self._dmLib.pychip_DeviceController_DiscoverCommissionableNodesLongDiscriminator.argtypes = [ +- c_void_p, c_uint16] +- self._dmLib.pychip_DeviceController_DiscoverCommissionableNodesLongDiscriminator.restype = PyChipError +- +- self._dmLib.pychip_DeviceController_DiscoverCommissionableNodesShortDiscriminator.argtypes = [ +- c_void_p, c_uint16] +- self._dmLib.pychip_DeviceController_DiscoverCommissionableNodesShortDiscriminator.restype = PyChipError +- +- self._dmLib.pychip_DeviceController_DiscoverCommissionableNodesVendor.argtypes = [ +- c_void_p, c_uint16] +- self._dmLib.pychip_DeviceController_DiscoverCommissionableNodesVendor.restype = PyChipError +- +- self._dmLib.pychip_DeviceController_DiscoverCommissionableNodesDeviceType.argtypes = [ +- c_void_p, c_uint16] +- self._dmLib.pychip_DeviceController_DiscoverCommissionableNodesDeviceType.restype = PyChipError +- +- self._dmLib.pychip_DeviceController_DiscoverCommissionableNodesCommissioningEnabled.argtypes = [ +- c_void_p] +- self._dmLib.pychip_DeviceController_DiscoverCommissionableNodesCommissioningEnabled.restype = PyChipError +- + self._dmLib.pychip_DeviceController_EstablishPASESessionIP.argtypes = [ + c_void_p, c_char_p, c_uint32, c_uint64, c_uint16] + self._dmLib.pychip_DeviceController_EstablishPASESessionIP.restype = PyChipError +@@ -1566,15 +1476,6 @@ class ChipDeviceControllerBase(): + c_void_p, c_char_p, c_uint64] + self._dmLib.pychip_DeviceController_EstablishPASESession.restype = PyChipError + +- self._dmLib.pychip_DeviceController_DiscoverAllCommissionableNodes.argtypes = [ +- c_void_p] +- self._dmLib.pychip_DeviceController_DiscoverAllCommissionableNodes.restype = PyChipError +- +- self._dmLib.pychip_DeviceController_PrintDiscoveredDevices.argtypes = [ +- c_void_p] +- self._dmLib.pychip_DeviceController_PrintDiscoveredDevices.argtypes = [ +- c_void_p, _ChipDeviceController_IterateDiscoveredCommissionableNodesFunct] +- + self._dmLib.pychip_DeviceController_HasDiscoveredCommissionableNode.argtypes = [c_void_p] + self._dmLib.pychip_DeviceController_HasDiscoveredCommissionableNode.restype = c_bool + +-- +2.45.2 + diff --git a/0021-Remove-unnecessary-error-log-from-CurrentFabricRemov.patch b/0021-Remove-unnecessary-error-log-from-CurrentFabricRemov.patch new file mode 100644 index 0000000..a0964f0 --- /dev/null +++ b/0021-Remove-unnecessary-error-log-from-CurrentFabricRemov.patch @@ -0,0 +1,39 @@ +From 92f9e7d0d746087ff4c6b0d86b80f7deba661d5d Mon Sep 17 00:00:00 2001 +From: Stefan Agner +Date: Thu, 13 Jun 2024 16:13:56 +0200 +Subject: [PATCH] Remove unnecessary error log from CurrentFabricRemover + (#33896) + +* Remove unnecessary error log from CurrentFabricRemover + +Currently, when the CurrentFabricRemover is successful it logs the +following error with err log level: + +Remove Current Fabric Result : src/controller/CurrentFabricRemover.cpp:133: Success + +Get rid of the message if successful, it is confusing. + +* Add braces to if statement +--- + src/controller/CurrentFabricRemover.cpp | 5 ++++- + 1 file changed, 4 insertions(+), 1 deletion(-) + +diff --git a/src/controller/CurrentFabricRemover.cpp b/src/controller/CurrentFabricRemover.cpp +index be89731b24..899860a028 100644 +--- a/src/controller/CurrentFabricRemover.cpp ++++ b/src/controller/CurrentFabricRemover.cpp +@@ -145,7 +145,10 @@ void CurrentFabricRemover::OnCommandFailure(void * context, CHIP_ERROR err) + + void CurrentFabricRemover::FinishRemoveCurrentFabric(void * context, CHIP_ERROR err) + { +- ChipLogError(Controller, "Remove Current Fabric Result : %" CHIP_ERROR_FORMAT, err.Format()); ++ if (err != CHIP_NO_ERROR) ++ { ++ ChipLogError(Controller, "Remove Current Fabric Failed : %" CHIP_ERROR_FORMAT, err.Format()); ++ } + auto * self = static_cast(context); + self->mNextStep = Step::kAcceptRemoveFabricStart; + if (self->mCurrentFabricRemoveCallback != nullptr) +-- +2.45.2 + diff --git a/0022-Python-Use-thread-safe-futures-for-concurrent-operat.patch b/0022-Python-Use-thread-safe-futures-for-concurrent-operat.patch new file mode 100644 index 0000000..1d082ec --- /dev/null +++ b/0022-Python-Use-thread-safe-futures-for-concurrent-operat.patch @@ -0,0 +1,579 @@ +From c50c9fe22beee19242de04ea01fa5eb031506c0b Mon Sep 17 00:00:00 2001 +From: Stefan Agner +Date: Thu, 13 Jun 2024 16:44:23 +0200 +Subject: [PATCH] [Python] Use thread-safe futures for concurrent operations + (#33891) + +* [Python] Use thread-safe futures for concurrent operations + +Instead of using quasi-global variables in the ChipStack singleton +use device controller local futures to store results from callbacks. +This has several advantages, namely: +- Avoid unnecessary shared state between device controllers +- Avoid unnecessary shared state between various operations within a + device controller (those who don't share callbacks could be called + from different threads now) +- Explicitly set Futures to None to detect spurious/unexpected callbacks +- Better code readability +- concurrent.futures are thread-safe +- Will make asyncio transition easier + +This change shouldn't change the external API. + +* [Python] Fix EstablishPASESession API compatibility + +* [Python] Make ConnectBLE behave as before +--- + src/controller/python/chip/ChipDeviceCtrl.py | 316 +++++++++++-------- + src/controller/python/chip/ChipStack.py | 27 +- + 2 files changed, 183 insertions(+), 160 deletions(-) + +diff --git a/src/controller/python/chip/ChipDeviceCtrl.py b/src/controller/python/chip/ChipDeviceCtrl.py +index c2c502ce3a..6805958420 100644 +--- a/src/controller/python/chip/ChipDeviceCtrl.py ++++ b/src/controller/python/chip/ChipDeviceCtrl.py +@@ -30,6 +30,7 @@ from __future__ import absolute_import, annotations, print_function + + import asyncio + import builtins ++import concurrent.futures + import copy + import ctypes + import enum +@@ -138,15 +139,6 @@ def _singleton(cls): + return wrapper + + +-class DCState(enum.IntEnum): +- NOT_INITIALIZED = 0 +- IDLE = 1 +- BLE_READY = 2 +- RENDEZVOUS_ONGOING = 3 +- RENDEZVOUS_CONNECTED = 4 +- COMMISSIONING = 5 +- +- + class CommissionableNode(discovery.CommissionableNode): + def SetDeviceController(self, devCtrl: 'ChipDeviceController'): + self._devCtrl = devCtrl +@@ -243,7 +235,6 @@ class ChipDeviceControllerBase(): + activeList = set() + + def __init__(self, name: str = ''): +- self.state = DCState.NOT_INITIALIZED + self.devCtrl = None + self._ChipStack = builtins.chipStack + self._dmLib = None +@@ -261,21 +252,26 @@ class ChipDeviceControllerBase(): + + self._Cluster = ChipClusters(builtins.chipStack) + self._Cluster.InitLib(self._dmLib) ++ self._commissioning_complete_future: typing.Optional[concurrent.futures.Future] = None ++ self._open_window_complete_future: typing.Optional[concurrent.futures.Future] = None ++ self._unpair_device_complete_future: typing.Optional[concurrent.futures.Future] = None ++ self._pase_establishment_complete_future: typing.Optional[concurrent.futures.Future] = None + + def _set_dev_ctrl(self, devCtrl, pairingDelegate): +- def HandleCommissioningComplete(nodeid, err): ++ def HandleCommissioningComplete(nodeId: int, err: PyChipError): + if err.is_success: + logging.info("Commissioning complete") + else: + logging.warning("Failed to commission: {}".format(err)) + +- self.state = DCState.IDLE +- self._ChipStack.callbackRes = err +- self._ChipStack.commissioningEventRes = err + if self._dmLib.pychip_TestCommissionerUsed(): +- self._ChipStack.commissioningEventRes = self._dmLib.pychip_GetCompletionError() +- self._ChipStack.commissioningCompleteEvent.set() +- self._ChipStack.completeEvent.set() ++ err = self._dmLib.pychip_GetCompletionError() ++ ++ if self._commissioning_complete_future is None: ++ logging.exception("HandleCommissioningComplete called unexpectedly") ++ return ++ ++ self._commissioning_complete_future.set_result(err) + + def HandleFabricCheck(nodeId): + self.fabricCheckNodeId = nodeId +@@ -284,13 +280,19 @@ class ChipDeviceControllerBase(): + setupQRCode: str, err: PyChipError) -> None: + if err.is_success: + logging.info("Open Commissioning Window complete setting nodeid {} pincode to {}".format(nodeid, setupPinCode)) +- self._ChipStack.openCommissioningWindowPincode[nodeid] = CommissioningParameters( ++ commissioningParameters = CommissioningParameters( + setupPinCode=setupPinCode, setupManualCode=setupManualCode.decode(), setupQRCode=setupQRCode.decode()) + else: + logging.warning("Failed to open commissioning window: {}".format(err)) + +- self._ChipStack.callbackRes = err +- self._ChipStack.completeEvent.set() ++ if self._open_window_complete_future is None: ++ logging.exception("HandleOpenWindowComplete called unexpectedly") ++ return ++ ++ if err.is_success: ++ self._open_window_complete_future.set_result(commissioningParameters) ++ else: ++ self._open_window_complete_future.set_exception(err.to_exception()) + + def HandleUnpairDeviceComplete(nodeid: int, err: PyChipError): + if err.is_success: +@@ -298,27 +300,33 @@ class ChipDeviceControllerBase(): + else: + logging.warning("Failed to unpair device: {}".format(err)) + +- self._ChipStack.callbackRes = err +- self._ChipStack.completeEvent.set() ++ if self._unpair_device_complete_future is None: ++ logging.exception("HandleUnpairDeviceComplete called unexpectedly") ++ return ++ ++ if err.is_success: ++ self._unpair_device_complete_future.set_result(None) ++ else: ++ self._unpair_device_complete_future.set_exception(err.to_exception()) + + def HandlePASEEstablishmentComplete(err: PyChipError): + if not err.is_success: + logging.warning("Failed to establish secure session to device: {}".format(err)) +- self._ChipStack.callbackRes = err.to_exception() + else: + logging.info("Established secure session with Device") + +- if self.state != DCState.COMMISSIONING: +- # During Commissioning, HandlePASEEstablishmentComplete will also be called, +- # in this case the async operation should be marked as finished by +- # HandleCommissioningComplete instead this function. +- self.state = DCState.IDLE +- self._ChipStack.completeEvent.set() +- else: +- # When commissioning, getting an error during key exhange +- # needs to unblock the entire commissioning flow. ++ if self._commissioning_complete_future is not None: ++ # During Commissioning, HandlePASEEstablishmentComplete will also be called. ++ # Only complete the future if PASE session establishment failed. + if not err.is_success: +- HandleCommissioningComplete(0, err) ++ self._commissioning_complete_future.set_result(err) ++ return ++ ++ if self._pase_establishment_complete_future is None: ++ logging.exception("HandlePASEEstablishmentComplete called unexpectedly") ++ return ++ ++ self._pase_establishment_complete_future.set_result(err) + + self.pairingDelegate = pairingDelegate + self.devCtrl = devCtrl +@@ -343,14 +351,12 @@ class ChipDeviceControllerBase(): + + self.cbHandleDeviceUnpairCompleteFunct = _DeviceUnpairingCompleteFunct(HandleUnpairDeviceComplete) + +- self.state = DCState.IDLE + self._isActive = True + # Validate FabricID/NodeID followed from NOC Chain + self._fabricId = self.GetFabricIdInternal() + self._nodeId = self.GetNodeIdInternal() + + def _finish_init(self): +- self.state = DCState.IDLE + self._isActive = True + + ChipDeviceController.activeList.add(self) +@@ -440,26 +446,35 @@ class ChipDeviceControllerBase(): + def ConnectBLE(self, discriminator, setupPinCode, nodeid) -> PyChipError: + self.CheckIsActive() + +- self._ChipStack.commissioningCompleteEvent.clear() ++ self._commissioning_complete_future = concurrent.futures.Future() + +- self.state = DCState.COMMISSIONING +- self._enablePairingCompeleteCallback(True) +- self._ChipStack.CallAsyncWithCompleteCallback( +- lambda: self._dmLib.pychip_DeviceController_ConnectBLE( +- self.devCtrl, discriminator, setupPinCode, nodeid) +- ).raise_on_error() +- if not self._ChipStack.commissioningCompleteEvent.isSet(): +- # Error 50 is a timeout +- return PyChipError(CHIP_ERROR_TIMEOUT) +- return self._ChipStack.commissioningEventRes ++ try: ++ self._enablePairingCompeleteCallback(True) ++ self._ChipStack.Call( ++ lambda: self._dmLib.pychip_DeviceController_ConnectBLE( ++ self.devCtrl, discriminator, setupPinCode, nodeid) ++ ).raise_on_error() ++ ++ # TODO: Change return None. Only returning on success is not useful. ++ # but that is what the previous implementation did. ++ res = self._commissioning_complete_future.result() ++ res.raise_on_error() ++ return res ++ finally: ++ self._commissioning_complete_future = None + +- def UnpairDevice(self, nodeid: int): ++ def UnpairDevice(self, nodeid: int) -> None: + self.CheckIsActive() + +- return self._ChipStack.CallAsyncWithCompleteCallback( +- lambda: self._dmLib.pychip_DeviceController_UnpairDevice( +- self.devCtrl, nodeid, self.cbHandleDeviceUnpairCompleteFunct) +- ).raise_on_error() ++ self._unpair_device_complete_future = concurrent.futures.Future() ++ try: ++ self._ChipStack.Call( ++ lambda: self._dmLib.pychip_DeviceController_UnpairDevice( ++ self.devCtrl, nodeid, self.cbHandleDeviceUnpairCompleteFunct) ++ ).raise_on_error() ++ self._unpair_device_complete_future.result() ++ finally: ++ self._unpair_device_complete_future = None + + def CloseBLEConnection(self): + self.CheckIsActive() +@@ -493,32 +508,62 @@ class ChipDeviceControllerBase(): + def EstablishPASESessionBLE(self, setupPinCode: int, discriminator: int, nodeid: int): + self.CheckIsActive() + +- self.state = DCState.RENDEZVOUS_ONGOING +- self._enablePairingCompeleteCallback(True) +- return self._ChipStack.CallAsyncWithCompleteCallback( +- lambda: self._dmLib.pychip_DeviceController_EstablishPASESessionBLE( +- self.devCtrl, setupPinCode, discriminator, nodeid) +- ) ++ self._pase_establishment_complete_future = concurrent.futures.Future() ++ try: ++ self._enablePairingCompeleteCallback(True) ++ self._ChipStack.Call( ++ lambda: self._dmLib.pychip_DeviceController_EstablishPASESessionBLE( ++ self.devCtrl, setupPinCode, discriminator, nodeid) ++ ).raise_on_error() ++ ++ # TODO: This is a bit funky, but what the API returned with the previous ++ # implementation. We should revisit this. ++ err = self._pase_establishment_complete_future.result() ++ if not err.is_success: ++ return err.to_exception() ++ return None ++ finally: ++ self._pase_establishment_complete_future = None + + def EstablishPASESessionIP(self, ipaddr: str, setupPinCode: int, nodeid: int, port: int = 0): + self.CheckIsActive() + +- self.state = DCState.RENDEZVOUS_ONGOING +- self._enablePairingCompeleteCallback(True) +- return self._ChipStack.CallAsyncWithCompleteCallback( +- lambda: self._dmLib.pychip_DeviceController_EstablishPASESessionIP( +- self.devCtrl, ipaddr.encode("utf-8"), setupPinCode, nodeid, port) +- ) ++ self._pase_establishment_complete_future = concurrent.futures.Future() ++ try: ++ self._enablePairingCompeleteCallback(True) ++ self._ChipStack.Call( ++ lambda: self._dmLib.pychip_DeviceController_EstablishPASESessionIP( ++ self.devCtrl, ipaddr.encode("utf-8"), setupPinCode, nodeid, port) ++ ).raise_on_error() ++ ++ # TODO: This is a bit funky, but what the API returned with the previous ++ # implementation. We should revisit this. ++ err = self._pase_establishment_complete_future.result() ++ if not err.is_success: ++ return err.to_exception() ++ return None ++ finally: ++ self._pase_establishment_complete_future = None + + def EstablishPASESession(self, setUpCode: str, nodeid: int): + self.CheckIsActive() + +- self.state = DCState.RENDEZVOUS_ONGOING +- self._enablePairingCompeleteCallback(True) +- return self._ChipStack.CallAsyncWithCompleteCallback( +- lambda: self._dmLib.pychip_DeviceController_EstablishPASESession( +- self.devCtrl, setUpCode.encode("utf-8"), nodeid) +- ) ++ self._pase_establishment_complete_future = concurrent.futures.Future() ++ try: ++ self._enablePairingCompeleteCallback(True) ++ self._ChipStack.Call( ++ lambda: self._dmLib.pychip_DeviceController_EstablishPASESession( ++ self.devCtrl, setUpCode.encode("utf-8"), nodeid) ++ ).raise_on_error() ++ ++ # TODO: This is a bit funky, but what the API returned with the previous ++ # implementation. We should revisit this. ++ err = self._pase_establishment_complete_future.result() ++ if not err.is_success: ++ return err.to_exception() ++ return None ++ finally: ++ self._pase_establishment_complete_future = None + + def GetTestCommissionerUsed(self): + return self._ChipStack.Call( +@@ -553,11 +598,6 @@ class ChipDeviceControllerBase(): + def CheckTestCommissionerPaseConnection(self, nodeid): + return self._dmLib.pychip_TestPaseConnection(nodeid) + +- def NOCChainCallback(self, nocChain): +- self._ChipStack.callbackRes = nocChain +- self._ChipStack.completeEvent.set() +- return +- + def ResolveNode(self, nodeid): + self.CheckIsActive() + +@@ -664,12 +704,16 @@ class ChipDeviceControllerBase(): + Returns CommissioningParameters + ''' + self.CheckIsActive() +- self._ChipStack.CallAsyncWithCompleteCallback( +- lambda: self._dmLib.pychip_DeviceController_OpenCommissioningWindow( +- self.devCtrl, self.pairingDelegate, nodeid, timeout, iteration, discriminator, option) +- ).raise_on_error() +- self._ChipStack.callbackRes.raise_on_error() +- return self._ChipStack.openCommissioningWindowPincode[nodeid] ++ self._open_window_complete_future = concurrent.futures.Future() ++ try: ++ self._ChipStack.Call( ++ lambda: self._dmLib.pychip_DeviceController_OpenCommissioningWindow( ++ self.devCtrl, self.pairingDelegate, nodeid, timeout, iteration, discriminator, option) ++ ).raise_on_error() ++ ++ return self._open_window_complete_future.result() ++ finally: ++ self._open_window_complete_future = None + + def GetCompressedFabricId(self): + self.CheckIsActive() +@@ -1630,6 +1674,7 @@ class ChipDeviceController(ChipDeviceControllerBase): + f"caIndex({fabricAdmin.caIndex:x})/fabricId(0x{fabricId:016X})/nodeId(0x{nodeId:016X})" + ) + ++ self._issue_node_chain_complete: typing.Optional[concurrent.futures.Future] = None + self._dmLib.pychip_DeviceController_SetIssueNOCChainCallbackPythonCallback(_IssueNOCChainCallbackPythonCallback) + + pairingDelegate = c_void_p(None) +@@ -1680,17 +1725,18 @@ class ChipDeviceController(ChipDeviceControllerBase): + bool: True if successful, False otherwise. + ''' + self.CheckIsActive() +- self._ChipStack.commissioningCompleteEvent.clear() +- self.state = DCState.COMMISSIONING + +- self._ChipStack.CallAsyncWithCompleteCallback( +- lambda: self._dmLib.pychip_DeviceController_Commission( +- self.devCtrl, nodeid) +- ) +- if not self._ChipStack.commissioningCompleteEvent.isSet(): +- # Error 50 is a timeout +- return PyChipError(CHIP_ERROR_TIMEOUT) +- return self._ChipStack.commissioningEventRes ++ self._commissioning_complete_future = concurrent.futures.Future() ++ ++ try: ++ self._ChipStack.Call( ++ lambda: self._dmLib.pychip_DeviceController_Commission( ++ self.devCtrl, nodeid) ++ ).raise_on_error() ++ ++ return self._commissioning_complete_future.result() ++ finally: ++ self._commissioning_complete_future = None + + def CommissionThread(self, discriminator, setupPinCode, nodeId, threadOperationalDataset: bytes) -> PyChipError: + ''' Commissions a Thread device over BLE +@@ -1788,25 +1834,21 @@ class ChipDeviceController(ChipDeviceControllerBase): + ''' + self.CheckIsActive() + +- # IP connection will run through full commissioning, so we need to wait +- # for the commissioning complete event, not just any callback. +- self.state = DCState.COMMISSIONING +- + # Convert numerical filters to string for passing down to binding. + if isinstance(filter, int): + filter = str(filter) + +- self._ChipStack.commissioningCompleteEvent.clear() ++ self._commissioning_complete_future = concurrent.futures.Future() ++ try: ++ self._enablePairingCompeleteCallback(True) ++ self._ChipStack.Call( ++ lambda: self._dmLib.pychip_DeviceController_OnNetworkCommission( ++ self.devCtrl, self.pairingDelegate, nodeId, setupPinCode, int(filterType), str(filter).encode("utf-8") + b"\x00" if filter is not None else None, discoveryTimeoutMsec) ++ ).raise_on_error() + +- self._enablePairingCompeleteCallback(True) +- self._ChipStack.CallAsyncWithCompleteCallback( +- lambda: self._dmLib.pychip_DeviceController_OnNetworkCommission( +- self.devCtrl, self.pairingDelegate, nodeId, setupPinCode, int(filterType), str(filter).encode("utf-8") + b"\x00" if filter is not None else None, discoveryTimeoutMsec) +- ) +- if not self._ChipStack.commissioningCompleteEvent.isSet(): +- # Error 50 is a timeout +- return PyChipError(CHIP_ERROR_TIMEOUT) +- return self._ChipStack.commissioningEventRes ++ return self._commissioning_complete_future.result() ++ finally: ++ self._commissioning_complete_future = None + + def CommissionWithCode(self, setupPayload: str, nodeid: int, discoveryType: DiscoveryType = DiscoveryType.DISCOVERY_ALL) -> PyChipError: + ''' Commission with the given nodeid from the setupPayload. +@@ -1816,51 +1858,57 @@ class ChipDeviceController(ChipDeviceControllerBase): + + setupPayload = setupPayload.encode() + b'\0' + +- # IP connection will run through full commissioning, so we need to wait +- # for the commissioning complete event, not just any callback. +- self.state = DCState.COMMISSIONING ++ self._commissioning_complete_future = concurrent.futures.Future() + +- self._ChipStack.commissioningCompleteEvent.clear() ++ try: ++ self._enablePairingCompeleteCallback(True) ++ self._ChipStack.Call( ++ lambda: self._dmLib.pychip_DeviceController_ConnectWithCode( ++ self.devCtrl, setupPayload, nodeid, discoveryType.value) ++ ).raise_on_error() + +- self._enablePairingCompeleteCallback(True) +- self._ChipStack.CallAsyncWithCompleteCallback( +- lambda: self._dmLib.pychip_DeviceController_ConnectWithCode( +- self.devCtrl, setupPayload, nodeid, discoveryType.value) +- ) +- if not self._ChipStack.commissioningCompleteEvent.isSet(): +- # Error 50 is a timeout +- return PyChipError(CHIP_ERROR_TIMEOUT) +- return self._ChipStack.commissioningEventRes ++ return self._commissioning_complete_future.result() ++ finally: ++ self._commissioning_complete_future = None + + def CommissionIP(self, ipaddr: str, setupPinCode: int, nodeid: int) -> PyChipError: + """ DEPRECATED, DO NOT USE! Use `CommissionOnNetwork` or `CommissionWithCode` """ + self.CheckIsActive() + +- # IP connection will run through full commissioning, so we need to wait +- # for the commissioning complete event, not just any callback. +- self.state = DCState.COMMISSIONING ++ self._commissioning_complete_future = concurrent.futures.Future() + +- self._ChipStack.commissioningCompleteEvent.clear() ++ try: ++ self._enablePairingCompeleteCallback(True) ++ self._ChipStack.Call( ++ lambda: self._dmLib.pychip_DeviceController_ConnectIP( ++ self.devCtrl, ipaddr.encode("utf-8"), setupPinCode, nodeid) ++ ).raise_on_error() + +- self._enablePairingCompeleteCallback(True) +- self._ChipStack.CallAsyncWithCompleteCallback( +- lambda: self._dmLib.pychip_DeviceController_ConnectIP( +- self.devCtrl, ipaddr.encode("utf-8"), setupPinCode, nodeid) +- ) +- if not self._ChipStack.commissioningCompleteEvent.isSet(): +- # Error 50 is a timeout +- return PyChipError(CHIP_ERROR_TIMEOUT) +- return self._ChipStack.commissioningEventRes ++ return self._commissioning_complete_future.result() ++ finally: ++ self._commissioning_complete_future = None ++ ++ def NOCChainCallback(self, nocChain): ++ if self._issue_node_chain_complete is None: ++ logging.exception("NOCChainCallback while not expecting a callback") ++ return ++ self._issue_node_chain_complete.set_result(nocChain) ++ return + + def IssueNOCChain(self, csr: Clusters.OperationalCredentials.Commands.CSRResponse, nodeId: int): + """Issue an NOC chain using the associated OperationalCredentialsDelegate. + The NOC chain will be provided in TLV cert format.""" + self.CheckIsActive() + +- return self._ChipStack.CallAsyncWithCompleteCallback( +- lambda: self._dmLib.pychip_DeviceController_IssueNOCChain( +- self.devCtrl, py_object(self), csr.NOCSRElements, len(csr.NOCSRElements), nodeId) +- ) ++ self._issue_node_chain_complete = concurrent.futures.Future() ++ try: ++ self._ChipStack.Call( ++ lambda: self._dmLib.pychip_DeviceController_IssueNOCChain( ++ self.devCtrl, py_object(self), csr.NOCSRElements, len(csr.NOCSRElements), nodeId) ++ ).raise_on_error() ++ return self._issue_node_chain_complete.result() ++ finally: ++ self._issue_node_chain_complete = None + + + class BareChipDeviceController(ChipDeviceControllerBase): +diff --git a/src/controller/python/chip/ChipStack.py b/src/controller/python/chip/ChipStack.py +index 5fd0601ba2..4f19776664 100644 +--- a/src/controller/python/chip/ChipStack.py ++++ b/src/controller/python/chip/ChipStack.py +@@ -30,7 +30,7 @@ import asyncio + import builtins + import os + from ctypes import CFUNCTYPE, Structure, c_bool, c_char_p, c_uint16, c_uint32, c_void_p, py_object, pythonapi +-from threading import Condition, Event, Lock ++from threading import Condition, Lock + + import chip.native + from chip.native import PyChipError +@@ -144,14 +144,9 @@ class ChipStack(object): + def __init__(self, persistentStoragePath: str, enableServerInteractions=True): + builtins.enableDebugMode = False + +- self.completeEvent = Event() +- self.commissioningCompleteEvent = Event() + self._ChipStackLib = None + self._chipDLLPath = None + self.devMgr = None +- self.callbackRes = None +- self.commissioningEventRes = None +- self.openCommissioningWindowPincode = {} + self._enableServerInteractions = enableServerInteractions + + # +@@ -212,7 +207,6 @@ class ChipStack(object): + self._ChipStackLib = None + self._chipDLLPath = None + self.devMgr = None +- self.callbackRes = None + + delattr(builtins, "chipStack") + +@@ -239,25 +233,6 @@ class ChipStack(object): + + return await asyncio.wait_for(callObj.future, timeoutMs / 1000 if timeoutMs else None) + +- def CallAsyncWithCompleteCallback(self, callFunct): +- '''Run a Python function on CHIP stack, and wait for the application specific response. +- This function is a wrapper of PostTaskOnChipThread, which includes some handling of application specific logics. +- Calling this function on CHIP on CHIP mainloop thread will cause deadlock. +- Make sure to register the necessary callbacks which release the function by setting the completeEvent. +- ''' +- # throw error if op in progress +- self.callbackRes = None +- self.completeEvent.clear() +- res = self.PostTaskOnChipThread(callFunct).Wait() +- +- if not res.is_success: +- self.completeEvent.set() +- raise res.to_exception() +- self.completeEvent.wait() +- if isinstance(self.callbackRes, ChipStackException): +- raise self.callbackRes +- return self.callbackRes +- + def PostTaskOnChipThread(self, callFunct) -> AsyncCallableHandle: + '''Run a Python function on CHIP stack, and wait for the response. + This function will post a task on CHIP mainloop, and return an object with Wait() method for getting the result. +-- +2.45.2 + diff --git a/0023-Avoid-errors-when-using-on-network-commissioning-338.patch b/0023-Avoid-errors-when-using-on-network-commissioning-338.patch new file mode 100644 index 0000000..819c9c1 --- /dev/null +++ b/0023-Avoid-errors-when-using-on-network-commissioning-338.patch @@ -0,0 +1,52 @@ +From 005887af17aa03eb655cee10871e16ff65ceb34e Mon Sep 17 00:00:00 2001 +From: Stefan Agner +Date: Thu, 13 Jun 2024 22:29:36 +0200 +Subject: [PATCH] Avoid errors when using on-network commissioning (#33880) + +When on network commissioning is used from Python we currently don't +stop discovery even though we already found a device. Future devices +found won't be processed, so it is fine to stop discovery of +commissionable nodes at this point. + +Also avoid "Unknown filter type; all matches will fail" errors in the +log: If the filter type is set to None, it wasn't the SetUpCodePairer +which set up the discovery. Avoid printing errors in this case. + +A potential alternative to this would be to skip notifying the +SetUpCodePairer in DeviceCommissioner::OnNodeDiscovered in this case. +--- + src/controller/SetUpCodePairer.cpp | 3 +++ + ...ipDeviceController-ScriptPairingDeviceDiscoveryDelegate.cpp | 3 +++ + 2 files changed, 6 insertions(+) + +diff --git a/src/controller/SetUpCodePairer.cpp b/src/controller/SetUpCodePairer.cpp +index db09d91fd7..3a8997703d 100644 +--- a/src/controller/SetUpCodePairer.cpp ++++ b/src/controller/SetUpCodePairer.cpp +@@ -363,6 +363,9 @@ bool SetUpCodePairer::NodeMatchesCurrentFilter(const Dnssd::DiscoveredNodeData & + case Dnssd::DiscoveryFilterType::kLongDiscriminator: + discriminatorMatches = (nodeData.commissionData.longDiscriminator == mCurrentFilter.code); + break; ++ case Dnssd::DiscoveryFilterType::kNone: ++ ChipLogDetail(Controller, "Filter type none; all matches will fail"); ++ return false; + default: + ChipLogError(Controller, "Unknown filter type; all matches will fail"); + return false; +diff --git a/src/controller/python/ChipDeviceController-ScriptPairingDeviceDiscoveryDelegate.cpp b/src/controller/python/ChipDeviceController-ScriptPairingDeviceDiscoveryDelegate.cpp +index 850ec208ac..d211ac9058 100644 +--- a/src/controller/python/ChipDeviceController-ScriptPairingDeviceDiscoveryDelegate.cpp ++++ b/src/controller/python/ChipDeviceController-ScriptPairingDeviceDiscoveryDelegate.cpp +@@ -32,6 +32,9 @@ void ScriptPairingDeviceDiscoveryDelegate::OnDiscoveredDevice(const Dnssd::Disco + nodeData.resolutionData.ipAddress[0].ToString(buf); + ChipLogProgress(chipTool, "Discovered Device: %s:%u", buf, port); + ++ // Stop active discovery. ++ mActiveDeviceCommissioner->StopCommissionableDiscovery(); ++ + // Cancel discovery timer. + chip::DeviceLayer::SystemLayer().CancelTimer(OnDiscoveredTimeout, this); + +-- +2.45.2 + diff --git a/0024-Add-success-message-on-removing-current-fabric-33914.patch b/0024-Add-success-message-on-removing-current-fabric-33914.patch new file mode 100644 index 0000000..c93f277 --- /dev/null +++ b/0024-Add-success-message-on-removing-current-fabric-33914.patch @@ -0,0 +1,31 @@ +From 5ec1d9c49d505d5e462f6c935b7f325cbf632e8f Mon Sep 17 00:00:00 2001 +From: Stefan Agner +Date: Fri, 14 Jun 2024 01:34:21 +0200 +Subject: [PATCH] Add success message on removing current fabric (#33914) + +Readd a message with progress-level when removing the current fabric +succeeded. +--- + src/controller/CurrentFabricRemover.cpp | 6 +++++- + 1 file changed, 5 insertions(+), 1 deletion(-) + +diff --git a/src/controller/CurrentFabricRemover.cpp b/src/controller/CurrentFabricRemover.cpp +index 899860a028..167fea0bb3 100644 +--- a/src/controller/CurrentFabricRemover.cpp ++++ b/src/controller/CurrentFabricRemover.cpp +@@ -145,7 +145,11 @@ void CurrentFabricRemover::OnCommandFailure(void * context, CHIP_ERROR err) + + void CurrentFabricRemover::FinishRemoveCurrentFabric(void * context, CHIP_ERROR err) + { +- if (err != CHIP_NO_ERROR) ++ if (err == CHIP_NO_ERROR) ++ { ++ ChipLogProgress(Controller, "Remove Current Fabric succeeded."); ++ } ++ else + { + ChipLogError(Controller, "Remove Current Fabric Failed : %" CHIP_ERROR_FORMAT, err.Format()); + } +-- +2.45.2 + diff --git a/0025-Python-Drop-unnecessary-null-termination-33915.patch b/0025-Python-Drop-unnecessary-null-termination-33915.patch new file mode 100644 index 0000000..291bc1e --- /dev/null +++ b/0025-Python-Drop-unnecessary-null-termination-33915.patch @@ -0,0 +1,54 @@ +From 049c5803b347e520ba4b3653ce623b6543ae05b6 Mon Sep 17 00:00:00 2001 +From: Stefan Agner +Date: Fri, 14 Jun 2024 15:43:44 +0200 +Subject: [PATCH] [Python] Drop unnecessary null termination (#33915) + +The ctypes data type `c_char_p` takes care of null-terminating the byte +array provided to it. The additional null termination doesn't hurt in +practice, but it's unnecessary. +--- + src/controller/python/chip/ChipDeviceCtrl.py | 8 +++----- + 1 file changed, 3 insertions(+), 5 deletions(-) + +diff --git a/src/controller/python/chip/ChipDeviceCtrl.py b/src/controller/python/chip/ChipDeviceCtrl.py +index 6805958420..b99d1db018 100644 +--- a/src/controller/python/chip/ChipDeviceCtrl.py ++++ b/src/controller/python/chip/ChipDeviceCtrl.py +@@ -642,7 +642,7 @@ class ChipDeviceControllerBase(): + + self._ChipStack.Call( + lambda: self._dmLib.pychip_DeviceController_DiscoverCommissionableNodes( +- self.devCtrl, int(filterType), str(filter).encode("utf-8") + b"\x00")).raise_on_error() ++ self.devCtrl, int(filterType), str(filter).encode("utf-8"))).raise_on_error() + + if timeoutSecond != 0: + if stopOnFirst: +@@ -1843,7 +1843,7 @@ class ChipDeviceController(ChipDeviceControllerBase): + self._enablePairingCompeleteCallback(True) + self._ChipStack.Call( + lambda: self._dmLib.pychip_DeviceController_OnNetworkCommission( +- self.devCtrl, self.pairingDelegate, nodeId, setupPinCode, int(filterType), str(filter).encode("utf-8") + b"\x00" if filter is not None else None, discoveryTimeoutMsec) ++ self.devCtrl, self.pairingDelegate, nodeId, setupPinCode, int(filterType), str(filter).encode("utf-8") if filter is not None else None, discoveryTimeoutMsec) + ).raise_on_error() + + return self._commissioning_complete_future.result() +@@ -1856,15 +1856,13 @@ class ChipDeviceController(ChipDeviceControllerBase): + ''' + self.CheckIsActive() + +- setupPayload = setupPayload.encode() + b'\0' +- + self._commissioning_complete_future = concurrent.futures.Future() + + try: + self._enablePairingCompeleteCallback(True) + self._ChipStack.Call( + lambda: self._dmLib.pychip_DeviceController_ConnectWithCode( +- self.devCtrl, setupPayload, nodeid, discoveryType.value) ++ self.devCtrl, setupPayload.encode("utf-8"), nodeid, discoveryType.value) + ).raise_on_error() + + return self._commissioning_complete_future.result() +-- +2.45.2 + diff --git a/0026-Fix-python-Wi-Fi-Thread-setup-with-manual-code-33933.patch b/0026-Fix-python-Wi-Fi-Thread-setup-with-manual-code-33933.patch new file mode 100644 index 0000000..3299abf --- /dev/null +++ b/0026-Fix-python-Wi-Fi-Thread-setup-with-manual-code-33933.patch @@ -0,0 +1,416 @@ +From 462bd9d6a8a9dcf60ab9f674e41c762c602fd8e0 Mon Sep 17 00:00:00 2001 +From: Tennessee Carmel-Veilleux +Date: Fri, 14 Jun 2024 18:52:44 -0400 +Subject: [PATCH] Fix python Wi-Fi/Thread setup with manual code (#33933) + +* Fix python Wi-Fi/Thread setup with manual code + +- Plumbing was missing to pass down the short discriminator +- Passing `--manual-code 1234-567-8901` which only has short + discriminator, would always fail to find device over BLE + +Fixes #26907 + +This PR: + +- Adds plumbing to detect short discriminator in Python controller +- Improves code-based setup in CHIPDeviceController to honor the + SetupDiscriminator value, including whether short/long. + +Testing done: +- Ran `python3 src/python_testing/TC_SC_3_6.py --commissioning-method ble-wifi --wifi-ssid MySsid --wifi-passphrase Secret123 --manual-code 2168-374-4904 --storage-path kvs1` + - Before fix, discriminator always mismatched. + - After fix, commissioning succeeds. +- Unit tests and other integration tests still pass + +* Restyled by clang-format + +* Restyled by autopep8 + +* Add warning about GetDiscriminator + +* Improve unit test + +* Fix tests + +* Address review comments + +* Restyled by clang-format + +--------- + +Co-authored-by: Restyled.io +--- + src/controller/CHIPDeviceController.cpp | 7 +-- + .../ChipDeviceController-ScriptBinding.cpp | 18 +++++- + src/controller/python/chip/ChipDeviceCtrl.py | 14 ++--- + src/lib/support/SetupDiscriminator.h | 10 ++-- + .../secure_channel/RendezvousParameters.h | 59 +++++++++++++++++-- + src/python_testing/matter_testing_support.py | 6 +- + src/setup_payload/SetupPayload.h | 2 +- + src/setup_payload/tests/TestManualCode.cpp | 20 ++++--- + 8 files changed, 99 insertions(+), 37 deletions(-) + +diff --git a/src/controller/CHIPDeviceController.cpp b/src/controller/CHIPDeviceController.cpp +index af0a66ea83..335717664b 100644 +--- a/src/controller/CHIPDeviceController.cpp ++++ b/src/controller/CHIPDeviceController.cpp +@@ -714,10 +714,9 @@ CHIP_ERROR DeviceCommissioner::EstablishPASEConnection(NodeId remoteDeviceId, Re + // for later. + mRendezvousParametersForDeviceDiscoveredOverBle = params; + +- SetupDiscriminator discriminator; +- discriminator.SetLongValue(params.GetDiscriminator()); +- SuccessOrExit(err = mSystemState->BleLayer()->NewBleConnectionByDiscriminator( +- discriminator, this, OnDiscoveredDeviceOverBleSuccess, OnDiscoveredDeviceOverBleError)); ++ SuccessOrExit(err = mSystemState->BleLayer()->NewBleConnectionByDiscriminator(params.GetSetupDiscriminator().value(), ++ this, OnDiscoveredDeviceOverBleSuccess, ++ OnDiscoveredDeviceOverBleError)); + ExitNow(CHIP_NO_ERROR); + } + else +diff --git a/src/controller/python/ChipDeviceController-ScriptBinding.cpp b/src/controller/python/ChipDeviceController-ScriptBinding.cpp +index 28bea5384a..4a48434411 100644 +--- a/src/controller/python/ChipDeviceController-ScriptBinding.cpp ++++ b/src/controller/python/ChipDeviceController-ScriptBinding.cpp +@@ -71,6 +71,7 @@ + #include + #include + #include ++#include + #include + #include + #include +@@ -130,7 +131,7 @@ PyChipError pychip_DeviceController_GetNodeId(chip::Controller::DeviceCommission + + // Rendezvous + PyChipError pychip_DeviceController_ConnectBLE(chip::Controller::DeviceCommissioner * devCtrl, uint16_t discriminator, +- uint32_t setupPINCode, chip::NodeId nodeid); ++ bool isShortDiscriminator, uint32_t setupPINCode, chip::NodeId nodeid); + PyChipError pychip_DeviceController_ConnectIP(chip::Controller::DeviceCommissioner * devCtrl, const char * peerAddrStr, + uint32_t setupPINCode, chip::NodeId nodeid); + PyChipError pychip_DeviceController_ConnectWithCode(chip::Controller::DeviceCommissioner * devCtrl, const char * onboardingPayload, +@@ -347,13 +348,24 @@ const char * pychip_DeviceController_StatusReportToString(uint32_t profileId, ui + } + + PyChipError pychip_DeviceController_ConnectBLE(chip::Controller::DeviceCommissioner * devCtrl, uint16_t discriminator, +- uint32_t setupPINCode, chip::NodeId nodeid) ++ bool isShortDiscriminator, uint32_t setupPINCode, chip::NodeId nodeid) + { ++ SetupDiscriminator setupDiscriminator; ++ ++ if (isShortDiscriminator) ++ { ++ setupDiscriminator.SetShortValue(discriminator & 0xFu); ++ } ++ else ++ { ++ setupDiscriminator.SetLongValue(discriminator); ++ } ++ + return ToPyChipError(devCtrl->PairDevice(nodeid, + chip::RendezvousParameters() + .SetPeerAddress(Transport::PeerAddress(Transport::Type::kBle)) + .SetSetupPINCode(setupPINCode) +- .SetDiscriminator(discriminator), ++ .SetSetupDiscriminator(setupDiscriminator), + sCommissioningParameters)); + } + +diff --git a/src/controller/python/chip/ChipDeviceCtrl.py b/src/controller/python/chip/ChipDeviceCtrl.py +index b99d1db018..3cb7e67b7a 100644 +--- a/src/controller/python/chip/ChipDeviceCtrl.py ++++ b/src/controller/python/chip/ChipDeviceCtrl.py +@@ -443,7 +443,7 @@ class ChipDeviceControllerBase(): + self.devCtrl) + ) + +- def ConnectBLE(self, discriminator, setupPinCode, nodeid) -> PyChipError: ++ def ConnectBLE(self, discriminator: int, setupPinCode: int, nodeid: int, isShortDiscriminator: bool = False) -> PyChipError: + self.CheckIsActive() + + self._commissioning_complete_future = concurrent.futures.Future() +@@ -452,7 +452,7 @@ class ChipDeviceControllerBase(): + self._enablePairingCompeleteCallback(True) + self._ChipStack.Call( + lambda: self._dmLib.pychip_DeviceController_ConnectBLE( +- self.devCtrl, discriminator, setupPinCode, nodeid) ++ self.devCtrl, discriminator, isShortDiscriminator, setupPinCode, nodeid) + ).raise_on_error() + + # TODO: Change return None. Only returning on success is not useful. +@@ -1459,7 +1459,7 @@ class ChipDeviceControllerBase(): + self._dmLib.pychip_DeviceController_DeleteDeviceController.restype = PyChipError + + self._dmLib.pychip_DeviceController_ConnectBLE.argtypes = [ +- c_void_p, c_uint16, c_uint32, c_uint64] ++ c_void_p, c_uint16, c_bool, c_uint32, c_uint64] + self._dmLib.pychip_DeviceController_ConnectBLE.restype = PyChipError + + self._dmLib.pychip_DeviceController_SetThreadOperationalDataset.argtypes = [ +@@ -1738,17 +1738,17 @@ class ChipDeviceController(ChipDeviceControllerBase): + finally: + self._commissioning_complete_future = None + +- def CommissionThread(self, discriminator, setupPinCode, nodeId, threadOperationalDataset: bytes) -> PyChipError: ++ def CommissionThread(self, discriminator, setupPinCode, nodeId, threadOperationalDataset: bytes, isShortDiscriminator: bool = False) -> PyChipError: + ''' Commissions a Thread device over BLE + ''' + self.SetThreadOperationalDataset(threadOperationalDataset) +- return self.ConnectBLE(discriminator, setupPinCode, nodeId) ++ return self.ConnectBLE(discriminator, setupPinCode, nodeId, isShortDiscriminator) + +- def CommissionWiFi(self, discriminator, setupPinCode, nodeId, ssid: str, credentials: str) -> PyChipError: ++ def CommissionWiFi(self, discriminator, setupPinCode, nodeId, ssid: str, credentials: str, isShortDiscriminator: bool = False) -> PyChipError: + ''' Commissions a Wi-Fi device over BLE. + ''' + self.SetWiFiCredentials(ssid, credentials) +- return self.ConnectBLE(discriminator, setupPinCode, nodeId) ++ return self.ConnectBLE(discriminator, setupPinCode, nodeId, isShortDiscriminator) + + def SetWiFiCredentials(self, ssid: str, credentials: str): + ''' Set the Wi-Fi credentials to set during commissioning.''' +diff --git a/src/lib/support/SetupDiscriminator.h b/src/lib/support/SetupDiscriminator.h +index 5c1fabae71..2083cdc7cb 100644 +--- a/src/lib/support/SetupDiscriminator.h ++++ b/src/lib/support/SetupDiscriminator.h +@@ -23,16 +23,16 @@ + + #pragma once + +-#include +- + #include + ++#include ++ + namespace chip { + + class SetupDiscriminator + { + public: +- constexpr SetupDiscriminator() : mDiscriminator(0), mIsShortDiscriminator(0) {} ++ constexpr SetupDiscriminator() : mDiscriminator(0), mIsShortDiscriminator(false) {} + + // See section 5.1.2. QR Code in the Matter specification + static constexpr int kLongBits = 12; +@@ -104,8 +104,8 @@ private: + // discriminator). + static_assert(kLongBits == 12, "Unexpected field length"); + static_assert(kShortBits <= kLongBits, "Unexpected field length"); +- uint16_t mDiscriminator : 12; +- uint16_t mIsShortDiscriminator : 1; ++ uint16_t mDiscriminator; ++ bool mIsShortDiscriminator; + }; + + } // namespace chip +diff --git a/src/protocols/secure_channel/RendezvousParameters.h b/src/protocols/secure_channel/RendezvousParameters.h +index e5e366d3b3..0e8b793dd0 100644 +--- a/src/protocols/secure_channel/RendezvousParameters.h ++++ b/src/protocols/secure_channel/RendezvousParameters.h +@@ -17,12 +17,15 @@ + + #pragma once + ++#include ++ + #include + #include + #if CONFIG_NETWORK_LAYER_BLE + #include + #endif // CONFIG_NETWORK_LAYER_BLE + ++#include + #include + #include + #include +@@ -58,11 +61,55 @@ public: + + // Discriminators in RendezvousParameters are always long (12-bit) + // discriminators. +- bool HasDiscriminator() const { return mDiscriminator <= kMaxRendezvousDiscriminatorValue; } +- uint16_t GetDiscriminator() const { return mDiscriminator; } ++ bool HasDiscriminator() const { return mSetupDiscriminator.has_value(); } ++ ++ // Obtains the long version of the discriminator, or 0 if short. ++ // WARNING: This is lossy and a bad idea to use. The correct method to use ++ // is GetSetupDiscriminator(). This method exists for public ++ // API backwards compatibility. ++ uint16_t GetDiscriminator() const ++ { ++ if (!mSetupDiscriminator.has_value()) ++ { ++ ChipLogError(Discovery, ++ "Get RendezvousParameters::GetDiscriminator() called without discriminator in params (inconsistent). " ++ "Using value 0 to avoid crash! Ensure discriminator is set!"); ++ return 0; ++ } ++ ++ if (mSetupDiscriminator.value().IsShortDiscriminator()) ++ { ++ ChipLogError(Discovery, ++ "Get RendezvousParameters::GetDiscriminator() called with SHORT discriminator (inconsistent). Using value " ++ "0 to avoid crash! Call GetSetupDiscriminator() to avoid loss."); ++ return 0; ++ } ++ ++ return mSetupDiscriminator.value().GetLongValue(); ++ } ++ ++ std::optional GetSetupDiscriminator() const ++ { ++ if (!mSetupDiscriminator.has_value()) ++ { ++ ChipLogError( ++ Discovery, ++ "Get RendezvousParameters::GetSetupDiscriminator() called without discriminator in params (inconsistent)."); ++ } ++ return mSetupDiscriminator; ++ } ++ ++ RendezvousParameters & SetSetupDiscriminator(SetupDiscriminator discriminator) ++ { ++ mSetupDiscriminator = discriminator; ++ return *this; ++ } ++ + RendezvousParameters & SetDiscriminator(uint16_t discriminator) + { +- mDiscriminator = discriminator; ++ SetupDiscriminator tempDiscriminator; ++ tempDiscriminator.SetLongValue(discriminator); ++ mSetupDiscriminator = tempDiscriminator; + return *this; + } + +@@ -127,9 +174,9 @@ public: + } + + private: +- Transport::PeerAddress mPeerAddress; ///< the peer node address +- uint32_t mSetupPINCode = 0; ///< the target peripheral setup PIN Code +- uint16_t mDiscriminator = UINT16_MAX; ///< the target peripheral discriminator ++ Transport::PeerAddress mPeerAddress; ///< the peer node address ++ uint32_t mSetupPINCode = 0; ///< the target peripheral setup PIN Code ++ std::optional mSetupDiscriminator; + + Spake2pVerifier mPASEVerifier; + bool mHasPASEVerifier = false; +diff --git a/src/python_testing/matter_testing_support.py b/src/python_testing/matter_testing_support.py +index aee09dd1b9..f38c116424 100644 +--- a/src/python_testing/matter_testing_support.py ++++ b/src/python_testing/matter_testing_support.py +@@ -1593,14 +1593,16 @@ class CommissionDeviceTest(MatterBaseTest): + info.passcode, + conf.dut_node_ids[i], + conf.wifi_ssid, +- conf.wifi_passphrase ++ conf.wifi_passphrase, ++ isShortDiscriminator=(info.filter_type == DiscoveryFilterType.SHORT_DISCRIMINATOR) + ) + elif conf.commissioning_method == "ble-thread": + return dev_ctrl.CommissionThread( + info.filter_value, + info.passcode, + conf.dut_node_ids[i], +- conf.thread_operational_dataset ++ conf.thread_operational_dataset, ++ isShortDiscriminator=(info.filter_type == DiscoveryFilterType.SHORT_DISCRIMINATOR) + ) + elif conf.commissioning_method == "on-network-ip": + logging.warning("==== USING A DIRECT IP COMMISSIONING METHOD NOT SUPPORTED IN THE LONG TERM ====") +diff --git a/src/setup_payload/SetupPayload.h b/src/setup_payload/SetupPayload.h +index 0bb2169834..1fc50f1508 100644 +--- a/src/setup_payload/SetupPayload.h ++++ b/src/setup_payload/SetupPayload.h +@@ -125,7 +125,7 @@ struct PayloadContents + // payload parsed from a QR code would always have a value for + // rendezvousInformation. + Optional rendezvousInformation; +- SetupDiscriminator discriminator; ++ SetupDiscriminator discriminator{}; + uint32_t setUpPINCode = 0; + + bool isValidQRCodePayload() const; +diff --git a/src/setup_payload/tests/TestManualCode.cpp b/src/setup_payload/tests/TestManualCode.cpp +index cfe7c59c06..37ee76b8af 100644 +--- a/src/setup_payload/tests/TestManualCode.cpp ++++ b/src/setup_payload/tests/TestManualCode.cpp +@@ -25,6 +25,7 @@ + #include + #include + ++#include + #include + #include + #include +@@ -402,8 +403,9 @@ void TestLongCodeReadWrite(nlTestSuite * inSuite, void * context) + } + + void assertEmptyPayloadWithError(nlTestSuite * inSuite, CHIP_ERROR actualError, CHIP_ERROR expectedError, +- const SetupPayload & payload) ++ const SetupPayload & payload, int line) + { ++ ChipLogProgress(Test, "Current check line: %d", line); + NL_TEST_ASSERT(inSuite, actualError == expectedError); + NL_TEST_ASSERT(inSuite, + payload.setUpPINCode == 0 && payload.discriminator.GetLongValue() == 0 && payload.productID == 0 && +@@ -419,46 +421,46 @@ void TestPayloadParser_InvalidEntry(nlTestSuite * inSuite, void * inContext) + decimalString = ""; + decimalString += Verhoeff10::ComputeCheckChar(decimalString.c_str()); + assertEmptyPayloadWithError(inSuite, ManualSetupPayloadParser(decimalString).populatePayload(payload), +- CHIP_ERROR_INVALID_STRING_LENGTH, payload); ++ CHIP_ERROR_INVALID_STRING_LENGTH, payload, __LINE__); + + // Invalid character + decimalString = "24184.2196"; + decimalString += Verhoeff10::ComputeCheckChar(decimalString.c_str()); + assertEmptyPayloadWithError(inSuite, ManualSetupPayloadParser(decimalString).populatePayload(payload), +- CHIP_ERROR_INVALID_INTEGER_VALUE, payload); ++ CHIP_ERROR_INVALID_INTEGER_VALUE, payload, __LINE__); + + // too short + decimalString = "2456"; + decimalString += Verhoeff10::ComputeCheckChar(decimalString.c_str()); + assertEmptyPayloadWithError(inSuite, ManualSetupPayloadParser(decimalString).populatePayload(payload), +- CHIP_ERROR_INVALID_STRING_LENGTH, payload); ++ CHIP_ERROR_INVALID_STRING_LENGTH, payload, __LINE__); + + // too long for long code + decimalString = "123456789123456785671"; + decimalString += Verhoeff10::ComputeCheckChar(decimalString.c_str()); + assertEmptyPayloadWithError(inSuite, ManualSetupPayloadParser(decimalString).populatePayload(payload), +- CHIP_ERROR_INVALID_STRING_LENGTH, payload); ++ CHIP_ERROR_INVALID_STRING_LENGTH, payload, __LINE__); + + // too long for short code + decimalString = "12749875380"; + decimalString += Verhoeff10::ComputeCheckChar(decimalString.c_str()); + assertEmptyPayloadWithError(inSuite, ManualSetupPayloadParser(decimalString).populatePayload(payload), +- CHIP_ERROR_INVALID_STRING_LENGTH, payload); ++ CHIP_ERROR_INVALID_STRING_LENGTH, payload, __LINE__); + + // bit to indicate short code but long code length + decimalString = "23456789123456785610"; + decimalString += Verhoeff10::ComputeCheckChar(decimalString.c_str()); + assertEmptyPayloadWithError(inSuite, ManualSetupPayloadParser(decimalString).populatePayload(payload), +- CHIP_ERROR_INVALID_STRING_LENGTH, payload); ++ CHIP_ERROR_INVALID_STRING_LENGTH, payload, __LINE__); + // no pin code (= 0) + decimalString = "2327680000"; + decimalString += Verhoeff10::ComputeCheckChar(decimalString.c_str()); + assertEmptyPayloadWithError(inSuite, ManualSetupPayloadParser(decimalString).populatePayload(payload), +- CHIP_ERROR_INVALID_ARGUMENT, payload); ++ CHIP_ERROR_INVALID_ARGUMENT, payload, __LINE__); + // wrong check digit + decimalString = "02684354589"; + assertEmptyPayloadWithError(inSuite, ManualSetupPayloadParser(decimalString).populatePayload(payload), +- CHIP_ERROR_INTEGRITY_CHECK_FAILED, payload); ++ CHIP_ERROR_INTEGRITY_CHECK_FAILED, payload, __LINE__); + } + + void TestCheckDecimalStringValidity(nlTestSuite * inSuite, void * inContext) +-- +2.45.2 +