Skip to content

Commit

Permalink
[chip-tool] Add force-write to allow writing to non-writable attribut…
Browse files Browse the repository at this point in the history
…es (#24788)

* [chip-tool] Add write-override to allow writing to non-writable attributes

* Update generated chip-tool commands
  • Loading branch information
vivien-apple authored Feb 2, 2023
1 parent 624ba3b commit fc41449
Show file tree
Hide file tree
Showing 4 changed files with 2,967 additions and 739 deletions.
49 changes: 31 additions & 18 deletions examples/chip-tool/commands/clusters/WriteAttributeCommand.h
Original file line number Diff line number Diff line change
Expand Up @@ -23,12 +23,22 @@
#include "DataModelLogger.h"
#include "ModelCommand.h"

constexpr const char * kWriteCommandKey = "write";
constexpr const char * kWriteByIdCommandKey = "write-by-id";
constexpr const char * kForceWriteCommandKey = "force-write";

enum class WriteCommandType
{
kWrite, // regular, writable attributes
kForceWrite, // forced writes, send a write command on something expected to fail
};

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)
InteractionModelWriter(this), ModelCommand(kWriteByIdCommandKey, credsIssuerConfig)
{
AddArgumentClusterIds();
AddArgumentAttributeIds();
Expand All @@ -37,7 +47,7 @@ class WriteAttribute : public InteractionModelWriter, public ModelCommand, publi
}

WriteAttribute(chip::ClusterId clusterId, CredentialIssuerCommands * credsIssuerConfig) :
InteractionModelWriter(this), ModelCommand("write-by-id", credsIssuerConfig), mClusterIds(1, clusterId)
InteractionModelWriter(this), ModelCommand(kWriteByIdCommandKey, credsIssuerConfig), mClusterIds(1, clusterId)
{
AddArgumentAttributeIds();
AddArgumentAttributeValues();
Expand All @@ -46,44 +56,45 @@ class WriteAttribute : public InteractionModelWriter, public ModelCommand, publi

template <typename minType, typename maxType>
WriteAttribute(chip::ClusterId clusterId, const char * attributeName, minType minValue, maxType maxValue,
chip::AttributeId attributeId, CredentialIssuerCommands * credsIssuerConfig) :
WriteAttribute(clusterId, attributeId, credsIssuerConfig)
chip::AttributeId attributeId, WriteCommandType commandType, CredentialIssuerCommands * credsIssuerConfig) :
WriteAttribute(clusterId, attributeId, commandType, credsIssuerConfig)
{
AddArgumentAttributeName(attributeName);
AddArgumentAttributeValues(static_cast<int64_t>(minValue), static_cast<uint64_t>(maxValue));
AddArguments();
}

WriteAttribute(chip::ClusterId clusterId, const char * attributeName, float minValue, float maxValue,
chip::AttributeId attributeId, CredentialIssuerCommands * credsIssuerConfig) :
WriteAttribute(clusterId, attributeId, credsIssuerConfig)
chip::AttributeId attributeId, WriteCommandType commandType, CredentialIssuerCommands * credsIssuerConfig) :
WriteAttribute(clusterId, attributeId, commandType, credsIssuerConfig)
{
AddArgumentAttributeName(attributeName);
AddArgumentAttributeValues(minValue, maxValue);
AddArguments();
}

WriteAttribute(chip::ClusterId clusterId, const char * attributeName, double minValue, double maxValue,
chip::AttributeId attributeId, CredentialIssuerCommands * credsIssuerConfig) :
WriteAttribute(clusterId, attributeId, credsIssuerConfig)
chip::AttributeId attributeId, WriteCommandType commandType, CredentialIssuerCommands * credsIssuerConfig) :
WriteAttribute(clusterId, attributeId, commandType, credsIssuerConfig)
{
AddArgumentAttributeName(attributeName);
AddArgumentAttributeValues(minValue, maxValue);
AddArguments();
}

