Skip to main content
Version: 3.5.x

Haply Inverse SDK

The Haply Inverse SDK is a language-agnostic WebSocket + HTTP interface to Haply haptic devices — the Inverse3, Inverse3x, Minverse, VerseGrip, and Wireless VerseGrip. It runs as a local service that handles device discovery, serial communication, safety monitoring, and state streaming — so your application only has to speak JSON over a socket.

Its functionalities include:

  • Device discovery and management — lists and configures connected Haply devices automatically over an HTTP REST API.
  • Real-time state streaming — delivers device state at haptic control rates (multi-kHz) over WebSockets.
  • Command processing — executes force and position commands with high fidelity for precise haptic feedback.
  • Background operation — runs as a local service, keeping devices ready without user intervention.

Install with the Haply Hub

The easiest way to get started is the Haply Hub — a desktop application to install, run, configure, test, and monitor your Haply devices. It keeps firmware up to date, bundles the Inverse Service, and ships demos so you can verify your hardware before writing a line of code.

Haply Hub

Haply Hub

Download the latest version of the Haply Hub

Download and install the Hub, plug in your device, and the Hub will guide you through any firmware updates. Once installed, the Inverse Service runs automatically in the background whenever the Hub is open.

Prefer a standalone install?

You can also install a specific version of the Inverse Service as a system service (Windows) or daemon (Linux / macOS) without the Hub. See Running the service for the installer link and instructions.

Quick Example

Connect to the service, read the cursor position of the first Inverse3, and send a zero-force keepalive so the service keeps streaming state frames:

import asyncio, json, websockets

async def main():
async with websockets.connect("ws://localhost:10001") as ws:
# Handshake: register profile and send a zero-force keepalive
first_state = json.loads(await ws.recv())
device_id = first_state["inverse3"][0]["device_id"]
keepalive = {"inverse3": [{
"device_id": device_id,
"commands": {"set_cursor_force": {"vector": {"x": 0, "y": 0, "z": 0}}}
}]}
while True:
state = json.loads(await ws.recv())
pos = state["inverse3"][0]["state"]["cursor_position"]
print(f"pos: {pos}")
await ws.send(json.dumps(keepalive))

asyncio.run(main())
warning

Change the force values with caution. Sudden high force values can damage the device or cause unexpected behaviour.

info

See the JSON Conventions page for the message envelope, ports, and content-type rules.

More examples

For fully-featured tutorials in Python, C++ (nlohmann), and C++ (Glaze) — covering force feedback, position control, multi-device setups, mount/basis configuration, and event streaming — see the Tutorials page.