The Trident Zigbee Command Line Interface (CLI) provides a way to interact with a device through a hierarchical, table driven, extensible interface. Many CLI commands are pre-defined for the Zigbee stack and for the services and ZCL plugins. Custom, user defined tables can easily be created to add project specific CLI functionality.
The most common physical interface for the CLI is through a UART, but there are other ways of capturing character strings and passing them to the CLI for parsing. One of these is the Trident Zigbee Remote CLI manufacturer specific cluster. This allows remote interaction with the CLI on a specific device through the Zigbee network rather than with a physical UART connection.
The CLI is based on standard argc
and argv
parsing as well as optarg
. argc
is an integer that contains the count of the space delimited arguments passed to the CLI parser, and argv
is an array of char
strings, with each element being an argument. For example, the string "this is a test"
will result in argc == 4
, and argv
being
Arg Parsing | |
---|---|
argv[0] | "this" |
argv[1] | "is" |
argv[2] | "a" |
argv[3] | "test" |
optarg
allows parsing of command arguments. The CLI uses the short form of options to keep command strings as short as possible. A command with an option will look like "send -a 0x1234"
. In this case, the command is "send"
, "-a"
is an option, and 0x1234
is the argument for the "-a"
option. Not all commands require options, and many commands have optional options. Also, not all command options require arguments.
Existing commands will provide a "usage" help string if they are missing required options or if the -h
option is provided. Here is the usage string for the "send" command:
Usage string syntax puts optional options inside []
and default values of option arguments inside <>
.
The CLI uses tables to define command strings, the function to invoke on a command string match, and a description string to display when there are no matches. Here is part of the general_commands
table, which is the root table of the CLI:
Each table entry constitutes a CLI command. In the example above, "info"
is the string that the CLI will try and match, cli_cmd_info
is the function to invoke when a match is made, and "Print device information"
is the description to show for that command.
The CLI is implemented with "exact or least character match" on command strings. This requires fewer characters in the command string input than exact match only, and has advantages when using a non-UART interface.
Command String Entered | Command Matched | Function Called |
---|---|---|
"reset" | "reset" | cli_cmd_reset |
"reset_u" | "reset_uart" | cli_cmd_reset_uart |
"reset_" | no match | commands and descriptions will be printed |
The CLI command table structure supports hierarchy or nested commands, resulting in command strings that simply point to a sub-table for further matching. Below is an example of nested commands.
In the above table, the command string "reset" will pass the next argument in the command string to the reset_commands table for matching. If the reset_commands table looks like this:
then entering a command string of "reset"
or just "res"
will print the commands and their descriptions like this:
With the sub-table, the command string matching will look like this:
Command String Entered | Command Matched | Function Called |
---|---|---|
"reset dev" | "device" | cli_cmd_reset |
"reset test" | "test" | cli_cmd_reset_test |
"reset u" | "uart" | cli_cmd_reset_uart |
The UART configuration is done in the project tr_hal_config.h
file. This is uniqe per project build target. In this file you must set the UART to be used as well as the pins for UART TX and RX. For the DKNCM11 development board, the follwing UART pin configuration should be used:
By default, the CLI UART (aka debug port) is configured as:
UART Port Settings | |
---|---|
Baud Rate | 115,200 |
Parity | none |
Data Bits | 8 |
Stop Bits | 1 |
The CLI prompt can be configured in the tr_plugin_config.h
file which is unique per project. Refer to the Command Line Interface (CLI) services plugin for the settings.
Refer to the Door Lock SZED sample app project for an example of a user extension of the CLI. The custom command table implementation is in src/lock_cli.c
.
Custom user command tables are enabled by defining the following macros in the project tr_plugin_config.h
file.
Macro Name | Value Matched | Function |
---|---|---|
#define CUSTOM_CLI_COMMANDS_ENABLE
| – | Enable the custom command table |
#define CUSTOM_CLI_TOPLEVEL
| "cmd_string" | Define the top level command string for the custom CLI command table |
The custom command tables take the following format:
TR_CLI_COMMAND_TABLE
is a macro used to begin the declaration of the table. The root user custom command table name must be custom_cli_commands
. Command table entries can be added as needed, including adding sub-command tables as shown in Table Hierarchy. The command table(s) must be terminated with TR_CLI_COMMAND_TABLE_END
. Command strings may include "-" and/or "_" and other special characters, but cannot have a space in them.
CLI functions take the form of:
As stated in Command Strings, argc
has a value equal to the number of arguments passed to the CLI function handler, and *argv[]
holds the arguments. These arguments are intended to be formatted as short options with optional arguments that can be parsed by optarg. An API, tr_cli_get_option()
is available to parse options and arguments that are passed to CLI functions. tr_dec_or_hex_string_to_int()
is available to convert hex or decimal strings into integers up to 64 bits long.
To use this API, pass in argc
and *argv[]
, a pointer to a string containing the option you are looking for, and a pointer to a pointer for the API to return the argument for the specified option. Examples of this API with and without option arguments can be seen in the Door Lock SZED sample app project, src/lock_cli.c
.
Here is an example CLI function from that file:
Option arguments can be strings or values. Strings may be enclosed in double quotes "<string>"
but that is not a requirement since all arguments are strings by default. Values can be either decimal or hex. Hex values are prefixed with 0x
and are case insensitive. The tr_cli_get_option()
API will return 1
if the option request is satisfied. That is just a fancy way of saying that if the option didn't require an agrument, it was present. If it required an argument, then an argument was given. This makes it easy write CLI commands with mandatory and optional options and mandatory and optional arguments. Upon return from tr_cli_get_option()
, option_argument
will be pointing to the string that was entered by the user. That string can be converted into a value with the API tr_dec_or_hex_string_to_int(option_argument);
From the example above, the call
expects a -u
followed by a numeric value. The value entered is returned with
Similarly, the call
expects a -c
followed by a string value. Upon return from tr_cli_get_option()
, option_argument
will be pointing to the string entered by the user and it can be processed in place using standard string functions.
-h
option to print the usage string. This option does not take an argumentThe Remote CLI Server plugin allows command strings to be received over the air via Zigbee packets. The command strings are passed to the CLI for parsing just like UART command strings are. The output from the CLI command execution is then packaged up and sent back out over Zigbee. The Remote CLI Client plugin is used to send remote CLI commands to a node on the Zigbee network. This feature provides powerful field debug capability, especially if the product vendor created custom commands to extend the CLI for thier specific use cases.