Skip to content

Commit

Permalink
Add the ability to print help text for clusters to chip-tool. (#26392)
Browse files Browse the repository at this point in the history
* Add the ability to print help text for clusters to chip-tool.

Also moves the "subscriptions" commands, which are not dependent on ZAP in any
way, out of generated stuff.

* Fix tv-casting-app build

* Also show help text in the cluster-specific help.
  • Loading branch information
bzbarsky-apple authored and pull[bot] committed Oct 11, 2023
1 parent a70e680 commit 3af0689
Show file tree
Hide file tree
Showing 7 changed files with 69 additions and 48 deletions.
4 changes: 2 additions & 2 deletions examples/chip-tool/commands/clusters/SubscriptionsCommands.h
Original file line number Diff line number Diff line change
Expand Up @@ -94,7 +94,7 @@ class ShutdownAllSubscriptions : public CHIPCommand
private:
};

void registerClusterSubscriptions(Commands & commands, CredentialIssuerCommands * credsIssuerConfig)
void registerCommandsSubscriptions(Commands & commands, CredentialIssuerCommands * credsIssuerConfig)
{
const char * clusterName = "Subscriptions";

Expand All @@ -104,5 +104,5 @@ void registerClusterSubscriptions(Commands & commands, CredentialIssuerCommands
make_unique<ShutdownAllSubscriptions>(credsIssuerConfig), //
};

commands.Register(clusterName, clusterCommands);
commands.Register(clusterName, clusterCommands, "Commands for shutting down subscriptions.");
}
92 changes: 55 additions & 37 deletions examples/chip-tool/commands/common/Commands.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -119,11 +119,12 @@ static void DetectAndLogMismatchedDoubleQuotes(int argc, char ** argv)

} // namespace

void Commands::Register(const char * clusterName, commands_list commandsList)
void Commands::Register(const char * clusterName, commands_list commandsList, const char * helpText)
{
mClusters[clusterName].second = helpText;
for (auto & command : commandsList)
{
mClusters[clusterName].push_back(std::move(command));
mClusters[clusterName].first.push_back(std::move(command));
}
}

Expand Down Expand Up @@ -186,7 +187,6 @@ int Commands::RunInteractive(const char * command)

CHIP_ERROR Commands::RunCommand(int argc, char ** argv, bool interactive)
{
std::map<std::string, CommandsVector>::iterator cluster;
Command * command = nullptr;

if (argc <= 1)
Expand All @@ -196,29 +196,32 @@ CHIP_ERROR Commands::RunCommand(int argc, char ** argv, bool interactive)
return CHIP_ERROR_INVALID_ARGUMENT;
}

cluster = GetCluster(argv[1]);
if (cluster == mClusters.end())
auto clusterIter = GetCluster(argv[1]);
if (clusterIter == mClusters.end())
{
ChipLogError(chipTool, "Unknown cluster: %s", argv[1]);
ShowClusters(argv[0]);
return CHIP_ERROR_INVALID_ARGUMENT;
}

auto & commandList = clusterIter->second.first;
auto * clusterHelp = clusterIter->second.second;

if (argc <= 2)
{
ChipLogError(chipTool, "Missing command name");
ShowCluster(argv[0], argv[1], cluster->second);
ShowCluster(argv[0], argv[1], commandList, clusterHelp);
return CHIP_ERROR_INVALID_ARGUMENT;
}

bool isGlobalCommand = IsGlobalCommand(argv[2]);
if (!isGlobalCommand)
{
command = GetCommand(cluster->second, argv[2]);
command = GetCommand(commandList, argv[2]);
if (command == nullptr)
{
ChipLogError(chipTool, "Unknown command: %s", argv[2]);
ShowCluster(argv[0], argv[1], cluster->second);
ShowCluster(argv[0], argv[1], commandList, clusterHelp);
return CHIP_ERROR_INVALID_ARGUMENT;
}
}
Expand All @@ -227,15 +230,15 @@ CHIP_ERROR Commands::RunCommand(int argc, char ** argv, bool interactive)
if (argc <= 3)
{
ChipLogError(chipTool, "Missing event name");
ShowClusterEvents(argv[0], argv[1], argv[2], cluster->second);
ShowClusterEvents(argv[0], argv[1], argv[2], commandList);
return CHIP_ERROR_INVALID_ARGUMENT;
}

command = GetGlobalCommand(cluster->second, argv[2], argv[3]);
command = GetGlobalCommand(commandList, argv[2], argv[3]);
if (command == nullptr)
{
ChipLogError(chipTool, "Unknown event: %s", argv[3]);
ShowClusterEvents(argv[0], argv[1], argv[2], cluster->second);
ShowClusterEvents(argv[0], argv[1], argv[2], commandList);
return CHIP_ERROR_INVALID_ARGUMENT;
}
}
Expand All @@ -244,15 +247,15 @@ CHIP_ERROR Commands::RunCommand(int argc, char ** argv, bool interactive)
if (argc <= 3)
{
ChipLogError(chipTool, "Missing attribute name");
ShowClusterAttributes(argv[0], argv[1], argv[2], cluster->second);
ShowClusterAttributes(argv[0], argv[1], argv[2], commandList);
return CHIP_ERROR_INVALID_ARGUMENT;
}

