Zum Hauptinhalt springen

WebSocket-Protokoll

Der Simulationskanal ist eine WebSocket-Verbindung auf Port 10001. Er überträgt die Steuerungs- und Statusschleife in Echtzeit zwischen Ihrer Anwendung und dem Dienst.

Grundregel: Eine Antwort pro Nachricht​

Der Dienst sendet genau eine Statusaktualisierung für jede Nachricht, die er von Ihrem Client erhält:

Es gibt weder eine Abfrage (Polling) noch ein Abonnement noch einen spontanen Versand außerhalb des Kanals. Die Frequenz wird vollständig durch Ihre Sendehäufigkeit bestimmt.


Schritt 1 – Erstaufnahme (erste Nachricht des Dienstes)​

Bei der Verbindung sendet der Dienst eine vollständige Momentaufnahme Behälter config, state et status für jedes erkannte Gerät:

{
"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": []
}

Die drei Blöcke haben unterschiedliche Aktualisierungsraten:

BlockInhaltÄnderungen
configInformationen zu Firmware, Voreinstellungen, Basis, Halterung, FilternSelten – nur bei einer expliziten Konfigurationsänderung
statePosition, Geschwindigkeit, Kraft, Ausrichtung, TransformationenBei jedem Zyklus (hohe Frequenz)
statusBereit, kalibriert, Stromversorgung, in GebrauchGelegentlich (selten)

Schritt 2 – Senden Sie Ihre erste Bestellung ab​

Analysieren Sie den Anfangszustand, um die ID Ihres Geräts zu ermitteln, und senden Sie anschließend eine Nachricht mit Ihrem Sitzungsprofil, allen Anfangskonfigurationen und/oder einem Steuerbefehl zurück:

{
"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 } }
}
}
]
}

Schritt 3 – Nachfolgende Statusaktualisierungen​

Nach dem ersten Austausch sendet der Dienst nur noch state + status (ohne config), es sei denn, eine Konfigurationsänderung löst die Übertragung eines vollständigen Snapshots aus:

{
"session_id": 7,
"inverse3": [
{
"device_id": "049D",
"state": { "cursor_position": { … }, "cursor_velocity": { … }, … },
"status": { "ready": true, "calibrated": true, … }
}
]
}

Schritt 4 – Wiederholen Sie den Vorgang​

Senden Sie einen Befehl → erhalten Sie eine Statusaktualisierung. Dieser Kreislauf wiederholt sich in dem von Ihnen festgelegten Sendeintervall.


configure ou commands​

Jeder Geräteeintrag in Ihrer ausgehenden Nachricht kann zwei Wörterbücher enthalten:

WörterbuchRolleBeharrlichkeit
configureEinzelne Einstellungen: Voreinstellung, Basis, Halterung, Filter, ModulkonfigurationWerden bis zur Änderung gespeichert
commandsPrüfung bei jedem Zyklus: Kraft, Position, DrehmomenteEinmal angebracht, dann vergessen

Siehe Sitzungskonfiguration für die vollständige Liste der Schlüssel von configure, und Steuerbefehle für die Vorspeisen von commands.

Anmerkung
set_transform bildet eine Ausnahme

set_transform befindet sich unter commands, aber sie ist dauerhaft — Der Dienst behält den letzten Wert bei, bis ein neuer gesendet wird. Dies liegt daran, dass seine Funktion die Navigation innerhalb der Szene ist: Sie übermitteln die Transformationen kontinuierlich während der Kamerabewegungen, möchten aber, dass die letzte Position zwischen zwei Tastendrücken beibehalten wird.


Der Indikator execute​

Jeder Eintrag configure ou commands kann umfassen "execute": false damit der Dienst analysieren und validieren die Nutzlast, ohne sie anzuwenden.

{
"inverse3": [{
"device_id": "049D",
"configure": {
"preset": { "preset": "arm_front", "execute": true },
"damping": { "scalar": 0.0, "execute": false }
}
}]
}

Das ist nützlich für die Reflexionsbasierte Serialisierer (zum Beispiel, JsonUtility (de Unity) die immer alle Felder ausgeben: Legen Sie die nicht verwendeten Eingaben auf execute: false damit sie die tatsächliche Konfiguration nicht überschreiben. Der Standardwert ist true — Wird der Indikator weggelassen, bedeutet dies „normal anwenden“.


Warnhinweise​

Senden Sie keine Abfragen, wenn Sie bereits Befehle übertragen.

probe_position et probe_orientation sind Keepalive-Nachrichten, die ausschließlich der Überwachung dienen, und zwar für Sitzungen, die keine Steuerbefehle senden (z. B. „ Haply Hub“). Wenn Ihre Sitzung bereits set_cursor_force, set_cursor_positionusw., Schickt bitte auch keine Sonden — Der Gerätestatus ist bereits in jeder Antwort enthalten. Beides zu kombinieren verschwendet Bandbreite und kann Ereignisse auslösen. session-probe-dropped.

Unbekannte Schlüssel werden stillschweigend ignoriert.

Wenn ein Befehl keine Wirkung zu zeigen scheint, ist der Feldname wahrscheinlich falsch. Der Dienst ignoriert derzeit nicht erkannte JSON-Schlüssel, ohne einen Fehler auszugeben. Sehen Sie sich die Protokolle des Dienstes an und überprüfen Sie die Feldnamen in der API-Referenz. Dieses Verhalten wird sich in einer kommenden Version ändern.