buttplug.js

Device

Represents a single device connected to a Buttplug server.


The Device class provides typed methods for controlling outputs (vibration, rotation, position, etc.) and reading or subscribing to input sensors. Device instances are created internally by ButtplugClient when devices are discovered.

client.on("deviceAdded", ({ device }) => {
  console.log(device.name, device.features);
  await device.vibrate(50);
});

Properties

index

get index(): number

Server-assigned device index.

name

get name(): string

Internal device name from firmware.

displayName

get displayName(): string | null

User-facing display name, or null if the server did not provide one.

messageTimingGap

get messageTimingGap(): number

Minimum interval in milliseconds between messages recommended by the server. Commands sent faster than this interval may be dropped.

features

get features(): DeviceFeatures

Parsed input and output feature descriptors for this device. See DeviceFeatures for the shape.

canRotate

get canRotate(): boolean

Whether this device supports any form of rotation output (Rotate or RotateWithDirection).

canPosition

get canPosition(): boolean

Whether this device supports any form of position output (Position or HwPositionWithDuration).

Output Methods

All scalar output methods accept either a single number (applied to all motors/actuators) or a FeatureValue[] array for per-feature control.

vibrate

vibrate(intensity: number | FeatureValue[]): Promise<void>

Sets vibration intensity on all or individual motors.

ParameterTypeDescription
intensitynumber | FeatureValue[]Single value for all motors, or per-motor entries

Throws: DeviceError if the device does not support vibration.

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

// Per-motor control
await device.vibrate([
  { index: 0, value: 80 },
  { index: 1, value: 40 },
]);

oscillate

oscillate(speed: number | FeatureValue[]): Promise<void>

Sets oscillation speed on all or individual motors.

Throws: DeviceError if the device does not support oscillation.

constrict

constrict(value: number | FeatureValue[]): Promise<void>

Sets constriction pressure on all or individual actuators.

Throws: DeviceError if the device does not support constriction.

spray

spray(value: number | FeatureValue[]): Promise<void>

Controls spray output on all or individual actuators.

Throws: DeviceError if the device does not support spraying.

temperature

temperature(value: number | FeatureValue[]): Promise<void>

Sets temperature on all or individual actuators.

Throws: DeviceError if the device does not support temperature control.

led

led(value: number | FeatureValue[]): Promise<void>

Controls LED brightness on all or individual actuators.

Throws: DeviceError if the device does not support LED control.

rotate

Rotation has two overloads:

// Uniform speed on all motors
rotate(speed: number, options?: { clockwise?: boolean }): Promise<void>

// Per-motor control
rotate(values: RotationValue[]): Promise<void>

Sets rotation speed and direction. Automatically selects RotateWithDirection if the device supports it, falling back to Rotate otherwise.

ParameterTypeDescription
speednumberSingle speed for all motors
options.clockwisebooleanDirection (defaults to true)
valuesRotationValue[]Per-motor entries with speed, direction, and index

Throws: DeviceError if the device does not support rotation.

await device.rotate(70, { clockwise: false });

await device.rotate([
  { index: 0, speed: 80, clockwise: true },
  { index: 1, speed: 40, clockwise: false },
]);

position

Position has two overloads:

// Uniform position on all axes
position(position: number, options: { duration: number }): Promise<void>

// Per-axis control
position(values: PositionValue[]): Promise<void>

Moves all axes to a position over a given duration. Automatically selects HwPositionWithDuration if the device supports it.

ParameterTypeDescription
positionnumberSingle position value for all axes
options.durationnumberMovement duration in milliseconds (required for uniform)
valuesPositionValue[]Per-axis entries with position, duration, and index

Throws: DeviceError if the device does not support position control.

await device.position(80, { duration: 500 });

await device.position([
  { index: 0, position: 100, duration: 300 },
]);

stop

stop(options?: DeviceStopOptions): Promise<void>

Stops activity on this device. Without options, stops all features. Can target a specific feature index or filter by input/output type.

Prop

Type

Throws: DeviceError if the specified feature index does not exist.

await device.stop();
await device.stop({ featureIndex: 0 });
await device.stop({ outputs: true, inputs: false });

output

output(options: DeviceOutputOptions): Promise<void>

Sends a raw output command to a specific feature. Values are validated against the feature's declared range and clamped if out of bounds.

Prop

Type

Throws: DeviceError if no matching output feature exists at the given index.

await device.output({
  featureIndex: 0,
  command: { Vibrate: { Value: 50 } },
});

Sensor Methods

readSensor

readSensor(type: InputType, sensorIndex?: number): Promise<number>

Performs a one-shot read of a sensor value.

ParameterTypeDescription
typeInputTypeSensor type (e.g. "Battery", "RSSI")
sensorIndexnumberIndex if the device has multiple sensors of the same type (default 0)

Returns: The numeric sensor value. Throws: DeviceError if the sensor does not exist or does not support reading.

const battery = await device.readSensor("Battery");
console.log(`Battery: ${battery}%`);

subscribeSensor

subscribeSensor(
  type: InputType,
  callback: (value: number) => void,
  sensorIndex?: number
): Promise<() => Promise<void>>

Subscribes to continuous sensor readings.

ParameterTypeDescription
typeInputTypeSensor type to subscribe to
callback(value: number) => voidCalled with the numeric sensor value on each new reading
sensorIndexnumberIndex if multiple sensors of the same type (default 0)

Returns: An async unsubscribe function that stops the subscription. Throws: DeviceError if the sensor does not exist or does not support subscriptions.

const unsubscribe = await device.subscribeSensor(
  "Battery",
  (value) => console.log(value)
);

// Later
await unsubscribe();

unsubscribe

unsubscribe(type: InputType, sensorIndex?: number): Promise<void>

Explicitly unsubscribes from a sensor subscription by type and sensor index.

Throws: DeviceError if the sensor does not exist at the given index.

Capability Checks

canOutput

canOutput(type: OutputType): boolean

Checks whether this device supports a given output type.

if (device.canOutput("Vibrate")) {
  await device.vibrate(50);
}

canRead

canRead(type: InputType): boolean

Checks whether this device can perform a one-shot read of a given sensor type.

canSubscribe

canSubscribe(type: InputType): boolean

Checks whether this device supports subscriptions for a given sensor type.

  • Devices -- discovering devices and inspecting capabilities
  • Commands -- output command patterns
  • Sensors -- reading and subscribing to sensors
  • Types -- FeatureValue, RotationValue, PositionValue, and more

On this page