command = GetGlobalCommand(cluster->second, argv[2], argv[3]);
command = GetGlobalCommand(commandList, argv[2], argv[3]);
if (command == nullptr)
{
ChipLogError(chipTool, "Unknown attribute: %s", argv[3]);
ShowClusterAttributes(argv[0], argv[1], argv[2], cluster->second);
ShowClusterAttributes(argv[0], argv[1], argv[2], commandList);
return CHIP_ERROR_INVALID_ARGUMENT;
}
}
Expand All @@ -271,7 +274,7 @@ CHIP_ERROR Commands::RunCommand(int argc, char ** argv, bool interactive)
return interactive ? command->RunAsInteractive() : command->Run();
}

std::map<std::string, Commands::CommandsVector>::iterator Commands::GetCluster(std::string clusterName)
Commands::ClusterMap::iterator Commands::GetCluster(std::string clusterName)
{
for (auto & cluster : mClusters)
{
Expand Down Expand Up @@ -342,14 +345,21 @@ void Commands::ShowClusters(std::string executable)
std::transform(clusterName.begin(), clusterName.end(), clusterName.begin(),
[](unsigned char c) { return std::tolower(c); });
fprintf(stderr, " | * %-82s|\n", clusterName.c_str());
ShowHelpText(cluster.second.second);
}
fprintf(stderr, " +-------------------------------------------------------------------------------------+\n");
}

