Skip to content

Commit

Permalink
Add Pairing Commands to chip-tool-darwin (#14662)
Browse files Browse the repository at this point in the history
  • Loading branch information
Josh V [Apple] authored Feb 4, 2022
1 parent cb8f7d8 commit 4549ca8
Show file tree
Hide file tree
Showing 15 changed files with 575 additions and 9 deletions.
2 changes: 1 addition & 1 deletion examples/chip-tool-darwin/.gn
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
# Copyright (c) 2020 Project CHIP Authors
# Copyright (c) 2022 Project CHIP Authors
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
Expand Down
32 changes: 30 additions & 2 deletions examples/chip-tool-darwin/BUILD.gn
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
# Copyright (c) 2020 Project CHIP Authors
# Copyright (c) 2022 Project CHIP Authors
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
Expand All @@ -20,14 +20,24 @@ import("${chip_root}/build/chip/tools.gni")
assert(chip_build_tools)

executable("chip-tool-darwin") {
sources = [ "main.m" ]
sources = [
"commands/common/CHIPCommandBridge.mm",
"commands/pairing/Commands.h",
"commands/pairing/PairingCommandBridge.mm",
"commands/pairing/PairingDelegateBridge.mm",
"main.mm",
]

include_dirs = [ "." ]

deps = [
"${chip_root}/examples/chip-tool:chip-tool-utils",
"${chip_root}/src/app/server",
"${chip_root}/src/darwin/Framework/CHIP",
"${chip_root}/src/lib",
"${chip_root}/src/platform",
"${chip_root}/third_party/inipp",
"${chip_root}/third_party/jsoncpp",
]

cflags = [
Expand All @@ -37,3 +47,21 @@ executable("chip-tool-darwin") {

output_dir = root_out_dir
}

action("codesign") {
script = "entitlements/codesign.py"
sources = [ "entitlements/chip-tool-darwin.entitlements" ]
public_deps = [ ":chip-tool-darwin" ]

args = [
"--target_path",
rebase_path("${root_build_dir}/chip-tool-darwin", root_build_dir),
"--entitlements_path",
rebase_path("entitlements/chip-tool-darwin.entitlements", root_build_dir),
"--log_path",
rebase_path("${root_build_dir}/codesign_log.txt", root_build_dir),
]

output_name = "codesign_log.txt"
outputs = [ "${root_build_dir}/${output_name}" ]
}
80 changes: 80 additions & 0 deletions examples/chip-tool-darwin/commands/common/CHIPCommandBridge.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,80 @@
/*
* 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
#import <CHIP/CHIPDeviceController.h>
#include <commands/common/Command.h>
#include <commands/common/CredentialIssuerCommands.h>

#pragma once

class CHIPCommandBridge : public Command
{
public:
CHIPCommandBridge(const char * commandName) : Command(commandName) {}

CHIPCommandBridge(const char * commandName, CredentialIssuerCommands * credIssuerCmds) : CHIPCommandBridge(commandName) {}

/////////// Command Interface /////////
CHIP_ERROR Run() override;

void SetCommandExitStatus(CHIP_ERROR status)
{
mCommandExitStatus = status;
ShutdownCommissioner();
StopWaiting();
}

protected:
// Will be called in a setting in which it's safe to touch the CHIP
// stack. The rules for Run() are as follows:
//
// 1) If error is returned, Run() must not call SetCommandExitStatus.
// 2) If success is returned Run() must either have called
// SetCommandExitStatus() or scheduled async work that will do that.
virtual CHIP_ERROR RunCommand() = 0;

// Get the wait duration, in seconds, before the command times out.
virtual chip::System::Clock::Timeout GetWaitDuration() const = 0;

// Shut down the command, in case any work needs to be done after the event
// loop has been stopped.
virtual void Shutdown() {}

void SetIdentity(const char * name);

// This method returns the commissioner instance to be used for running the command.
CHIPDeviceController * CurrentCommissioner();

private:
CHIP_ERROR InitializeCommissioner(std::string key, chip::FabricId fabricId);
CHIP_ERROR ShutdownCommissioner();
uint16_t CurrentCommissionerIndex();

CHIP_ERROR mCommandExitStatus = CHIP_ERROR_INTERNAL;

CHIP_ERROR StartWaiting(chip::System::Clock::Timeout seconds);
void StopWaiting();
CHIPDeviceController * mController;

#if CONFIG_USE_SEPARATE_EVENTLOOP
std::condition_variable cvWaitingForResponse;
std::mutex cvWaitingForResponseMutex;
bool mWaitingForResponse{ true };
#endif // CONFIG_USE_SEPARATE_EVENTLOOP
};
91 changes: 91 additions & 0 deletions examples/chip-tool-darwin/commands/common/CHIPCommandBridge.mm
Original file line number Diff line number Diff line change
@@ -0,0 +1,91 @@
/*
* 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.
*
*/

#include "CHIPCommandBridge.h"

#import <CHIP/CHIPDeviceController.h>
#include <core/CHIPBuildConfig.h>
#include <lib/support/CodeUtils.h>

const uint16_t kListenPort = 5541;

CHIP_ERROR CHIPCommandBridge::Run()
{
NSLog(@"Running Command");

mController = [CHIPDeviceController sharedController];
[mController setListenPort:kListenPort];
[mController startup:nil vendorId:0 nocSigner:nil];

RunCommand();
ReturnLogErrorOnFailure(StartWaiting(GetWaitDuration()));
return CHIP_NO_ERROR;
}

CHIPDeviceController * CHIPCommandBridge::CurrentCommissioner() { return mController; }

CHIP_ERROR CHIPCommandBridge::ShutdownCommissioner()
{
NSLog(@"Shutting down controller");
BOOL result = [CurrentCommissioner() shutdown];
if (!result) {
NSLog(@"Unable to shut down controller");
return CHIP_ERROR_INTERNAL;
}
return CHIP_NO_ERROR;
}

#if !CONFIG_USE_SEPARATE_EVENTLOOP
static void OnResponseTimeout(chip::System::Layer *, void * appState)
{
(reinterpret_cast<CHIPCommandBridge *>(appState))->SetCommandExitStatus(CHIP_ERROR_TIMEOUT);
}
#endif // !CONFIG_USE_SEPARATE_EVENTLOOP

CHIP_ERROR CHIPCommandBridge::StartWaiting(chip::System::Clock::Timeout duration)
{
#if CONFIG_USE_SEPARATE_EVENTLOOP
chip::DeviceLayer::PlatformMgr().StartEventLoopTask();
auto waitingUntil = std::chrono::system_clock::now() + std::chrono::duration_cast<std::chrono::seconds>(duration);
{
std::unique_lock<std::mutex> lk(cvWaitingForResponseMutex);
if (!cvWaitingForResponse.wait_until(lk, waitingUntil, [this]() { return !this->mWaitingForResponse; })) {
mCommandExitStatus = CHIP_ERROR_TIMEOUT;
}
}
LogErrorOnFailure(chip::DeviceLayer::PlatformMgr().StopEventLoopTask());
#else
ReturnLogErrorOnFailure(chip::DeviceLayer::SystemLayer().StartTimer(duration, OnResponseTimeout, this));
chip::DeviceLayer::PlatformMgr().RunEventLoop();
#endif // CONFIG_USE_SEPARATE_EVENTLOOP

return mCommandExitStatus;
}

void CHIPCommandBridge::StopWaiting()
{
#if CONFIG_USE_SEPARATE_EVENTLOOP
{
std::lock_guard<std::mutex> lk(cvWaitingForResponseMutex);
mWaitingForResponse = false;
}
cvWaitingForResponse.notify_all();
#else // CONFIG_USE_SEPARATE_EVENTLOOP
LogErrorOnFailure(chip::DeviceLayer::PlatformMgr().StopEventLoopTask());
#endif // CONFIG_USE_SEPARATE_EVENTLOOP
}
59 changes: 59 additions & 0 deletions examples/chip-tool-darwin/commands/pairing/Commands.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,59 @@
/*
* 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 "PairingCommandBridge.h"

class Unpair : public PairingCommandBridge
{
public:
Unpair() : PairingCommandBridge("unpair", PairingMode::None) {}
};

class PairQRCode : public PairingCommandBridge
{
public:
PairQRCode() : PairingCommandBridge("qrcode", PairingMode::QRCode) {}
};

class PairManualCode : public PairingCommandBridge
{
public:
PairManualCode() : PairingCommandBridge("manualcode", PairingMode::ManualCode) {}
};

class PairWithIPAddress : public PairingCommandBridge
{
public:
PairWithIPAddress() : PairingCommandBridge("ethernet", PairingMode::Ethernet) {}
};

void registerCommandsPairing(Commands & commands)
{
const char * clusterName = "Pairing";

commands_list clusterCommands = {
make_unique<Unpair>(),
make_unique<PairQRCode>(),
make_unique<PairManualCode>(),
make_unique<PairWithIPAddress>(),
};

commands.Register(clusterName, clusterCommands);
}
75 changes: 75 additions & 0 deletions examples/chip-tool-darwin/commands/pairing/PairingCommandBridge.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,75 @@
/*
* 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"
#import <CHIP/CHIPClustersObjc.h>
#import <CHIP/CHIPDevicePairingDelegate.h>

enum class PairingMode
{
None,
QRCode,
ManualCode,
Ethernet
};

class PairingCommandBridge : public CHIPCommandBridge
{
public:
PairingCommandBridge(const char * commandName, PairingMode mode) : CHIPCommandBridge(commandName), mPairingMode(mode)
{
AddArgument("node-id", 0, UINT64_MAX, &mNodeId);

switch (mode)
{
case PairingMode::None:
break;
case PairingMode::QRCode:
AddArgument("payload", &mOnboardingPayload);
break;
case PairingMode::ManualCode:
AddArgument("payload", &mOnboardingPayload);
break;
case PairingMode::Ethernet:
AddArgument("setup-pin-code", 0, 134217727, &mSetupPINCode);
AddArgument("discriminator", 0, 4096, &mDiscriminator);
AddArgument("device-remote-ip", &ipAddress);
AddArgument("device-remote-port", 0, UINT16_MAX, &mRemotePort);
break;
}
}

/////////// CHIPCommandBridge Interface /////////
CHIP_ERROR RunCommand() override;
chip::System::Clock::Timeout GetWaitDuration() const override { return chip::System::Clock::Seconds16(120); }

private:
void PairWithCode(NSError * error);
void PairWithIPAddress(NSError * error);
void Unpair(NSError * error);
void SetUpPairingDelegate();

const PairingMode mPairingMode;
chip::NodeId mNodeId;
uint16_t mRemotePort;
uint16_t mDiscriminator;
uint32_t mSetupPINCode;
char * mOnboardingPayload;
char * ipAddress;
};
Loading

0 comments on commit 4549ca8

Please sign in to comment.