[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;
+};