From 47b8d4524a838fd6aa2f1c0a68153b67eff9be8f Mon Sep 17 00:00:00 2001 From: Damian Krolik Date: Sun, 3 Mar 2024 18:05:29 +0100 Subject: [PATCH] [shell] Reduce memory usage and boileplate code for subcommands 1. Add lightweight CommandSet class to prevent instantiating Shell::Engine, which allows for dynamic command registration, just to create a subshell with a fixed number of subcommands. This slightly reduces the RAM usage. Additionally, the command set automatically prints the help texts if no command or "help" command has been submitted. 2. Add SubShellCommand templatized command handler to remove the boilerplate associated with creating a subshell. --- src/lib/shell/BUILD.gn | 4 ++ src/lib/shell/Command.h | 62 ++++++++++++++++++++++ src/lib/shell/CommandSet.cpp | 52 ++++++++++++++++++ src/lib/shell/CommandSet.h | 58 ++++++++++++++++++++ src/lib/shell/Engine.h | 35 +----------- src/lib/shell/SubShellCommand.h | 58 ++++++++++++++++++++ src/lib/shell/commands/BLE.cpp | 38 +++---------- src/lib/shell/commands/Config.cpp | 50 +++++------------ src/lib/shell/commands/Device.cpp | 40 +++----------- src/lib/shell/commands/Dns.cpp | 60 ++++++--------------- src/lib/shell/commands/NFC.cpp | 10 ++-- src/lib/shell/commands/OnboardingCodes.cpp | 7 +-- src/lib/shell/commands/Ota.cpp | 28 ++-------- src/lib/shell/commands/Stat.cpp | 19 ++----- src/lib/shell/commands/WiFi.cpp | 28 ++-------- 15 files changed, 297 insertions(+), 252 deletions(-) create mode 100644 src/lib/shell/Command.h create mode 100644 src/lib/shell/CommandSet.cpp create mode 100644 src/lib/shell/CommandSet.h create mode 100644 src/lib/shell/SubShellCommand.h diff --git a/src/lib/shell/BUILD.gn b/src/lib/shell/BUILD.gn index 46981b83bb6bb0..8a9f6233a476f6 100644 --- a/src/lib/shell/BUILD.gn +++ b/src/lib/shell/BUILD.gn @@ -20,9 +20,13 @@ import("${chip_root}/src/platform/device.gni") source_set("shell_core") { sources = [ + "Command.h", + "CommandSet.cpp", + "CommandSet.h", "Commands.h", "Engine.cpp", "Engine.h", + "SubShellCommand.h", "streamer.cpp", "streamer.h", ] diff --git a/src/lib/shell/Command.h b/src/lib/shell/Command.h new file mode 100644 index 00000000000000..0b4e3002e38d34 --- /dev/null +++ b/src/lib/shell/Command.h @@ -0,0 +1,62 @@ +/* + * Copyright (c) 2024 Project CHIP Authors + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#pragma once + +#include + +namespace chip { +namespace Shell { + +/** + * Shell command descriptor structure. + * + * Typically a set of commands is defined as an array of this structure and registered + * at the shell root using the @c Shell::Engine::Root().RegisterCommands() method, or + * used to construct a @c CommandSet. + * + * Usage example: + * + * @code + * static Shell::Command cmds[] = { + * { &cmd_echo, "echo", "Echo back provided inputs" }, + * { &cmd_exit, "exit", "Exit the shell application" }, + * { &cmd_help, "help", "List out all top level commands" }, + * { &cmd_version, "version", "Output the software version" }, + * }; + * @endcode + */ +struct Command +{ + /** + * Shell command handler function type. + * + * @param argc Number of arguments in argv. + * @param argv Array of arguments in the tokenized command line to execute. + */ + using Handler = CHIP_ERROR (*)(int argc, char * argv[]); + + Handler cmd_func; + const char * cmd_name; + const char * cmd_help; +}; + +// DEPRECATED: +// shell_command_t is used in many examples, so keep it for backwards compatibility +using shell_command_t = const Command; + +} // namespace Shell +} // namespace chip diff --git a/src/lib/shell/CommandSet.cpp b/src/lib/shell/CommandSet.cpp new file mode 100644 index 00000000000000..7a6efd9db467da --- /dev/null +++ b/src/lib/shell/CommandSet.cpp @@ -0,0 +1,52 @@ +/* + * Copyright (c) 2024 Project CHIP Authors + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include +#include +#include + +namespace chip { +namespace Shell { + +CHIP_ERROR CommandSet::ExecCommand(int argc, char * argv[]) const +{ + if (argc == 0 || strcmp(argv[0], "help") == 0) + { + ShowHelp(); + return CHIP_NO_ERROR; + } + + for (const Command & command : mCommands) + { + if (strcmp(argv[0], command.cmd_name) == 0) + { + return command.cmd_func(argc - 1, argv + 1); + } + } + + return CHIP_ERROR_INVALID_ARGUMENT; +} + +void CommandSet::ShowHelp() const +{ + for (const Command & command : mCommands) + { + streamer_printf(streamer_get(), " %-15s %s\r\n", command.cmd_name, command.cmd_help); + } +} + +} // namespace Shell +} // namespace chip diff --git a/src/lib/shell/CommandSet.h b/src/lib/shell/CommandSet.h new file mode 100644 index 00000000000000..eef0b69180f8dd --- /dev/null +++ b/src/lib/shell/CommandSet.h @@ -0,0 +1,58 @@ +/* + * Copyright (c) 2024 Project CHIP Authors + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#pragma once + +#include +#include + +namespace chip { +namespace Shell { + +/** + * Shell command set. + * + * The shell command set is a thin wrapper for the span of commands. + * It facilitates executing a matching shell command for the given input arguments. + */ +class CommandSet +{ +public: + template + constexpr CommandSet(const Command (&commands)[N]) : mCommands(commands) + {} + + /** + * Dispatch and execute the command for the given argument list. + * + * The first argument is used to select the command to be executed and + * the remaining arguments are forwarded to the command's handler. + * If no argument has been provided or the first argument is "help", then + * the function prints help text for each command and returns no error. + * + * @param argc Number of arguments in argv. + * @param argv Array of arguments in the tokenized command line to execute. + */ + CHIP_ERROR ExecCommand(int argc, char * argv[]) const; + +private: + void ShowHelp() const; + + Span mCommands; +}; + +} // namespace Shell +} // namespace chip diff --git a/src/lib/shell/Engine.h b/src/lib/shell/Engine.h index be65ed45c94dc0..a0d7cfa6fa71fe 100644 --- a/src/lib/shell/Engine.h +++ b/src/lib/shell/Engine.h @@ -26,6 +26,7 @@ #include "streamer.h" #include +#include #include #include @@ -49,40 +50,6 @@ namespace chip { namespace Shell { -/** - * Callback to execute an individual shell command. - * - * @param argc Number of arguments passed. - * @param argv Array of option strings. The command name is not included. - * - * @return 0 on success; CHIP_ERROR[...] on failure. - */ -typedef CHIP_ERROR shell_command_fn(int argc, char * argv[]); - -/** - * Descriptor structure for a single command. - * - * Typically a set of commands are defined as an array of this structure - * and passed to the `shell_register()` during application initialization. - * - * An example command set definition follows: - * - * static shell_command_t cmds[] = { - * { &cmd_echo, "echo", "Echo back provided inputs" }, - * { &cmd_exit, "exit", "Exit the shell application" }, - * { &cmd_help, "help", "List out all top level commands" }, - * { &cmd_version, "version", "Output the software version" }, - * }; - */ -struct shell_command -{ - shell_command_fn * cmd_func; - const char * cmd_name; - const char * cmd_help; -}; - -typedef const struct shell_command shell_command_t; - /** * Execution callback for a shell command. * diff --git a/src/lib/shell/SubShellCommand.h b/src/lib/shell/SubShellCommand.h new file mode 100644 index 00000000000000..2f5008a2407b93 --- /dev/null +++ b/src/lib/shell/SubShellCommand.h @@ -0,0 +1,58 @@ +/* + * Copyright (c) 2024 Project CHIP Authors + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#pragma once + +#include + +namespace chip { +namespace Shell { + +/** + * Templatized shell command handler that runs one of the provided subcommands. + * + * The array of subcommands is provided as a non-type template parameter. + * + * The first argument is used to select the subcommand to be executed and + * the remaining arguments are forwarded to the subcommand's handler. + * If no argument has been provided or the first argument is "help", then + * the function prints help text for each subcommand and returns no error. + * + * Usage example: + * @code + * constexpr Command subCommands[3] = { + * {handler_a, "cmd_a", "command a help text"}, + * {handler_b, "cmd_b", "command b help text"}, + * {handler_c, "cmd_c", "command c help text"}, + * }; + * + * // Execute the matching subcommand + * SubShellCommand<3, subCommands>(argc, argv); + * @endcode + * + * @param argc Number of arguments in argv. + * @param argv Array of arguments in the tokenized command line to execute. + */ +template +inline CHIP_ERROR SubShellCommand(int argc, char ** argv) +{ + static constexpr CommandSet commandSet(C); + + return commandSet.ExecCommand(argc, argv); +} + +} // namespace Shell +} // namespace chip diff --git a/src/lib/shell/commands/BLE.cpp b/src/lib/shell/commands/BLE.cpp index f12c2101561b6d..9647f7fc5c6f3e 100644 --- a/src/lib/shell/commands/BLE.cpp +++ b/src/lib/shell/commands/BLE.cpp @@ -21,7 +21,7 @@ #include #endif #include -#include +#include #include #include #include @@ -31,21 +31,12 @@ using chip::DeviceLayer::ConnectivityMgr; namespace chip { namespace Shell { -static chip::Shell::Engine sShellDeviceSubcommands; - -CHIP_ERROR BLEHelpHandler(int argc, char ** argv) -{ - sShellDeviceSubcommands.ForEachCommand(PrintCommandHelp, nullptr); - return CHIP_NO_ERROR; -} - CHIP_ERROR BLEAdvertiseHandler(int argc, char ** argv) { - CHIP_ERROR error = CHIP_NO_ERROR; streamer_t * sout = streamer_get(); bool adv_enabled; - VerifyOrReturnError(argc == 1, error = CHIP_ERROR_INVALID_ARGUMENT); + VerifyOrReturnError(argc == 1, CHIP_ERROR_INVALID_ARGUMENT); adv_enabled = ConnectivityMgr().IsBLEAdvertisingEnabled(); if (strcmp(argv[0], "start") == 0) @@ -86,33 +77,18 @@ CHIP_ERROR BLEAdvertiseHandler(int argc, char ** argv) return CHIP_ERROR_INVALID_ARGUMENT; } - return error; -} - -CHIP_ERROR BLEDispatch(int argc, char ** argv) -{ - if (argc == 0) - { - BLEHelpHandler(argc, argv); - return CHIP_NO_ERROR; - } - return sShellDeviceSubcommands.ExecCommand(argc, argv); + return CHIP_NO_ERROR; } void RegisterBLECommands() { - static const shell_command_t sBLESubCommands[] = { - { &BLEHelpHandler, "help", "Usage: ble " }, - { &BLEAdvertiseHandler, "adv", "Enable or disable advertisement. Usage: ble adv " }, + static constexpr Command subCommands[] = { + { &BLEAdvertiseHandler, "adv", "Manage BLE advertising. Usage: ble adv " }, }; - static const shell_command_t sBLECommand = { &BLEDispatch, "ble", "BLE transport commands" }; - - // Register `device` subcommands with the local shell dispatcher. - sShellDeviceSubcommands.RegisterCommands(sBLESubCommands, ArraySize(sBLESubCommands)); + static constexpr Command bleCommand = { &SubShellCommand, "ble", "Bluetooth LE commands" }; - // Register the root `btp` command with the top-level shell. - Engine::Root().RegisterCommands(&sBLECommand, 1); + Engine::Root().RegisterCommands(&bleCommand, 1); } } // namespace Shell diff --git a/src/lib/shell/commands/Config.cpp b/src/lib/shell/commands/Config.cpp index ae1274a599bb16..e1452f9b35ba67 100644 --- a/src/lib/shell/commands/Config.cpp +++ b/src/lib/shell/commands/Config.cpp @@ -17,9 +17,9 @@ #include #include +#include #include #include -#include #include #include #include @@ -28,19 +28,9 @@ #include #include -using chip::DeviceLayer::ConfigurationMgr; - namespace chip { namespace Shell { -static chip::Shell::Engine sShellConfigSubcommands; - -CHIP_ERROR ConfigHelpHandler(int argc, char ** argv) -{ - sShellConfigSubcommands.ForEachCommand(PrintCommandHelp, nullptr); - return CHIP_NO_ERROR; -} - static CHIP_ERROR ConfigGetVendorId(bool printHeader) { streamer_t * sout = streamer_get(); @@ -182,28 +172,7 @@ static CHIP_ERROR PrintAllConfigs() static CHIP_ERROR ConfigHandler(int argc, char ** argv) { - switch (argc) - { - case 0: - return PrintAllConfigs(); - case 1: - if ((strcmp(argv[0], "help") == 0) || (strcmp(argv[0], "-h") == 0)) - { - return ConfigHelpHandler(argc, argv); - } - } - return sShellConfigSubcommands.ExecCommand(argc, argv); -} - -void RegisterConfigCommands() -{ - - static const shell_command_t sConfigComand = { &ConfigHandler, "config", - "Manage device configuration. Usage to dump value: config [param_name] and " - "to set some values (discriminator): config [param_name] [param_value]." }; - - static const shell_command_t sConfigSubCommands[] = { - { &ConfigHelpHandler, "help", "Usage: config " }, + static constexpr Command subCommands[] = { { &ConfigVendorId, "vendorid", "Get VendorId. Usage: config vendorid" }, { &ConfigProductId, "productid", "Get ProductId. Usage: config productid" }, { &ConfigHardwareVersion, "hardwarever", "Get HardwareVersion. Usage: config hardwarever" }, @@ -211,11 +180,18 @@ void RegisterConfigCommands() { &ConfigDiscriminator, "discriminator", "Get/Set commissioning discriminator. Usage: config discriminator [value]" }, }; - // Register `config` subcommands with the local shell dispatcher. - sShellConfigSubcommands.RegisterCommands(sConfigSubCommands, ArraySize(sConfigSubCommands)); + static constexpr CommandSet subShell(subCommands); + + return argc ? subShell.ExecCommand(argc, argv) : PrintAllConfigs(); +} + +void RegisterConfigCommands() +{ + static constexpr Command configCommand = { &ConfigHandler, "config", + "Manage device configuration. Usage to dump value: config [param_name] and " + "to set some values (discriminator): config [param_name] [param_value]." }; - // Register the root `config` command with the top-level shell. - Engine::Root().RegisterCommands(&sConfigComand, 1); + Engine::Root().RegisterCommands(&configCommand, 1); } } // namespace Shell diff --git a/src/lib/shell/commands/Device.cpp b/src/lib/shell/commands/Device.cpp index 7e26a75a5c32fb..de11f4d2e7a25d 100644 --- a/src/lib/shell/commands/Device.cpp +++ b/src/lib/shell/commands/Device.cpp @@ -15,30 +15,15 @@ * limitations under the License. */ -#include #include -#if CONFIG_DEVICE_LAYER -#include -#endif #include -#include -#include -#include +#include #include - -using chip::DeviceLayer::ConnectivityMgr; +#include namespace chip { namespace Shell { -static chip::Shell::Engine sShellDeviceSubcommands; - -int DeviceHelpHandler(int argc, char ** argv) -{ - sShellDeviceSubcommands.ForEachCommand(PrintCommandHelp, nullptr); - return 0; -} - static CHIP_ERROR FactoryResetHandler(int argc, char ** argv) { streamer_printf(streamer_get(), "Performing factory reset ... \r\n"); @@ -46,29 +31,16 @@ static CHIP_ERROR FactoryResetHandler(int argc, char ** argv) return CHIP_NO_ERROR; } -static CHIP_ERROR DeviceHandler(int argc, char ** argv) -{ - if (argc == 0) - { - DeviceHelpHandler(argc, argv); - return CHIP_NO_ERROR; - } - return sShellDeviceSubcommands.ExecCommand(argc, argv); -} - void RegisterDeviceCommands() { - static const shell_command_t sDeviceSubCommands[] = { + static constexpr Command subCommands[] = { { &FactoryResetHandler, "factoryreset", "Performs device factory reset" }, }; - static const shell_command_t sDeviceComand = { &DeviceHandler, "device", "Device management commands" }; - - // Register `device` subcommands with the local shell dispatcher. - sShellDeviceSubcommands.RegisterCommands(sDeviceSubCommands, ArraySize(sDeviceSubCommands)); + static constexpr Command deviceComand = { &SubShellCommand, "device", + "Device management commands" }; - // Register the root `device` command with the top-level shell. - Engine::Root().RegisterCommands(&sDeviceComand, 1); + Engine::Root().RegisterCommands(&deviceComand, 1); } } // namespace Shell diff --git a/src/lib/shell/commands/Dns.cpp b/src/lib/shell/commands/Dns.cpp index c6a93657ca7440..65b3f7bc9cc537 100644 --- a/src/lib/shell/commands/Dns.cpp +++ b/src/lib/shell/commands/Dns.cpp @@ -19,13 +19,12 @@ #include #include #include -#include #include #include #include #include #include -#include +#include #include #include #include @@ -36,8 +35,6 @@ namespace Shell { namespace { -Shell::Engine sShellDnsBrowseSubcommands; -Shell::Engine sShellDnsSubcommands; Dnssd::ResolverProxy sResolverProxy; class DnsShellResolverDelegate : public Dnssd::DiscoverNodeDelegate, public AddressResolve::NodeListener @@ -232,6 +229,9 @@ CHIP_ERROR BrowseCommissionableHandler(int argc, char ** argv) streamer_printf(streamer_get(), "Browsing commissionable nodes...\r\n"); + sResolverProxy.Init(DeviceLayer::UDPEndPointManager()); + sResolverProxy.SetDiscoveryDelegate(&sDnsShellResolverDelegate); + return sResolverProxy.DiscoverCommissionableNodes(filter); } @@ -242,6 +242,9 @@ CHIP_ERROR BrowseCommissionerHandler(int argc, char ** argv) streamer_printf(streamer_get(), "Browsing commissioners...\r\n"); + sResolverProxy.Init(DeviceLayer::UDPEndPointManager()); + sResolverProxy.SetDiscoveryDelegate(&sDnsShellResolverDelegate); + return sResolverProxy.DiscoverCommissioners(filter); } @@ -252,63 +255,32 @@ CHIP_ERROR BrowseOperationalHandler(int argc, char ** argv) streamer_printf(streamer_get(), "Browsing operational...\r\n"); - return sResolverProxy.DiscoverOperationalNodes(filter); -} - -CHIP_ERROR BrowseHandler(int argc, char ** argv) -{ - if (argc == 0) - { - sShellDnsBrowseSubcommands.ForEachCommand(PrintCommandHelp, nullptr); - return CHIP_NO_ERROR; - } - sResolverProxy.Init(DeviceLayer::UDPEndPointManager()); sResolverProxy.SetDiscoveryDelegate(&sDnsShellResolverDelegate); - return sShellDnsBrowseSubcommands.ExecCommand(argc, argv); -} - -CHIP_ERROR DnsHandler(int argc, char ** argv) -{ - if (argc == 0) - { - sShellDnsSubcommands.ForEachCommand(PrintCommandHelp, nullptr); - return CHIP_NO_ERROR; - } - - return sShellDnsSubcommands.ExecCommand(argc, argv); + return sResolverProxy.DiscoverOperationalNodes(filter); } } // namespace void RegisterDnsCommands() { - static const shell_command_t sDnsBrowseSubCommands[] = { + static constexpr Command browseSubCommands[] = { { &BrowseCommissionableHandler, "commissionable", - "Browse Matter commissionable nodes. Usage: dns browse commissionable [subtype]" }, - { &BrowseCommissionerHandler, "commissioner", - "Browse Matter commissioner nodes. Usage: dns browse commissioner [subtype]" }, + "Browse Matter commissionables. Usage: dns browse commissionable [subtype]" }, + { &BrowseCommissionerHandler, "commissioner", "Browse Matter commissioners. Usage: dns browse commissioner [subtype]" }, { &BrowseOperationalHandler, "operational", "Browse Matter operational nodes. Usage: dns browse operational" }, }; - static const shell_command_t sDnsSubCommands[] = { + static constexpr Command subCommands[] = { { &ResolveHandler, "resolve", - "Resolve the DNS service. Usage: dns resolve (e.g. dns resolve 5544332211 1)" }, - { &BrowseHandler, "browse", - "Browse DNS services published by Matter nodes. Usage: dns browse " }, + "Resolve Matter operational service. Usage: dns resolve fabricid nodeid (e.g. dns resolve 5544332211 1)" }, + { &SubShellCommand, "browse", "Browse Matter DNS services" }, }; - static const shell_command_t sDnsCommand = { &DnsHandler, "dns", "Dns client commands" }; - - // Register `dns browse` subcommands - sShellDnsBrowseSubcommands.RegisterCommands(sDnsBrowseSubCommands, ArraySize(sDnsBrowseSubCommands)); - - // Register `dns` subcommands with the local shell dispatcher. - sShellDnsSubcommands.RegisterCommands(sDnsSubCommands, ArraySize(sDnsSubCommands)); + static constexpr Command dnsCommand = { &SubShellCommand, "dns", "DNS client commands" }; - // Register the root `dns` command with the top-level shell. - Engine::Root().RegisterCommands(&sDnsCommand, 1); + Engine::Root().RegisterCommands(&dnsCommand, 1); } } // namespace Shell diff --git a/src/lib/shell/commands/NFC.cpp b/src/lib/shell/commands/NFC.cpp index 23b745b1901b90..78d2cc841b66df 100644 --- a/src/lib/shell/commands/NFC.cpp +++ b/src/lib/shell/commands/NFC.cpp @@ -22,9 +22,6 @@ #endif #include #include -#include -#include -#include #include using chip::DeviceLayer::ConnectivityMgr; @@ -86,11 +83,10 @@ static CHIP_ERROR NFCHandler(int argc, char ** argv) void RegisterNFCCommands() { - static const shell_command_t sDeviceComand = { &NFCHandler, "nfc", - "Start, stop or get nfc emulation state. Usage: nfc " }; + static constexpr Command nfcComand = { &NFCHandler, "nfc", + "Start, stop or get nfc emulation state. Usage: nfc " }; - // Register the root `device` command with the top-level shell. - Engine::Root().RegisterCommands(&sDeviceComand, 1); + Engine::Root().RegisterCommands(&nfcComand, 1); } } // namespace Shell diff --git a/src/lib/shell/commands/OnboardingCodes.cpp b/src/lib/shell/commands/OnboardingCodes.cpp index 1ecb791904280b..1e17812d183a3f 100644 --- a/src/lib/shell/commands/OnboardingCodes.cpp +++ b/src/lib/shell/commands/OnboardingCodes.cpp @@ -20,7 +20,6 @@ #include #include #include -#include #include #include #include @@ -170,14 +169,12 @@ static CHIP_ERROR OnboardingHandler(int argc, char ** argv) void RegisterOnboardingCodesCommands() { - - static const shell_command_t sDeviceComand = { + static constexpr Command deviceComand = { &OnboardingHandler, "onboardingcodes", "Dump device onboarding codes. Usage: onboardingcodes none|softap|ble|onnetwork [qrcode|qrcodeurl|manualpairingcode]" }; - // Register the root `device` command with the top-level shell. - Engine::Root().RegisterCommands(&sDeviceComand, 1); + Engine::Root().RegisterCommands(&deviceComand, 1); } } // namespace Shell diff --git a/src/lib/shell/commands/Ota.cpp b/src/lib/shell/commands/Ota.cpp index 729d1b9b059466..2be0619151e2d0 100644 --- a/src/lib/shell/commands/Ota.cpp +++ b/src/lib/shell/commands/Ota.cpp @@ -19,7 +19,7 @@ #include #include #include -#include +#include #include using namespace chip::DeviceLayer; @@ -28,8 +28,6 @@ namespace chip { namespace Shell { namespace { -Shell::Engine sSubShell; - CHIP_ERROR QueryImageHandler(int argc, char ** argv) { VerifyOrReturnError(GetRequestorInstance() != nullptr, CHIP_ERROR_INCORRECT_STATE); @@ -96,31 +94,15 @@ CHIP_ERROR ProgressHandler(int argc, char ** argv) return CHIP_NO_ERROR; } -CHIP_ERROR OtaHandler(int argc, char ** argv) -{ - if (argc == 0) - { - sSubShell.ForEachCommand(PrintCommandHelp, nullptr); - return CHIP_NO_ERROR; - } - - return sSubShell.ExecCommand(argc, argv); -} } // namespace void RegisterOtaCommands() { - // Register subcommands of the `ota` commands. - static const shell_command_t subCommands[] = { - { &QueryImageHandler, "query", "Query for a new image. Usage: ota query" }, - { &StateHandler, "state", "Gets state of a current image update process. Usage: ota state" }, - { &ProgressHandler, "progress", "Gets progress of a current image update process. Usage: ota progress" } - }; - - sSubShell.RegisterCommands(subCommands, ArraySize(subCommands)); + static constexpr Command subCommands[] = { { &QueryImageHandler, "query", "Query for a new image" }, + { &StateHandler, "state", "Get current image update state" }, + { &ProgressHandler, "progress", "Get current image update progress" } }; - // Register the root `ota` command in the top-level shell. - static const shell_command_t otaCommand = { &OtaHandler, "ota", "OTA commands" }; + static constexpr Command otaCommand = { &SubShellCommand, "ota", "OTA commands" }; Engine::Root().RegisterCommands(&otaCommand, 1); } diff --git a/src/lib/shell/commands/Stat.cpp b/src/lib/shell/commands/Stat.cpp index 88262e1e8daa1a..cf1799c8a71db8 100644 --- a/src/lib/shell/commands/Stat.cpp +++ b/src/lib/shell/commands/Stat.cpp @@ -16,6 +16,7 @@ #include #include +#include #include #include #include @@ -35,8 +36,6 @@ namespace chip { namespace Shell { namespace { -Shell::Engine sSubShell; - CHIP_ERROR StatPeakHandler(int argc, char ** argv) { auto labels = System::Stats::GetStrings(); @@ -88,24 +87,16 @@ CHIP_ERROR StatResetHandler(int argc, char ** argv) return CHIP_NO_ERROR; } -CHIP_ERROR StatHandler(int argc, char ** argv) -{ - return sSubShell.ExecCommand(argc, argv); -} } // namespace void RegisterStatCommands() { - // Register subcommands of the `stat` commands. - static const shell_command_t subCommands[] = { - { &StatPeakHandler, "peak", "Print peak usage of system resources. Usage: stat peak" }, - { &StatResetHandler, "reset", "Reset peak usage of system resources. Usage: stat reset" }, + static constexpr Command subCommands[] = { + { &StatPeakHandler, "peak", "Print peak usage of system resources" }, + { &StatResetHandler, "reset", "Reset peak usage of system resources" }, }; - sSubShell.RegisterCommands(subCommands, ArraySize(subCommands)); - - // Register the root `stat` command in the top-level shell. - static const shell_command_t statCommand = { &StatHandler, "stat", "Statistics commands" }; + static constexpr Command statCommand = { &SubShellCommand, "stat", "Statistics commands" }; Engine::Root().RegisterCommands(&statCommand, 1); } diff --git a/src/lib/shell/commands/WiFi.cpp b/src/lib/shell/commands/WiFi.cpp index 35ab5e26ae23a2..f2076a72decdba 100644 --- a/src/lib/shell/commands/WiFi.cpp +++ b/src/lib/shell/commands/WiFi.cpp @@ -17,7 +17,7 @@ #include #include -#include +#include #include #include #include @@ -32,15 +32,8 @@ using namespace chip::DeviceLayer::NetworkCommissioning; namespace chip { namespace Shell { -static Shell::Engine sShellWiFiSubCommands; static DeviceLayer::NetworkCommissioning::WiFiDriver * sDriver; -static CHIP_ERROR WiFiHelpHandler(int argc, char ** argv) -{ - sShellWiFiSubCommands.ForEachCommand(PrintCommandHelp, nullptr); - return CHIP_NO_ERROR; -} - static CHIP_ERROR PrintWiFiMode() { streamer_t * sout = streamer_get(); @@ -143,15 +136,6 @@ static CHIP_ERROR WiFiDisconnectHandler(int argc, char ** argv) return ConnectivityMgr().DisconnectNetwork(); } -static CHIP_ERROR WiFiDispatch(int argc, char ** argv) -{ - if (argc == 0) - { - return WiFiHelpHandler(argc, argv); - } - return sShellWiFiSubCommands.ExecCommand(argc, argv); -} - void SetWiFiDriver(WiFiDriver * driver) { sDriver = driver; @@ -164,17 +148,15 @@ WiFiDriver * GetWiFiDriver() void RegisterWiFiCommands() { - /// Subcommands for root command: `device ` - static const shell_command_t sWiFiSubCommands[] = { - { &WiFiHelpHandler, "help", "" }, + static constexpr Command subCommands[] = { { &WiFiModeHandler, "mode", "Get/Set wifi mode. Usage: wifi mode [disable|ap|sta]" }, { &WiFiConnectHandler, "connect", "Connect to AP. Usage: wifi connect " }, { &WiFiDisconnectHandler, "disconnect", "Disconnect device from AP. Usage: wifi disconnect" }, }; - static const shell_command_t sWiFiCommand = { &WiFiDispatch, "wifi", "Usage: wifi " }; - sShellWiFiSubCommands.RegisterCommands(sWiFiSubCommands, ArraySize(sWiFiSubCommands)); - Engine::Root().RegisterCommands(&sWiFiCommand, 1); + static constexpr Command wifiCommand = { &SubShellCommand, "wifi", "Wi-Fi commands" }; + + Engine::Root().RegisterCommands(&wifiCommand, 1); } } // namespace Shell