From c0071eb67552cae7d12ef47b4f42f57e7b881b20 Mon Sep 17 00:00:00 2001 From: Vivien Nicolas Date: Wed, 30 Oct 2024 17:58:33 +0100 Subject: [PATCH] [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) --- .../commands/common/CHIPCommandBridge.h | 2 - .../commands/common/CHIPCommandBridge.mm | 5 -- .../commands/common/DeviceDelegate.h | 1 + .../commands/common/DeviceDelegate.mm | 12 +++ .../commands/configuration/Commands.h | 2 + .../configuration/SetUpDeviceCommand.h | 82 +++++++++++++++++++ 6 files changed, 97 insertions(+), 7 deletions(-) create mode 100644 examples/darwin-framework-tool/commands/configuration/SetUpDeviceCommand.h diff --git a/examples/darwin-framework-tool/commands/common/CHIPCommandBridge.h b/examples/darwin-framework-tool/commands/common/CHIPCommandBridge.h index 2f53c0dd7bc4db..90f3a6c56415f6 100644 --- a/examples/darwin-framework-tool/commands/common/CHIPCommandBridge.h +++ b/examples/darwin-framework-tool/commands/common/CHIPCommandBridge.h @@ -52,7 +52,6 @@ class CHIPCommandBridge : public Command { 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 @@ class CHIPCommandBridge : public Command { chip::Optional mPaaTrustStorePath; chip::Optional mCommissionerVendorId; std::string mCurrentIdentity; - chip::Optional mPretendThreadEnabled; }; diff --git a/examples/darwin-framework-tool/commands/common/CHIPCommandBridge.mm b/examples/darwin-framework-tool/commands/common/CHIPCommandBridge.mm index 2eba24c84ad44c..6472d2cae77f5e 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 a3f5cf427f191c..97ab5574295728 100644 --- a/examples/darwin-framework-tool/commands/common/DeviceDelegate.h +++ b/examples/darwin-framework-tool/commands/common/DeviceDelegate.h @@ -19,5 +19,6 @@ #import @interface DeviceDelegate : NSObject +- (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 ecf8e708e26ff3..1a7c82b46e631d 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 @@ @implementation DeviceDelegate - (instancetype)init { if (self = [super init]) { + _maxIntervalForSubscription = nil; _threadEnabled = NO; } return self; @@ -55,6 +57,16 @@ - (void)deviceConfigurationChanged:(MTRDevice *)device { } +- (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 8ee148e63b8f8b..1466f1fd93d9c3 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(), make_unique(), make_unique(), }; 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 00000000000000..8df842cf5769ae --- /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 + +#include + +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 mPretendThreadEnabled; + chip::Optional mMaxIntervalForSubscription; +};