Dzbj_ESP32-S3_Key/移植到Baji_Rtc_Toy_Key方案.md
Rdzleo 75586b3744 ESP32-S3按键版电子吧唧功能完整实现
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>
2026-03-26 17:35:05 +08:00

7.2 KiB
Raw Permalink Blame History

按键版电子吧唧移植到 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 ServerAPP 传图) 已有,仅 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 + 适配按键驱动

操作:

  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 接口

关键修改点:

// 本项目
#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.cmain/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.cmain/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_buttonAI 模式保持 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其余模块可直接复制适配。建议按步骤顺序执行每步编译验证。