This is the third tutorial in a series that demonstrates "the essentials" of building applications based on Silicon Labs Connect. See Connect Tutorial Series: Table of Contents for an overview of topics addressed in the series, general pre-requisites to ensure you get the most out of the exercises, and definitive Connect references for when you're ready to dive deeper.
The first tutorial (Getting Started with Application Development) introduced the Connect application development construct, based on plugins, callbacks, and events. In this third tutorial, we introduce the powerful command line interface (CLI) available in Connect-based applications using a UART serial communication channel.
To conduct the following exercises, you'll need a single Wireless Starter Kit (WSTK) and radio board. Although the UART GPIO pins can be arbitrarily selected, we'll use the default configuration which enables access to the EFR32 serial port through the USB connector of the WSTK board (as a Virtual COM port).
Basic Application Example 1: Printing to UART
Commonly, an application has no need for sophisticated interactive communications on the networked devices. However, even in many of these cases the ability to easily print basic information (for example, debug messages) remains vital - especially during initial bring-up or installed network diagnostics.
Connect supports this simple "print-only" functionality with built-in application print routines. This first example will demonstrate the implementation and capability of this feature set.
To begin, create a new "Empty" Flex SDK Project as described in tutorial 1 "Getting Started with Application Development". (Just create a new project for this tutorial 3 and give it an appropriate name - you don't need to actually repeat the tutorial 1 exercise.)
Configure Simple Printing Support in AppBuilder
In AppBuilder, select the plugins listed below:
- Connect Debug / Debug Print
- Connect I/O / Serial
Then, enable debug printing by checking the AppBuilder / Printing / Debug Configuration / Enable debug printing box.
As depicted in this section of AppBuilder, the debug printing facility supports functional areas. Related messages are grouped together into a functional area, and each area can be enabled (or disabled) in this AppBuilder interface. Only debug messages belonging to enabled areas will then be printed. Available functional areas are:
- Core
- Debug
- App
- Custom 1/2/3
By default, the Core and App areas are enabled - this is suitable for the purposes of this example. Remember to [Generate] your project in AppBuilder to initially populate your project directory.
API Calls for Simple Printing
The debug printing messages discussed above are available by calling the corresponding API function emberAf<Area><Method>()
, for example emberAfCustom2PrintBuffer()
. All (currently, six) functional areas are available for use by the application in this manner.
Connect also supports general message printing to the serial interface. To print such messages from the application, use the following functions:
emberAfAppPrint()
emberAfAppPrintln()
emberAfAppPrintBuffer()
- prints bytes of the buffer as two digit hexadecimal value
The format string is not fully compatible with the standard printf()
call, and is fairly limited in functionality. For details see emPrintfInternal
in ember-printf.c
.
Example Simple Printing Usage and Testing
The following code prints a few lines to demonstrate the APIs discussed above:
int16_t valueDec = -1000;
uint32_t valueHex = 0xDEADBEEF;
uint8_t buffer[] = "Hello World!";
emberAfDebugPrintln("Connect tutorial 03: CLI");
emberAfAppPrintln("Dec: %d, Hex: %04x", valueDec, valueHex);
emberAfAppPrint("Buffer: ");
emberAfAppPrintBuffer(buffer, 12, true);
emberAfAppPrintln("");
The attached flex-callbacks.c
"solution" implements this snippet in emberAfMainInitCallback()
.
Compile and download the firmware onto your device. Then, open a terminal emulator (TeraTerm, PuTTY, the Simplicity Studio Console, etc.) and connect to the VCOM port presented over USB by your WSTK board. By default, the VCOM serial port is configured to use 115200 8N1 (115.2 Kbit/s, 8 data bits, 1 stop bit), with flow control disabled/ignored. For more information see the User's Guide for your radio board.
Once connected, hitting the RESET pushbutton on the WSTK should produce the following result (including the system message in the first two lines):
Reset info: 0x03 (EXT)
Init: 0x00
Connect tutorial 03: CLI
Dec: -1000, Hex: DEADBEEF
48 65 6C 6C 6F 20 57 6F 72 6C 64 21
Notes:
- The print functions above are blocking
- If debug print is enabled, the application will print some status information on start
Basic Application Example 2: Interactive CLI
Beyond simple printing capability, some applications also require the ability to respond to user/operator commands, adjust device configurations at run-time, print statistical information on demand, etc.
Connect supports this kind of interactivity through the built-in command line interface.
Configure CLI Support in AppBuilder
To enable the CLI feature set, first select Command Interpreter in AppBuilder / Plugins in the Connect I/O section. You also need to check the Enable command line interface box in AppBuilder / Printing / Command Line Configuration.
Add CLI commands
To add a new CLI command click on Add new button in Command Line Configuration frame. Three items must be specified for each single added command:
- Command:
- the character string which, when typed into the CLI, will execute the command
- Arglist:
- the list of arguments the command will accept
- Callback:
- the function that will be called upon each execution of the command
The default command help
is already implemented for convenience - issuing this command will print a list of available commands to the serial console.
Connect supports essentially two kinds of input arguments: numeric (of different sizes and signedness) and array (string, multibyte data). Arglist specifies the number and explicit data type of arguments (as well as more flexible options - e.g. wildcards) expected by the command. Details on the argument types available can be found at https://docs.silabs.com/connect-stack/latest/structEmberCommandEntry.
Let's create two new commands:
greeting
with argument list b
(a single string argument) and callback greetingCommand
led
with argument list uu
(two arguments, each a one-byte unsigned integer) and callback ledCommand
When the project is next generated, AppBuilder automatically creates the command table in flex-cli.c
. The application needs only to implement the logic behind the commands in flex-callbacks.c
, using the names as specified in the Callback column.
The first command takes one argument (we'll call it name
), and when executed it prints a line of greeting text that includes the previously-provided string argument:
void greetingCommand(void) {
uint8_t name[20];
emberGetStringArgument(0, &name, 20, false);
emberAfAppPrintln("Hey %s! How are you?", name);
}
For string CLI arguments, the application has to first allocate an array and then put the provided argument into this variable using emberGetStringArgument()
- a call that requires a few arguments of its own. The first argument is the position of the CLI argument in the CLI command's argument list (zero-indexed). The second and third parameters specify the storage array for the string and its maximum size (to avoid buffer overflow), respectively. The last parameter dictates whether or not to left-pad the string with space characters.
For convenience, the strings/arrays can be represented in two different ways - use quotation marks (""
) for ASCII text, or curly braces ({}
) for list of hex values:
"Hello"
{48 65 6C 6C 6F}
Example usage of our new CLI greeting
command (you need to hit Enter
to solicit a command prompt in your terminal) is as follows:
cli>greeting "John Doe"
Hey John Doe! How are you?
cli>
Retrieving numeric CLI arguments is a simpler task - just assign the return value of emberUnsignedCommandArgument()
to a variable:
void ledCommand(void) {
uint8_t ledID = emberUnsignedCommandArgument(0);
bool ledState = emberUnsignedCommandArgument(1);
if(ledState) {
halSetLed(ledID);
} else {
halClearLed(ledID);
}
}
As shown above, emberUnsignedCommandArgument()
requires only the CLI argument list position parameter. To test this code, issue the led <ID> <state>
command (note that consecutive arguments are separated by space characters) in your terminal. Valid input values for the ID
are 0
(LED0) and 1
(LED1), while the LED state
can be 0
(off) or 1
(on):
cli>led 0 1
cli>led 1 1
cli>
The command line interpreter does a simple sanity check on the arguments to ensure the correct number and type of arguments were provided. However, it does not validate the actual argument values - an application should gracefully handle the full range of input values enabled by the CLI command argument definitions.
Conclusion
The Connect command line interface is a flexible and convenient built-in feature that both accelerates application development and enhances the management and operation of production firmware. In fact, we will use it as our main interface to the example applications for the remainder of this tutorial series.
For detailed information about the Connect CLI API, visit https://docs.silabs.com/connect-stack/latest/group-command-interpreter. For additional guidance, see UG235.08: Using the Command Line Interface with Silicon Labs Connect.
API References
Functions
Connect Tutorial 3 - Command Line Interface
This is the third tutorial in a series that demonstrates "the essentials" of building applications based on Silicon Labs Connect. See Connect Tutorial Series: Table of Contents for an overview of topics addressed in the series, general pre-requisites to ensure you get the most out of the exercises, and definitive Connect references for when you're ready to dive deeper.
The first tutorial (Getting Started with Application Development) introduced the Connect application development construct, based on plugins, callbacks, and events. In this third tutorial, we introduce the powerful command line interface (CLI) available in Connect-based applications using a UART serial communication channel.
To conduct the following exercises, you'll need a single Wireless Starter Kit (WSTK) and radio board. Although the UART GPIO pins can be arbitrarily selected, we'll use the default configuration which enables access to the EFR32 serial port through the USB connector of the WSTK board (as a Virtual COM port).
Basic Application Example 1: Printing to UART
Commonly, an application has no need for sophisticated interactive communications on the networked devices. However, even in many of these cases the ability to easily print basic information (for example, debug messages) remains vital - especially during initial bring-up or installed network diagnostics.
Connect supports this simple "print-only" functionality with built-in application print routines. This first example will demonstrate the implementation and capability of this feature set.
To begin, create a new "Empty" Flex SDK Project as described in tutorial 1 "Getting Started with Application Development". (Just create a new project for this tutorial 3 and give it an appropriate name - you don't need to actually repeat the tutorial 1 exercise.)
Configure Simple Printing Support in AppBuilder
In AppBuilder, select the plugins listed below:
Then, enable debug printing by checking the AppBuilder / Printing / Debug Configuration / Enable debug printing box.
As depicted in this section of AppBuilder, the debug printing facility supports functional areas. Related messages are grouped together into a functional area, and each area can be enabled (or disabled) in this AppBuilder interface. Only debug messages belonging to enabled areas will then be printed. Available functional areas are:
By default, the Core and App areas are enabled - this is suitable for the purposes of this example. Remember to [Generate] your project in AppBuilder to initially populate your project directory.
API Calls for Simple Printing
The debug printing messages discussed above are available by calling the corresponding API function
emberAf<Area><Method>()
, for exampleemberAfCustom2PrintBuffer()
. All (currently, six) functional areas are available for use by the application in this manner.Connect also supports general message printing to the serial interface. To print such messages from the application, use the following functions:
emberAfAppPrint()
emberAfAppPrintln()
emberAfAppPrintBuffer()
The format string is not fully compatible with the standard
printf()
call, and is fairly limited in functionality. For details seeemPrintfInternal
inember-printf.c
.Example Simple Printing Usage and Testing
The following code prints a few lines to demonstrate the APIs discussed above:
The attached
flex-callbacks.c
"solution" implements this snippet inemberAfMainInitCallback()
.Compile and download the firmware onto your device. Then, open a terminal emulator (TeraTerm, PuTTY, the Simplicity Studio Console, etc.) and connect to the VCOM port presented over USB by your WSTK board. By default, the VCOM serial port is configured to use 115200 8N1 (115.2 Kbit/s, 8 data bits, 1 stop bit), with flow control disabled/ignored. For more information see the User's Guide for your radio board.
Once connected, hitting the RESET pushbutton on the WSTK should produce the following result (including the system message in the first two lines):
Notes:
Basic Application Example 2: Interactive CLI
Beyond simple printing capability, some applications also require the ability to respond to user/operator commands, adjust device configurations at run-time, print statistical information on demand, etc.
Connect supports this kind of interactivity through the built-in command line interface.
Configure CLI Support in AppBuilder
To enable the CLI feature set, first select Command Interpreter in AppBuilder / Plugins in the Connect I/O section. You also need to check the Enable command line interface box in AppBuilder / Printing / Command Line Configuration.
Add CLI commands
To add a new CLI command click on Add new button in Command Line Configuration frame. Three items must be specified for each single added command:
The default command
help
is already implemented for convenience - issuing this command will print a list of available commands to the serial console.Connect supports essentially two kinds of input arguments: numeric (of different sizes and signedness) and array (string, multibyte data). Arglist specifies the number and explicit data type of arguments (as well as more flexible options - e.g. wildcards) expected by the command. Details on the argument types available can be found at https://docs.silabs.com/connect-stack/latest/structEmberCommandEntry.
Let's create two new commands:
greeting
with argument listb
(a single string argument) and callbackgreetingCommand
led
with argument listuu
(two arguments, each a one-byte unsigned integer) and callbackledCommand
When the project is next generated, AppBuilder automatically creates the command table in
flex-cli.c
. The application needs only to implement the logic behind the commands inflex-callbacks.c
, using the names as specified in the Callback column.The first command takes one argument (we'll call it
name
), and when executed it prints a line of greeting text that includes the previously-provided string argument:For string CLI arguments, the application has to first allocate an array and then put the provided argument into this variable using
emberGetStringArgument()
- a call that requires a few arguments of its own. The first argument is the position of the CLI argument in the CLI command's argument list (zero-indexed). The second and third parameters specify the storage array for the string and its maximum size (to avoid buffer overflow), respectively. The last parameter dictates whether or not to left-pad the string with space characters.For convenience, the strings/arrays can be represented in two different ways - use quotation marks (
""
) for ASCII text, or curly braces ({}
) for list of hex values:Example usage of our new CLI
greeting
command (you need to hitEnter
to solicit a command prompt in your terminal) is as follows:Retrieving numeric CLI arguments is a simpler task - just assign the return value of
emberUnsignedCommandArgument()
to a variable:As shown above,
emberUnsignedCommandArgument()
requires only the CLI argument list position parameter. To test this code, issue theled <ID> <state>
command (note that consecutive arguments are separated by space characters) in your terminal. Valid input values for theID
are0
(LED0) and1
(LED1), while the LEDstate
can be0
(off) or1
(on):The command line interpreter does a simple sanity check on the arguments to ensure the correct number and type of arguments were provided. However, it does not validate the actual argument values - an application should gracefully handle the full range of input values enabled by the CLI command argument definitions.
Conclusion
The Connect command line interface is a flexible and convenient built-in feature that both accelerates application development and enhances the management and operation of production firmware. In fact, we will use it as our main interface to the example applications for the remainder of this tutorial series.
For detailed information about the Connect CLI API, visit https://docs.silabs.com/connect-stack/latest/group-command-interpreter. For additional guidance, see UG235.08: Using the Command Line Interface with Silicon Labs Connect.
API References
Functions
emberGetStringArgument()
emberUnsignedCommandArgument()