[darwin-framework-tool] Set device delegate when using MTRDevice with –use-mtr-device (#36263)
diff --git a/examples/darwin-framework-tool/BUILD.gn b/examples/darwin-framework-tool/BUILD.gn
index 0d1e142..1c492ba 100644
--- a/examples/darwin-framework-tool/BUILD.gn
+++ b/examples/darwin-framework-tool/BUILD.gn
@@ -194,6 +194,8 @@
"commands/common/CertificateIssuer.mm",
"commands/common/ControllerStorage.h",
"commands/common/ControllerStorage.mm",
+ "commands/common/DeviceDelegate.h",
+ "commands/common/DeviceDelegate.mm",
"commands/common/MTRDevice_Externs.h",
"commands/common/MTRError.mm",
"commands/common/MTRError_Utils.h",
diff --git a/examples/darwin-framework-tool/commands/clusters/ReportCommandBridge.h b/examples/darwin-framework-tool/commands/clusters/ReportCommandBridge.h
index cd8125e..ba34283 100644
--- a/examples/darwin-framework-tool/commands/clusters/ReportCommandBridge.h
+++ b/examples/darwin-framework-tool/commands/clusters/ReportCommandBridge.h
@@ -105,9 +105,7 @@
LogNSError("Error reading attribute", error);
RemoteDataModelLogger::LogAttributeErrorAsJSON(endpoint, cluster, attribute, error);
} else {
- for (id item in values) {
- NSLog(@"Response Item: %@", [item description]);
- }
+ NSLog(@"cluster (0x%08" PRIX32 ") ReadAttribute (0x%08" PRIX32 ") on endpoint %u: %@", mClusterId, mAttributeId, endpointId, values);
RemoteDataModelLogger::LogAttributeAsJSON(endpoint, cluster, attribute, values);
}
diff --git a/examples/darwin-framework-tool/commands/common/CHIPCommandBridge.h b/examples/darwin-framework-tool/commands/common/CHIPCommandBridge.h
index 90f3a6c..2f53c0d 100644
--- a/examples/darwin-framework-tool/commands/common/CHIPCommandBridge.h
+++ b/examples/darwin-framework-tool/commands/common/CHIPCommandBridge.h
@@ -52,6 +52,7 @@
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 /////////
@@ -164,4 +165,5 @@
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 b237aca..2eba24c 100644
--- a/examples/darwin-framework-tool/commands/common/CHIPCommandBridge.mm
+++ b/examples/darwin-framework-tool/commands/common/CHIPCommandBridge.mm
@@ -28,12 +28,15 @@
#import "CHIPCommandStorageDelegate.h"
#import "CertificateIssuer.h"
#import "ControllerStorage.h"
+#import "DeviceDelegate.h"
#include "MTRError_Utils.h"
#include <map>
#include <string>
static CHIPToolPersistentStorageDelegate * storage = nil;
+static DeviceDelegate * sDeviceDelegate = nil;
+static dispatch_queue_t sDeviceDelegateDispatchQueue = nil;
std::set<CHIPCommandBridge *> CHIPCommandBridge::sDeferredCleanups;
std::map<std::string, MTRDeviceController *> CHIPCommandBridge::mControllers;
dispatch_queue_t CHIPCommandBridge::mOTAProviderCallbackQueue;
@@ -302,6 +305,18 @@
__auto_type * device = [MTRDevice deviceWithNodeID:@(nodeId) controller:controller];
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];
+
return device;
}
diff --git a/examples/darwin-framework-tool/commands/common/DeviceDelegate.h b/examples/darwin-framework-tool/commands/common/DeviceDelegate.h
new file mode 100644
index 0000000..a3f5cf4
--- /dev/null
+++ b/examples/darwin-framework-tool/commands/common/DeviceDelegate.h
@@ -0,0 +1,23 @@
+/*
+ * 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.
+ *
+ */
+
+#import <Matter/Matter.h>
+
+@interface DeviceDelegate : NSObject <MTRDeviceDelegate>
+- (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
new file mode 100644
index 0000000..ecf8e70
--- /dev/null
+++ b/examples/darwin-framework-tool/commands/common/DeviceDelegate.mm
@@ -0,0 +1,69 @@
+/*
+ * 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.
+ *
+ */
+
+#import "DeviceDelegate.h"
+
+#include <lib/support/logging/CHIPLogging.h>
+
+NS_ASSUME_NONNULL_BEGIN
+
+@interface DeviceDelegate ()
+@property (nonatomic, readwrite) BOOL threadEnabled;
+@end
+
+@implementation DeviceDelegate
+- (instancetype)init
+{
+ if (self = [super init]) {
+ _threadEnabled = NO;
+ }
+ return self;
+}
+
+- (void)device:(MTRDevice *)device stateChanged:(MTRDeviceState)state
+{
+}
+
+- (void)device:(MTRDevice *)device receivedAttributeReport:(NSArray<NSDictionary<NSString *, id> *> *)attributeReport
+{
+}
+
+- (void)device:(MTRDevice *)device receivedEventReport:(NSArray<NSDictionary<NSString *, id> *> *)eventReport
+{
+}
+
+- (void)deviceCachePrimed:(MTRDevice *)device
+{
+}
+
+- (void)deviceConfigurationChanged:(MTRDevice *)device
+{
+}
+
+- (void)setPretendThreadEnabled:(BOOL)threadEnabled
+{
+ _threadEnabled = threadEnabled;
+}
+
+- (BOOL)unitTestPretendThreadEnabled:(MTRDevice *)device
+{
+ return _threadEnabled;
+}
+@end
+
+NS_ASSUME_NONNULL_END
diff --git a/src/darwin/Framework/Matter.xcodeproj/project.pbxproj b/src/darwin/Framework/Matter.xcodeproj/project.pbxproj
index 6a80290..673f1ca 100644
--- a/src/darwin/Framework/Matter.xcodeproj/project.pbxproj
+++ b/src/darwin/Framework/Matter.xcodeproj/project.pbxproj
@@ -336,6 +336,8 @@
B2E0D7B7245B0B5C003C5B48 /* MTRQRCodeSetupPayloadParser.mm in Sources */ = {isa = PBXBuildFile; fileRef = B2E0D7AE245B0B5C003C5B48 /* MTRQRCodeSetupPayloadParser.mm */; };
B2E0D7B8245B0B5C003C5B48 /* MTRSetupPayload.h in Headers */ = {isa = PBXBuildFile; fileRef = B2E0D7AF245B0B5C003C5B48 /* MTRSetupPayload.h */; settings = {ATTRIBUTES = (Public, ); }; };
B2E0D7B9245B0B5C003C5B48 /* MTRSetupPayload.mm in Sources */ = {isa = PBXBuildFile; fileRef = B2E0D7B0245B0B5C003C5B48 /* MTRSetupPayload.mm */; };
+ B409D0AE2CCFB89600A7ED5A /* DeviceDelegate.h in Headers */ = {isa = PBXBuildFile; fileRef = B409D0AC2CCFB89600A7ED5A /* DeviceDelegate.h */; };
+ B409D0AF2CCFB89600A7ED5A /* DeviceDelegate.mm in Sources */ = {isa = PBXBuildFile; fileRef = B409D0AD2CCFB89600A7ED5A /* DeviceDelegate.mm */; };
B43B39EA2CB859A5006AA284 /* DumpMemoryGraphCommand.mm in Sources */ = {isa = PBXBuildFile; fileRef = B43B39E62CB859A5006AA284 /* DumpMemoryGraphCommand.mm */; };
B43B39EB2CB859A5006AA284 /* LeaksTool.mm in Sources */ = {isa = PBXBuildFile; fileRef = B43B39E82CB859A5006AA284 /* LeaksTool.mm */; };
B43B39EC2CB859A5006AA284 /* DumpMemoryGraphCommand.h in Headers */ = {isa = PBXBuildFile; fileRef = B43B39E52CB859A5006AA284 /* DumpMemoryGraphCommand.h */; };
@@ -800,6 +802,8 @@
B2E0D7AE245B0B5C003C5B48 /* MTRQRCodeSetupPayloadParser.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = MTRQRCodeSetupPayloadParser.mm; sourceTree = "<group>"; };
B2E0D7AF245B0B5C003C5B48 /* MTRSetupPayload.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MTRSetupPayload.h; sourceTree = "<group>"; };
B2E0D7B0245B0B5C003C5B48 /* MTRSetupPayload.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = MTRSetupPayload.mm; sourceTree = "<group>"; };
+ B409D0AC2CCFB89600A7ED5A /* DeviceDelegate.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = DeviceDelegate.h; sourceTree = "<group>"; };
+ B409D0AD2CCFB89600A7ED5A /* DeviceDelegate.mm */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.objcpp; path = DeviceDelegate.mm; sourceTree = "<group>"; };
B43B39E42CB859A5006AA284 /* Commands.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = Commands.h; sourceTree = "<group>"; };
B43B39E52CB859A5006AA284 /* DumpMemoryGraphCommand.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = DumpMemoryGraphCommand.h; sourceTree = "<group>"; };
B43B39E62CB859A5006AA284 /* DumpMemoryGraphCommand.mm */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.objcpp; path = DumpMemoryGraphCommand.mm; sourceTree = "<group>"; };
@@ -1013,6 +1017,8 @@
037C3D9B2991BD4F00B7EEE2 /* common */ = {
isa = PBXGroup;
children = (
+ B409D0AC2CCFB89600A7ED5A /* DeviceDelegate.h */,
+ B409D0AD2CCFB89600A7ED5A /* DeviceDelegate.mm */,
B43B39EF2CB99090006AA284 /* CertificateIssuer.h */,
B43B39F02CB99090006AA284 /* CertificateIssuer.mm */,
B43B39F12CB99090006AA284 /* ControllerStorage.h */,
@@ -1673,6 +1679,7 @@
B4F773CA2CB54B61008C6B23 /* LeakChecker.h in Headers */,
B43B39F82CB99090006AA284 /* CertificateIssuer.h in Headers */,
B43B39F92CB99090006AA284 /* PreferencesStorage.h in Headers */,
+ B409D0AE2CCFB89600A7ED5A /* DeviceDelegate.h in Headers */,
B43B39FA2CB99090006AA284 /* ControllerStorage.h in Headers */,
037C3DB82991BD5000B7EEE2 /* ClusterCommandBridge.h in Headers */,
037C3DC82991BD5100B7EEE2 /* CHIPToolKeypair.h in Headers */,
@@ -2058,6 +2065,7 @@
0382FA302992F40C00247BBB /* ComplexArgumentParser.cpp in Sources */,
039145E12993102B00257B3E /* main.mm in Sources */,
037C3DD42991BD5200B7EEE2 /* logging.mm in Sources */,
+ B409D0AF2CCFB89600A7ED5A /* DeviceDelegate.mm in Sources */,
512431282BA0C8BF000BC136 /* SetMRPParametersCommand.mm in Sources */,
512431292BA0C8BF000BC136 /* ResetMRPParametersCommand.mm in Sources */,
037C3DB32991BD5000B7EEE2 /* OpenCommissioningWindowCommand.mm in Sources */,