迁移至 3.5
本页面是 Inverse Service 3.5 的综合升级指南。它
涵盖了该服务中所有尚未移除的弃用功能——即旧版 3.0
计划于 4.0、已弃用的 HTTP 端点,
以及已弃用的会话通道模拟命令——此外还有
一个 新 3.5 版本引入的迁移功能:可选用的 Wireless Verse Grip
输出格式。
出于向后兼容性的考虑,此处列出的所有已弃用功能在实际传输中仍被接受。升级时不会导致任何功能失效——请根据您的实际情况安排迁移。
3.0 vs 3.x API 版本
该服务提供了两种并行的 JSON 格式:旧版 3.0 格式
在端口上 10000 以及当前的 3.x 端口上的格式 10001. 两者均保留
以保持向后兼容性 — 3.0 升级后,集成任务将继续
照常运行。
3.0 将放弃对以下应用程序接口版本的支持 4.0.
-
3.0应用程序接口- 完全记录在
3.0.x文档页面. HTTP关于 http://localhost:10000/3.0/.Websockets在港口10000.
- 完全记录在
-
3.x应用程序接口- 完全记录在
3.x文档页面. HTTP关于 http://localhost:10001/.Websockets在港口10001.- 功能得到增强,并与游戏引擎的集成速度更快。
- 完全记录在
随时升级——现有工作流程不受影响。
已弃用的 HTTP 端点
以下端点仍可使用,但会发出弃用警告。
它们将在 4.0请改用替代路线。
| 已弃用的路径 | 替换 |
|---|---|
POST /force_scale | POST /settings/devices/force_scale |
POST /gravity_compensation | POST /{type}/{id}/config/gravity_compensation |
POST /torque_scaling | POST /{type}/{id}/config/torque_scaling |
POST /device_handedness | POST /{type}/{id}/config/handedness |
POST /serial_enable | POST /settings/system/serial_enable |
POST /experimental/features/grip_dropped_simulation_stopper | POST /settings/features/grip_hook/enabled |
POST /experimental/features/screensaver_enable | POST /settings/features/screensaver/enabled |
每条已弃用的路由都会触发一个 http-route-deprecated
活动频道上的活动,同时包含旧路线及其
替代路线。
已弃用的会话通道命令
以下两个会话级模拟命令已弃用,并将在
未来的重大版本中移除。它们在
网络传输中仍然被接受;新的集成应使用 configure 列在
“替换”列中的条目。
每个已弃用的命令都会触发一个 command-deprecated
活动频道上的活动。
session.set_coordinate_origin → inverse3[*].configure.preset
// Old — deprecated
{ "session": { "set_coordinate_origin": { "coordinate_origin": "workspace_center" } } }
// New — canonical
{ "inverse3": [ { "device_id": "…", "configure": { "preset": { "preset": "arm_front_centered" } } } ] }
值映射:
旧的 coordinate_origin | 新预设 |
|---|---|
device_base | arm_front (或 defaults) |
workspace_center | arm_front_centered |
预设是通过以下方式按设备应用的: inverse3[*].configure.preset (或
configure.preset (关于Verse Grip / 无线Verse Grip设备的条目),
而非作为全局开关。请参阅 配置部分
请参阅模拟参考文档以获取预设名称的完整列表。
session.set_basis → session.configure.basis
// Old — deprecated
{ "session": { "set_basis": { "basis": { "permutation": "X-ZY" } } } }
// New — canonical
{ "session": { "configure": { "basis": { "permutation": "XZ-Y" } } } }
这两个命令对坐标轴符号的解释有所不同。一种
置换,它在
下产生了正确的映射 session.set_basis
可以产生一个 逆变换 在……之下
session.configure.basis — 在迁移过程中,您可能需要对一个或
多个坐标轴的符号进行取反。
示例:一个运行正常的会话,其中 session.set_basis +
"permutation": "X-ZY" 通常需要 "permutation": "XZ-Y" 在……之下
session.configure.basis. 在发布迁移脚本之前,请务必重新验证生成的转换结果。
Wireless Verse Grip 输出形状(3.5,需启用)
服务版本 3.5 在 v3.1 模拟通道的 完整快照帧和流式帧中,为 Wireless Verse Grip 设备(包括 Ruko 和 Kingfisher 定制版本)新增了一个可选的 JSON 格式。
3.5 随附 serialization/wireless_verse_grip/legacy_mode = true 默认. 现有 3.5 版本之前的客户端无需更改配置或
修改代码即可继续正常运行——您可以在不触及
集成代码的情况下升级服务。
仅在以下情况下进行迁移: 想要 新造型:更简洁
config.type / config.sub_type 拆分并明确控制是否
在整个 wireless_verse_grip 和
custom_verse_grip 数组。如需订阅,请设置
serialization/wireless_verse_grip/legacy_mode = false 并按照本节
的其余内容操作。
这一变化是 线上的添加剂 — v3.1 有效载荷版本
保持不变 — 且完全由以下四个运行时设置控制:
serialization/wireless_verse_grip/. 希望使用 3.5 版本之前波形形状的
用户将自动获得该波形;选择使用新波形形状的用户可以调整三个
额外参数来塑造输出效果。
哪些人可能想要迁移
任何解析该 wireless_verse_grip 或 custom_verse_grip v3.1 有效载荷中的数组
可能受益于新的 shape:
- 通过以下方式读取 WVG 条目的 Unity 插件集成
JsonUtility - 使用 WebSocket 流的TouchDesigner集成
- Python / C++ 示例代码已按主题分类
config.type(例如:"ruko"/"kingfisher")
仅进行解析的客户端 inverse3 或 verse_grip 数组是 不受
影响 无论设置如何。
选择加入
翻转 legacy_mode 至 false 要启用新形状。有两种方法:
- HTTP(运行时)
- 配置文件(持久化)
curl -X POST http://127.0.0.1:10001/settings/serialization/wireless_verse_grip/legacy_mode \
-H 'Content-Type: application/json' \
-d 'false'
该服务会立即重新发送完整的快照,因此正在接收数据流的客户端将在 下一帧看到新的形状。
将密钥添加到 haply-inverse-service-config.json:
{
"serialization/wireless_verse_grip/legacy_mode": false
}
配置文件的位置(其中之一):
| 平台 | 路径 |
|---|---|
| Windows | C:\ProgramData\Haply\Inverse\haply-inverse-service-config.json |
| macOS | /Library/Application Support/Haply/Inverse/haply-inverse-service-config.json |
| Linux | /etc/haply-inverse-service/haply-inverse-service-config.json |
请重启该服务(或Haply ),以便更改生效。
一次 legacy_mode = false,其余旋钮(explicit_custom,
extended_data/raw_data, extended_data/custom_fields) 生效。参见
旋钮矩阵 如下。
新造型长什么样
当您选择加入时(legacy_mode = false),有效载荷将先前处于纠缠状态的轴
展开:
config.type是父系家族,每条记录 —"wireless_verse_grip"对于触控笔行,"custom_verse_grip"用于 自定义行(Ruko、Kingfisher、prototype)。config.sub_type是一个新兴领域 (仅限选择加入类型)具有 物理硬件子类型——"stylus","prototype","ruko"或"kingfisher". 它将wireless_verse_grip::subtypeenum 直接,有别于config.type的device_typeenum。此前 触控笔和原型均被序列化为"wireless_verse_grip"; 每个 现在都有自己的值。兼容模式会 不 发射sub_type.- 自定义握把分享
wireless_verse_grip[]默认情况下 当您选择 加入时——笔阵中也会包含自定义变体。独立的custom_verse_grip只有在翻转时才会发出数组explicit_custom = true在这种情况下,该 数组将仅限自定义(触控笔永远不会出现在那里)。 - 自定义握把有效载荷仍以原始扩展字节的形式保留。
extended_data/raw_data(默认true) 保留原始state.extension_data: [...]自定义握把条目中的字节数组 — 与旧版形状匹配。客户端应在自身代码中将这些 字节转换为特定子类型的字段(Ruko 滚轮/触发器、Kingfisher 按钮等);一个专用的高级标志extended_data/custom_fields可以在服务内部输出预翻译字段,但这是 不 这是推荐迁移路径的一部分——在启用该控件之前,请参阅相关说明。
传统(默认)与主动选择示例
假设有一支触控笔(1615) 和一个 Ruko (1419) 已连接。
- 传统版(3.5版默认)
- 选择加入(legacy_mode = false,默认设置)
{
"wireless_verse_grip": [
{
"device_id": "1615",
"config": { "type": "wireless_verse_grip", "…": "…" },
"state": {
"buttons": { "a": false, "b": false, "c": false },
"hall": 16,
"orientation": { "x": 0, "y": 0, "z": 0, "w": 1 }
}
},
{
"device_id": "1419",
"config": { "type": "ruko", "…": "…" },
"state": {
"buttons": { "up": false, "down": false, "left": false, "right": false },
"trigger": 7,
"wheel": 4,
"hall": 16,
"orientation": { "x": 0, "y": 0, "z": 0, "w": 1 }
}
}
],
"custom_verse_grip": [
{
"device_id": "1419",
"config": { "type": "custom_verse_grip", "…": "…" },
"state": {
"buttons": { "a": false, "b": false, "c": false },
"hall": 16,
"orientation": { "x": 0, "y": 0, "z": 0, "w": 1 },
"extension_data": [0, 6, 1, 183, 5, 6, 7, 8, 9, 10, 11, 12]
}
}
]
}
{
"wireless_verse_grip": [
{
"device_id": "1615",
"config": { "type": "wireless_verse_grip", "sub_type": "stylus", "…": "…" },
"state": {
"buttons": { "a": false, "b": false, "c": false },
"hall": 16,
"orientation": { "x": 0, "y": 0, "z": 0, "w": 1 }
}
},
{
"device_id": "1419",
"config": { "type": "custom_verse_grip", "sub_type": "ruko", "…": "…" },
"state": {
"buttons": { "a": false, "b": false, "c": false },
"hall": 16,
"orientation": { "x": 0, "y": 0, "z": 0, "w": 1 },
"extension_data": [0, 6, 1, 183, 5, 6, 7, 8, 9, 10, 11, 12]
}
}
]
}
在此示例中,其余三个旋钮均保持默认设置
(explicit_custom = false, raw_data = true, custom_fields = false),
因此海关负责 wireless_verse_grip 数组,独立的
custom_verse_grip 数组不会被输出,而 ruko 条目包含
原始数据 extension_data 供客户端本地翻译的字节数组。
选择加入时的关键区别:
| 方面 | 传统版(3.5版默认) | 选择加入 (legacy_mode = false) |
|---|---|---|
config.type 用于“下”下的自定义行 wireless_verse_grip | 子类型名称(例如 "ruko") | 父母家庭 "custom_verse_grip" |
config.sub_type | 缺席 | 当前 — "stylus" / "prototype" / "ruko" / "kingfisher" |
custom_verse_grip 数组已发出 | 始终(当连接了自定义握把时) | 只有当……时 explicit_custom = true |
| 自定义握把状态模式 | 原始 extension_data 字节 + a/b/c 按钮 | 相同的原始数据 extension_data 默认以字节为单位; raw_data 可以禁用,并且 custom_fields 这是一个高级订阅选项——详见下文 |
触控笔位于 custom_verse_grip | 从不 | 从不 |
调整您的解析器
一旦您选择加入,请 config.sub_type 作为 硬件标识 和
config.type 作为 家庭桶. 此前基于
config.type == "ruko" 应以……为依据 config.sub_type == "ruko":
- const isRuko = entry.config.type === "ruko";
+ const isRuko = entry.config.sub_type === "ruko";
对于需要在同一二进制文件中同时支持 3.5 版本之前的 Service 版本(或仍处于旧版模式的 3.5 Service)以及处于选择加入模式的 3.5 Service 的解析器,请勾选以下任一选项:
const subtype = entry.config.sub_type ?? entry.config.type;
const isRuko = subtype === "ruko";
任何此前依赖于 翻译 子类型字段
位于 Ruko 或 Kingfisher 条目中(buttons.{up,down,left,right},
trigger, wheel, buttons.{a..f}, …) 现在应将原始数据
state.extension_data[] 字节方面。该服务将
传统的在线翻译功能保留在
extended_data/custom_fields 标志,
但该标志仅面向非常特定的内部客户端,
且计划在未来版本中将在线翻译功能完全移出该服务——
请从一开始就在客户端构建字节解码器,
以避免日后再次进行迁移。
继续使用旧系统(无需采取任何行动)
3.5 版的默认设置是兼容模式。如果您的客户端已冻结且无法 更新,或者您暂时不需要新格式,请无需进行任何操作——升级至 3.5 版不会改变您的有效载荷。
legacy_mode = true 这是 3.5 版本的默认设置,旨在为Haply 内部Haply
(包括 Hub)以及第一方集成提供迁移时间。这是
未被废弃 今天,但默认设置计划恢复为
false 将在未来的次要版本中进行调整,且该设置本身预计将在
4.0 主要版本发布之前被移除。请在方便时进行迁移——不要
等到最后期限才行动。
完整的旋钮矩阵
这四个旋钮都位于 serialization/wireless_verse_grip/ 并且可以通过设置 HTTP API
在运行时进行切换。
旋钮: legacy_mode
- 类型:
bool - 默认:
true(3.5 版默认开启兼容模式)
当 true, 有效载荷与 3.5 版本之前的格式完全一致(字节对字节),而
其他控制项则不再起作用。当 false,此时新形状已生效,
下方的三个旋钮也开始起作用。参见 选择加入.
旋钮: explicit_custom
- 类型:
bool - 默认:
false - 需要
legacy_mode = false才能产生效果。
控制自定义握把是否拥有自己的专用数组。
false(默认) — 海关份额wireless_verse_grip[]数组 与触控笔输入并列;无需单独custom_verse_grip数组被 输出。true— 报关单也会通过一个专门的custom_verse_grip[]数组(并继续出现在wireless_verse_grip[](也是)。
上一页 merged_in_wireless 将此设置为反转:默认设置为
true (海关信息已复制到 wireless_verse_grip) 并必须设置为
false 以实现清晰的分离。新的命名方式是积极的—— explicit_custom = true 可理解为“在各自的数组下显式发出自定义信号”——并且
默认行为已被反转,因此开箱即用的“主动加入”模式会生成一个
统一的 wireless_verse_grip[] 数组,从而降低了每次时钟周期序列化的开销。
旋钮: extended_data/raw_data
- 类型:
bool - 默认:
true - 需要
legacy_mode = false才能产生效果。
当 true (默认),自定义握把条目包含原始
state.extension_data: [...] 字节数组 — 适用于
基于反射的反序列化器(如 Unity 的)的稳定结构 JsonUtility 以及对于
通过扩展通道传输自定义二进制协议的客户端。当 false,
字节数组被省略。与 custom_fields; 请参见
下表中的四种组合。
在普通触控笔子类型上不执行任何操作(无扩展通道)。
旋钮: extended_data/custom_fields
- 类型:
bool - 默认:
false - 需要
legacy_mode = false才能产生效果。
custom_fields 该功能仅保留给少数特定的内部客户,他们
仍然依赖该服务将原始扩展字节转换为
特定子类型的字段。计划将服务内的转换功能迁移至 退役 在未来的版本中,因此新的集成应 不
启用此标志。保持 custom_fields = false (默认)并在客户端进行
字节到字段的转换。
当 true, 自定义握把条目将获得针对各子类型的转换后模式 —
buttons.{up,down,left,right} + trigger + wheel 致Ruko;
buttons.{a..f} + trigger 为翠鸟。当 false (默认),
仅通用 buttons.{a,b,c} 存在且具有亚型特异性的状态
必须从中解码 state.extension_data[]. 独立于
raw_data.
在普通 stylus 子类型和原型子类型上不执行任何操作——该
原型没有转换后的模式,因此总是回退到
extension_data 字节(如果 raw_data = true) 或简体 a/b/c 按钮
仅限(如果 raw_data = false).
组合矩阵(主动加入模式)
使用 legacy_mode = false:
explicit_custom | raw_data | custom_fields | wireless_verse_grip[] 包含 | custom_verse_grip[] 包含 |
|---|---|---|---|---|
false (默认) | true (默认) | false (默认) | 笔尖(普通)+ 自定义(原始字节) | (不显示) |
false | false | true | 触控笔(简体)+ 海关(翻译) | (不显示) |
false | true | true | stylus(原版)+ 自定义(原始字节 + 已翻译) | (不显示) |
true | true | false | 笔尖(普通)+ 自定义(原始字节) | 自定义(原始字节) |
true | false | true | 触控笔(简体)+ 海关(翻译) | 海关(译文) |
true | true | true | 手写笔(简体)+ 自定义(原始 + 已翻译) | 海关(原文 + 译文) |
(包含 raw_data = false 和 custom_fields = false 是允许的,但
仅输出通用版本 a/b/c 按钮——通常没什么用。)
原型子类型
在路由方面,原型自定义握把子类型被视为自定义类型——它出现在 wireless_verse_grip[],以及在
custom_verse_grip[] 当……时 explicit_custom = true. 因为没有
原型的翻译模式, custom_fields 对原型条目而言是无操作的;
它们的状态完全来自 extension_data 字节(当
raw_data = true) 或者完全不(当 raw_data = false).
在“主动加入”模式下,原型条目会报告 config.sub_type = "prototype" —
一个与……不同的专用枚举值 "stylus". 在 3.4 中,这两个子类型
被序列化为 "wireless_verse_grip"; 3.5 选择加入模式为每个元素赋予独立的
值。传统模式不发出 sub_type 一点也不。
参考资料
- 设置参考 — 这四位
serialization/wireless_verse_grip/*钥匙 - WebSocket 协议— 完整快照 以及流式帧布局。
- AsyncAPI 参考文档— 适用于所有 v3.1 有效载荷的 机器可读模式。
- HTTP API 参考文档— Swagger UI,用于查看 当前的 HTTP 路由及其对上述已弃用端点的替代方案 。