Skip to content

Commit

Permalink
[chip-tool] Add vector arguments supports for write interactions
Browse files Browse the repository at this point in the history
  • Loading branch information
vivien-apple committed Jun 14, 2022
1 parent 37004b4 commit acd95fc
Show file tree
Hide file tree
Showing 5 changed files with 250 additions and 116 deletions.
11 changes: 10 additions & 1 deletion examples/chip-tool/commands/clusters/ComplexArgument.h
Original file line number Diff line number Diff line change
Expand Up @@ -308,8 +308,17 @@ template <typename T>
class TypedComplexArgument : public ComplexArgument
{
public:
TypedComplexArgument() {}
TypedComplexArgument(T * request) : mRequest(request) {}
~TypedComplexArgument() { ComplexArgumentParser::Finalize(*mRequest); }
~TypedComplexArgument()
{
if (mRequest != nullptr)
{
ComplexArgumentParser::Finalize(*mRequest);
}
}

void SetArgument(T * request) { mRequest = request; };

CHIP_ERROR Parse(const char * label, const char * json)
{
Expand Down
139 changes: 114 additions & 25 deletions examples/chip-tool/commands/clusters/WriteAttributeCommand.h
Original file line number Diff line number Diff line change
Expand Up @@ -23,36 +23,105 @@
#include "DataModelLogger.h"
#include "ModelCommand.h"

template <class T = std::vector<CustomArgument *>>
class WriteAttribute : public InteractionModelWriter, public ModelCommand, public chip::app::WriteClient::Callback
{
public:
WriteAttribute(CredentialIssuerCommands * credsIssuerConfig) :
InteractionModelWriter(this), ModelCommand("write-by-id", credsIssuerConfig)
{
AddArgument("cluster-id", 0, UINT32_MAX, &mClusterId);
AddArgument("attribute-id", 0, UINT32_MAX, &mAttributeId);
AddArgument("attribute-value", &mAttributeValue);
AddArgument("cluster-ids", 0, UINT32_MAX, &mClusterIds,
"Comma-separated list of cluster ids to write to (e.g. \"6\" or \"8,0x201\").");
AddArgument("attribute-ids", 0, UINT32_MAX, &mAttributeIds,
"Comma-separated list of attribute ids to write (e.g. \"0\" or \"1,0xFFFC,0xFFFD\").");
AddArgument("attribute-value", &mAttributeValues, "Comma-separated list of attribute values to write.");
AddArguments();
}

WriteAttribute(chip::ClusterId clusterId, CredentialIssuerCommands * credsIssuerConfig) :
InteractionModelWriter(this), ModelCommand("write-by-id", credsIssuerConfig), mClusterId(clusterId)
InteractionModelWriter(this), ModelCommand("write-by-id", credsIssuerConfig), mClusterIds(1, clusterId)
{
AddArgument("attribute-id", 0, UINT32_MAX, &mAttributeId);
AddArgument("attribute-value", &mAttributeValue);
AddArgument("attribute-ids", 0, UINT32_MAX, &mAttributeIds,
"Comma-separated list of attribute ids to write (e.g. \"0\" or \"1,0xFFFC,0xFFFD\").");
AddArgument("attribute-value", &mAttributeValues, "Comma-separated list of attribute values to write.");
AddArguments();
}

template <typename maxType>
WriteAttribute(chip::ClusterId clusterId, const char * attributeName, long long minValue, maxType maxValue,
chip::AttributeId attributeId, CredentialIssuerCommands * credsIssuerConfig) :
InteractionModelWriter(this),
ModelCommand("write", credsIssuerConfig), mClusterIds(1, clusterId), mAttributeIds(1, attributeId)
{
AddArgument("attribute-name", attributeName, "The attribute name to write.");
AddArgument("attribute-value", static_cast<int64_t>(minValue), static_cast<uint64_t>(maxValue), &mAttributeValues,
"The attribute value to write.");
AddArguments();
}

template <typename maxType>
WriteAttribute(chip::ClusterId clusterId, const char * attributeName, int minValue, maxType maxValue,
chip::AttributeId attributeId, CredentialIssuerCommands * credsIssuerConfig) :
InteractionModelWriter(this),
ModelCommand("write", credsIssuerConfig), mClusterIds(1, clusterId), mAttributeIds(1, attributeId)
{
AddArgument("attribute-name", attributeName, "The attribute name to write.");
AddArgument("attribute-value", static_cast<int64_t>(minValue), static_cast<uint64_t>(maxValue), &mAttributeValues,
"The attribute value to write.");
AddArguments();
}

WriteAttribute(chip::ClusterId clusterId, const char * attributeName, float minValue, float maxValue,
chip::AttributeId attributeId, CredentialIssuerCommands * credsIssuerConfig) :
InteractionModelWriter(this),
ModelCommand("write", credsIssuerConfig), mClusterIds(1, clusterId), mAttributeIds(1, attributeId)
{
AddArgument("attribute-name", attributeName, "The attribute name to write.");
AddArgument("attribute-value", minValue, maxValue, &mAttributeValues, "The attribute value to write.");
AddArguments();
}

WriteAttribute(chip::ClusterId clusterId, const char * attributeName, double minValue, double maxValue,
chip::AttributeId attributeId, CredentialIssuerCommands * credsIssuerConfig) :
InteractionModelWriter(this),
ModelCommand("write", credsIssuerConfig), mClusterIds(1, clusterId), mAttributeIds(1, attributeId)
{
AddArgument("attribute-name", attributeName, "The attribute name to write.");
AddArgument("attribute-value", minValue, maxValue, &mAttributeValues, "The attribute value to write.");
AddArguments();
}

WriteAttribute(chip::ClusterId clusterId, const char * attributeName, chip::AttributeId attributeId,
CredentialIssuerCommands * credsIssuerConfig) :
InteractionModelWriter(this),
ModelCommand("write", credsIssuerConfig), mClusterIds(1, clusterId), mAttributeIds(1, attributeId)
{
AddArgument("attribute-name", attributeName, "The attribute name to write.");
AddArgument("attribute-value", &mAttributeValues, "The attribute value to write.");
AddArguments();
}

WriteAttribute(chip::ClusterId clusterId, const char * attributeName, chip::AttributeId attributeId,
TypedComplexArgument<T> & attributeParser, CredentialIssuerCommands * credsIssuerConfig) :
InteractionModelWriter(this),
ModelCommand("write", credsIssuerConfig), mClusterIds(1, clusterId), mAttributeIds(1, attributeId)
{
attributeParser.SetArgument(&mAttributeValues);
AddArgument("attribute-name", attributeName, "The attribute name to write.");
AddArgument("attribute-value", &attributeParser, "The attribute value to write.");
AddArguments();
}

~WriteAttribute() {}

CHIP_ERROR SendCommand(chip::DeviceProxy * device, std::vector<chip::EndpointId> endpointIds) override
{
return WriteAttribute::SendCommand(device, endpointIds.at(0), mClusterId, mAttributeId, mAttributeValue);
return WriteAttribute::SendCommand(device, endpointIds, mClusterIds, mAttributeIds, mAttributeValues);
}

CHIP_ERROR SendGroupCommand(chip::GroupId groupId, chip::FabricIndex fabricIndex) override
{
return WriteAttribute::SendGroupCommand(groupId, fabricIndex, mClusterId, mAttributeId, mAttributeValue);
return WriteAttribute::SendGroupCommand(groupId, fabricIndex, mClusterIds, mAttributeIds, mAttributeValues);
}

/////////// WriteClient Callback Interface /////////
Expand All @@ -79,23 +148,27 @@ class WriteAttribute : public InteractionModelWriter, public ModelCommand, publi
SetCommandExitStatus(mError);
}

template <class T>
CHIP_ERROR SendCommand(chip::DeviceProxy * device, chip::EndpointId endpointId, chip::ClusterId clusterId,
chip::AttributeId attributeId, const T & value)
CHIP_ERROR SendCommand(chip::DeviceProxy * device, std::vector<chip::EndpointId> endpointIds,
std::vector<chip::ClusterId> clusterIds, std::vector<chip::AttributeId> attributeIds, const T & values)
{
ChipLogProgress(chipTool, "Sending WriteAttribute to cluster " ChipLogFormatMEI " on endpoint %u",
ChipLogValueMEI(clusterId), endpointId);
return InteractionModelWriter::WriteAttribute(device, endpointId, clusterId, attributeId, value, mTimedInteractionTimeoutMs,
mSuppressResponse, mDataVersion, mRepeatCount, mRepeatDelayInMs);
return InteractionModelWriter::WriteAttribute(device, endpointIds, clusterIds, attributeIds, values,
mTimedInteractionTimeoutMs, mSuppressResponse, mDataVersions, mRepeatCount,
mRepeatDelayInMs);
}

template <class T>
CHIP_ERROR SendGroupCommand(chip::GroupId groupId, chip::FabricIndex fabricIndex, chip::ClusterId clusterId,
chip::AttributeId attributeId, const T & value)
CHIP_ERROR SendGroupCommand(chip::GroupId groupId, chip::FabricIndex fabricIndex, std::vector<chip::ClusterId> clusterIds,
std::vector<chip::AttributeId> attributeIds, const T & value)
{
ChipLogDetail(chipTool, "Sending Write Attribute to Group %u, on Fabric %x, for cluster %u with attributeId %u", groupId,
fabricIndex, clusterId, attributeId);
return InteractionModelWriter::WriteGroupAttribute(groupId, fabricIndex, clusterId, attributeId, value, mDataVersion);
fabricIndex, clusterIds.at(0), attributeIds.at(0));
chip::Optional<chip::DataVersion> dataVersion = chip::NullOptional;
if (mDataVersions.HasValue())
{
dataVersion.SetValue(mDataVersions.Value().at(0));
}

return InteractionModelWriter::WriteGroupAttribute(groupId, fabricIndex, clusterIds.at(0), attributeIds.at(0), value,
dataVersion);
}

protected:
Expand All @@ -109,21 +182,37 @@ class WriteAttribute : public InteractionModelWriter, public ModelCommand, publi
{
AddArgument("timedInteractionTimeoutMs", 0, UINT16_MAX, &mTimedInteractionTimeoutMs,
"If provided, do a timed write with the given timed interaction timeout.");
AddArgument("data-version", 0, UINT32_MAX, &mDataVersion);
AddArgument("data-version", 0, UINT32_MAX, &mDataVersions,
"Comma-separated list of data versions for the clusters being written.");
AddArgument("suppressResponse", 0, 1, &mSuppressResponse);
AddArgument("repeat-count", 1, UINT16_MAX, &mRepeatCount);
AddArgument("repeat-delay-ms", 0, UINT16_MAX, &mRepeatDelayInMs);
ModelCommand::AddArguments();
}

private:
chip::ClusterId mClusterId;
chip::AttributeId mAttributeId;
std::vector<chip::ClusterId> mClusterIds;
std::vector<chip::AttributeId> mAttributeIds;

CHIP_ERROR mError = CHIP_NO_ERROR;
chip::Optional<uint16_t> mTimedInteractionTimeoutMs;
chip::Optional<chip::DataVersion> mDataVersion = chip::NullOptional;
chip::Optional<std::vector<chip::DataVersion>> mDataVersions;
chip::Optional<bool> mSuppressResponse;
CustomArgument mAttributeValue;
chip::Optional<uint16_t> mRepeatCount;
chip::Optional<uint16_t> mRepeatDelayInMs;

T mAttributeValues;
};

