[darwin-framework-tool] Add a command to initialize a MTRDevice such the the initial subscription is setted up without having to issue an additional command (e.g read or write) (#36287)
diff --git a/examples/darwin-framework-tool/commands/common/CHIPCommandBridge.h b/examples/darwin-framework-tool/commands/common/CHIPCommandBridge.h
index 2f53c0d..90f3a6c 100644
--- a/examples/darwin-framework-tool/commands/common/CHIPCommandBridge.h
+++ b/examples/darwin-framework-tool/commands/common/CHIPCommandBridge.h
@@ -52,7 +52,6 @@
AddArgument("commissioner-vendor-id", 0, UINT16_MAX, &mCommissionerVendorId,
"The vendor id to use for darwin-framework-tool. If not provided, chip::VendorId::TestVendor1 (65521, 0xFFF1) will be "
"used.");
- AddArgument("pretend-thread-enabled", 0, 1, &mPretendThreadEnabled, "When the command is issued using an MTRDevice (via -use-mtr-device), instructs the MTRDevice to treat the target device as a Thread device.");
}
/////////// Command Interface /////////
@@ -165,5 +164,4 @@
chip::Optional<char *> mPaaTrustStorePath;
chip::Optional<chip::VendorId> mCommissionerVendorId;
std::string mCurrentIdentity;
- chip::Optional<bool> mPretendThreadEnabled;
};
diff --git a/examples/darwin-framework-tool/commands/common/CHIPCommandBridge.mm b/examples/darwin-framework-tool/commands/common/CHIPCommandBridge.mm
index 2eba24c..6472d2c 100644
--- a/examples/darwin-framework-tool/commands/common/CHIPCommandBridge.mm
+++ b/examples/darwin-framework-tool/commands/common/CHIPCommandBridge.mm
@@ -306,14 +306,9 @@
VerifyOrReturnValue(nil != device, nil);
// The device delegate is initialized only once, when the first MTRDevice is created.
- // As a result, subsequent commands using --use-mtr-device don’t need to specify the
- // `--pretend-thread-enabled 1` argument again. Any further attempts to set it to `0` will also be ignored.
if (sDeviceDelegate == nil) {
sDeviceDelegate = [[DeviceDelegate alloc] init];
sDeviceDelegateDispatchQueue = dispatch_queue_create("com.chip.devicedelegate", DISPATCH_QUEUE_SERIAL_WITH_AUTORELEASE_POOL);
- if (mPretendThreadEnabled.ValueOr(false)) {
- [sDeviceDelegate setPretendThreadEnabled:YES];
- }
}
[device addDelegate:sDeviceDelegate queue:sDeviceDelegateDispatchQueue];
diff --git a/examples/darwin-framework-tool/commands/common/DeviceDelegate.h b/examples/darwin-framework-tool/commands/common/DeviceDelegate.h
index a3f5cf4..97ab557 100644
--- a/examples/darwin-framework-tool/commands/common/DeviceDelegate.h
+++ b/examples/darwin-framework-tool/commands/common/DeviceDelegate.h
@@ -19,5 +19,6 @@
#import <Matter/Matter.h>
@interface DeviceDelegate : NSObject <MTRDeviceDelegate>
+- (void)setMaxIntervalForSubscription:(NSNumber *)maxInterval;
- (void)setPretendThreadEnabled:(BOOL)threadEnabled;
@end
diff --git a/examples/darwin-framework-tool/commands/common/DeviceDelegate.mm b/examples/darwin-framework-tool/commands/common/DeviceDelegate.mm
index ecf8e70..1a7c82b 100644
--- a/examples/darwin-framework-tool/commands/common/DeviceDelegate.mm
+++ b/examples/darwin-framework-tool/commands/common/DeviceDelegate.mm
@@ -23,6 +23,7 @@
NS_ASSUME_NONNULL_BEGIN
@interface DeviceDelegate ()
+@property (nonatomic, readwrite) NSNumber * maxIntervalForSubscription;
@property (nonatomic, readwrite) BOOL threadEnabled;
@end
@@ -30,6 +31,7 @@
- (instancetype)init
{
if (self = [super init]) {
+ _maxIntervalForSubscription = nil;
_threadEnabled = NO;
}
return self;
@@ -55,6 +57,16 @@
{
}
+- (void)setMaxIntervalForSubscription:(NSNumber *)maxInterval
+{
+ _maxIntervalForSubscription = maxInterval;
+}
+
+- (NSNumber *)unitTestMaxIntervalOverrideForSubscription:(MTRDevice *)device
+{
+ return _maxIntervalForSubscription;
+}
+
- (void)setPretendThreadEnabled:(BOOL)threadEnabled
{
_threadEnabled = threadEnabled;
diff --git a/examples/darwin-framework-tool/commands/configuration/Commands.h b/examples/darwin-framework-tool/commands/configuration/Commands.h
index 8ee148e..1466f1f 100644
--- a/examples/darwin-framework-tool/commands/configuration/Commands.h
+++ b/examples/darwin-framework-tool/commands/configuration/Commands.h
@@ -22,12 +22,14 @@
#include "ResetMRPParametersCommand.h"
#include "SetMRPParametersCommand.h"
+#include "SetUpDeviceCommand.h"
void registerCommandsConfiguration(Commands & commands)
{
const char * clusterName = "Configuration";
commands_list clusterCommands = {
+ make_unique<SetUpDeviceCommand>(),
make_unique<SetMRPParametersCommand>(),
make_unique<ResetMRPParametersCommand>(),
};
diff --git a/examples/darwin-framework-tool/commands/configuration/SetUpDeviceCommand.h b/examples/darwin-framework-tool/commands/configuration/SetUpDeviceCommand.h
new file mode 100644
index 0000000..8df842c
--- /dev/null
+++ b/examples/darwin-framework-tool/commands/configuration/SetUpDeviceCommand.h
@@ -0,0 +1,82 @@
+/*
+ * Copyright (c) 2024 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 "../common/DeviceDelegate.h"
+#import <Matter/Matter.h>
+
+#include <commands/common/Command.h>
+
+class SetUpDeviceCommand : public CHIPCommandBridge {
+public:
+ SetUpDeviceCommand()
+ : CHIPCommandBridge("device", "Creates and configures an instance of a device.")
+ {
+ AddArgument("node-id", 0, UINT64_MAX, &mNodeId, "The Node ID of the device instance to create.");
+ AddArgument("pretend-thread-enabled", 0, 1, &mPretendThreadEnabled,
+ "When the device is configured using an MTRDevice (via -use-mtr-device), instructs the MTRDevice to treat the "
+ "target device as a Thread device.");
+ AddArgument("max-interval", 0, UINT32_MAX, &mMaxIntervalForSubscription,
+ "When the device is configured using an MTRDevice (via --use-mtr-device), configure the maximum interval for the "
+ "delegate subscription.");
+ }
+
+protected:
+ /////////// CHIPCommandBridge Interface /////////
+ CHIP_ERROR RunCommand() override
+ {
+ __auto_type * controller = CurrentCommissioner();
+ VerifyOrReturnError(nil != controller, CHIP_ERROR_INCORRECT_STATE);
+
+ __auto_type * device = [MTRDevice deviceWithNodeID:@(mNodeId) controller:controller];
+ VerifyOrReturnError(nil != device, CHIP_ERROR_INCORRECT_STATE);
+
+ __auto_type * delegate = ConfigureDelegate();
+ __auto_type queue = dispatch_queue_create("com.chip.devicedelegate", DISPATCH_QUEUE_SERIAL_WITH_AUTORELEASE_POOL);
+ [device addDelegate:delegate queue:queue];
+
+ mDelegate = delegate;
+ SetCommandExitStatus(CHIP_NO_ERROR);
+ return CHIP_NO_ERROR;
+ }
+
+ // Our command is synchronous, so no need to wait.
+ chip::System::Clock::Timeout GetWaitDuration() const override { return chip::System::Clock::kZero; }
+
+private:
+ DeviceDelegate * ConfigureDelegate()
+ {
+ __auto_type * delegate = [[DeviceDelegate alloc] init];
+
+ if (mPretendThreadEnabled.ValueOr(false)) {
+ [delegate setPretendThreadEnabled:YES];
+ }
+
+ if (mMaxIntervalForSubscription.HasValue()) {
+ [delegate setMaxIntervalForSubscription:@(mMaxIntervalForSubscription.Value())];
+ }
+
+ return delegate;
+ }
+
+ DeviceDelegate * mDelegate;
+
+ chip::NodeId mNodeId;
+ chip::Optional<bool> mPretendThreadEnabled;
+ chip::Optional<uint32_t> mMaxIntervalForSubscription;
+};