웹소켓 프로토콜
시뮬레이션 채널은 포트 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 vs 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 )에 대한
모니터링 전용 키프얼라이브입니다. 세션에서 이미
전송하고 있다면 set_cursor_force, set_cursor_position등, 또한
탐사선을 보내지 마세요 — 장치 상태는 이미 모든 응답에 포함되어 있습니다. 두 가지를 혼합하면
대역폭을 낭비할 뿐만 아니라 session-probe-dropped 행사.
명령어가 아무런 효과가 없는 것처럼 보인다면, 필드 이름이 잘못된 것일 수 있습니다. 현재 이 서비스는 인식되지 않는 JSON 키를 오류 메시지 없이 무시합니다. 서비스 로그를 확인하고API 참조 문서를 바탕으로 필드 이름을 다시 확인해 주십시오. 이 동작은 향후 버전에서 변경될 예정입니다.