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>
7.2 KiB
7.2 KiB
按键版电子吧唧移植到 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 模式隔离
目标项目已有模式隔离框架:
// 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 + 适配按键驱动
操作:
main/idf_component.yml添加button: ">=3.2.0"- 新建
main/dzbj/dzbj_button_nav.c(或修改dzbj_button.c) - 实现 6 种事件回调接口,参数照搬本项目的
button.c
注意:
- AI 模式下不初始化 iot_button,避免资源浪费
- 确认 iot_button 和现有 ISR 按键不冲突(同一 GPIO 不要双重处理)
步骤 2: 移植 key_nav 模块
操作:
- 复制
main/key_nav/目录到目标项目main/dzbj/key_nav/ - 适配 include 路径(ui 头文件路径可能不同)
- 适配 LVGL 锁:确认目标项目的
lvgl_port_lock()接口一致 - 替换 SPIFFS 相关调用为 FatFS 接口
关键修改点:
// 本项目
#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 模块
操作:
- 复制
main/ble/ble_transfer.c和main/ble/include/ble_transfer.h - 适配 BLE 初始化:目标项目的
dzbj_ble.c已有 GATT Server,需新增 GATT Client 能力 - 适配图片保存:SPIFFS → FatFS 路径
- 适配界面跳转:确认目标项目的
_ui_screen_change()接口
注意:
- 目标项目的 BLE 在 AI 模式下可能有不同用途,确保吧唧模式的 ble_transfer 不影响 AI 模式
ble_start()/ble_stop()需适配到dzbj_ble.c的广播控制
步骤 4: 移植 4 个新 UI 界面
操作:
- 复制以下文件到目标项目的 UI 目录:
ui_ScreenImageShar.c/.hui_ScreenImageReception.c/.hui_ScreenSharing.c/.hui_ScreenReceiving.c/.h
- 复制 4 张图片资源文件(
ui_img_*_png.c) - 在目标项目的
ui.h中添加 include 和LV_IMG_DECLARE - 在 CMakeLists.txt 中添加编译
步骤 5: 移植 battery_ui 模块
操作:
- 复制
main/ui/battery_ui.c和main/ui/battery_ui.h - 在 ScreenHome 和 ScreenImg 的
screen_init中调用battery_ui_add_to_screen() - 在 SCREEN_LOADED 事件中调用
battery_ui_show_briefly() - 在
dzbj_battery.c的电量更新回调中调用battery_ui_update_level()
步骤 6: 适配 ScreenImg 删除确认 UI
操作:
- 将目标项目的
ui_ScreenImg.c中的 ContainerDle 改为 220×220 底部半圆设计 - ui_ImageDel 改为 68×68 正圆容器 + S13 图片居中
- 添加白色边框显示/隐藏函数
- key_nav 中已包含两步删除逻辑,无需额外修改
步骤 7: 适配 main 入口和手势移除
操作:
- 在
dzbj_app_main()中添加key_nav_init()调用 - 移除吧唧模式下各界面的触摸手势事件回调
- 保留
LV_EVENT_SCREEN_LOADED延迟加载逻辑 - 适配 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),其余模块可直接复制适配。建议按步骤顺序执行,每步编译验证。