feat: 添加 console_simple_init 组件支持,提供可交互控制台功能
This commit is contained in:
164
CONSOLE_SIMPLE_INIT_BLOG_ZH.md
Normal file
164
CONSOLE_SIMPLE_INIT_BLOG_ZH.md
Normal file
@@ -0,0 +1,164 @@
|
|||||||
|
# 用 `console_simple_init` 给 ESP-IDF 项目加一个可交互控制台(中文实践)
|
||||||
|
|
||||||
|
很多时候我们在调 ESP32 项目时,会遇到这种场景:
|
||||||
|
|
||||||
|
- 想临时执行一个命令看状态
|
||||||
|
- 想在线触发某个动作(比如开关某个外设)
|
||||||
|
- 不想每次都改代码、烧录、再看日志
|
||||||
|
|
||||||
|
这时候,一个可交互的 Console 就非常有价值。
|
||||||
|
|
||||||
|
这篇文章记录一个通用做法:在任何 ESP-IDF 项目里,用 `espressif/console_simple_init` 快速接入命令行控制台。
|
||||||
|
|
||||||
|
## 一、为什么用它
|
||||||
|
|
||||||
|
原生 `esp_console` 功能很完整,但初始化流程相对分散。`console_simple_init` 的价值在于把常用步骤封装成了 4 个 API:
|
||||||
|
|
||||||
|
- `console_cmd_init()`:初始化控制台
|
||||||
|
- `console_cmd_user_register()`:注册用户命令
|
||||||
|
- `console_cmd_all_register()`:自动注册插件命令
|
||||||
|
- `console_cmd_start()`:启动 REPL
|
||||||
|
|
||||||
|
一句话:快速可用,适合先跑通再扩展。
|
||||||
|
|
||||||
|
## 二、接入步骤
|
||||||
|
|
||||||
|
### 1. 添加组件依赖
|
||||||
|
|
||||||
|
```bash
|
||||||
|
idf.py add-dependency "espressif/console_simple_init^1.1.0"
|
||||||
|
```
|
||||||
|
|
||||||
|
或者在 `idf_component.yml` 里手动添加:
|
||||||
|
|
||||||
|
```yaml
|
||||||
|
dependencies:
|
||||||
|
idf: ">=5.0"
|
||||||
|
espressif/console_simple_init: ^1.1.0
|
||||||
|
```
|
||||||
|
|
||||||
|
### 2. 在 CMake 里声明依赖
|
||||||
|
|
||||||
|
在你的组件 `CMakeLists.txt`(例如 `main/CMakeLists.txt`)里:
|
||||||
|
|
||||||
|
```cmake
|
||||||
|
idf_component_register(
|
||||||
|
SRCS "main.c"
|
||||||
|
INCLUDE_DIRS "."
|
||||||
|
REQUIRES console_simple_init console
|
||||||
|
)
|
||||||
|
```
|
||||||
|
|
||||||
|
这里建议把 `console` 显式写上,能避免一类常见的 include/IntelliSense 问题(后文会讲)。
|
||||||
|
|
||||||
|
### 3. 在代码里初始化并注册命令
|
||||||
|
|
||||||
|
```c
|
||||||
|
#include <stdio.h>
|
||||||
|
#include "esp_check.h"
|
||||||
|
#include "console_simple_init.h"
|
||||||
|
|
||||||
|
static int cmd_hello(int argc, char **argv)
|
||||||
|
{
|
||||||
|
(void)argc;
|
||||||
|
(void)argv;
|
||||||
|
printf("hello from console\n");
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
void app_main(void)
|
||||||
|
{
|
||||||
|
// 你的项目里需确保 NVS 和默认事件循环已初始化
|
||||||
|
|
||||||
|
ESP_ERROR_CHECK(console_cmd_init());
|
||||||
|
ESP_ERROR_CHECK(console_cmd_user_register("hello", cmd_hello));
|
||||||
|
ESP_ERROR_CHECK(console_cmd_all_register()); // 可选
|
||||||
|
ESP_ERROR_CHECK(console_cmd_start());
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
### 4. 烧录后验证
|
||||||
|
|
||||||
|
```bash
|
||||||
|
idf.py flash monitor
|
||||||
|
```
|
||||||
|
|
||||||
|
在 `esp>` 提示符输入:
|
||||||
|
|
||||||
|
- `help`
|
||||||
|
- `hello`
|
||||||
|
|
||||||
|
如果能看到输出,说明接入成功。
|
||||||
|
|
||||||
|
## 三、一个很常见的坑
|
||||||
|
|
||||||
|
### 现象
|
||||||
|
|
||||||
|
- `#include "console_simple_init.h"` 报 include 错
|
||||||
|
- 或提示找不到 `esp_console.h`
|
||||||
|
|
||||||
|
### 本质
|
||||||
|
|
||||||
|
`console_simple_init.h` 会依赖 `esp_console.h`。如果你的组件没有显式依赖 `console`,编辑器索引有时会解析不到。
|
||||||
|
|
||||||
|
### 解决
|
||||||
|
|
||||||
|
1. CMake 增加 `REQUIRES console`
|
||||||
|
2. 执行:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
idf.py reconfigure
|
||||||
|
idf.py build
|
||||||
|
```
|
||||||
|
|
||||||
|
3. 在 VS Code 刷新索引(Reset IntelliSense Database + Reload Window)
|
||||||
|
|
||||||
|
## 四、另一个常见坑:串口写入超时
|
||||||
|
|
||||||
|
### 现象
|
||||||
|
|
||||||
|
Monitor 日志里反复出现:
|
||||||
|
|
||||||
|
- `Writing to serial is timing out...`
|
||||||
|
|
||||||
|
### 本质
|
||||||
|
|
||||||
|
Console 所用的通道(UART / USB CDC / USB Serial/JTAG)和你当前 monitor 连接端口不一致。
|
||||||
|
|
||||||
|
### 解决
|
||||||
|
|
||||||
|
在 `menuconfig` 里把 console 输出通道配置成和你实际连接一致:
|
||||||
|
|
||||||
|
- `Component config -> ESP System Settings -> Channel for console output`
|
||||||
|
|
||||||
|
改完后重新 build + flash。
|
||||||
|
|
||||||
|
## 五、为什么它适合做“运维入口”
|
||||||
|
|
||||||
|
当项目复杂起来后,你会很自然地需要这些命令:
|
||||||
|
|
||||||
|
- `status`:看系统状态
|
||||||
|
- `sensor`:看传感器实时值
|
||||||
|
- `pump on/off`:控制执行器
|
||||||
|
- `wifi status`:看联网状态
|
||||||
|
|
||||||
|
有了 console,这些能力都能在不改 UI 的情况下快速加上。
|
||||||
|
|
||||||
|
## 六、我建议的演进路线
|
||||||
|
|
||||||
|
1. 先做 1~2 个命令跑通链路
|
||||||
|
2. 加参数解析和错误提示
|
||||||
|
3. 按模块分组命令(sensor/io/net)
|
||||||
|
4. 给危险动作加确认机制
|
||||||
|
|
||||||
|
## 七、总结
|
||||||
|
|
||||||
|
`console_simple_init` 的优势不是“功能比 `esp_console` 更多”,而是把接入门槛降得很低:
|
||||||
|
|
||||||
|
- 依赖加上
|
||||||
|
- 几个 API 调用
|
||||||
|
- 很快就能得到可交互的调试入口
|
||||||
|
|
||||||
|
对于早期开发和现场调试,它能显著减少反复烧录的成本。
|
||||||
|
|
||||||
|
|
||||||
174
CONSOLE_SIMPLE_INIT_TUTORIAL.md
Normal file
174
CONSOLE_SIMPLE_INIT_TUTORIAL.md
Normal file
@@ -0,0 +1,174 @@
|
|||||||
|
# ESP-IDF `console_simple_init` Tutorial (Project-Independent)
|
||||||
|
|
||||||
|
This guide is a standalone tutorial for adding and using `espressif/console_simple_init` in any ESP-IDF project.
|
||||||
|
|
||||||
|
## 1. What This Component Does
|
||||||
|
|
||||||
|
`console_simple_init` is a convenience wrapper around ESP-IDF console/REPL setup.
|
||||||
|
|
||||||
|
It provides these APIs:
|
||||||
|
|
||||||
|
- `console_cmd_init()`
|
||||||
|
- `console_cmd_user_register()`
|
||||||
|
- `console_cmd_all_register()`
|
||||||
|
- `console_cmd_start()`
|
||||||
|
|
||||||
|
Header:
|
||||||
|
|
||||||
|
```c
|
||||||
|
#include "console_simple_init.h"
|
||||||
|
```
|
||||||
|
|
||||||
|
## 2. Add Dependency
|
||||||
|
|
||||||
|
Run:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
idf.py add-dependency "espressif/console_simple_init^1.1.0"
|
||||||
|
```
|
||||||
|
|
||||||
|
Or edit your component manifest (`idf_component.yml`):
|
||||||
|
|
||||||
|
```yaml
|
||||||
|
dependencies:
|
||||||
|
idf: ">=5.0"
|
||||||
|
espressif/console_simple_init: ^1.1.0
|
||||||
|
```
|
||||||
|
|
||||||
|
## 3. Declare CMake Dependency
|
||||||
|
|
||||||
|
In your component `CMakeLists.txt` (for example `main/CMakeLists.txt`):
|
||||||
|
|
||||||
|
```cmake
|
||||||
|
idf_component_register(
|
||||||
|
SRCS "main.c"
|
||||||
|
INCLUDE_DIRS "."
|
||||||
|
REQUIRES console_simple_init console
|
||||||
|
)
|
||||||
|
```
|
||||||
|
|
||||||
|
Why include `console` explicitly?
|
||||||
|
|
||||||
|
- `console_simple_init.h` uses `esp_console.h`.
|
||||||
|
- Explicit `REQUIRES console` avoids include path and IntelliSense issues.
|
||||||
|
|
||||||
|
## 4. Minimal Working Example
|
||||||
|
|
||||||
|
```c
|
||||||
|
#include <stdio.h>
|
||||||
|
#include "esp_check.h"
|
||||||
|
#include "console_simple_init.h"
|
||||||
|
|
||||||
|
static int cmd_hello(int argc, char **argv)
|
||||||
|
{
|
||||||
|
(void)argc;
|
||||||
|
(void)argv;
|
||||||
|
printf("hello from console\n");
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
void app_main(void)
|
||||||
|
{
|
||||||
|
// Ensure required system init is done in your app:
|
||||||
|
// - NVS initialized
|
||||||
|
// - default event loop created
|
||||||
|
|
||||||
|
ESP_ERROR_CHECK(console_cmd_init());
|
||||||
|
ESP_ERROR_CHECK(console_cmd_user_register("hello", cmd_hello));
|
||||||
|
ESP_ERROR_CHECK(console_cmd_all_register()); // optional
|
||||||
|
ESP_ERROR_CHECK(console_cmd_start());
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
## 5. Preconditions
|
||||||
|
|
||||||
|
Before starting console, make sure your app has initialized:
|
||||||
|
|
||||||
|
- NVS (`nvs_flash_init`)
|
||||||
|
- default event loop (`esp_event_loop_create_default`)
|
||||||
|
|
||||||
|
If your project already has a network/bootstrap module, these may already be done.
|
||||||
|
|
||||||
|
## 6. How to Use at Runtime
|
||||||
|
|
||||||
|
1. Flash firmware.
|
||||||
|
2. Open monitor (`idf.py monitor`).
|
||||||
|
3. At prompt `esp>`, type:
|
||||||
|
|
||||||
|
```text
|
||||||
|
help
|
||||||
|
hello
|
||||||
|
```
|
||||||
|
|
||||||
|
## 7. Console Channel Selection (Important)
|
||||||
|
|
||||||
|
Pick the console channel to match your physical connection:
|
||||||
|
|
||||||
|
- UART
|
||||||
|
- USB CDC
|
||||||
|
- USB Serial/JTAG
|
||||||
|
|
||||||
|
If channel and monitor port do not match, you may see warnings like write timeout when typing commands.
|
||||||
|
|
||||||
|
Configure via `menuconfig`:
|
||||||
|
|
||||||
|
- `Component config -> ESP System Settings -> Channel for console output`
|
||||||
|
|
||||||
|
Then rebuild and flash.
|
||||||
|
|
||||||
|
## 8. Common Issues
|
||||||
|
|
||||||
|
### Issue A: `#include` errors for `console_simple_init.h` or `esp_console.h`
|
||||||
|
|
||||||
|
Checklist:
|
||||||
|
|
||||||
|
- Added dependency in `idf_component.yml`
|
||||||
|
- Added `REQUIRES console_simple_init console` in `CMakeLists.txt`
|
||||||
|
- Re-run:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
idf.py reconfigure
|
||||||
|
idf.py build
|
||||||
|
```
|
||||||
|
|
||||||
|
- Refresh editor index/IntelliSense
|
||||||
|
|
||||||
|
### Issue B: Serial port busy while flashing
|
||||||
|
|
||||||
|
Another monitor/process holds the port.
|
||||||
|
|
||||||
|
- Close monitor first
|
||||||
|
- Retry `idf.py flash`
|
||||||
|
|
||||||
|
### Issue C: Console starts but input behaves poorly
|
||||||
|
|
||||||
|
Your terminal may not support escape sequences/history editing.
|
||||||
|
|
||||||
|
Use a terminal that supports VT sequences.
|
||||||
|
|
||||||
|
## 9. Next Step Ideas
|
||||||
|
|
||||||
|
- Add commands for system status (`status`)
|
||||||
|
- Add commands for peripheral control (`pump on`, `light off`)
|
||||||
|
- Add argument parsing and help text
|
||||||
|
- Group commands by module for maintainability
|
||||||
|
|
||||||
|
## 10. Quick Command Template
|
||||||
|
|
||||||
|
Use this template to add a command quickly:
|
||||||
|
|
||||||
|
```c
|
||||||
|
static int cmd_name(int argc, char **argv)
|
||||||
|
{
|
||||||
|
// parse args
|
||||||
|
// run logic
|
||||||
|
// print result
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
ESP_ERROR_CHECK(console_cmd_user_register("name", cmd_name));
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
This tutorial is intentionally generic so it can be reused in any ESP-IDF codebase.
|
||||||
@@ -9,6 +9,16 @@ dependencies:
|
|||||||
registry_url: https://components.espressif.com/
|
registry_url: https://components.espressif.com/
|
||||||
type: service
|
type: service
|
||||||
version: 2.0.0
|
version: 2.0.0
|
||||||
|
espressif/console_simple_init:
|
||||||
|
component_hash: b488b12318f3cb6e0b55b034bd12956926d45f0e1396442e820f8ece4776c306
|
||||||
|
dependencies:
|
||||||
|
- name: idf
|
||||||
|
require: private
|
||||||
|
version: '>=5.0'
|
||||||
|
source:
|
||||||
|
registry_url: https://components.espressif.com/
|
||||||
|
type: service
|
||||||
|
version: 1.1.0
|
||||||
espressif/esp_lvgl_port:
|
espressif/esp_lvgl_port:
|
||||||
component_hash: b6360960f47b6776462e7092861b3ea66477ffb762a01baa0aecbb3d74cd50f4
|
component_hash: b6360960f47b6776462e7092861b3ea66477ffb762a01baa0aecbb3d74cd50f4
|
||||||
dependencies:
|
dependencies:
|
||||||
@@ -60,9 +70,10 @@ dependencies:
|
|||||||
version: 9.5.0
|
version: 9.5.0
|
||||||
direct_dependencies:
|
direct_dependencies:
|
||||||
- espressif/bh1750
|
- espressif/bh1750
|
||||||
|
- espressif/console_simple_init
|
||||||
- espressif/esp_lvgl_port
|
- espressif/esp_lvgl_port
|
||||||
- idf
|
- idf
|
||||||
- k0i05/esp_ahtxx
|
- k0i05/esp_ahtxx
|
||||||
manifest_hash: 5762034b4c66072216d7ea1b788e5406026bf0ac8db349bd46ccb04dc37ff0d1
|
manifest_hash: 876b8b787041413cd7d3f71227f1618dceac35f343e17a5874d56c77837d0705
|
||||||
target: esp32c3
|
target: esp32c3
|
||||||
version: 2.0.0
|
version: 2.0.0
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
idf_component_register(SRCS "main.c"
|
idf_component_register(SRCS "main.c"
|
||||||
INCLUDE_DIRS "."
|
INCLUDE_DIRS "."
|
||||||
REQUIRES wifi-connect esp_lvgl_port lvgl_st7735s_use i2c_master_messager io_device_control
|
REQUIRES wifi-connect esp_lvgl_port lvgl_st7735s_use i2c_master_messager io_device_control console_simple_init console
|
||||||
)
|
)
|
||||||
|
|||||||
@@ -17,3 +17,4 @@ dependencies:
|
|||||||
espressif/esp_lvgl_port: ^2.7.2
|
espressif/esp_lvgl_port: ^2.7.2
|
||||||
espressif/bh1750: ^2.0.0
|
espressif/bh1750: ^2.0.0
|
||||||
k0i05/esp_ahtxx: ^1.2.7
|
k0i05/esp_ahtxx: ^1.2.7
|
||||||
|
espressif/console_simple_init: ^1.1.0
|
||||||
|
|||||||
13
main/main.c
13
main/main.c
@@ -9,6 +9,7 @@
|
|||||||
#include "lvgl_st7735s_use.h"
|
#include "lvgl_st7735s_use.h"
|
||||||
#include "i2c_master_messager.h"
|
#include "i2c_master_messager.h"
|
||||||
#include "io_device_control.h"
|
#include "io_device_control.h"
|
||||||
|
#include "console_simple_init.h" // 提供 console_cmd_user_register 和 console_cmd_all_register
|
||||||
|
|
||||||
#ifndef CONFIG_I2C_MASTER_MESSAGER_BH1750_ENABLE
|
#ifndef CONFIG_I2C_MASTER_MESSAGER_BH1750_ENABLE
|
||||||
#define CONFIG_I2C_MASTER_MESSAGER_BH1750_ENABLE 0
|
#define CONFIG_I2C_MASTER_MESSAGER_BH1750_ENABLE 0
|
||||||
@@ -41,12 +42,23 @@
|
|||||||
|
|
||||||
static const char *TAG = "main";
|
static const char *TAG = "main";
|
||||||
|
|
||||||
|
static int cmd_hello(int argc, char **argv)
|
||||||
|
{
|
||||||
|
printf("hello from BotanicalBuddy\n");
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
void app_main(void)
|
void app_main(void)
|
||||||
{
|
{
|
||||||
// 初始化 Wi-Fi 配网组件,支持长按按键进入配网
|
// 初始化 Wi-Fi 配网组件,支持长按按键进入配网
|
||||||
ESP_ERROR_CHECK(wifi_connect_init());
|
ESP_ERROR_CHECK(wifi_connect_init());
|
||||||
printf("设备启动完成:长按按键进入配网模式,手机连接 ESP32-* 后访问 http://192.168.4.1\n");
|
printf("设备启动完成:长按按键进入配网模式,手机连接 ESP32-* 后访问 http://192.168.4.1\n");
|
||||||
|
|
||||||
|
ESP_ERROR_CHECK(console_cmd_init());
|
||||||
|
ESP_ERROR_CHECK(console_cmd_user_register("hello", cmd_hello));
|
||||||
|
ESP_ERROR_CHECK(console_cmd_all_register()); // 可选:自动注册插件命令
|
||||||
|
ESP_ERROR_CHECK(console_cmd_start());
|
||||||
|
|
||||||
// 启动 LVGL 演示程序,显示简单的界面
|
// 启动 LVGL 演示程序,显示简单的界面
|
||||||
ESP_ERROR_CHECK(start_lvgl_demo());
|
ESP_ERROR_CHECK(start_lvgl_demo());
|
||||||
|
|
||||||
@@ -120,7 +132,6 @@ void app_main(void)
|
|||||||
{
|
{
|
||||||
ESP_ERROR_CHECK(lvgl_st7735s_set_center_text("Sensor waiting..."));
|
ESP_ERROR_CHECK(lvgl_st7735s_set_center_text("Sensor waiting..."));
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
else if (i2c_ready)
|
else if (i2c_ready)
|
||||||
{
|
{
|
||||||
|
|||||||
Reference in New Issue
Block a user