Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Commissioning: Fix fabric check stage and add test #28531

Merged
merged 2 commits into from
Aug 16, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 4 additions & 4 deletions examples/platform/linux/CommissionerMain.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -248,7 +248,7 @@ class PairingCommand : public Controller::DevicePairingDelegate
void OnCommissioningStatusUpdate(PeerId peerId, CommissioningStage stageCompleted, CHIP_ERROR error) override;

void OnReadCommissioningInfo(const ReadCommissioningInfo & info) override;
void OnFabricCheck(const MatchingFabricInfo & info) override;
void OnFabricCheck(NodeId matchingNodeId) override;

private:
#if CHIP_DEVICE_CONFIG_APP_PLATFORM_ENABLED
Expand Down Expand Up @@ -347,11 +347,11 @@ void PairingCommand::OnReadCommissioningInfo(const ReadCommissioningInfo & info)
info.basic.productId);
}

void PairingCommand::OnFabricCheck(const MatchingFabricInfo & info)
void PairingCommand::OnFabricCheck(NodeId matchingNodeId)
{
if (info.nodeId != kUndefinedNodeId)
if (matchingNodeId != kUndefinedNodeId)
{
ChipLogProgress(AppServer, "ALREADY ON FABRIC WITH nodeId=0x" ChipLogFormatX64, ChipLogValueX64(info.nodeId));
ChipLogProgress(AppServer, "ALREADY ON FABRIC WITH nodeId=0x" ChipLogFormatX64, ChipLogValueX64(matchingNodeId));
// wait until attestation verification before cancelling so we can validate vid/pid
}
}
Expand Down
4 changes: 2 additions & 2 deletions src/controller/CHIPDeviceController.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2154,7 +2154,7 @@ void DeviceCommissioner::ParseFabrics()

if (mPairingDelegate != nullptr)
{
mPairingDelegate->OnFabricCheck(info);
mPairingDelegate->OnFabricCheck(info.nodeId);
}

