seanheiney/rodey

GitHub: seanheiney/rodey

通过逆向工程 USB HID 协议,为 RØDECaster Pro II 调音台提供 Python 库、CLI 和 MCP server,实现编程化的设备控制与状态读取。

Stars: 1 | Forks: 0

# rodey *就像为你操作设备的后台助理一样 —— 只不过这次是为了你的 RØDECaster。* 非官方的 Python 库、CLI 和用于 **RØDECaster Pro II** 的 **MCP server**。 通过代码控制调音台 —— 包括静音、路由、通道处理以及全状态 读取 —— 所有这些都通过其 USB HID 接口完成。RØDE 未发布任何主机 API;该协议是通过 观察 RØDE 自家的应用程序和设备自身的通知进行逆向工程得出的, 随后在硬件上进行了验证。参见 [docs/PROTOCOL.md](docs/PROTOCOL.md)。 ## 安装 ``` curl -fsSL https://raw.githubusercontent.com/seanheiney/rodey/main/install.sh | bash ``` macOS 或 Linux。只需粘贴一行命令:它会自动寻找合适的 Python (3.9+),安装 `hidapi`, 设置隔离环境,将 `rodey` 添加到你的 PATH 中,并且(在 Linux 上)安装 用于非 root HID 访问的 udev 规则。可重复运行;直接原地升级。 ``` rodey channels # what's patched to each strip rodey get noiseGateOn # a value across all channels rodey set 0x1c noiseGateOn on # write, then auto-verify ``` ## 功能说明 | 领域 | 状态 | 备注 | |------|--------|-------| | **读取所有设备状态** | ✅ | 139 KB 快照,49 个组,533 个属性,耗时约 1 秒 | | **通道静音** | ✅ | 每个通道条;已为你处理了反极性逻辑 | | **混音总线路由矩阵** | ✅ | 在 13 个总线中的任意一个上静音任意源 —— 这用于实现 mix-minus | | **单通道处理** | ✅ | noise gate、HPF、compressor、de-esser、Aphex、EQ、pan | | **主控通道** | ✅ | Compellor、delay | | **输出 / 监听 / 耳机** | ✅ | 电平和静音 | | **启用 MIDI 控制** | ✅ | 通过 HID 开启调音台文档记载的 MIDI 控制面 | | **已验证的写入** | ✅ | 每次写入都会通过状态转储差异进行确认 | | **MCP server** | ✅ | 从 AI 代理驱动调音台 | ### 我们研究出的内容(协议) 所有这些内容都记录在 [docs/PROTOCOL.md](docs/PROTOCOL.md) 中并编码在库里: - **握手** — 在报告 1 上发送 `'N'` + 在报告 3 上开启会话。没有这一步什么都 无法工作;它还会触发完整的状态转储。 - **数据帧格式** — 一种带长度前缀、以名称寻址的记录,包含五种值类型 (bool、uint32、float64、string),为读取和写入所共用。 - **读取** — 必须在订阅后*立即*排空转储数据;任何停顿都会导致 状态树头部丢失(这耗费了数小时的时间并引发了几个错误的理论)。 - **通道寻址** — `objID = 0x1C + strip`。一个对象就是一整个通道的 处理块。已在 10 个通道条中的 7 个上验证,随后进行了预测并确认。 - **混音总线矩阵** — `objID = 0x4C + 13·source + bus`,以输入源为键,而不是 通道条位置。映射了 106 个对象。 - **两种值约定** — 推子/电位器是 `uint32` 0–127(并发布其自身的 边界);其他所有项均为 `float64` 0–1。 - **反转的静音极性** — `channelOutputMute = False` 意味着*已静音*。库 封装了这一点,因此你永远不必记住它。 ### **无法**实现的功能 记录这些是为了防止任何人再去费力重新推导它们: - **写入推子电平。** 推子是物理部件且**非电动** —— 写入的 值会与滑块位置不一致,因此设备会拒绝它。RØDE 自家的应用程序 也做不到这一点,且 MIDI CC 也无法触及它们。推子是**只读的**;请改为通过 通道处理来调整增益。 - **基于我们的订阅进行实时仪表监测。** 实时仪表仅在 RØDE 的应用程序 驱动调音台时才会进行流式传输;我们的会话开启会产生状态转储,但不包含仪表数据流。仪表*数值*仍然可以从转储中读取。 - **以真实单位表示的 Float 参数。** `noiseGateThreshold = 0.5` 能够可靠地写入和读取, 但 0–1 → dB/Hz/ms 的映射关系未知 —— 这些属性不发布任何 边界。数值是可设置的;但其工程意义尚未解码。 - **无需刷入固件即可使用 SSH。** 调音台运行启用了 SSH 的 Linux 系统,但固件中仅随附了 厂商的*公共*密钥。要获取 shell 需要构建并 刷入自定义固件(变砖风险极高);这不是本工具所做的事情。 ## 安全性 该库拒绝危险的写入,而不是盲目信任调用者: - **固件模式字节。** 报告 1 仅接受 `0x4E` (`'N'`)。`0x4D` (`'M'`) 会进入 固件更新模式,而 `0x55` (`'U'`) 会触发 flash —— 这两者都曾导致设备变砖。 除 `0x4E` 外的任何内容都会被拒绝。(一个流行的第三方项目使用 `0x55` 作为 “ping”进行探测 —— 它并不是。) - **破坏性属性** —— 设备重置、SD 擦除、固件 flash、节目删除 —— 会被 `encode_write` 拒绝。 - **绝不扫描 object ID。** 将未知属性写入猜测的 ID 会永久地将 该属性添加到对象中。ID 是通过观察到的流量收集的,从不进行探测; 我们特意没有提供扫描器。 - **不要靠耳朵来验证写入。** 电容麦克风的本底噪音会漂移数 dB;请改用 状态转储进行验证(库已为你处理了此项)。 ## 库 ``` from rodey import Rodecaster with Rodecaster() as rc: print(rc.strip_sources()) # [0, 1, 10, 7, 8, ...] channelInputSource codes print(rc.muted()) # [False, True, ...] per strip, polarity handled rc.set_muted(3, True) # mute strip 3 rc.set_channel(0, "noiseGateOn", True) # objID resolved from strip index if rc.set_verified(0x1C, "hpfOn", True): # write, confirmed by dump diff print("high-pass on") snap = rc.snapshot() # {GROUP: {property: [per-strip values]}} ``` ## MCP server ``` rodey-mcp ``` ``` { "mcpServers": { "rodey": { "command": "rodey-mcp" } } } ``` 工具:`get_property`、`set_property` (已验证)、`list_properties`、`list_known_objects`、 `watch_changes`。没有任何工具可以触及固件模式通道;也没有 objID 扫描器。 ## 扩展对象映射 `docs/PROTOCOL.md` 解释了捕获程序。`tools/harvest_objids.py` 解析由 RØDE 应用程序发出的写入操作;`tools/capture_board.py` 监听你操作物理 控件的过程。两者纯粹是观察性的 —— 欢迎提交收集到的 ID 贡献。 ## 开发 ``` git clone https://github.com/seanheiney/rodey && cd rodey python3 -m venv .venv && . .venv/bin/activate pip install -e '.[dev]' pytest # 56 tests, no hardware required ``` ## 许可证 MIT
标签:MCP服务器, Python, USB HID, 无后门, 硬件控制, 逆向工具, 音频设备