@zendrex/buttplug.js 0.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +21 -0
- package/README.md +162 -0
- package/dist/index.cjs +3176 -0
- package/dist/index.d.cts +1752 -0
- package/dist/index.d.ts +1752 -0
- package/dist/index.js +3084 -0
- package/package.json +55 -0
package/dist/index.d.cts
ADDED
|
@@ -0,0 +1,1752 @@
|
|
|
1
|
+
import { z } from 'zod';
|
|
2
|
+
import Emittery from 'emittery';
|
|
3
|
+
|
|
4
|
+
/** Supported output actuator types in the Buttplug v4 protocol. */
|
|
5
|
+
declare const OUTPUT_TYPE_VALUES: readonly ["Vibrate", "Rotate", "RotateWithDirection", "Oscillate", "Constrict", "Spray", "Temperature", "Led", "Position", "HwPositionWithDuration"];
|
|
6
|
+
declare const OutputTypeSchema: z.ZodEnum<{
|
|
7
|
+
Vibrate: "Vibrate";
|
|
8
|
+
Rotate: "Rotate";
|
|
9
|
+
RotateWithDirection: "RotateWithDirection";
|
|
10
|
+
Oscillate: "Oscillate";
|
|
11
|
+
Constrict: "Constrict";
|
|
12
|
+
Spray: "Spray";
|
|
13
|
+
Temperature: "Temperature";
|
|
14
|
+
Led: "Led";
|
|
15
|
+
Position: "Position";
|
|
16
|
+
HwPositionWithDuration: "HwPositionWithDuration";
|
|
17
|
+
}>;
|
|
18
|
+
type OutputType = z.infer<typeof OutputTypeSchema>;
|
|
19
|
+
/** Supported input sensor types in the Buttplug v4 protocol. */
|
|
20
|
+
declare const INPUT_TYPE_VALUES: readonly ["Battery", "RSSI", "Pressure", "Button", "Position"];
|
|
21
|
+
declare const InputTypeSchema: z.ZodEnum<{
|
|
22
|
+
Position: "Position";
|
|
23
|
+
Battery: "Battery";
|
|
24
|
+
RSSI: "RSSI";
|
|
25
|
+
Pressure: "Pressure";
|
|
26
|
+
Button: "Button";
|
|
27
|
+
}>;
|
|
28
|
+
type InputType = z.infer<typeof InputTypeSchema>;
|
|
29
|
+
declare const InputCommandTypeSchema: z.ZodEnum<{
|
|
30
|
+
Read: "Read";
|
|
31
|
+
Subscribe: "Subscribe";
|
|
32
|
+
Unsubscribe: "Unsubscribe";
|
|
33
|
+
}>;
|
|
34
|
+
/** Input command operation: one-shot read, subscribe for updates, or unsubscribe. */
|
|
35
|
+
type InputCommandType = z.infer<typeof InputCommandTypeSchema>;
|
|
36
|
+
/**
|
|
37
|
+
* Unsigned scalar output command data wrapped in a `{Value}` object.
|
|
38
|
+
*
|
|
39
|
+
* Intiface Central expects `{"Vibrate": {"Value": 15}}`, not bare integers.
|
|
40
|
+
*/
|
|
41
|
+
declare const UnsignedScalarOutputDataSchema: z.ZodObject<{
|
|
42
|
+
Value: z.ZodNumber;
|
|
43
|
+
}, z.core.$strip>;
|
|
44
|
+
type UnsignedScalarOutputData = z.infer<typeof UnsignedScalarOutputDataSchema>;
|
|
45
|
+
/**
|
|
46
|
+
* Signed scalar output command data wrapped in a `{Value}` object.
|
|
47
|
+
*
|
|
48
|
+
* Used by Temperature (positive = heat, negative = cool).
|
|
49
|
+
*/
|
|
50
|
+
declare const SignedScalarOutputDataSchema: z.ZodObject<{
|
|
51
|
+
Value: z.ZodNumber;
|
|
52
|
+
}, z.core.$strip>;
|
|
53
|
+
type SignedScalarOutputData = z.infer<typeof SignedScalarOutputDataSchema>;
|
|
54
|
+
/** Alias for {@link UnsignedScalarOutputData}, used by most output types. */
|
|
55
|
+
type ScalarOutputData = UnsignedScalarOutputData;
|
|
56
|
+
/** Rotation output with explicit direction control. */
|
|
57
|
+
declare const RotateWithDirectionOutputDataSchema: z.ZodObject<{
|
|
58
|
+
Value: z.ZodNumber;
|
|
59
|
+
Clockwise: z.ZodBoolean;
|
|
60
|
+
}, z.core.$strip>;
|
|
61
|
+
type RotateWithDirectionOutputData = z.infer<typeof RotateWithDirectionOutputDataSchema>;
|
|
62
|
+
/**
|
|
63
|
+
* Hardware position output with duration for timed movements.
|
|
64
|
+
*
|
|
65
|
+
* Spec section: HwPositionWithDuration uses `Position` (not `Value`) and `Duration`.
|
|
66
|
+
*/
|
|
67
|
+
declare const HwPositionOutputDataSchema: z.ZodObject<{
|
|
68
|
+
Position: z.ZodNumber;
|
|
69
|
+
Duration: z.ZodNumber;
|
|
70
|
+
}, z.core.$strip>;
|
|
71
|
+
type HwPositionOutputData = z.infer<typeof HwPositionOutputDataSchema>;
|
|
72
|
+
/**
|
|
73
|
+
* Tagged output command union discriminated by actuator type key.
|
|
74
|
+
*
|
|
75
|
+
* Each variant is a single-key object mapping the output type name to its data shape.
|
|
76
|
+
*/
|
|
77
|
+
declare const OutputCommandSchema: z.ZodUnion<readonly [z.ZodObject<{
|
|
78
|
+
Vibrate: z.ZodObject<{
|
|
79
|
+
Value: z.ZodNumber;
|
|
80
|
+
}, z.core.$strip>;
|
|
81
|
+
}, z.core.$strict>, z.ZodObject<{
|
|
82
|
+
Rotate: z.ZodObject<{
|
|
83
|
+
Value: z.ZodNumber;
|
|
84
|
+
}, z.core.$strip>;
|
|
85
|
+
}, z.core.$strict>, z.ZodObject<{
|
|
86
|
+
RotateWithDirection: z.ZodObject<{
|
|
87
|
+
Value: z.ZodNumber;
|
|
88
|
+
Clockwise: z.ZodBoolean;
|
|
89
|
+
}, z.core.$strip>;
|
|
90
|
+
}, z.core.$strict>, z.ZodObject<{
|
|
91
|
+
Oscillate: z.ZodObject<{
|
|
92
|
+
Value: z.ZodNumber;
|
|
93
|
+
}, z.core.$strip>;
|
|
94
|
+
}, z.core.$strict>, z.ZodObject<{
|
|
95
|
+
Constrict: z.ZodObject<{
|
|
96
|
+
Value: z.ZodNumber;
|
|
97
|
+
}, z.core.$strip>;
|
|
98
|
+
}, z.core.$strict>, z.ZodObject<{
|
|
99
|
+
Spray: z.ZodObject<{
|
|
100
|
+
Value: z.ZodNumber;
|
|
101
|
+
}, z.core.$strip>;
|
|
102
|
+
}, z.core.$strict>, z.ZodObject<{
|
|
103
|
+
Temperature: z.ZodObject<{
|
|
104
|
+
Value: z.ZodNumber;
|
|
105
|
+
}, z.core.$strip>;
|
|
106
|
+
}, z.core.$strict>, z.ZodObject<{
|
|
107
|
+
Led: z.ZodObject<{
|
|
108
|
+
Value: z.ZodNumber;
|
|
109
|
+
}, z.core.$strip>;
|
|
110
|
+
}, z.core.$strict>, z.ZodObject<{
|
|
111
|
+
Position: z.ZodObject<{
|
|
112
|
+
Value: z.ZodNumber;
|
|
113
|
+
}, z.core.$strip>;
|
|
114
|
+
}, z.core.$strict>, z.ZodObject<{
|
|
115
|
+
HwPositionWithDuration: z.ZodObject<{
|
|
116
|
+
Position: z.ZodNumber;
|
|
117
|
+
Duration: z.ZodNumber;
|
|
118
|
+
}, z.core.$strip>;
|
|
119
|
+
}, z.core.$strict>]>;
|
|
120
|
+
type OutputCommand = z.infer<typeof OutputCommandSchema>;
|
|
121
|
+
/**
|
|
122
|
+
* Tagged union of all client messages.
|
|
123
|
+
*
|
|
124
|
+
* Each variant is a single-key object wrapping the specific message schema.
|
|
125
|
+
*/
|
|
126
|
+
declare const ClientMessageSchema: z.ZodUnion<readonly [z.ZodObject<{
|
|
127
|
+
RequestServerInfo: z.ZodObject<{
|
|
128
|
+
Id: z.ZodNumber;
|
|
129
|
+
ClientName: z.ZodString;
|
|
130
|
+
ProtocolVersionMajor: z.ZodNumber;
|
|
131
|
+
ProtocolVersionMinor: z.ZodNumber;
|
|
132
|
+
}, z.core.$strip>;
|
|
133
|
+
}, z.core.$strict>, z.ZodObject<{
|
|
134
|
+
StartScanning: z.ZodObject<{
|
|
135
|
+
Id: z.ZodNumber;
|
|
136
|
+
}, z.core.$strip>;
|
|
137
|
+
}, z.core.$strict>, z.ZodObject<{
|
|
138
|
+
StopScanning: z.ZodObject<{
|
|
139
|
+
Id: z.ZodNumber;
|
|
140
|
+
}, z.core.$strip>;
|
|
141
|
+
}, z.core.$strict>, z.ZodObject<{
|
|
142
|
+
RequestDeviceList: z.ZodObject<{
|
|
143
|
+
Id: z.ZodNumber;
|
|
144
|
+
}, z.core.$strip>;
|
|
145
|
+
}, z.core.$strict>, z.ZodObject<{
|
|
146
|
+
Ping: z.ZodObject<{
|
|
147
|
+
Id: z.ZodNumber;
|
|
148
|
+
}, z.core.$strip>;
|
|
149
|
+
}, z.core.$strict>, z.ZodObject<{
|
|
150
|
+
Disconnect: z.ZodObject<{
|
|
151
|
+
Id: z.ZodNumber;
|
|
152
|
+
}, z.core.$strip>;
|
|
153
|
+
}, z.core.$strict>, z.ZodObject<{
|
|
154
|
+
StopCmd: z.ZodObject<{
|
|
155
|
+
Id: z.ZodNumber;
|
|
156
|
+
DeviceIndex: z.ZodOptional<z.ZodNumber>;
|
|
157
|
+
FeatureIndex: z.ZodOptional<z.ZodNumber>;
|
|
158
|
+
Inputs: z.ZodOptional<z.ZodBoolean>;
|
|
159
|
+
Outputs: z.ZodOptional<z.ZodBoolean>;
|
|
160
|
+
}, z.core.$strip>;
|
|
161
|
+
}, z.core.$strict>, z.ZodObject<{
|
|
162
|
+
OutputCmd: z.ZodObject<{
|
|
163
|
+
Id: z.ZodNumber;
|
|
164
|
+
DeviceIndex: z.ZodNumber;
|
|
165
|
+
FeatureIndex: z.ZodNumber;
|
|
166
|
+
Command: z.ZodUnion<readonly [z.ZodObject<{
|
|
167
|
+
Vibrate: z.ZodObject<{
|
|
168
|
+
Value: z.ZodNumber;
|
|
169
|
+
}, z.core.$strip>;
|
|
170
|
+
}, z.core.$strict>, z.ZodObject<{
|
|
171
|
+
Rotate: z.ZodObject<{
|
|
172
|
+
Value: z.ZodNumber;
|
|
173
|
+
}, z.core.$strip>;
|
|
174
|
+
}, z.core.$strict>, z.ZodObject<{
|
|
175
|
+
RotateWithDirection: z.ZodObject<{
|
|
176
|
+
Value: z.ZodNumber;
|
|
177
|
+
Clockwise: z.ZodBoolean;
|
|
178
|
+
}, z.core.$strip>;
|
|
179
|
+
}, z.core.$strict>, z.ZodObject<{
|
|
180
|
+
Oscillate: z.ZodObject<{
|
|
181
|
+
Value: z.ZodNumber;
|
|
182
|
+
}, z.core.$strip>;
|
|
183
|
+
}, z.core.$strict>, z.ZodObject<{
|
|
184
|
+
Constrict: z.ZodObject<{
|
|
185
|
+
Value: z.ZodNumber;
|
|
186
|
+
}, z.core.$strip>;
|
|
187
|
+
}, z.core.$strict>, z.ZodObject<{
|
|
188
|
+
Spray: z.ZodObject<{
|
|
189
|
+
Value: z.ZodNumber;
|
|
190
|
+
}, z.core.$strip>;
|
|
191
|
+
}, z.core.$strict>, z.ZodObject<{
|
|
192
|
+
Temperature: z.ZodObject<{
|
|
193
|
+
Value: z.ZodNumber;
|
|
194
|
+
}, z.core.$strip>;
|
|
195
|
+
}, z.core.$strict>, z.ZodObject<{
|
|
196
|
+
Led: z.ZodObject<{
|
|
197
|
+
Value: z.ZodNumber;
|
|
198
|
+
}, z.core.$strip>;
|
|
199
|
+
}, z.core.$strict>, z.ZodObject<{
|
|
200
|
+
Position: z.ZodObject<{
|
|
201
|
+
Value: z.ZodNumber;
|
|
202
|
+
}, z.core.$strip>;
|
|
203
|
+
}, z.core.$strict>, z.ZodObject<{
|
|
204
|
+
HwPositionWithDuration: z.ZodObject<{
|
|
205
|
+
Position: z.ZodNumber;
|
|
206
|
+
Duration: z.ZodNumber;
|
|
207
|
+
}, z.core.$strip>;
|
|
208
|
+
}, z.core.$strict>]>;
|
|
209
|
+
}, z.core.$strip>;
|
|
210
|
+
}, z.core.$strict>, z.ZodObject<{
|
|
211
|
+
InputCmd: z.ZodObject<{
|
|
212
|
+
Id: z.ZodNumber;
|
|
213
|
+
DeviceIndex: z.ZodNumber;
|
|
214
|
+
FeatureIndex: z.ZodNumber;
|
|
215
|
+
Type: z.ZodEnum<{
|
|
216
|
+
Position: "Position";
|
|
217
|
+
Battery: "Battery";
|
|
218
|
+
RSSI: "RSSI";
|
|
219
|
+
Pressure: "Pressure";
|
|
220
|
+
Button: "Button";
|
|
221
|
+
}>;
|
|
222
|
+
Command: z.ZodEnum<{
|
|
223
|
+
Read: "Read";
|
|
224
|
+
Subscribe: "Subscribe";
|
|
225
|
+
Unsubscribe: "Unsubscribe";
|
|
226
|
+
}>;
|
|
227
|
+
}, z.core.$strip>;
|
|
228
|
+
}, z.core.$strict>]>;
|
|
229
|
+
type ClientMessage = z.infer<typeof ClientMessageSchema>;
|
|
230
|
+
/** Handshake response from the server with capabilities and timing requirements. */
|
|
231
|
+
declare const ServerInfoSchema: z.ZodObject<{
|
|
232
|
+
Id: z.ZodNumber;
|
|
233
|
+
ServerName: z.ZodOptional<z.ZodNullable<z.ZodString>>;
|
|
234
|
+
ProtocolVersionMajor: z.ZodNumber;
|
|
235
|
+
ProtocolVersionMinor: z.ZodNumber;
|
|
236
|
+
MaxPingTime: z.ZodNumber;
|
|
237
|
+
}, z.core.$strip>;
|
|
238
|
+
type ServerInfo = z.infer<typeof ServerInfoSchema>;
|
|
239
|
+
/**
|
|
240
|
+
* Sensor reading value from a device.
|
|
241
|
+
*
|
|
242
|
+
* Intiface Central wraps sensor values in a `{Value}` object,
|
|
243
|
+
* e.g. `{"Battery": {"Value": 90}}`.
|
|
244
|
+
*/
|
|
245
|
+
declare const SensorValueSchema: z.ZodObject<{
|
|
246
|
+
Value: z.ZodNumber;
|
|
247
|
+
}, z.core.$strip>;
|
|
248
|
+
type SensorValue = z.infer<typeof SensorValueSchema>;
|
|
249
|
+
/**
|
|
250
|
+
* Tagged sensor data union discriminated by sensor type key.
|
|
251
|
+
*
|
|
252
|
+
* Each variant maps a sensor type name to its {@link SensorValue}.
|
|
253
|
+
*/
|
|
254
|
+
declare const InputDataSchema: z.ZodUnion<readonly [z.ZodObject<{
|
|
255
|
+
Battery: z.ZodObject<{
|
|
256
|
+
Value: z.ZodNumber;
|
|
257
|
+
}, z.core.$strip>;
|
|
258
|
+
}, z.core.$strict>, z.ZodObject<{
|
|
259
|
+
RSSI: z.ZodObject<{
|
|
260
|
+
Value: z.ZodNumber;
|
|
261
|
+
}, z.core.$strip>;
|
|
262
|
+
}, z.core.$strict>, z.ZodObject<{
|
|
263
|
+
Pressure: z.ZodObject<{
|
|
264
|
+
Value: z.ZodNumber;
|
|
265
|
+
}, z.core.$strip>;
|
|
266
|
+
}, z.core.$strict>, z.ZodObject<{
|
|
267
|
+
Button: z.ZodObject<{
|
|
268
|
+
Value: z.ZodNumber;
|
|
269
|
+
}, z.core.$strip>;
|
|
270
|
+
}, z.core.$strict>, z.ZodObject<{
|
|
271
|
+
Position: z.ZodObject<{
|
|
272
|
+
Value: z.ZodNumber;
|
|
273
|
+
}, z.core.$strip>;
|
|
274
|
+
}, z.core.$strict>]>;
|
|
275
|
+
type InputData = z.infer<typeof InputDataSchema>;
|
|
276
|
+
/** Server message delivering a sensor reading from a device. */
|
|
277
|
+
declare const InputReadingSchema: z.ZodObject<{
|
|
278
|
+
Id: z.ZodNumber;
|
|
279
|
+
DeviceIndex: z.ZodNumber;
|
|
280
|
+
FeatureIndex: z.ZodNumber;
|
|
281
|
+
Reading: z.ZodUnion<readonly [z.ZodObject<{
|
|
282
|
+
Battery: z.ZodObject<{
|
|
283
|
+
Value: z.ZodNumber;
|
|
284
|
+
}, z.core.$strip>;
|
|
285
|
+
}, z.core.$strict>, z.ZodObject<{
|
|
286
|
+
RSSI: z.ZodObject<{
|
|
287
|
+
Value: z.ZodNumber;
|
|
288
|
+
}, z.core.$strip>;
|
|
289
|
+
}, z.core.$strict>, z.ZodObject<{
|
|
290
|
+
Pressure: z.ZodObject<{
|
|
291
|
+
Value: z.ZodNumber;
|
|
292
|
+
}, z.core.$strip>;
|
|
293
|
+
}, z.core.$strict>, z.ZodObject<{
|
|
294
|
+
Button: z.ZodObject<{
|
|
295
|
+
Value: z.ZodNumber;
|
|
296
|
+
}, z.core.$strip>;
|
|
297
|
+
}, z.core.$strict>, z.ZodObject<{
|
|
298
|
+
Position: z.ZodObject<{
|
|
299
|
+
Value: z.ZodNumber;
|
|
300
|
+
}, z.core.$strip>;
|
|
301
|
+
}, z.core.$strict>]>;
|
|
302
|
+
}, z.core.$strip>;
|
|
303
|
+
type InputReading = z.infer<typeof InputReadingSchema>;
|
|
304
|
+
/** Raw device descriptor as reported by the server, before normalization. */
|
|
305
|
+
declare const RawDeviceSchema: z.ZodObject<{
|
|
306
|
+
DeviceName: z.ZodString;
|
|
307
|
+
DeviceIndex: z.ZodNumber;
|
|
308
|
+
DeviceMessageTimingGap: z.ZodNumber;
|
|
309
|
+
DeviceDisplayName: z.ZodOptional<z.ZodNullable<z.ZodString>>;
|
|
310
|
+
DeviceFeatures: z.ZodRecord<z.ZodString, z.ZodObject<{
|
|
311
|
+
FeatureIndex: z.ZodNumber;
|
|
312
|
+
FeatureDescription: z.ZodString;
|
|
313
|
+
Output: z.ZodOptional<z.ZodNullable<z.ZodRecord<z.ZodString, z.ZodObject<{
|
|
314
|
+
Value: z.ZodTuple<[z.ZodNumber, z.ZodNumber], null>;
|
|
315
|
+
Duration: z.ZodOptional<z.ZodTuple<[z.ZodNumber, z.ZodNumber], null>>;
|
|
316
|
+
}, z.core.$strip>>>>;
|
|
317
|
+
Input: z.ZodOptional<z.ZodNullable<z.ZodRecord<z.ZodString, z.ZodObject<{
|
|
318
|
+
Command: z.ZodArray<z.ZodEnum<{
|
|
319
|
+
Read: "Read";
|
|
320
|
+
Subscribe: "Subscribe";
|
|
321
|
+
Unsubscribe: "Unsubscribe";
|
|
322
|
+
}>>;
|
|
323
|
+
Value: z.ZodArray<z.ZodTuple<[z.ZodNumber, z.ZodNumber], null>>;
|
|
324
|
+
}, z.core.$strip>>>>;
|
|
325
|
+
}, z.core.$strip>>;
|
|
326
|
+
}, z.core.$strip>;
|
|
327
|
+
type RawDevice = z.infer<typeof RawDeviceSchema>;
|
|
328
|
+
/**
|
|
329
|
+
* Tagged union of all server messages.
|
|
330
|
+
*
|
|
331
|
+
* Each variant is a single-key object wrapping the specific message schema.
|
|
332
|
+
*/
|
|
333
|
+
declare const ServerMessageSchema: z.ZodUnion<readonly [z.ZodObject<{
|
|
334
|
+
ServerInfo: z.ZodObject<{
|
|
335
|
+
Id: z.ZodNumber;
|
|
336
|
+
ServerName: z.ZodOptional<z.ZodNullable<z.ZodString>>;
|
|
337
|
+
ProtocolVersionMajor: z.ZodNumber;
|
|
338
|
+
ProtocolVersionMinor: z.ZodNumber;
|
|
339
|
+
MaxPingTime: z.ZodNumber;
|
|
340
|
+
}, z.core.$strip>;
|
|
341
|
+
}, z.core.$strict>, z.ZodObject<{
|
|
342
|
+
Ok: z.ZodObject<{
|
|
343
|
+
Id: z.ZodNumber;
|
|
344
|
+
}, z.core.$strip>;
|
|
345
|
+
}, z.core.$strict>, z.ZodObject<{
|
|
346
|
+
Error: z.ZodObject<{
|
|
347
|
+
Id: z.ZodNumber;
|
|
348
|
+
ErrorCode: z.ZodEnum<{
|
|
349
|
+
readonly UNKNOWN: 0;
|
|
350
|
+
readonly INIT: 1;
|
|
351
|
+
readonly PING: 2;
|
|
352
|
+
readonly MESSAGE: 3;
|
|
353
|
+
readonly DEVICE: 4;
|
|
354
|
+
}>;
|
|
355
|
+
ErrorMessage: z.ZodString;
|
|
356
|
+
}, z.core.$strip>;
|
|
357
|
+
}, z.core.$strict>, z.ZodObject<{
|
|
358
|
+
DeviceList: z.ZodObject<{
|
|
359
|
+
Id: z.ZodNumber;
|
|
360
|
+
Devices: z.ZodRecord<z.ZodString, z.ZodObject<{
|
|
361
|
+
DeviceName: z.ZodString;
|
|
362
|
+
DeviceIndex: z.ZodNumber;
|
|
363
|
+
DeviceMessageTimingGap: z.ZodNumber;
|
|
364
|
+
DeviceDisplayName: z.ZodOptional<z.ZodNullable<z.ZodString>>;
|
|
365
|
+
DeviceFeatures: z.ZodRecord<z.ZodString, z.ZodObject<{
|
|
366
|
+
FeatureIndex: z.ZodNumber;
|
|
367
|
+
FeatureDescription: z.ZodString;
|
|
368
|
+
Output: z.ZodOptional<z.ZodNullable<z.ZodRecord<z.ZodString, z.ZodObject<{
|
|
369
|
+
Value: z.ZodTuple<[z.ZodNumber, z.ZodNumber], null>;
|
|
370
|
+
Duration: z.ZodOptional<z.ZodTuple<[z.ZodNumber, z.ZodNumber], null>>;
|
|
371
|
+
}, z.core.$strip>>>>;
|
|
372
|
+
Input: z.ZodOptional<z.ZodNullable<z.ZodRecord<z.ZodString, z.ZodObject<{
|
|
373
|
+
Command: z.ZodArray<z.ZodEnum<{
|
|
374
|
+
Read: "Read";
|
|
375
|
+
Subscribe: "Subscribe";
|
|
376
|
+
Unsubscribe: "Unsubscribe";
|
|
377
|
+
}>>;
|
|
378
|
+
Value: z.ZodArray<z.ZodTuple<[z.ZodNumber, z.ZodNumber], null>>;
|
|
379
|
+
}, z.core.$strip>>>>;
|
|
380
|
+
}, z.core.$strip>>;
|
|
381
|
+
}, z.core.$strip>>;
|
|
382
|
+
}, z.core.$strip>;
|
|
383
|
+
}, z.core.$strict>, z.ZodObject<{
|
|
384
|
+
ScanningFinished: z.ZodObject<{
|
|
385
|
+
Id: z.ZodNumber;
|
|
386
|
+
}, z.core.$strip>;
|
|
387
|
+
}, z.core.$strict>, z.ZodObject<{
|
|
388
|
+
InputReading: z.ZodObject<{
|
|
389
|
+
Id: z.ZodNumber;
|
|
390
|
+
DeviceIndex: z.ZodNumber;
|
|
391
|
+
FeatureIndex: z.ZodNumber;
|
|
392
|
+
Reading: z.ZodUnion<readonly [z.ZodObject<{
|
|
393
|
+
Battery: z.ZodObject<{
|
|
394
|
+
Value: z.ZodNumber;
|
|
395
|
+
}, z.core.$strip>;
|
|
396
|
+
}, z.core.$strict>, z.ZodObject<{
|
|
397
|
+
RSSI: z.ZodObject<{
|
|
398
|
+
Value: z.ZodNumber;
|
|
399
|
+
}, z.core.$strip>;
|
|
400
|
+
}, z.core.$strict>, z.ZodObject<{
|
|
401
|
+
Pressure: z.ZodObject<{
|
|
402
|
+
Value: z.ZodNumber;
|
|
403
|
+
}, z.core.$strip>;
|
|
404
|
+
}, z.core.$strict>, z.ZodObject<{
|
|
405
|
+
Button: z.ZodObject<{
|
|
406
|
+
Value: z.ZodNumber;
|
|
407
|
+
}, z.core.$strip>;
|
|
408
|
+
}, z.core.$strict>, z.ZodObject<{
|
|
409
|
+
Position: z.ZodObject<{
|
|
410
|
+
Value: z.ZodNumber;
|
|
411
|
+
}, z.core.$strip>;
|
|
412
|
+
}, z.core.$strict>]>;
|
|
413
|
+
}, z.core.$strip>;
|
|
414
|
+
}, z.core.$strict>]>;
|
|
415
|
+
type ServerMessage = z.infer<typeof ServerMessageSchema>;
|
|
416
|
+
/** Normalized output feature descriptor with type, index, and capabilities. */
|
|
417
|
+
declare const OutputFeatureSchema: z.ZodObject<{
|
|
418
|
+
type: z.ZodEnum<{
|
|
419
|
+
Vibrate: "Vibrate";
|
|
420
|
+
Rotate: "Rotate";
|
|
421
|
+
RotateWithDirection: "RotateWithDirection";
|
|
422
|
+
Oscillate: "Oscillate";
|
|
423
|
+
Constrict: "Constrict";
|
|
424
|
+
Spray: "Spray";
|
|
425
|
+
Temperature: "Temperature";
|
|
426
|
+
Led: "Led";
|
|
427
|
+
Position: "Position";
|
|
428
|
+
HwPositionWithDuration: "HwPositionWithDuration";
|
|
429
|
+
}>;
|
|
430
|
+
index: z.ZodNumber;
|
|
431
|
+
description: z.ZodString;
|
|
432
|
+
range: z.ZodTuple<[z.ZodNumber, z.ZodNumber], null>;
|
|
433
|
+
durationRange: z.ZodOptional<z.ZodTuple<[z.ZodNumber, z.ZodNumber], null>>;
|
|
434
|
+
}, z.core.$strip>;
|
|
435
|
+
type OutputFeature = z.infer<typeof OutputFeatureSchema>;
|
|
436
|
+
/**
|
|
437
|
+
* Normalized input feature descriptor with type, index, and command capabilities.
|
|
438
|
+
*
|
|
439
|
+
* Spec section: Input Capability Object — Value is a single `[min, max]` range.
|
|
440
|
+
*/
|
|
441
|
+
declare const InputFeatureSchema: z.ZodObject<{
|
|
442
|
+
type: z.ZodEnum<{
|
|
443
|
+
Position: "Position";
|
|
444
|
+
Battery: "Battery";
|
|
445
|
+
RSSI: "RSSI";
|
|
446
|
+
Pressure: "Pressure";
|
|
447
|
+
Button: "Button";
|
|
448
|
+
}>;
|
|
449
|
+
index: z.ZodNumber;
|
|
450
|
+
description: z.ZodString;
|
|
451
|
+
range: z.ZodTuple<[z.ZodNumber, z.ZodNumber], null>;
|
|
452
|
+
canRead: z.ZodBoolean;
|
|
453
|
+
canSubscribe: z.ZodBoolean;
|
|
454
|
+
}, z.core.$strip>;
|
|
455
|
+
type InputFeature = z.infer<typeof InputFeatureSchema>;
|
|
456
|
+
/** Collection of normalized input and output features for a device. */
|
|
457
|
+
declare const DeviceFeaturesSchema: z.ZodObject<{
|
|
458
|
+
outputs: z.ZodArray<z.ZodObject<{
|
|
459
|
+
type: z.ZodEnum<{
|
|
460
|
+
Vibrate: "Vibrate";
|
|
461
|
+
Rotate: "Rotate";
|
|
462
|
+
RotateWithDirection: "RotateWithDirection";
|
|
463
|
+
Oscillate: "Oscillate";
|
|
464
|
+
Constrict: "Constrict";
|
|
465
|
+
Spray: "Spray";
|
|
466
|
+
Temperature: "Temperature";
|
|
467
|
+
Led: "Led";
|
|
468
|
+
Position: "Position";
|
|
469
|
+
HwPositionWithDuration: "HwPositionWithDuration";
|
|
470
|
+
}>;
|
|
471
|
+
index: z.ZodNumber;
|
|
472
|
+
description: z.ZodString;
|
|
473
|
+
range: z.ZodTuple<[z.ZodNumber, z.ZodNumber], null>;
|
|
474
|
+
durationRange: z.ZodOptional<z.ZodTuple<[z.ZodNumber, z.ZodNumber], null>>;
|
|
475
|
+
}, z.core.$strip>>;
|
|
476
|
+
inputs: z.ZodArray<z.ZodObject<{
|
|
477
|
+
type: z.ZodEnum<{
|
|
478
|
+
Position: "Position";
|
|
479
|
+
Battery: "Battery";
|
|
480
|
+
RSSI: "RSSI";
|
|
481
|
+
Pressure: "Pressure";
|
|
482
|
+
Button: "Button";
|
|
483
|
+
}>;
|
|
484
|
+
index: z.ZodNumber;
|
|
485
|
+
description: z.ZodString;
|
|
486
|
+
range: z.ZodTuple<[z.ZodNumber, z.ZodNumber], null>;
|
|
487
|
+
canRead: z.ZodBoolean;
|
|
488
|
+
canSubscribe: z.ZodBoolean;
|
|
489
|
+
}, z.core.$strip>>;
|
|
490
|
+
}, z.core.$strip>;
|
|
491
|
+
type DeviceFeatures = z.infer<typeof DeviceFeaturesSchema>;
|
|
492
|
+
declare const FeatureValueSchema: z.ZodObject<{
|
|
493
|
+
index: z.ZodNumber;
|
|
494
|
+
value: z.ZodNumber;
|
|
495
|
+
}, z.core.$strip>;
|
|
496
|
+
/** Feature index paired with a scalar value, used for batch output commands. */
|
|
497
|
+
type FeatureValue = z.infer<typeof FeatureValueSchema>;
|
|
498
|
+
/** Feature index paired with speed and direction for rotation commands. */
|
|
499
|
+
declare const RotationValueSchema: z.ZodObject<{
|
|
500
|
+
index: z.ZodNumber;
|
|
501
|
+
speed: z.ZodNumber;
|
|
502
|
+
clockwise: z.ZodBoolean;
|
|
503
|
+
}, z.core.$strip>;
|
|
504
|
+
type RotationValue = z.infer<typeof RotationValueSchema>;
|
|
505
|
+
/** Feature index paired with position and duration for timed movement commands. */
|
|
506
|
+
declare const PositionValueSchema: z.ZodObject<{
|
|
507
|
+
index: z.ZodNumber;
|
|
508
|
+
position: z.ZodNumber;
|
|
509
|
+
duration: z.ZodNumber;
|
|
510
|
+
}, z.core.$strip>;
|
|
511
|
+
type PositionValue = z.infer<typeof PositionValueSchema>;
|
|
512
|
+
|
|
513
|
+
/** Callback invoked when a sensor subscription delivers a new reading. */
|
|
514
|
+
type SensorCallback = (value: number) => void;
|
|
515
|
+
/**
|
|
516
|
+
* Interface for sending protocol messages and managing sensor subscriptions.
|
|
517
|
+
*
|
|
518
|
+
* Implemented by the client to provide the transport layer that
|
|
519
|
+
* {@link Device} instances use for communication with the server.
|
|
520
|
+
*/
|
|
521
|
+
interface DeviceMessageSender {
|
|
522
|
+
/**
|
|
523
|
+
* Allocates the next unique message ID for request/response correlation.
|
|
524
|
+
*
|
|
525
|
+
* @returns A monotonically increasing integer within the valid ID range
|
|
526
|
+
*/
|
|
527
|
+
nextId(): number;
|
|
528
|
+
/**
|
|
529
|
+
* Registers a callback to receive sensor readings for a specific subscription.
|
|
530
|
+
*
|
|
531
|
+
* @param key - Unique subscription key from {@link sensorKey}
|
|
532
|
+
* @param callback - Function invoked with each sensor value
|
|
533
|
+
* @param info - Metadata identifying the device, feature, and sensor type
|
|
534
|
+
*/
|
|
535
|
+
registerSensorSubscription(key: string, callback: SensorCallback, info: {
|
|
536
|
+
deviceIndex: number;
|
|
537
|
+
featureIndex: number;
|
|
538
|
+
type: InputType;
|
|
539
|
+
}): void;
|
|
540
|
+
/**
|
|
541
|
+
* Sends one or more client messages and waits for the server's responses.
|
|
542
|
+
*
|
|
543
|
+
* @param messages - A single message or array of messages to send
|
|
544
|
+
* @returns The server's response messages
|
|
545
|
+
*/
|
|
546
|
+
send(messages: ClientMessage | ClientMessage[]): Promise<ServerMessage[]>;
|
|
547
|
+
/**
|
|
548
|
+
* Removes a previously registered sensor subscription.
|
|
549
|
+
*
|
|
550
|
+
* @param key - The subscription key to unregister
|
|
551
|
+
*/
|
|
552
|
+
unregisterSensorSubscription(key: string): void;
|
|
553
|
+
}
|
|
554
|
+
|
|
555
|
+
/**
|
|
556
|
+
* Represents a single device connected to a Buttplug server.
|
|
557
|
+
*
|
|
558
|
+
* Provides typed methods for controlling outputs (vibration, rotation, position, etc.)
|
|
559
|
+
* and reading or subscribing to input sensors. Constructed internally by {@link ButtplugClient}
|
|
560
|
+
* when devices are discovered.
|
|
561
|
+
*/
|
|
562
|
+
declare class Device {
|
|
563
|
+
#private;
|
|
564
|
+
constructor(options: DeviceOptions);
|
|
565
|
+
/**
|
|
566
|
+
* Sets vibration intensity on all or individual motors.
|
|
567
|
+
*
|
|
568
|
+
* @param intensity - A single value for all motors, or per-motor {@link FeatureValue} entries
|
|
569
|
+
* @throws DeviceError if the device does not support vibration
|
|
570
|
+
*/
|
|
571
|
+
vibrate(intensity: number | FeatureValue[]): Promise<void>;
|
|
572
|
+
/**
|
|
573
|
+
* Sets oscillation speed on all or individual motors.
|
|
574
|
+
*
|
|
575
|
+
* @param speed - A single value for all motors, or per-motor {@link FeatureValue} entries
|
|
576
|
+
* @throws DeviceError if the device does not support oscillation
|
|
577
|
+
*/
|
|
578
|
+
oscillate(speed: number | FeatureValue[]): Promise<void>;
|
|
579
|
+
/**
|
|
580
|
+
* Sets constriction pressure on all or individual actuators.
|
|
581
|
+
*
|
|
582
|
+
* @param value - A single value for all actuators, or per-actuator {@link FeatureValue} entries
|
|
583
|
+
* @throws DeviceError if the device does not support constriction
|
|
584
|
+
*/
|
|
585
|
+
constrict(value: number | FeatureValue[]): Promise<void>;
|
|
586
|
+
/**
|
|
587
|
+
* Controls spray output on all or individual actuators.
|
|
588
|
+
*
|
|
589
|
+
* @param value - A single value for all actuators, or per-actuator {@link FeatureValue} entries
|
|
590
|
+
* @throws DeviceError if the device does not support spraying
|
|
591
|
+
*/
|
|
592
|
+
spray(value: number | FeatureValue[]): Promise<void>;
|
|
593
|
+
/**
|
|
594
|
+
* Sets temperature on all or individual actuators.
|
|
595
|
+
*
|
|
596
|
+
* @param value - A single value for all actuators, or per-actuator {@link FeatureValue} entries
|
|
597
|
+
* @throws DeviceError if the device does not support temperature control
|
|
598
|
+
*/
|
|
599
|
+
temperature(value: number | FeatureValue[]): Promise<void>;
|
|
600
|
+
/**
|
|
601
|
+
* Controls LED brightness on all or individual actuators.
|
|
602
|
+
*
|
|
603
|
+
* @param value - A single value for all actuators, or per-actuator {@link FeatureValue} entries
|
|
604
|
+
* @throws DeviceError if the device does not support LED control
|
|
605
|
+
*/
|
|
606
|
+
led(value: number | FeatureValue[]): Promise<void>;
|
|
607
|
+
/**
|
|
608
|
+
* Sets rotation speed on per-motor {@link RotationValue} entries with individual direction.
|
|
609
|
+
*
|
|
610
|
+
* @param values - Per-motor rotation entries with speed and direction
|
|
611
|
+
* @throws DeviceError if the device does not support rotation
|
|
612
|
+
*/
|
|
613
|
+
rotate(values: RotationValue[]): Promise<void>;
|
|
614
|
+
/**
|
|
615
|
+
* Sets rotation speed (and optionally direction) on all motors.
|
|
616
|
+
*
|
|
617
|
+
* Automatically selects `RotateWithDirection` if the device supports it,
|
|
618
|
+
* falling back to `Rotate` otherwise.
|
|
619
|
+
*
|
|
620
|
+
* @param speed - A single speed for all motors
|
|
621
|
+
* @param options - Direction options (defaults to clockwise)
|
|
622
|
+
* @throws DeviceError if the device does not support rotation
|
|
623
|
+
*/
|
|
624
|
+
rotate(speed: number, options?: {
|
|
625
|
+
clockwise?: boolean;
|
|
626
|
+
}): Promise<void>;
|
|
627
|
+
/**
|
|
628
|
+
* Moves per-axis {@link PositionValue} entries with individual durations.
|
|
629
|
+
*
|
|
630
|
+
* @param values - Per-axis position entries with position and duration
|
|
631
|
+
* @throws DeviceError if the device does not support position control
|
|
632
|
+
*/
|
|
633
|
+
position(values: PositionValue[]): Promise<void>;
|
|
634
|
+
/**
|
|
635
|
+
* Moves all axes to a uniform position over a given duration.
|
|
636
|
+
*
|
|
637
|
+
* Automatically selects `HwPositionWithDuration` if the device supports it,
|
|
638
|
+
* falling back to `Position` otherwise.
|
|
639
|
+
*
|
|
640
|
+
* @param position - A single position value for all axes
|
|
641
|
+
* @param options - Movement options including duration in milliseconds
|
|
642
|
+
* @throws DeviceError if the device does not support position control
|
|
643
|
+
*/
|
|
644
|
+
position(position: number, options: {
|
|
645
|
+
duration: number;
|
|
646
|
+
}): Promise<void>;
|
|
647
|
+
/**
|
|
648
|
+
* Stops activity on this device.
|
|
649
|
+
*
|
|
650
|
+
* Can target a specific feature index or filter by input/output type.
|
|
651
|
+
* Without options, stops all features.
|
|
652
|
+
*
|
|
653
|
+
* @param options - Optional filters for which features to stop
|
|
654
|
+
* @throws DeviceError if the specified feature index does not exist
|
|
655
|
+
*/
|
|
656
|
+
stop(options?: DeviceStopOptions): Promise<void>;
|
|
657
|
+
/**
|
|
658
|
+
* Sends a raw output command to a specific feature.
|
|
659
|
+
*
|
|
660
|
+
* Values are validated against the feature's declared range and clamped if out of bounds.
|
|
661
|
+
*
|
|
662
|
+
* @param options - The feature index and output command payload
|
|
663
|
+
* @throws DeviceError if no matching output feature exists at the given index
|
|
664
|
+
*/
|
|
665
|
+
output(options: DeviceOutputOptions): Promise<void>;
|
|
666
|
+
/**
|
|
667
|
+
* Performs a one-shot read of a sensor value.
|
|
668
|
+
*
|
|
669
|
+
* @param type - The sensor type to read (e.g. `"Battery"`, `"RSSI"`)
|
|
670
|
+
* @param sensorIndex - Index of the sensor if the device has multiple of the same type
|
|
671
|
+
* @returns The numeric sensor value
|
|
672
|
+
* @throws DeviceError if the sensor does not exist or does not support reading
|
|
673
|
+
*/
|
|
674
|
+
readSensor(type: InputType, sensorIndex?: number): Promise<number>;
|
|
675
|
+
/**
|
|
676
|
+
* Subscribes to continuous sensor readings.
|
|
677
|
+
*
|
|
678
|
+
* @param type - The sensor type to subscribe to
|
|
679
|
+
* @param callback - Invoked each time a new reading arrives
|
|
680
|
+
* @param sensorIndex - Index of the sensor if the device has multiple of the same type
|
|
681
|
+
* @returns An async unsubscribe function that stops the subscription
|
|
682
|
+
* @throws DeviceError if the sensor does not exist or does not support subscriptions
|
|
683
|
+
*/
|
|
684
|
+
subscribeSensor(type: InputType, callback: SensorCallback, sensorIndex?: number): Promise<() => Promise<void>>;
|
|
685
|
+
/**
|
|
686
|
+
* Explicitly unsubscribes from a sensor subscription by type and sensor index.
|
|
687
|
+
*
|
|
688
|
+
* @param type - The sensor type to unsubscribe from
|
|
689
|
+
* @param sensorIndex - Index of the sensor if the device has multiple of the same type
|
|
690
|
+
*/
|
|
691
|
+
unsubscribe(type: InputType, sensorIndex?: number): Promise<void>;
|
|
692
|
+
/**
|
|
693
|
+
* Checks whether this device supports a given output type.
|
|
694
|
+
*
|
|
695
|
+
* @param type - The output type to check
|
|
696
|
+
* @returns `true` if at least one feature supports the output type
|
|
697
|
+
*/
|
|
698
|
+
canOutput(type: OutputType): boolean;
|
|
699
|
+
/**
|
|
700
|
+
* Checks whether this device can perform a one-shot read of a given sensor type.
|
|
701
|
+
*
|
|
702
|
+
* @param type - The input type to check
|
|
703
|
+
* @returns `true` if at least one matching sensor supports reading
|
|
704
|
+
*/
|
|
705
|
+
canRead(type: InputType): boolean;
|
|
706
|
+
/**
|
|
707
|
+
* Checks whether this device supports subscriptions for a given sensor type.
|
|
708
|
+
*
|
|
709
|
+
* @param type - The input type to check
|
|
710
|
+
* @returns `true` if at least one matching sensor supports subscriptions
|
|
711
|
+
*/
|
|
712
|
+
canSubscribe(type: InputType): boolean;
|
|
713
|
+
/** Server-assigned device index. */
|
|
714
|
+
get index(): number;
|
|
715
|
+
/** Internal device name from firmware. */
|
|
716
|
+
get name(): string;
|
|
717
|
+
/** User-facing display name, or `null` if the server did not provide one. */
|
|
718
|
+
get displayName(): string | null;
|
|
719
|
+
/** Minimum interval in milliseconds between messages recommended by the server. */
|
|
720
|
+
get messageTimingGap(): number;
|
|
721
|
+
/** Parsed input and output feature descriptors for this device. */
|
|
722
|
+
get features(): DeviceFeatures;
|
|
723
|
+
/** Whether this device supports any form of rotation output. */
|
|
724
|
+
get canRotate(): boolean;
|
|
725
|
+
/** Whether this device supports any form of position output. */
|
|
726
|
+
get canPosition(): boolean;
|
|
727
|
+
}
|
|
728
|
+
|
|
729
|
+
/**
|
|
730
|
+
* Structured logging interface for Buttplug components.
|
|
731
|
+
*
|
|
732
|
+
* Supports hierarchical prefixes via {@link Logger.child} for scoped logging.
|
|
733
|
+
*/
|
|
734
|
+
interface Logger {
|
|
735
|
+
/**
|
|
736
|
+
* Creates a child logger with a nested prefix.
|
|
737
|
+
*
|
|
738
|
+
* @param prefix - Label appended to the parent prefix, separated by ':'
|
|
739
|
+
* @returns A new {@link Logger} with the combined prefix
|
|
740
|
+
*/
|
|
741
|
+
child(prefix: string): Logger;
|
|
742
|
+
/** Logs a debug-level message. */
|
|
743
|
+
debug(message: string): void;
|
|
744
|
+
/** Logs an error-level message. */
|
|
745
|
+
error(message: string): void;
|
|
746
|
+
/** Logs an info-level message. */
|
|
747
|
+
info(message: string): void;
|
|
748
|
+
/** Logs a warning-level message. */
|
|
749
|
+
warn(message: string): void;
|
|
750
|
+
}
|
|
751
|
+
/**
|
|
752
|
+
* A logger that silently discards all messages.
|
|
753
|
+
* Used as the default when no logging is configured.
|
|
754
|
+
*/
|
|
755
|
+
declare const noopLogger: Logger;
|
|
756
|
+
/** Default console logger prefixed with "buttplug". */
|
|
757
|
+
declare const consoleLogger: Logger;
|
|
758
|
+
|
|
759
|
+
/**
|
|
760
|
+
* Construction options for a {@link Device} instance.
|
|
761
|
+
*/
|
|
762
|
+
interface DeviceOptions {
|
|
763
|
+
/** The {@link DeviceMessageSender} used to route messages to the server. */
|
|
764
|
+
client: DeviceMessageSender;
|
|
765
|
+
/** Optional logger for device-level diagnostics. */
|
|
766
|
+
logger?: Logger;
|
|
767
|
+
/** Raw device descriptor received from the server during enumeration. */
|
|
768
|
+
raw: RawDevice;
|
|
769
|
+
}
|
|
770
|
+
/**
|
|
771
|
+
* Event map for the {@link ButtplugClient} emitter.
|
|
772
|
+
*
|
|
773
|
+
* Each key is an event name and its value is the payload type passed to listeners.
|
|
774
|
+
*/
|
|
775
|
+
interface ClientEventMap {
|
|
776
|
+
/** Emitted after a successful connection and handshake. */
|
|
777
|
+
connected: undefined;
|
|
778
|
+
/** Emitted when a new device is discovered. */
|
|
779
|
+
deviceAdded: {
|
|
780
|
+
device: Device;
|
|
781
|
+
};
|
|
782
|
+
/** Emitted with the full device list after a reconciliation pass. */
|
|
783
|
+
deviceList: {
|
|
784
|
+
devices: Device[];
|
|
785
|
+
};
|
|
786
|
+
/** Emitted when a previously known device is removed. */
|
|
787
|
+
deviceRemoved: {
|
|
788
|
+
device: Device;
|
|
789
|
+
};
|
|
790
|
+
/** Emitted when a device's metadata is updated by the server. */
|
|
791
|
+
deviceUpdated: {
|
|
792
|
+
device: Device;
|
|
793
|
+
previousDevice: Device;
|
|
794
|
+
};
|
|
795
|
+
/** Emitted when the WebSocket connection closes. */
|
|
796
|
+
disconnected: {
|
|
797
|
+
reason?: string;
|
|
798
|
+
};
|
|
799
|
+
/** Emitted when a transport or protocol error occurs. */
|
|
800
|
+
error: {
|
|
801
|
+
error: Error;
|
|
802
|
+
};
|
|
803
|
+
/** Emitted when the server pushes an input sensor reading. */
|
|
804
|
+
inputReading: {
|
|
805
|
+
reading: InputReading;
|
|
806
|
+
};
|
|
807
|
+
/** Emitted after a successful reconnection and re-handshake. */
|
|
808
|
+
reconnected: undefined;
|
|
809
|
+
/** Emitted on each reconnection attempt with the current attempt number. */
|
|
810
|
+
reconnecting: {
|
|
811
|
+
attempt: number;
|
|
812
|
+
};
|
|
813
|
+
/** Emitted when the server finishes a device scan. */
|
|
814
|
+
scanningFinished: undefined;
|
|
815
|
+
}
|
|
816
|
+
/**
|
|
817
|
+
* Options for {@link Device.stop}.
|
|
818
|
+
*
|
|
819
|
+
* Without any options, stops all features on the device.
|
|
820
|
+
* Provide filters to target specific features or feature types.
|
|
821
|
+
*/
|
|
822
|
+
interface DeviceStopOptions {
|
|
823
|
+
/** Stop a specific feature by index. */
|
|
824
|
+
featureIndex?: number;
|
|
825
|
+
/** Stop only input features (unsubscribes sensors). */
|
|
826
|
+
inputs?: boolean;
|
|
827
|
+
/** Stop only output features. */
|
|
828
|
+
outputs?: boolean;
|
|
829
|
+
}
|
|
830
|
+
/**
|
|
831
|
+
* Options for {@link Device.output}.
|
|
832
|
+
*
|
|
833
|
+
* Sends a raw {@link OutputCommand} to a specific feature on the device.
|
|
834
|
+
*/
|
|
835
|
+
interface DeviceOutputOptions {
|
|
836
|
+
/** The output command payload. */
|
|
837
|
+
command: OutputCommand;
|
|
838
|
+
/** Target feature index on this device. */
|
|
839
|
+
featureIndex: number;
|
|
840
|
+
}
|
|
841
|
+
/**
|
|
842
|
+
* Configuration options for {@link ButtplugClient}.
|
|
843
|
+
*/
|
|
844
|
+
interface ButtplugClientOptions {
|
|
845
|
+
/** Whether to automatically send pings to keep the connection alive. Defaults to `true`. */
|
|
846
|
+
autoPing?: boolean;
|
|
847
|
+
/** Whether to automatically reconnect on connection loss. */
|
|
848
|
+
autoReconnect?: boolean;
|
|
849
|
+
/** Display name sent to the server during handshake. */
|
|
850
|
+
clientName?: string;
|
|
851
|
+
/** Logger instance for client diagnostics. */
|
|
852
|
+
logger?: Logger;
|
|
853
|
+
/** Maximum number of reconnection attempts before giving up. */
|
|
854
|
+
maxReconnectAttempts?: number;
|
|
855
|
+
/** Maximum delay in milliseconds between reconnection attempts (exponential backoff cap). */
|
|
856
|
+
maxReconnectDelay?: number;
|
|
857
|
+
/** Initial delay in milliseconds before the first reconnection attempt. */
|
|
858
|
+
reconnectDelay?: number;
|
|
859
|
+
/** Timeout in milliseconds for individual protocol requests. */
|
|
860
|
+
requestTimeout?: number;
|
|
861
|
+
}
|
|
862
|
+
|
|
863
|
+
/**
|
|
864
|
+
* High-level client for communicating with a Buttplug server over WebSocket.
|
|
865
|
+
*
|
|
866
|
+
* Manages the full connection lifecycle including handshake, device discovery,
|
|
867
|
+
* ping keep-alive, sensor subscriptions, and optional automatic reconnection.
|
|
868
|
+
* Emits events defined in {@link ClientEventMap}.
|
|
869
|
+
*/
|
|
870
|
+
declare class ButtplugClient extends Emittery<ClientEventMap> implements DeviceMessageSender {
|
|
871
|
+
#private;
|
|
872
|
+
constructor(url: string, options?: ButtplugClientOptions);
|
|
873
|
+
/**
|
|
874
|
+
* Opens a WebSocket connection and performs the Buttplug handshake.
|
|
875
|
+
*
|
|
876
|
+
* @throws ConnectionError if the transport fails to connect
|
|
877
|
+
* @throws HandshakeError if the server rejects the handshake
|
|
878
|
+
*/
|
|
879
|
+
connect(): Promise<void>;
|
|
880
|
+
/**
|
|
881
|
+
* Gracefully disconnects from the server.
|
|
882
|
+
*
|
|
883
|
+
* Stops all devices, sends a protocol-level disconnect message, then closes
|
|
884
|
+
* the WebSocket. Both stop and disconnect steps are time-bounded so the
|
|
885
|
+
* method does not hang indefinitely.
|
|
886
|
+
*
|
|
887
|
+
* @param reason - Optional human-readable reason for the disconnection
|
|
888
|
+
*/
|
|
889
|
+
disconnect(reason?: string): Promise<void>;
|
|
890
|
+
/**
|
|
891
|
+
* Begins scanning for devices on the server.
|
|
892
|
+
*
|
|
893
|
+
* @throws ConnectionError if the client is not connected
|
|
894
|
+
*/
|
|
895
|
+
startScanning(): Promise<void>;
|
|
896
|
+
/**
|
|
897
|
+
* Stops an active device scan on the server.
|
|
898
|
+
*
|
|
899
|
+
* @throws ConnectionError if the client is not connected
|
|
900
|
+
*/
|
|
901
|
+
stopScanning(): Promise<void>;
|
|
902
|
+
/**
|
|
903
|
+
* Sends a global stop command to halt all devices on the server.
|
|
904
|
+
*
|
|
905
|
+
* @throws ConnectionError if the client is not connected
|
|
906
|
+
*/
|
|
907
|
+
stopAll(): Promise<void>;
|
|
908
|
+
/**
|
|
909
|
+
* Requests the current device list from the server.
|
|
910
|
+
*
|
|
911
|
+
* The response triggers device reconciliation and emits
|
|
912
|
+
* `deviceAdded`, `deviceRemoved`, `deviceUpdated`, and `deviceList` events.
|
|
913
|
+
*
|
|
914
|
+
* @throws ConnectionError if the client is not connected
|
|
915
|
+
*/
|
|
916
|
+
requestDeviceList(): Promise<void>;
|
|
917
|
+
/**
|
|
918
|
+
* Sends one or more raw protocol messages to the server.
|
|
919
|
+
*
|
|
920
|
+
* @param messages - A single message or array of messages to send
|
|
921
|
+
* @returns Server response messages
|
|
922
|
+
* @throws ConnectionError if the client is not connected
|
|
923
|
+
*/
|
|
924
|
+
send(messages: ClientMessage | ClientMessage[]): Promise<ServerMessage[]>;
|
|
925
|
+
/**
|
|
926
|
+
* Returns the next monotonically increasing message ID.
|
|
927
|
+
*
|
|
928
|
+
* @returns A unique message ID for the next outgoing message
|
|
929
|
+
*/
|
|
930
|
+
nextId(): number;
|
|
931
|
+
/**
|
|
932
|
+
* Registers a callback for incoming sensor readings.
|
|
933
|
+
*
|
|
934
|
+
* @param key - Unique subscription key (typically from `sensorKey()`)
|
|
935
|
+
* @param callback - Function invoked when a matching reading arrives
|
|
936
|
+
* @param info - Device, feature, and input type identifying the subscription
|
|
937
|
+
*/
|
|
938
|
+
registerSensorSubscription(key: string, callback: SensorCallback, info: {
|
|
939
|
+
deviceIndex: number;
|
|
940
|
+
featureIndex: number;
|
|
941
|
+
type: InputType;
|
|
942
|
+
}): void;
|
|
943
|
+
/**
|
|
944
|
+
* Removes a previously registered sensor subscription.
|
|
945
|
+
*
|
|
946
|
+
* @param key - The subscription key to remove
|
|
947
|
+
*/
|
|
948
|
+
unregisterSensorSubscription(key: string): void;
|
|
949
|
+
/**
|
|
950
|
+
* Retrieves a device by its server-assigned index.
|
|
951
|
+
*
|
|
952
|
+
* @param index - The device index
|
|
953
|
+
* @returns The {@link Device} instance, or `undefined` if not found
|
|
954
|
+
*/
|
|
955
|
+
getDevice(index: number): Device | undefined;
|
|
956
|
+
/** Whether the WebSocket transport is currently connected. */
|
|
957
|
+
get connected(): boolean;
|
|
958
|
+
/** Whether a device scan is currently in progress. */
|
|
959
|
+
get scanning(): boolean;
|
|
960
|
+
/** Server information received during handshake, or `null` if not connected. */
|
|
961
|
+
get serverInfo(): ServerInfo | null;
|
|
962
|
+
/** Snapshot of all currently known {@link Device} instances. */
|
|
963
|
+
get devices(): Device[];
|
|
964
|
+
}
|
|
965
|
+
|
|
966
|
+
/** Constraint for event maps used with {@link TypedEmitter}. */
|
|
967
|
+
type EventMap = Record<string, unknown>;
|
|
968
|
+
/**
|
|
969
|
+
* A strongly-typed event emitter backed by Emittery.
|
|
970
|
+
*
|
|
971
|
+
* @typeParam T - An {@link EventMap} defining event names and their payload types
|
|
972
|
+
*/
|
|
973
|
+
type TypedEmitter<T extends EventMap> = Emittery<T>;
|
|
974
|
+
|
|
975
|
+
/** Numeric error codes returned by the Buttplug protocol. */
|
|
976
|
+
declare const ErrorCode: {
|
|
977
|
+
readonly UNKNOWN: 0;
|
|
978
|
+
readonly INIT: 1;
|
|
979
|
+
readonly PING: 2;
|
|
980
|
+
readonly MESSAGE: 3;
|
|
981
|
+
readonly DEVICE: 4;
|
|
982
|
+
};
|
|
983
|
+
/** Union type of all valid Buttplug error codes. */
|
|
984
|
+
type ErrorCode = (typeof ErrorCode)[keyof typeof ErrorCode];
|
|
985
|
+
/** Base error class for all Buttplug-related failures. */
|
|
986
|
+
declare class ButtplugError extends Error {
|
|
987
|
+
readonly name: string;
|
|
988
|
+
/**
|
|
989
|
+
* @param message - Human-readable error description
|
|
990
|
+
* @param cause - The underlying error that caused this failure
|
|
991
|
+
*/
|
|
992
|
+
constructor(message: string, cause?: Error);
|
|
993
|
+
}
|
|
994
|
+
/**
|
|
995
|
+
* Error thrown when a WebSocket or transport connection fails.
|
|
996
|
+
*/
|
|
997
|
+
declare class ConnectionError extends ButtplugError {
|
|
998
|
+
readonly name: string;
|
|
999
|
+
}
|
|
1000
|
+
/**
|
|
1001
|
+
* Error thrown when the initial protocol handshake with the server fails.
|
|
1002
|
+
*/
|
|
1003
|
+
declare class HandshakeError extends ButtplugError {
|
|
1004
|
+
readonly name: string;
|
|
1005
|
+
}
|
|
1006
|
+
/**
|
|
1007
|
+
* Error thrown when the server returns a protocol-level error message.
|
|
1008
|
+
*/
|
|
1009
|
+
declare class ProtocolError extends ButtplugError {
|
|
1010
|
+
readonly name: string;
|
|
1011
|
+
/** The protocol {@link ErrorCode} returned by the server. */
|
|
1012
|
+
readonly code: ErrorCode;
|
|
1013
|
+
/**
|
|
1014
|
+
* @param code - The protocol error code
|
|
1015
|
+
* @param message - Human-readable error description
|
|
1016
|
+
* @param cause - The underlying error that caused this failure
|
|
1017
|
+
*/
|
|
1018
|
+
constructor(code: ErrorCode, message: string, cause?: Error);
|
|
1019
|
+
}
|
|
1020
|
+
/**
|
|
1021
|
+
* Error thrown when a device-specific operation fails.
|
|
1022
|
+
*/
|
|
1023
|
+
declare class DeviceError extends ButtplugError {
|
|
1024
|
+
readonly name: string;
|
|
1025
|
+
/** Index of the device that triggered the error. */
|
|
1026
|
+
readonly deviceIndex: number;
|
|
1027
|
+
/**
|
|
1028
|
+
* @param deviceIndex - Index of the device that triggered the error
|
|
1029
|
+
* @param message - Human-readable error description
|
|
1030
|
+
* @param cause - The underlying error that caused this failure
|
|
1031
|
+
*/
|
|
1032
|
+
constructor(deviceIndex: number, message: string, cause?: Error);
|
|
1033
|
+
}
|
|
1034
|
+
/**
|
|
1035
|
+
* Error thrown when an operation exceeds its allowed duration.
|
|
1036
|
+
*/
|
|
1037
|
+
declare class TimeoutError extends ButtplugError {
|
|
1038
|
+
readonly name: string;
|
|
1039
|
+
/** Name of the operation that timed out. */
|
|
1040
|
+
readonly operation: string;
|
|
1041
|
+
/** Duration in milliseconds before the timeout triggered. */
|
|
1042
|
+
readonly timeoutMs: number;
|
|
1043
|
+
/**
|
|
1044
|
+
* @param operation - Name of the operation that timed out
|
|
1045
|
+
* @param timeoutMs - Duration in milliseconds before the timeout triggered
|
|
1046
|
+
* @param cause - The underlying error that caused this failure
|
|
1047
|
+
*/
|
|
1048
|
+
constructor(operation: string, timeoutMs: number, cause?: Error);
|
|
1049
|
+
}
|
|
1050
|
+
/**
|
|
1051
|
+
* Normalizes an unknown thrown value into a human-readable message.
|
|
1052
|
+
*
|
|
1053
|
+
* @param err - The caught value to format
|
|
1054
|
+
* @returns Error message for Error instances, stringified value otherwise
|
|
1055
|
+
*/
|
|
1056
|
+
declare function formatError(err: unknown): string;
|
|
1057
|
+
|
|
1058
|
+
/**
|
|
1059
|
+
* Returns the {@link Logger} from the current context.
|
|
1060
|
+
*
|
|
1061
|
+
* Falls back to {@link noopLogger} when called outside a `runWithLogger` scope.
|
|
1062
|
+
*
|
|
1063
|
+
* @returns The context-scoped logger, or noop if none is set
|
|
1064
|
+
*/
|
|
1065
|
+
declare function getLogger(): Logger;
|
|
1066
|
+
/**
|
|
1067
|
+
* Executes a function with the given {@link Logger} scoped to the
|
|
1068
|
+
* current synchronous call stack.
|
|
1069
|
+
*
|
|
1070
|
+
* All downstream calls to {@link getLogger} within `fn` will receive
|
|
1071
|
+
* the provided logger for the duration of the synchronous execution.
|
|
1072
|
+
*
|
|
1073
|
+
* @param logger - The logger to make available via `getLogger()`
|
|
1074
|
+
* @param fn - The function to execute within the scoped context
|
|
1075
|
+
* @returns The return value of `fn`
|
|
1076
|
+
*/
|
|
1077
|
+
declare function runWithLogger<T>(logger: Logger, fn: () => T): T;
|
|
1078
|
+
|
|
1079
|
+
/** Major version of the Buttplug protocol this library implements (v4). */
|
|
1080
|
+
declare const PROTOCOL_VERSION_MAJOR = 4;
|
|
1081
|
+
/** Minor version of the Buttplug protocol this library implements. */
|
|
1082
|
+
declare const PROTOCOL_VERSION_MINOR = 0;
|
|
1083
|
+
/** Default client name sent during the handshake with a Buttplug server. */
|
|
1084
|
+
declare const DEFAULT_CLIENT_NAME = "buttplug.js";
|
|
1085
|
+
/** Default timeout in milliseconds for awaiting a server response to a request. */
|
|
1086
|
+
declare const DEFAULT_REQUEST_TIMEOUT = 10000;
|
|
1087
|
+
/** Default interval in milliseconds between keep-alive ping messages. */
|
|
1088
|
+
declare const DEFAULT_PING_INTERVAL = 1000;
|
|
1089
|
+
/** Maximum allowed message ID value (32-bit unsigned integer ceiling). */
|
|
1090
|
+
declare const MAX_MESSAGE_ID = 4294967295;
|
|
1091
|
+
|
|
1092
|
+
/**
|
|
1093
|
+
* Event handler signatures emitted by a {@link Transport}.
|
|
1094
|
+
*/
|
|
1095
|
+
interface TransportEvents {
|
|
1096
|
+
/** Provides the WebSocket close code and reason for diagnostics. */
|
|
1097
|
+
close: (code: number, reason: string) => void;
|
|
1098
|
+
error: (error: Error) => void;
|
|
1099
|
+
message: (data: string) => void;
|
|
1100
|
+
open: () => void;
|
|
1101
|
+
}
|
|
1102
|
+
/**
|
|
1103
|
+
* Lifecycle state of a {@link Transport} connection.
|
|
1104
|
+
*/
|
|
1105
|
+
type TransportState = "disconnected" | "connecting" | "connected";
|
|
1106
|
+
/**
|
|
1107
|
+
* Union of event names that a {@link Transport} can emit.
|
|
1108
|
+
*/
|
|
1109
|
+
type TransportEventName = keyof TransportEvents;
|
|
1110
|
+
/**
|
|
1111
|
+
* Base options shared across {@link Transport} implementations.
|
|
1112
|
+
*/
|
|
1113
|
+
interface TransportOptions {
|
|
1114
|
+
logger?: Logger;
|
|
1115
|
+
}
|
|
1116
|
+
/**
|
|
1117
|
+
* Minimal contract for a bidirectional message transport.
|
|
1118
|
+
*
|
|
1119
|
+
* Implementations handle the underlying connection lifecycle (connect, disconnect, send)
|
|
1120
|
+
* and expose an event-based API for incoming data and state changes.
|
|
1121
|
+
*/
|
|
1122
|
+
interface Transport {
|
|
1123
|
+
/**
|
|
1124
|
+
* Opens a connection to the given URL.
|
|
1125
|
+
*
|
|
1126
|
+
* @param url - The WebSocket endpoint to connect to
|
|
1127
|
+
*/
|
|
1128
|
+
connect(url: string): Promise<void>;
|
|
1129
|
+
/**
|
|
1130
|
+
* Closes the active connection.
|
|
1131
|
+
*
|
|
1132
|
+
* Implementations should handle cleanup and emit a "close" event.
|
|
1133
|
+
*/
|
|
1134
|
+
disconnect(): Promise<void>;
|
|
1135
|
+
/**
|
|
1136
|
+
* Removes a previously registered handler for the given event.
|
|
1137
|
+
*
|
|
1138
|
+
* @param event - The event to stop listening for
|
|
1139
|
+
* @param handler - The callback to remove
|
|
1140
|
+
*/
|
|
1141
|
+
off<E extends TransportEventName>(event: E, handler: TransportEvents[E]): void;
|
|
1142
|
+
/**
|
|
1143
|
+
* Subscribes a handler for the given event.
|
|
1144
|
+
*
|
|
1145
|
+
* @param event - The event to listen for
|
|
1146
|
+
* @param handler - The callback to invoke when the event fires
|
|
1147
|
+
*/
|
|
1148
|
+
on<E extends TransportEventName>(event: E, handler: TransportEvents[E]): void;
|
|
1149
|
+
/**
|
|
1150
|
+
* Sends a text message over the active connection.
|
|
1151
|
+
*
|
|
1152
|
+
* @param data - The string payload to send
|
|
1153
|
+
* @throws {ConnectionError} if the transport is not connected
|
|
1154
|
+
*/
|
|
1155
|
+
send(data: string): void;
|
|
1156
|
+
readonly state: TransportState;
|
|
1157
|
+
}
|
|
1158
|
+
|
|
1159
|
+
/**
|
|
1160
|
+
* Configuration for {@link PingManager}.
|
|
1161
|
+
*/
|
|
1162
|
+
interface PingOptions {
|
|
1163
|
+
/** Whether to automatically send periodic pings. Defaults to `true`. */
|
|
1164
|
+
autoPing?: boolean;
|
|
1165
|
+
/** Cancels an in-flight ping with the given error (e.g. on timeout). */
|
|
1166
|
+
cancelPing: (error: Error) => void;
|
|
1167
|
+
/** Returns whether the transport is currently connected. */
|
|
1168
|
+
isConnected: () => boolean;
|
|
1169
|
+
/** Optional logger for ping diagnostics. Defaults to a no-op logger. */
|
|
1170
|
+
logger?: Logger;
|
|
1171
|
+
/** Called to initiate a disconnect when a ping times out while still connected. */
|
|
1172
|
+
onDisconnect: (reason: string) => Promise<void>;
|
|
1173
|
+
/** Called when a ping fails with a non-timeout error. */
|
|
1174
|
+
onError: (error: Error) => void;
|
|
1175
|
+
/** Sends a protocol-level ping and resolves when the pong arrives. */
|
|
1176
|
+
sendPing: () => Promise<void>;
|
|
1177
|
+
}
|
|
1178
|
+
/**
|
|
1179
|
+
* Schedules periodic keep-alive pings over a {@link Transport} and triggers
|
|
1180
|
+
* disconnect when the server stops responding within the allowed time.
|
|
1181
|
+
*
|
|
1182
|
+
* **Important**: Callers must call {@link PingManager.stop} when the transport
|
|
1183
|
+
* disconnects. The PingManager does not subscribe to transport events directly.
|
|
1184
|
+
*/
|
|
1185
|
+
declare class PingManager {
|
|
1186
|
+
#private;
|
|
1187
|
+
constructor(options: PingOptions);
|
|
1188
|
+
/**
|
|
1189
|
+
* Starts the periodic ping timer.
|
|
1190
|
+
*
|
|
1191
|
+
* The ping interval is 60% of `maxPingTime`, clamped to a minimum of 100ms.
|
|
1192
|
+
* Stops any previously running timer before starting a new one.
|
|
1193
|
+
*
|
|
1194
|
+
* **Important**: Callers must call {@link PingManager.stop} when the transport
|
|
1195
|
+
* disconnects to prevent pings from being sent to a closed connection.
|
|
1196
|
+
*
|
|
1197
|
+
* @param maxPingTime - Maximum time in ms the server allows between pings
|
|
1198
|
+
*/
|
|
1199
|
+
start(maxPingTime: number): void;
|
|
1200
|
+
/** Stops the ping timer and resets in-flight state. */
|
|
1201
|
+
stop(): void;
|
|
1202
|
+
}
|
|
1203
|
+
|
|
1204
|
+
/**
|
|
1205
|
+
* Configuration for {@link ReconnectHandler}.
|
|
1206
|
+
*/
|
|
1207
|
+
interface ReconnectOptions {
|
|
1208
|
+
/** Optional logger for reconnection diagnostics. Defaults to a no-op logger. */
|
|
1209
|
+
logger?: Logger;
|
|
1210
|
+
/** Maximum number of reconnect attempts before giving up. Defaults to 10. */
|
|
1211
|
+
maxReconnectAttempts?: number;
|
|
1212
|
+
/** Upper bound in ms for exponential backoff. Defaults to 30000ms. */
|
|
1213
|
+
maxReconnectDelay?: number;
|
|
1214
|
+
/** Called when all reconnect attempts are exhausted. */
|
|
1215
|
+
onFailed?: (reason: string) => void;
|
|
1216
|
+
/** Called when reconnection succeeds. */
|
|
1217
|
+
onReconnected?: () => void;
|
|
1218
|
+
/** Called before each reconnect attempt with the current attempt number. */
|
|
1219
|
+
onReconnecting?: (attempt: number) => void;
|
|
1220
|
+
/** Base delay in ms before the first reconnect attempt. Defaults to 1000ms. */
|
|
1221
|
+
reconnectDelay?: number;
|
|
1222
|
+
/** The {@link Transport} instance to reconnect. */
|
|
1223
|
+
transport: Transport;
|
|
1224
|
+
/** The WebSocket endpoint URL to reconnect to. */
|
|
1225
|
+
url: string;
|
|
1226
|
+
}
|
|
1227
|
+
/**
|
|
1228
|
+
* Manages automatic reconnection to a {@link Transport} using exponential backoff.
|
|
1229
|
+
*
|
|
1230
|
+
* Attempts are scheduled with increasing delays up to {@link ReconnectOptions.maxReconnectDelay},
|
|
1231
|
+
* and stop after {@link ReconnectOptions.maxReconnectAttempts} failures.
|
|
1232
|
+
*/
|
|
1233
|
+
declare class ReconnectHandler {
|
|
1234
|
+
#private;
|
|
1235
|
+
constructor(options: ReconnectOptions);
|
|
1236
|
+
/**
|
|
1237
|
+
* Begins the reconnection sequence.
|
|
1238
|
+
*
|
|
1239
|
+
* No-ops if a reconnection is already in progress.
|
|
1240
|
+
*/
|
|
1241
|
+
start(): void;
|
|
1242
|
+
/** Cancels the reconnection sequence and clears any pending timers. */
|
|
1243
|
+
cancel(): void;
|
|
1244
|
+
/** Whether a reconnection sequence is currently in progress. */
|
|
1245
|
+
get active(): boolean;
|
|
1246
|
+
}
|
|
1247
|
+
|
|
1248
|
+
/**
|
|
1249
|
+
* Configuration for {@link WebSocketTransport}.
|
|
1250
|
+
*/
|
|
1251
|
+
interface WebSocketTransportOptions {
|
|
1252
|
+
/** Optional logger for connection diagnostics. Defaults to a no-op logger. */
|
|
1253
|
+
logger?: Logger;
|
|
1254
|
+
}
|
|
1255
|
+
/**
|
|
1256
|
+
* {@link Transport} implementation backed by a native WebSocket.
|
|
1257
|
+
*
|
|
1258
|
+
* Manages the full connection lifecycle including opening, closing,
|
|
1259
|
+
* message dispatch, and event propagation.
|
|
1260
|
+
*/
|
|
1261
|
+
declare class WebSocketTransport implements Transport {
|
|
1262
|
+
#private;
|
|
1263
|
+
constructor(options?: WebSocketTransportOptions);
|
|
1264
|
+
/**
|
|
1265
|
+
* Opens a WebSocket connection to the given URL.
|
|
1266
|
+
*
|
|
1267
|
+
* Returns immediately if already connected. Deduplicates concurrent
|
|
1268
|
+
* connect calls by returning the same in-flight promise.
|
|
1269
|
+
*
|
|
1270
|
+
* @param url - The WebSocket endpoint to connect to
|
|
1271
|
+
* @throws {ConnectionError} if the connection fails or is closed during handshake
|
|
1272
|
+
*/
|
|
1273
|
+
connect(url: string): Promise<void>;
|
|
1274
|
+
/**
|
|
1275
|
+
* Closes the active WebSocket connection.
|
|
1276
|
+
*
|
|
1277
|
+
* No-ops if already disconnected. Waits for the close handshake to complete
|
|
1278
|
+
* if the socket is currently open or closing.
|
|
1279
|
+
*/
|
|
1280
|
+
disconnect(): Promise<void>;
|
|
1281
|
+
/**
|
|
1282
|
+
* Sends a text message over the active WebSocket.
|
|
1283
|
+
*
|
|
1284
|
+
* @param data - The string payload to send
|
|
1285
|
+
* @throws {ConnectionError} if the WebSocket is not in the OPEN state or send fails
|
|
1286
|
+
*/
|
|
1287
|
+
send(data: string): void;
|
|
1288
|
+
/**
|
|
1289
|
+
* Subscribes a handler for the given transport event.
|
|
1290
|
+
*
|
|
1291
|
+
* @param event - The event to listen for
|
|
1292
|
+
* @param handler - The callback to invoke when the event fires
|
|
1293
|
+
*/
|
|
1294
|
+
on<E extends TransportEventName>(event: E, handler: TransportEvents[E]): void;
|
|
1295
|
+
/**
|
|
1296
|
+
* Removes a previously registered handler for the given event.
|
|
1297
|
+
*
|
|
1298
|
+
* @param event - The event to stop listening for
|
|
1299
|
+
* @param handler - The callback to remove
|
|
1300
|
+
*/
|
|
1301
|
+
off<E extends TransportEventName>(event: E, handler: TransportEvents[E]): void;
|
|
1302
|
+
/** Current connection lifecycle state. */
|
|
1303
|
+
get state(): TransportState;
|
|
1304
|
+
}
|
|
1305
|
+
|
|
1306
|
+
/**
|
|
1307
|
+
* Default values for {@link ReconnectHandler} configuration.
|
|
1308
|
+
*
|
|
1309
|
+
* - `DELAY` — Base delay in ms before the first reconnect attempt
|
|
1310
|
+
* - `MAX_DELAY` — Upper bound in ms for exponential backoff
|
|
1311
|
+
* - `MAX_ATTEMPTS` — Maximum number of reconnect attempts before giving up
|
|
1312
|
+
*/
|
|
1313
|
+
declare const ReconnectDefaults: {
|
|
1314
|
+
readonly DELAY: 1000;
|
|
1315
|
+
readonly MAX_DELAY: 30000;
|
|
1316
|
+
readonly MAX_ATTEMPTS: 10;
|
|
1317
|
+
};
|
|
1318
|
+
|
|
1319
|
+
/** All {@link OutputType} values defined by the buttplug protocol. */
|
|
1320
|
+
declare const OUTPUT_TYPES: readonly OutputType[];
|
|
1321
|
+
/** All {@link InputType} values defined by the buttplug protocol. */
|
|
1322
|
+
declare const INPUT_TYPES: readonly InputType[];
|
|
1323
|
+
|
|
1324
|
+
/**
|
|
1325
|
+
* Minimal device interface required by {@link PatternEngine}.
|
|
1326
|
+
*
|
|
1327
|
+
* Decouples the pattern system from the full client device implementation,
|
|
1328
|
+
* allowing patterns to target any object that can send {@link OutputCommand} messages.
|
|
1329
|
+
*/
|
|
1330
|
+
interface PatternDevice {
|
|
1331
|
+
/** Available input/output features on the device. */
|
|
1332
|
+
readonly features: DeviceFeatures;
|
|
1333
|
+
/** Device index in the server's device list. */
|
|
1334
|
+
readonly index: number;
|
|
1335
|
+
/** Minimum interval in milliseconds between consecutive messages to this device. */
|
|
1336
|
+
readonly messageTimingGap: number;
|
|
1337
|
+
/** Human-readable device name. */
|
|
1338
|
+
readonly name: string;
|
|
1339
|
+
/**
|
|
1340
|
+
* Sends an {@link OutputCommand} to a specific feature.
|
|
1341
|
+
*
|
|
1342
|
+
* @param options - The feature index and output command to send
|
|
1343
|
+
*/
|
|
1344
|
+
output(options: DeviceOutputOptions): Promise<void>;
|
|
1345
|
+
/**
|
|
1346
|
+
* Stops device output.
|
|
1347
|
+
*
|
|
1348
|
+
* @param options - Optional filters for which features/directions to stop
|
|
1349
|
+
*/
|
|
1350
|
+
stop(options?: DeviceStopOptions): Promise<void>;
|
|
1351
|
+
}
|
|
1352
|
+
/** Supported {@link Easing} curve names. */
|
|
1353
|
+
declare const EASING_VALUES: readonly ["linear", "easeIn", "easeOut", "easeInOut", "step"];
|
|
1354
|
+
/** Zod schema for validating {@link Easing} values. */
|
|
1355
|
+
declare const EasingSchema: z.ZodEnum<{
|
|
1356
|
+
linear: "linear";
|
|
1357
|
+
easeIn: "easeIn";
|
|
1358
|
+
easeOut: "easeOut";
|
|
1359
|
+
easeInOut: "easeInOut";
|
|
1360
|
+
step: "step";
|
|
1361
|
+
}>;
|
|
1362
|
+
/** Easing curve identifier used for keyframe interpolation. */
|
|
1363
|
+
type Easing = z.infer<typeof EasingSchema>;
|
|
1364
|
+
/** Zod schema for validating {@link Keyframe} objects. */
|
|
1365
|
+
declare const KeyframeSchema: z.ZodObject<{
|
|
1366
|
+
value: z.ZodNumber;
|
|
1367
|
+
duration: z.ZodNumber;
|
|
1368
|
+
easing: z.ZodOptional<z.ZodEnum<{
|
|
1369
|
+
linear: "linear";
|
|
1370
|
+
easeIn: "easeIn";
|
|
1371
|
+
easeOut: "easeOut";
|
|
1372
|
+
easeInOut: "easeInOut";
|
|
1373
|
+
step: "step";
|
|
1374
|
+
}>>;
|
|
1375
|
+
}, z.core.$strip>;
|
|
1376
|
+
/**
|
|
1377
|
+
* A single animation keyframe with a target value, transition duration, and optional {@link Easing}.
|
|
1378
|
+
*
|
|
1379
|
+
* Duration of 0 creates an instant jump to the value.
|
|
1380
|
+
*/
|
|
1381
|
+
type Keyframe = z.infer<typeof KeyframeSchema>;
|
|
1382
|
+
/** Zod schema for validating {@link Track} objects. */
|
|
1383
|
+
declare const TrackSchema: z.ZodObject<{
|
|
1384
|
+
featureIndex: z.ZodNumber;
|
|
1385
|
+
keyframes: z.ZodArray<z.ZodObject<{
|
|
1386
|
+
value: z.ZodNumber;
|
|
1387
|
+
duration: z.ZodNumber;
|
|
1388
|
+
easing: z.ZodOptional<z.ZodEnum<{
|
|
1389
|
+
linear: "linear";
|
|
1390
|
+
easeIn: "easeIn";
|
|
1391
|
+
easeOut: "easeOut";
|
|
1392
|
+
easeInOut: "easeInOut";
|
|
1393
|
+
step: "step";
|
|
1394
|
+
}>>;
|
|
1395
|
+
}, z.core.$strip>>;
|
|
1396
|
+
clockwise: z.ZodOptional<z.ZodBoolean>;
|
|
1397
|
+
outputType: z.ZodOptional<z.ZodEnum<{
|
|
1398
|
+
Vibrate: "Vibrate";
|
|
1399
|
+
Rotate: "Rotate";
|
|
1400
|
+
RotateWithDirection: "RotateWithDirection";
|
|
1401
|
+
Oscillate: "Oscillate";
|
|
1402
|
+
Constrict: "Constrict";
|
|
1403
|
+
Spray: "Spray";
|
|
1404
|
+
Temperature: "Temperature";
|
|
1405
|
+
Led: "Led";
|
|
1406
|
+
Position: "Position";
|
|
1407
|
+
HwPositionWithDuration: "HwPositionWithDuration";
|
|
1408
|
+
}>>;
|
|
1409
|
+
}, z.core.$strip>;
|
|
1410
|
+
/** A sequence of {@link Keyframe} values bound to a specific device feature. */
|
|
1411
|
+
type Track = z.infer<typeof TrackSchema>;
|
|
1412
|
+
/** Available built-in pattern preset names. */
|
|
1413
|
+
declare const PRESET_NAMES: readonly ["pulse", "wave", "ramp_up", "ramp_down", "heartbeat", "surge", "stroke"];
|
|
1414
|
+
/** A built-in preset pattern name from {@link PRESET_NAMES}. */
|
|
1415
|
+
type PresetName = (typeof PRESET_NAMES)[number];
|
|
1416
|
+
/** Zod schema for validating {@link PresetPattern} descriptors. */
|
|
1417
|
+
declare const PresetPatternSchema: z.ZodObject<{
|
|
1418
|
+
type: z.ZodLiteral<"preset">;
|
|
1419
|
+
preset: z.ZodEnum<{
|
|
1420
|
+
pulse: "pulse";
|
|
1421
|
+
wave: "wave";
|
|
1422
|
+
ramp_up: "ramp_up";
|
|
1423
|
+
ramp_down: "ramp_down";
|
|
1424
|
+
heartbeat: "heartbeat";
|
|
1425
|
+
surge: "surge";
|
|
1426
|
+
stroke: "stroke";
|
|
1427
|
+
}>;
|
|
1428
|
+
intensity: z.ZodOptional<z.ZodNumber>;
|
|
1429
|
+
speed: z.ZodOptional<z.ZodNumber>;
|
|
1430
|
+
loop: z.ZodOptional<z.ZodUnion<readonly [z.ZodBoolean, z.ZodNumber]>>;
|
|
1431
|
+
}, z.core.$strip>;
|
|
1432
|
+
/**
|
|
1433
|
+
* Pattern descriptor that references a built-in preset by name.
|
|
1434
|
+
*
|
|
1435
|
+
* Allows optional intensity scaling (0-1), speed multiplier (0.25-4x),
|
|
1436
|
+
* and loop configuration.
|
|
1437
|
+
*/
|
|
1438
|
+
type PresetPattern = z.infer<typeof PresetPatternSchema>;
|
|
1439
|
+
/** Zod schema for validating {@link CustomPattern} descriptors. */
|
|
1440
|
+
declare const CustomPatternSchema: z.ZodObject<{
|
|
1441
|
+
type: z.ZodLiteral<"custom">;
|
|
1442
|
+
tracks: z.ZodArray<z.ZodObject<{
|
|
1443
|
+
featureIndex: z.ZodNumber;
|
|
1444
|
+
keyframes: z.ZodArray<z.ZodObject<{
|
|
1445
|
+
value: z.ZodNumber;
|
|
1446
|
+
duration: z.ZodNumber;
|
|
1447
|
+
easing: z.ZodOptional<z.ZodEnum<{
|
|
1448
|
+
linear: "linear";
|
|
1449
|
+
easeIn: "easeIn";
|
|
1450
|
+
easeOut: "easeOut";
|
|
1451
|
+
easeInOut: "easeInOut";
|
|
1452
|
+
step: "step";
|
|
1453
|
+
}>>;
|
|
1454
|
+
}, z.core.$strip>>;
|
|
1455
|
+
clockwise: z.ZodOptional<z.ZodBoolean>;
|
|
1456
|
+
outputType: z.ZodOptional<z.ZodEnum<{
|
|
1457
|
+
Vibrate: "Vibrate";
|
|
1458
|
+
Rotate: "Rotate";
|
|
1459
|
+
RotateWithDirection: "RotateWithDirection";
|
|
1460
|
+
Oscillate: "Oscillate";
|
|
1461
|
+
Constrict: "Constrict";
|
|
1462
|
+
Spray: "Spray";
|
|
1463
|
+
Temperature: "Temperature";
|
|
1464
|
+
Led: "Led";
|
|
1465
|
+
Position: "Position";
|
|
1466
|
+
HwPositionWithDuration: "HwPositionWithDuration";
|
|
1467
|
+
}>>;
|
|
1468
|
+
}, z.core.$strip>>;
|
|
1469
|
+
intensity: z.ZodOptional<z.ZodNumber>;
|
|
1470
|
+
loop: z.ZodOptional<z.ZodUnion<readonly [z.ZodBoolean, z.ZodNumber]>>;
|
|
1471
|
+
}, z.core.$strip>;
|
|
1472
|
+
/**
|
|
1473
|
+
* Pattern descriptor with user-defined keyframe tracks.
|
|
1474
|
+
*
|
|
1475
|
+
* Each track targets a specific feature index and contains its own keyframe sequence.
|
|
1476
|
+
*/
|
|
1477
|
+
type CustomPattern = z.infer<typeof CustomPatternSchema>;
|
|
1478
|
+
/**
|
|
1479
|
+
* Discriminated union schema for pattern descriptors.
|
|
1480
|
+
*
|
|
1481
|
+
* Uses the `type` field to distinguish between preset and custom patterns.
|
|
1482
|
+
*/
|
|
1483
|
+
declare const PatternDescriptorSchema: z.ZodDiscriminatedUnion<[z.ZodObject<{
|
|
1484
|
+
type: z.ZodLiteral<"preset">;
|
|
1485
|
+
preset: z.ZodEnum<{
|
|
1486
|
+
pulse: "pulse";
|
|
1487
|
+
wave: "wave";
|
|
1488
|
+
ramp_up: "ramp_up";
|
|
1489
|
+
ramp_down: "ramp_down";
|
|
1490
|
+
heartbeat: "heartbeat";
|
|
1491
|
+
surge: "surge";
|
|
1492
|
+
stroke: "stroke";
|
|
1493
|
+
}>;
|
|
1494
|
+
intensity: z.ZodOptional<z.ZodNumber>;
|
|
1495
|
+
speed: z.ZodOptional<z.ZodNumber>;
|
|
1496
|
+
loop: z.ZodOptional<z.ZodUnion<readonly [z.ZodBoolean, z.ZodNumber]>>;
|
|
1497
|
+
}, z.core.$strip>, z.ZodObject<{
|
|
1498
|
+
type: z.ZodLiteral<"custom">;
|
|
1499
|
+
tracks: z.ZodArray<z.ZodObject<{
|
|
1500
|
+
featureIndex: z.ZodNumber;
|
|
1501
|
+
keyframes: z.ZodArray<z.ZodObject<{
|
|
1502
|
+
value: z.ZodNumber;
|
|
1503
|
+
duration: z.ZodNumber;
|
|
1504
|
+
easing: z.ZodOptional<z.ZodEnum<{
|
|
1505
|
+
linear: "linear";
|
|
1506
|
+
easeIn: "easeIn";
|
|
1507
|
+
easeOut: "easeOut";
|
|
1508
|
+
easeInOut: "easeInOut";
|
|
1509
|
+
step: "step";
|
|
1510
|
+
}>>;
|
|
1511
|
+
}, z.core.$strip>>;
|
|
1512
|
+
clockwise: z.ZodOptional<z.ZodBoolean>;
|
|
1513
|
+
outputType: z.ZodOptional<z.ZodEnum<{
|
|
1514
|
+
Vibrate: "Vibrate";
|
|
1515
|
+
Rotate: "Rotate";
|
|
1516
|
+
RotateWithDirection: "RotateWithDirection";
|
|
1517
|
+
Oscillate: "Oscillate";
|
|
1518
|
+
Constrict: "Constrict";
|
|
1519
|
+
Spray: "Spray";
|
|
1520
|
+
Temperature: "Temperature";
|
|
1521
|
+
Led: "Led";
|
|
1522
|
+
Position: "Position";
|
|
1523
|
+
HwPositionWithDuration: "HwPositionWithDuration";
|
|
1524
|
+
}>>;
|
|
1525
|
+
}, z.core.$strip>>;
|
|
1526
|
+
intensity: z.ZodOptional<z.ZodNumber>;
|
|
1527
|
+
loop: z.ZodOptional<z.ZodUnion<readonly [z.ZodBoolean, z.ZodNumber]>>;
|
|
1528
|
+
}, z.core.$strip>], "type">;
|
|
1529
|
+
/**
|
|
1530
|
+
* Pattern descriptor that can be either preset-based or custom-defined.
|
|
1531
|
+
*/
|
|
1532
|
+
type PatternDescriptor = z.infer<typeof PatternDescriptorSchema>;
|
|
1533
|
+
/**
|
|
1534
|
+
* Client interface consumed by {@link PatternEngine} for {@link PatternDevice} access and event subscription.
|
|
1535
|
+
*
|
|
1536
|
+
* Decouples the engine from the full buttplug client, requiring only device
|
|
1537
|
+
* lookup and disconnect/removal event hooks.
|
|
1538
|
+
*/
|
|
1539
|
+
interface PatternEngineClient {
|
|
1540
|
+
/**
|
|
1541
|
+
* Retrieves a {@link PatternDevice} by its server-assigned index.
|
|
1542
|
+
*
|
|
1543
|
+
* @param index - The device index to look up
|
|
1544
|
+
* @returns The device if found, or undefined
|
|
1545
|
+
*/
|
|
1546
|
+
getDevice(index: number): PatternDevice | undefined;
|
|
1547
|
+
/**
|
|
1548
|
+
* Subscribes to the client disconnected event.
|
|
1549
|
+
*
|
|
1550
|
+
* @param event - The event name
|
|
1551
|
+
* @param handler - Callback invoked on disconnect
|
|
1552
|
+
* @returns Unsubscribe function
|
|
1553
|
+
*/
|
|
1554
|
+
on(event: "disconnected", handler: (data: {
|
|
1555
|
+
reason?: string;
|
|
1556
|
+
}) => void): () => void;
|
|
1557
|
+
/**
|
|
1558
|
+
* Subscribes to the device removed event.
|
|
1559
|
+
*
|
|
1560
|
+
* @param event - The event name
|
|
1561
|
+
* @param handler - Callback invoked when a {@link PatternDevice} is removed
|
|
1562
|
+
* @returns Unsubscribe function
|
|
1563
|
+
*/
|
|
1564
|
+
on(event: "deviceRemoved", handler: (data: {
|
|
1565
|
+
device: PatternDevice;
|
|
1566
|
+
}) => void): () => void;
|
|
1567
|
+
}
|
|
1568
|
+
/** Reason a pattern was stopped, used in {@link PatternPlayOptions.onStop} callbacks. */
|
|
1569
|
+
type StopReason = "manual" | "complete" | "timeout" | "error" | "disconnect" | "deviceRemoved";
|
|
1570
|
+
/**
|
|
1571
|
+
* Unified options for controlling pattern playback behavior.
|
|
1572
|
+
*
|
|
1573
|
+
* Combines device targeting, preset tuning, loop control, timeout,
|
|
1574
|
+
* and lifecycle callbacks into a single options object.
|
|
1575
|
+
*/
|
|
1576
|
+
interface PatternPlayOptions {
|
|
1577
|
+
/** Target a specific feature index instead of auto-resolving. */
|
|
1578
|
+
featureIndex?: number;
|
|
1579
|
+
/** Intensity scaling (0-1). Applied to preset and custom patterns. */
|
|
1580
|
+
intensity?: number;
|
|
1581
|
+
/** Loop behavior override. */
|
|
1582
|
+
loop?: boolean | number;
|
|
1583
|
+
/** Called when the pattern completes all loops naturally. */
|
|
1584
|
+
onComplete?: (patternId: string) => void;
|
|
1585
|
+
/** Called whenever the pattern stops for any {@link StopReason}. */
|
|
1586
|
+
onStop?: (patternId: string, reason: StopReason) => void;
|
|
1587
|
+
/** Speed multiplier (0.25-4x). Only applies to preset shorthand. */
|
|
1588
|
+
speed?: number;
|
|
1589
|
+
/** Maximum playback duration in milliseconds before auto-stop. */
|
|
1590
|
+
timeout?: number;
|
|
1591
|
+
}
|
|
1592
|
+
/**
|
|
1593
|
+
* @deprecated Use {@link PatternPlayOptions} instead.
|
|
1594
|
+
*/
|
|
1595
|
+
type PlayOptions = PatternPlayOptions;
|
|
1596
|
+
/**
|
|
1597
|
+
* Read-only snapshot of a running pattern, returned by {@link PatternEngine.list}.
|
|
1598
|
+
*/
|
|
1599
|
+
interface PatternInfo {
|
|
1600
|
+
/** The original {@link PatternDescriptor} used to create this pattern. */
|
|
1601
|
+
readonly descriptor: PatternDescriptor;
|
|
1602
|
+
/** Index of the device this pattern targets. */
|
|
1603
|
+
readonly deviceIndex: number;
|
|
1604
|
+
/** Milliseconds elapsed since playback began. */
|
|
1605
|
+
readonly elapsed: number;
|
|
1606
|
+
/** Feature indices being driven by this pattern. */
|
|
1607
|
+
readonly featureIndices: number[];
|
|
1608
|
+
/** Unique pattern instance identifier. */
|
|
1609
|
+
readonly id: string;
|
|
1610
|
+
/** Timestamp (from `performance.now()`) when playback began. */
|
|
1611
|
+
readonly startedAt: number;
|
|
1612
|
+
}
|
|
1613
|
+
/**
|
|
1614
|
+
* Metadata describing a built-in preset pattern.
|
|
1615
|
+
*/
|
|
1616
|
+
interface PresetInfo {
|
|
1617
|
+
/** {@link OutputType} values this preset is designed for. */
|
|
1618
|
+
readonly compatibleOutputTypes: OutputType[];
|
|
1619
|
+
/** Whether the preset loops by default. */
|
|
1620
|
+
readonly defaultLoop: boolean;
|
|
1621
|
+
/** Human-readable description of the pattern's behavior. */
|
|
1622
|
+
readonly description: string;
|
|
1623
|
+
/** Preset name identifier. */
|
|
1624
|
+
readonly name: string;
|
|
1625
|
+
}
|
|
1626
|
+
|
|
1627
|
+
type EasingName = Easing;
|
|
1628
|
+
/** A function that maps a normalized time value (0-1) to an eased output value. */
|
|
1629
|
+
type EasingFunction = (t: number) => number;
|
|
1630
|
+
/**
|
|
1631
|
+
* Lookup table mapping {@link EasingName} identifiers to their easing functions.
|
|
1632
|
+
*
|
|
1633
|
+
* All functions use cubic curves except `step` (discrete) and `linear` (identity).
|
|
1634
|
+
*/
|
|
1635
|
+
declare const EASING_FUNCTIONS: Record<EasingName, EasingFunction>;
|
|
1636
|
+
|
|
1637
|
+
/**
|
|
1638
|
+
* Orchestrates pattern playback on buttplug devices using tick-based keyframe scheduling.
|
|
1639
|
+
*
|
|
1640
|
+
* Manages the lifecycle of active patterns including loop handling, drift-corrected
|
|
1641
|
+
* tick scheduling, deduplication of redundant commands, and automatic cleanup on
|
|
1642
|
+
* disconnect or device removal.
|
|
1643
|
+
*/
|
|
1644
|
+
declare class PatternEngine {
|
|
1645
|
+
#private;
|
|
1646
|
+
/**
|
|
1647
|
+
* @param client - Client providing device access and event hooks
|
|
1648
|
+
* @param options - Optional configuration for default timeout behavior
|
|
1649
|
+
*/
|
|
1650
|
+
constructor(client: PatternEngineClient, options?: {
|
|
1651
|
+
defaultTimeout?: number;
|
|
1652
|
+
});
|
|
1653
|
+
/**
|
|
1654
|
+
* Starts playing a preset pattern on a device by name.
|
|
1655
|
+
*
|
|
1656
|
+
* @param device - Target device or device index
|
|
1657
|
+
* @param preset - Built-in preset name (e.g. "wave", "pulse")
|
|
1658
|
+
* @param options - Playback options including intensity, speed, loop, timeout, and callbacks
|
|
1659
|
+
* @returns Unique pattern instance ID for later control
|
|
1660
|
+
* @throws {DeviceError} If the engine is disposed, device not found, or no compatible features
|
|
1661
|
+
*/
|
|
1662
|
+
play(device: PatternDevice | number, preset: PresetName, options?: PatternPlayOptions): Promise<string>;
|
|
1663
|
+
/**
|
|
1664
|
+
* Starts playing a custom pattern defined by keyframe tracks.
|
|
1665
|
+
*
|
|
1666
|
+
* @param device - Target device or device index
|
|
1667
|
+
* @param tracks - Array of {@link Track} definitions with keyframes bound to feature indices
|
|
1668
|
+
* @param options - Playback options including intensity, loop, timeout, and callbacks
|
|
1669
|
+
* @returns Unique pattern instance ID for later control
|
|
1670
|
+
* @throws {DeviceError} If the engine is disposed, device not found, or no compatible features
|
|
1671
|
+
*/
|
|
1672
|
+
play(device: PatternDevice | number, tracks: Track[], options?: PatternPlayOptions): Promise<string>;
|
|
1673
|
+
/**
|
|
1674
|
+
* Starts playing a pattern from a full {@link PatternDescriptor}.
|
|
1675
|
+
*
|
|
1676
|
+
* @param device - Target device or device index
|
|
1677
|
+
* @param descriptor - Full pattern descriptor (preset or custom)
|
|
1678
|
+
* @param options - Playback options including timeout and callbacks
|
|
1679
|
+
* @returns Unique pattern instance ID for later control
|
|
1680
|
+
* @throws {DeviceError} If the engine is disposed, device not found, or no compatible features
|
|
1681
|
+
*/
|
|
1682
|
+
play(device: PatternDevice | number, descriptor: PatternDescriptor, options?: PatternPlayOptions): Promise<string>;
|
|
1683
|
+
/**
|
|
1684
|
+
* Stops a specific pattern by its ID.
|
|
1685
|
+
*
|
|
1686
|
+
* No-op if the pattern ID is not found (already stopped or never started).
|
|
1687
|
+
*
|
|
1688
|
+
* @param patternId - The pattern instance ID returned by {@link play}
|
|
1689
|
+
*/
|
|
1690
|
+
stop(patternId: string): Promise<void>;
|
|
1691
|
+
/**
|
|
1692
|
+
* Stops all active patterns.
|
|
1693
|
+
*
|
|
1694
|
+
* @returns Number of patterns that were stopped
|
|
1695
|
+
*/
|
|
1696
|
+
stopAll(): number;
|
|
1697
|
+
/**
|
|
1698
|
+
* Stops all active patterns targeting a specific device.
|
|
1699
|
+
*
|
|
1700
|
+
* @param deviceIndex - The device index to stop patterns for
|
|
1701
|
+
* @returns Number of patterns that were stopped
|
|
1702
|
+
*/
|
|
1703
|
+
stopByDevice(deviceIndex: number): number;
|
|
1704
|
+
/**
|
|
1705
|
+
* Returns a snapshot of all active patterns.
|
|
1706
|
+
*
|
|
1707
|
+
* @returns Array of {@link PatternInfo} snapshots
|
|
1708
|
+
*/
|
|
1709
|
+
list(): PatternInfo[];
|
|
1710
|
+
/**
|
|
1711
|
+
* Returns metadata for all available built-in presets.
|
|
1712
|
+
*
|
|
1713
|
+
* @returns Array of {@link PresetInfo} descriptors
|
|
1714
|
+
*/
|
|
1715
|
+
listPresets(): PresetInfo[];
|
|
1716
|
+
/**
|
|
1717
|
+
* Disposes the engine, stopping all patterns and unsubscribing from client events.
|
|
1718
|
+
*
|
|
1719
|
+
* Subsequent calls to {@link play} will throw. Idempotent.
|
|
1720
|
+
*/
|
|
1721
|
+
dispose(): void;
|
|
1722
|
+
}
|
|
1723
|
+
|
|
1724
|
+
/**
|
|
1725
|
+
* Internal definition of a preset pattern, including its keyframe tracks
|
|
1726
|
+
* and compatible output types.
|
|
1727
|
+
*/
|
|
1728
|
+
interface PresetDefinition {
|
|
1729
|
+
/** Human-readable description of the pattern's behavior. */
|
|
1730
|
+
readonly description: string;
|
|
1731
|
+
/** Whether this preset loops by default. */
|
|
1732
|
+
readonly loop: boolean;
|
|
1733
|
+
/** {@link OutputType} values this preset is compatible with. */
|
|
1734
|
+
readonly outputTypes: OutputType[];
|
|
1735
|
+
/** Keyframe sequences for the pattern. Features are assigned tracks via round-robin when there are more features than tracks. */
|
|
1736
|
+
readonly tracks: Keyframe[][];
|
|
1737
|
+
}
|
|
1738
|
+
/**
|
|
1739
|
+
* Built-in pattern presets keyed by {@link PresetName}.
|
|
1740
|
+
*
|
|
1741
|
+
* Each preset defines keyframe tracks, compatible output types, and default loop behavior.
|
|
1742
|
+
* Presets are resolved into {@link ResolvedTrack} arrays by the track resolver.
|
|
1743
|
+
*/
|
|
1744
|
+
declare const PRESETS: Record<PresetName, PresetDefinition>;
|
|
1745
|
+
/**
|
|
1746
|
+
* Returns metadata for all available preset patterns.
|
|
1747
|
+
*
|
|
1748
|
+
* @returns Array of {@link PresetInfo} with name, description, compatible types, and loop defaults
|
|
1749
|
+
*/
|
|
1750
|
+
declare function getPresetInfo(): PresetInfo[];
|
|
1751
|
+
|
|
1752
|
+
export { ButtplugClient, type ButtplugClientOptions, ButtplugError, type ClientEventMap, type ClientMessage, ClientMessageSchema, ConnectionError, type CustomPattern, DEFAULT_CLIENT_NAME, DEFAULT_PING_INTERVAL, DEFAULT_REQUEST_TIMEOUT, Device, DeviceError, type DeviceFeatures, DeviceFeaturesSchema, type DeviceMessageSender, type DeviceOptions, type DeviceOutputOptions, type DeviceStopOptions, EASING_FUNCTIONS, EASING_VALUES, type Easing, type EasingFunction, type EasingName, ErrorCode, type FeatureValue, FeatureValueSchema, HandshakeError, type HwPositionOutputData, HwPositionOutputDataSchema, INPUT_TYPES, INPUT_TYPE_VALUES, type InputCommandType, InputCommandTypeSchema, type InputData, InputDataSchema, type InputFeature, InputFeatureSchema, type InputReading, InputReadingSchema, type InputType, InputTypeSchema, type Keyframe, KeyframeSchema, type Logger, MAX_MESSAGE_ID, OUTPUT_TYPES, OUTPUT_TYPE_VALUES, type OutputCommand, OutputCommandSchema, type OutputFeature, OutputFeatureSchema, type OutputType, OutputTypeSchema, PRESETS, PRESET_NAMES, PROTOCOL_VERSION_MAJOR, PROTOCOL_VERSION_MINOR, type PatternDescriptor, PatternDescriptorSchema, type PatternDevice, PatternEngine, type PatternEngineClient, type PatternInfo, type PatternPlayOptions, PingManager, type PingOptions, type PlayOptions, type PositionValue, PositionValueSchema, type PresetInfo, type PresetName, type PresetPattern, ProtocolError, ReconnectDefaults, ReconnectHandler, type ReconnectOptions, type RotateWithDirectionOutputData, RotateWithDirectionOutputDataSchema, type RotationValue, RotationValueSchema, type ScalarOutputData, type SensorCallback, type SensorValue, SensorValueSchema, type ServerInfo, ServerInfoSchema, type ServerMessage, ServerMessageSchema, type SignedScalarOutputData, SignedScalarOutputDataSchema, type StopReason, TimeoutError, type Track, type Transport, type TransportEvents, type TransportOptions, type TransportState, type TypedEmitter, type UnsignedScalarOutputData, UnsignedScalarOutputDataSchema, WebSocketTransport, type WebSocketTransportOptions, consoleLogger, formatError, getLogger, getPresetInfo, noopLogger, runWithLogger };
|