Python integration
Drive the HEXR glove directly from Python over Bluetooth (BLE) with the HaptGlovePython library.
Install
You need Python 3.8 to 3.13. The library pins bleak 0.22.3, which does not install on Python 3.14 or newer, so pip stops with “No matching distribution found for bleak==0.22.3” there. Clone the library and install its dependencies:
git clone https://github.com/MicrotubeTechnologies/HaptGlovePython.git
cd HaptGlovePython
pip install -r requirements.txtThe library talks to the glove over BLE using bleak, which runs on Windows, macOS and Linux. It runs from a clone — it is not published to PyPI, so there is no pip install haptglove.
Find your glove
Power on the arm module. The example below finds the glove by the name it advertises, HaptGloveAR Right or HaptGloveAR Left, so there is no address to copy. To see every glove in range — or to pick one of several with the same name — run the discovery script and pass the address it prints to BleakClient instead of the name lookup:
python AddressDiscovery.pyOn macOS, Bluetooth reports a device UUID instead of a hardware address, so the value looks different — use whatever AddressDiscovery.py prints.
Your first pulse
Connect, press the index finger at a moderate intensity for two seconds, then release it. The release sits in a finally block, so it is sent even if something goes wrong or you press Ctrl+C mid-press. If no glove is found, the script says so and sends nothing. For the left glove, change GLOVE_NAME and "Right" to their left versions.
import asyncio
from bleak import BleakClient, BleakScanner
from Haptics import Haptics
GLOVE_NAME = "HaptGloveAR Right" # the left glove is "HaptGloveAR Left"
CHAR_UUID = "0000ff01-0000-1000-8000-00805f9b34fb"
FINGER = Haptics.Finger.Index
async def main():
# Find the glove by the name it advertises; no address to copy.
glove = await BleakScanner.find_device_by_name(GLOVE_NAME, timeout=10.0)
if glove is None:
print(f"No {GLOVE_NAME} found. Is the arm module switched on?")
return
haptics = Haptics("Right")
async with BleakClient(glove) as client:
# Subscribe to the glove's readings, as ExampleHaptics.py does.
# This example does not use them, so the callback ignores them.
await client.start_notify(CHAR_UUID, lambda sender, data: None)
try:
# Press: finger, True applies, intensity 0.1-1.0 (0.5 is
# moderate), ramp speed 0.1-1.0.
await client.write_gatt_char(CHAR_UUID, haptics.hexr_pressure(FINGER, True, 0.5, 1.0))
await asyncio.sleep(2) # hold for two seconds
finally:
# Release: False, intensity 0. Runs on success, on an error and
# on Ctrl+C -- but only while the link is up. If the Bluetooth
# link itself drops, nothing can reach the glove and it keeps
# pressing: switch the arm module off.
if client.is_connected:
await client.write_gatt_char(CHAR_UUID, haptics.hexr_pressure(FINGER, False, 0, 1.0))
asyncio.run(main())The glove keeps applying the last pressure it was sent until it receives a release; nothing on the glove lets go by itself. From 0.9.4 the Unity package releases every channel when your app quits, pauses or disconnects the glove, but nothing can release it if the app crashes or the Bluetooth link drops, and the Python library releases nothing for you. If a glove is left pressing, switch the arm module off.
It runs only while your script is running and the link is up. If the Bluetooth link drops mid-press, or the process is killed, no release reaches the glove and it keeps pressing until the arm module is switched off. A release on link loss would have to come from the glove’s firmware, which does not do that today.
To press several channels in one write, use hexr_pressure_multiple — see Every finger, its own value. ExampleHaptics.py in the repo does a press-and-release on every channel, with more logging.