Skip to main content

References

The tact-js package provides functions for controlling bHaptics haptic devices from JavaScript. It enables you to play haptic patterns, control device motors directly, and manage haptic playback.

import Tact from "tact-js";

Play Event-driven Haptic

Play haptic patterns bound to specific events (designed in the bHaptics Designer/Portal). These are the recommended functions for most applications.

play

play({ eventKey, startTime, intensityRatio, durationRatio, offsetX, offsetY }: PlayParams): Promise<void>;

type PlayParams = {
eventKey: string; // Name of the haptic event
startTime?: number; // Delay in milliseconds
intensityRatio?: number; // Intensity multiplier [0.0 - 2.0]
durationRatio?: number; // Duration multiplier
offsetX?: number; // Rotation offset [0.0 - 360.0]
offsetY?: number; // Vertical offset [-0.5 - 0.5]
};

Play the predefined haptic event.

Parameters

  • eventKey: Name of the haptic event.
  • startTime(optional): Playback start position in milliseconds. (Default: 0)
  • intensityRatio(optional): Multiplier for haptic intensity. Valid range is: [0.0 - 2.0] (Default: 1.0)
  • durationRatio(optional): Multiplier for duration. (Default: 1.0)
  • offsetX(optional): Rotate haptic counterclockwise. Valid range is: [0.0 - 360.0] (Default: 0.0)
  • offsetY(optional): Move haptic up or down. Valid range is: [-0.5 - 0.5] (Default: 0.0)

Returns

TODO

Example

import Tact from "tact-js";

const playExample = async () => {
await Tact.play({ eventKey: "heartbeat" });
};

const playMoreExample = async () => {
await Tact.play({
eventKey: "hit",
startTime: 0,
intensityRatio: 1.0,
durationRatio: 1.0,
offsetX: 180.0,
offsetY: 0.25,
});
};

playLoop

playLoop({ eventKey, intensityRatio, durationRatio, interval, max_count, offsetX, offsetY }: PlayLoopParams): Promise<number>;

type PlayLoopParams = {
eventKey: string; // Name of the haptic event
intensityRatio?: number; // Intensity multiplier [0.0 - 2.0]
durationRatio?: number; // Duration multiplier
interval: number; // Time between loops (milliseconds)
max_count: number; // Maximum number of loops
offsetX: number; // Rotation offset [0.0 - 360.0]
offsetY: number; // Vertical offset [-0.5 - 0.5]
};

Play the haptic event in a loop for a specified number of times.

Parameters

  • eventKey: Name of the haptic event.
  • intensityRatio(optional): Multiplier for haptic intensity. Valid range is: [0.0 - 2.0] (Default: 1.0)
  • durationRatio(optional): Multiplier for duration. (Default: 1.0)
  • interval: Time interval between loops in milliseconds.
  • max_count: Number of times to loop the haptic event. TODO
  • offsetX: Rotate haptic counterclockwise. Valid range is: [0.0 - 360.0] (Default: 0.0)
  • offsetY: Move haptic up or down. Valid range is: [-0.5 - 0.5] (Default: 0.0)

Returns

Request ID. You can use this to stop playback. Returns -1 if failed.

Example

import Tact from "tact-js";

const playLoopExample = async () => {
const requestId = await Tact.playLoop({
eventKey: "hit",
intensityRatio: 1.0,
durationRatio: 1.0,
interval: 1000,
max_count: 5,
offsetX: 0.0,
offsetY: 0.0,
});

console.log(`Playback request ID: ${requestId}`);
};

Play Haptic Directly

If you want to play haptics without events, use these functions.

playDot

playDot({ position, motorValues, duration }: PlayDotParams): Promise<number>;

type PlayDotParams = {
position: PositionType; // Device position type
motorValues: number[]; // Array of motor intensity values [0 - 100]
duration?: number; // Duration in milliseconds
};

Play haptic feedback on the specific haptic actuators.

Parameters

  • position: Type of haptic device to playback. Refer the PositionType enum.
  • motorValues: Array of intensity values for each motor. The array length must match the number of motors in the device. Each value must be integer and in range. Valid range is: [0 - 100].
  • duration(optional): Duration of haptic feedback in milliseconds. Greater than or equal to 100 is recommended.

Returns

Request ID. You can use this to stop playback. Returns -1 if failed.

Example

import Tact, { PositionType } from "tact-js";

const playDotExample = async () => {
const requestId = await Tact.playDot({
position: PositionType.ForearmL, // Left TactSleeve
motorValues: [100, 80, 60], // TactSleeve has 3 motors
duration: 100
});

console.log(`Playback request ID: ${requestId}`);
}

playPath

playPath({ position, x, y, intensity, duration }: PlayPathParams): Promise<number>;

type PlayPathParams = {
position: PositionType; // Device position type
x: number[]; // Array of x coordinates [0.0 - 1.0]
y: number[]; // Array of y coordinates [0.0 - 1.0]
intensity: number[]; // Array of intensity values [0 - 100]
duration?: number; // Duration in milliseconds
};

