ESP CLI Service

[English]

简介

CLI ServiceESP Service 的子类,把 ESP-IDF 控制台的串口交互嵌入服务生命周期。它提供两层命令:内置静态系统命令,以及由服务管理器驱动的动态服务命令与工具命令。通过串口终端即可完成交互式调试与运行时控制。

备注

需要 ESP-IDF >= 5.4。

功能清单

  • UART REPL 集成:esp_console REPL 直接嵌入服务生命周期,调用 esp_service_start() 时启动,停止/销毁时关闭

  • 内置系统命令:自动注册 sys_heapsys_chipsys_uptimesys_reboot

  • 静态命令:通过 esp_cli_service_register_static_command() 在 REPL 启动前后随时注册任意 esp_console_cmd_t

  • 动态 svc 命令:从终端列出、查看和控制(start / stop / pause / resume)已跟踪的服务

  • 动态 tool 命令:枚举并调用 esp_service_manager 暴露的 JSON Schema 工具,支持 key=value--json 两种参数传入方式

  • 所有公开 API 由内部互斥锁保护,可从任意任务安全调用

技术拆解

命令体系

REPL 上挂载的命令分为三类:内置系统命令始终可用;应用通过 esp_cli_service_register_static_command() 注册的静态命令;以及在绑定 esp_service_manager 后才可用的 svc / tool 动态命令。调用 esp_service_start() 后 REPL 任务被创建,所有待注册的静态命令随即注册到 esp_console

        flowchart TD
    UART[UART 终端] --> REPL[esp_console REPL]
    REPL --> Sys["内置 sys_* 命令"]
    REPL --> Static["静态命令"]
    REPL --> Dyn["动态命令(需绑定 manager)"]
    Dyn --> Svc["svc 命令:已跟踪服务 / manager"]
    Dyn --> Tool["tool 命令:manager 工具注册表"]
    
esp_cli_service_config_t cfg = ESP_CLI_SERVICE_CONFIG_DEFAULT();
cfg.prompt = "app>";

esp_cli_service_t *cli = NULL;
esp_cli_service_create(&cfg, &cli);

esp_cli_service_track_service(cli, (esp_service_t *)my_svc, "audio");

const esp_console_cmd_t my_cmd = {
    .command = "version",
    .help    = "Print firmware version",
    .func    = cmd_version,
};
esp_cli_service_register_static_command(cli, &my_cmd);

esp_service_start((esp_service_t *)cli);

svc 与 tool 命令

svc 命令(list / info / start / stop / pause / resume)优先展示通过 esp_cli_service_track_service() 显式跟踪的服务,其次是绑定的 esp_service_manager 中登记的服务。tool 命令(list / info / call)枚举管理器暴露的 JSON Schema 工具;tool call 会按工具的 inputSchemakey=value 键值对序列化成 JSON 对象,支持 stringintegernumberboolean 类型,遇到 arrayobject 等复杂类型时改用 --json 传入原始 JSON 参数。管理器通过配置中的 manager 字段或运行期调用 esp_cli_service_bind_manager() 绑定,两种动态命令都依赖这一步。

应用示例

  • components/esp_cli_service/examples/ 提供独立示例,执行 idf.py set-target <chip>idf.py build flash monitor 即可上板体验。

FAQ

Q1:串口终端上没有出现提示符怎么办?

先确认已调用 esp_service_start()(REPL 任务只在启动时创建),再检查终端模拟器选择的 UART 端口和波特率是否匹配 IDF menuconfig 中配置的 console UART;如果注册的命令分配了较多数据,默认 4096 字节的 task_stack 未必够用,需要适当增大。

Q2:为什么 ``svc`` / ``tool`` 命令提示 “manager not bound”?

这两类动态命令都需要先绑定 esp_service_manager:在配置中设置 cfg.manager,或在运行期调用 esp_cli_service_bind_manager() 之后再使用。

API 参考

Header File

Functions

esp_err_t esp_cli_service_create(const esp_cli_service_config_t *cfg, esp_cli_service_t **out)

Create a CLI service handle (UART REPL backed by esp_console)

备注

Not ISR-safe. Not thread-safe for concurrent creation of the same logical instance; typical use is from one init task. May allocate heap memory.

备注

Internal mutex acquisition may block briefly when contended.

参数:
  • cfg[in] Configuration; struct_size must equal sizeof(esp_cli_service_config_t)

  • out[out] Receives new handle on success; set to NULL on error

返回:

  • ESP_OK On success

  • ESP_ERR_INVALID_ARG cfg or out is NULL, or struct_size is wrong

  • ESP_ERR_NO_MEM Allocation failed