template <class T>
class WriteAttributeAsComplex : public WriteAttribute<T>
{
public:
WriteAttributeAsComplex(chip::ClusterId clusterId, const char * attributeName, chip::AttributeId attributeId,
CredentialIssuerCommands * credsIssuerConfig) :
WriteAttribute<T>(clusterId, attributeName, attributeId, mAttributeParser, credsIssuerConfig)
{}

private:
TypedComplexArgument<T> mAttributeParser;
};
51 changes: 9 additions & 42 deletions examples/chip-tool/templates/commands.zapt
Original file line number Diff line number Diff line change
Expand Up @@ -64,45 +64,6 @@ private:

{{/zcl_commands_source_client}}

{{#zcl_attributes_server}}
{{#if isWritable}}
class Write{{asUpperCamelCase parent.name}}{{asUpperCamelCase name}}: public WriteAttribute
{
public:
Write{{asUpperCamelCase parent.name}}{{asUpperCamelCase name}}(CredentialIssuerCommands * credsIssuerConfig): WriteAttribute("{{asUpperCamelCase name}}", credsIssuerConfig){{#if_chip_complex}}, mComplex(&mValue){{/if_chip_complex}}
{
AddArgument("attr-name", "{{asDelimitedCommand (asUpperCamelCase name)}}");
{{#if_chip_complex}}
AddArgument("attr-value", &mComplex);
{{else if (isString type)}}
AddArgument("attr-value", &mValue);
{{else}}
AddArgument("attr-value", {{asTypeMinValue type}}, {{asTypeMaxValue type}}, &mValue);
{{/if_chip_complex}}
WriteAttribute::AddArguments();
}

~Write{{asUpperCamelCase parent.name}}{{asUpperCamelCase name}}() {}

CHIP_ERROR SendCommand(chip::DeviceProxy * device, std::vector<chip::EndpointId> endpointIds) override
{
return WriteAttribute::SendCommand(device, endpointIds.at(0), {{asHex parent.code 8}}, {{asHex code 8}}, mValue);
}

CHIP_ERROR SendGroupCommand(chip::GroupId groupId, chip::FabricIndex fabricIndex) override
{
return WriteAttribute::SendGroupCommand(groupId, fabricIndex, {{asHex parent.code 8}}, {{asHex code 8}}, mValue);
}

private:
{{zapTypeToEncodableClusterObjectType type ns=parent.name forceNotOptional=true}} mValue;
{{#if_chip_complex}}
TypedComplexArgument<{{zapTypeToEncodableClusterObjectType type ns=parent.name forceNotOptional=true}}> mComplex;
{{/if_chip_complex}}
};

{{/if}}
{{/zcl_attributes_server}}
{{/zcl_clusters}}

/*----------------------------------------------------------------------------*\
Expand Down Expand Up @@ -130,10 +91,16 @@ void registerCluster{{asUpperCamelCase name}}(Commands & commands, CredentialIss
{{#zcl_attributes_server}}
make_unique<ReadAttribute>(Id, "{{asDelimitedCommand (asUpperCamelCase name)}}", Attributes::{{asUpperCamelCase name}}::Id, credsIssuerConfig), //
{{/zcl_attributes_server}}
make_unique<WriteAttribute>(Id, credsIssuerConfig), //
make_unique<WriteAttribute<>>(Id, credsIssuerConfig), //
{{#zcl_attributes_server}}
{{#if isWritable}}
make_unique<Write{{asUpperCamelCase parent.name}}{{asUpperCamelCase name}}>(credsIssuerConfig), //
{{#if_chip_complex}}
make_unique<WriteAttributeAsComplex<{{zapTypeToEncodableClusterObjectType type ns=parent.name forceNotOptional=true}}>>(Id, "{{asDelimitedCommand (asUpperCamelCase name)}}", Attributes::{{asUpperCamelCase name}}::Id, credsIssuerConfig), //
{{else if (isString type)}}
make_unique<WriteAttribute<{{zapTypeToEncodableClusterObjectType type ns=parent.name forceNotOptional=true}}>>(Id, "{{asDelimitedCommand (asUpperCamelCase name)}}", Attributes::{{asUpperCamelCase name}}::Id, credsIssuerConfig), //
{{else}}
make_unique<WriteAttribute<{{zapTypeToEncodableClusterObjectType type ns=parent.name forceNotOptional=true}}>>(Id, "{{asDelimitedCommand (asUpperCamelCase name)}}", {{asTypeMinValue type}}, {{asTypeMaxValue type}}, Attributes::{{asUpperCamelCase name}}::Id, credsIssuerConfig), //
{{/if_chip_complex}}
{{/if}}
{{/zcl_attributes_server}}
make_unique<SubscribeAttribute>(Id, credsIssuerConfig), //
Expand Down Expand Up @@ -166,7 +133,7 @@ void registerClusterAny(Commands & commands, CredentialIssuerCommands * credsIss
commands_list clusterCommands = {
make_unique<ClusterCommand>(credsIssuerConfig), //
make_unique<ReadAttribute>(credsIssuerConfig), //
make_unique<WriteAttribute>(credsIssuerConfig), //
make_unique<WriteAttribute<>>(credsIssuerConfig), //
make_unique<SubscribeAttribute>(credsIssuerConfig), //
make_unique<ReadEvent>(credsIssuerConfig), //
make_unique<SubscribeEvent>(credsIssuerConfig), //
Expand Down
Loading

0 comments on commit acd95fc

Please sign in to comment.