Skip to content

Commit 2710605

Browse files
bzbarsky-applepull[bot]
authored andcommitted
Add an open-commissioning-window command to darwin-framework-tool. (#18917)
* Add an open-commissioning-window command to darwin-framework-tool. This way we can open ECM windows and know what the pairing code is. Fixes #18916 * Address review comments.
1 parent 5d1dd7b commit 2710605

File tree

4 files changed

+126
-2
lines changed

4 files changed

+126
-2
lines changed

examples/darwin-framework-tool/BUILD.gn

+2
Original file line numberDiff line numberDiff line change
@@ -46,6 +46,8 @@ executable("darwin-framework-tool") {
4646
"commands/common/CHIPCommandStorageDelegate.mm",
4747
"commands/common/CHIPToolKeypair.mm",
4848
"commands/pairing/Commands.h",
49+
"commands/pairing/OpenCommissioningWindowCommand.h",
50+
"commands/pairing/OpenCommissioningWindowCommand.mm",
4951
"commands/pairing/PairingCommandBridge.mm",
5052
"commands/pairing/PairingDelegateBridge.mm",
5153
"commands/storage/Commands.h",

examples/darwin-framework-tool/commands/pairing/Commands.h

+4-2
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@
1818

1919
#pragma once
2020

21+
#include "OpenCommissioningWindowCommand.h"
2122
#include "PairingCommandBridge.h"
2223

2324
class PairCode : public PairingCommandBridge
@@ -55,8 +56,9 @@ void registerCommandsPairing(Commands & commands)
5556
const char * clusterName = "Pairing";
5657

5758
commands_list clusterCommands = {
58-
make_unique<PairCode>(), make_unique<PairWithIPAddress>(), make_unique<PairBleWiFi>(), make_unique<PairBleThread>(),
59-
make_unique<Unpair>(),
59+
make_unique<PairCode>(), make_unique<PairWithIPAddress>(),
60+
make_unique<PairBleWiFi>(), make_unique<PairBleThread>(),
61+
make_unique<Unpair>(), make_unique<OpenCommissioningWindowCommand>(),
6062
};
6163

6264
commands.Register(clusterName, clusterCommands);
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,57 @@
1+
/*
2+
* Copyright (c) 2022 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+
#pragma once
19+
20+
#include "../common/CHIPCommandBridge.h"
21+
22+
class OpenCommissioningWindowCommand : public CHIPCommandBridge
23+
{
24+
public:
25+
OpenCommissioningWindowCommand() : CHIPCommandBridge("open-commissioning-window")
26+
{
27+
AddArgument("node-id", 0, UINT64_MAX, &mNodeId, "Node to open a commissionging window on.");
28+
AddArgument("option", 0, 1, &mCommissioningWindowOption,
29+
"1 to use Enhanced Commissioning Method.\n 0 to use Basic Commissioning Method.");
30+
AddArgument("window-timeout", 0, UINT16_MAX, &mCommissioningWindowTimeoutMs,
31+
"Time, in seconds, before the commissioning window closes.");
32+
AddArgument("iteration", chip::kSpake2p_Min_PBKDF_Iterations, chip::kSpake2p_Max_PBKDF_Iterations, &mIteration,
33+
"Number of PBKDF iterations to use to derive the verifier. Ignored if 'option' is 0.");
34+
AddArgument("discriminator", 0, 4096, &mDiscriminator, "Discriminator to use for advertising. Ignored if 'option' is 0.");
35+
AddArgument("timeout", 0, UINT16_MAX, &mTimeout, "Time, in seconds, before this command is considered to have timed out.");
36+
}
37+
38+
protected:
39+
/////////// CHIPCommandBridge Interface /////////
40+
CHIP_ERROR RunCommand() override;
41+
// We issue multiple data model operations for this command, and the default
42+
// timeout for those is 10 seconds, so default to 20 seconds.
43+
chip::System::Clock::Timeout GetWaitDuration() const override { return chip::System::Clock::Seconds16(mTimeout.ValueOr(20)); }
44+
45+
chip::NodeId mNodeId;
46+
uint8_t mCommissioningWindowOption;
47+
uint16_t mCommissioningWindowTimeoutMs;
48+
uint32_t mIteration;
49+
uint16_t mDiscriminator;
50+
51+
chip::Optional<uint16_t> mTimeout;
52+
53+
// TODO: We should not need these members if we got sane callbacks from the
54+
// framework when the commissioning window is open.
55+
dispatch_queue_t mWorkQueue;
56+
dispatch_source_t mTimer;
57+
};
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,63 @@
1+
/*
2+
* Copyright (c) 2022 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+
#import <CHIP/CHIP.h>
19+
20+
#include "OpenCommissioningWindowCommand.h"
21+
22+
CHIP_ERROR OpenCommissioningWindowCommand::RunCommand()
23+
{
24+
auto * controller = CurrentCommissioner();
25+
NSError * error;
26+
__block NSString * pairingCode;
27+
if (mCommissioningWindowOption == 0) {
28+
[controller openPairingWindow:mNodeId duration:mCommissioningWindowTimeoutMs error:&error];
29+
} else {
30+
pairingCode = [controller openPairingWindowWithPIN:mNodeId
31+
duration:mCommissioningWindowTimeoutMs
32+
discriminator:mDiscriminator
33+
setupPIN:arc4random()
34+
error:&error];
35+
}
36+
37+
if (error != nil) {
38+
SetCommandExitStatus(error);
39+
return CHIP_NO_ERROR;
40+
}
41+
42+
// TODO: Those should be async operations and we should not claim to
43+
// be done until they complete. As things stand, we have no idea
44+
// how to tell when we're done, so just set a timer for slightly
45+
// less than our command timeout to call SetCommandExitStatus.
46+
mWorkQueue = dispatch_queue_create("com.chip.open_commissioning_window", DISPATCH_QUEUE_SERIAL);
47+
mTimer = dispatch_source_create(DISPATCH_SOURCE_TYPE_TIMER, 0, 0, mWorkQueue);
48+
auto * self = this;
49+
dispatch_source_set_event_handler(mTimer, ^{
50+
dispatch_source_cancel(mTimer);
51+
mTimer = nil;
52+
mWorkQueue = nil;
53+
if (pairingCode != nil) {
54+
ChipLogProgress(chipTool, "Setup code: %s\n", [pairingCode UTF8String]);
55+
}
56+
self->SetCommandExitStatus(CHIP_NO_ERROR);
57+
});
58+
dispatch_source_set_timer(
59+
mTimer, dispatch_time(DISPATCH_TIME_NOW, (GetWaitDuration().count() - 2000) * NSEC_PER_MSEC), DISPATCH_TIME_FOREVER, 0);
60+
dispatch_resume(mTimer);
61+
62+
return CHIP_NO_ERROR;
63+
}

0 commit comments

Comments
 (0)