diff --git a/Claude Code插件高效运用指南.md b/Claude Code插件高效运用指南.md new file mode 100644 index 0000000..73348c8 --- /dev/null +++ b/Claude Code插件高效运用指南.md @@ -0,0 +1,503 @@ +# Claude Code 插件高效运用指南 + +> 更新日期: 2026-03-19(skill-creator 补充) +> 适用环境: macOS / Claude Code 2.1.37+ / ESP32 嵌入式开发 + +--- + +## 一、当前已安装资源总览 + +| 类别 | 数量 | 说明 | +|------|------|------| +| 官方插件 (claude-plugins-official) | 7 个 | Git 工作流、代码审查、功能开发、迭代循环、规则维护、Skill 创建 | +| 社区插件 (claude-code-settings) | 2 个 | 长时任务自主执行、规格驱动开发 | +| 自定义 Skills (~/.claude/skills/) | 10 个 | ESP32 专用 6 个 + RK3588/Linux 驱动 4 个 | +| 内置 Skills | 3 个 | simplify、loop、claude-api | + +--- + +## 二、命令速查表 + +| 命令 | 来源 | 一句话说明 | +|------|------|-----------| +| `/commit` | commit-commands | 自动分析变更,生成提交信息并 commit | +| `/commit-push-pr` | commit-commands | 一键 commit → push → 创建 PR | +| `/clean_gone` | commit-commands | 清理远程已删除的本地分支 | +| `/code-review` | code-review | 4 个 Agent 并行审查,置信度过滤 | +| `/review-pr` | pr-review-toolkit | 6 个专业 Agent 综合 PR 审查 | +| `/feature-dev` | feature-dev | 7 阶段引导式功能开发 | +| `/ralph-loop` | ralph-loop | 迭代式自引用开发循环,持续直到任务完成 | +| `/cancel-ralph` | ralph-loop | 取消正在运行的 Ralph Loop | +| `/claude-md-improver` | claude-md-management | 审计 CLAUDE.md,检查与代码库一致性 | +| `/revise-claude-md` | claude-md-management | 从当前会话提取经验更新 CLAUDE.md | +| `/autonomous-skill` | autonomous-skill | 多会话长时任务自主执行 | +| `/spec-kit-skill` | spec-kit-skill | 7 阶段规格驱动开发工作流 | +| `/skill-creator` | skill-creator | **元技能**:交互式创建、测试、优化自定义 Skills | +| `/simplify` | 内置 | 审查代码复用性、质量和效率 | +| `/loop` | 内置 | 定时循环执行命令(如每 5 分钟检查一次) | + +--- + + +## 三、按场景分类的使用指南 + +### 场景 1:日常编码提交(每天用) + +#### `/commit` — 智能提交 + +**何时用**:写完代码,需要提交时 + +**使用方式**: +``` +你:/commit +``` +Claude 会自动: +1. 运行 `git diff` 分析所有变更 +2. 理解变更内容和意图 +3. 生成符合项目风格的提交信息 +4. 执行 `git commit` + +**对比手动提交的优势**: +- 不用自己写 commit message +- 自动识别变更类型(feat/fix/refactor) +- 遵循项目已有的提交风格 + +--- + +#### `/commit-push-pr` — 一键发布 + +**何时用**:功能开发完成,需要提交 + 推送 + 创建 PR + +**使用方式**: +``` +你:/commit-push-pr +``` +一步完成三件事,适合功能分支开发完成后快速发布。 + +--- + +#### `/clean_gone` — 清理分支 + +**何时用**:定期清理,或感觉本地分支太多时 + +**使用方式**: +``` +你:/clean_gone +``` +自动清理所有远程已删除但本地仍残留的分支(`git branch` 中标记为 `[gone]` 的)。 + +--- + +### 场景 2:代码审查(提交前 / PR 合并前) + +#### `/code-review` — 快速审查 + +**何时用**:提交前快速检查是否有明显问题 + +**使用方式**: +``` +你:/code-review +``` + +**工作原理**:启动 4 个并行 Agent +1. CLAUDE.md 合规检查 ×2(检查代码是否遵循项目规则) +2. Bug 扫描(检测潜在 Bug) +3. Git 历史上下文分析(结合 git log 理解变更背景) + +置信度 < 80 的问题自动过滤,只报告高确信度问题。 + +**适合**:日常快速检查,耗时较短 + +--- + +#### `/review-pr` — 深度审查 + +**何时用**:重要功能合并前的全面审查 + +**使用方式**: +``` +你:/review-pr +``` + +**工作原理**:启动 6 个专业 Agent +| Agent | 检查内容 | +|-------|---------| +| code-reviewer | 代码质量、Bug、安全漏洞 | +| comment-analyzer | 注释准确性和可维护性 | +| silent-failure-hunter | 静默失败和错误处理缺陷 | +| pr-test-analyzer | 测试覆盖质量 | +| type-design-analyzer | 类型设计质量(封装、不变量) | +| code-simplifier | 代码简化机会 | + +**适合**:重要 PR、团队协作代码、关键功能上线前 + +**`/code-review` vs `/review-pr` 如何选择?** +| | `/code-review` | `/review-pr` | +|---|---|---| +| Agent 数量 | 4 个 | 6 个 | +| 耗时 | 较短 | 较长 | +| 深度 | 快速扫描 | 全面审查 | +| 使用频率 | 每次提交前 | 重要 PR 合并前 | + +--- + +### 场景 3:功能开发(新功能 / 复杂任务) + +#### `/feature-dev` — 引导式功能开发 + +**何时用**:开发新功能,需要系统性地理解代码库并设计方案 + +**使用方式**: +``` +你:/feature-dev 添加 OTA 远程固件升级功能 +``` + +**7 阶段工作流**: +``` +阶段 1: 理解代码库 → code-explorer Agent 分析现有架构 +阶段 2: 提问澄清 → 向你提出关键问题(如 OTA 源、回滚策略) +阶段 3: 需求确认 → 确认功能范围和约束 +阶段 4: 架构设计 → code-architect Agent 设计方案 +阶段 5: 实现 → 按设计方案编码 +阶段 6: 审查 → code-reviewer Agent 检查实现质量 +阶段 7: 总结 → 输出变更摘要 +``` + +**ESP32 项目实际用例**: +``` +你:/feature-dev 新增 BLE OTA 固件升级功能 +你:/feature-dev 添加 MQTT 设备影子同步 +你:/feature-dev 实现多语言 TTS 语音切换 +``` + +**优势**:避免直接写代码导致的架构混乱,先理解再动手 + +--- + +#### `/autonomous-skill` — 长时任务自主执行 + +**何时用**:任务太大,一个会话搞不定(如大规模重构、全项目代码迁移) + +**使用方式**: +``` +你:/autonomous-skill 将项目从 ESP-IDF v5.1 迁移到 v5.4 +``` + +**工作原理**: +1. **Initializer Agent**:分析任务,分解为子任务清单 +2. 生成 `.autonomous//task_list.md` 和 `progress.md` +3. **Executor Agent**:逐个执行子任务,自动更新进度 +4. 会话中断后,下次启动自动从 `progress.md` 继续 + +**适合**: +- 跨多文件的大规模重构 +- 框架/SDK 版本迁移 +- 全项目代码规范统一 + +--- + +### 场景 4:迭代式开发(调试 / 持续改进) + +#### `/ralph-loop` — 持续迭代直到完成 + +**何时用**:任务需要多轮尝试才能完成(如调试、性能调优) + +**使用方式**: +``` +你:/ralph-loop 优化 GIF 动画播放性能,目标是音频不卡顿 +``` + +**工作原理**: +- Claude 完成一轮后尝试退出 → Stop Hook 拦截 → 重新注入 prompt → 继续迭代 +- 直到任务真正完成才停止 + +**取消方式**: +``` +你:/cancel-ralph +``` + +**适合**: +- 性能调优(反复测量-修改-验证) +- 复杂 Bug 排查(需要多轮假设-验证) +- 代码质量持续改进 + +**注意**:会消耗较多 token,确保任务值得持续迭代 + +--- + +### 场景 5:知识管理(CLAUDE.md 维护) + +#### `/claude-md-improver` — 审计规则文件 + +**何时用**:定期维护(建议每 1-2 周一次),或感觉 CLAUDE.md 与实际代码不一致时 + +**使用方式**: +``` +你:/claude-md-improver +``` + +**输出**: +- 质量报告(一致性评分、过时内容、遗漏项) +- 自动更新建议 +- 与当前代码库对比的差异分析 + +--- + +#### `/revise-claude-md` — 提取会话经验 + +**何时用**:解决了一个复杂问题后,在会话结束前执行 + +**使用方式**: +``` +你:/revise-claude-md +``` + +**工作原理**: +- 回顾当前会话中的所有踩坑经验、解决方案、架构决策 +- 自动提取有价值的内容更新到 CLAUDE.md +- 避免下次遇到同样问题 + +**最佳实践**: +``` +解决完 Bug → 测试通过 → /revise-claude-md → /commit +``` + +--- + +### 场景 6:代码简化(内置) + +#### `/simplify` — 代码简化审查 + +**何时用**:写完代码后,检查是否有可简化的地方 + +**使用方式**: +``` +你:/simplify +``` + +**检查内容**: +- 代码复用机会 +- 不必要的复杂度 +- 可删除的冗余代码 +- 保持功能不变的前提下简化实现 + +--- + +### 场景 7:自定义 Skill 创建与优化(元技能) + +#### `/skill-creator` — 从零创建专业领域 Skills + +**何时用**:需要为新的技术领域(如 Linux 驱动、Android HAL、新硬件平台)创建专属的 Claude Code Skill + +**来源**:Anthropic 官方插件(claude-plugins-official),是一个"元技能"(Meta-Skill)— 专门用来创建其他 Skills 的 Skill。 + +**使用方式**: +``` +你:/skill-creator +``` + +**四种操作模式**: + +| 模式 | 命令 | 说明 | +|------|------|------| +| **Create** | `/skill-creator` | 通过交互式问答从零创建新 Skill,自动生成 SKILL.md | +| **Eval** | `/skill-creator eval` | 运行测试用例,对比有/无 Skill 的效果差异 | +| **Improve** | `/skill-creator improve` | 基于评测反馈自动迭代改进 Skill(最多 5 轮) | +| **Benchmark** | `/skill-creator benchmark` | A/B 盲测对比,量化 Skill 对输出质量的提升 | + +**内置 4 个子 Agent**: + +| Agent | 职责 | +|-------|------| +| Executor | 执行 Skill,生成输出结果 | +| Grader | 对输出结果评分(质量、准确性、完整性) | +| Comparator | A/B 盲测对比(有 Skill vs 无 Skill) | +| Analyzer | 分析评测结果,生成改进建议 | + +**完整工作流程(Create 模式)**: + +``` +步骤 1: 捕获意图 → 理解你想让 Skill 做什么 +步骤 2: 问答调研 → 收集边界情况、格式要求、依赖工具等 +步骤 3: 编写 SKILL.md → 按最佳实践自动生成(含 frontmatter + 指令内容) +步骤 4: 定义测试用例 → 生成 2-3 个真实测试提示 +步骤 5: 运行评估 → 执行 with-skill 和 baseline 对比打分 +步骤 6: 迭代改进 → 根据反馈自动优化 SKILL.md 内容 +步骤 7: 优化触发词 → 微调 description 字段提升触发精度 +``` + +**实际用例**: + +``` +# 从零创建 Linux 驱动开发 Skill +你:/skill-creator +Claude:你想创建什么领域的 Skill? +你:Linux 内核驱动开发,包括设备树 DTS、GPIO/I2C/SPI 驱动、V4L2 摄像头驱动 + +# 从文档资料创建 Skill +你:/skill-creator +你:(提供 RK3588 SDK 文档、Android HAL 开发指南等资料) +Claude:自动消化资料 → 生成结构化的 SKILL.md + +# 评估并优化已有 Skill +你:/skill-creator eval ~/.claude/skills/linux-driver/SKILL.md +你:/skill-creator improve ~/.claude/skills/linux-driver/SKILL.md +``` + +**生成的 SKILL.md 标准格式**: + +```yaml +--- +name: my-skill-name +description: 描述功能和触发时机(决定何时自动激活) +allowed-tools: Bash, Read, Grep, Glob # 可选,限制可用工具 +--- + +# Skill 标题 + +## 审查清单 / 排障速查表 / 构建流程 +(结构化的专业知识内容) +``` + +**Skill 存放位置**: + +| 范围 | 路径 | 说明 | +|------|------|------| +| 个人全局 | `~/.claude/skills//SKILL.md` | 所有项目通用(如你的 ESP32 Skills) | +| 项目级 | `.claude/skills//SKILL.md` | 仅当前项目 | +| 插件提供 | 插件安装目录内 | 通过 `claude plugins install` 安装 | + +**与手动创建 Skill 的对比**: + +| | 手动创建 | `/skill-creator` | +|---|---|---| +| 方式 | 自己编写 SKILL.md | 交互式引导 + 自动生成 | +| 测试 | 凭感觉验证 | 自动化评测 + A/B 对比 | +| 迭代 | 手动修改 | 自动分析 + 5 轮迭代优化 | +| 触发精度 | 靠经验写 description | 自动优化触发词 | +| 适合 | 熟悉 Skill 格式的用户 | 任何用户,尤其是新领域拓展 | + +**最佳实践**: + +``` +准备资料(文档/教程/代码示例) + ↓ +/skill-creator(Create 模式,喂入资料) + ↓ +/skill-creator eval(评估效果) + ↓ +/skill-creator improve(迭代优化) + ↓ +投入使用,后续根据实际踩坑经验持续补充 +``` + +--- + +## 四、ESP32 项目推荐工作流 + +### 日常开发流程 + +``` +编码 → /simplify(检查简化)→ /commit(提交) +``` + +### 新功能开发流程 + +``` +/feature-dev(引导开发)→ 编码 → 构建测试 → /code-review(快速审查)→ /commit-push-pr(发布) +``` + +### 重要功能上线流程 + +``` +/feature-dev → 编码 → 构建测试 → /review-pr(深度审查)→ 修复审查问题 → /commit-push-pr +``` + +### 复杂 Bug 排查流程 + +``` +/ralph-loop 排查并修复xxx问题 → 修复完成 → /revise-claude-md(记录经验)→ /commit +``` + +### 大规模重构流程 + +``` +/autonomous-skill(自主执行重构)→ 检查结果 → /review-pr(审查)→ /commit-push-pr +``` + +### 定期维护流程(每 1-2 周) + +``` +/claude-md-improver(审计规则)→ /clean_gone(清理分支) +``` + +### 新领域 Skill 创建流程 + +``` +收集资料(文档/教程/API手册)→ /skill-creator(创建)→ /skill-creator eval(评估)→ /skill-creator improve(优化) +``` + +**示例**:为香橙派 CM5 (RK3588S) 创建 Linux 驱动开发 Skills: +``` +1. 准备 Rockchip BSP 文档、Linux 内核驱动教程、设备树语法说明 +2. /skill-creator → 创建 linux-driver Skill +3. /skill-creator → 创建 android-hal Skill +4. /skill-creator → 创建 rk3588-build Skill +5. /skill-creator eval → 评估效果 → /skill-creator improve → 迭代优化 +``` + +--- + +## 五、自定义 Skills 与自动触发 + +### Skills 自动触发机制 + +当前对话中,以下 Skills 会根据关键词自动激活: + +| Skill | 触发条件 | +|-------|---------| +| esp-build | 你说"编译"、"构建"、"烧录" | +| esp-analyze-log | 你提供设备日志、提到 crash/panic | +| esp-troubleshoot | 你描述设备异常 | +| esp-optimize | 你提到"优化"、"内存不足" | +| esp-code-review | 你要求"代码审查"、"review" | +| esp-driver | 你说"写一个驱动" | +| linux-driver | 你说"Linux 驱动"、"设备树"、"内核模块" | +| android-hal | 你说"HAL"、"AIDL"、"HIDL"、"JNI" | +| rk3588-build | 你说"编译 SDK"、"刷机"、"Docker 编译环境" | +| rk3588-troubleshoot | 你描述驱动不工作、设备不识别、内核崩溃 | +| simplify | 通过 /simplify 调用 | +| loop | 通过 /loop 调用 | +| claude-api | 涉及 Anthropic SDK 开发 | + +### ESP32 Skills 与插件配合 + +| 自定义 Skill | 触发方式 | 与插件配合 | +|-------------|---------|-----------| +| esp-build | "帮我编译" / "构建项目" | 编译 → `/commit` 提交 | +| esp-analyze-log | 提供日志文件路径 | 分析日志 → 修复 → `/revise-claude-md` 记录 | +| esp-troubleshoot | 描述设备异常现象 | 排障 → `/ralph-loop` 持续调试 | +| esp-optimize | "优化内存" / "固件太大" | 优化 → `/simplify` 检查 → `/commit` | +| esp-code-review | "帮我审查代码" | 先 esp-code-review → 再 `/review-pr` 双重审查 | +| esp-driver | "写一个I2C驱动" | `/feature-dev` 设计 → esp-driver 生成 → `/code-review` 审查 | + +### RK3588/Linux 驱动 Skills 与插件配合 + +| 自定义 Skill | 触发方式 | 与插件配合 | +|-------------|---------|-----------| +| linux-driver | "写一个 GPIO/I2C/SPI 驱动" | `/feature-dev` 设计 → linux-driver 生成 → `/code-review` 审查 | +| android-hal | "开发 HAL 让 APP 控制硬件" | linux-driver 写驱动 → android-hal 写 HAL → `/review-pr` 审查 | +| rk3588-build | "编译内核" / "刷机" / "搭建编译环境" | 编译 → 刷机 → `/revise-claude-md` 记录踩坑 | +| rk3588-troubleshoot | "设备不识别" / "内核崩溃" | 排障 → `/ralph-loop` 持续调试 → `/revise-claude-md` 记录 | + +--- + +## 六、注意事项 + +1. **Token 消耗**:`/review-pr`(6 Agent)和 `/ralph-loop`(持续迭代)消耗较多 token,按需使用 +2. **`/ralph-loop` 需要手动取消**:通过 `/cancel-ralph` 停止,否则会一直运行 +3. **`/autonomous-skill` 的进度文件**:保存在 `.autonomous/` 目录,不要手动删除未完成的任务 +4. **`/spec-kit-skill` 依赖外部工具**:需要安装 GitHub Spec-Kit CLI,目前 ESP32 项目用不到 +5. **插件更新**:运行 `claude plugins update` 可更新所有插件到最新版本 +6. **`/skill-creator` 资料质量决定 Skill 质量**:喂入的文档越专业、越详细,生成的 Skill 审查清单和排障表越准确。建议提供官方文档 + 实战踩坑经验的组合 +7. **Skill 持续迭代**:首次创建的 Skill 不一定完美,随着实际开发中遇到新问题,持续补充更新 SKILL.md(类似你现有 ESP32 Skills 的演进过程) diff --git a/docs/touch-to-button-migration.md b/docs/touch-to-button-migration.md new file mode 100644 index 0000000..90a4bf2 --- /dev/null +++ b/docs/touch-to-button-migration.md @@ -0,0 +1,331 @@ +# 触屏版 → 按键版迁移总结 + +> 适用于 ESP32-C3 / ESP32-S3 电子吧唧项目,从触摸屏交互迁移到两键物理按键交互。 + +## 一、迁移背景 + +取消触摸芯片以降低硬件成本,所有用户交互通过两个物理按键实现: +- **BOOT按键**(GPIO9):确认/执行/返回 +- **KEY按键**(GPIO8):导航/切换 + +--- + +## 二、变更文件清单 + +| 文件 | 变更类型 | 说明 | +|------|----------|------| +| `main/button/button.c` | 重构 | GPIO中断+手动去抖 → iot_button 组件 | +| `main/button/include/button.h` | 重构 | 新增事件类型枚举,回调签名变更 | +| `main/key_nav/key_nav.c` | **新增** | 按键导航管理器(核心模块) | +| `main/key_nav/include/key_nav.h` | **新增** | 导航上下文和焦点状态枚举 | +| `main/main.c` | 修改 | 移除 boot_btn_handler,集成 key_nav_init | +| `main/ui/screens/ui_ScreenHome.c` | 修改 | 移除手势事件,界面导航交由 key_nav | +| `main/ui/screens/ui_ScreenHome.h` | 修改 | 移除 ui_event_ScreenHome 声明 | +| `main/ui/screens/ui_ScreenImg.c` | 修改 | 移除手势/点击事件,保留 SCREEN_LOADED 事件 | +| `main/ui/screens/ui_ScreenSet.c` | 修改 | 移除手势/滑块/节能/删除点击事件,新增按键版颜色切换 | +| `main/ui/screens/ui_ScreenSet.h` | 修改 | 新增 flashlight_switch_color/restart_blink 声明 | +| `main/lcd/lcd.c` | 修改 | 新增 lcd_fill_color() 直接写 GRAM | +| `main/lcd/include/lcd.h` | 修改 | 新增 lcd_fill_color() 声明 | +| `main/sleep_mgr/sleep_mgr.c` | 修改 | 移除按键回调注册,交由 key_nav 统一处理 | +| `main/CMakeLists.txt` | 修改 | 添加 key_nav 源文件和头文件路径 | +| `main/idf_component.yml` | 修改 | 添加 `button: ">=3.2.0"` 依赖 | +| `sdkconfig` | 修改 | 新增 IoT Button 配置项 | + +--- + +## 三、核心架构变更 + +### 3.1 按键驱动重构(button模块) + +**触屏版**:自定义 GPIO 中断 + FreeRTOS 队列 + 手动去抖(200ms时间戳判断) +```c +// 旧方案 +gpio_isr_handler_add(PIN_BTN_BOOT, gpio_isr_handler, (void *)PIN_BTN_BOOT); +xTaskCreate(btn_task, "btn_task", 3072, NULL, 5, NULL); // 队列消费任务 +``` + +**按键版**:ESP-IDF 官方 `iot_button` 组件,原生支持单击/双击/长按 +```c +// 新方案 +button_config_t btn_cfg = { + .long_press_time = 2000, // 长按2秒 + .short_press_time = 0, // 使用默认180ms(双击检测窗口) +}; +button_gpio_config_t gpio_cfg = { + .gpio_num = PIN_BTN_BOOT, + .active_level = 0, // 低电平有效 +}; +iot_button_new_gpio_device(&btn_cfg, &gpio_cfg, &boot_btn_handle); +iot_button_register_cb(boot_btn_handle, BUTTON_SINGLE_CLICK, NULL, boot_click_cb, NULL); +iot_button_register_cb(boot_btn_handle, BUTTON_DOUBLE_CLICK, NULL, boot_double_click_cb, NULL); +iot_button_register_cb(boot_btn_handle, BUTTON_LONG_PRESS_START, NULL, boot_long_press_cb, NULL); +``` + +**回调签名变更**: +```c +// 旧版(只有按下事件) +typedef void (*btn_event_cb_t)(int gpio_num, void *usr_data); + +// 新版(区分单击/双击/长按) +typedef enum { + BTN_EVT_CLICK, + BTN_EVT_DOUBLE_CLICK, + BTN_EVT_LONG_PRESS, +} btn_event_type_t; +typedef void (*btn_event_cb_t)(int gpio_num, btn_event_type_t event, void *usr_data); +``` + +**注册接口变更**: +```c +// 旧版 +button_on_boot_press(cb, usr_data); +button_on_key2_press(cb, usr_data); + +// 新版 +button_on_boot_event(cb, usr_data); +button_on_key2_event(cb, usr_data); +``` + +**idf_component.yml 依赖**: +```yaml +dependencies: + button: ">=3.2.0" +``` + +### 3.2 新增按键导航管理器(key_nav模块) + +这是本次迁移的**核心新增模块**,集中管理所有按键行为和界面导航逻辑。 + +**设计思想**: +- 上下文状态机:根据当前界面/模式决定按键行为 +- 焦点管理系统:Set界面的图标选中和蓝色边框高亮 +- 任务派发模式:iot_button 回调在 esp_timer 上下文中执行(不能 vTaskDelay),通过 xTaskCreate 派发到独立任务 + +**上下文枚举**: +```c +typedef enum { + NAV_CTX_HOME, // Home界面 + NAV_CTX_IMG, // Img界面(正常浏览) + NAV_CTX_IMG_DELETE, // Img界面(删除模式) + NAV_CTX_SET, // Set界面(焦点导航) + NAV_CTX_SET_BRIGHTNESS, // Set界面(亮度调节模式) + NAV_CTX_FLASHLIGHT, // 应援灯全屏模式 +} nav_context_t; +``` + +**Set界面焦点枚举**: +```c +typedef enum { + SET_FOCUS_NONE = -1, // 无选中 + SET_FOCUS_LOW_POWER = 0,// 节能 + SET_FOCUS_FLASHLIGHT, // 应援灯 + SET_FOCUS_DELETE, // 删除 + SET_FOCUS_BRIGHTNESS, // 亮度 + SET_FOCUS_COUNT, // 焦点总数(用于循环) +} set_focus_item_t; +``` + +**任务派发模式**(关键模式,必须遵循): +```c +// iot_button 回调在 esp_timer 上下文中,不能 vTaskDelay +// 必须派发到独立 FreeRTOS 任务执行需要延时的操作 +static void dispatch_task(TaskFunction_t func, const char *name) +{ + xTaskCreate(func, name, 3072, NULL, 5, NULL); +} + +static void boot_event_handler(int gpio_num, btn_event_type_t event, void *usr_data) +{ + if (event == BTN_EVT_CLICK) { + dispatch_task(nav_task_home_boot_click, "h_boot"); // 派发到独立任务 + } +} +``` + +**焦点高亮实现**: +```c +#define FOCUS_BORDER_COLOR 0x2196F3 // Material Blue +#define FOCUS_BORDER_WIDTH 3 + +static void set_focus_border(int index) { + lv_obj_set_style_border_color(obj, lv_color_hex(FOCUS_BORDER_COLOR), LV_PART_MAIN | LV_STATE_DEFAULT); + lv_obj_set_style_border_width(obj, FOCUS_BORDER_WIDTH, LV_PART_MAIN | LV_STATE_DEFAULT); + lv_obj_set_style_border_opa(obj, LV_OPA_COVER, LV_PART_MAIN | LV_STATE_DEFAULT); +} +``` + +### 3.3 各界面触摸事件移除 + +#### ScreenHome +- 移除 `ui_event_ScreenHome()` 函数(下滑→Set、左滑/右滑→Img 手势) +- 移除 `lv_obj_add_event_cb(ui_ScreenHome, ui_event_ScreenHome, LV_EVENT_ALL, NULL)` +- 移除 `#include "ui_ScreenSet.h"` 依赖 + +#### ScreenImg +- 移除 `ui_event_ImageDel()`(删除按钮点击) +- 移除 `ui_event_ImageReturn()`(返回按钮点击) +- 移除所有手势事件(上滑→Home、下滑→Set、左滑→下一张、右滑→上一张) +- 保留 `LV_EVENT_SCREEN_LOADED` 事件(首次加载图片初始化) +- 保留 `should_show_container` 标志逻辑(从Set删除图标进入时显示) +- 移除 `lv_obj_add_event_cb` 对 ImageDel 和 ImageReturn 的注册 + +#### ScreenSet +- 移除 `ui_event_ScreenSet()`(上滑返回手势) +- 移除 `ui_event_SliderBrightness()`(滑块值变更事件) +- 移除 `ui_event_ImgLowPower()`(节能图标点击事件) +- 移除 `ui_event_ImgDelete()`(删除图标点击事件) +- 保留 `ui_event_ImgFlashlight()` 的 `LV_EVENT_CLICKED`(由 key_nav 通过 `lv_event_send` 触发) +- 移除 `lv_obj_add_event_cb` 对节能、删除、滑块、手势的注册 + +--- + +## 四、新增功能和优化 + +### 4.1 按键导航系统 + +| 界面 | BOOT单击 | KEY单击 | BOOT双击 | KEY长按 | +|------|----------|---------|----------|---------| +| Home | →Set | →Img | - | - | +| Img(浏览) | →Home | 下一张图 | →Home | - | +| Img(删除) | 确认删除 | 取消删除 | →Home | - | +| Set(无焦点) | →Home | 选中第一个 | →Home | - | +| Set(有焦点) | 激活功能 | 下一个焦点 | →Home | - | +| Set(亮度调节) | 亮度+10% | 亮度-10% | →Home | 退出调节 | +| 应援灯 | 切换颜色 | 退出→Set | →Home | - | + +### 4.2 Set界面焦点蓝色边框高亮 + +- 用 LVGL `border` 样式实现焦点指示(Material Blue #2196F3) +- 焦点切换时自动清除旧边框、设置新边框 +- 离开界面或返回 Home 自动清除所有边框 +- 进入删除模式时,ImageDel 控件也显示蓝色边框提示 + +### 4.3 应援灯颜色切换优化 + +触屏版直接修改 LVGL 样式,LVGL 30行分band渲染导致从上到下的视觉刷新感。 + +按键版优化为 **LCD 硬件级切换**: +```c +void flashlight_switch_color(void) { + lcd_disp_on_off(false); // DISPOFF 0x28:LCD停止输出 + lcd_fill_color(new_color); // 直接写GRAM,绕过LVGL(~35ms同步阻塞) + lcd_disp_on_off(true); // DISPON 0x29:LCD瞬间恢复,GRAM已完整 +} +``` + +新增 `lcd_fill_color()` 函数: +```c +// 绕过 LVGL 分band渲染,直接用 esp_lcd_panel_draw_bitmap 写 GRAM +// 40行为单位,DMA 内存,同步阻塞写入 +void lcd_fill_color(uint32_t color_rgb) { + lv_color_t c = lv_color_hex(color_rgb); // RGB888→RGB565(含byte swap) + uint16_t *buf = heap_caps_malloc(LCD_WID * 40 * sizeof(uint16_t), MALLOC_CAP_DMA); + for (int y = 0; y < LCD_HIGH; y += 40) { + esp_lcd_panel_draw_bitmap(panel_handle, 0, y, LCD_WID, y + lines, buf); + } + heap_caps_free(buf); +} +``` + +### 4.4 亮度调节按键化 + +触屏版通过滑块拖动调节。按键版改为: +- BOOT单击 +10%,KEY单击 -10% +- 范围 10%~100% +- 同步更新滑块控件值和百分比标签 +- KEY长按2秒退出调节模式 + +### 4.5 休眠管理适配 + +- 移除 sleep_mgr 中的按键回调注册(旧版在 sleep_mgr_init 中注册 KEY2 回调) +- 按键唤醒逻辑统一由 key_nav 处理: + ```c + if (sleep_mgr_is_screen_off()) { + sleep_mgr_notify_activity(); // 唤醒屏幕 + return; // 仅唤醒,不触发业务 + } + sleep_mgr_notify_activity(); // 重置休眠计时器 + ``` + +### 4.6 main.c 简化 + +- 移除 ~50 行的 `boot_btn_handler()` 函数(手电筒退出+界面切换+亮度恢复逻辑) +- 所有按键处理逻辑集中到 key_nav 模块 +- 初始化顺序调整:`button_init()` → `sleep_mgr_init()` → `key_nav_init()` + +--- + +## 五、关键技术要点(迁移到 S3 时注意) + +### 5.1 iot_button 状态机特性 + +- `BUTTON_SINGLE_CLICK` 和 `BUTTON_DOUBLE_CLICK` 互斥,不会同时触发 +- 按键释放后等待 `short_press_time`(默认180ms)决定是单击还是双击 +- `short_press_time` 控制双击检测窗口,不是去抖时间(去抖由 `CONFIG_BUTTON_DEBOUNCE_TICKS` 控制,默认10ms) +- 设为 0 表示使用默认值 180ms + +### 5.2 iot_button 回调上下文 + +- 回调在 `esp_timer` 任务中执行 +- **禁止在回调中调用 `vTaskDelay()`**,否则阻塞 esp_timer 任务,导致 LVGL tick 停止 +- **解决方案**:通过 `xTaskCreate` 派发到独立 FreeRTOS 任务 + +### 5.3 LVGL 操作线程安全 + +- 修改 UI 必须加锁:`lvgl_port_lock(timeout_ms)` / `lvgl_port_unlock()` +- 建议超时 50-100ms,避免死锁 +- 永久等待用 `lvgl_port_lock(-1)` + +### 5.4 手电筒退出时序 + +``` +亮度→0 → flashlight_exit() → vTaskDelay(80ms) → 切换界面 → vTaskDelay(150ms) → 恢复亮度 +``` +- 80ms 等待 overlay 删除(LVGL 需要 15+ 刷新周期) +- 150ms 等待新界面渲染完成 +- 先切换界面再恢复亮度,避免用户看到旧界面 + +### 5.5 GPIO 引脚适配 + +S3 项目需要根据实际硬件修改 button.h 中的 GPIO 定义: +```c +#define PIN_BTN_BOOT 9 // 根据S3硬件原理图修改 +#define PIN_BTN_KEY2 8 // 根据S3硬件原理图修改 +``` + +### 5.6 sdkconfig 配置 + +新增 IoT Button 相关配置(menuconfig 或直接修改 sdkconfig): +``` +CONFIG_BUTTON_PERIOD_TIME_MS=5 +CONFIG_BUTTON_DEBOUNCE_TICKS=2 +CONFIG_BUTTON_SHORT_PRESS_TIME_MS=180 +CONFIG_BUTTON_LONG_PRESS_TIME_MS=1500 +``` + +--- + +## 六、迁移步骤(适用于 ESP32-S3 项目) + +1. **添加依赖**:`idf_component.yml` 添加 `button: ">=3.2.0"` +2. **重构 button 模块**:替换 GPIO 中断为 iot_button,修改回调签名 +3. **新建 key_nav 模块**:复制 `main/key_nav/` 目录,根据 S3 项目的界面结构调整上下文枚举和任务函数 +4. **移除触摸事件**:各 Screen 文件中移除手势事件函数和 `lv_obj_add_event_cb` 注册 +5. **适配 main.c**:移除旧的按键处理函数,添加 `key_nav_init()` 调用 +6. **适配 sleep_mgr**:移除按键回调注册,由 key_nav 统一处理唤醒 +7. **添加 lcd_fill_color()**(如需应援灯颜色切换优化) +8. **更新 CMakeLists.txt**:添加 key_nav 源文件和头文件路径 +9. **适配 GPIO 引脚**:根据 S3 硬件原理图修改按键 GPIO 定义 +10. **编译测试**:`idf.py build` 验证,逐个功能测试 + +--- + +## 七、资源变化 + +| 指标 | 触屏版 | 按键版 | 变化 | +|------|--------|--------|------| +| button 任务栈 | 3072B(btn_task 队列消费) | 0(iot_button 内部管理) | 节省 3KB | +| key_nav 任务栈 | 无 | 3072B(每次按键临时创建,执行完销毁) | 临时占用 | +| 触摸事件代码 | ~200 行(手势+点击回调) | 0 | 移除 | +| key_nav 代码 | 0 | ~530 行 | 新增 | +| iot_button 组件 | 无 | ~20KB Flash | 新增依赖 |