darwin-framework-tool: Add support for paseonly pairing (#35206)
This includes code-paseonly and by-index-paseonly commands, as as interacting
with devices over PASE by preferring an existing MTRBaseDevice connected over
PASE to creating a new CASE connection when looking up a device by node id.
diff --git a/examples/darwin-framework-tool/commands/clusters/ModelCommandBridge.mm b/examples/darwin-framework-tool/commands/clusters/ModelCommandBridge.mm
index 97b7c09..47a29f8 100644
--- a/examples/darwin-framework-tool/commands/clusters/ModelCommandBridge.mm
+++ b/examples/darwin-framework-tool/commands/clusters/ModelCommandBridge.mm
@@ -25,9 +25,10 @@
CHIP_ERROR ModelCommand::RunCommand()
{
- MTRDeviceController * commissioner = CurrentCommissioner();
ChipLogProgress(chipTool, "Sending command to node 0x" ChipLogFormatX64, ChipLogValueX64(mNodeId));
- auto * device = [MTRBaseDevice deviceWithNodeID:@(mNodeId) controller:commissioner];
+ auto * device = BaseDeviceWithNodeId(mNodeId);
+ VerifyOrReturnError(device != nil, CHIP_ERROR_INCORRECT_STATE);
+
CHIP_ERROR err = SendCommand(device, mEndPointId);
if (err != CHIP_NO_ERROR) {
diff --git a/examples/darwin-framework-tool/commands/common/CHIPCommandBridge.h b/examples/darwin-framework-tool/commands/common/CHIPCommandBridge.h
index 6cb580d..9458d30 100644
--- a/examples/darwin-framework-tool/commands/common/CHIPCommandBridge.h
+++ b/examples/darwin-framework-tool/commands/common/CHIPCommandBridge.h
@@ -17,6 +17,7 @@
*/
#pragma once
+
#import <Matter/Matter.h>
#include <commands/common/Command.h>
#include <commands/common/CredentialIssuerCommands.h>
@@ -26,8 +27,6 @@
#include "../provider/OTAProviderDelegate.h"
-#pragma once
-
inline constexpr char kIdentityAlpha[] = "alpha";
inline constexpr char kIdentityBeta[] = "beta";
inline constexpr char kIdentityGamma[] = "gamma";
@@ -91,6 +90,10 @@
MTRDeviceController * GetCommissioner(const char * identity);
+ // Returns the MTRBaseDevice for the specified node ID.
+ // Will utilize an existing PASE connection if the device is being commissioned.
+ MTRBaseDevice * BaseDeviceWithNodeId(chip::NodeId nodeId);
+
// Will log the given string and given error (as progress if success, error
// if failure).
void LogNSError(const char * logString, NSError * error);
diff --git a/examples/darwin-framework-tool/commands/common/CHIPCommandBridge.mm b/examples/darwin-framework-tool/commands/common/CHIPCommandBridge.mm
index bb232e3..8b9a5d3 100644
--- a/examples/darwin-framework-tool/commands/common/CHIPCommandBridge.mm
+++ b/examples/darwin-framework-tool/commands/common/CHIPCommandBridge.mm
@@ -195,6 +195,14 @@
MTRDeviceController * CHIPCommandBridge::GetCommissioner(const char * identity) { return mControllers[identity]; }
+MTRBaseDevice * CHIPCommandBridge::BaseDeviceWithNodeId(chip::NodeId nodeId)
+{
+ MTRDeviceController * controller = CurrentCommissioner();
+ VerifyOrReturnValue(controller != nil, nil);
+ return [controller deviceBeingCommissionedWithNodeID:@(nodeId) error:nullptr]
+ ?: [MTRBaseDevice deviceWithNodeID:@(nodeId) controller:controller];
+}
+
void CHIPCommandBridge::StopCommissioners()
{
for (auto & pair : mControllers) {
diff --git a/examples/darwin-framework-tool/commands/delay/WaitForCommissioneeCommand.mm b/examples/darwin-framework-tool/commands/delay/WaitForCommissioneeCommand.mm
index 6bc25de..f3c15c9 100644
--- a/examples/darwin-framework-tool/commands/delay/WaitForCommissioneeCommand.mm
+++ b/examples/darwin-framework-tool/commands/delay/WaitForCommissioneeCommand.mm
@@ -22,10 +22,7 @@
CHIP_ERROR WaitForCommissioneeCommand::RunCommand()
{
- MTRDeviceController * commissioner = CurrentCommissioner();
- VerifyOrReturnError(nil != commissioner, CHIP_ERROR_INCORRECT_STATE);
-
- auto * base_device = [MTRBaseDevice deviceWithNodeID:@(mNodeId) controller:commissioner];
+ auto * base_device = BaseDeviceWithNodeId(mNodeId);
VerifyOrReturnError(base_device != nil, CHIP_ERROR_INCORRECT_STATE);
if (mExpireExistingSession.ValueOr(true)) {
diff --git a/examples/darwin-framework-tool/commands/pairing/Commands.h b/examples/darwin-framework-tool/commands/pairing/Commands.h
index bc1bccd..4923a55 100644
--- a/examples/darwin-framework-tool/commands/pairing/Commands.h
+++ b/examples/darwin-framework-tool/commands/pairing/Commands.h
@@ -28,38 +28,52 @@
class PairCode : public PairingCommandBridge
{
public:
- PairCode() : PairingCommandBridge("code", PairingMode::Code, PairingNetworkType::None) {}
+ PairCode() : PairingCommandBridge("code", PairingMode::Code, CommissioningType::NoNetwork) {}
+};
+
+class PairCodePASEOnly : public PairingCommandBridge
+{
+public:
+ PairCodePASEOnly() : PairingCommandBridge("code-paseonly", PairingMode::Code, CommissioningType::None) {}
};
class PairCodeWifi : public PairingCommandBridge
{
public:
- PairCodeWifi() : PairingCommandBridge("code-wifi", PairingMode::Code, PairingNetworkType::WiFi) {}
+ PairCodeWifi() : PairingCommandBridge("code-wifi", PairingMode::Code, CommissioningType::WiFi) {}
};
class PairCodeThread : public PairingCommandBridge
{
public:
- PairCodeThread() : PairingCommandBridge("code-thread", PairingMode::Code, PairingNetworkType::Thread) {}
+ PairCodeThread() : PairingCommandBridge("code-thread", PairingMode::Code, CommissioningType::Thread) {}
};
class PairBleWiFi : public PairingCommandBridge
{
public:
- PairBleWiFi() : PairingCommandBridge("ble-wifi", PairingMode::Ble, PairingNetworkType::WiFi) {}
+ PairBleWiFi() : PairingCommandBridge("ble-wifi", PairingMode::Ble, CommissioningType::WiFi) {}
};
class PairBleThread : public PairingCommandBridge
{
public:
- PairBleThread() : PairingCommandBridge("ble-thread", PairingMode::Ble, PairingNetworkType::Thread) {}
+ PairBleThread() : PairingCommandBridge("ble-thread", PairingMode::Ble, CommissioningType::Thread) {}
};
class PairAlreadyDiscoveredByIndex : public PairingCommandBridge
{
public:
PairAlreadyDiscoveredByIndex() :
- PairingCommandBridge("by-index", PairingMode::AlreadyDiscoveredByIndex, PairingNetworkType::None)
+ PairingCommandBridge("by-index", PairingMode::AlreadyDiscoveredByIndex, CommissioningType::NoNetwork)
+ {}
+};
+
+class PairAlreadyDiscoveredByIndexPASEOnly : public PairingCommandBridge
+{
+public:
+ PairAlreadyDiscoveredByIndexPASEOnly() :
+ PairingCommandBridge("by-index-paseonly", PairingMode::AlreadyDiscoveredByIndex, CommissioningType::None)
{}
};
@@ -67,7 +81,7 @@
{
public:
PairAlreadyDiscoveredByIndexWithWiFi() :
- PairingCommandBridge("by-index-with-wifi", PairingMode::AlreadyDiscoveredByIndex, PairingNetworkType::WiFi)
+ PairingCommandBridge("by-index-with-wifi", PairingMode::AlreadyDiscoveredByIndex, CommissioningType::WiFi)
{}
};
@@ -75,14 +89,14 @@
{
public:
PairAlreadyDiscoveredByIndexWithThread() :
- PairingCommandBridge("by-index-with-thread", PairingMode::AlreadyDiscoveredByIndex, PairingNetworkType::Thread)
+ PairingCommandBridge("by-index-with-thread", PairingMode::AlreadyDiscoveredByIndex, CommissioningType::Thread)
{}
};
class Unpair : public PairingCommandBridge
{
public:
- Unpair() : PairingCommandBridge("unpair", PairingMode::None, PairingNetworkType::None) {}
+ Unpair() : PairingCommandBridge("unpair", PairingMode::Unpair, CommissioningType::None) {}
};
void registerCommandsPairing(Commands & commands)
@@ -91,11 +105,13 @@
commands_list clusterCommands = {
make_unique<PairCode>(),
+ make_unique<PairCodePASEOnly>(),
make_unique<PairCodeWifi>(),
make_unique<PairCodeThread>(),
make_unique<PairBleWiFi>(),
make_unique<PairBleThread>(),
make_unique<PairAlreadyDiscoveredByIndex>(),
+ make_unique<PairAlreadyDiscoveredByIndexPASEOnly>(),
make_unique<Unpair>(),
make_unique<OpenCommissioningWindowCommand>(),
make_unique<PreWarmCommissioningCommand>(),
diff --git a/examples/darwin-framework-tool/commands/pairing/DeviceControllerDelegateBridge.mm b/examples/darwin-framework-tool/commands/pairing/DeviceControllerDelegateBridge.mm
index 52f0fd4..92ff56a 100644
--- a/examples/darwin-framework-tool/commands/pairing/DeviceControllerDelegateBridge.mm
+++ b/examples/darwin-framework-tool/commands/pairing/DeviceControllerDelegateBridge.mm
@@ -50,6 +50,11 @@
}
ChipLogProgress(chipTool, "Pairing Success");
ChipLogProgress(chipTool, "PASE establishment successful");
+ if (_params == nil) {
+ _commandBridge->SetCommandExitStatus(nil);
+ return;
+ }
+
NSError * commissionError;
[_commissioner commissionNodeWithID:@(_deviceID) commissioningParams:_params error:&commissionError];
if (commissionError != nil) {
diff --git a/examples/darwin-framework-tool/commands/pairing/PairingCommandBridge.h b/examples/darwin-framework-tool/commands/pairing/PairingCommandBridge.h
index 4ca6c4c..7502ba6 100644
--- a/examples/darwin-framework-tool/commands/pairing/PairingCommandBridge.h
+++ b/examples/darwin-framework-tool/commands/pairing/PairingCommandBridge.h
@@ -22,15 +22,16 @@
enum class PairingMode
{
- None,
+ Unpair,
Code,
Ble,
AlreadyDiscoveredByIndex,
};
-enum class PairingNetworkType
+enum class CommissioningType
{
- None,
+ None, // establish PASE only
+ NoNetwork,
WiFi,
Thread,
Ethernet,
@@ -39,27 +40,28 @@
class PairingCommandBridge : public CHIPCommandBridge
{
public:
- PairingCommandBridge(const char * commandName, PairingMode mode, PairingNetworkType networkType) :
- CHIPCommandBridge(commandName), mPairingMode(mode), mNetworkType(networkType)
+ PairingCommandBridge(const char * commandName, PairingMode mode, CommissioningType commissioningType) :
+ CHIPCommandBridge(commandName), mPairingMode(mode), mCommissioningType(commissioningType)
{
AddArgument("node-id", 0, UINT64_MAX, &mNodeId);
- switch (networkType)
+ switch (commissioningType)
{
- case PairingNetworkType::None:
- case PairingNetworkType::Ethernet:
+ case CommissioningType::None:
+ case CommissioningType::NoNetwork:
+ case CommissioningType::Ethernet:
break;
- case PairingNetworkType::WiFi:
+ case CommissioningType::WiFi:
AddArgument("ssid", &mSSID);
AddArgument("password", &mPassword);
break;
- case PairingNetworkType::Thread:
+ case CommissioningType::Thread:
AddArgument("operationalDataset", &mOperationalDataset);
break;
}
switch (mode)
{
- case PairingMode::None:
+ case PairingMode::Unpair:
break;
case PairingMode::Code:
AddArgument("payload", &mOnboardingPayload);
@@ -74,17 +76,16 @@
break;
}
- if (mode != PairingMode::None)
+ if (commissioningType != CommissioningType::None)
{
AddArgument("country-code", &mCountryCode,
"Country code to use to set the Basic Information cluster's Location attribute");
+ AddArgument("use-device-attestation-delegate", 0, 1, &mUseDeviceAttestationDelegate,
+ "If true, use a device attestation delegate that always wants to be notified about attestation results. "
+ "Defaults to false.");
+ AddArgument("device-attestation-failsafe-time", 0, UINT16_MAX, &mDeviceAttestationFailsafeTime,
+ "If set, the time to extend the failsafe to before calling the device attestation delegate");
}
-
- AddArgument("use-device-attestation-delegate", 0, 1, &mUseDeviceAttestationDelegate,
- "If true, use a device attestation delegate that always wants to be notified about attestation results. "
- "Defaults to false.");
- AddArgument("device-attestation-failsafe-time", 0, UINT16_MAX, &mDeviceAttestationFailsafeTime,
- "If set, the time to extend the failsafe to before calling the device attestation delegate");
}
/////////// CHIPCommandBridge Interface /////////
@@ -99,7 +100,7 @@
void SetUpDeviceControllerDelegate();
const PairingMode mPairingMode;
- const PairingNetworkType mNetworkType;
+ const CommissioningType mCommissioningType;
chip::ByteSpan mOperationalDataset;
chip::ByteSpan mSSID;
chip::ByteSpan mPassword;
diff --git a/examples/darwin-framework-tool/commands/pairing/PairingCommandBridge.mm b/examples/darwin-framework-tool/commands/pairing/PairingCommandBridge.mm
index 2ab95a9..122cb24 100644
--- a/examples/darwin-framework-tool/commands/pairing/PairingCommandBridge.mm
+++ b/examples/darwin-framework-tool/commands/pairing/PairingCommandBridge.mm
@@ -48,40 +48,43 @@
void PairingCommandBridge::SetUpDeviceControllerDelegate()
{
- dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.pairing", DISPATCH_QUEUE_SERIAL);
CHIPToolDeviceControllerDelegate * deviceControllerDelegate = [[CHIPToolDeviceControllerDelegate alloc] init];
- MTRCommissioningParameters * params = [[MTRCommissioningParameters alloc] init];
- MTRDeviceController * commissioner = CurrentCommissioner();
-
- [deviceControllerDelegate setDeviceID:mNodeId];
- switch (mNetworkType) {
- case PairingNetworkType::None:
- case PairingNetworkType::Ethernet:
- break;
- case PairingNetworkType::WiFi:
- [params setWifiSSID:[NSData dataWithBytes:mSSID.data() length:mSSID.size()]];
- [params setWifiCredentials:[NSData dataWithBytes:mPassword.data() length:mPassword.size()]];
- break;
- case PairingNetworkType::Thread:
- [params setThreadOperationalDataset:[NSData dataWithBytes:mOperationalDataset.data() length:mOperationalDataset.size()]];
- break;
- }
-
- if (mUseDeviceAttestationDelegate.ValueOr(false)) {
- params.deviceAttestationDelegate = [[NoOpAttestationDelegate alloc] init];
- if (mDeviceAttestationFailsafeTime.HasValue()) {
- params.failSafeTimeout = @(mDeviceAttestationFailsafeTime.Value());
- }
- }
-
- if (mCountryCode.HasValue()) {
- params.countryCode = [NSString stringWithUTF8String:mCountryCode.Value()];
- }
-
[deviceControllerDelegate setCommandBridge:this];
- [deviceControllerDelegate setParams:params];
- [deviceControllerDelegate setCommissioner:commissioner];
+ [deviceControllerDelegate setDeviceID:mNodeId];
+ if (mCommissioningType != CommissioningType::None) {
+ MTRCommissioningParameters * params = [[MTRCommissioningParameters alloc] init];
+ switch (mCommissioningType) {
+ case CommissioningType::None:
+ case CommissioningType::NoNetwork:
+ case CommissioningType::Ethernet:
+ break;
+ case CommissioningType::WiFi:
+ [params setWifiSSID:[NSData dataWithBytes:mSSID.data() length:mSSID.size()]];
+ [params setWifiCredentials:[NSData dataWithBytes:mPassword.data() length:mPassword.size()]];
+ break;
+ case CommissioningType::Thread:
+ [params setThreadOperationalDataset:[NSData dataWithBytes:mOperationalDataset.data() length:mOperationalDataset.size()]];
+ break;
+ }
+
+ if (mUseDeviceAttestationDelegate.ValueOr(false)) {
+ params.deviceAttestationDelegate = [[NoOpAttestationDelegate alloc] init];
+ if (mDeviceAttestationFailsafeTime.HasValue()) {
+ params.failSafeTimeout = @(mDeviceAttestationFailsafeTime.Value());
+ }
+ }
+
+ if (mCountryCode.HasValue()) {
+ params.countryCode = [NSString stringWithUTF8String:mCountryCode.Value()];
+ }
+
+ [deviceControllerDelegate setParams:params];
+ }
+
+ MTRDeviceController * commissioner = CurrentCommissioner();
+ [deviceControllerDelegate setCommissioner:commissioner];
+ dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.pairing", DISPATCH_QUEUE_SERIAL);
[commissioner setDeviceControllerDelegate:deviceControllerDelegate queue:callbackQueue];
}
@@ -89,7 +92,7 @@
{
NSError * error;
switch (mPairingMode) {
- case PairingMode::None:
+ case PairingMode::Unpair:
Unpair();
break;
case PairingMode::Code:
@@ -155,8 +158,7 @@
void PairingCommandBridge::Unpair()
{
dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip-tool.command", DISPATCH_QUEUE_SERIAL);
- MTRDeviceController * commissioner = CurrentCommissioner();
- auto * device = [MTRBaseDevice deviceWithNodeID:@(mNodeId) controller:commissioner];
+ auto * device = BaseDeviceWithNodeId(mNodeId);
ChipLogProgress(chipTool, "Attempting to unpair device %llu", mNodeId);
MTRBaseClusterOperationalCredentials * opCredsCluster =