Skip to main content

Python SDK for driving Hapbeat haptic devices over Wi-Fi UDP

Project description

Hapbeat Python SDK

Drive Hapbeat haptic devices from Python over Wi-Fi UDP. For researchers (PsychoPy / Jupyter / ROS), media artists, and anyone prototyping haptics in Python.

📚 Docs: https://devtools.hapbeat.com/docs/sdk-integration/

A script can drive Hapbeat with a few lines. The fire side (play / stop) and the tuning side (EventMap) are kept orthogonal and linked only by event id.

Install

pip install hapbeat-python-sdk        # core (zero dependencies, stdlib socket only)
pip install "hapbeat-python-sdk[osc]"   # + generic OSC bridge (TouchOSC / Max / TD)

With pipx you get the hapbeat CLI (including the launchpad below) in an isolated environment: pipx install hapbeat-python-sdk. Note that pipx does not make import hapbeat available to your own scripts — for the examples/ use a normal pip install in a venv.

Try everything from one page (launchpad)

hapbeat launchpad          # opens http://127.0.0.1:7100 in your browser

A single local web page to fire events, run a metronome, a breathing pacer, or send Morse — start and stop them live, no per-example launching. It serves a tiny stdlib HTTP server that relays button presses to the device over UDP (browsers can't send UDP directly). Works great with pipx install hapbeat-python-sdk.

Quick start

import hapbeat

hb = hapbeat.connect(app_name="MyExperiment")  # opens UDP broadcast + keep-alive
hb.play("impact.hit", gain=0.3)   # fire event "impact.hit" at gain 0.3
hb.play("impact.hit")             # gain omitted -> kit baseline intensity
hb.stop("impact.hit")
hb.stop_all()
hb.close()

or as a context manager:

with hapbeat.connect(app_name="MyExperiment") as hb:
    hb.play("impact.hit")

"impact.hit" must be an event id present in the kit deployed to the device (via Hapbeat Studio). The SDK sends the instruction; the waveform lives in the kit on the device.

Discovery

for dev in hb.discover(timeout=1.5):
    print(dev.ip, dev.address, dev.firmware_version)

EventMap — the tuning side (optional)

Keep per-event default gains in one place and let play("id") resolve them, so firing code never hard-codes intensities:

em = hapbeat.EventMap.from_manifest("my-kit/my-kit-manifest.json")
hb = hapbeat.connect(event_map=em)
hb.play("impact.hit")        # uses the kit manifest's intensity for this event

EventMap reads the kit manifest (schema 2.0.0) intensity as the baseline gain. You can also build one by hand: EventMap.from_dict({"impact.hit": 0.5}).

Haptic file — add targeting on top of the kit

The Studio-generated manifest holds kit content (intensity / clip), but not app-side concerns like which device/body part an event goes to. Put those in a haptic file (an EventMap overlay that references the kit), so play(id) resolves the target without the caller passing it:

// haptics.json
{
  "kit": "kits/my-kit",
  "events": {
    "impact.hit": { "target": "player_1/chest", "gain": 0.8 },
    "rain.loop":  { "target": "*/back" }
  }
}
hb = hapbeat.connect(app_name="MyApp", haptics="haptics.json")
hb.play("impact.hit")     # goes to player_1/chest at gain 0.8 — from the file

Two playback modes: command and clip

The same play(id) call branches on the manifest:

Manifest bucket Mode What happens
events command the SDK sends a PLAY; the device plays its installed clip
stream_events clip the SDK reads the WAV from the kit's stream-clips/ and streams it over UDP

Put the kit inside your project and call events by id — the per-event details (intensity, loop, command vs clip, which WAV) live in the kit, not your code:

my-app/
  app.py
  kits/my-kit/
    my-kit-manifest.json     # the "haptic file" -> EventMap
    install-clips/           # command clips (flashed to the device via Studio)
    stream-clips/*.wav       # clip-mode WAVs the SDK streams
import hapbeat
hb = hapbeat.connect(app_name="MyApp", kit="kits/my-kit")
hb.play("impact.hit")     # command -> device plays its installed clip
hb.play("rain.loop")      # clip    -> SDK streams stream-clips/<wav> over UDP
hb.stop("rain.loop")      # ends the active stream

You can also stream an ad-hoc PCM16 buffer (e.g. a synthesized stereo cue where L/R amplitude conveys direction):

hb.stream_pcm(pcm_bytes, sample_rate=16000, channels=2)

Author clips as 16 kHz mono PCM16 (the device plays at 16 kHz; the SDK does not resample). A full runnable example is in examples/clip_project/.

Generic OSC bridge

Any OSC tool (TouchOSC, Max/MSP, TouchDesigner, a DAW) can drive Hapbeat without code. Run the bridge and send /hapbeat/play <event_id> [target] [time] [gain]:

hapbeat osc-bridge --listen 7702

See docs/osc.md for the address spec.

CLI

hapbeat scan                       # list devices on the LAN
hapbeat play impact.hit --gain 0.3
hapbeat stop-all
hapbeat launchpad                  # browser UI for all of the above

Examples

Ready-to-run sample applications live in examples/: a psychophysics experiment, a breathing pacer, a haptic metronome, a live trigger pad, a task-completion notifier, and a Morse transmitter. Each is a single stdlib-only file — see examples/README.md.

For AI coding agents

Working with Claude / Cursor / Copilot? Hand your agent AGENTS.md — a single self-contained file with the SDK's model, API, project layout, and pitfalls. One file is enough to get the whole picture.

Use the Hapbeat Python SDK. Read AGENTS.md and follow its API and best practices.

License

MIT © Hapbeat

Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

hapbeat_python_sdk-0.1.0.tar.gz (42.3 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

hapbeat_python_sdk-0.1.0-py3-none-any.whl (33.8 kB view details)

Uploaded Python 3

File details

Details for the file hapbeat_python_sdk-0.1.0.tar.gz.

File metadata

  • Download URL: hapbeat_python_sdk-0.1.0.tar.gz
  • Upload date:
  • Size: 42.3 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/6.1.0 CPython/3.13.12

File hashes

Hashes for hapbeat_python_sdk-0.1.0.tar.gz
Algorithm Hash digest
SHA256 12eb8c14c6a4f2c9809f567bd785fe08182df63384d3d5cbbfcd390b77b98599
MD5 aba9ac283b9dfd8d2c5b14dfdea4219c
BLAKE2b-256 6bfff4e60090dca4f488cd2ca0e6d7196b569b58f15d41ae6260d58fdc8850db

See more details on using hashes here.

Provenance

The following attestation bundles were made for hapbeat_python_sdk-0.1.0.tar.gz:

Publisher: publish.yml on hapbeat/hapbeat-python-sdk

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

File details

Details for the file hapbeat_python_sdk-0.1.0-py3-none-any.whl.

File metadata

File hashes

Hashes for hapbeat_python_sdk-0.1.0-py3-none-any.whl
Algorithm Hash digest
SHA256 c99351146341e0e6c6fd35bfbab59c0639d525451015882ab38b6507beb8eb2b
MD5 1375699f5c188958266ac4c1ae946478
BLAKE2b-256 95cd067436c6fb43fbe496a4c058196ca06c6e16a3303645aa024eabd1418ffd

See more details on using hashes here.

Provenance

The following attestation bundles were made for hapbeat_python_sdk-0.1.0-py3-none-any.whl:

Publisher: publish.yml on hapbeat/hapbeat-python-sdk

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page