WriteAttribute(chip::ClusterId clusterId, const char * attributeName, chip::AttributeId attributeId,
CredentialIssuerCommands * credsIssuerConfig) :
WriteAttribute(clusterId, attributeId, credsIssuerConfig)
WriteCommandType commandType, CredentialIssuerCommands * credsIssuerConfig) :
WriteAttribute(clusterId, attributeId, commandType, credsIssuerConfig)
{
AddArgumentAttributeName(attributeName);
AddArgumentAttributeValues();
AddArguments();
}

WriteAttribute(chip::ClusterId clusterId, const char * attributeName, chip::AttributeId attributeId,
TypedComplexArgument<T> & attributeParser, CredentialIssuerCommands * credsIssuerConfig) :
WriteAttribute(clusterId, attributeId, credsIssuerConfig)
TypedComplexArgument<T> & attributeParser, WriteCommandType commandType,
CredentialIssuerCommands * credsIssuerConfig) :
WriteAttribute(clusterId, attributeId, commandType, credsIssuerConfig)
{
AddArgumentAttributeName(attributeName);
AddArgumentAttributeValues(attributeParser);
Expand Down Expand Up @@ -159,7 +170,7 @@ class WriteAttribute : public InteractionModelWriter, public ModelCommand, publi

protected:
WriteAttribute(const char * attributeName, CredentialIssuerCommands * credsIssuerConfig) :
InteractionModelWriter(this), ModelCommand("write", credsIssuerConfig)
InteractionModelWriter(this), ModelCommand(kWriteCommandKey, credsIssuerConfig)
{
// Subclasses are responsible for calling AddArguments.
}
Expand Down Expand Up @@ -244,9 +255,11 @@ class WriteAttribute : public InteractionModelWriter, public ModelCommand, publi

private:
// This constructor is private as it is not intended to be used from outside the class.
WriteAttribute(chip::ClusterId clusterId, chip::AttributeId attributeId, CredentialIssuerCommands * credsIssuerConfig) :
InteractionModelWriter(this), ModelCommand("write", credsIssuerConfig), mClusterIds(1, clusterId),
mAttributeIds(1, attributeId)
WriteAttribute(chip::ClusterId clusterId, chip::AttributeId attributeId, WriteCommandType commandType,
CredentialIssuerCommands * credsIssuerConfig) :
InteractionModelWriter(this),
ModelCommand(commandType == WriteCommandType::kWrite ? kWriteCommandKey : kForceWriteCommandKey, credsIssuerConfig),
mClusterIds(1, clusterId), mAttributeIds(1, attributeId)
{}

std::vector<chip::ClusterId> mClusterIds;
Expand All @@ -261,8 +274,8 @@ 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)
WriteCommandType commandType, CredentialIssuerCommands * credsIssuerConfig) :
WriteAttribute<T>(clusterId, attributeName, attributeId, mAttributeParser, commandType, credsIssuerConfig)
{}