esp_err_t esp_cli_service_destroy(esp_cli_service_t *svc)

Destroy a CLI service and free its resources.

    Stops the REPL if running, frees tracked/static command state, and invalidates @a svc.

备注

After this returns, svc must not be used even if the return code is not ESP_OK (resources are still released).

备注

Not ISR-safe. Not thread-safe against concurrent use of svc or its REPL task; call when the service is quiesced.

参数:

svc[in] Handle from esp_cli_service_create

返回:

  • ESP_OK On success.

  • ESP_ERR_INVALID_ARG svc is NULL.

  • Other Error from underlying service teardown; all resources are freed regardless.

esp_err_t esp_cli_service_bind_manager(esp_cli_service_t *svc, esp_service_manager_t *mgr)

Bind or replace the service manager used for dynamic svc / tool commands.

备注

Not ISR-safe. Thread-safe with other APIs on the same handle (mutex held briefly). May block briefly when acquiring an internal mutex.

参数:
  • svc[in] Service handle

  • mgr[in] Manager pointer (may be NULL to clear)

返回:

  • ESP_OK Manager bound.

  • ESP_ERR_INVALID_ARG svc is NULL.

  • ESP_ERR_TIMEOUT Mutex acquisition timed out.

esp_err_t esp_cli_service_track_service(esp_cli_service_t *svc, esp_service_t *service, const char *category)

Track a service by name for svc list / lifecycle commands.

    If the name already exists, updates category and service pointer.

备注

Not ISR-safe. Thread-safe with other APIs on the same handle.

参数:
  • svc[in] Service handle

  • service[in] Service to track (name from esp_service_get_name)

  • category[in] Category string for display (may be NULL, stored as empty string)

返回:

  • ESP_OK Tracked (created or updated).

  • ESP_ERR_INVALID_ARG svc or service is NULL; service name is empty.

  • ESP_ERR_NO_MEM Allocation failed.

  • ESP_ERR_TIMEOUT Mutex acquisition timed out.

  • Other Error from esp_service_get_name.

esp_err_t esp_cli_service_untrack_service(esp_cli_service_t *svc, const char *name)

Remove a tracked service entry by logical service name.

备注

Not ISR-safe. Thread-safe with other APIs on the same handle.

参数:
  • svc[in] Service handle

  • name[in] Service name previously tracked

返回:

  • ESP_OK Service untracked.

  • ESP_ERR_INVALID_ARG svc is NULL or name is empty.

  • ESP_ERR_NOT_FOUND name not in the tracked list.

  • ESP_ERR_TIMEOUT Mutex acquisition timed out.

esp_err_t esp_cli_service_register_static_command(esp_cli_service_t *svc, const esp_console_cmd_t *cmd)

Register an extra static esp_console command before or after REPL start.

    Command name must be a single token (no spaces). Strings are copied; the @a cmd
    descriptor need only live for the call. If the REPL is already running, the command is
    registered with esp_console immediately.

备注

Not ISR-safe. Thread-safe with other APIs on the same handle. Do not register from inside another command handler unless re-entrancy is safe for esp_console on your IDF version.

参数:
  • svc[in] Service handle

  • cmd[in] Command descriptor (see esp_console_cmd_t)

返回:

  • ESP_OK Command registered.

  • ESP_ERR_INVALID_ARG svc or cmd is NULL; invalid command descriptor.

  • ESP_ERR_INVALID_STATE Command name already registered.

  • ESP_ERR_NO_MEM Allocation or storage failed.

  • ESP_ERR_TIMEOUT Mutex acquisition timed out.

Structures

struct esp_cli_service_config_t

CLI service creation configuration.

    Set @c struct_size to @c sizeof(esp_cli_service_config_t) on every call. The @c reserved
    fields must be zero. Use @ref ESP_CLI_SERVICE_CONFIG_DEFAULT() unless you intentionally
    override fields.

    String ownership: @c prompt is copied internally; the pointer in @a cfg only needs to
    remain valid for the duration of @ref esp_cli_service_create. @c base_cfg fields follow
    @c esp_service_init rules.

Public Members

uint32_t struct_size

Must equal sizeof(esp_cli_service_config_t)

uint32_t reserved[2]

Reserved; must be zero

esp_service_config_t base_cfg

Core service registration configuration

const char *prompt

REPL prompt string (copied on create)

uint16_t max_cmdline_length

Maximum command line length for esp_console

uint32_t task_stack

REPL task stack size in bytes

uint32_t task_prio

REPL task priority

esp_service_manager_t *manager

Optional manager for tool commands

Macros

ESP_CLI_SERVICE_CONFIG_DEFAULT()

Type Definitions

typedef struct esp_cli_service esp_cli_service_t