Play haptic feedback along specified coordinates. Unlike playDot which controls individual motors, this method specifies haptic intensity for particular coordinates on the device.

When specifying haptic position, playDot offers discrete control, while playPath is more continuous. playDot assigns intensity to individual actuators, whereas playPath allows intensity specification for specific coordinates (between 0 and 1 for both X and Y axis), causing nearby actuators to vibrate accordingly.

You can specify multiple coordinates with multiple intensities. Note that all actuators around these coordinates in the list will activate simultaneously, not sequentially. The size of all arrays (x, y, and intensity) must be the same.

By continuously calling this function while gradually changing the values, you can achieve the effect of a moving haptic point.

Coordinate

Parameters

  • position: Type of haptic device to playback. Refer the PositionType enum.
  • x: Array of X coordinates for the haptic effect. Each value must be in range: [0.0 - 1.0]
  • y: Array of Y coordinates for the haptic effect. Each value must be in range: [0.0 - 1.0]
  • intensity: Array of intensity values for each coordinate. Each value must be integer and in range: [0 - 100]
  • duration(optional): Duration of haptic feedback in milliseconds. Greater than or equal to 100 is recommended.

Returns

Request ID. You can use this to stop playback. Returns -1 if failed.

Example

import Tact, { PositionType } from "tact-js";

const HAPTIC_PATHS = [
{
x: [0.738, 0.723, 0.709, 0.696, 0.682, 0.667, 0.653],
y: [0.680, 0.715, 0.749, 0.782, 0.816, 0.852, 0.885],
intensity: 20
},
{
x: [0.061, 0.072, 0.102, 0.184, 0.254, 0.310, 0.363],
y: [0.632, 0.587, 0.542, 0.498, 0.411, 0.366, 0.301],
intensity: 60
}
];

const TIME_OF_FRAME = 250; // milliseconds

const playPathExample = async () => {
const frames = HAPTIC_PATHS[0].x.length;

for (let i = 0; i < frames; i++) {
await Tact.playPath({
position: PositionType.Vest, // TactSuit
x: HAPTIC_PATHS.map(point => point.x[i]),
y: HAPTIC_PATHS.map(point => point.y[i]),
intensity: HAPTIC_PATHS.map(point => point.intensity),
duration: TIME_OF_FRAME
});
await new Promise(resolve => setTimeout(resolve, TIME_OF_FRAME));
}
}

playGlove

playGlove({ position, motors, playtimes, shapes, repeat_count }: PlayGloveParams): Promise<number>;

type PlayGloveParams = {
position: PositionType; // GloveL or GloveR
motors: Int32Array; // Array of 6 motor intensity values [0 - 100]
playtimes: Int32Array; // Array of 6 time interval values
shapes: Int32Array; // Array of 6 waveform values
repeat_count: number; // Number of times to repeat
};

TactGlove Only. Play haptics in TactGlove with fine-grained control over duration and intensity patterns. This provides more detailed control compared to playDot.

Each array parameter must contain exactly six elements, one for each motor in the glove.

Parameters

  • position: Type of haptic device to playback. Must use PositionType.GloveL or PositionType.GloveR.
  • motors: Array of 6 intensity values, one per motor. Each value must be integer and in range: [0 - 100]
  • playtimes: Array of 6 time interval values. Valid values are:
    ValueDuration
    15ms
    210ms
    420ms
    630ms
    840ms
  • shapes: Array of 6 waveform values controlling how intensity changes over time:
    ValueWaveform Pattern
    0Constant intensity for the duration
    1Starts at specified intensity and decreases by half
    2Starts at half intensity and increases to full
  • repeat_count: Number of times to repeat the pattern. TODO

Returns

Request ID. You can use this to stop playback. Returns -1 if failed.

Example

import Tact, { PositionType } from "tact-js";

const playGloveExample = async () => {
const motors = new Int32Array([100, 100, 100, 100, 100, 100]);
const playtimes = new Int32Array([8, 8, 8, 8, 8, 8]);
const shapes = new Int32Array([2, 2, 2, 2, 2, 2]);

const requestId = await Tact.playGlove({
position: PositionType.GloveR,
motors,
playtimes,
shapes,
repeat_count: 3
});

console.log(`Playback request ID: ${requestId}`);
}

Playback Control

pause

pause(eventKey: string): Promise<void>

Pause a specific haptic event that is currently playing.

Parameters

  • eventKey: Name of the haptic event to pause.

Example

import Tact, { PositionType } from "tact-js";

const playAndPauseExample = async () => {
await Tact.play("dash");
await new Promise(resolve => setTimeout(resolve, 1000));
await Tact.pause("dash");
}

resume

resume(eventKey: string): Promise<void>

Resume a previously paused haptic event.

Parameters

Example

import Tact, { PositionType } from "tact-js";

const playPauseAndResumeExample = async () => {
await Tact.play("dash");
await new Promise(resolve => setTimeout(resolve, 1000));
await Tact.pause("dash");
await new Promise(resolve => setTimeout(resolve, 1000));
await Tact.resume("dash");
}

