WebSocket 프로토콜
시뮬레이션 채널은포트 10001에 설정된 WebSocket 연결입니다. 이 채널은 애플리케이션과 서비스 간의 실시간 명령/상태 루프를 처리합니다.
핵심 규칙: 각 메시지에 대해 하나의 응답이 발생합니다.
서비스는 클라이언트에서 전송해 온각 메시지에 대해정확히한 번씩 상태 업데이트를 전송합니다:
폴링, 구독 또는 아웃오브밴드 푸시 기능은 없습니다. 업데이트 주기는 전적으로 사용자의 전송 속도에 따라 결정됩니다.
1단계——초기 목록 (서비스에서 전송한 첫 번째 메시지)
연결 시, 서비스는 감지된 각 기기에 대해 하나씩전체 스냅샷,여기에는 다음이 포함되어 있습니다. config、state 와 status:
{
"session_id": 7,
"inverse3": [
{
"device_id": "049D",
"config": {
"type": "inverse3",
"port": "COM12",
"device_info": { "major_version": 7, "minor_version": 4, "id": "049D", "device_type": 4, "uuid": "…" },
"extended_device_id": "…",
"extended_firmware_version": "…",
"gravity_compensation": { "enabled": true, "scaling_factor": 1.0 },
"handedness": "right",
"streaming_mode": "USB",
"torque_scaling": { "enabled": true },
"home_return": { "enabled": false },
"preset": "defaults",
"basis": { "permutation": "XYZ" },
"mount": { "position": { "x": 0, "y": 0, "z": 0 }, "rotation": { "w": 1, "x": 0, "y": 0, "z": 0 }, "scale": { "x": 1, "y": 1, "z": 1 } },
"filters": {
"force_gate": { "gain": 0.3 },
"damping": { "scalar": 0.0 }
}
},
"state": {
"cursor_position": { "x": 0.0, "y": -0.12, "z": 0.15 },
"cursor_velocity": { "x": 0.0, "y": 0.0, "z": 0.0 },
"angular_position": { "a0": 0.0, "a1": 0.0, "a2": 0.0 },
"angular_velocity": { "a0": 0.0, "a1": 0.0, "a2": 0.0 },
"body_orientation": { "w": 1.0, "x": 0.0, "y": 0.0, "z": 0.0 },
"current_cursor_force": { "x": 0.0, "y": 0.0, "z": 0.0 },
"current_cursor_position": { "x": 0.0, "y": 0.0, "z": 0.0 },
"current_angular_torques": { "a0": 0.0, "a1": 0.0, "a2": 0.0 },
"current_angular_position": { "a0": 0.0, "a1": 0.0, "a2": 0.0 },
"control_domain": "cartesian",
"control_mode": "idle",
"transform": { "position": { "x": 0, "y": 0, "z": 0 }, "rotation": { "w": 1, "x": 0, "y": 0, "z": 0 }, "scale": { "x": 1, "y": 1, "z": 1 } },
"transform_velocity": { "position": { "x": 0, "y": 0, "z": 0 }, "rotation": { "w": 1, "x": 0, "y": 0, "z": 0 }, "scale": { "x": 0, "y": 0, "z": 0 } }
},
"status": {
"calibrated": true,
"in_use": false,
"power_supply": true,
"ready": true,
"started": true
}
}
],
"verse_grip": [],
"wireless_verse_grip": []
}
이 세 데이터 블록의 업데이트 빈도는 각각 다릅니다:
| 데이터 블록 | 포함된 내용 | 변경 빈도 |
|---|---|---|
config | 펌웨어 정보, 프리셋, 베이스, 마운트, 필터 | 거의 없습니다——명시적으로 설정을 수정할 때만 |
state | 위치, 속도, 힘, 자세, 변환 | 각 틱(고주파) |
status | 준비 완료, 보정 완료, 전원, 사용 중 | 가끔 (드물게) |
2단계——첫 번째 명령어 전송
초기 목록을 분석하여 기기 ID를 확인한 다음, 세션 구성, 초기 구성 및/또는 제어 명령이 포함된 메시지를 반환하십시오:
{
"session": {
"configure": {
"profile": { "name": "co.haply.inverse.tutorials:hello-floor" }
}
},
"inverse3": [
{
"device_id": "049D",
"configure": {
"preset": { "preset": "arm_front_centered" }
},
"commands": {
"set_cursor_force": { "vector": { "x": 0.0, "y": 0.0, "z": 0.0 } }
}
}
]
}
3단계——후속 상태 업데이트
첫 번째 상호작용 이후, 구성 변경으로 인해 전체 스냅샷 전송이 트리거되지 않는 한, 서비스는 다음만 전송합니다. state + status(제외) config):
{
"session_id": 7,
"inverse3": [
{
"device_id": "049D",
"state": { "cursor_position": { … }, "cursor_velocity": { … }, … },
"status": { "ready": true, "calibrated": true, … }
}
]
}
4단계 — 반복
명령 전송 → 상태 업데이트 수신. 이 과정은 전송 속도에 따라 반복됩니다.
configure 와 commands
보낸 메시지 내에서 각 기기 항목은 두 개의 매핑을 포함할 수 있습니다:
| 매핑 | 용도 | 지속성 |
|---|---|---|
configure | 일회성 설정: 프리셋, 베이스, 마운트, 필터, 모듈 구성 | 변경될 때까지 유효함 |
commands | 주기별 제어: 힘, 위치, 토크 | 한 번만 적용되며, 그 후에는 효력이 상실됩니다. |
관련 configure 키의 전체 목록은 다음을 참조하십시오. 세션 구성;관련 commands 항목에 대해서는 다음을 참조하십시오. 제어 명령。
set_transform 예외적인 경우입니다set_transform ~에 위치한 commands 아래, 하지만 그것은지속적인——이 서비스는 사용자가 새로운 값을 전송할 때까지 마지막 값을 유지합니다. 이는 장면 이동 기능을 위한 것이기 때문입니다. 즉, 카메라가 이동할 때 변환 값을 스트리밍 방식으로 전송하지만, 두 번의 키 입력 사이에는 마지막 위치를 유지하기를 원하기 때문입니다.
execute 로고
어떤 configure 또는 commands 모든 항목에는 다음이 포함될 수 있습니다 "execute": false,서비스를분석 및 검증부하를 가하되 이를 적용하지는 않는다.
{
"inverse3": [{
"device_id": "049D",
"configure": {
"preset": { "preset": "arm_front", "execute": true },
"damping": { "scalar": 0.0, "execute": false }
}
}]
}
이는반사 기반 직렬화기(예를 들어 Unity의 JsonUtility)매우 유용합니다. 이러한 직렬화기는 항상 모든 필드를 출력합니다: 사용되지 않는 항목을 execute: false,이렇게 하면 실제 설정을 덮어쓰지 않게 됩니다. 기본값은 true——이 표시가 생략된 경우 “정상 적용”을 의미합니다.
경고
probe_position 와 probe_orientation 단순히 모니터링을 위한 연결 유지 메시지이며, 제어 명령을 전송하지 않는 세션(예: Haply Hub)에 적용됩니다. 세션에서 이미 전송을 시작한 경우 set_cursor_force、set_cursor_position 등과 같은 명령어,더 이상 탐지 메시지를 동시에 보내지 마십시오.——장비 상태 정보는 각 응답에 이미 포함되어 있습니다. 두 가지를 동시에 사용하면 대역폭을 낭비할 뿐만 아니라, 다음을 유발할 수도 있습니다. session-probe-dropped 사건.
특정 명령이 아무런 효과가 없는 것처럼 보인다면, 필드명이 잘못되었을 가능성이 높습니다. 현재 이 서비스는 인식할 수 없는 JSON 키를 오류 메시지 없이 무시합니다. 서비스 로그를 확인하고 API 참조 문서를 대조하여 필드명을 확인해 주십시오. 이 동작은 향후 버전에서 변경될 예정입니다.