private:
Expand Down
8 changes: 7 additions & 1 deletion examples/chip-tool/commands/common/Commands.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -267,7 +267,8 @@ Command * Commands::GetGlobalCommand(CommandsVector & commands, std::string comm

bool Commands::IsAttributeCommand(std::string commandName) const
{
return commandName.compare("read") == 0 || commandName.compare("write") == 0 || commandName.compare("subscribe") == 0;
return commandName.compare("read") == 0 || commandName.compare("write") == 0 || commandName.compare("force-write") == 0 ||
commandName.compare("subscribe") == 0;
}

bool Commands::IsEventCommand(std::string commandName) const
Expand Down Expand Up @@ -308,6 +309,7 @@ void Commands::ShowCluster(std::string executable, std::string clusterName, Comm
fprintf(stderr, " +-------------------------------------------------------------------------------------+\n");
bool readCommand = false;
bool writeCommand = false;
bool writeOverrideCommand = false;
bool subscribeCommand = false;
bool readEventCommand = false;
bool subscribeEventCommand = false;
Expand All @@ -325,6 +327,10 @@ void Commands::ShowCluster(std::string executable, std::string clusterName, Comm
{
writeCommand = true;
}
else if (strcmp(command->GetName(), "force-write") == 0 && !writeOverrideCommand)
{
writeOverrideCommand = true;
}
else if (strcmp(command->GetName(), "subscribe") == 0 && !subscribeCommand)
{
subscribeCommand = true;
Expand Down
10 changes: 3 additions & 7 deletions examples/chip-tool/templates/commands.zapt
Original file line number Diff line number Diff line change
Expand Up @@ -93,21 +93,17 @@ void registerCluster{{asUpperCamelCase name}}(Commands & commands, CredentialIss
{{/zcl_attributes_server}}
make_unique<WriteAttribute<>>(Id, credsIssuerConfig), //
{{#zcl_attributes_server}}
{{#if isWritable}}
{{#if_chip_complex}}
make_unique<WriteAttributeAsComplex<{{zapTypeToEncodableClusterObjectType type ns=parent.name forceNotOptional=true}}>>(Id, "{{cleanse_label_as_kebab_case (asUpperCamelCase name)}}", Attributes::{{asUpperCamelCase name}}::Id, credsIssuerConfig), //
make_unique<WriteAttributeAsComplex<{{zapTypeToEncodableClusterObjectType type ns=parent.name forceNotOptional=true}}>>(Id, "{{cleanse_label_as_kebab_case (asUpperCamelCase name)}}", Attributes::{{asUpperCamelCase name}}::Id, WriteCommandType::k{{#unless isWritable}}Force{{/unless}}Write, credsIssuerConfig), //
{{else if (isString type)}}
make_unique<WriteAttribute<{{zapTypeToEncodableClusterObjectType type ns=parent.name forceNotOptional=true}}>>(Id, "{{cleanse_label_as_kebab_case (asUpperCamelCase name)}}", Attributes::{{asUpperCamelCase name}}::Id, credsIssuerConfig), //
make_unique<WriteAttribute<{{zapTypeToEncodableClusterObjectType type ns=parent.name forceNotOptional=true}}>>(Id, "{{cleanse_label_as_kebab_case (asUpperCamelCase name)}}", Attributes::{{asUpperCamelCase name}}::Id, WriteCommandType::k{{#unless isWritable}}Force{{/unless}}Write, credsIssuerConfig), //
{{else}}
make_unique<WriteAttribute<{{zapTypeToEncodableClusterObjectType type ns=parent.name forceNotOptional=true}}>>(Id, "{{cleanse_label_as_kebab_case (asUpperCamelCase name)}}", {{as_type_min_value type language='c++'}}, {{as_type_max_value type language='c++'}}, Attributes::{{asUpperCamelCase name}}::Id, credsIssuerConfig), //
make_unique<WriteAttribute<{{zapTypeToEncodableClusterObjectType type ns=parent.name forceNotOptional=true}}>>(Id, "{{cleanse_label_as_kebab_case (asUpperCamelCase name)}}", {{as_type_min_value type language='c++'}}, {{as_type_max_value type language='c++'}}, Attributes::{{asUpperCamelCase name}}::Id, WriteCommandType::k{{#unless isWritable}}Force{{/unless}}Write, credsIssuerConfig), //
{{/if_chip_complex}}
{{/if}}
{{/zcl_attributes_server}}
make_unique<SubscribeAttribute>(Id, credsIssuerConfig), //
{{#zcl_attributes_server}}
{{#if isReportable}}
make_unique<SubscribeAttribute>(Id, "{{cleanse_label_as_kebab_case (asUpperCamelCase name)}}", Attributes::{{asUpperCamelCase name}}::Id, credsIssuerConfig), //
{{/if}}
{{/zcl_attributes_server}}
//
// Events
Expand Down
Loading

0 comments on commit fc41449

Please sign in to comment.