Skip to content

Commit

Permalink
Add an open-commissioning-window command to darwin-framework-tool. (#…
Browse files Browse the repository at this point in the history
…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.
  • Loading branch information
bzbarsky-apple authored Jun 2, 2022
1 parent d7b84a2 commit 954a920
Show file tree
Hide file tree
Showing 4 changed files with 126 additions and 2 deletions.
2 changes: 2 additions & 0 deletions examples/darwin-framework-tool/BUILD.gn
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,8 @@ executable("darwin-framework-tool") {
"commands/common/CHIPCommandStorageDelegate.mm",
"commands/common/CHIPToolKeypair.mm",
"commands/pairing/Commands.h",
"commands/pairing/OpenCommissioningWindowCommand.h",
"commands/pairing/OpenCommissioningWindowCommand.mm",
"commands/pairing/PairingCommandBridge.mm",
"commands/pairing/PairingDelegateBridge.mm",
"commands/storage/Commands.h",
Expand Down
6 changes: 4 additions & 2 deletions examples/darwin-framework-tool/commands/pairing/Commands.h
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@

#pragma once

#include "OpenCommissioningWindowCommand.h"
#include "PairingCommandBridge.h"

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

commands_list clusterCommands = {
make_unique<PairCode>(), make_unique<PairWithIPAddress>(), make_unique<PairBleWiFi>(), make_unique<PairBleThread>(),
make_unique<Unpair>(),
make_unique<PairCode>(), make_unique<PairWithIPAddress>(),
make_unique<PairBleWiFi>(), make_unique<PairBleThread>(),
make_unique<Unpair>(), make_unique<OpenCommissioningWindowCommand>(),
};

commands.Register(clusterName, clusterCommands);
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,57 @@
/*
* Copyright (c) 2022 Project CHIP Authors
* All rights reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/

#pragma once

#include "../common/CHIPCommandBridge.h"

class OpenCommissioningWindowCommand : public CHIPCommandBridge
{
public:
OpenCommissioningWindowCommand() : CHIPCommandBridge("open-commissioning-window")
{
AddArgument("node-id", 0, UINT64_MAX, &mNodeId, "Node to open a commissionging window on.");
AddArgument("option", 0, 1, &mCommissioningWindowOption,
"1 to use Enhanced Commissioning Method.\n 0 to use Basic Commissioning Method.");
AddArgument("window-timeout", 0, UINT16_MAX, &mCommissioningWindowTimeoutMs,
"Time, in seconds, before the commissioning window closes.");
AddArgument("iteration", chip::kSpake2p_Min_PBKDF_Iterations, chip::kSpake2p_Max_PBKDF_Iterations, &mIteration,
"Number of PBKDF iterations to use to derive the verifier. Ignored if 'option' is 0.");
AddArgument("discriminator", 0, 4096, &mDiscriminator, "Discriminator to use for advertising. Ignored if 'option' is 0.");
AddArgument("timeout", 0, UINT16_MAX, &mTimeout, "Time, in seconds, before this command is considered to have timed out.");
}

protected:
/////////// CHIPCommandBridge Interface /////////
CHIP_ERROR RunCommand() override;
// We issue multiple data model operations for this command, and the default
// timeout for those is 10 seconds, so default to 20 seconds.
chip::System::Clock::Timeout GetWaitDuration() const override { return chip::System::Clock::Seconds16(mTimeout.ValueOr(20)); }

chip::NodeId mNodeId;
uint8_t mCommissioningWindowOption;
uint16_t mCommissioningWindowTimeoutMs;
uint32_t mIteration;
uint16_t mDiscriminator;

chip::Optional<uint16_t> mTimeout;

// TODO: We should not need these members if we got sane callbacks from the
// framework when the commissioning window is open.
dispatch_queue_t mWorkQueue;
dispatch_source_t mTimer;
};
Original file line number Diff line number Diff line change
@@ -0,0 +1,63 @@
/*
* Copyright (c) 2022 Project CHIP Authors
* All rights reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/

#import <CHIP/CHIP.h>

#include "OpenCommissioningWindowCommand.h"

CHIP_ERROR OpenCommissioningWindowCommand::RunCommand()
{
auto * controller = CurrentCommissioner();
NSError * error;
__block NSString * pairingCode;
if (mCommissioningWindowOption == 0) {
[controller openPairingWindow:mNodeId duration:mCommissioningWindowTimeoutMs error:&error];
} else {
pairingCode = [controller openPairingWindowWithPIN:mNodeId
duration:mCommissioningWindowTimeoutMs
discriminator:mDiscriminator
setupPIN:arc4random()
error:&error];
}

if (error != nil) {
SetCommandExitStatus(error);
return CHIP_NO_ERROR;
}

// TODO: Those should be async operations and we should not claim to
// be done until they complete. As things stand, we have no idea
// how to tell when we're done, so just set a timer for slightly
// less than our command timeout to call SetCommandExitStatus.
mWorkQueue = dispatch_queue_create("com.chip.open_commissioning_window", DISPATCH_QUEUE_SERIAL);
mTimer = dispatch_source_create(DISPATCH_SOURCE_TYPE_TIMER, 0, 0, mWorkQueue);
auto * self = this;
dispatch_source_set_event_handler(mTimer, ^{
dispatch_source_cancel(mTimer);
mTimer = nil;
mWorkQueue = nil;
if (pairingCode != nil) {
ChipLogProgress(chipTool, "Setup code: %s\n", [pairingCode UTF8String]);
}
self->SetCommandExitStatus(CHIP_NO_ERROR);
});
dispatch_source_set_timer(
mTimer, dispatch_time(DISPATCH_TIME_NOW, (GetWaitDuration().count() - 2000) * NSEC_PER_MSEC), DISPATCH_TIME_FOREVER, 0);
dispatch_resume(mTimer);

return CHIP_NO_ERROR;
}

0 comments on commit 954a920

Please sign in to comment.