void Commands::ShowCluster(std::string executable, std::string clusterName, CommandsVector & commands)
void Commands::ShowCluster(std::string executable, std::string clusterName, CommandsVector & commands, const char * helpText)
{
fprintf(stderr, "Usage:\n");
fprintf(stderr, " %s %s command_name [param1 param2 ...]\n", executable.c_str(), clusterName.c_str());

if (helpText)
{
fprintf(stderr, "\n%s\n", helpText);
}

fprintf(stderr, "\n");
fprintf(stderr, " +-------------------------------------------------------------------------------------+\n");
fprintf(stderr, " | Commands: |\n");
Expand Down Expand Up @@ -399,23 +409,7 @@ void Commands::ShowCluster(std::string executable, std::string clusterName, Comm
if (shouldPrint)
{
fprintf(stderr, " | * %-82s|\n", command->GetName());
const char * helpText = command->GetHelpText();
if (command->GetHelpText())
{
// We leave 82 chars for command names. The help text starts
// two chars further to the right, so there are 80 chars left
// for it.
if (strlen(helpText) > 80)
{
// Add "..." at the end to indicate truncation, and only
// show the first 77 chars, since that's what will fit.
fprintf(stderr, " | - %.77s...|\n", helpText);
}
else
{
fprintf(stderr, " | - %-80s|\n", helpText);
}
}
ShowHelpText(command->GetHelpText());
}
}
fprintf(stderr, " +-------------------------------------------------------------------------------------+\n");
Expand Down Expand Up @@ -541,16 +535,18 @@ bool Commands::DecodeArgumentsFromBase64EncodedJson(const char * json, std::vect
auto commandName = jsonValue[kJsonCommandKey].asString();
auto arguments = jsonValue[kJsonArgumentsKey].asString();

auto cluster = GetCluster(clusterName);
VerifyOrReturnValue(cluster != mClusters.end(), false,
auto clusterIter = GetCluster(clusterName);
VerifyOrReturnValue(clusterIter != mClusters.end(), false,
ChipLogError(chipTool, "Cluster '%s' is not supported.", clusterName.c_str()));

auto command = GetCommand(cluster->second, commandName);
auto & commandList = clusterIter->second.first;

auto command = GetCommand(commandList, commandName);

if (jsonValue.isMember(kJsonCommandSpecifierKey) && IsGlobalCommand(commandName))
{
auto commandSpecifierName = jsonValue[kJsonCommandSpecifierKey].asString();
command = GetGlobalCommand(cluster->second, commandName, commandSpecifierName);
command = GetGlobalCommand(commandList, commandName, commandSpecifierName);
}
VerifyOrReturnValue(nullptr != command, false, ChipLogError(chipTool, "Unknown command."));

Expand Down Expand Up @@ -602,3 +598,25 @@ bool Commands::DecodeArgumentsFromStringStream(const char * command, std::vector

return true;
}

void Commands::ShowHelpText(const char * helpText)
{
if (helpText == nullptr)
{
return;
}

// We leave 82 chars for command/cluster names. The help text starts
// two chars further to the right, so there are 80 chars left
// for it.
if (strlen(helpText) > 80)
{
// Add "..." at the end to indicate truncation, and only
// show the first 77 chars, since that's what will fit.
fprintf(stderr, " | - %.77s...|\n", helpText);
}
else
{
fprintf(stderr, " | - %-80s|\n", helpText);
}
}
13 changes: 9 additions & 4 deletions examples/chip-tool/commands/common/Commands.h
Original file line number Diff line number Diff line change
Expand Up @@ -30,22 +30,24 @@ class Commands
public:
using CommandsVector = ::std::vector<std::unique_ptr<Command>>;

void Register(const char * clusterName, commands_list commandsList);
void Register(const char * clusterName, commands_list commandsList, const char * helpText = nullptr);
int Run(int argc, char ** argv);
int RunInteractive(const char * command);

private:
using ClusterMap = std::map<std::string, std::pair<CommandsVector, const char *>>;

CHIP_ERROR RunCommand(int argc, char ** argv, bool interactive = false);

std::map<std::string, CommandsVector>::iterator GetCluster(std::string clusterName);
ClusterMap::iterator GetCluster(std::string clusterName);
Command * GetCommand(CommandsVector & commands, std::string commandName);
Command * GetGlobalCommand(CommandsVector & commands, std::string commandName, std::string attributeName);
bool IsAttributeCommand(std::string commandName) const;
bool IsEventCommand(std::string commandName) const;
bool IsGlobalCommand(std::string commandName) const;

void ShowClusters(std::string executable);
void ShowCluster(std::string executable, std::string clusterName, CommandsVector & commands);
void ShowCluster(std::string executable, std::string clusterName, CommandsVector & commands, const char * helpText);
void ShowClusterAttributes(std::string executable, std::string clusterName, std::string commandName, CommandsVector & commands);
void ShowClusterEvents(std::string executable, std::string clusterName, std::string commandName, CommandsVector & commands);
void ShowCommand(std::string executable, std::string clusterName, Command * command);
Expand All @@ -54,7 +56,10 @@ class Commands
bool DecodeArgumentsFromBase64EncodedJson(const char * encodedData, std::vector<std::string> & args);
bool DecodeArgumentsFromStringStream(const char * command, std::vector<std::string> & args);

std::map<std::string, CommandsVector> mClusters;
// helpText may be null, in which case it's not shown.
static void ShowHelpText(const char * helpText);

ClusterMap mClusters;
#ifdef CONFIG_USE_LOCAL_STORAGE
PersistentStorage mStorage;
#endif // CONFIG_USE_LOCAL_STORAGE
Expand Down
2 changes: 2 additions & 0 deletions examples/chip-tool/main.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@
#include "commands/common/Commands.h"
#include "commands/example/ExampleCredentialIssuerCommands.h"

#include "commands/clusters/SubscriptionsCommands.h"
#include "commands/delay/Commands.h"
#include "commands/discover/Commands.h"
#include "commands/group/Commands.h"
Expand All @@ -45,6 +46,7 @@ int main(int argc, char * argv[])
registerCommandsTests(commands, &credIssuerCommands);
registerCommandsGroup(commands, &credIssuerCommands);
registerClusters(commands, &credIssuerCommands);
registerCommandsSubscriptions(commands, &credIssuerCommands);
registerCommandsStorage(commands);

return commands.Run(argc, argv);
Expand Down
2 changes: 0 additions & 2 deletions examples/chip-tool/templates/commands.zapt
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,6 @@
#include <commands/clusters/ComplexArgument.h>
#include <commands/clusters/ClusterCommand.h>
#include <commands/clusters/ReportCommand.h>
#include <commands/clusters/SubscriptionsCommands.h>
#include <commands/clusters/WriteAttributeCommand.h>

{{> clusters_header}}
Expand Down Expand Up @@ -146,5 +145,4 @@ void registerClusters(Commands & commands, CredentialIssuerCommands * credsIssue
{{#zcl_clusters}}
registerCluster{{asUpperCamelCase name}}(commands, credsIssuerConfig);
{{/zcl_clusters}}
registerClusterSubscriptions(commands, credsIssuerConfig);
}
2 changes: 1 addition & 1 deletion examples/tv-casting-app/linux/main.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -161,7 +161,7 @@ int main(int argc, char * argv[])
}

registerClusters(gCommands, &gCredIssuerCommands);
registerClusterSubscriptions(gCommands, &gCredIssuerCommands);
registerCommandsSubscriptions(gCommands, &gCredIssuerCommands);

if (argc > 1)
{
Expand Down
2 changes: 0 additions & 2 deletions zzz_generated/chip-tool/zap-generated/cluster/Commands.h

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

0 comments on commit 3af0689

Please sign in to comment.