Skip to content

Commit

Permalink
[darwin-framework-tool] Add an optional -use-mtr-device argument to r…
Browse files Browse the repository at this point in the history
…ead-by-id and write-by-id commands (#36243)

* [darwin-framework-tool][use-mtr-device] Add an option to send command using an MTRDevice instead of a MTRBaseDevice

* [darwin-framework-tool][use-mtr-device] Add an implementation for reading attributes via an MTRDevice

* [darwin-framework-tool][use-mtr-device] Add an implementation for writing attributes via an MTRDevice
  • Loading branch information
vivien-apple authored and pull[bot] committed Nov 11, 2024
1 parent b01d144 commit 1285930
Show file tree
Hide file tree
Showing 7 changed files with 115 additions and 7 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,8 @@ class ClusterCommand : public ModelCommand {

~ClusterCommand() {}

using ModelCommand::SendCommand;

CHIP_ERROR SendCommand(MTRBaseDevice * _Nonnull device, chip::EndpointId endpointId) override
{
id commandFields;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -52,6 +52,10 @@ class ModelCommand : public CHIPCommandBridge
}

virtual CHIP_ERROR SendCommand(MTRBaseDevice * _Nonnull device, chip::EndpointId endPointId) = 0;
virtual CHIP_ERROR SendCommand(MTRDevice * _Nonnull device, chip::EndpointId endPointId) { return CHIP_ERROR_NOT_IMPLEMENTED; }

protected:
chip::Optional<bool> mUseMTRDevice;

private:
chip::NodeId mNodeId;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -26,10 +26,18 @@
CHIP_ERROR ModelCommand::RunCommand()
{
ChipLogProgress(chipTool, "Sending command to node 0x" ChipLogFormatX64, ChipLogValueX64(mNodeId));
auto * device = BaseDeviceWithNodeId(mNodeId);
VerifyOrReturnError(device != nil, CHIP_ERROR_INCORRECT_STATE);

CHIP_ERROR err = SendCommand(device, mEndPointId);
CHIP_ERROR err = CHIP_NO_ERROR;

if (mUseMTRDevice.ValueOr(false)) {
auto * device = DeviceWithNodeId(mNodeId);
VerifyOrReturnError(device != nil, CHIP_ERROR_INCORRECT_STATE);
err = SendCommand(device, mEndPointId);
} else {
auto * device = BaseDeviceWithNodeId(mNodeId);
VerifyOrReturnError(device != nil, CHIP_ERROR_INCORRECT_STATE);
err = SendCommand(device, mEndPointId);
}

if (err != CHIP_NO_ERROR) {
ChipLogError(chipTool, "Error: %s", chip::ErrorStr(err));
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@ class ReadAttribute : public ModelCommand {
AddArgument("cluster-id", 0, UINT32_MAX, &mClusterId);
AddArgument("attribute-id", 0, UINT32_MAX, &mAttributeId);
AddArgument("fabric-filtered", 0, 1, &mFabricFiltered);
ModelCommand::AddArguments();
AddCommonByIdArguments();
}

ReadAttribute(chip::ClusterId clusterId)
Expand All @@ -37,7 +37,7 @@ class ReadAttribute : public ModelCommand {
{
AddArgument("attribute-id", 0, UINT32_MAX, &mAttributeId);
AddArgument("fabric-filtered", 0, 1, &mFabricFiltered);
ModelCommand::AddArguments();
AddCommonByIdArguments();
}

ReadAttribute(const char * _Nonnull attributeName)
Expand Down Expand Up @@ -83,7 +83,46 @@ class ReadAttribute : public ModelCommand {
return CHIP_NO_ERROR;
}

CHIP_ERROR SendCommand(MTRDevice * _Nonnull device, chip::EndpointId endpointId) override
{
MTRReadParams * params = [[MTRReadParams alloc] init];
if (mFabricFiltered.HasValue()) {
params.filterByFabric = mFabricFiltered.Value();
}

__auto_type * endpoint = @(endpointId);
__auto_type * cluster = @(mClusterId);
__auto_type * attribute = @(mAttributeId);
__auto_type values = [device readAttributeWithEndpointID:endpoint
clusterID:cluster
attributeID:attribute
params:params];

NSError * error = nil;
if (nil == values) {
__auto_type * userInfo = @ { @"reason" : @"No value available." };
error = [NSError errorWithDomain:@"Error" code:0 userInfo:userInfo];
LogNSError("Error reading attribute", error);
RemoteDataModelLogger::LogAttributeErrorAsJSON(endpoint, cluster, attribute, error);
} else {
for (id item in values) {
NSLog(@"Response Item: %@", [item description]);
}
RemoteDataModelLogger::LogAttributeAsJSON(endpoint, cluster, attribute, values);
}

SetCommandExitStatus(error);
return CHIP_NO_ERROR;
}

protected:
void AddCommonByIdArguments()
{
AddArgument("use-mtr-device", 0, 1, &mUseMTRDevice,
"Use MTRDevice instead of MTRBaseDevice to send this command. Default is false.");
ModelCommand::AddArguments();
}

chip::Optional<bool> mFabricFiltered;

private:
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,8 @@
#import "MTRError_Utils.h"
#import <Matter/Matter.h>

constexpr uint32_t kDefaultExpectedValueInterval = 60000;

class WriteAttribute : public ModelCommand {
public:
WriteAttribute()
Expand All @@ -33,7 +35,7 @@ class WriteAttribute : public ModelCommand {
AddArgument("cluster-id", 0, UINT32_MAX, &mClusterId);
AddArgument("attribute-id", 0, UINT32_MAX, &mAttributeId);
AddArgument("attribute-value", &mAttributeValue);
AddArguments();
AddCommonByIdArguments();
}

WriteAttribute(chip::ClusterId clusterId)
Expand All @@ -42,7 +44,7 @@ class WriteAttribute : public ModelCommand {
{
AddArgument("attribute-id", 0, UINT32_MAX, &mAttributeId);
AddArgument("attribute-value", &mAttributeValue);
AddArguments();
AddCommonByIdArguments();
}

~WriteAttribute() {}
Expand All @@ -54,6 +56,13 @@ class WriteAttribute : public ModelCommand {
return WriteAttribute::SendCommand(device, endpointId, mClusterId, mAttributeId, value);
}

CHIP_ERROR SendCommand(MTRDevice * _Nonnull device, chip::EndpointId endpointId) override
{
id value;
ReturnErrorOnFailure(GetValue(&value));
return WriteAttribute::SendCommand(device, endpointId, mClusterId, mAttributeId, value);
}

CHIP_ERROR SendCommand(MTRBaseDevice * _Nonnull device, chip::EndpointId endpointId, chip::ClusterId clusterId,
chip::AttributeId attributeId, id _Nonnull value)
{
Expand Down Expand Up @@ -87,6 +96,28 @@ class WriteAttribute : public ModelCommand {
return CHIP_NO_ERROR;
}

CHIP_ERROR SendCommand(MTRDevice * _Nonnull device, chip::EndpointId endpointId, chip::ClusterId clusterId,
chip::AttributeId attributeId, id _Nonnull value)
{
__auto_type * endpoint = @(endpointId);
__auto_type * cluster = @(mClusterId);
__auto_type * attribute = @(mAttributeId);
__auto_type * expectedValueInterval = @(mExpectedValueInterval.ValueOr(kDefaultExpectedValueInterval));
__auto_type * timedWriteTimeout = mTimedInteractionTimeoutMs.HasValue()
? [NSNumber numberWithUnsignedShort:mTimedInteractionTimeoutMs.Value()]
: nil;

[device writeAttributeWithEndpointID:endpoint
clusterID:cluster
attributeID:attribute
value:value
expectedValueInterval:expectedValueInterval
timedWriteTimeout:timedWriteTimeout];

SetCommandExitStatus(CHIP_NO_ERROR);
return CHIP_NO_ERROR;
}

protected:
WriteAttribute(const char * _Nonnull attributeName)
: ModelCommand("write")
Expand All @@ -95,6 +126,14 @@ class WriteAttribute : public ModelCommand {
// Subclasses are responsible for calling AddArguments.
}

void AddCommonByIdArguments()
{
AddArgument("use-mtr-device", 0, 1, &mUseMTRDevice,
"Use MTRDevice instead of MTRBaseDevice to send this command. Default is false.");
AddArgument("expectedValueInterval", 0, UINT32_MAX, &mExpectedValueInterval, "When the write is issued using an MTRDevice (via –use-mtr-device), specify the maximum interval (in milliseconds) during which reads of the attribute will return the expected value. The default is 60000 milliseconds (60 seconds).");
AddArguments();
}

void AddArguments()
{
AddArgument("timedInteractionTimeoutMs", 0, UINT16_MAX, &mTimedInteractionTimeoutMs,
Expand All @@ -104,6 +143,7 @@ class WriteAttribute : public ModelCommand {
}

chip::Optional<uint16_t> mTimedInteractionTimeoutMs;
chip::Optional<uint32_t> mExpectedValueInterval;
chip::Optional<uint32_t> mDataVersion;

private:
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -97,6 +97,10 @@ class CHIPCommandBridge : public Command {
// Will utilize an existing PASE connection if the device is being commissioned.
MTRBaseDevice * BaseDeviceWithNodeId(chip::NodeId nodeId);

// Returns the MTRDevice for the specified node ID.
// Will utilize an existing PASE connection if the device is being commissioned.
MTRDevice * DeviceWithNodeId(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);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -285,6 +285,17 @@
?: [MTRBaseDevice deviceWithNodeID:@(nodeId) controller:controller];
}

MTRDevice * CHIPCommandBridge::DeviceWithNodeId(chip::NodeId nodeId)
{
__auto_type * controller = CurrentCommissioner();
VerifyOrReturnValue(nil != controller, nil);

__auto_type * device = [MTRDevice deviceWithNodeID:@(nodeId) controller:controller];
VerifyOrReturnValue(nil != device, nil);

return device;
}

void CHIPCommandBridge::StopCommissioners()
{
for (auto & pair : mControllers) {
Expand Down

0 comments on commit 1285930

Please sign in to comment.