欢迎光临
我们一直在努力

08 keyflow 按键模块集成 Skill 设计方案

版本:v1.0.0 状态:已实现(Python CLI 工具,约 70% 设计覆盖率) 适用范围:C 语言嵌入式工程(STM32 / 51 / ESP32 / Linux / 裸机) 实现路径:.trae/skills/keyflow-integrator/keyflow_integrator.py(1019 行)


1. Skill 定位与目标

Skill 名称:keyflow-integrator

核心能力:让 Agent 在任意嵌入式/C 工程中,一键完成:

  • Install(安装) — 将 keyflow 的核心代码作为子模块/拷贝集成到项目
  • Configure(配置) — 选择硬件平台(STM32 / 51 / ESP32 / Linux / 裸机)、分配 GPIO 引脚
  • Integrate(对接) — 生成按键配置表、回调函数、扫描周期配置,并与业务逻辑对接
  • Verify(验证) — 生成最小可运行示例/测试代码,编译并输出验证报告
  • 设计原则:

    • ✅ 零破坏性:不会删除/重写用户代码,仅在必要处追加最小补丁
    • ✅ 可回滚:所有修改前自动备份关键文件为 .bak
    • ✅ 显式决策:存在歧义时(如引脚选择、按键数量),必须通过对话明确而非猜测
    • ✅ 幂等:同一项目多次执行不产生重复代码

    2. 输入 / 输出契约

    2.1 用户输入(自然语言或结构化描述)

    project:
    path: /absolute/path/to/project # 用户工程根目录
    build_system: make|cmake|keil|iar|other # 构建系统
    platform: stm32|51|esp32|linux|baremetal
    compiler: armcc|gcc|sdcc|other
    button_count: <N> # 按键数量
    button_list: # (可选)按键描述列表
    name: "KEY_OK"
    pin: "GPIOA,5" # 或自定义描述
    active_level: low # low / high
    debounce_ms: 15
    long_press_ms: 1000
    event_handler: "on_ok_pressed" # 业务回调函数名

    scan_period_ms: 10 # 主循环扫描周期
    features: # 需要启用的扩展模块
    matrix_keypad: {rows: 4, cols: 4} # (可选)矩阵键盘
    exti_driven # (可选)中断驱动
    event_queue # (可选)事件队列
    combo_keys # (可选)组合键
    integration_style: table_driven # table_driven(推荐) | manual
    code_output_dir: src/app/buttons # 生成文件输出目录
    business_hooks: # 业务层回调映射
    event: PRESSED
    handler: "app_on_button_pressed(idx)"
    event: LONG_PRESS
    handler: "app_on_button_long_press(idx)"

    2.2 Skill 输出

    files_created:
    /project/src/app/buttons/keyflow_config.h # 按键配置表 + 回调声明
    /project/src/app/buttons/keyflow_integration.c # glue code(初始化 + 扫描循环)
    /project/src/app/buttons/keyflow_port.c # 平台端口实现(GPIO 读写)
    /project/src/app/buttons/README.md # 说明文档(中文,自动生成)
    files_modified:
    Makefile 或 CMakeLists.txt # 追加 keyflow 源码路径
    main.c / xxx_init.c # 追加初始化调用
    verification:
    build_status: success|failed
    test_output: "7/7 tests passed"


    3. 核心流程设计(5 阶段)

    阶段 1:项目探查(Exploration)

    目标:在不修改任何文件的前提下,识别工程结构与约定。

    探查内容:

    探查项探查方法示例
    构建系统 ls *.c Makefile CMakeLists.txt project.uvprojx 识别为 Make / CMake / Keil
    源码目录结构 find . -name "*.c" -type d | head -30 src/ app/ main hw/ 等
    头文件目录 定位 #include 模式 #include "stm32f1xx_hal.h" / #include "main.h"
    GPIO HAL 接口类型 grep -rn "HAL_GPIO|digitalRead|P1\\s*&\\s*(1|PORT_WritePin" src 等 判断 STM32 HAL / Arduino / 51 / ESP-IDF / Linux sysfs
    主循环入口 grep -n "while\\s*(\\s*1\\s*)|main\\s*(" src/main* 定位扫描代码放入何处
    已有按键代码 grep -rn "button|key|按键" src/ 判断是否需要迁移已有按键
    编译器/平台 从 Makefile / CMakeLists.txt 中提取 arm-none-eabi-gcc / sdcc / gcc

    输出:结构化 JSON project_profile.json(仅内存使用,不写文件)

    阶段 2:安装(Installation)

    目标:把 keyflow 源码按工程约定放置。

    安装策略(二选一):

    策略适用场景操作
    A. Git 子模块 Git 仓库已初始化 git submodule add keyflow 仓库到 third_party/keyflow/
    B. 文件拷贝 非 Git / 简单工程 拷贝 include/button/*.h 和 src/button/*.c 到 third_party/keyflow/

    安装产物位置约定:

    project/
    ├── third_party/
    │ └── keyflow/ ← keyflow 完整仓库或仅需要的文件
    │ ├── include/button/*.h
    │ └── src/button/*.c
    └── src/app/buttons/ ← Skill 生成的 glue code(见阶段 4)

    CMake/Makefile 修改策略:

    • CMake 工程:在顶层 CMakeLists.txt 追加 add_subdirectory(third_party/keyflow/src/button) 并 target_link_libraries(your_app keyflow::button)(demo 可选项,与 keyflow 当前项目类似)
    • Makefile 工程:定义 BUTTON_DIR := third_party/keyflow,在 SRCS += … 追加 $(BUTTON_DIR)/src/button/*.c,并 CFLAGS += -I$(BUTTON_DIR)/include
    • Keil/IAR:基于 .uvprojx / .ewp 添加源文件条目(XML 解析/追加)

    阶段 3:配置(Configuration)

    目标:根据探查结果,生成 keyflow_port.c。

    平台判定规则:

    平台判定条件生成内容
    STM32 包含 stm32fxxx_hal.h 头文件 ButtonPort_ReadPin 实现 → HAL_GPIO_ReadPin;GetTickMs → HAL_GetTick
    51 单片机 包含 reg51.h / stc*.h,且编译器为 sdcc/keil c51 P1 & (1 << pin) 方式;GetTickMs → 基于定时器 systick
    ESP32 包含 freertos/FreeRTOS.h / driver/gpio.h gpio_get_level(pin);GetTickMs → xTaskGetTickCount * portTICK_PERIOD_MS
    Linux 包含 unistd.h 且无 MCU 头文件 Linux sysfs GPIO 或 /dev/gpiochipN
    裸机 以上均不满足 生成模板 + extern uint32_t SystemTick;

    引脚抽象约定:

    引脚编码 port_pin_code 为 uint16_t,高 8 位为 port(如 A=0, B=1, …),低 8 位为 pin 编号。

    阶段 4:对接(Integration)

    核心生成策略:

    A. 生成配置表(keyflow_config.h + keyflow_integration.c)

    /* 示例(STM32) */
    static ButtonManager g_keyflow_mgr;

    /* 按键配置表 — 从用户输入的 button_list 转换而成 */
    static const KeyflowEntry s_keyflow_keys[] = {
    {
    .cfg = {
    .pin = KEYFLOW_MAKE_PIN(KEYFLOW_PORT_A, 5), /* GPIOA,5 */
    .active_level = 0, /* 低电平有效 */
    .debounce_ms = 15,
    .release_debounce_ms = 15,
    .long_press_ms = 1000,
    .double_click_ms = 250,
    .stable_cnt_required = 2,
    .long_press_repeat_ms = 0,
    },
    .name = "KEY_OK",
    .on_pressed = app_on_key_ok_pressed,
    .on_long_press = app_on_key_ok_long_press,
    .on_clicked = app_on_key_ok_clicked,
    },
    /* … more keys … */
    };

    /* 统一事件分发回调 */
    static void keyflow_event_cb(Button *btn, ButtonEventType ev, void *ud) {
    const KeyflowEntry *entry = (const KeyflowEntry *)ud;
    switch (ev) {
    case BUTTON_EVENT_PRESSED:
    if (entry->on_pressed) entry->on_pressed(entry->idx);
    break;
    case BUTTON_EVENT_LONG_PRESS:
    if (entry->on_long_press) entry->on_long_press(entry->idx);
    break;
    /* … other events … */
    }
    }

    /* 初始化 */
    void keyflow_init(void) {
    ButtonManager_Init(&g_keyflow_mgr);
    for (int i = 0; i < ARRAY_SIZE(s_keyflow_keys); ++i) {
    ButtonManager_AddButton(&g_keyflow_mgr,
    s_keyflow_keys[i].cfg,
    keyflow_event_cb,
    &s_keyflow_keys[i]);
    }
    }

    /* 主循环扫描 — 用户在主循环调用 */
    void keyflow_task(void) {
    ButtonManager_UpdateAuto(&g_keyflow_mgr);
    }

    B. 矩阵键盘 / 中断驱动 / 事件队列 / 组合键

    若用户在 features 中声明启用,分别生成:

    功能生成文件核心内容
    矩阵键盘 keyflow_matrix.c MatrixKeyScanner 初始化 + MatrixKey_Scan 在扫描任务内调用
    中断驱动 keyflow_exti.c ExtiButton_OnInterrupt() 在 EXTI ISR 中调用,ExtiButton_Dispatch() 在主循环调用
    事件队列 keyflow_queue.c ButtonEventQueue_Push 回调 + 主循环 ButtonEventQueue_Pop
    组合键 keyflow_combo.c ComboKeyDetector 初始化 + 修饰键掩码匹配表
    C. 业务层对接

    在 business_hooks 中列出的业务函数,生成弱符号(__attribute__((weak)))或 extern 声明,让业务层自行实现:

    /* keyflow_integration.h — 业务层需实现的回调 */
    extern void app_on_key_ok_pressed(uint8_t idx);
    extern void app_on_key_ok_long_press(uint8_t idx);
    /* … */

    阶段 5:验证(Verification)

    验证步骤:

  • 生成最小可运行示例 keyflow_demo.c — 单按键 + 长按连发测试
  • 构建验证:执行用户项目的构建命令,捕获错误并仅打印,不修改非必要代码
  • 静态检查:gcc -Wall -Wextra -fsyntax-only 语法检查(不链接)
  • 日志输出验证报告:keyflow_integration_report.md — 中文,列出:按键数、事件类型、回调函数、编译状态、测试输出

  • 3.6 实现状态对照

    设计要求实现状态说明
    Phase 1: 项目探查 ✅ 完全实现 explore_project() 扫描构建系统/平台/GPIO HAL/main 入口
    Phase 2: 源码安装 ✅ 实现 支持 copy-local 和 git-submodule 两种方式
    Phase 3: 端口生成 ✅ 完全实现 5 个平台模板(STM32/51/ESP32/Linux/baremetal)
    Phase 4a: 配置表生成 ✅ 完全实现 动态生成按键配置表 + 弱符号回调声明
    Phase 4b: 集成代码 ✅ 完全实现 模板包含 init + 循环注册 + 统一事件分发
    Phase 4c: 扩展模块 ✅ 完全实现 matrix/exti/queue/combo 4 个独立模板
    Phase 4d: Demo 示例 ✅ 完全实现 mock 端口注入 + 短按/长按自测试
    Phase 5: 编译验证 ⚠️ 部分实现 Linux/baremetal 执行 gcc 语法检查,其他平台仅文件检查
    Phase 0: Git 分支隔离 ✅ 完全实现 自动创建 feature 分支,失败可回滚
    CMake/Makefile 修改 ❌ 未实现 需用户手动将生成的 .c 文件添加到编译列表
    main.c 注入调用 ❌ 未实现 需用户手动在 main 中添加 keyflow_init() 和 keyflow_task()
    .bak 备份策略 ❌ 未实现 改用 Git 分支隔离替代
    交互式模式 ❌ 未实现 当前仅支持命令行参数
    幂等性检测 ⚠️ 部分实现 检测已存在目录时警告并覆盖,但不检测重复注册

    当前版本使用须知:集成完成后,用户需手动完成两步:

  • 将 src/third_party/keyflow/ 下的 .c 文件添加到编译系统(CMakeLists.txt / Makefile)
  • 在 main 函数中调用 keyflow_init() 和 keyflow_task()

  • 3.7 实际文件结构

    .trae/skills/keyflow-integrator/
    ├── SKILL.md # Skill 使用说明
    ├── keyflow_integrator.py # 核心实现(1019 行)
    └── templates/
    ├── keyflow_config_template.h # 按键配置表模板
    ├── keyflow_integration_template.c # init + task 集成模板
    ├── keyflow_port_stm32_template.c # STM32 HAL 端口
    ├── keyflow_port_51_template.c # 51 单片机端口
    ├── keyflow_port_esp32_template.c # ESP32 IDF 端口
    ├── keyflow_port_linux_template.c # Linux sysfs GPIO 端口
    ├── keyflow_port_baremetal_template.c # 裸机/自定义端口
    ├── keyflow_matrix_template.c # 矩阵键盘扩展
    ├── keyflow_exti_template.c # 中断驱动扩展
    ├── keyflow_queue_template.c # 事件队列扩展
    ├── keyflow_combo_template.c # 组合键/序列键扩展
    └── keyflow_demo_template.c # 最小可运行示例


    4. 安全性与幂等性设计

    风险防护策略
    重复安装 third_party/keyflow/ 已存在时跳过安装,仅提示更新
    重复生成 src/app/buttons/ 已存在时先 .bak 备份再覆盖,或提示用户选择覆盖/跳过
    破坏已有按键实现 先扫描 grep -rn "button|key",若已存在按键代码,不删除仅追加补丁:把新实现放在独立目录,并在 README 中说明迁移建议
    路径不完整 所有路径相对 project.path
    Git 未初始化 B 策略(文件拷贝)自动降级
    平台识别失败 生成模板占位符代码 + 在验证阶段提供多平台模板,让用户手动选择
    业务回调不存在 弱符号 + 编译链接警告,验证阶段输出缺失列表

    5. 示例运行流程(伪代码)

    ┌────────────────────────────────────────────┐
    │ 用户输入:"把 keyflow 装到 /my_project" │
    └────────────────────────────────────────────┘


    ┌────────────────────────────────────────────┐
    │ Phase 1: 项目探查(read-only) │
    │ – ls /my_project │
    │ – grep 构建系统 / GPIO 头文件 / 按键关键字 │
    │ 输出: project_profile = { │
    │ build_system: cmake, │
    │ platform: stm32, │
    │ compiler: arm-none-eabi-gcc │
    │ } │
    └────────────────────────────────────────────┘


    ┌────────────────────────────────────────────┐
    │ Phase 2: 安装 keyflow │
    │ – git submodule add keyflow 到 third_party/│
    │ 或: cp keyflow/include/button/*.{h,c} │
    │ – CMakeLists.txt 追加 add_subdirectory │
    │ 或: Makefile 追加 BUTTON_DIR + CFLAGS │
    └────────────────────────────────────────────┘


    ┌────────────────────────────────────────────┐
    │ Phase 3: 生成端口 │
    │ – 生成 keyflow_port.c(基于 platform) │
    │ – 生成 keyflow_config.h(按键配置表) │
    │ – 生成 keyflow_integration.c(主循环扫描) │
    │ – 生成 keyflow_<feature>.c(扩展模块) │
    └────────────────────────────────────────────┘


    ┌────────────────────────────────────────────┐
    │ Phase 4: 业务对接 │
    │ – 生成 business_hooks → 弱符号 extern │
    │ – 让用户实现业务回调 │
    └────────────────────────────────────────────┘


    ┌────────────────────────────────────────────┐
    │ Phase 5: 验证 │
    │ – cmake –build . │
    │ – 语法检查 │
    │ – 生成验证报告 keyflow_integration_report.md │
    └────────────────────────────────────────────┘


    ┌────────────────┐
    │ 完成! │
    └────────────────┘


    6. 文件命名约定(与当前 keyflow 项目保持一致)

    生成文件路径(相对 project.path)说明
    keyflow_config.h src/app/buttons/ 按键配置表 + 回调声明
    keyflow_port.c src/app/buttons/ GPIO 读写 + 时间戳
    keyflow_integration.c src/app/buttons/ 初始化 + 主循环扫描
    keyflow_demo.c src/app/buttons/ 最小可运行示例
    keyflow_integration_report.md src/app/buttons/ 中文验证报告

    7. 与当前 keyflow 项目的接口映射

    keyflow APISkill 生成的 glue code
    ButtonConfig keyflow_config.h → 结构体数组
    ButtonManager_Init keyflow_integration.c → keyflow_init()
    ButtonManager_AddButton keyflow_integration.c → 循环注册
    ButtonManager_UpdateAuto keyflow_task()
    MatrixKey_Init / Scan keyflow_matrix.c → 矩阵键盘
    ExtiButton_OnInterrupt / Dispatch keyflow_exti.c → 中断驱动
    ButtonEventQueue_Init / Push / Pop keyflow_queue.c → 事件队列
    ComboKey_Init / Detect keyflow_combo.c → 组合键 / 序列键

    8. 错误处理与用户交互策略

    场景Skill 行为对用户的反馈
    无法识别构建系统 停止并询问 “你的工程使用什么构建系统?(make/cmake/keil/…)”
    无法识别平台 停止并询问 “你的目标硬件平台是?(stm32/51/esp32/linux/baremetal)”
    button_list 为空 询问并生成参考 “请描述你的按键列表(名称/引脚/有效电平/消抖/长按阈值/回调函数名)”,或默认 3 按键示例
    GPIO 语法无法解析 把 pin 标记为"需手动确认" 在报告中列出所有"需手动确认的 pin 映射"
    编译失败 不修改代码,打印完整编译日志 “编译失败,错误日志已输出”

    9. 回滚策略

    • 每次执行前自动:

    • 备份 CMakeLists.txt / Makefile → .bak
    • 备份 src/app/buttons/ 若已存在 → .bak/
    • 记录操作日志 keyflow_integration.log
    • 回滚命令(Skill 可执行):若用户说"撤销刚才的操作",执行 git checkout — <files> 或 mv .bak 文件恢复


    10. Skill 元数据

    skill:
    name: keyflowintegrator
    version: 1.0.0
    description: 将 keyflow 按键模块安装到目标 C/嵌入式工程,并生成配置表、端口抽象、业务对接代码与验证报告
    inputs:
    项目路径(绝对路径)
    构建系统(make/cmake/keil/iar/other)
    平台(stm32/51/esp32/linux/baremetal)
    按键数量 + 按键描述列表(可选)
    启用的扩展功能(矩阵/中断/事件队列/组合键)
    业务回调函数映射(可选)
    outputs:
    third_party/keyflow/ 源码
    src/app/buttons/*.{h,c} 业务对接代码
    修改后的构建文件(CMake/Makefile)
    中文集成报告 keyflow_integration_report.md


    11. 与 keyflow 当前代码的关联

    Skill 在生成代码时,严格遵循 keyflow 当前项目中 include/button/button.h 的 API 契约,不做任何 API 扩展或修改。生成的 glue code 仅做三件事:

  • 调用现有 API
  • 把业务层的业务逻辑通过回调与 keyflow 事件分发器连接
  • 为目标平台实现 ButtonPort_* 的具体实现
  • 实际实现中的关键映射:

    keyflow API模板中使用方式模板文件
    ButtonConfig keyflow_config_template.h → 结构体数组 keyflow_config_template.h
    ButtonManager_Init keyflow_integration_template.c → keyflow_init() keyflow_integration_template.c
    ButtonManager_AddButton 循环注册 + keyflow_event_cb 统一分发 keyflow_integration_template.c
    ButtonManager_UpdateAuto keyflow_task() 中调用 keyflow_integration_template.c
    ButtonPort_ReadPin/WritePin/GetTickMs 5 个平台模板分别实现 keyflow_port_*.c
    MatrixKey_* / ExtiButton_* / ButtonEventQueue_* / ComboKey_* 4 个扩展模块独立实现 keyflow_*_template.c

    12. 设计确认记录

    以下为设计阶段提出的待确认事项及其最终处理结果:

    #待确认事项最终决策实现情况
    1 Skill 名称 keyflow-integrator ✅ 已采用
    2 生成文件位置 src/third_party/keyflow/(源码)+ src/app/buttons/(glue code)✅ 已调整路径约定
    3 业务回调策略 弱符号 extern 声明 ✅ 已实现
    4 扩展模块策略 用户声明时才生成 ✅ 已实现(4 个独立模板)
    5 验证深度 仅编译 + 日志输出 ✅ 已实现(gcc 语法检查)
    6 备份策略 Git 分支隔离替代 .bak ✅ 已实现(feature/keyflow-integration-<timestamp>)

    尚未实现的设计项(待后续版本补充):

    • CMake/Makefile 自动修改
    • main.c 自动注入 keyflow_init() / keyflow_task()
    • 交互式参数收集模式

    项目仓库

    • GitCode 仓库:https://gitcode.com/AZE-BlackCore/keyflow

    免责声明

    本文内容仅作为技术研究与学习交流之用,不构成任何形式的产品设计建议、电子工程建议或商业推荐。文中涉及的代码片段、状态机模型、消抖策略等技术方案,基于特定嵌入式场景与硬件条件设计,直接用于生产环境前请务必进行充分的测试与验证。

    使用本文内容所导致的任何直接或间接后果(包括但不限于设备损坏、数据丢失、商业损失等),作者及 AZE-BlackCore 不承担任何责任。 请根据你的实际项目需求,结合硬件手册、行业规范与最佳实践进行独立判断和决策。

    版权声明:本文版权归 AZE-BlackCore 所有,转载请注明出处。封面与示意图由 AI 生成,仅供示意参考。

    赞(0)
    未经允许不得转载:171主机测评 » 08 keyflow 按键模块集成 Skill 设计方案
    分享到: 更多 (0)

    评论 抢沙发

    • 昵称 (必填)
    • 邮箱 (必填)
    • 网址