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. TODOoffsetX
: 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 thePositionType
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 to100
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.
Parameters
position
: Type of haptic device to playback. Refer thePositionType
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 to100
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 usePositionType.GloveL
orPositionType.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:Value Duration 1
5ms 2
10ms 4
20ms 6
30ms 8
40ms shapes
: Array of 6 waveform values controlling how intensity changes over time:Value Waveform Pattern 0
Constant intensity for the duration 1
Starts at specified intensity and decreases by half 2
Starts 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
position
: Type of haptic device to playback. Refer thePositionType
enum.
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 PortalapiKey
: 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
position
: Type of haptic device to playback. Refer thePositionType
enum.
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 fromgetConnectedDevices()
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.
Value | Device | Motors Count |
---|---|---|
Vest | TactSuit | 32 |
ForearmL | TactSleeve(Left) | 3 |
ForearmR | TactSleeve(Right) | 3 |
Head | TactVisor | 4 |
HandL | Tactosy for Hands(Left) | 6 |
HandR | Tactosy for Hands(Right) | 6 |
FootL | Tactosy for Feet(Left) | 6 |
FootR | Tactosy for Feet(Right) | 6 |
GloveL | TactGlove(Left) | 6 |
GloveR | TactGlove(Right) | 6 |