Zum Haupttext springen

WebSocket-Protokoll

Der Simulationskanal ist eine WebSocket-Verbindung über Port 10001. Dieser Kanal überträgt die Echtzeit-Befehls- und Status-Schleife zwischen der Anwendung und dem Dienst.

Grundregel: Eine Antwort pro Nachricht​

Der Dienst sendet für jedevom Client empfangene Nachricht genau eine Statusaktualisierung:

Es gibt weder Polling noch Abonnements noch Push-Benachrichtigungen außerhalb des Bandbreitenbereichs. Der Aktualisierungsrhythmus hängt ausschließlich von der Übertragungshäufigkeit des Clients ab.


Schritt 1 – Erstinventar (die erste Nachricht des Dienstes)​

Sobald die Verbindung hergestellt ist, führt der Dienst für alle erkannten Geräte folgende Schritte durch: config, state, statuseinschließlich Gesamtübersichtübermittelt:

{
"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 werden in unterschiedlichen Abständen aktualisiert:

BlockLieferumfangÄnderungshäufigkeit
configFirmware-Informationen, Voreinstellungen, Basis, Halterung, FilterSelten – nur bei expliziten Konfigurationsänderungen
statePosition, Geschwindigkeit, Kraft, Richtung, UmrechnungMatik (Hochfrequenz)
statusBereit, kalibriert, Stromversorgung, in Betriebgelegentlich (selten)

Schritt 2 – Übertragung des ersten Befehls​

Analysieren Sie den Anfangsbestand, um die Geräte-ID zu ermitteln, und senden Sie anschließend eine Nachricht mit dem Sitzungsprofil, der Anfangskonfiguration und/oder Steuerbefehlen 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 Statusaktualisierung​

Nach dem ersten Austausch wird der Dienst, sofern keine vollständige Snapshot-Übertragung aufgrund von Konfigurationsänderungen erfolgt, state + statusEs werden nur (config (Ausgenommen):

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

Schritt 4 – Wiederholung​

Befehlsübertragung → Empfang einer Statusaktualisierung. Der Zyklus wird entsprechend der Übertragungsgeschwindigkeit fortgesetzt.


configureWow commandsDer Unterschied​

Jeder Geräteeintrag in der gesendeten Nachricht kann die folgenden beiden Zuordnungen enthalten:

KarteVerwendungszweckBeständigkeit
configureEinmalige Einstellungen: Voreinstellungen, Basis, Halterung, Filter, ModuleinstellungenBis zur Änderung beibehalten
commandsSteuerung in Tick-Schritten: Kraft, Position, DrehmomenteNach einmaliger Anwendung entsorgen

configure Die vollständige Liste der Schlüssel finden Sie unter Aufbau der Sitzung을, commands Die Punkte sind SteuerbefehlSiehe dazu.

Anmerkung
set_transformDas ist ein Ausnahmefall.

set_transform은 commands Es befindet sich zwar unten, ist aber **persistent**. Der Dienst behält den letzten Wert bei, bis ein neuer Wert gesendet wird. Dies dient der Szenenerkundung, bei der die Kamera sich bewegt und gleichzeitig die Transformationswerte streamt, während die letzte Position zwischen den Eingaben beibehalten werden soll.


execute Flagge​

configure oder commands unter dem Punkt "execute": falseWenn man dies einbezieht, wendet der Dienst die Nutzlast nicht an und Nur Syntaxanalyse und Validierung Wir führen dies durch.

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

Dies bedeutet, dass stets alle Felder ausgegeben werden. Reflexionsbasierter Serializer(Beispiel: In Unity JsonUtility) nützlich. Nicht verwendete Elemente sind execute: falseStellen Sie dies so ein, dass die tatsächliche Konfiguration nicht überschrieben wird. Der Standardwert lautet trueWenn das Flag weggelassen wird, wird es „normal angewendet“.


Warnung​

Wenn Sie bereits einen Befehl senden, senden Sie bitte keine Sonde.

probe_positionund probe_orientationEs handelt sich um eine reine Überwachungs-Keepalive-Nachricht für Sitzungen, die keine Steuerbefehle senden (z. B. „ Haply Hub“). Wenn die Sitzung bereits set_cursor_force, set_cursor_position wenn man den Rücken zukehrt Bitte senden Sie die Sonde nicht mit.. Der Gerätestatus ist bereits in allen Antworten enthalten. Wenn man beides zusammen verwendet, wird Bandbreite verschwendet und session-probe-dropped Es kann zu einem Ereignis kommen.

Unbekannte Schlüssel werden ohne Fehler ignoriert.

Wenn der Befehl scheinbar keine Wirkung zeigt, ist der Feldname höchstwahrscheinlich falsch. Der Dienst ignoriert derzeit nicht erkannte JSON-Schlüssel, ohne einen Fehler auszugeben. Überprüfen Sie das Dienstprotokoll und vergewissern Sie sich anhand der API-Referenz, dass der Feldname korrekt ist. Dieses Verhalten wird sich in zukünftigen Versionen ändern.