Pattern Engine
Keyframe-based pattern playback for device automation.
import { ButtplugClient, PatternEngine } from "@zendrex/buttplug.js";
const client = new ButtplugClient("ws://localhost:12345");
await client.connect();
const engine = new PatternEngine(client);
const id = await engine.play(device, "wave");
await engine.stop(id);Setup
Pass a connected ButtplugClient directly to the constructor. The optional defaultTimeout controls the safety auto-stop duration (defaults to 30 minutes).
const engine = new PatternEngine(client, {
defaultTimeout: 600_000, // 10 minutes
});The engine subscribes to disconnected and deviceRemoved events on the client. When either fires, all affected patterns stop automatically. Call engine.dispose() when you no longer need the engine to clean up event subscriptions.
Playing Patterns
play() accepts three forms. The first argument is always a Device or device index (number).
Preset name -- pass a string from the 7 built-in presets:
await engine.play(device, "pulse", { intensity: 0.7 });Custom tracks -- pass an array of Track objects with keyframe sequences:
await engine.play(device, tracks, { loop: true });Full descriptor -- pass a PatternDescriptor object for complete control. This form is useful when descriptors are stored as data (e.g., loaded from JSON).
Every call returns a unique pattern ID string. Starting a new pattern on a device that already has one running auto-stops the existing pattern first.
Stopping Patterns
Three methods cover different granularities:
stop(patternId)-- stops one specific patternstopByDevice(deviceIndex)-- stops all patterns on a device, returns the countstopAll()-- stops everything, returns the count
Lifecycle
The engine handles cleanup automatically in several scenarios. Client disconnect stops all patterns with reason "disconnect". A device removal stops patterns targeting that device with reason "deviceRemoved". The safety timeout stops long-running patterns with reason "timeout".
The default safety timeout is 30 minutes. Any pattern running longer than this is automatically stopped. Override it per-engine via defaultTimeout or per-pattern via the timeout option. Set timeout: 0 to disable the safety limit entirely -- use this with caution.
Use list() to inspect all active patterns at any time. It returns an array of PatternInfo snapshots with elapsed time, device index, and descriptor metadata.
For the full API surface, see the PatternEngine reference.