CommissioningDelegate::CommissioningReport report;
Expand Down Expand Up @@ -2403,7 +2403,7 @@ void DeviceCommissioner::PerformCommissioningStep(DeviceProxy * proxy, Commissio
break;
case CommissioningStage::kCheckForMatchingFabric: {
// Read the current fabrics
if (params.GetCheckForMatchingFabric())
if (!params.GetCheckForMatchingFabric())
{
// We don't actually want to do this step, so just bypass it
ChipLogProgress(Controller, "kCheckForMatchingFabric step called without parameter set, skipping");
Expand Down
2 changes: 1 addition & 1 deletion src/controller/DevicePairingDelegate.h
Original file line number Diff line number Diff line change
Expand Up @@ -87,7 +87,7 @@ class DLL_EXPORT DevicePairingDelegate
* @brief
* Called when MatchingFabricInfo returned from target
*/
virtual void OnFabricCheck(const MatchingFabricInfo & info) {}
virtual void OnFabricCheck(NodeId matchingNodeId) {}

/**
* @brief
Expand Down
16 changes: 16 additions & 0 deletions src/controller/python/ChipDeviceController-ScriptBinding.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -144,6 +144,7 @@ PyChipError pychip_DeviceController_SetTimeZone(int32_t offset, uint64_t validAt
PyChipError pychip_DeviceController_SetDSTOffset(int32_t offset, uint64_t validStarting, uint64_t validUntil);
PyChipError pychip_DeviceController_SetDefaultNtp(const char * defaultNTP);
PyChipError pychip_DeviceController_SetTrustedTimeSource(chip::NodeId nodeId, chip::EndpointId endpoint);
PyChipError pychip_DeviceController_SetCheckMatchingFabric(bool check);
PyChipError pychip_DeviceController_ResetCommissioningParameters();
PyChipError pychip_DeviceController_CloseSession(chip::Controller::DeviceCommissioner * devCtrl, chip::NodeId nodeid);
PyChipError pychip_DeviceController_EstablishPASESessionIP(chip::Controller::DeviceCommissioner * devCtrl, const char * peerAddrStr,
Expand Down Expand Up @@ -189,6 +190,8 @@ PyChipError pychip_ScriptDevicePairingDelegate_SetCommissioningCompleteCallback(
PyChipError pychip_ScriptDevicePairingDelegate_SetCommissioningStatusUpdateCallback(
chip::Controller::DeviceCommissioner * devCtrl,
chip::Controller::DevicePairingDelegate_OnCommissioningStatusUpdateFunct callback);
PyChipError
pychip_ScriptDevicePairingDelegate_SetFabricCheckCallback(chip::Controller::DevicePairingDelegate_OnFabricCheckFunct callback);
PyChipError pychip_ScriptDevicePairingDelegate_SetOpenWindowCompleteCallback(
chip::Controller::DeviceCommissioner * devCtrl, chip::Controller::DevicePairingDelegate_OnWindowOpenCompleteFunct callback);

Expand Down Expand Up @@ -541,6 +544,12 @@ PyChipError pychip_DeviceController_SetTrustedTimeSource(chip::NodeId nodeId, ch
return ToPyChipError(CHIP_NO_ERROR);
}

PyChipError pychip_DeviceController_SetCheckMatchingFabric(bool check)
{
sCommissioningParameters.SetCheckForMatchingFabric(check);
return ToPyChipError(CHIP_NO_ERROR);
}

PyChipError pychip_DeviceController_ResetCommissioningParameters()
{
sCommissioningParameters = CommissioningParameters();
Expand Down Expand Up @@ -693,6 +702,13 @@ PyChipError pychip_ScriptDevicePairingDelegate_SetCommissioningStatusUpdateCallb
return ToPyChipError(CHIP_NO_ERROR);
}

PyChipError
pychip_ScriptDevicePairingDelegate_SetFabricCheckCallback(chip::Controller::DevicePairingDelegate_OnFabricCheckFunct callback)
{
sPairingDelegate.SetFabricCheckCallback(callback);
return ToPyChipError(CHIP_NO_ERROR);
}

const char * pychip_Stack_ErrorToString(ChipError::StorageType err)
{
return chip::ErrorStr(CHIP_ERROR(err));
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -60,6 +60,10 @@ void ScriptDevicePairingDelegate::SetCommissioningFailureCallback(DevicePairingD
{
mOnCommissioningFailureCallback = callback;
}
void ScriptDevicePairingDelegate::SetFabricCheckCallback(DevicePairingDelegate_OnFabricCheckFunct callback)
{
mOnFabricCheckCallback = callback;
}

void ScriptDevicePairingDelegate::SetCommissioningStatusUpdateCallback(
DevicePairingDelegate_OnCommissioningStatusUpdateFunct callback)
Expand Down Expand Up @@ -150,6 +154,23 @@ void ScriptDevicePairingDelegate::OnOpenCommissioningWindow(NodeId deviceId, CHI
mWindowOpener = nullptr;
}
}

void ScriptDevicePairingDelegate::OnFabricCheck(NodeId matchingNodeId)
{
if (matchingNodeId == kUndefinedNodeId)
{
ChipLogProgress(Zcl, "No matching fabric found");
}
else
{
ChipLogProgress(Zcl, "Matching fabric found");
}
if (mOnFabricCheckCallback != nullptr)
{
mOnFabricCheckCallback(matchingNodeId);
}
}

Callback::Callback<Controller::OnOpenCommissioningWindow> *
ScriptDevicePairingDelegate::GetOpenWindowCallback(Controller::CommissioningWindowOpener * context)
{
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,7 @@ typedef void (*DevicePairingDelegate_OnCommissioningFailureFunct)(
typedef void (*DevicePairingDelegate_OnCommissioningStatusUpdateFunct)(PeerId peerId,
chip::Controller::CommissioningStage stageCompleted,
CHIP_ERROR err);
typedef void (*DevicePairingDelegate_OnFabricCheckFunct)(NodeId nodeId);
}

class ScriptDevicePairingDelegate final : public Controller::DevicePairingDelegate
Expand All @@ -59,13 +60,15 @@ class ScriptDevicePairingDelegate final : public Controller::DevicePairingDelega
void SetCommissioningSuccessCallback(DevicePairingDelegate_OnCommissioningSuccessFunct callback);
void SetCommissioningFailureCallback(DevicePairingDelegate_OnCommissioningFailureFunct callback);
void SetCommissioningWindowOpenCallback(DevicePairingDelegate_OnWindowOpenCompleteFunct callback);
void SetFabricCheckCallback(DevicePairingDelegate_OnFabricCheckFunct callback);
void OnStatusUpdate(Controller::DevicePairingDelegate::Status status) override;
void OnPairingComplete(CHIP_ERROR error) override;
void OnCommissioningComplete(NodeId nodeId, CHIP_ERROR err) override;
void OnCommissioningSuccess(PeerId peerId) override;
void OnCommissioningFailure(PeerId peerId, CHIP_ERROR error, CommissioningStage stageFailed,
Optional<Credentials::AttestationVerificationResult> additionalErrorInfo) override;
void OnCommissioningStatusUpdate(PeerId peerId, CommissioningStage stageCompleted, CHIP_ERROR error) override;
void OnFabricCheck(NodeId matchingNodeId) override;
Callback::Callback<Controller::OnOpenCommissioningWindow> *
GetOpenWindowCallback(Controller::CommissioningWindowOpener * context);
void OnOpenCommissioningWindow(NodeId deviceId, CHIP_ERROR status, SetupPayload payload);
Expand All @@ -78,6 +81,7 @@ class ScriptDevicePairingDelegate final : public Controller::DevicePairingDelega
DevicePairingDelegate_OnCommissioningSuccessFunct mOnCommissioningSuccessCallback = nullptr;
DevicePairingDelegate_OnCommissioningFailureFunct mOnCommissioningFailureCallback = nullptr;
DevicePairingDelegate_OnCommissioningStatusUpdateFunct mOnCommissioningStatusUpdateCallback = nullptr;
DevicePairingDelegate_OnFabricCheckFunct mOnFabricCheckCallback = nullptr;
Callback::Callback<Controller::OnOpenCommissioningWindow> mOpenWindowCallback;
Controller::CommissioningWindowOpener * mWindowOpener = nullptr;
bool expectingPairingComplete = false;
Expand Down
25 changes: 25 additions & 0 deletions src/controller/python/chip/ChipDeviceCtrl.py
Original file line number Diff line number Diff line change
Expand Up @@ -70,6 +70,8 @@
None, c_uint64, c_uint32, c_char_p, c_char_p, PyChipError)
_DevicePairingDelegate_OnCommissioningStatusUpdateFunct = CFUNCTYPE(
None, c_uint64, c_uint8, PyChipError)
_DevicePairingDelegate_OnFabricCheckFunct = CFUNCTYPE(
None, c_uint64)
# void (*)(Device *, CHIP_ERROR).
#
# CHIP_ERROR is actually signed, so using c_uint32 is weird, but everything
Expand Down Expand Up @@ -248,6 +250,7 @@ def __init__(self, name: str = ''):

self.devCtrl = devCtrl
self.name = name
self.fabricCheckNodeId = -1

self._Cluster = ChipClusters(builtins.chipStack)
self._Cluster.InitLib(self._dmLib)
Expand All @@ -267,6 +270,9 @@ def HandleCommissioningComplete(nodeid, err):
self._ChipStack.commissioningCompleteEvent.set()
self._ChipStack.completeEvent.set()

def HandleFabricCheck(nodeId):
self.fabricCheckNodeId = nodeId

def HandleOpenWindowComplete(nodeid: int, setupPinCode: int, setupManualCode: str,
setupQRCode: str, err: PyChipError) -> None:
if err.is_success:
Expand Down Expand Up @@ -319,6 +325,9 @@ def HandlePASEEstablishmentComplete(err: PyChipError):
self._dmLib.pychip_ScriptDevicePairingDelegate_SetCommissioningCompleteCallback(
self.devCtrl, self.cbHandleCommissioningCompleteFunct)

self.cbHandleFabricCheckFunct = _DevicePairingDelegate_OnFabricCheckFunct(HandleFabricCheck)
self._dmLib.pychip_ScriptDevicePairingDelegate_SetFabricCheckCallback(self.cbHandleFabricCheckFunct)

self.cbHandleOpenWindowCompleteFunct = _DevicePairingDelegate_OnOpenWindowCompleteFunct(
HandleOpenWindowComplete)
self._dmLib.pychip_ScriptDevicePairingDelegate_SetOpenWindowCompleteCallback(
Expand Down Expand Up @@ -1348,6 +1357,9 @@ def _InitLib(self):
self._dmLib.pychip_DeviceController_SetTrustedTimeSource.restype = PyChipError
self._dmLib.pychip_DeviceController_SetTrustedTimeSource.argtypes = [c_uint64, c_uint16]

self._dmLib.pychip_DeviceController_SetCheckMatchingFabric.restype = PyChipError
self._dmLib.pychip_DeviceController_SetCheckMatchingFabric.argtypes = [c_bool]

self._dmLib.pychip_DeviceController_ResetCommissioningParameters.restype = PyChipError
self._dmLib.pychip_DeviceController_ResetCommissioningParameters.argtypes = []

Expand Down Expand Up @@ -1441,6 +1453,10 @@ def _InitLib(self):
c_void_p, _DevicePairingDelegate_OnCommissioningStatusUpdateFunct]
self._dmLib.pychip_ScriptDevicePairingDelegate_SetCommissioningStatusUpdateCallback.restype = PyChipError

self._dmLib.pychip_ScriptDevicePairingDelegate_SetFabricCheckCallback.argtypes = [
_DevicePairingDelegate_OnFabricCheckFunct]
self._dmLib.pychip_ScriptDevicePairingDelegate_SetFabricCheckCallback.restype = PyChipError

self._dmLib.pychip_GetConnectedDeviceByNodeId.argtypes = [
c_void_p, c_uint64, _DeviceAvailableFunct]
self._dmLib.pychip_GetConnectedDeviceByNodeId.restype = PyChipError
Expand Down Expand Up @@ -1662,6 +1678,15 @@ def SetTrustedTimeSource(self, nodeId: int, endpoint: int):
lambda: self._dmLib.pychip_DeviceController_SetTrustedTimeSource(nodeId, endpoint)
).raise_on_error()

def SetCheckMatchingFabric(self, check: bool):
self.CheckIsActive()
self._ChipStack.Call(
lambda: self._dmLib.pychip_DeviceController_SetCheckMatchingFabric(check)
).raise_on_error()

def GetFabricCheckResult(self) -> int:
return self.fabricCheckNodeId

def CommissionOnNetwork(self, nodeId: int, setupPinCode: int,
filterType: DiscoveryFilterType = DiscoveryFilterType.NONE, filter: typing.Any = None, discoveryTimeoutMsec: int = 30000) -> PyChipError:
'''
Expand Down
22 changes: 22 additions & 0 deletions src/python_testing/TestCommissioningTimeSync.py
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@
# We don't have a good pipe between the c++ enums in CommissioningDelegate and python
# so this is hardcoded.
# I realize this is dodgy, not sure how to cross the enum from c++ to python cleanly
kCheckForMatchingFabric = 3
kConfigureUTCTime = 6
kConfigureTimeZone = 7
kConfigureDSTOffset = 8
Expand Down Expand Up @@ -208,6 +209,27 @@ async def test_CommissioningPreSetValues(self):
asserts.assert_false(self.commissioner.CheckStageSuccessful(
kConfigureTrustedTimeSource), 'kConfigureTrustedTimeSource incorrectly set')

@async_test_body
async def test_FabricCheckStage(self):
await self.create_commissioner()

# This was moved into a different stage when the time sync stuff was added
asserts.assert_equal(self.commissioner.GetFabricCheckResult(), -1, "Fabric check result is already set")
self.commissioner.SetCheckMatchingFabric(True)
await self.commission_and_base_checks()
asserts.assert_true(self.commissioner.CheckStageSuccessful(
kCheckForMatchingFabric), "Did not run check for matching fabric stage")
asserts.assert_equal(self.commissioner.GetFabricCheckResult(), 0, "Fabric check result did not get set by pairing delegate")

# Let's try it again with no check
await self.create_commissioner()
asserts.assert_equal(self.commissioner.GetFabricCheckResult(), -1, "Fabric check result is already set")
self.commissioner.SetCheckMatchingFabric(False)
await self.commission_and_base_checks()
asserts.assert_false(self.commissioner.CheckStageSuccessful(
kCheckForMatchingFabric), "Incorrectly ran check for matching fabric stage")
asserts.assert_equal(self.commissioner.GetFabricCheckResult(), -1, "Fabric check result incorrectly set")


# TODO(cecille): Test - Add hooks to change the time zone response to indicate no DST is needed
# TODO(cecille): Test - Set commissioningParameters TimeZone and DST list size to > node list size to ensure they get truncated
Expand Down