stop

stop(eventKey: string): Promise<void>

Stop a specific haptic event completely.

Parameters

  • eventKey: Name of the haptic event to stop.

Example

import Tact from "tact-js";

const stopExample = async () => {
await Tact.play("dash");
await new Promise(resolve => setTimeout(resolve, 1000));
await Tact.stop("dash");
}

stopAll

stopAll(): Promise<void>

Stop all currently playing haptics.

Example

import Tact from "tact-js";

const stopAllExample = async () => {
await Tact.play("dash");
await Tact.play("heartbeat");
await Tact.play("hit");
await Tact.play("slash");
await new Promise(resolve => setTimeout(resolve, 500));

await Tact.stopAll();
}

Lifecycle

init

init({ appId, apiKey }: InitParams): Promise<boolean>;

type InitParams = {
appId: string; // Your bHaptics App ID
apiKey: string; // Your bHaptics API Key
};

Initialize the bHaptics SDK. This function must be called before using any other functions in the SDK. It initializes the SDK and establishes connection with bHaptics Player.

Parameters

  • appId: Your bHaptics application ID from the bHaptics Developer Portal
  • apiKey: Your bHaptics API key from the bHaptics Developer Portal

Returns

Returns true if initialization is successful, false otherwise.

Example

import Tact from "tact-js";

const initTact = () => {
const result = await Tact.init({
appId: "your-app-id",
apiKey: "your-api-key",
});

console.log({ result
? "Connection Success!"
: "Connection Failed..."
});
}


Status Checking

getConnectedDevices

getConnectedDevices(): Promise<any[]>

Get a list of all connected haptic devices.

Returns

Array of connected device objects containing device information.

// TODO: Use JSON Schema to explain this?

The example of return value follows:

[
{
"position": 8,
"deviceName": "TactGlove (L)",
"address": "F418EB165E99",
"connected": true,
"paired": true,
"battery": 91,
"audioJackIn": false,
"vsm": 20
},
{
"position": 9,
"deviceName": "TactGlove (R)",
"address": "DF8B33412EC5",
"connected": true,
"paired": true,
"battery": 84,
"audioJackIn": false,
"vsm": 20
}
]

Example

import Tact from "tact-js";

const showDevicesExample = () => {
const devices = await Tact.getConnectedDevices();
console.log("Connected devices:", devices);
}

getHapticMappings (NOT IMPLEMETED)

getHapticMappings(): Promise<any[]>

Get a list of all haptic patterns registered in the current haptic application.

Returns

Array of haptic mapping objects containing information about available haptic patterns.

// TODO

Example

// TODO

isDeviceConnected

isDeviceConnected(position: PositionType): Promise<boolean>

Check if a specific device type is connected.

Parameters

Returns

true if the device type is connected, false otherwise.

Example

import Tact, { PositionType } from "tact-js";

const isDeviceConnectedExample = async () => {
const isGloveConnected = await Tact.isDeviceConnected(PositionType.GloveR);
console.log("Right TactGlove connected:", isGloveConnected);
}

isConnected

isConnected(): Promise<boolean>

Check the connection status with bHaptics Player.

Returns

true if connected to bHaptics Player, false otherwise.

isPlaying

isPlaying(): Promise<boolean>

Check if any haptic feedback is currently playing.

Returns

true if any haptic is playing, false otherwise.

isPlayingByEventKey

isPlayingByEventKey(eventKey: string): Promise<boolean>

Check if a specific haptic event is currently playing.

Parameters

  • eventKey: Name of the haptic event to check

Returns

true if the specified haptic event is playing, false otherwise.

Device Control

ping

ping(address: string): Promise<void>

Sends a ping signal to a specific device to test connection.

Parameters

  • address: The MAC address of the haptic device. You can get the address from getConnectedDevices()

Example

import Tact from "tact-js";

const pingFirstDeviceExample = async () => {
const devices = await Tact.getConnectedDevices();

if (devices.length > 0) {
await Tact.ping(devices[0].address);
}
}

pingAll

pingAll(): Promise<void>

Send a ping signal to all connected devices.

motorTest (TODO)

motorTest(): Promise<void>

Run a test sequence on all connected device motors to verify they are working correctly.

Common Enums

PositionType

enum PositionType {
  Vest = "Vest",
  ForearmL = "ForearmL",
  ForearmR = "ForearmR",
  Head = "Head",
  HandL = "HandL",
  HandR = "HandR",
  FootL = "FootL",
  FootR = "FootR",
  GloveL = "GloveL",
  GloveR = "GloveR"
}

String enums. Use it to decide the type of haptic device.

ValueDeviceMotors Count
VestTactSuit32
ForearmLTactSleeve(Left)3
ForearmRTactSleeve(Right)3
HeadTactVisor4
HandLTactosy for Hands(Left)6
HandRTactosy for Hands(Right)6
FootLTactosy for Feet(Left)6
FootRTactosy for Feet(Right)6
GloveLTactGlove(Left)6
GloveRTactGlove(Right)6