内容

# 提示旋钮伴侣应用
提示旋钮的伴侣应用 — 一款BLE旋转控制器,可将物理旋钮映射到媒体、会议和系统命令,支持 **macOS** 和 **Android**。
## 概述
提示旋钮是一款Kotlin多平台伴侣应用,适用于提示旋钮硬件(基于ESP32的旋转旋钮)。通过BLE连接,绑定旋转、点击和滑动到实际操作 — 播放/暂停、静音、音量、亮度、shell命令或Google Assistant提示 — 并通过共享的Compose多平台UI管理所有内容。在macOS上,它兼作MCP的有人在环控制表面,并支持钩子。
采用模块化架构构建:完整的构建系统、Koin依赖注入、类型安全导航、完整的UI组件库、新手引导、设置、预设和本地化/主题基础设施。
## 图库
### 硬件
提示旋钮是一款基于ESP32的BLE旋转控制器,带有圆形显示。
<table>
<tr>
<td width="50%"><img src="docs/img/hardware_pairing.jpg" alt="提示旋钮通过蓝牙配对" /></td>
<td width="50%"><img src="docs/img/hardware_radial_menu.jpg" alt="提示旋钮径向宏菜单" /></td>
</tr>
<tr>
<td align="center"><em>通过蓝牙配对</em></td>
<td align="center"><em>设备径向宏菜单</em></td>
</tr>
</table>
### 应用
在Android和macOS上,通过共享的Compose多平台UI管理设备、宏和预设。
<table>
<tr>
<td width="40%"><img src="docs/img/screenshot_android_device.jpg" alt="Android应用 — 设备和活动宏" /></td>
<td width="60%"><img src="docs/img/screenshot_macos_settings.png" alt="macOS应用 — 设置屏幕" /></td>
</tr>
<tr>
<td align="center"><em>Android — 设备和活动宏</em></td>
<td align="center"><em>macOS — 设置和MCP集成</em></td>
</tr>
</table>
## 构建命令
```bash
# 构建Android调试APK
./gradlew :aos-application:assembleDebug
# 运行所有检查
./gradlew check
# 构建iOS调试框架(由Xcode使用)
./gradlew :compose-application:linkDebugFrameworkIosArm64
# 清洁构建
./gradlew clean
```
对于iOS,在Xcode 16+中打开`ios-application/`并从那里运行。
## 技术栈
| 方面 | 库 |
|---|---|
| UI | Compose Multiplatform 1.10.2, Material3 |
| 状态管理 | Orbit MVI 11.0.0 |
| 依赖注入 | Koin 4.1.1 |
| 导航 | AndroidX Navigation 3 |
| 首选项 | multiplatform-settings 1.3.0 |
| 序列化 | kotlinx-serialization 1.6.0 |
| 协程 | kotlinx-coroutines 1.9.0 |
| 构建 | Gradle 9.1.0, Kotlin 2.3.20, JVM 21 |
| Android | minSdk 27, targetSdk 36 |
## 先决条件
- Android Studio Ladybug 或更新版本
- Xcode 16+(用于iOS)
- JDK 21
## 操作指南
| 任务 | 指南 |
|---|---|
| 将此项目用作模板 | [操作指南:用作模板](docs/how-to/use-as-template.md) |
| 在Android上构建和运行 | [操作指南:在Android上运行](docs/how-to/run-android.md) |
| 在iOS上构建和运行 | [操作指南:在iOS上运行](docs/how-to/run-ios.md) |
| 添加功能屏幕 | [开发:添加功能](docs/development/add-feature.md) |
| 添加新模块 | [开发:添加模块](docs/development/add-module.md) |
| 更改主题颜色或字体 | [操作指南:更改主题](docs/how-to/change-theme.md) |
| 添加本地化字符串 | [操作指南:添加本地化](docs/how-to/add-localisation.md) |
## 内置预设
应用随附每个平台的预制预设包。打开应用中的**预设**,点击画廊卡片导入它,命令树会立即同步到设备。
### macOS预设
| 预设 | 命令 | 类型 |
|--------|----------|------|
| **媒体** | 播放/暂停 · 下一曲 · 上一曲 · 音量加 · 音量减 | 系统 |
| **焦点** | 麦克风切换 · 静音 · 锁定屏幕 · 保持唤醒 | 系统 |
| **显示** | 亮度加 · 亮度减 · 任务控制 · 显示桌面 | 系统 |
| **终端** | 打开终端 · 打开VS Code · 说完成 · 截图 | shell + 系统 |
### Android预设
| 预设 | 命令 | 类型 |
|--------|----------|------|
| **通勤** | 导航到家 · 显示工作交通 | 提示(Google Assistant) |
| **音乐** | 在YouTube音乐上播放我喜欢的歌曲 · 播放低保真音乐列表 | 提示 |
| **日常** | 今天我的日历上有什麼? · 关闭灯 | 提示 |
Android预设通过`AssistantPromptExecutor`使用Google Assistant语音命令。需要在无障碍设置中启用**AssistantRobotService**。
> iOS和桌面版不附带内置预设。用户可以创建自己的预设并以JSON格式导出/导入。
---
## 硬件和固件
提示旋钮基于 **ESP32-S3** 微控制器构建。伴侣应用(此仓库)使用YAMK线协议通过BLE与设备通信。设备上运行的固件位于 **单独的仓库**:[github.com/andrew-malitchuk/prompt-knob-firmware](https://github.com/andrew-malitchuk/prompt-knob-firmware)。
### 板卡
参考设备是 **Guition JC3636K518C** (K5旋钮系列)— 一款现成的ESP32-S3旋钮模块,带有圆形触摸显示屏和旋转编码器环,尺寸正好适合提示旋钮。
| 组件 | 详情 |
|-----------|---------|
| MCU | ESP32-S3R8 (Xtensa LX7 双核, 240 MHz) |
| 无线 | Wi-Fi + 蓝牙 5.0 (BLE) |
| 内存 | 512 KB SRAM · **8 MB PSRAM** · 384 KB ROM |
| 存储 | **16 MB 闪存**; NVS分区用于命令树 |
| 显示 | 1.8″ 圆形IPS LCD, 360 × 360, QSPI |
| 输入 | 旋转编码器(顺时针/逆时针)+ 电容触摸 — 映射到旋转、点击、滑动 |
| 输出 | 显示, RGB LED环, 通知反馈 |
| USB | 通过板载USB-to-UART桥接器(闪存 + 串行监视器)的USB-C |
### 在哪里购买
| 来源 | 链接 |
|--------|------|
| 制造商 | [guition.com](https://www.guition.com/) |
| 快速入门指南 | [1.8″ ESP32-S3 旋钮模块 — GUITION](https://www.guition.com/knowledge/quick-start-guide-1-8-inch-esp32s3-knob-module) |
| Surenoo (K5 旋钮系列) | [surenoo.com — JC3636K518C 列表](https://www.surenoo.com/products/23666971) |
| AliExpress | [搜索 "Guition JC3636K518C K5 旋钮"](https://www.aliexpress.com/w/wholesale-Guition-JC3636K518C.html) |
> ⚠️ **订购前请检查确切的型号。** 提示旋钮针对 **JC3636K518C** — 具有 **8 MB PSRAM + 16 MB 闪存** 的变体。 K5系列中的相邻板卡看起来相同但有所不同(例如 **JC3636K718C** 使用不同的触摸/显示控制器和内存布局)。订购错误的SKU将为您提供固件未针对的板卡。
### 使用PlatformIO闪存
```bash
# 安装PlatformIO
pip install platformio
# 克隆固件仓库
git clone https://github.com/andrew-malitchuk/prompt-knob-firmware.git
cd prompt-knob-firmware
# 构建和闪存(自动检测串行端口)
pio run -t upload
# 打开串行监视器
pio device monitor
```
有关完整的闪存说明、驱动程序设置和故障排除,请参阅固件文档:
| 指南 | 链接 |
|-------|------|
| 固件概述 | [docs/firmware/overview.md](docs/firmware/overview.md) |
| 硬件规格 | [docs/firmware/hardware.md](docs/firmware/hardware.md) |
| 开发环境 | [docs/firmware/development.md](docs/firmware/development.md) |
| 闪存 | [docs/firmware/flashing.md](docs/firmware/flashing.md) |
| BLE / YAMK协议 | [docs/development/ble-protocol.md](docs/development/ble-protocol.md) |
---
## Claude Code集成
当macOS伴侣应用运行时,并且连接了提示旋钮设备,它会公开两个本地服务器,共同使旋钮成为Claude Code的 **有人在环控制表面**。
```
Claude Code
├── MCP工具(JSON-RPC/SSE) ──▶ macOS应用 :7474 ──┐
└── 钩子 (HTTP POST) ──▶ macOS应用 :7777 ──┤
│ BLE(YAMK)
▼
提示旋钮(ESP32)
```
### 两个通道,两个角色
| 通道 | 端口 | 方向 | 功能 |
|---------|------|-----------|--------------|
| **MCP服务器** | 7474 | Claude → 旋钮 → Claude | 交互式工具:阻塞并等待物理响应 |
| **钩子服务器** | 7777 | Claude → 旋钮 | 被动叠加层:在设备屏幕上显示Claude的工作状态 |
---
### 钩子服务器 — 活动叠加层
Claude Code钩子在每次工具使用时,将状态字符串POST到`:7777/state`。macOS应用通过BLE转发状态,设备屏幕自动反应:
| 钩子事件 | 发送状态 | 设备屏幕 |
|------------|-----------|---------------|
| `PreToolUse` | `working` | 橙色环 `WORKING...` — Claude正在忙碌 |
| `PostToolUse` | `done` | 绿色环 `DONE ✓` — 自动在1.5秒后dismiss |
| `Notification` | `waiting` | 红色环 `WAITING` — Claude需要您的注意力 |
| `Stop` | `idle` | 叠加层dismiss — 会话结束 |
将以下内容添加到`~/.claude/settings.json`:
```json
{
"hooks": {
"PreToolUse": [{ "hooks": [{ "type": "command", "command": "curl -s -X POST http://127.0.0.1:7777/state -d 'working' 2>/dev/null || true" }] }],
"PostToolUse": [{ "hooks": [{ "type": "command", "command": "curl -s -X POST http://127.0.0.1:7777/state -d 'done' 2>/dev/null || true" }] }],
"Stop": [{ "hooks": [{ "type": "command", "command": "curl -s -X POST http://127.0.0.1:7777/state -d 'idle' 2>/dev/null || true" }] }],
"Notification":[{ "hooks": [{ "type": "command", "command": "curl -s -X POST http://127.0.0.1:7777/state -d 'waiting' 2>/dev/null || true" }] }]
}
}
```
叠加层自动显示和隐藏 — 无需手动导航。
---
### MCP工具 — 交互式控制
项目根目录中的`.mcp.json`注册了MCP服务器。Claude Code自动连接并获得三个工具:
| 工具 | 阻塞 | 目的 |
|------|--------|---------|
| `request_approval` | 是(30秒) | 显示批准/拒绝屏幕。用户点击批准或滑动拒绝。 |
| `request_choice` | 是(30秒) | 显示可滚动列表。用户旋转编码器导航,点击确认。 |
| `notify` | 否 | 具有触觉/LED反馈的即时通知。 |
---
### 用户流程
#### 1. 正常任务 — 仅限钩子
```
您: “重构BleRepository”
Claude开始读取文件
→ PreToolUse → 设备:橙色WORKING...
→ PostToolUse → 设备:绿色DONE ✓ (1.5秒后消失)
→ PreToolUse → 设备:橙色WORKING... (下一个文件)
→ PostToolUse → 设备:绿色DONE ✓
...
Claude完成,写入响应
→ Stop → 叠加层消失,设备返回轮子
```
您处理其他事情。旋钮显示Claude正在做什么,无需触摸键盘。
---
#### 2. 风险操作 — `request_approval`
```
您: “将分支重置为origin/main”
Claude:识别`git reset --hard` → 调用request_approval
→ 设备:SCR_APPROVAL “重置为origin/main?”
→ 您:点击中心圆 → 已批准 → Claude执行
或向右滑动 → 已拒绝 → Claude停止
或等待30秒 → 超时 → Claude停止
```
旋钮物理上控制破坏性操作 — Claude不会在没有响应的情况下继续。
---
#### 3. 模糊请求 — `request_choice`
```
您: “我应该为新屏幕使用哪种方法?”
Claude:2-4个有效选项 → 调用request_choice
→ 设备:可滚动列表 [“ViewModel + State”,“纯粹的可组合”,“取消”]
→ 您:旋转编码器突出显示,点击确认
→ Claude继续选择所选选项
```
---
#### 4. 任务完成 — `notify`
```
Claude完成长时间的构建或测试运行
→ 调用notify(“Build OK”,level =“success”)
→ 设备:简短的绿色通知叠加层 + 触觉脉冲
→ Claude继续
```
当您离开并希望有一个物理信号表明任务已完成时很有用。
---
### 快速入门
1. 构建并运行macOS应用:`./gradlew :compose-application:runReleaseMacosArm64`
2. 连接您的设备:**设备** → 在扫描列表中点击旋钮 → 等待 **已连接**
3. 将上述钩子块添加到`~/.claude/settings.json`
4. 从此目录运行Claude Code — `.mcp.json`自动注册MCP服务器
有关完整的设置演练、工具参考和故障排除,请参阅 [MCP设置](docs/user-guide/mcp-setup.md)。
---
## 许可证
Apache 2.0 许可证
```
版权(c)2026 Andrew Malitchuk
根据Apache许可证版本2.0(“许可证”)授权;
您可能不使用此文件,除非您遵守许可证。
您可以在以下网址获得许可证的副本:
http://www.apache.org/licenses/LICENSE-2.0
除非适用法律要求或书面同意,否则根据许可证分发的软件
以“原样”分发,不附带任何保证或条件,
无论是明确的还是隐含的。
请参阅许可证中关于权限和
许可证下的限制。
```