diff --git a/.gitlab/ci/build.yml b/.gitlab/ci/build.yml index 689aa82..4c8dfc7 100644 --- a/.gitlab/ci/build.yml +++ b/.gitlab/ci/build.yml @@ -83,5 +83,8 @@ build_application_basic_demo: - IMAGE: espressif/idf:release-v5.5 EXAMPLE_BOARD: esp32_S3_DevKitC_1 EXAMPLE_TARGET: esp32s3 + - IMAGE: espressif/idf:release-v5.5 + EXAMPLE_BOARD: esp32_p4_function_ev + EXAMPLE_TARGET: esp32p4 variables: EXAMPLE_DIR: application/basic_demo diff --git a/.gitlab/ci/build_apps.py b/.gitlab/ci/build_apps.py index 4ee3a85..736119d 100644 --- a/.gitlab/ci/build_apps.py +++ b/.gitlab/ci/build_apps.py @@ -53,6 +53,8 @@ IGNORE_WARNINGS = [ r'warning: casting \'CvRNG\' {aka \'long long unsigned int\'} to \'cv::RNG&\' does not use \'cv::RNG::RNG\(uint64\)\' \[-Wcast-user-defined\]', # OpenCV warning: for examples/robot/ragtime_panther/follower r'WARNING: The following Kconfig variables were used in "if" clauses, but not', # Due to the introduction of Kconfig and package manager dependencies, compilation warnings are generated r'.+MultiCommand.+', + r'warning: \'ISP_AWB_SAMPLE_POINT_BEFORE_CCM\' is deprecated: Use ISP_AWB_SAMPLE_POINT_0 instead \[-Wdeprecated-declarations\]', + r'warning: \'ISP_AE_SAMPLE_POINT_AFTER_DEMOSAIC\' is deprecated: Use ISP_AE_SAMPLE_POINT_0 instead \[-Wdeprecated-declarations\]', ] class CustomApp(CMakeApp): diff --git a/README_CN.md b/README_CN.md index 6b55edc..290eebf 100644 --- a/README_CN.md +++ b/README_CN.md @@ -199,4 +199,3 @@ esp-clawgent/ Agent Loop 和 IM 通讯等功能在 ESP32 上的实现参考了 [MimiClaw](https://github.com/memovai/mimiclaw)。 MimiClaw 同时也揭示了在 ESP32-S3 上运行 OpenClaw 的可行性。 - diff --git a/application/basic_demo/CMakeLists.txt b/application/basic_demo/CMakeLists.txt index dd1bf86..73766dc 100644 --- a/application/basic_demo/CMakeLists.txt +++ b/application/basic_demo/CMakeLists.txt @@ -1,5 +1,46 @@ cmake_minimum_required(VERSION 3.16) +set(BASIC_DEMO_ESP_IDF_PATCH "${CMAKE_SOURCE_DIR}/tools/esp-idf.patch") + +if(NOT DEFINED ENV{IDF_PATH} OR "$ENV{IDF_PATH}" STREQUAL "") + message(FATAL_ERROR "IDF_PATH environment variable is not set") +endif() + +find_program(GIT_EXECUTABLE git REQUIRED) + +if(EXISTS "${BASIC_DEMO_ESP_IDF_PATCH}") + execute_process( + COMMAND ${GIT_EXECUTABLE} apply --reverse --check "${BASIC_DEMO_ESP_IDF_PATCH}" + WORKING_DIRECTORY "$ENV{IDF_PATH}" + RESULT_VARIABLE BASIC_DEMO_PATCH_ALREADY_APPLIED + OUTPUT_QUIET + ERROR_QUIET + ) + + if(BASIC_DEMO_PATCH_ALREADY_APPLIED EQUAL 0) + message(STATUS "ESP-IDF patch already applied: ${BASIC_DEMO_ESP_IDF_PATCH}") + else() + execute_process( + COMMAND ${GIT_EXECUTABLE} apply "${BASIC_DEMO_ESP_IDF_PATCH}" + WORKING_DIRECTORY "$ENV{IDF_PATH}" + RESULT_VARIABLE BASIC_DEMO_PATCH_APPLY_RESULT + OUTPUT_VARIABLE BASIC_DEMO_PATCH_APPLY_STDOUT + ERROR_VARIABLE BASIC_DEMO_PATCH_APPLY_STDERR + ) + + if(NOT BASIC_DEMO_PATCH_APPLY_RESULT EQUAL 0) + message(FATAL_ERROR + "Failed to apply ESP-IDF patch: ${BASIC_DEMO_ESP_IDF_PATCH}\n" + "stdout:\n${BASIC_DEMO_PATCH_APPLY_STDOUT}\n" + "stderr:\n${BASIC_DEMO_PATCH_APPLY_STDERR}") + endif() + + message(STATUS "Applied ESP-IDF patch: ${BASIC_DEMO_ESP_IDF_PATCH}") + endif() +else() + message(FATAL_ERROR "ESP-IDF patch file not found: ${BASIC_DEMO_ESP_IDF_PATCH}") +endif() + include($ENV{IDF_PATH}/tools/cmake/project.cmake) project(basic_demo) diff --git a/application/basic_demo/README.md b/application/basic_demo/README.md index b30e3f4..2ecc891 100644 --- a/application/basic_demo/README.md +++ b/application/basic_demo/README.md @@ -1,143 +1,29 @@ -# ESP-Clawgent +# basic_demo Guide -**事件驱动的 OpenClaw,为嵌入式场景量身定制。** +## How It Works -`ESP-Clawgent` 是一套运行于 ESP32 上的事件驱动 AI assistant,适用于需要长期运行、可持续扩展、功能持续迭代的设备侧 AI 场景 +The main entry point is `application/basic_demo/main/main.c`. -- 事件驱动:不局限于消息输入,多种外部事件都可以触发 Agent Loop -- 组件化:可按需裁切模块 -- 离线自动化:在无网络条件下执行本地规则 -- 自编程:内嵌 Lua 解释器,可由 AI 自主规划实现功能 -- 渐进式工具披露:当前 agent 能做什么,由已加载和已激活的 skills 决定 -- 超低资源占用:ESP32-C 系列上也能流畅运行 +After the device boots, the overall flow is: -## 1. What is ESP-Clawgent +1. Initialize NVS and load device settings +2. Mount FATFS at `/fatfs/data` +3. Initialize Wi-Fi and the local HTTP configuration service +4. Enter `app_clawgent_start()` +5. Initialize the event router, memory, skills, and capabilities +6. Initialize and start `claw_core` +7. Start the CLI and begin handling requests and events -项目包含示例与基础功能组件。 +The current runtime depends on the following local directories: -- `application/basic_demo/`:当前主应用,用于将这些模块装配成可运行固件 +- `/fatfs/data/sessions`: session history +- `/fatfs/data/memory/MEMORY.md`: long-term memory +- `/fatfs/data/skills`: skill documents and manifest +- `/fatfs/data/lua`: Lua scripts +- `/fatfs/data/automation/automations.json`: automation rules +- `/fatfs/data/inbox`: message attachment storage -`components/` 包含以下核心部分: - -- `claw_core`:负责完整的 agent 执行流 -- `claw_cap`:负责能力注册、调度和工具调用 -- `claw_memory`:负责会话历史和长期记忆 -- `claw_skill`:负责技能加载、技能文档和激活态技能上下文 -- `claw_event_router`:负责标准事件接入、规则路由、Agent/脚本分发和出站路由 -- `cap_*`:负责拓展具体能力,比如 QQ、Telegram、文件、时间、Web Search、MCP、Lua 等 - -## 2. How it works - -主启动入口位于 `application/basic_demo/main/main.c`。 - -设备启动后,整体流程如下: - -1. 初始化 NVS,加载设备配置 -2. 挂载 FATFS 到 `/fatfs/data` -3. 初始化 Wi-Fi 和本地 HTTP 配置服务 -4. 进入 `app_clawgent_start()` -5. 初始化 event router、memory、skills、capabilities -6. 初始化并启动 `claw_core` -7. 启动 CLI,开始响应请求和事件 - -当前运行时依赖以下本地目录: - -- `/fatfs/data/sessions`:会话历史 -- `/fatfs/data/memory/MEMORY.md`:长期记忆 -- `/fatfs/data/skills`:skills 文档和清单 -- `/fatfs/data/lua`:Lua 脚本 -- `/fatfs/data/automation/automations.json`:自动化规则 -- `/fatfs/data/inbox`:消息附件存储目录 - -### Event-driven - -`ESP-Clawgent` 的核心是“收到事件,触发行为”。 - -事件可以来自: - -- 即时通讯入口 -- 配置界面 -- 本地事件规则 -- 文件或附件输入 -- 后续扩展的 cap 事件源 - -行为可以是: - -- 调模型 -- 调工具 -- 读写本地文件 -- 执行 Lua -- 触发事件路由链路 -- 给外部 IM 回消息 - -### Progressive tool exposure - -工具不会默认一次性全部暴露给模型。 - -`claw_core` 在运行时会接入这些上下文提供器: - -- 长期记忆 -- 会话历史 -- skills list -- 已激活 skill 的文档 -- 当前 cap 工具描述 - -初始情况下,仅暴露由 `skills_list.json` 声明的基础能力。 - -- skill 没加载,模型看不到对应能力的说明 -- skill 没激活,模型拿不到对应文档上下文 -- 当前会话能做什么,是逐步展开的 - - -### Self-programming with Lua - -项目内嵌 Lua 解释器,支持 Lua 脚本编辑与运行。 - -这使得以下能力成为可能: - -- 把设备逻辑写成 Lua -- 把某些 agent 行为抽成脚本 -- 让 assistant 在现有能力之上继续组合出新的功能 - -许多扩展可以先在 Lua 层完成,无需重新烧录固件。只要向 LLM 提出具体需求,系统即可直接生成并实现对应功能。 - -## 3. Project architecture - -仓库结构如下: - -```text -esp-clawgent-master/ -├── components/ -│ ├── claw_core/ -│ ├── claw_cap/ -│ ├── claw_event_router/ -│ ├── claw_memory/ -│ ├── claw_skill/ -│ └── cap_*/ -└── application/ - └── basic_demo/ - ├── main/ - └── build/ -``` - -### Runtime layers - -- Application layer - 负责启动、配置、文件系统、Wi-Fi、HTTP 配置页和整机装配 -- Core layer - `claw_core` 负责 agent 执行流 -- cap layer - `claw_cap` 和各类 `cap_*` 负责工具和具体能力实现 -- Event routing layer - `claw_event_router` 负责统一事件入口、规则匹配、脚本/agent 调度和出站分发 -- Memory layer - `claw_memory` 负责持久化上下文 -- Skill layer - `claw_skill` 负责按 skill 控制上下文与功能暴露 - -### Current capabilities - -当前 `basic_demo` 已接入的能力包括: +The current `basic_demo` integrates the following capabilities: - `cap_im_qq` - `cap_im_tg` @@ -150,41 +36,31 @@ esp-clawgent-master/ - `cap_llm_inspect` - `cap_web_search` -### Design style - -项目的架构关键词包括: - -- event-driven -- componentized -- local-first - -联网并不是系统运行的唯一前提。无网络时,本地事件路由、Lua、文件系统和既有记忆仍可继续工作。 - -## 4. Quick Start +## Quick Start ### Prerequisites -- ESP-IDF 环境已安装并导出 -- 建议使用 `ESP-IDF v5.5.1` -- 默认目标芯片为 `esp32s3` +- ESP-IDF is installed and exported +- `ESP-IDF v5.5.4` is recommended ```bash -. /esp-idf/export.sh +. /export.sh ``` -### Build +### Configuration -所有 ESP-IDF 命令都在 `application/basic_demo/` 下执行: +To make `esp-board-manager` easier to use, first install the helper package with `pip install esp-bmgr-assist`. You only need to do this once in a given ESP-IDF environment. + +1. Generate board support files: ```bash cd application/basic_demo -idf.py set-target esp32s3 -idf.py build +idf.py gen-bmgr-config -c ./boards -b esp32_S3_DevKitC_1 ``` -### Configure +2. Configure Wi-Fi, LLM, IM, search engine, and related parameters: -当前 Demo 的关键配置包括: +The key demo settings include: - Wi-Fi SSID / Password - LLM API Key / Provider / Model @@ -193,43 +69,22 @@ idf.py build - Brave / Tavily Search Key - Timezone -可以通过 `menuconfig` 调整编译期默认值: +You can adjust compile-time default values through `menuconfig`: ```bash -cd application/basic_demo idf.py menuconfig ``` -设备运行后,配置也会通过 NVS 持久化。 - -### Notes on Keys - -- IM bot token:可通过 Telegram 的 [@BotFather](https://t.me/BotFather) 或 [QQ Bot](https://q.qq.com/qqbot/openclaw/login.html) 获取 -- LLM API key:可使用 [Anthropic Console](https://console.anthropic.com)、[OpenAI Platform](https://platform.openai.com) 或 [阿里云百炼](https://bailian.console.aliyun.com/#/api-key) 提供的 Key - - -### Flash +3. Build and flash: ```bash -cd application/basic_demo +idf.py build idf.py flash monitor ``` -如果串口不是默认值: +> `idf.py gen-bmgr-config -c ./boards -b ` generates the configuration for the specified board. Available board names can be found in the `boards` directory. -```bash -cd application/basic_demo -idf.py flash monitor -p /dev/ttyUSB0 -``` +### Key Notes -### First boot - -首次启动后,通常会看到以下阶段: - -- NVS 初始化 -- FATFS 挂载 -- 设置加载 -- Wi-Fi 和本地配置服务启动 -- memory / skills / capabilities 初始化 -- `claw_core` 启动 -- CLI 启动 +- IM bot token: available from Telegram [@BotFather](https://t.me/BotFather) or [QQ Bot](https://q.qq.com/qqbot/openclaw/login.html) +- LLM API key: available from [Anthropic Console](https://console.anthropic.com), [OpenAI Platform](https://platform.openai.com), or [Alibaba Cloud Bailian](https://bailian.console.aliyun.com/#/api-key) diff --git a/application/basic_demo/tools/esp-idf.patch b/application/basic_demo/tools/esp-idf.patch new file mode 100644 index 0000000..94227ee --- /dev/null +++ b/application/basic_demo/tools/esp-idf.patch @@ -0,0 +1,26 @@ +diff --git a/components/esp_lcd/parl/esp_lcd_panel_io_parl.c b/components/esp_lcd/parl/esp_lcd_panel_io_parl.c +index efdba5926af..1c22adaa39f 100644 +--- a/components/esp_lcd/parl/esp_lcd_panel_io_parl.c ++++ b/components/esp_lcd/parl/esp_lcd_panel_io_parl.c +@@ -115,7 +115,7 @@ esp_err_t esp_lcd_new_panel_io_parl(const esp_lcd_panel_io_parl_config_t *io_con + .output_clk_freq_hz = io_config->pclk_hz, + .trans_queue_depth = io_config->trans_queue_depth ? io_config->trans_queue_depth : 4, + .max_transfer_size = io_config->max_transfer_bytes, +- .sample_edge = PARLIO_SAMPLE_EDGE_POS, ++ .sample_edge = PARLIO_SAMPLE_EDGE_NEG, + .bit_pack_order = PARLIO_BIT_PACK_ORDER_MSB, + .dma_burst_size = io_config->dma_burst_size, + .flags.invert_valid_out = !io_config->flags.cs_active_high, +diff --git a/components/usb/include/usb/usb_types_ch9.h b/components/usb/include/usb/usb_types_ch9.h +index f54f94842a0..a1214324fd2 100644 +--- a/components/usb/include/usb/usb_types_ch9.h ++++ b/components/usb/include/usb/usb_types_ch9.h +@@ -384,7 +384,7 @@ ESP_STATIC_ASSERT(sizeof(usb_config_desc_t) == USB_CONFIG_DESC_SIZE, "Size of us + /** + * @brief Size of a USB interface association descriptor in bytes + */ +-#define USB_IAD_DESC_SIZE 9 ++#define USB_IAD_DESC_SIZE 8 + + /** + * @brief Structure representing a USB interface association descriptor diff --git a/components/lua_modules/esp_painter/esp_painter.c b/components/lua_modules/esp_painter/esp_painter.c index a851cb0..cefae0c 100644 --- a/components/lua_modules/esp_painter/esp_painter.c +++ b/components/lua_modules/esp_painter/esp_painter.c @@ -11,6 +11,7 @@ #include "esp_painter.h" #include "esp_cache.h" #include "esp_heap_caps.h" +#undef CONFIG_SOC_PPA_SUPPORTED #define CONFIG_SOC_PPA_SUPPORTED 0 #if CONFIG_SOC_PPA_SUPPORTED #include "esp_private/esp_cache_private.h"