From 735652b34fe92baa5ecf8ed503ce15c012e523d1 Mon Sep 17 00:00:00 2001 From: cuicuiV5 Date: Sat, 5 Sep 2026 21:10:41 +0800 Subject: [PATCH] refactor: simplify webui labels, unify layer naming, and polish readme --- README.md | 410 +++++++++----------------- src/keymap/key_state_machine.c | 12 +- src/keymap/key_state_machine.h | 2 +- src/web/web_ui.h | 513 ++++++++++++++++----------------- 4 files changed, 400 insertions(+), 537 deletions(-) diff --git a/README.md b/README.md index e71ad52..cbd55de 100644 --- a/README.md +++ b/README.md @@ -1,326 +1,204 @@ -# RemoteMapper-ESP32 · 小米蓝牙遥控器 2 Pro (RC003) ➔ USB 复合硬件桥接器 +# RemoteMapper-ESP32 -> 🎯 **基于 ESP32-S3 (N16R8 / N8R2 / N4R2) 的硬件级中间人协议桥接方案** -> 彻底解决 Windows 内核驱动丢弃「音量+ / 音量- / 返回键」的顽疾,告别 VB-Cable 虚拟声卡依赖,实现真·即插即用! -> ⚠️ **硬件型号限定**:目前固件**仅支持「小米蓝牙遥控器 2 Pro(型号:RC003)」**,暂不支持其他型号遥控器。 +基于 ESP32-S3 的小米蓝牙遥控器 2 Pro (RC003) 转 USB 复合设备硬件桥接方案。 +将遥控器信号直接转换为标准免驱的 USB 输入设备(UAC 1.0 麦克风 + HID 键盘 + 媒体控制),解决 Windows 系统下特定按键被丢弃和音频输入依赖虚拟声卡的问题。 + +注:当前固件仅支持**小米蓝牙遥控器 2 Pro(型号:RC003)**,暂不支持其他型号。支持 ESP32-S3 N16R8、N8R2、N4R2 等主流硬件版本。 --- -## 💡 为什么需要这个硬件项目?(背景与痛点) +## 背景与解决的问题 -市面上的**小米蓝牙语音遥控器 2 Pro(型号:RC003)**采用精致的银色铝合金金属外壳,按键手感清脆、布局经典,并内置麦克风与拾音孔,非常适合作为 PC / HTPC 的全局多功能遥控器与 AI 语音助手控制器。 +在 Windows 系统下直接使用小米蓝牙遥控器 2 Pro 时,存在两处系统级限制: -此前,开源社区作者 QL-4 等曾开发过基于 C# 的纯软件方案([QL-4/RemoteMapper](https://github.com/QL-4/RemoteMapper)),通过 Windows BLE API 读取按键与音频。 +1. **部分物理按键被系统丢弃**: + 遥控器的「音量+ (0x80)」、「音量- (0x81)」、「返回 (0xF1)」采用非标准 HID 键码。Windows 自带的蓝牙键盘驱动(`kbdhid.sys`)会在内核层将其直接过滤丢弃,应用层(包括全局 Hook、RawInput、AutoHotkey 等)无法截获这三个按键。若通过编写 Windows 内核过滤驱动来捕获,必须开启系统测试签名模式,存在系统崩溃风险且易被游戏反作弊程序拦截。 +2. **语音功能依赖虚拟声卡**: + 遥控器传输的是私有 ATVV 协议编码音频。在纯软件方案中,解码后的音频需要借助第三方虚拟声卡(如 VB-Cable)进行二次路由,输入法才能采集,配置繁琐且存在额外延迟。 -但经过大量跨平台测试发现了一个非常核心的事实: -* 🍏 **在 macOS 与 🐧 Linux 系统下**:操作系统原生蓝牙 HID 协议栈极其开放,**完全没有所谓的按键屏蔽限制**,所有按键都能被正常捕获与映射,体验非常爽快! -* 🪟 **唯独在 Windows 系统下**:微软官方的蓝牙键盘驱动对非标 HID 做了极为死板的内核层过滤,导致纯软件方案在 Windows 上遭遇了无法逾越的系统级绝症——**必须依靠我们的硬件中转桥接器才能完美解决!** - -### Windows 平台下纯软件方案的致命局限: -1. **三个核心按键被 Windows 驱动直接丢弃(无法映射)**: - * **音量+(`0x80`)**、**音量-(`0x81`)**、**返回键(`0xF1`)**:这三个按键在 RC003 遥控器固件中采用的是 Android 专属非标 HID 编码; - * 当遥控器直接与 Windows 电脑蓝牙配对时,微软官方蓝牙键盘驱动 `kbdhid.sys` 在内核层将其识别为未知非法键码并**直接丢弃**! - * 结果就是:应用层(无论通过全局 Windows Hook、RawInput 还是 AutoHotkey)**完全收不到任何按键消息**,这三个键在 Windows 下彻底沦为“死键”。 -2. **纯软件若想在 Windows 捕获,必须付出惨痛代价(内核级驱动风险)**: - * 要在 Windows 层面拦截未进入 `kbdhid.sys` 的原始 HID 报文,唯一的软件途径是编写 Windows 内核过滤驱动(Kernel Filter Driver); - * 这要求操作系统必须永久开启**「测试签名模式(Test Mode)」或「禁用驱动程序签名强制」**; - * **严重负面后果**:直接导致主流游戏反作弊系统(如腾讯 ACE、拳头 Vanguard、Easy Anti-Cheat、BattlEye)判定系统存在内核作弊隐患并封禁游戏;同时破坏 Windows 内核完整性,带来极高的蓝屏(BSOD)与系统崩溃风险。 -3. **语音输入强依赖第三方虚拟声卡(VB-Cable)**: - * 虽然纯软件可以通过 Windows GATT API 接收 ATVV 语音流并解码为 PCM,但要让输入法(微信输入法、讯飞等)识别,用户**必须额外安装第三方虚拟声卡(如 VB-Cable)**; - * 繁琐的虚拟音频管道配置、难以避免的缓冲区延迟、偶尔出现的采样率抖动与破音,严重影响了语音输入的优雅体验。 +本项目采用 ESP32-S3 作为硬件中间人: +* 上游直连遥控器蓝牙,在空口完整接收所有 13 个按键的原始报文并解码音频; +* 下游通过芯片原生 USB 向电脑模拟标准的免驱硬件(UAC 1.0 麦克风与标准 HID 键盘/多媒体设备); +* 电脑端即插即用,无需安装任何驱动或后台软件,不修改系统内核,不影响游戏反作弊。 --- -## ⚡ 硬件桥接的基本原理 - -**软件在操作系统层无法优雅解决的问题,交给硬件中间人来做。** - -本项目通过一颗极低成本的 **ESP32-S3** 芯片充当**硬件中间人(Hardware Bridge)**: +## 系统拓扑 ```text -┌────────────────────────┐ Bluetooth LE 5.0 (HOGP + ATVV) ┌────────────────────────┐ -│ │ ───────────────────────────────────────► │ │ -│ 小米蓝牙语音遥控器 │ │ ESP32-S3 N16R8 │ -│ (Peripheral 端) │ ◄─────────────────────────────────────── │ (Central 主机端) │ -└────────────────────────┘ 双向配对握手与私有音频协商 └───────────┬────────────┘ - │ - │ USB 2.0 Full-Speed - │ (TinyUSB 硬件复合设备) - ▼ - ┌────────────────────────┐ - │ PC 宿主机 (Win/Mac) │ - │ │ - │ • 标准 UAC 1.0 麦克风 │ - │ • 标准 USB HID 键盘 │ - │ • 标准 Consumer 多媒体 │ - └────────────────────────┘ +┌────────────────────────┐ BLE 5.0 (HOGP + ATVV) ┌────────────────────────┐ +│ │ ──────────────────────────────► │ │ +│ 小米蓝牙遥控器 2 Pro │ │ ESP32-S3 │ +│ (RC003) │ ◄────────────────────────────── │ (Central 主机) │ +└────────────────────────┘ └───────────┬────────────┘ + │ + │ USB 2.0 Full-Speed + │ (原生 USB OTG 复合设备) + ▼ + ┌────────────────────────┐ + │ PC 宿主机 │ + │ │ + │ • 标准 UAC 1.0 麦克风 │ + │ • 标准 USB HID 键盘 │ + │ • 标准 Consumer 媒体键 │ + └────────────────────────┘ ``` -1. **上游接管**:ESP32-S3 作为 BLE Central 主机端直连小米遥控器,在蓝牙空中信道原始层完整接收 HOGP 报文与私有 ATVV 协议,**绕过微软 `kbdhid.sys` 的过滤,100% 捕获包括「音量+、音量-、返回键」在内的全部 13 个物理按键**; -2. **边缘 DSP 音频处理**:遥控器传出的 4-bit IMA-ADPCM 压缩音频流,在 ESP32 内部实时解码为 16kHz 16-Bit PCM,并完成 Declip 防破音、FIR 低通滤波与动态 AGC 增益平滑; -3. **下游模拟物理硬件**:ESP32-S3 原生 USB OTG 直接向电脑模拟出符合 USB-IF 标准的**标准免驱硬件设备**: - * 将 `0x80` / `0x81` 映射为标准 USB Consumer 键码 `0x00E9` / `0x00EA`(原生调节系统音量); - * 将 `0xF1` 映射为标准 USB Consumer 键码 `0x0224`(网页与播放器原生后退); - * 将解码后的音频通过标准 UAC 1.0 Isochronous 管道实时推送给电脑; -4. **对电脑而言**:PC 认为接入的就是一个**正规的物理 USB 麦克风和物理 USB 键盘**,**无需安装任何驱动,无需配置虚拟声卡,无内核侵入,不触发反作弊,绝对稳定安全**。 +--- + +## 核心特性 + +1. **免驱 USB 物理麦克风(UAC 1.0)** + * 基于 TinyUSB 协议栈,模拟 16kHz 16-Bit 单声道标准输入设备。 + * 实时解码遥控器 IMA-ADPCM 音频流。 + * 包含音频前处理:按下瞬间立即注入输入法快捷键,并在音频前段插入 150ms 静音区(抑制按键微动物理杂音并留出输入法唤起窗口),消隐期结束施加 10ms 微平滑淡入(消除电平跳变爆音),结合 AGC 软启动避免拾取环境底噪。 + +2. **5 层独立映射系统** + * 提供 5 个独立按键配置层(默认层、层1 ~ 层4)。 + * 每个按键均支持单击、长按(200~2000ms 可调)、双击(100~600ms 可调)。 + * 支持三种层级生命周期: + * 永久停留层:手动切入后持续生效,直至再次切换。 + * 一次性层:触发任意按键后自动返回默认层。 + * 超时返回层:闲置达到设定秒数(3~300 秒)后自动返回默认层。 + * 穿透继承:非默认层未单独配置的按键自动沿用默认层的设置。 + * 自动防呆反转:若当前已在目标层,再次触发切入该层的按键时,会自动返回默认层。 + * 支持为不同层级指定不同的板载 RGB 指示灯颜色。 + +3. **标准媒体与系统按键支持** + * 支持映射为音量调节、静音、播放/暂停、曲目切换、系统休眠等标准 USB Consumer 键码,系统级原生响应。 + +4. **内置 Web 管理后台** + * 固件集成 Web 服务器,通过浏览器即可完成可视化按键映射配置、蓝牙配对、网络设置与日志查看。 + * 支持 AP 热点配置与 STA 局域网接入。 + * 配置数据持久化保存在 ESP32 的 NVS 分区中,掉电不丢失。 --- -## 🌟 项目核心特性 +## 默认出厂按键映射 -### 1. 🎙️ 真·免驱 USB 物理麦克风(UAC 1.0) -* 基于 TinyUSB 栈模拟标准 USB Audio Class 1.0 设备,16kHz 16-Bit Mono 原生输入; -* **按住语音键说话,松开自动静音**,无缝对接 Windows 语音听写(`Win+H`)、豆包 AI、微信语音与各类会议软件; -* 独创 **bInterval=2 / wMaxPacketSize=64** 降频缓冲设计,彻底解决 DWC2 硬件 USB 缺失 SOF 中断导致的 500Hz 丢帧魔咒,音频平滑无底噪; -* 🔇 **独创「150ms 消隐区 + 10ms 微平滑 + AGC 软启动」三阶抑噪技术**: - * **150ms 前置消隐区**:按下语音按键瞬间(0ms)即刻向电脑注入输入法热键,同时在音频流前段强制填入 150ms 数字全 0 静音,彻底抹除微动开关物理按压的“咯噔”敲击声,并为电脑端输入法留足唤出录音窗口的缓冲时间; - * **10ms 微平滑淡入(Micro Fade-In)**:消隐期结束瞬间施加 10ms(160 采样点)快速微平滑过渡,短于人耳感知阈值,既完美消除硬切边界引起的阶跃冲激电流爆音,又彻底杜绝了调幅效应产生的“沙沙”底噪; - * **AGC 软启动(Soft-Start)**:增益从 1.0x(0dB)平稳起步,并在消隐期冻结增益爬升,彻底避免开局将环境底噪放大引发输入法误识别出“嗯、啊、额”等杂音字。 - -### 2. 🎚️ 极客客制化 5 大独立层级系统 (Multi-Layer Architecture) -* **打破 12 键硬件上限**:内置 **5 个完全独立的按键映射层(Layer 0 ~ Layer 4)**,配合单击、长按、双击,带来多达 **180+ 动作维度**; -* 🔄 **智能自翻转双向切层 (Auto-Toggle on Same Target)**: - * 当触发“切入 Layer X”时,若当前已经在 Layer X,系统**自动翻转回退至 Layer 0 (默认主层)**; - * 结合穿透继承,双击/长按同一按键即可自然进出目标层,**无需专门占用宝贵的按键去配置返回键**! -* ⏱️ **三种完备的层级生命周期类型**: - * **🔒 永久停留层 (Persistent)**:驻留在目标层,直到手动再次切层; - * **⚡ 一次性瞬态层 (One-Shot)**:执行该层内任意按键后,瞬间自动退回 Layer 0; - * **⏳ 超时自动返回层 (Timeout)**:持续使用保持在该层,一旦闲置超过预设秒数(3~300秒自定),硬件自动静默回退回 Layer 0; -* 🔗 **按键穿透继承 (Layer Transparency)**:Layer 1~4 中未单独覆盖的按键自动穿透继承 Layer 0,免除重复配置; -* 🟣 **板载 WS2812 RGB 状态指示灯**:各层支持自定义独立 RGB 状态灯色彩(Layer 0: 绿色, 1: 青色, 2: 紫色, 3: 黄色, 4: 白色等),切层瞬间伴随高光呼吸闪烁,当前所在层级一目了然; -* 🎮 **完备的手势触发**:所有 12 个可编辑按键全部支持 **单击(Click)、长按(Long Press, 200~2000ms 可调)、双击(Double Click, 100~600ms 可调)**。 - -### 3. 🎵 原生标准 USB Consumer 多媒体控制 -* 音量增加(`0x00E9`)、音量减少(`0x00EA`)、静音(`0x00E2`)、播放/暂停(`0x00CD`)、曲目切换与系统休眠; -* 完美兼容 Windows、macOS 与 Linux 原生全局音量与媒体控制。 - -### 4. 🔢 全链路 16 进制 / 10 进制双模智能引擎 -* WebUI 所有选项、按键下拉菜单与微调输入框全面标清 `0x...` 标准 16 进制键码; -* 支持直接粘贴标准 16 进制键码(如 `0x2C`)或传统十进制数值,双向智能兼容。 - -### 5. 🛡️ 生产级 NVS 存储容灾与开机自愈 -* 紧凑型 JSON 序列化存储,所有配置写入仅占用 Flash NVS 扇区不足 35%; -* 采用局部原子事务,写入后立刻调用 `nvs_flash_commit()`,彻底杜绝异常断电丢数据; -* 具备开机自愈校验机制:若检测到 Flash 扇区数据损坏或非法修改,自动无缝降级回出厂安全配置,杜绝系统崩溃变砖。 - -### 6. 🌐 免客户端嵌入式 Web 可视化后台 -* 自带双模 Wi-Fi 管理器: - * **热点模式(AP)**:无需电脑连接局域网,手机或电脑直连热点 `RemoteMapper-AP`(192.168.4.1)并通过 Captive Portal 自动弹窗配置; - * **局域网模式(STA)**:连接家中 Wi-Fi,随时随地在浏览器中访问管理; -* 内置 1:1 遥控器真机动态交互面板、实体键盘敲击即录制改键、实时高频运行日志流与 Flash NVS 纯文本高级编辑器。 - ---- - -## 📋 预置按键映射表(出厂默认配置) - -| 遥控器按键 | 物理键码 | 单击行为 (Click) | 长按行为 (Long Press) | 双击行为 (Double Click) | +| 按键 | 物理键码 | 单击行为 | 长按行为 | 双击行为 | | :--- | :--- | :--- | :--- | :--- | -| **电源键** | `0x66` | `Alt + F4` (关闭窗口) | 🌙 系统休眠 (`0x0032`) | — | -| **语音键** | `0x04` | 🎙️ UAC 麦克风推流 + `Alt + ,` (AI语音助手) | 🎙️ 按住持续录音 | — | -| **方向上** | `0x52` | 键盘 `↑` (Arrow Up) | — | — | -| **方向下** | `0x51` | 键盘 `↓` (Arrow Down) | — | — | -| **方向左** | `0x50` | 键盘 `←` (Arrow Left) | — | — | -| **方向右** | `0x4F` | 键盘 `→` (Arrow Right) | — | — | -| **确定键** | `0x28` | 键盘 `Enter` (回车) | — | — | -| **返回键** | `0xF1` | 多媒体返回 (`0x0224` AC Back) | — | — | -| **主页键** | `0x24` | `Win + D` (显示/隐藏桌面) | — | — | -| **菜单键** | `0x5D` | 键盘 `Space` (空格 / 播放暂停) | — | — | -| **音量+** | `0x80` | 🔊 音量增加 (`0x00E9` Vol+) | — | — | -| **音量-** | `0x81` | 🔉 音量减少 (`0x00EA` Vol-) | — | — | -| **电视键** | `0xC0` | 键盘 `F8` | — | — | +| **电源键** | `0x66` | `Alt + F4` (关闭窗口) | 系统休眠 (`0x0032`) | — | +| **语音键** | `0x04` | 麦克风音频推流 + `Alt + ,` | 按住持续录音 | — | +| **方向上** | `0x52` | 方向键上 (`↑`) | — | — | +| **方向下** | `0x51` | 方向键下 (`↓`) | — | — | +| **方向左** | `0x50` | 方向键左 (`←`) | — | — | +| **方向右** | `0x4F` | 方向键右 (`→`) | — | — | +| **确定键** | `0x28` | 回车 (`Enter`) | — | — | +| **返回键** | `0xF1` | 多媒体返回 (`0x0224`) | — | — | +| **主页键** | `0x24` | 显示桌面 (`Win + D`) | — | — | +| **菜单键** | `0x5D` | 空格 (`Space`) | — | — | +| **音量+** | `0x80` | 音量增加 (`0x00E9`) | — | — | +| **音量-** | `0x81` | 音量减少 (`0x00EA`) | — | — | +| **电视键** | `0xC0` | `F8` | — | — | -*注:以上按键均可在 Web 后台任意修改、互换或自定义为任何按键/多媒体功能。* +*注:以上按键均可在 Web 后台自由修改、重新分配或清除。* --- -## 🚀 完整使用教程(从零上手) +## 硬件连接 -整个使用流程简单清晰,分为以下六个核心步骤: - -### 步骤 1:硬件采购与接线 -1. **采购开发板**:购买任意 **ESP32-S3-DevKitC-1** 主控板(淘宝约 18~35 元): - * 🌟 **全系列主流型号无缝兼容**: - * **N16R8**(16MB Flash + 8MB Octal PSRAM):旗舰大容量配置,出厂默认目标; - * **N8R2**(8MB Flash + 2MB Quad PSRAM):性价比极高的高频主流款,内存与存储极为充裕; - * **N4R2**(4MB Flash + 2MB Quad PSRAM):极简低成本版,固件极致精简后仅 1.16MB,仍完整保留 A/B 双分区 OTA 升级能力! -2. **准备遥控器**:小米蓝牙遥控器 2 Pro(型号: RC003) -3. **关键数据线连接**: - * ESP32-S3 开发板通常有两个 Type-C 口:一个标注为 **`UART`**(或 COM),另一个标注为 **`USB`**(或 **`OTG`**); - * **⚠️ 日常使用必须将数据线插在 `USB / OTG` 接口**(直连芯片原生内部 USB 控制器,才能免驱模拟物理麦克风与键盘;UART 口仅用于串口日志调试,无法模拟 USB 输入外设)。 +1. **开发板要求**: + 任意 ESP32-S3 开发板,推荐配置: + * **N16R8**(16MB Flash, 8MB PSRAM):默认构建目标。 + * **N8R2**(8MB Flash, 2MB PSRAM):主流常见规格。 + * **N4R2**(4MB Flash, 2MB PSRAM):极简规格,编译产物约 1.2MB。 +2. **遥控器**: + 小米蓝牙语音遥控器 2 Pro(型号:RC003)。 +3. **接口接线**: + ESP32-S3 通常带有两个 Type-C 接口: + * **`USB`(或 `OTG`)口**:必须连接到电脑。该接口直通 ESP32-S3 原生 USB 控制器,用于模拟 UAC 麦克风与 HID 设备。 + * **`UART` 口**:仅用于烧录与查看串口日志,日常使用无需连接。 --- -### 步骤 2:固件编译与一键烧写(多型号支持) +## 固件编译与烧录 -将 ESP32-S3 开发板通过数据线连接至电脑,根据开发板型号选择对应的烧录方式: +连接开发板至电脑,按需选择以下任一方式: -#### 方式 1:双击批处理脚本(最简便) -在本项目根目录下运行: -* **默认烧写 N16R8**:直接双击运行 `flash.bat` -* **命令行指定型号烧写**: - ```cmd - flash.bat n8r2 # 烧录至 N8R2 开发板 - flash.bat n4r2 # 烧录至 N4R2 开发板 - flash.bat n16r8 # 烧录至 N16R8 开发板 - ``` +### 方式 1:使用批处理脚本 -#### 方式 2:PlatformIO 命令行精确构建与烧录 -在本项目根目录下打开终端,可直接使用以下命令进行编译与烧写: +项目根目录下提供了预置脚本: +```cmd +flash.bat n16r8 :: 烧录至 N16R8 开发板(默认) +flash.bat n8r2 :: 烧录至 N8R2 开发板 +flash.bat n4r2 :: 烧录至 N4R2 开发板 +``` + +### 方式 2:使用 PlatformIO 命令行 + +在终端中执行对应型号命令: ```bash -# ======================================================== -# 1. 旗舰版 N16R8 (16MB Flash, 8MB Octal PSRAM) -# ======================================================== -# 仅编译固件 -python -m platformio run -e esp32s3_n16r8 -# 编译并烧录至开发板 -python -m platformio run -e esp32s3_n16r8 -t upload +# N16R8 +pio run -e esp32s3_n16r8 -t upload -# ======================================================== -# 2. 性价比版 N8R2 (8MB Flash, 2MB Quad PSRAM) -# ======================================================== -# 仅编译固件 -python -m platformio run -e esp32s3_n8r2 -# 编译并烧录至开发板 -python -m platformio run -e esp32s3_n8r2 -t upload +# N8R2 +pio run -e esp32s3_n8r2 -t upload -# ======================================================== -# 3. 极简版 N4R2 (4MB Flash, 2MB Quad PSRAM) -# ======================================================== -# 仅编译固件 -python -m platformio run -e esp32s3_n4r2 -# 编译并烧录至开发板 -python -m platformio run -e esp32s3_n4r2 -t upload +# N4R2 +pio run -e esp32s3_n4r2 -t upload ``` -> 💡 **烧录排错小贴士(Boot 模式)**: -> 若提示连接开发板超时或无法识别 COM 口,可按住开发板上的 **`BOOT` 按键不放**,点按一下 **`RST` 复位键**(或重新拔插一次 USB 线),松开 `BOOT` 按键即可强制开发板进入 ROM Download 下载模式,然后再执行上述烧录命令。 +若连接超时或无法进入下载模式,可按住开发板上的 `BOOT` 键,点按一次 `RST` 键后再松开 `BOOT` 键,即可强制进入下载模式。 --- -### 步骤 3:开机配网(连接家里 Wi-Fi) -1. 固件初次启动时,会自动广播一个开放式配置热点: - * **Wi-Fi 热点名称**:`RemoteMapper-AP` - * **热点默认密码**:无密码(直接连接) -2. 拿起手机或电脑,搜索并连接 `RemoteMapper-AP`; -3. 连接后系统通常会自动弹出强制门户配置页面;若未弹出,直接在浏览器中打开后台地址: - ```text - http://192.168.4.1/ - ``` -4. 切换到底部的 **「📶 Wi-Fi 与系统配置」** 选项卡,点击「🔍 搜索 Wi-Fi」,在列表中选定家里的 2.4GHz Wi-Fi 并输入密码,点击「💾 保存并连接 Wi-Fi」; -5. ESP32 连接成功后,以后只要电脑或手机在同一局域网下,直接在浏览器中访问分配的 IP(例如 `http://192.168.2.179`)或直接输入域名访问: - ```text - http://remotemapper.local/ - ``` +## 使用指南 + +### 1. 配网 +固件首次启动后会开启配置热点: +* 热点名称:`RemoteMapper-AP`(无密码) +* 浏览器访问:`http://192.168.4.1/` +* 进入「Wi-Fi 与系统配置」页面,扫描并连接局域网 Wi-Fi。连接成功后,可在局域网内直接通过分配的 IP 地址访问后台。 + +### 2. 配对遥控器 +1. 打开 Web 后台的「蓝牙配对管理」标签页。 +2. 拿起遥控器,**同时按住「主页键」与「菜单键」3 秒**,待指示灯快闪进入广播配对状态。 +3. 在网页上点击「扫描蓝牙设备」,找到对应设备并点击连接。 +4. 绑定成功后,设备信息会持久化保存,后续开机或遥控器休眠唤醒均会自动重连。 + +### 3. 按键与层级设置 +1. 进入「按键映射和层级设置」页面。 +2. 点击上方层级选项卡切换配置层(默认层、层1 ~ 层4)。 +3. 点击遥控器模型上的按键进入编辑弹窗,可独立设置单击、长按、双击触发的行为(键盘按键、多媒体控制或层级切换)。 +4. 保存配置后即刻生效并写入 Flash。 + +### 4. 输入法语音配置 +固件出厂默认在按住语音键时注入 `Alt + ,` 快捷键(微信输入法默认语音热键)。 +1. 打开电脑输入法设置,将麦克风输入源选择为系统新增的硬件设备:`RemoteMapper Mic`。 +2. 确认输入法的语音输入快捷键与遥控器语音键配置的快捷键一致。 +3. 按住遥控器语音键说话,松开按键即完成输入。 --- -### 步骤 4:遥控器蓝牙配对与绑定 -1. 在 Web 控制台顶部进入 **「📡 蓝牙配对管理」** 选项卡; -2. 拿起实体小米遥控器,**同时按住「主页键」与「菜单键」3 秒**,听到滴声或看到遥控器指示灯快闪,进入蓝牙配对广播状态; -3. 在网页上点击 **「🔍 扫描附近蓝牙设备」**,列表中会出现 `Xiaomi Voice Remote`(或 `小米蓝牙语音遥控器`); -4. 点击对应的 **「连接此设备」** 按钮,连接成功后遥控器 MAC 地址将自动写入 ESP32 Flash NVS; -5. **持久化自动回连**:绑定成功后,后续无论设备断电重启,还是遥控器深度休眠,按任意键即可在 **2~3 秒内秒级无感回连**! +## 进阶:与 PC 伴侣程序联动 ---- +若需要让按键触发打开特定软件、运行脚本或系统命令,可以使用项目附带的 `pc_companion` 辅助程序: -### 步骤 5:按键映射与手势自定义 -1. 进入 **「🎮 遥控器与改键测试」** 选项卡; -2. 随意按下实体遥控器的任意按键,屏幕上的 1:1 仿真遥控器模型会实时点亮高光绿框,并显示实时触发动作; -3. 点击模型上的任意按键卡片(例如点击「菜单键」或「电源键」),即可弹出改键弹窗; -4. 每个按键均可独立配置三个手势标签页: - * **单击(Click)**:瞬时点按或按下保持(Hold); - * **长按(Long Press)**:可自定 200ms ~ 2000ms 触发时长,长按自动阻止短按,互不干扰; - * **双击(Double Click)**:可自定 100ms ~ 600ms 双击判定间隔; -5. **改键极为简单**: - * **敲击即录制**:直接在物理电脑键盘上敲击目标按键(如敲一下 `Space` 或 `Ctrl+C`),网页自动捕捉录制; - * **快捷下拉选择**:菜单中预置了修饰键、F1~F24 专用键、快捷组合键(`Win+D` 回桌面、`Alt+Tab` 任务切换),以及原生多媒体功能(音量增减、静音、播放/暂停、休眠等); -6. 点击「💾 保存映射」,修改即刻生效并持久化至 Flash,断电不丢失。 - ---- - -### 步骤 6:配置语音输入法(让语音键满血工作) -遥控器的语音键出厂默认配置为:**按住时启动 UAC 麦克风音频推流,并注入快捷键 `右Alt + 逗号`**(这是微信输入法的默认语音快捷键)。 - -要让语音输入在 Windows 上完美工作,只需简单设置你的输入法(以微信输入法为例,搜狗、讯飞同理): -1. 打开输入法设置 ➔ 找到 **麦克风/音频输入源**,在下拉菜单中选择: - ```text - RemoteMapper Mic (设备管理器中免驱的原生物理麦克风) - ``` -2. 查看并确认输入法的 **语音输入唤醒快捷键** 与 ESP32 语音键派发的快捷键一致(默认即为 `右Alt + 逗号`;如果使用讯飞或搜狗,可把输入法快捷键设为 `F8` 或 `Ctrl+Shift+V`,并在 Web 后台同步修改语音键快捷键); -3. **开始体验**: - * 拿起遥控器,**按住语音键直接说话,说完松开按键**; - * 麦克风录音与快捷键完美无缝衔接,文字瞬间自动上屏打出! - ---- - -## 🎮 进阶可玩性:PC 本地伴侣程序 (`pc_companion`) 深度联动 - -> 💡 **解决痛点**:普通 USB 键盘只能模拟按键,无法执行「一键启动指定应用」、「一键运行复杂批处理」、「一键切换显示器信号源」或「一键运行 Python 脚本」。 - -我们随项目附带了极简、高性能的 PC 端伴侣后台服务:**`pc_companion`**。 - -### 🌟 核心原理:利用 F13 ~ F24 零冲突键码 -* Windows 原生支持 `F13` 到 `F24` 虚拟键码(VK_F13 ~ VK_F24),但现代实体键盘几乎没有这些按键; -* 本项目将遥控器动作映射为 `F13 ~ F24`,PC 伴侣通过原生 Win32 `RegisterHotKey` 监听,**待机 CPU 占用绝对 0.0%,内存占用仅几 MB,无任何钩子冲突与延迟**! - -### 🛠️ 快速配置与玩法示例: -1. **在 ESP32 Web 后台**:将任意遥控器按键(如双击 TV 键)映射为 `F13` 或 `F14`; -2. **在 PC 端编辑配置**:打开 `pc_companion/config.json`,为每个 F 键绑定任意本地动作: +1. 将遥控器指定手势映射为 `F13` ~ `F24` 等空闲功能键。 +2. 在 `pc_companion/config.json` 中为对应键位定义执行命令: ```json { "F13": { - "name": "一键打开抖音网页版", - "command": "start https://www.douyin.com/", - "enabled": true - }, - "F14": { - "name": "一键切换显示器信号源到 PS5", - "command": "C:\\Scripts\\切到ps5.bat", - "enabled": true - }, - "F15": { - "name": "运行自定义 Python 自动化脚本", - "command": "python scripts/demo_task.py", + "name": "打开浏览器", + "command": "start https://www.google.com", "enabled": true } } ``` -3. **启动与常驻**: - * **调试运行**:双击 `pc_companion/start_companion.bat`(前台黑框输出执行日志); - * **静默常驻**:双击 `pc_companion/silent_start.vbs`(无弹窗后台静默运行); - * **开机自启**:双击 `pc_companion/enable_autostart.bat`(自动注入 Windows 用户注册表启动项); - * **独立打包**:运行 `pc_companion/build_exe.bat`,即可一键打包生成独立的单文件绿色可执行程序 `RemoteMapperHost.exe`(无需安装 Python 环境)。 +3. 运行 `pc_companion/silent_start.vbs` 即可在后台静默监听触发。 --- -## 💖 鸣谢与致敬开源项目 (Special Thanks) +## 致谢 -本项目的诞生离不开开源社区先行者的无私探索与灵感启发,特此向以下优秀开源项目致以诚挚敬意: -* [QL-4/RemoteMapper](https://github.com/QL-4/RemoteMapper):启发了小米遥控器在 PC 端增强控制的应用场景,提供了宝贵的 Windows C# 软件实现方案与 ATVV 协议参考; -* [godarrenw/mi_remote_control](https://github.com/godarrenw/mi_remote_control):深入剖析了小米遥控器的蓝牙通信、逆向工程与 Linux 驱动底层细节,为本项目的协议实现提供了重要参考。 +* [QL-4/RemoteMapper](https://github.com/QL-4/RemoteMapper):提供了 Windows C# 软件方案与 ATVV 协议参考。 +* [godarrenw/mi_remote_control](https://github.com/godarrenw/mi_remote_control):提供了遥控器蓝牙协议分析与逆向参考。 --- -## 🤝 欢迎贡献 (Contributing & Roadmap) +## 开源协议 -本项目完全开源,代码模块化且结构清晰,热烈欢迎各位极客与开发者提交 Issue 和 Pull Request! -我们非常期待社区共同完善以下方向: -* 📡 **支持更多遥控器型号**:扩展适配更多小米老款遥控器、天猫魔盒遥控器、Apple TV 遥控器、Google Chromecast 遥控器等; -* 🎚️ **多层功能触发层 (Multi-Layer / Fn Chording)**:引入 Leader Key 前导键机制,实现按键层级切换; -* 📲 **WebUI 在线 OTA 固件升级**:免插拔数据线,直接在浏览器一键上传 `.bin` 固件无感更新。 -* 等等更多功能 - ---- - -## 📖 深入阅读与底层源码参考 - -* 📘 [开发者手册与系统技术全景文档 (DEVELOPMENT.md)](./DEVELOPMENT.md) -* 🐛 [蓝牙与 USB 复合设备稳定性深度修复报告](./BLE_HID_UAC_BUGS_POSTMORTEM.md) -* 🎧 [USB UAC 1.0 与 DWC2 驱动优化报告](./USB_UAC_BUG_POSTMORTEM.md) - ---- - -## 📄 开源许可证 -本项目遵循 [MIT License](./LICENSE) 开源许可协议。 +本项目采用 [MIT License](./LICENSE) 协议开源。 diff --git a/src/keymap/key_state_machine.c b/src/keymap/key_state_machine.c index 02c4b2b..060ace6 100644 --- a/src/keymap/key_state_machine.c +++ b/src/keymap/key_state_machine.c @@ -201,10 +201,10 @@ void key_engine_load_defaults(key_mapper_engine_t *engine) { engine->last_activity_time = 0; // ---------------------------------------------------- - // Layer 0: 默认主层 (Default Layer) + // Layer 0: 默认层 // ---------------------------------------------------- key_layer_t *l0 = &engine->layers[0]; - strncpy(l0->name, "默认主层", sizeof(l0->name) - 1); + strncpy(l0->name, "默认层", sizeof(l0->name) - 1); l0->type = LAYER_TYPE_PERSISTENT; l0->timeout_sec = 0; l0->led_color = 0x00FF00; // Green @@ -354,25 +354,25 @@ void key_engine_load_defaults(key_mapper_engine_t *engine) { // ---------------------------------------------------- // Preset Layers 1 ~ 4 (Inherit Layer 0 by default) // ---------------------------------------------------- - strncpy(engine->layers[1].name, "影音娱乐", sizeof(engine->layers[1].name) - 1); + strncpy(engine->layers[1].name, "层1", sizeof(engine->layers[1].name) - 1); engine->layers[1].type = LAYER_TYPE_TIMEOUT; engine->layers[1].timeout_sec = 15; engine->layers[1].led_color = 0x06B6D4; // Cyan engine->layers[1].binding_count = 0; - strncpy(engine->layers[2].name, "游戏模式", sizeof(engine->layers[2].name) - 1); + strncpy(engine->layers[2].name, "层2", sizeof(engine->layers[2].name) - 1); engine->layers[2].type = LAYER_TYPE_PERSISTENT; engine->layers[2].timeout_sec = 0; engine->layers[2].led_color = 0xA855F7; // Purple engine->layers[2].binding_count = 0; - strncpy(engine->layers[3].name, "快捷宏层", sizeof(engine->layers[3].name) - 1); + strncpy(engine->layers[3].name, "层3", sizeof(engine->layers[3].name) - 1); engine->layers[3].type = LAYER_TYPE_ONESHOT; engine->layers[3].timeout_sec = 0; engine->layers[3].led_color = 0xEAB308; // Yellow engine->layers[3].binding_count = 0; - strncpy(engine->layers[4].name, "办公演示", sizeof(engine->layers[4].name) - 1); + strncpy(engine->layers[4].name, "层4", sizeof(engine->layers[4].name) - 1); engine->layers[4].type = LAYER_TYPE_PERSISTENT; engine->layers[4].timeout_sec = 0; engine->layers[4].led_color = 0xFFFFFF; // White diff --git a/src/keymap/key_state_machine.h b/src/keymap/key_state_machine.h index 807e5cd..27333dd 100644 --- a/src/keymap/key_state_machine.h +++ b/src/keymap/key_state_machine.h @@ -80,7 +80,7 @@ typedef enum { } layer_type_t; typedef struct { - char name[MAX_LAYER_NAME_LEN]; // e.g. "默认主层", "影音娱乐" + char name[MAX_LAYER_NAME_LEN]; // e.g. "默认层", "层1" layer_type_t type; // LAYER_TYPE_* uint16_t timeout_sec; // 3 ~ 300s (for LAYER_TYPE_TIMEOUT) uint32_t led_color; // RGB 0x00RRGGBB (e.g. 0x00FF00) diff --git a/src/web/web_ui.h b/src/web/web_ui.h index af4c892..494729d 100644 --- a/src/web/web_ui.h +++ b/src/web/web_ui.h @@ -325,18 +325,18 @@ const char INDEX_HTML[] PROGMEM = R"rawliteral(
- - - - - + + + + +
- 🎮 真机 1:1 遥控器多层级系统 (Multi-Layer Keymapper) + 按键映射和层级设置
@@ -348,25 +348,25 @@ const char INDEX_HTML[] PROGMEM = R"rawliteral(
- 层级别名 (Layer Name) - 层级别名 +
- 层级生命周期类型 (Lifecycle Type) + 层级生命周期类型