Tap strap python sdk
Project description
TapStrap Python SDK (beta)
What Is This ?
TAP python SDK allows you to build python app that can establish BLE connection with Tap Strap and TapXR, send commands and receive events and data - Thus allowing TAP to act as a controller for your app!
The library is developed with Python >= 3.9 and is currently in beta.
Supported Platforms
This package supports the following platforms:
- MacOS (tested on 10.15.2) - using Apple's CoreBluetooth library. The library depends on PyObjC which Apple includes with their Python version on OSX. Note that if you're using a different Python, be sure to install PyObjC for that version of Python.
- Windows 10 - using Bleak with WinRT for BLE connectivity (no external DLL required).
- Linux (tested on Ubuntu 18.04) - need to install libbluetooth-dev and bluez-tools
also the user needs to be in the bluetooth group:sudo apt-get install bluez-tools libbluetooth-devsudo usermod -G bluetooth -a <username> #and can reload groups in this shell by running the following command or by logging out and back in: su - $USER
Installation
Install the package from PyPI:
pip install tap-python-sdk
Or clone this repo and install the package locally:
git clone https://github.com/TapWithUs/tap-python-sdk
cd tap-python-sdk
pip install .
The SDK is asyncio-based. Pair your Tap device with the OS first, then connect and register callbacks inside an async entry point:
import asyncio
from tapsdk import TapSDK
async def main():
tap_device = TapSDK()
tap_device.register_tap_events(lambda identifier, tapcode: print(identifier, tapcode))
await tap_device.run() # connects to a paired Tap, or scans until one is found
asyncio.run(main())
If no Tap is already connected at the OS level, run() will scan and wait for a device. On Windows and MacOS it also polls for already-paired devices that reconnect without advertising.
Also make sure that you have updated your Tap device to the latest version.
Features
This SDK implements two basic interfaces with a Tap device.
First is setting the operation mode:
- Text mode - the Tap device will operate normally, with no events being sent to the SDK
- Controller mode - the Tap device will send events to the SDK
- Controller and Text mode - the Tap device will operate normally, in parallel with sending events to the SDK
- Raw data mode - the Tap device will stream raw sensors data to the SDK.
Second, subscribing to the following events:
- Tap event - whenever a tap event has occurred
- Mouse event - whenever a mouse movement has occurred
- AirGesture event - whenever one of the gestures is detected
- Raw data - whenever new raw data sample is being made.
Additional to these functional events, there are also some state events, such as connection and disconnection of Tap devices to the SDK backend.
Spatial Control - NEW
Authorized developers can gain access to the experimental Spatial Control features:
- Extended AirGesture state - enabling aggregation for pinch, drag and swipe gestures.
- Select input type - enabling the selection of input type to be activated - i.e. AirMouse/Tapping.
These features are only available on TapXR and only for qualified developers. Request access here
Migration from 0.6.x
If you are upgrading from an earlier release, note these breaking changes:
TapInputMode("controller")→InputModeController()(and similarly for other modes). Import fromtapsdk.TapInputMode("raw", sensitivity=[2, 1, 4])→InputModeRaw(finger_accl_sens=..., imu_gyro_sens=..., imu_accl_sens=...). Use the typed enums intapsdk.enumerations.from tapsdk.models import AirGestures→from tapsdk import AirGestures- The
loop=constructor argument has been removed. - Event registration (
register_*) is synchronous; call it beforeawait tap_device.run(). - Commands (
set_input_mode,set_input_type,send_vibration_sequence) are async and must be awaited. - OS-specific examples (
example_unix.py,example_win.py) have been replaced by a single cross-platformexamples/basic.py.
High level API
The SDK uses callbacks to implement user functions on the various events. To register a callback, you just have to instance a TapSDK object and:
def on_tap_event(identifier, tapcode):
print(identifier + " tapped " + str(tapcode))
tap_device.register_tap_events(on_tap_event)
Commands list
-
set_input_mode(self, input_mode:InputMode, identifier=None):This function sends a mode selection command. It accepts an object of typeInputModesuch asInputModeText,InputModeController,InputModeControllerText, orInputModeRaw.
For example:from tapsdk import InputModeController await tap_device.set_input_mode(InputModeController())
For raw sensors mode, you can specify sensitivity and scaling:
from tapsdk import InputModeRaw from tapsdk.enumerations import FingerAcclSensitivity, ImuGyroSensitivity, ImuAcclSensitivity await tap_device.set_input_mode(InputModeRaw( scaled=True, finger_accl_sens=FingerAcclSensitivity.G4, imu_gyro_sens=ImuGyroSensitivity.DPS250, imu_accl_sens=ImuAcclSensitivity.G4 ))
-
set_input_type(self, input_type:InputType, identifier=None):Only for TapXR and with Spatial Control experimental firmware
This function sends a command to force input type. It accepts an enum of type
InputTypeinitialized with any of the typesInputType.MOUSE,InputType.KEYBOARD, orInputType.AUTO.
For example:from tapsdk import InputType await tap_device.set_input_type(InputType.AUTO)
This will set the input to be automatically selected by the Tap device, based on hand posture.
-
send_vibration_sequence(self, sequence:list, identifier=None):This function sends a series of haptic activations.sequenceis a list of integers indicating the activation and delay periods one after another. The periods are in millisecond units, in the range of [10,2550] and in resolution of 10ms. Each haptic command supports up to 18 period definitions (i.e. 9 haptics + delay pairs).
For example:await tap_device.send_vibration_sequence(sequence=[1000,300,200])
will trigger a 1s haptic, followed by 300ms delay, followed by 200ms haptic.
Events list
-
register_connection_events(self, listener:Callable):
Register callback to a Tap strap connection event.def on_connect(tap_sdk_instance): print("Connected to Tap device") tap_device.register_connection_events(on_connect)
-
register_disconnection_events(self, listener:Callable):
Register callback to a Tap strap disconnection event.def on_disconnect(client): print("Tap device disconnected") tap_device.register_disconnection_events(on_disconnect)
-
register_tap_events(self, listener:Callable):
Register callback to a tap event.def on_tap_event(identifier, tapcode): print(identifier + " - tapped " + str(tapcode)) tap_device.register_tap_events(on_tap_event)
tapcodeis an 8-bit unsigned number, between 1 and 31 which is formed by a binary representation of the fingers that are tapped. The LSb is thumb finger, the MSb is the pinky finger. For example: if combination equals 5 - its binary form is 10100 - means that the thumb and the middle fingers were tapped. -
register_mouse_events(self, listener:Callable):
Register callback to a mouse or air mouse movement event.def on_mouse_event(identifier, vx, vy, proximity): print(identifier + " - moused: %d, %d" %(vx, vy)) tap_device.register_mouse_events(on_mouse_event)
vxandvyare the horizontal and vertical velocities of the mouse movement respectively.proximityis a boolean that indicates proximity with a surface. -
register_raw_data_events(self, listener:Callable):
Register callback to raw sensors data packet received event.def on_raw_sensor_data(identifier, packets): for packet in packets: print(identifier, packet["type"], packet["ts"], packet["payload"]) tap_device.register_raw_data_events(on_raw_sensor_data)
The callback receives a list of dicts, each with keys
type("imu"or"accl"),ts(millisecond timestamp), andpayload(list of sample values). WhenInputModeRaw(scaled=True)is active, values are in mg and mdps. You'll find more information on that mode in the dedicated section below or here. -
register_air_gesture_events(self, listener:Callable):
Register callback to air gesture events.from tapsdk import AirGestures def on_airgesture(identifier, gesture): print(identifier + " - gesture: " + str(AirGestures(gesture))) tap_device.register_air_gesture_events(on_airgesture)
gestureis an integer code of the air gesture detected. The air gesture values are enumerated in theAirGesturesclass, including directional gestures (UP_ONE_FINGER,PINCH, etc.), thumb gestures (THUMB_FINGER,THUMB_MIDDLE), and spatial state gestures (STATE_OPEN,STATE_FIST, etc.). -
register_air_gesture_state_events(self, listener:Callable):
Register callback to mouse-mode state changes (e.g. air mouse, optical mouse).from tapsdk.enumerations import MouseModes def on_mouse_mode_change(identifier, mouse_mode): print(identifier + " - mode: " + str(mouse_mode)) tap_device.register_air_gesture_state_events(on_mouse_mode_change)
mouse_modeis aMouseModesenum value:STDBY,AIR_MOUSE,OPTICAL1, orOPTICAL2.
Raw sensors mode
Make sure that "Developer mode" is enabled on TapManager app for this mode to work properly
In raw sensors mode, the Tap device continuously sends raw data from the following sensors:
- Five 3-axis accelerometers - one per each finger (available only on TAP Strap and Tap Strap 2).
- sampled at 200Hz
- allows dynamic range configuration (±2G, ±4G, ±8G, ±16G)
- IMU (3-axis accelerometer + gyro) located on the thumb (available on TAP Strap 2 and TapXR).
- sampled at 208Hz.
- allows dynamic range configuration for the accelerometer (±2G, ±4G, ±8G, ±16G) and for the gyro (±125dps, ±250dps, ±500dps, ±1000dps, ±2000dps).
The sensors measurements are given with respect to the reference system below.
Each sample (of accelerometer or imu) is preambled with a millisecond timestamp, referenced to an internal Tap clock.
The dynamic range of the sensors is determined with the set_input_mode method by passing an InputModeRaw instance with the desired sensitivity enums, and a boolean flag indicating if the data should be scaled to mg and mdps for the accelerometer and gyro respectively:
from tapsdk import InputModeRaw
from tapsdk.enumerations import FingerAcclSensitivity, ImuGyroSensitivity, ImuAcclSensitivity
await tap_device.set_input_mode(InputModeRaw(
scaled=True,
finger_accl_sens=FingerAcclSensitivity.G4,
imu_gyro_sens=ImuGyroSensitivity.DPS250,
imu_accl_sens=ImuAcclSensitivity.G4
))
Refer to FingerAcclSensitivity, ImuGyroSensitivity, and ImuAcclSensitivity in tapsdk.enumerations for the available sensitivity values.
Examples
You can find some examples in the examples folder.
Testing
To run the tests, first install the development dependencies:
pip install .[dev]
Then run the tests using pytest:
pytest
Known Issues
See History.md for release notes. No known issues at 0.7.0.
Support
Please refer to the issues tab! :)
History
Releasing
PyPI releases are published automatically when a version tag is pushed to GitHub.
-
Bump
__version__intapsdk/__version__.pyand update this file. -
Merge the release changes into
develop, then intomasteras needed. -
Create and push an annotated tag whose name matches the package version (for example
v0.7.0):git tag -a v0.7.0 -m "Release 0.7.0" git push origin v0.7.0
The Publish to PyPI workflow runs the same lint and test matrix as CI, verifies that the tag (without the v prefix) matches tapsdk.__version__, builds the package with python -m build, and uploads it to PyPI using Trusted Publishing.
Maintainers must configure PyPI Trusted Publishing for the tap-python-sdk project name, the TapWithUs/tap-python-sdk repository, and a GitHub pypi environment before the first automated release.
0.7.0 (2026-06-09)
Main features
- Unified cross-platform implementation in
tapsdk/tap.py(removed separate posix/dotnet backends). - Windows rewritten to use Bleak/WinRT instead of TAPWin.dll.
InputModeAPI:TapInputMode("…")replaced byInputModeText,InputModeController,InputModeControllerText,InputModeRaw.- Raw mode: typed sensitivity enums and optional scaling to mg/mdps (
scaled=True). - Connection and disconnection events implemented on all platforms.
- Windows: BLE scan and reconnect polling for paired devices.
- Python requirement raised to 3.9+.
- CI: cross-platform pytest and flake8.
- New
AirGesturesvalues (thumb and state gestures).
Breaking changes
- Removed
TapInputMode,loopconstructor argument,tapsdk.models, and OS-specific examples. - Windows no longer uses bundled TAPWin.dll.
0.6.0 (2024-07-04)
Main features
- Added Spatial features for TapXR.
- Mac and Linux backends unified to posix backend.
Known Issues
- Windows backend -
- Raw sensor data rate might be lower than expected.
- Sometimes a Tap strap wouldn't be detected upon connection. In this case try restarting your Tap and/or the Python application. In worst case scenario re-pair your Tap.
- Spatial features are still not available for Windows backend.
- MacOS & Linux backends -
- Doesn't support multiple Tap strap connections.
- OnConnect and OnDisconnect events are not implemented
- Raw sensor data is given unscaled (i.e. unitless), therefore in order to scale to physical units need to multiply by the relevant scale factor
0.5.1 (2024-01-01)
Main features
- Support TapXR Air Gesture pinch
0.5.0 (2021-08-03)
Main features
- Support Bleak 0.12.1 for mac
0.3.0 (2020-09-07)
Main features
- Linux support
- Some bug fixes
0.2.0 (2020-02-22)
Main features
- Added dll to enable windows backend.
- fix parsers output types on gesture and tap messages
0.1.0 (2020-02-20)
Main features
- SDK created.
Project details
Release history Release notifications | RSS feed
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file tap_python_sdk-0.7.0.tar.gz.
File metadata
- Download URL: tap_python_sdk-0.7.0.tar.gz
- Upload date:
- Size: 19.3 kB
- Tags: Source
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.12
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
7e378a88b2e53bed50e9f8979dc7e4589bad9c6248c2b17fed689cec28923196
|
|
| MD5 |
9a04180cdbaa25d7250be65c29ff096b
|
|
| BLAKE2b-256 |
f2d53f641e4f6674f9c56cf02b6117ebc8e31f794e26647973fc3bdbc573cd31
|
Provenance
The following attestation bundles were made for tap_python_sdk-0.7.0.tar.gz:
Publisher:
publish.yml on TapWithUs/tap-python-sdk
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
tap_python_sdk-0.7.0.tar.gz -
Subject digest:
7e378a88b2e53bed50e9f8979dc7e4589bad9c6248c2b17fed689cec28923196 - Sigstore transparency entry: 2149650147
- Sigstore integration time:
-
Permalink:
TapWithUs/tap-python-sdk@2a9ba68531e4f50f3c88cd2ce9e8f0426c295ecc -
Branch / Tag:
refs/tags/v0.7.0 - Owner: https://github.com/TapWithUs
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
publish.yml@2a9ba68531e4f50f3c88cd2ce9e8f0426c295ecc -
Trigger Event:
push
-
Statement type:
File details
Details for the file tap_python_sdk-0.7.0-py3-none-any.whl.
File metadata
- Download URL: tap_python_sdk-0.7.0-py3-none-any.whl
- Upload date:
- Size: 16.4 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.12
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
41101eed2e7ce1c6915baf041bd082049b160daa985c1259eeeb0bfd1f442ba4
|
|
| MD5 |
4f7588308532a6fc27abe88c0e8784b3
|
|
| BLAKE2b-256 |
ae94390b90b3a4335f1b87992154c9cb90d26546c1a124a9355987e6263494c0
|
Provenance
The following attestation bundles were made for tap_python_sdk-0.7.0-py3-none-any.whl:
Publisher:
publish.yml on TapWithUs/tap-python-sdk
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
tap_python_sdk-0.7.0-py3-none-any.whl -
Subject digest:
41101eed2e7ce1c6915baf041bd082049b160daa985c1259eeeb0bfd1f442ba4 - Sigstore transparency entry: 2149650250
- Sigstore integration time:
-
Permalink:
TapWithUs/tap-python-sdk@2a9ba68531e4f50f3c88cd2ce9e8f0426c295ecc -
Branch / Tag:
refs/tags/v0.7.0 - Owner: https://github.com/TapWithUs
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
publish.yml@2a9ba68531e4f50f3c88cd2ce9e8f0426c295ecc -
Trigger Event:
push
-
Statement type: