1、按键驱动重构:从GPIO中断改为iot_button组件,支持BOOT/KEY2的单击/双击/长按6种事件; 2、新增按键导航管理器(key_nav):9种上下文状态机,统一分发按键事件到对应界面业务逻辑; 3、BLE模块改造:广播默认关闭由按键触发,新增设备间图片传输(GATT Client),支持扫描配对→MTU协商→分包发送; 4、新增6个UI界面:配对(Peiwang)、更新(Update)、发送等待(ImageShar)、接收等待(ImageReception)、发送中(Sharing)、接收中(Receiving); 5、新增电池指示器组件(battery_ui):支持多界面真实电量显示,3秒渐隐效果; 6、Home界面重构:移除手势事件,改为airhub背景图+电池指示器; 7、Img界面重构:移除触摸事件,新增删除二次确认边框机制; 8、禁用ScreenSet/ScreenChar界面(保留文件),禁用触摸初始化(保留代码可恢复); 9、sleep_mgr简化:移除ScreenSet亮度UI依赖,按键唤醒由key_nav统一处理; 10、新增9张图片资源(airhub背景、配对、传输状态、电池图标等); Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
187 lines
7.2 KiB
Markdown
187 lines
7.2 KiB
Markdown
# 按键版电子吧唧移植到 Baji_Rtc_Toy_Key 方案
|
||
|
||
## 一、目标项目分析
|
||
|
||
### 1.1 项目架构
|
||
`Baji_Rtc_Toy_Key` 是 AI 对话 + 电子吧唧双模式项目,通过 NVS 存储的 `device_mode` 切换:
|
||
- **AI 模式** (`DEVICE_MODE_AI`): 火山引擎 RTC 语音对话 + GIF 表情
|
||
- **电子吧唧模式** (`DEVICE_MODE_BADGE`): 图片浏览 + BLE 传图(当前仍为触屏版)
|
||
|
||
### 1.2 目标项目已有的吧唧模块(`main/dzbj/` 目录)
|
||
| 文件 | 功能 | 状态 |
|
||
|------|------|------|
|
||
| `dzbj_ble.c` | GATT Server(APP 传图) | ✅ 已有,仅 Server |
|
||
| `dzbj_button.c` | ISR 轮询按键 | ⚠️ 需替换为 iot_button |
|
||
| `dzbj_battery.c` | 电池 ADC 采样 | ✅ 已有 |
|
||
| `sleep_mgr.c` | 休眠管理 | ✅ 已有 |
|
||
| `fatfs.c` | FatFS 图片存储 | ✅ 已有(本项目用 SPIFFS) |
|
||
| `pages.c` | 图片列表管理 | ✅ 已有 |
|
||
| `lcd.c` | LCD 驱动 | ✅ 已有 |
|
||
| UI 界面 | ScreenHome/Img/Set/Peiwang/Update | ✅ 已有(触屏版) |
|
||
|
||
### 1.3 目标项目缺失的模块
|
||
| 模块 | 说明 |
|
||
|------|------|
|
||
| **key_nav** | 按键导航管理器(上下文状态机 + 事件分发) |
|
||
| **ble_transfer** | 设备间 BLE 图片传输(GATT Client 扫描/连接/发送) |
|
||
| **4 个新界面** | ScreenImageShar / ScreenImageReception / ScreenSharing / ScreenReceiving |
|
||
| **battery_ui** | 电池指示器 show-briefly + fade-out 动画 |
|
||
| **两步删除确认** | ScreenImg 的 ContainerDle 重设计 + NAV_CTX_IMG_DELETE_CONFIRM |
|
||
|
||
---
|
||
|
||
## 二、架构差异与适配策略
|
||
|
||
### 2.1 按键驱动差异
|
||
|
||
| 维度 | 本项目 (Dzbj_ESP32_S3_Key) | 目标项目 (Baji_Rtc_Toy_Key) |
|
||
|------|---------------------------|---------------------------|
|
||
| 组件 | iot_button (ESP Component Registry) | ISR 轮询(自定义 dzbj_button.c) |
|
||
| 语言 | 纯 C | C++ (Application 框架) |
|
||
| 事件 | 单击/双击/长按 × 2 键 | 仅按下/释放 |
|
||
| 回调线程 | esp_timer 任务 | ISR 中断 |
|
||
|
||
**适配策略**:
|
||
- 在吧唧模式下添加 iot_button 依赖,替换 `dzbj_button.c` 的 ISR 实现
|
||
- 或在 `dzbj_button.c` 中增加双击/长按检测逻辑(不引入新依赖,但开发量大)
|
||
- **推荐**: 引入 iot_button,仅在吧唧模式下初始化
|
||
|
||
### 2.2 模式隔离
|
||
|
||
目标项目已有模式隔离框架:
|
||
```cpp
|
||
// main/main.cc
|
||
if (device_mode_is_badge()) {
|
||
dzbj_app_main(); // 吧唧模式入口
|
||
} else {
|
||
// AI 模式入口
|
||
}
|
||
```
|
||
|
||
**适配策略**:
|
||
- key_nav 模块仅在 `dzbj_app_main()` 中初始化
|
||
- iot_button 的按键回调仅注册吧唧模式的处理函数
|
||
- AI 模式的按键处理保持不变(ISR 方式)
|
||
|
||
### 2.3 存储差异
|
||
|
||
| 维度 | 本项目 | 目标项目 |
|
||
|------|--------|---------|
|
||
| 文件系统 | SPIFFS | FatFS |
|
||
| 图片管理 | `init_spiffs_image_list()` | `fatfs` 模块 |
|
||
|
||
**适配策略**:
|
||
- key_nav 中的 `init_spiffs_image_list()` 替换为目标项目的 FatFS 图片列表接口
|
||
- ble_transfer 中的图片保存路径适配 FatFS 挂载点
|
||
|
||
---
|
||
|
||
## 三、移植步骤(共 7 步)
|
||
|
||
### 步骤 1: 添加 iot_button + 适配按键驱动
|
||
|
||
**操作**:
|
||
1. `main/idf_component.yml` 添加 `button: ">=3.2.0"`
|
||
2. 新建 `main/dzbj/dzbj_button_nav.c`(或修改 `dzbj_button.c`)
|
||
3. 实现 6 种事件回调接口,参数照搬本项目的 `button.c`
|
||
|
||
**注意**:
|
||
- AI 模式下不初始化 iot_button,避免资源浪费
|
||
- 确认 iot_button 和现有 ISR 按键不冲突(同一 GPIO 不要双重处理)
|
||
|
||
### 步骤 2: 移植 key_nav 模块
|
||
|
||
**操作**:
|
||
1. 复制 `main/key_nav/` 目录到目标项目 `main/dzbj/key_nav/`
|
||
2. 适配 include 路径(ui 头文件路径可能不同)
|
||
3. 适配 LVGL 锁:确认目标项目的 `lvgl_port_lock()` 接口一致
|
||
4. 替换 SPIFFS 相关调用为 FatFS 接口
|
||
|
||
**关键修改点**:
|
||
```c
|
||
// 本项目
|
||
#include "ui/ui.h"
|
||
#include "ui/screens/ui_ScreenHome.h"
|
||
init_spiffs_image_list();
|
||
|
||
// 目标项目适配
|
||
#include "dzbj_ui.h" // 或目标项目实际的 UI 头文件路径
|
||
init_fatfs_image_list(); // 或目标项目的图片列表初始化函数
|
||
```
|
||
|
||
### 步骤 3: 移植 ble_transfer 模块
|
||
|
||
**操作**:
|
||
1. 复制 `main/ble/ble_transfer.c` 和 `main/ble/include/ble_transfer.h`
|
||
2. 适配 BLE 初始化:目标项目的 `dzbj_ble.c` 已有 GATT Server,需新增 GATT Client 能力
|
||
3. 适配图片保存:SPIFFS → FatFS 路径
|
||
4. 适配界面跳转:确认目标项目的 `_ui_screen_change()` 接口
|
||
|
||
**注意**:
|
||
- 目标项目的 BLE 在 AI 模式下可能有不同用途,确保吧唧模式的 ble_transfer 不影响 AI 模式
|
||
- `ble_start()` / `ble_stop()` 需适配到 `dzbj_ble.c` 的广播控制
|
||
|
||
### 步骤 4: 移植 4 个新 UI 界面
|
||
|
||
**操作**:
|
||
1. 复制以下文件到目标项目的 UI 目录:
|
||
- `ui_ScreenImageShar.c/.h`
|
||
- `ui_ScreenImageReception.c/.h`
|
||
- `ui_ScreenSharing.c/.h`
|
||
- `ui_ScreenReceiving.c/.h`
|
||
2. 复制 4 张图片资源文件(`ui_img_*_png.c`)
|
||
3. 在目标项目的 `ui.h` 中添加 include 和 `LV_IMG_DECLARE`
|
||
4. 在 CMakeLists.txt 中添加编译
|
||
|
||
### 步骤 5: 移植 battery_ui 模块
|
||
|
||
**操作**:
|
||
1. 复制 `main/ui/battery_ui.c` 和 `main/ui/battery_ui.h`
|
||
2. 在 ScreenHome 和 ScreenImg 的 `screen_init` 中调用 `battery_ui_add_to_screen()`
|
||
3. 在 SCREEN_LOADED 事件中调用 `battery_ui_show_briefly()`
|
||
4. 在 `dzbj_battery.c` 的电量更新回调中调用 `battery_ui_update_level()`
|
||
|
||
### 步骤 6: 适配 ScreenImg 删除确认 UI
|
||
|
||
**操作**:
|
||
1. 将目标项目的 `ui_ScreenImg.c` 中的 ContainerDle 改为 220×220 底部半圆设计
|
||
2. ui_ImageDel 改为 68×68 正圆容器 + S13 图片居中
|
||
3. 添加白色边框显示/隐藏函数
|
||
4. key_nav 中已包含两步删除逻辑,无需额外修改
|
||
|
||
### 步骤 7: 适配 main 入口和手势移除
|
||
|
||
**操作**:
|
||
1. 在 `dzbj_app_main()` 中添加 `key_nav_init()` 调用
|
||
2. 移除吧唧模式下各界面的触摸手势事件回调
|
||
3. 保留 `LV_EVENT_SCREEN_LOADED` 延迟加载逻辑
|
||
4. 适配 sleep_mgr 的唤醒回调(由 key_nav 统一管理)
|
||
|
||
---
|
||
|
||
## 四、风险评估
|
||
|
||
| 风险 | 影响 | 缓解措施 |
|
||
|------|------|---------|
|
||
| iot_button 与 AI 模式按键冲突 | GPIO 双重处理导致崩溃 | 模式隔离:吧唧模式用 iot_button,AI 模式保持 ISR |
|
||
| BLE Client + Server 同时运行 | 资源不足或状态冲突 | ble_transfer 使用独立的 GATT App ID |
|
||
| FatFS vs SPIFFS 接口差异 | 图片路径/文件操作不兼容 | 统一封装图片读写接口 |
|
||
| UI 头文件路径差异 | 编译错误 | 系统性检查所有 #include 路径 |
|
||
| C++ 框架与纯 C 模块交互 | 链接/调用约定问题 | key_nav 等 C 模块用 `extern "C"` 包裹头文件 |
|
||
|
||
---
|
||
|
||
## 五、预估工作量
|
||
|
||
| 步骤 | 复杂度 | 说明 |
|
||
|------|--------|------|
|
||
| 步骤 1: 按键驱动 | 中 | 需处理模式隔离和 GPIO 冲突 |
|
||
| 步骤 2: key_nav | 低 | 主要是路径适配 |
|
||
| 步骤 3: ble_transfer | 高 | BLE Client 集成到已有 BLE 框架最复杂 |
|
||
| 步骤 4: 新界面 | 低 | 直接复制 + 适配路径 |
|
||
| 步骤 5: battery_ui | 低 | 直接复制 + 接入电量回调 |
|
||
| 步骤 6: 删除确认 | 低 | UI 修改量小 |
|
||
| 步骤 7: 入口适配 | 中 | 需仔细处理手势移除和模式切换 |
|
||
|
||
**总结**: 移植可行性高。核心难点在 ble_transfer 的集成(步骤 3)和按键驱动的模式隔离(步骤 1),其余模块可直接复制适配。建议按步骤顺序执行,每步编译验证。
|