控制台终端
ESP-IDF 提供了 console
组件,它包含了开发基于串口的交互式控制终端所需要的所有模块,主要支持以下功能:
行编辑,由 linenoise 库具体实现,它支持处理退格键和方向键,支持回看命令的历史记录,支持命令的自动补全和参数提示。
将命令行拆分为参数列表。
参数解析,由 argtable3 库具体实现,该库提供解析 GNU 样式的命令行参数的 API。
用于注册和调度命令的函数。
帮助创建 REPL (Read-Evaluate-Print-Loop) 环境的函数。
备注
这些功能模块可以一起使用,也可以独立使用,例如仅使用行编辑和命令注册的功能,然后使用 getopt
函数或者自定义的函数来实现参数解析,而不是直接使用 argtable3 库。同样地,还可以使用更简单的命令输入方法(比如 fgets
函数)和其他用于命令分割和参数解析的方法。
备注
当在支持硬件 USB 串行接口的芯片上使用控制台应用程序时,建议禁用次级串口控制台输出。次级输出仅用于显示,对于交互式应用程序没有任何作用。
行编辑
行编辑功能允许用户通过按键输入来编辑命令,使用退格键删除符号,使用左/右键在命令中移动光标,使用上/下键导航到之前输入的命令,使用制表键(“Tab”)来自动补全命令。
备注
此功能依赖于终端应用程序对 ANSI 转义符的支持。因此,显示原始 UART 数据的串口监视器不能与行编辑库一同使用。如果运行 system/console 示例程序的时候看到的输出结果是 [6n
或者类似的转义字符而不是命令行提示符 esp>
时,就表明当前的串口监视器不支持 ANSI 转义字符。已知可用的串口监视程序有 GNU screen、minicom 和 esp-idf-monitor(可以通过在项目目录下执行 idf.py monitor
来调用)。
前往这里可以查看 linenoise 库提供的所有函数的描述。
配置
Linenoise 库不需要显式地初始化,但是在调用行编辑函数之前,可能需要对某些配置的默认值稍作修改。
linenoiseClearScreen()
使用转义字符清除终端屏幕,并将光标定位在左上角。
linenoiseSetMultiLine()
在单行和多行编辑模式之间进行切换。单行模式下,如果命令的长度超过终端的宽度,会在行内滚动命令文本以显示文本的结尾,在这种情况下,文本的开头部分会被隐藏。单行模式在每次按下按键时发送给屏幕刷新的数据比较少,与多行模式相比更不容易发生故障。另一方面,在单行模式下编辑命令和复制命令将变得更加困难。默认情况下开启的是单行模式。
linenoiseAllowEmpty()
设置 linenoise 库收到空行的解析行为,设置为
true
时返回长度为零的字符串 (""
) ,设置为false
时返回NULL
。默认情况下,将返回长度为零的字符串。linenoiseSetMaxLineLen()
设置 linenoise 库中每行的最大长度,默认长度为 4096 字节,可以通过更新该默认值来优化 RAM 内存的使用。
主循环
linenoise()
在大多数情况下,控制台应用程序都会具有相同的工作形式——在某个循环中不断读取输入的内容,然后解析再处理。
linenoise()
是专门用来获取用户按键输入的函数,当回车键被按下后会便返回完整的一行内容。因此可以用它来完成前面循环中的“读取”任务。linenoiseFree()
必须调用此函数才能释放从
linenoise()
函数获取的命令行缓冲区。
提示和补全
linenoiseSetCompletionCallback()
当用户按下制表键时,linenoise 会调用 补全回调函数 ,该回调函数会检查当前已经输入的内容,然后调用
linenoiseAddCompletion()
函数来提供所有可能的补全后的命令列表。启用补全功能,需要事先调用linenoiseSetCompletionCallback()
函数来注册补全回调函数。console
组件提供了一个现成的函数来为注册的命令提供补全功能esp_console_get_completion()
(见下文)。linenoiseAddCompletion()
补全回调函数会通过调用此函数来通知 linenoise 库当前键入命令所有可能的补全结果。
linenoiseSetHintsCallback()
每当用户的输入改变时,linenoise 就会调用此回调函数,检查到目前为止输入的命令行内容,然后提供带有提示信息的字符串(例如命令参数列表),然后会在同一行上用不同的颜色显示出该文本。
linenoiseSetFreeHintsCallback()
如果 提示回调函数 返回的提示字符串是动态分配的或者需要以其它方式回收,就需要使用
linenoiseSetFreeHintsCallback()
注册具体的清理函数。
历史记录
linenoiseHistorySetMaxLen()
该函数设置要保留在内存中的最近输入的命令的数量。用户通过使用向上/向下箭头来导航历史记录。
linenoiseHistoryAdd()
Linenoise 不会自动向历史记录中添加命令,应用程序需要调用此函数来将命令字符串添加到历史记录中。
linenoiseHistorySave()
该函数将命令的历史记录从 RAM 中保存为文本文件,例如保存到 SD 卡或者 flash 的文件系统中。
linenoiseHistoryLoad()
与
linenoiseHistorySave
相对应,从文件中加载历史记录。linenoiseHistoryFree()
释放用于存储命令历史记录的内存。当使用完 linenoise 库后需要调用此函数。
将命令行拆分成参数列表
console
组件提供 esp_console_split_argv()
函数来将命令行字符串拆分为参数列表。该函数会返回参数的数量(argc
)和一个指针数组,该指针数组可以作为 argv
参数传递给任何接受 argc,argv
格式参数的函数。
根据以下规则来将命令行拆分成参数列表:
参数由空格分隔
如果参数本身需要使用空格,可以使用
\
(反斜杠)对它们进行转义其它能被识别的转义字符有
\\
(显示反斜杠本身)和\"
(显示双引号)可以使用双引号来引用参数,引号只可能出现在参数的开头和结尾。参数中的引号必须如上所述进行转义。参数周围的引号会被
esp_console_split_argv()
函数删除
示例:
abc def 1 20 .3
> [abc
,def
,1
,20
,.3
]abc "123 456" def
> [abc
,123 456
,def
]`a\ b\\c\"
> [a b\c"
]
参数解析
对于参数解析,console
组件使用 argtable3 库。有关 argtable3 的介绍请查看 教程 或者 Github 仓库中的 示例代码 。
命令的注册与调度
console
组件包含了一些工具函数,用来注册命令,将用户输入的命令和已经注册的命令进行匹配,使用命令行输入的参数调用命令。
应用程序首先调用 esp_console_init()
来初始化命令注册模块,然后调用 esp_console_cmd_register()
函数注册命令处理程序。
对于每个命令,应用程序需要提供以下信息(需要以 esp_console_cmd_t
结构体的形式给出):
命令名字(不含空格的字符串)
帮助文档,解释该命令的用途
可选的提示文本,列出命令的参数。如果应用程序使用
Argtable3
库来解析参数,则可以通过提供指向 argtable 参数定义结构体的指针来自动生成提示文本命令处理函数(无上下文),或
命令处理函数(有上下文)。如要使用此函数,则必须在调用其他命令 之前 调用
esp_console_cmd_set_context()
初始化上下文。
备注
使用接受上下文的命令处理函数或者不接受上下文的命令处理函数均可,但两者不能同时使用。如果使用接受上下文的命令处理程序函数,则必须调用 esp_console_cmd_set_context()
初始化上下文,否则该函数可能会访问未初始化的上下文。
命令注册模块还提供了其它函数:
-
该函数接受命令行字符串,使用
esp_console_split_argv()
函数将其拆分为 argc/argv 形式的参数列表,在已经注册的组件列表中查找命令,如果找到,则执行其对应的处理程序。 esp_console_register_help_command()
将
help
命令添加到已注册命令列表中,此命令将会以列表的方式打印所有注册的命令及其参数和帮助文本。-
与 linenoise 库中的
linenoiseSetCompletionCallback()
一同使用的回调函数,根据已经注册的命令列表为 linenoise 提供补全功能。 -
与 linenoise 库中
linenoiseSetHintsCallback()
一同使用的回调函数,为 linenoise 提供已经注册的命令的参数提示功能。
初始化 REPL 环境
除了上述的各种函数,console
组件还提供了一些 API 来帮助创建一个基本的 REPL 环境。
在一个典型的 console 应用中,你只需要调用 esp_console_new_repl_uart()
,它会为你初始化好构建在 UART 基础上的 REPL 环境,其中包括安装 UART 驱动,基本的 console 配置,创建一个新的线程来执行 REPL 任务,注册一些基本的命令(比如 help 命令)。
之后你可以使用 esp_console_cmd_register()
来注册其它命令。REPL 环境在初始化后需要再调用 esp_console_start_repl()
函数才能开始运行。
同样,如果 REPL 环境是构建在 USB_SERIAL_JTAG 设备基础上,你只需要先调用 esp_console_new_repl_usb_serial_jtag()
函数进行初始化,然后再照常调用其它函数。
应用示例
system/console/basic 演示了如何使用控制台组件的 REPL(读-评估-打印循环)API 在 ESP32-C5 上创建一个交互式 Shell,该 Shell 可以通过串行接口控制,支持 UART 和 USB 接口,并可以作为需要命令行接口的应用程序的基础。
system/console/advanced 演示了如何使用控制台组件在 ESP32-C5 上创建一个交互式 Shell,该 Shell 可以通过串行接口控制,支持 UART 和 USB 接口,可作为需要命令行接口的应用程序的基础。
API 参考
Header File
This header file can be included with:
#include "esp_console.h"
This header file is a part of the API provided by the
console
component. To declare that your component depends onconsole
, add the following to your CMakeLists.txt:REQUIRES console
or
PRIV_REQUIRES console
Functions
-
esp_err_t esp_console_init(const esp_console_config_t *config)
initialize console module
备注
Call this once before using other console module features
- 参数
config -- console configuration
- 返回
ESP_OK on success
ESP_ERR_NO_MEM if out of memory
ESP_ERR_INVALID_STATE if already initialized
ESP_ERR_INVALID_ARG if the configuration is invalid
-
esp_err_t esp_console_deinit(void)
de-initialize console module
备注
Call this once when done using console module functions
- 返回
ESP_OK on success
ESP_ERR_INVALID_STATE if not initialized yet
-
esp_err_t esp_console_cmd_register(const esp_console_cmd_t *cmd)
Register console command.
备注
If the member
func_w_context
of cmd is set instead of func, then the membercontext
is passed to the function pointed to byfunc_w_context
.- 参数
cmd -- pointer to the command description; can point to a temporary value
- 返回
ESP_OK on success
ESP_ERR_NO_MEM if out of memory
ESP_ERR_INVALID_ARG if command description includes invalid arguments
ESP_ERR_INVALID_ARG if both func and func_w_context members of cmd are non-NULL
ESP_ERR_INVALID_ARG if both func and func_w_context members of cmd are NULL
-
esp_err_t esp_console_cmd_deregister(const char *cmd_name)
Deregister console command.
- 参数
cmd_name -- Name of the command to be deregistered. Must not be NULL, must not contain spaces.
- 返回
ESP_OK on success
ESP_ERR_INVALID_ARG if command is not registered
-
esp_err_t esp_console_run(const char *cmdline, int *cmd_ret)
Run command line.
- 参数
cmdline -- command line (command name followed by a number of arguments)
cmd_ret -- [out] return code from the command (set if command was run)
- 返回
ESP_OK, if command was run
ESP_ERR_INVALID_ARG, if the command line is empty, or only contained whitespace
ESP_ERR_NOT_FOUND, if command with given name wasn't registered
ESP_ERR_INVALID_STATE, if esp_console_init wasn't called
-
size_t esp_console_split_argv(char *line, char **argv, size_t argv_size)
Split command line into arguments in place.
* - This function finds whitespace-separated arguments in the given input line. * * 'abc def 1 20 .3' -> [ 'abc', 'def', '1', '20', '.3' ] * * - Argument which include spaces may be surrounded with quotes. In this case * spaces are preserved and quotes are stripped. * * 'abc "123 456" def' -> [ 'abc', '123 456', 'def' ] * * - Escape sequences may be used to produce backslash, double quote, and space: * * 'a\ b\\c\"' -> [ 'a b\c"' ] *
备注
Pointers to at most argv_size - 1 arguments are returned in argv array. The pointer after the last one (i.e. argv[argc]) is set to NULL.
- 参数
line -- pointer to buffer to parse; it is modified in place
argv -- array where the pointers to arguments are written
argv_size -- number of elements in argv_array (max. number of arguments)
- 返回
number of arguments found (argc)
-
void esp_console_get_completion(const char *buf, linenoiseCompletions *lc)
Callback which provides command completion for linenoise library.
When using linenoise for line editing, command completion support can be enabled like this:
linenoiseSetCompletionCallback(&esp_console_get_completion);
- 参数
buf -- the string typed by the user
lc -- linenoiseCompletions to be filled in
-
const char *esp_console_get_hint(const char *buf, int *color, int *bold)
Callback which provides command hints for linenoise library.
When using linenoise for line editing, hints support can be enabled as follows:
linenoiseSetHintsCallback((linenoiseHintsCallback*) &esp_console_get_hint);
The extra cast is needed because linenoiseHintsCallback is defined as returning a char* instead of const char*.
- 参数
buf -- line typed by the user
color -- [out] ANSI color code to be used when displaying the hint
bold -- [out] set to 1 if hint has to be displayed in bold
- 返回
string containing the hint text. This string is persistent and should not be freed (i.e. linenoiseSetFreeHintsCallback should not be used).
-
esp_err_t esp_console_register_help_command(void)
Register a 'help' command.
Default 'help' command prints the list of registered commands along with hints and help strings if no additional argument is given. If an additional argument is given, the help command will look for a command with the same name and only print the hints and help strings of that command.
- 返回
ESP_OK on success
ESP_ERR_INVALID_STATE, if esp_console_init wasn't called
-
esp_err_t esp_console_set_help_verbose_level(esp_console_help_verbose_level_e verbose_level)
Set the verbose level for 'help' command.
Set the verbose level for 'help' command. Higher verbose level shows more details. Valid verbose_level values are described in esp_console_help_verbose_level_e and must be lower than
ESP_CONSOLE_HELP_VERBOSE_LEVEL_MAX_NUM
.- 返回
ESP_OK on success
ESP_ERR_INVALID_ARG, if invalid verbose level is provided
-
esp_err_t esp_console_new_repl_uart(const esp_console_dev_uart_config_t *dev_config, const esp_console_repl_config_t *repl_config, esp_console_repl_t **ret_repl)
Establish a console REPL environment over UART driver.
- Attention
This function is meant to be used in the examples to make the code more compact. Applications which use console functionality should be based on the underlying linenoise and esp_console functions.
备注
This is an all-in-one function to establish the environment needed for REPL, includes:
Install the UART driver on the console UART (8n1, 115200, REF_TICK clock source)
Configures the stdin/stdout to go through the UART driver
Initializes linenoise
Spawn new thread to run REPL in the background
- 参数
dev_config -- [in] UART device configuration
repl_config -- [in] REPL configuration
ret_repl -- [out] return REPL handle after initialization succeed, return NULL otherwise
- 返回
ESP_OK on success
ESP_FAIL Parameter error
-
esp_err_t esp_console_new_repl_usb_serial_jtag(const esp_console_dev_usb_serial_jtag_config_t *dev_config, const esp_console_repl_config_t *repl_config, esp_console_repl_t **ret_repl)
Establish a console REPL (Read-eval-print loop) environment over USB-SERIAL-JTAG.
- Attention
This function is meant to be used in the examples to make the code more compact. Applications which use console functionality should be based on the underlying linenoise and esp_console functions.
备注
This is an all-in-one function to establish the environment needed for REPL, includes:
Initializes linenoise
Spawn new thread to run REPL in the background
- 参数
dev_config -- [in] USB-SERIAL-JTAG configuration
repl_config -- [in] REPL configuration
ret_repl -- [out] return REPL handle after initialization succeed, return NULL otherwise
- 返回
ESP_OK on success
ESP_FAIL Parameter error
-
esp_err_t esp_console_start_repl(esp_console_repl_t *repl)
Start REPL environment.
备注
Once the REPL gets started, it won't be stopped until the user calls repl->del(repl) to destroy the REPL environment.
- 参数
repl -- [in] REPL handle returned from esp_console_new_repl_xxx
- 返回
ESP_OK on success
ESP_ERR_INVALID_STATE, if repl has started already
Structures
-
struct esp_console_config_t
Parameters for console initialization.
Public Members
-
size_t max_cmdline_length
length of command line buffer, in bytes
-
size_t max_cmdline_args
maximum number of command line arguments to parse
-
uint32_t heap_alloc_caps
where to (e.g. MALLOC_CAP_SPIRAM) allocate heap objects such as cmds used by esp_console
-
int hint_color
ASCII color code of hint text.
-
int hint_bold
Set to 1 to print hint text in bold.
-
size_t max_cmdline_length
-
struct esp_console_repl_config_t
Parameters for console REPL (Read Eval Print Loop)
Public Members
-
uint32_t max_history_len
maximum length for the history
-
const char *history_save_path
file path used to save history commands, set to NULL won't save to file system
-
uint32_t task_stack_size
repl task stack size
-
uint32_t task_priority
repl task priority
-
BaseType_t task_core_id
repl task affinity, i.e. which core the task is pinned to
-
const char *prompt
prompt (NULL represents default: "esp> ")
-
size_t max_cmdline_length
maximum length of a command line. If 0, default value will be used
-
uint32_t max_history_len
-
struct esp_console_dev_uart_config_t
Parameters for console device: UART.
-
struct esp_console_dev_usb_serial_jtag_config_t
Parameters for console device: USB-SERIAL-JTAG.
备注
It's an empty structure for now, reserved for future
-
struct esp_console_cmd_t
Console command description.
Public Members
-
const char *command
Command name. Must not be NULL, must not contain spaces. The pointer must be valid until the call to esp_console_deinit.
-
const char *help
Help text for the command, shown by help command. If set, the pointer must be valid until the call to esp_console_deinit. If not set, the command will not be listed in 'help' output.
-
const char *hint
Hint text, usually lists possible arguments. If set to NULL, and 'argtable' field is non-NULL, hint will be generated automatically
-
esp_console_cmd_func_t func
Pointer to a function which implements the command.
备注
: Setting both
func
andfunc_w_context
is not allowed.
-
void *argtable
Array or structure of pointers to arg_xxx structures, may be NULL. Used to generate hint text if 'hint' is set to NULL. Array/structure which this field points to must end with an arg_end. Only used for the duration of esp_console_cmd_register call.
-
esp_console_cmd_func_with_context_t func_w_context
Pointer to a context aware function which implements the command.
备注
: Setting both
func
andfunc_w_context
is not allowed.
-
void *context
Context pointer to user-defined per-command context data. This is used if context aware function
func_w_context
is set.
-
const char *command
-
struct esp_console_repl_s
Console REPL base structure.
Public Members
-
esp_err_t (*del)(esp_console_repl_t *repl)
Delete console REPL environment.
- Param repl
[in] REPL handle returned from esp_console_new_repl_xxx
- Return
ESP_OK on success
ESP_FAIL on errors
-
esp_err_t (*del)(esp_console_repl_t *repl)
Macros
-
ESP_CONSOLE_CONFIG_DEFAULT()
Default console configuration value.
-
ESP_CONSOLE_REPL_CONFIG_DEFAULT()
Default console repl configuration value.
-
ESP_CONSOLE_DEV_UART_CONFIG_DEFAULT()
-
ESP_CONSOLE_DEV_USB_SERIAL_JTAG_CONFIG_DEFAULT()
Type Definitions
-
typedef struct linenoiseCompletions linenoiseCompletions
-
typedef int (*esp_console_cmd_func_t)(int argc, char **argv)
Console command main function.
- Param argc
number of arguments
- Param argv
array with argc entries, each pointing to a zero-terminated string argument
- Return
console command return code, 0 indicates "success"
-
typedef int (*esp_console_cmd_func_with_context_t)(void *context, int argc, char **argv)
Console command main function, with context.
- Param context
a user context given at invocation
- Param argc
number of arguments
- Param argv
array with argc entries, each pointing to a zero-terminated string argument
- Return
console command return code, 0 indicates "success"
-
typedef struct esp_console_repl_s esp_console_repl_t
Type defined for console REPL.