Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[chip-tool] Add force-write to allow writing to non-writable attributes #24788

Merged
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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