buttplug.js

Commands

Control device outputs — vibration, rotation, position, and more


await device.vibrate(50);

All output commands on a Device are async and accept integer values within the device's feature range (typically 0 to 100, except position durations which are in milliseconds). The valid range is defined per-feature in device.features.outputs. Values are rounded and clamped to the feature range automatically. Commands throw a DeviceError if the device lacks the required capability.

Scalar Commands

The scalar commands -- vibrate(), oscillate(), constrict(), spray(), temperature(), and led() -- share the same signature. Pass a single number to set all motors/actuators uniformly, or a FeatureValue[] to address each one individually.

// All motors at 75%
await device.vibrate(75);

// Per-motor control: motor 0 at 50%, motor 1 at 100%
await device.vibrate([
  { index: 0, value: 50 },
  { index: 1, value: 100 },
]);

Each scalar type maps to an output type: vibrate() sends Vibrate, oscillate() sends Oscillate, and so on. Check support with device.canOutput("Vibrate") before calling.

Rotation

rotate() has two overloads. The simple form takes a speed and an optional direction. The array form addresses each motor independently with a RotationValue[].

// All motors at 60%, clockwise (default)
await device.rotate(60);

// Counterclockwise
await device.rotate(60, { clockwise: false });

// Per-motor: different speeds and directions
await device.rotate([
  { index: 0, speed: 50, clockwise: true },
  { index: 1, speed: 80, clockwise: false },
]);

The client automatically selects RotateWithDirection when the device supports it, falling back to Rotate otherwise. Use device.canRotate to check support.

Position

position() moves linear axes to a target position over a specified duration. The duration parameter is required for the uniform overload and is specified in milliseconds.

// All axes to 80% over 500ms
await device.position(80, { duration: 500 });

// Per-axis control
await device.position([
  { index: 0, position: 100, duration: 300 },
  { index: 1, position: 20, duration: 600 },
]);

The client selects HwPositionWithDuration when available, falling back to Position. Use device.canPosition to check support.

Stopping

Stop a single device or all devices at once:

// Stop everything on one device
await device.stop();

// Stop only outputs (keep sensor subscriptions)
await device.stop({ outputs: true });

// Stop all devices globally
await client.stopAll();

device.stop() without options halts all features. Pass DeviceStopOptions to target a specific feature index or filter by inputs/outputs.

Devices report a messageTimingGap -- the minimum interval between commands. Sending commands faster than this interval may cause the server to drop messages. The client logs a warning when this happens but does not throttle automatically.

On this page