Skip to content

Commit e954be2

Browse files
committed
Implemented the JCM mDNS advertisement and Open Commissioning Window
1 parent d761e1b commit e954be2

36 files changed

+587
-48
lines changed

docs/guides/joint_fabric_guide.md

Lines changed: 17 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2,8 +2,11 @@
22

33
- [Joint Fabric Guide](#joint-fabric-guide)
44
- [Joint Fabric Example Applications](#joint-fabric-example-applications)
5-
- [Bootstrap Joint Fabric Demo on Linux](#bootstrap-joint-fabric-demo-on-linux)
6-
- [Run Joint Fabric Demo](#run-joint-fabric-demo)
5+
- [Building the Example Application](#building-the-example-application)
6+
- [Bootstrap Joint Fabric Demo on Linux](#bootstrap-joint-fabric-demo-on-linux)
7+
- [Initialize Ecosystem A (Vendor ID = 0xFFF1)](#initialize-ecosystem-a-vendor-id--0xfff1)
8+
- [Initialize Ecosystem B (Vendor ID = 0xFFF2)](#initialize-ecosystem-b-vendor-id--0xfff2)
9+
- [Run Joint Fabric Demo](#run-joint-fabric-demo)
710

811
## Joint Fabric Example Applications
912

@@ -250,4 +253,16 @@ jf-admin-app has been installed:
250253
A `Subjects` field equal to `18446744065119551489` (`FFFFFFFDFFFF0001` in hex)
251254
should be found.
252255

256+
- Open Joint Commissioning Window on JF Admin App of Ecosystem B
257+
258+
```
259+
>>> pairing open-joint-commissioning-window 1 400 1000 1261
260+
```
261+
262+
Check for the following logs on the jf-admin-app side:
263+
264+
```
265+
>>> [DIS] Advertise commission parameter vendorID=65521 productID=32769 discriminator=1261/04 cm=2 cp=0 jf=14
266+
```
267+
253268
## Run Joint Fabric Demo

examples/chip-tool/BUILD.gn

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -91,6 +91,8 @@ static_library("chip-tool-utils") {
9191
"commands/icd/ICDCommand.h",
9292
"commands/pairing/OpenCommissioningWindowCommand.cpp",
9393
"commands/pairing/OpenCommissioningWindowCommand.h",
94+
"commands/pairing/OpenJointCommissioningWindowCommand.cpp",
95+
"commands/pairing/OpenJointCommissioningWindowCommand.h",
9496
"commands/pairing/PairingCommand.cpp",
9597
"commands/pairing/ToTLVCert.cpp",
9698
"commands/payload/AdditionalDataParseCommand.cpp",

examples/chip-tool/commands/pairing/Commands.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,7 @@
2323
#include "commands/pairing/GetCommissionerRootCertificateCommand.h"
2424
#include "commands/pairing/IssueNOCChainCommand.h"
2525
#include "commands/pairing/OpenCommissioningWindowCommand.h"
26+
#include "commands/pairing/OpenJointCommissioningWindowCommand.h"
2627
#include "commands/pairing/PairingCommand.h"
2728

2829
#include <app/server/Dnssd.h>
@@ -272,6 +273,7 @@ void registerCommandsPairing(Commands & commands, CredentialIssuerCommands * cre
272273
// make_unique<CommissionedListCommand>(),
273274
make_unique<StartUdcServerCommand>(credsIssuerConfig),
274275
make_unique<OpenCommissioningWindowCommand>(credsIssuerConfig),
276+
make_unique<OpenJointCommissioningWindowCommand>(credsIssuerConfig),
275277
make_unique<GetCommissionerNodeIdCommand>(credsIssuerConfig),
276278
make_unique<GetCommissionerRootCertificateCommand>(credsIssuerConfig),
277279
make_unique<IssueNOCChainCommand>(credsIssuerConfig),
Lines changed: 48 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,48 @@
1+
/*
2+
* Copyright (c) 2025 Project CHIP Authors
3+
* All rights reserved.
4+
*
5+
* Licensed under the Apache License, Version 2.0 (the "License");
6+
* you may not use this file except in compliance with the License.
7+
* You may obtain a copy of the License at
8+
*
9+
* http://www.apache.org/licenses/LICENSE-2.0
10+
*
11+
* Unless required by applicable law or agreed to in writing, software
12+
* distributed under the License is distributed on an "AS IS" BASIS,
13+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14+
* See the License for the specific language governing permissions and
15+
* limitations under the License.
16+
*
17+
*/
18+
19+
#include "OpenJointCommissioningWindowCommand.h"
20+
21+
#include <system/SystemClock.h>
22+
23+
using namespace ::chip;
24+
25+
CHIP_ERROR OpenJointCommissioningWindowCommand::RunCommand()
26+
{
27+
mWindowOpener = Platform::MakeUnique<Controller::CommissioningWindowOpener>(&CurrentCommissioner());
28+
29+
SetupPayload ignored;
30+
return mWindowOpener->OpenCommissioningWindow(Controller::CommissioningWindowPasscodeParams()
31+
.SetNodeId(mNodeId)
32+
.SetTimeout(mCommissioningWindowTimeout)
33+
.SetIteration(mIteration)
34+
.SetDiscriminator(mDiscriminator)
35+
.SetReadVIDPIDAttributes(true)
36+
.SetCallback(&mOnOpenCommissioningWindowCallback),
37+
ignored, true);
38+
}
39+
40+
void OpenJointCommissioningWindowCommand::OnOpenCommissioningWindowResponse(void * context, NodeId remoteId, CHIP_ERROR err,
41+
SetupPayload payload)
42+
{
43+
LogErrorOnFailure(err);
44+
45+
OpenJointCommissioningWindowCommand * command = reinterpret_cast<OpenJointCommissioningWindowCommand *>(context);
46+
VerifyOrReturn(command != nullptr, ChipLogError(chipTool, "OnOpenJointCommissioningWindowCommand: context is null"));
47+
command->SetCommandExitStatus(err);
48+
}
Lines changed: 61 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,61 @@
1+
/*
2+
* Copyright (c) 2025 Project CHIP Authors
3+
* All rights reserved.
4+
*
5+
* Licensed under the Apache License, Version 2.0 (the "License");
6+
* you may not use this file except in compliance with the License.
7+
* You may obtain a copy of the License at
8+
*
9+
* http://www.apache.org/licenses/LICENSE-2.0
10+
*
11+
* Unless required by applicable law or agreed to in writing, software
12+
* distributed under the License is distributed on an "AS IS" BASIS,
13+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14+
* See the License for the specific language governing permissions and
15+
* limitations under the License.
16+
*
17+
*/
18+
19+
#pragma once
20+
21+
#include "../common/CHIPCommand.h"
22+
23+
#include <controller/CommissioningWindowOpener.h>
24+
#include <lib/support/CHIPMem.h>
25+
26+
class OpenJointCommissioningWindowCommand : public CHIPCommand
27+
{
28+
public:
29+
OpenJointCommissioningWindowCommand(CredentialIssuerCommands * credIssuerCommands) :
30+
CHIPCommand("open-joint-commissioning-window", credIssuerCommands),
31+
mOnOpenCommissioningWindowCallback(OnOpenCommissioningWindowResponse, this)
32+
{
33+
AddArgument("node-id", 0, UINT64_MAX, &mNodeId, "Node to send command to.");
34+
AddArgument("window-timeout", 0, UINT16_MAX, &mCommissioningWindowTimeout,
35+
"Time, in seconds, before the commissioning window closes.");
36+
AddArgument("iteration", chip::Crypto::kSpake2p_Min_PBKDF_Iterations, chip::Crypto::kSpake2p_Max_PBKDF_Iterations,
37+
&mIteration, "Number of PBKDF iterations to use to derive the verifier. Ignored if 'option' is 0.");
38+
AddArgument("discriminator", 0, 4095, &mDiscriminator, "Discriminator to use for advertising. Ignored if 'option' is 0.");
39+
AddArgument("timeout", 0, UINT16_MAX, &mTimeout, "Time, in seconds, before this command is considered to have timed out.");
40+
}
41+
42+
/////////// CHIPCommand Interface /////////
43+
CHIP_ERROR RunCommand() override;
44+
// We issue multiple data model operations for this command, and the default
45+
// timeout for those is 10 seconds, so default to 20 seconds.
46+
chip::System::Clock::Timeout GetWaitDuration() const override { return chip::System::Clock::Seconds16(mTimeout.ValueOr(20)); }
47+
48+
private:
49+
NodeId mNodeId;
50+
uint16_t mCommissioningWindowTimeout;
51+
uint32_t mIteration;
52+
uint16_t mDiscriminator;
53+
54+
chip::Optional<uint16_t> mTimeout;
55+
56+
chip::Platform::UniquePtr<chip::Controller::CommissioningWindowOpener> mWindowOpener;
57+
58+
static void OnOpenCommissioningWindowResponse(void * context, NodeId deviceId, CHIP_ERROR status, chip::SetupPayload payload);
59+
60+
chip::Callback::Callback<chip::Controller::OnOpenCommissioningWindow> mOnOpenCommissioningWindowCallback;
61+
};

examples/chip-tool/commands/pairing/PairingCommand.cpp

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -368,6 +368,9 @@ CHIP_ERROR PairingCommand::PairWithMdns(NodeId remoteId)
368368
filter.code = 0;
369369
filter.instanceName = mDiscoveryFilterInstanceName;
370370
break;
371+
case chip::Dnssd::DiscoveryFilterType::kJointFabricMode:
372+
// TODO
373+
break;
371374
}
372375

373376
CurrentCommissioner().RegisterDeviceDiscoveryDelegate(this);

examples/chip-tool/commands/pairing/PairingCommand.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -180,6 +180,7 @@ class PairingCommand : public CHIPCommand,
180180
break;
181181
case chip::Dnssd::DiscoveryFilterType::kCommissioningMode:
182182
case chip::Dnssd::DiscoveryFilterType::kCommissioner:
183+
case chip::Dnssd::DiscoveryFilterType::kJointFabricMode:
183184
break;
184185
case chip::Dnssd::DiscoveryFilterType::kDeviceType:
185186
AddArgument("device-type", 0, UINT16_MAX, &mDiscoveryFilterCode);

examples/fabric-admin/commands/pairing/PairingCommand.cpp

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -331,6 +331,9 @@ CHIP_ERROR PairingCommand::PairWithMdns(NodeId remoteId)
331331
filter.code = 0;
332332
filter.instanceName = mDiscoveryFilterInstanceName;
333333
break;
334+
case chip::Dnssd::DiscoveryFilterType::kJointFabricMode:
335+
// TODO
336+
break;
334337
}
335338

336339
CurrentCommissioner().RegisterDeviceDiscoveryDelegate(this);

examples/fabric-admin/commands/pairing/PairingCommand.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -158,6 +158,7 @@ class PairingCommand : public CHIPCommand,
158158
break;
159159
case chip::Dnssd::DiscoveryFilterType::kCommissioningMode:
160160
case chip::Dnssd::DiscoveryFilterType::kCommissioner:
161+
case chip::Dnssd::DiscoveryFilterType::kJointFabricMode:
161162
break;
162163
case chip::Dnssd::DiscoveryFilterType::kDeviceType:
163164
AddArgument("device-type", 0, UINT16_MAX, &mDiscoveryFilterCode);

examples/jf-admin-app/linux/JFAManager.cpp

Lines changed: 47 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -40,6 +40,13 @@ CHIP_ERROR JFAManager::Init(Server & server)
4040
return CHIP_NO_ERROR;
4141
}
4242

43+
CHIP_ERROR JFAManager::GetJointFabricMode(uint8_t & jointFabricMode)
44+
{
45+
jointFabricMode = ((IsDeviceCommissioned() ? 0 : 1) << 0) | (IsDeviceCommissioned() ? (IsDeviceJFAdmin() ? (1 << 1) : 0) : 0) |
46+
(IsDeviceCommissioned() ? (IsDeviceJFAnchor() ? (1 << 2) : 0) : 0) | (IsDeviceCommissioned() ? (1 << 3) : 0);
47+
return CHIP_NO_ERROR;
48+
}
49+
4350
CHIP_ERROR JFAManager::FinalizeCommissioning(NodeId nodeId)
4451
{
4552
if (jfFabricIndex == kUndefinedFabricId)
@@ -72,6 +79,46 @@ void JFAManager::HandleCommissioningCompleteEvent()
7279
}
7380
}
7481

82+
bool JFAManager::IsDeviceJFAdmin()
83+
{
84+
if (jfFabricIndex == kUndefinedFabricId)
85+
{
86+
return false;
87+
}
88+
89+
CATValues cats;
90+
91+
if (mServer->GetFabricTable().FetchCATs(jfFabricIndex, cats) == CHIP_NO_ERROR)
92+
{
93+
if (cats.ContainsIdentifier(kAdminCATIdentifier))
94+
{
95+
return true;
96+
}
97+
}
98+
99+
return false;
100+
}
101+
102+
bool JFAManager::IsDeviceJFAnchor()
103+
{
104+
if (jfFabricIndex == kUndefinedFabricId)
105+
{
106+
return false;
107+
}
108+
109+
CATValues cats;
110+
111+
if (mServer->GetFabricTable().FetchCATs(jfFabricIndex, cats) == CHIP_NO_ERROR)
112+
{
113+
if (cats.ContainsIdentifier(kAnchorCATIdentifier))
114+
{
115+
return true;
116+
}
117+
}
118+
119+
return false;
120+
}
121+
75122
void JFAManager::ReleaseSession()
76123
{
77124
auto optionalSessionHandle = mSessionHolder.Get();

0 commit comments

Comments
 (0)