chore: checkpoint 第一版
ci / verify (push) Canceled after 0s

This commit is contained in:
Codex Local
2026-09-06 17:04:11 +08:00
parent a8cdec98d1
commit 0c2151ace9
659 changed files with 185855 additions and 554 deletions
+211
View File
@@ -0,0 +1,211 @@
<h1 align="center"><img src="https://iam.volccdn.com/obj/volcengine-public/pic/volcengine-icon.png"></h1>
<h1 align="center">ConversationalAI Embedded Kit 2.0 </h1>
## EchoEar 平台版固件
本目录是在火山官方 Embedded Kit 2.0 基础上适配的 ESP32-S3 EchoEar 固件。它使用低负载 WebSocket 方案,并将设备身份、动态注册和会话配置统一接入自有 SaaS。
安全边界:
- 固件和设备端都不包含火山 `Product Secret`;
- SaaS 使用平台设备身份为 EchoEar 动态申请火山 `Device Secret`;
- EchoEar 只保存自己的平台设备凭据和火山单设备凭据;
- 每次对话前由 SaaS 下发 Bot、人设、记忆上下文和会话配置;
- 字幕和最终轮次回传 SaaS,供会话记录与长期记忆处理。
当前测试硬件:ESP32-S3 EchoEar,16 MB Flash、16 MB PSRAM,硬件标识由 STA MAC 生成(当前板为 `echoear-b43a451634a8`)。
每次申请对话前,先通过 `/device/v2/bootstrap` 上报实际固件版本并检查 `firmware_compatible`,再获取配置和创建会话。固件版本为 `1.0.0-echoear-platform.1`;本工程基于 Embedded Kit 2.0,硬件智能体 SDK 版本独立上报为 `2.0.0`。会话能力中的 `sdk_version` 不能用固件版本代替。会话尚未创建时保持唤醒采集,不重复拆建音频管线。SPI 屏幕仅在 `on_color_trans_done` 后释放 GFX 帧缓冲,避免异步传输期间提前复用缓冲区。运行状态用眼睛动画表示,避免 80 MHz 下中文逐像素渲染长期占用 CPU:快速眨眼表示聆听,转圈表示思考,正常眼睛表示待机或回答。
本板构建使用 16 MB Flash,Flash 与八线 PSRAM 均为 80 MHz。通用默认配置、ESP32-S3 默认配置和当前 `sdkconfig` 必须一致;不要恢复上游的 32 MB Flash 或实验性 120 MHz PSRAM 参数。
唤醒词为“嗨,乐鑫”,启用 `CONFIG_SR_WN_WN9_HILEXIN`,使用 `DET_MODE_95` 高灵敏度检测,并将 AFE 线性增益设为 2.0。生成的 `build/srmodels/srmodels.bin` 必须包含 `wn9_hilexin` 模型(约291 KB),并烧录到 `model` 分区 `0x510000`;不能使用未选择任何模型时生成的4字节空文件。
EchoEar V1.2 的 ES7210 使用 TDM:I2S 按两路32位接收,AFE 按四路16位解释,布局为 `RMNM`(ch1/ch3 麦克风、ch0 回声参考、ch2 忽略)。不可改成两路16位 `MR`。诊断日志 `MIC_LEVEL` 仅记录各路幅度统计,不保存录音。PCM输出每帧60 ms、16 kHz、单声道16位,读取缓冲区为1920字节,避免截断半帧。唤醒事件在会话服务就绪后直接发布,不依赖已移除的 `CONFIG_LANGUAGE_WAKEUP_MODE`。
低负载 WebSocket 任务使用 12 KiB 栈;4 KiB 会在收到 `session.created` 后发生栈溢出并重启。握手期间暂停上传麦克风帧,待引擎进入 STARTED 后再发送。低负载接口返回的 PCM 按 24 kHz 单声道16位解码,再由播放管线转换到板载 16 kHz I2S。`session.created` 的 `job_id` 用作平台启动确认,确保后续字幕和结束事件在 ACTIVE 会话上提交。
联网、平台 HTTPS 激活和音频初始化在独立的 24 KiB 启动任务中执行,避免默认 4 KiB `main` 栈溢出导致循环重启;任务退出时释放栈,并记录启动阶段最小栈余量。平台激活成功后才启动音频采集。激活失败时保留设备配置、显示绑定或配置提示,并仅记录平台错误码,不输出响应正文或凭据。
STA 连接使用全信道扫描并按信号强度选择同名 AP,实时语音期间关闭 Wi-Fi 省电,避免多 AP 环境中误连弱信号节点造成 WebSocket 写入失败。
### Windows 编译与烧录
使用 ESP-IDF v5.5.1:
```powershell
. 'E:\Codex\toolchains\esp-idf-v5.5.1\export.ps1'
idf.py build
idf.py -p COM6 flash
idf.py -p COM6 monitor
```
首次烧录前建议完整备份 Flash。当前板原厂备份位于 `backups/b43a451634a8/factory-2026-09-03-16mb.bin`,恢复命令:
```powershell
esptool.py --chip esp32s3 --port COM6 write_flash 0x0 backups/b43a451634a8/factory-2026-09-03-16mb.bin
```
### 首次激活
首次启动、缺少平台设备凭据、保存的 Wi-Fi 连接失败或超时,以及手动请求重新配网时,都会进入配置热点,无需清空 NVS:
1. 连接 `VolcConvAI-XXXXXX`,热点密码与热点名相同;
2. 打开 `http://192.168.4.1`;
3. 填写 2.4 GHz Wi-Fi、平台 Device ID 和平台 Device Secret;
4. 重启后,设备通过 SaaS 完成火山动态注册并获取单设备运行凭据。
正常运行时短触圆屏任意位置可直接开始对话,作为唤醒词的可靠备用入口。屏幕底部区域持续按住3秒后设备重启并开启配置热点。该操作保留原来的 Wi-Fi 和设备身份,只记录重新配网请求;成功提交配网页后退出配网模式。触摸任务在联网和平台激活之前创建,因此激活失败时也可以请求重新配网。
如果尚未配置平台设备身份,固件不会尝试用 Product Secret 直接访问火山。
重新配网回归检查(需要烧录后实机验证):
- 已保存可用 Wi-Fi、但缺少平台凭据:启动后直接出现热点和配网地址。
- Wi-Fi 密码错误或 DHCP 超时:连接等待结束后进入热点,不能重启循环。
- 正常运行时:短触屏幕启动对话;按住屏幕底部区域3秒进入配置热点。
- 配网页提交错误 Wi-Fi 后可重试;只有取得 IP 地址后才保存配置并重启。
- 配网页成功提交后正常启动,手动配网请求清除,原平台身份不会因进入配网而被删除。
本地 `idf.py build` 仅验证编译、链接和分区大小,不代替热点可见性、触摸坐标及长按时长的实机验证。
配网页提交使用 JSON 与后台连接任务,`POST /submit` 受理后立即返回 202,页面通过 `GET /setup-status` 查询连接、保存成功或失败状态。连接失败可以重试;保存成功后等待15秒重启,再由启动流程执行平台激活。Wi-Fi 扫描改为手动触发,连接期间不扫描。更新固件后请刷新配网页,避免继续使用已经打开的旧表单。
配网页交互回归:`node --test tests/setup-portal.test.cjs`(模拟设备响应,覆盖失败重试、响应丢失、断联、成功提示和输入校验)。
## 快速开始
具体操作,请参考 [官网文档](https://www.volcengine.com/docs/6348/1806625)。
## 运行设备端(乐鑫)
以下操作以 macOS 操作系统为例。
### 环境与硬件要求
- 乐鑫 ESP32-S3-Korvo-2
- USB 数据线:两条 A 转 Micro-B 数据线,一条作为电源线,一条作为串口线。
- PC 设备:编译和烧录。支持 Windows、Linux 或者 macOS 操作系统。(本文操作以 macOS 为例)
### 配置乐鑫环境
详见[开发环境配置文档](https://docs.espressif.com/projects/esp-idf/zh_CN/stable/esp32s3/get-started/index.html)。
1. 安装 CMake 和 Ninja 编译工具。
```bash
brew install cmake ninja dfu-util
```
2. 将乐鑫 ADF 框架克隆到本地,并同步各子仓(submodule)代码。
> **注意**:Demo 中使用的 ADF 版本为 `eca11f20e56f9b5321b714da4305e123672d92a9`,对应 IDF 版本为 `v5.4`,请确保 ADF 版本与 IDF 版本匹配。
>
```bash
# 1. clone 乐鑫 ADF 框架
git clone https://github.com/espressif/esp-adf.git
# 2. 进入esp-adf目录
cd esp-adf
# 3. 切换到乐鑫 ADF 指定版本
git reset --hard eca11f20e56f9b5321b714da4305e123672d92a9
# 4. 同步各子仓代码
git submodule update --init --recursive
```
3. 安装乐鑫 esp32s3 开发环境相关依赖。
```bash
./install.sh esp32s3
```
成功安装所有依赖后,命令行会出现如下提示:
```bash
All done! You can now run:
. ./export.sh
```
> 如在上述任何步骤中遇到以下错误:
> `<urlopen error [SSL: CERTIFICATE_VERIFY_FAILED] certificate verify failed: unable to get local issuer certificate (_ssl.c:xxx)`
> 可前往**访达->应用程序->Python** 文件夹,点击 `Install Certificates.command` 安装证书。更多信息,请参考 [安装 ESP-IDF 工具时出现的下载错误](https://github.com/espressif/esp-idf/issues/4775)。
>
4. 设置环境变量。
> **每次打开命令行窗口均需要运行该命令进行设置。**
>
```bash
. ./export.sh
```
### 下载并配置工程
1. 将实时对话式 AI 硬件示例工程克隆到 乐鑫 ADF examples 目录下。
1. 进入 esp-adf/examples 目录。
```bash
cd $ADF_PATH/examples
```
2. 克隆实时对话式 AI 硬件示例工程。
```bash
git clone https://github.com/volcengine/ConversationalAI-Embedded-Kit-2.0.git
```
2. 修复乐鑫按键问题
1. 进入 esp-adf 目录。
```bash
cd $ADF_PATH
```
2. 修复乐鑫按键问题。
```bash
git apply $ADF_PATH/examples/ConversationalAI-Embedded-Kit-2.0/low_load_first/espressif/0002-fix-esp-button.patch
```
### 编译固件
进入 `esp-adf/examples/ConversationalAI-Embedded-Kit-2.0/low_load_first/espressif` 目录下编译固件。
1. 进入 espressif 目录。
```bash
cd $ADF_PATH/examples/ConversationalAI-Embedded-Kit-2.0/low_load_first/espressif
```
2. 设置编译目标平台。
```bash
idf.py set-target esp32s3
```
3. 设置 实例ID、产品ID、产品秘钥、设备ID等参数。
```bash
idf.py menuconfig
```
进入 `Example Configuration` 菜单,在 `volcano instance id` 中填入你的实例ID,在 `volcano product key` 中填入你的产品Key,在 `volcano product secret` 中填入你的产品秘钥,在 `device name` 中填入你的设备ID, 在 `bot id` 中填入你的智能体ID,并保存。
4. 编译固件。
```bash
idf.py build
```
### 烧录并运行示例 Demo
1. 打开乐鑫开发板电源开关。
2. 烧录固件。
```bash
idf.py flash
```
3. 运行示例 Demo 并查看串口日志输出。
```bash
idf.py monitor
```
4. Wi-Fi 配网。
1. 手机找到名如 VolcConvAI-XXXXXX” 的 Wi-Fi 热点,密码同Wi-Fi名,连接上 Wi-Fi。
2. 打开浏览器,在地址栏输入 `http://192.168.4.1`,进入 Wi-Fi 配网页面。
3. 输入 Wi-Fi 名称和密码,点击提交。
> **注意**:如果需更换 Wi-Fi,请重启设备。如果设备重启后无法连接到之前保存的 Wi-Fi(例如超出了范围或旧网络已关闭),请等待 30s 进入配网模式,再重新执行上面 Wi-Fi 配网的 3 个步骤。
>