@dg-kit/transport-webbluetooth 1.11.0 → 1.13.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.
@@ -0,0 +1,51 @@
1
+ import { type BluetoothDeviceLike, type BluetoothRemoteGATTServerLike, type GattReadyRetryOptions, type NavigatorBluetoothLike, type RequestDeviceOptionsLike, type WebBluetoothConnectionContext } from '@dg-kit/protocol';
2
+ /** Minimal shape both `OpossumVibrateAdapter` and the sensor adapters satisfy. */
3
+ export interface ConnectableAdapter {
4
+ onConnected(context: WebBluetoothConnectionContext): Promise<void>;
5
+ onDisconnected(): Promise<void>;
6
+ }
7
+ export interface AuxDeviceConnectOptions {
8
+ navigatorRef?: NavigatorBluetoothLike;
9
+ requestDeviceOptions: RequestDeviceOptionsLike;
10
+ /**
11
+ * Tuning for the GATT-not-ready retry wrapped around `adapter.onConnected()`
12
+ * — see `runWithGattReadyRetry`'s doc (`@dg-kit/protocol`). These three
13
+ * device kinds share the exact same GATT skeleton as Coyote, so they hit
14
+ * the identical "gatt.connect() resolves before service discovery"
15
+ * Web Bluetooth race. Defaults are fine for normal use; exposed mainly for
16
+ * tests.
17
+ */
18
+ gattReadyRetryOptions?: GattReadyRetryOptions;
19
+ }
20
+ /**
21
+ * Opens the Bluetooth chooser scoped to `options.requestDeviceOptions`,
22
+ * connects GATT, and hands the connection to `adapter.onConnected()`.
23
+ * Mirrors `WebBluetoothDeviceClient.connect()`'s "replace the previous
24
+ * device only after the new one succeeds" ordering, minus the reconnect
25
+ * bookkeeping that client also carries.
26
+ *
27
+ * Returns the newly connected device; the caller is responsible for storing
28
+ * it and passing it back in on the next call (as `previousDevice`) and to
29
+ * `disconnectAuxDevice`.
30
+ */
31
+ export declare function connectAuxDevice(options: AuxDeviceConnectOptions, adapter: ConnectableAdapter, previousDevice: BluetoothDeviceLike | null, onGattDisconnected: (event: Event) => void): Promise<BluetoothDeviceLike>;
32
+ /**
33
+ * Attaches to an already-obtained `(device, server)` pair instead of
34
+ * running this helper's own `bluetooth.requestDevice()` chooser prompt —
35
+ * the aux-device counterpart to `WebBluetoothDeviceClient.connectDevice()`.
36
+ * Lets a caller that already ran ONE shared chooser scoped to every DG-Lab
37
+ * device kind (see `requestDgLabDevice()`) and identified the picked
38
+ * device's kind via `detectDeviceKind()` hand it straight to the matching
39
+ * client, instead of needing a second, kind-scoped chooser prompt.
40
+ * `gatt.connect()` must already have been called by the caller; this only
41
+ * runs the adapter handshake and the same replace-previous-device
42
+ * bookkeeping `connectAuxDevice()` does.
43
+ */
44
+ export declare function attachAuxDevice(nextDevice: BluetoothDeviceLike, server: BluetoothRemoteGATTServerLike, adapter: ConnectableAdapter, previousDevice: BluetoothDeviceLike | null, onGattDisconnected: (event: Event) => void, gattReadyRetryOptions?: GattReadyRetryOptions): Promise<BluetoothDeviceLike>;
45
+ /**
46
+ * User-initiated disconnect: removes the listener BEFORE calling
47
+ * `gatt.disconnect()` so the resulting `gattserverdisconnected` event never
48
+ * reaches `onGattDisconnected` a second time.
49
+ */
50
+ export declare function disconnectAuxDevice(device: BluetoothDeviceLike | null, adapter: ConnectableAdapter, onGattDisconnected: (event: Event) => void): Promise<void>;
51
+ //# sourceMappingURL=aux-device-connect.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"aux-device-connect.d.ts","sourceRoot":"","sources":["../src/aux-device-connect.ts"],"names":[],"mappings":"AAcA,OAAO,EAEL,KAAK,mBAAmB,EACxB,KAAK,6BAA6B,EAClC,KAAK,qBAAqB,EAC1B,KAAK,sBAAsB,EAC3B,KAAK,wBAAwB,EAC7B,KAAK,6BAA6B,EACnC,MAAM,kBAAkB,CAAC;AAE1B,kFAAkF;AAClF,MAAM,WAAW,kBAAkB;IACjC,WAAW,CAAC,OAAO,EAAE,6BAA6B,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;IACnE,cAAc,IAAI,OAAO,CAAC,IAAI,CAAC,CAAC;CACjC;AAED,MAAM,WAAW,uBAAuB;IACtC,YAAY,CAAC,EAAE,sBAAsB,CAAC;IACtC,oBAAoB,EAAE,wBAAwB,CAAC;IAC/C;;;;;;;OAOG;IACH,qBAAqB,CAAC,EAAE,qBAAqB,CAAC;CAC/C;AAED;;;;;;;;;;GAUG;AACH,wBAAsB,gBAAgB,CACpC,OAAO,EAAE,uBAAuB,EAChC,OAAO,EAAE,kBAAkB,EAC3B,cAAc,EAAE,mBAAmB,GAAG,IAAI,EAC1C,kBAAkB,EAAE,CAAC,KAAK,EAAE,KAAK,KAAK,IAAI,GACzC,OAAO,CAAC,mBAAmB,CAAC,CAgC9B;AAED;;;;;;;;;;;GAWG;AACH,wBAAsB,eAAe,CACnC,UAAU,EAAE,mBAAmB,EAC/B,MAAM,EAAE,6BAA6B,EACrC,OAAO,EAAE,kBAAkB,EAC3B,cAAc,EAAE,mBAAmB,GAAG,IAAI,EAC1C,kBAAkB,EAAE,CAAC,KAAK,EAAE,KAAK,KAAK,IAAI,EAC1C,qBAAqB,CAAC,EAAE,qBAAqB,GAC5C,OAAO,CAAC,mBAAmB,CAAC,CA8B9B;AAED;;;;GAIG;AACH,wBAAsB,mBAAmB,CACvC,MAAM,EAAE,mBAAmB,GAAG,IAAI,EAClC,OAAO,EAAE,kBAAkB,EAC3B,kBAAkB,EAAE,CAAC,KAAK,EAAE,KAAK,KAAK,IAAI,GACzC,OAAO,CAAC,IAAI,CAAC,CAQf"}
@@ -0,0 +1,106 @@
1
+ /**
2
+ * Shared connect/disconnect bookkeeping for the three "auxiliary" device
3
+ * kinds (opossum, paw-prints, civet-edging), factored out so
4
+ * `WebBluetoothOpossumClient`/`WebBluetoothSensorClient` don't each
5
+ * reimplement the same requestDevice → gatt.connect → adapter.onConnected →
6
+ * listener-wiring dance.
7
+ *
8
+ * Deliberately does NOT replicate `WebBluetoothDeviceClient`'s
9
+ * `autoReconnect` option — none of the three new device kinds need it (see
10
+ * the `OpossumClient`/`SensorDeviceClient` contracts, which only require
11
+ * connect/disconnect/state, no reconnect semantics), and skipping it keeps
12
+ * this helper — and the two clients built on it — simple.
13
+ */
14
+ import { getWebBluetoothAvailability } from './availability.js';
15
+ import { runWithGattReadyRetry, } from '@dg-kit/protocol';
16
+ /**
17
+ * Opens the Bluetooth chooser scoped to `options.requestDeviceOptions`,
18
+ * connects GATT, and hands the connection to `adapter.onConnected()`.
19
+ * Mirrors `WebBluetoothDeviceClient.connect()`'s "replace the previous
20
+ * device only after the new one succeeds" ordering, minus the reconnect
21
+ * bookkeeping that client also carries.
22
+ *
23
+ * Returns the newly connected device; the caller is responsible for storing
24
+ * it and passing it back in on the next call (as `previousDevice`) and to
25
+ * `disconnectAuxDevice`.
26
+ */
27
+ export async function connectAuxDevice(options, adapter, previousDevice, onGattDisconnected) {
28
+ const nav = options.navigatorRef ??
29
+ (typeof navigator === 'undefined'
30
+ ? undefined
31
+ : navigator);
32
+ const availability = getWebBluetoothAvailability(nav);
33
+ if (!availability.supported) {
34
+ throw new Error(availability.reason);
35
+ }
36
+ const bluetooth = nav?.bluetooth;
37
+ if (!bluetooth) {
38
+ throw new Error('当前环境不支持 Web Bluetooth');
39
+ }
40
+ const nextDevice = await bluetooth.requestDevice(options.requestDeviceOptions);
41
+ const gatt = nextDevice.gatt;
42
+ if (!gatt) {
43
+ throw new Error('所选蓝牙设备不支持 GATT');
44
+ }
45
+ const server = await gatt.connect();
46
+ return attachAuxDevice(nextDevice, server, adapter, previousDevice, onGattDisconnected, options.gattReadyRetryOptions);
47
+ }
48
+ /**
49
+ * Attaches to an already-obtained `(device, server)` pair instead of
50
+ * running this helper's own `bluetooth.requestDevice()` chooser prompt —
51
+ * the aux-device counterpart to `WebBluetoothDeviceClient.connectDevice()`.
52
+ * Lets a caller that already ran ONE shared chooser scoped to every DG-Lab
53
+ * device kind (see `requestDgLabDevice()`) and identified the picked
54
+ * device's kind via `detectDeviceKind()` hand it straight to the matching
55
+ * client, instead of needing a second, kind-scoped chooser prompt.
56
+ * `gatt.connect()` must already have been called by the caller; this only
57
+ * runs the adapter handshake and the same replace-previous-device
58
+ * bookkeeping `connectAuxDevice()` does.
59
+ */
60
+ export async function attachAuxDevice(nextDevice, server, adapter, previousDevice, onGattDisconnected, gattReadyRetryOptions) {
61
+ const gatt = nextDevice.gatt;
62
+ const shouldReplacePrevious = !!previousDevice && previousDevice !== nextDevice;
63
+ if (shouldReplacePrevious) {
64
+ previousDevice.removeEventListener('gattserverdisconnected', onGattDisconnected);
65
+ }
66
+ try {
67
+ await runWithGattReadyRetry(() => adapter.onConnected({ device: nextDevice, server }), gattReadyRetryOptions ?? {});
68
+ }
69
+ catch (error) {
70
+ if (shouldReplacePrevious && isGattConnected(previousDevice)) {
71
+ previousDevice.addEventListener('gattserverdisconnected', onGattDisconnected);
72
+ }
73
+ if (gatt?.connected) {
74
+ gatt.disconnect();
75
+ }
76
+ throw error;
77
+ }
78
+ nextDevice.addEventListener('gattserverdisconnected', onGattDisconnected);
79
+ if (shouldReplacePrevious) {
80
+ disconnectDeviceGatt(previousDevice);
81
+ }
82
+ return nextDevice;
83
+ }
84
+ /**
85
+ * User-initiated disconnect: removes the listener BEFORE calling
86
+ * `gatt.disconnect()` so the resulting `gattserverdisconnected` event never
87
+ * reaches `onGattDisconnected` a second time.
88
+ */
89
+ export async function disconnectAuxDevice(device, adapter, onGattDisconnected) {
90
+ if (device) {
91
+ device.removeEventListener('gattserverdisconnected', onGattDisconnected);
92
+ if (device.gatt?.connected) {
93
+ device.gatt.disconnect();
94
+ }
95
+ }
96
+ await adapter.onDisconnected();
97
+ }
98
+ function isGattConnected(device) {
99
+ return !!device?.gatt?.connected;
100
+ }
101
+ function disconnectDeviceGatt(device) {
102
+ if (!device?.gatt?.connected)
103
+ return;
104
+ device.gatt.disconnect();
105
+ }
106
+ //# sourceMappingURL=aux-device-connect.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"aux-device-connect.js","sourceRoot":"","sources":["../src/aux-device-connect.ts"],"names":[],"mappings":"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"}
package/dist/index.d.ts CHANGED
@@ -1,4 +1,8 @@
1
1
  export { getWebBluetoothAvailability } from './availability.js';
2
2
  export { WebBluetoothDeviceClient, type WebBluetoothDeviceClientOptions, type ReconnectState, } from './client.js';
3
3
  export { requestDgLabDevice, type RequestDgLabDeviceOptions, type RequestedDgLabDevice, } from './picker.js';
4
+ export { WebBluetoothOpossumClient, type WebBluetoothOpossumClientOptions, } from './opossum-client.js';
5
+ export { WebBluetoothSensorClient, WebBluetoothPawPrintsClient, WebBluetoothCivetEdgingClient, type WebBluetoothSensorClientOptions, type WebBluetoothAuxSensorClientOptions, } from './sensor-client.js';
6
+ export { connectAuxDevice, attachAuxDevice, disconnectAuxDevice, type ConnectableAdapter, type AuxDeviceConnectOptions, } from './aux-device-connect.js';
7
+ export { PAW_PRINTS_REQUEST_DEVICE_OPTIONS, CIVET_EDGING_REQUEST_DEVICE_OPTIONS, OPOSSUM_REQUEST_DEVICE_OPTIONS, } from './request-device-options.js';
4
8
  //# sourceMappingURL=index.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,2BAA2B,EAAE,MAAM,mBAAmB,CAAC;AAChE,OAAO,EACL,wBAAwB,EACxB,KAAK,+BAA+B,EACpC,KAAK,cAAc,GACpB,MAAM,aAAa,CAAC;AACrB,OAAO,EACL,kBAAkB,EAClB,KAAK,yBAAyB,EAC9B,KAAK,oBAAoB,GAC1B,MAAM,aAAa,CAAC"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,2BAA2B,EAAE,MAAM,mBAAmB,CAAC;AAChE,OAAO,EACL,wBAAwB,EACxB,KAAK,+BAA+B,EACpC,KAAK,cAAc,GACpB,MAAM,aAAa,CAAC;AACrB,OAAO,EACL,kBAAkB,EAClB,KAAK,yBAAyB,EAC9B,KAAK,oBAAoB,GAC1B,MAAM,aAAa,CAAC;AACrB,OAAO,EACL,yBAAyB,EACzB,KAAK,gCAAgC,GACtC,MAAM,qBAAqB,CAAC;AAC7B,OAAO,EACL,wBAAwB,EACxB,2BAA2B,EAC3B,6BAA6B,EAC7B,KAAK,+BAA+B,EACpC,KAAK,kCAAkC,GACxC,MAAM,oBAAoB,CAAC;AAC5B,OAAO,EACL,gBAAgB,EAChB,eAAe,EACf,mBAAmB,EACnB,KAAK,kBAAkB,EACvB,KAAK,uBAAuB,GAC7B,MAAM,yBAAyB,CAAC;AACjC,OAAO,EACL,iCAAiC,EACjC,mCAAmC,EACnC,8BAA8B,GAC/B,MAAM,6BAA6B,CAAC"}
package/dist/index.js CHANGED
@@ -1,4 +1,8 @@
1
1
  export { getWebBluetoothAvailability } from './availability.js';
2
2
  export { WebBluetoothDeviceClient, } from './client.js';
3
3
  export { requestDgLabDevice, } from './picker.js';
4
+ export { WebBluetoothOpossumClient, } from './opossum-client.js';
5
+ export { WebBluetoothSensorClient, WebBluetoothPawPrintsClient, WebBluetoothCivetEdgingClient, } from './sensor-client.js';
6
+ export { connectAuxDevice, attachAuxDevice, disconnectAuxDevice, } from './aux-device-connect.js';
7
+ export { PAW_PRINTS_REQUEST_DEVICE_OPTIONS, CIVET_EDGING_REQUEST_DEVICE_OPTIONS, OPOSSUM_REQUEST_DEVICE_OPTIONS, } from './request-device-options.js';
4
8
  //# sourceMappingURL=index.js.map
package/dist/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,2BAA2B,EAAE,MAAM,mBAAmB,CAAC;AAChE,OAAO,EACL,wBAAwB,GAGzB,MAAM,aAAa,CAAC;AACrB,OAAO,EACL,kBAAkB,GAGnB,MAAM,aAAa,CAAC"}
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,2BAA2B,EAAE,MAAM,mBAAmB,CAAC;AAChE,OAAO,EACL,wBAAwB,GAGzB,MAAM,aAAa,CAAC;AACrB,OAAO,EACL,kBAAkB,GAGnB,MAAM,aAAa,CAAC;AACrB,OAAO,EACL,yBAAyB,GAE1B,MAAM,qBAAqB,CAAC;AAC7B,OAAO,EACL,wBAAwB,EACxB,2BAA2B,EAC3B,6BAA6B,GAG9B,MAAM,oBAAoB,CAAC;AAC5B,OAAO,EACL,gBAAgB,EAChB,eAAe,EACf,mBAAmB,GAGpB,MAAM,yBAAyB,CAAC;AACjC,OAAO,EACL,iCAAiC,EACjC,mCAAmC,EACnC,8BAA8B,GAC/B,MAAM,6BAA6B,CAAC"}
@@ -0,0 +1,37 @@
1
+ /**
2
+ * Web Bluetooth-backed `OpossumClient`. Wraps `OpossumVibrateAdapter` the
3
+ * same way `WebBluetoothDeviceClient` wraps `CoyoteProtocolAdapter` for
4
+ * Coyote, minus the auto-reconnect option (see `aux-device-connect.ts`'s
5
+ * doc comment for why that's intentionally out of scope here).
6
+ */
7
+ import type { OpossumCommand } from '@dg-kit/core';
8
+ import { type OpossumClient, type OpossumCommandResult, type OpossumState } from '@dg-kit/protocol';
9
+ import type { BluetoothDeviceLike, BluetoothRemoteGATTServerLike, NavigatorBluetoothLike, RequestDeviceOptionsLike } from '@dg-kit/protocol';
10
+ export interface WebBluetoothOpossumClientOptions {
11
+ navigatorRef?: NavigatorBluetoothLike;
12
+ /** Overrides the default opossum-only scan filter — mainly for tests. */
13
+ requestDeviceOptions?: RequestDeviceOptionsLike;
14
+ }
15
+ export declare class WebBluetoothOpossumClient implements OpossumClient {
16
+ private readonly options;
17
+ private readonly adapter;
18
+ private readonly listeners;
19
+ private device;
20
+ constructor(options?: WebBluetoothOpossumClientOptions);
21
+ connect(): Promise<void>;
22
+ /**
23
+ * Attach to an already-obtained `(device, server)` pair instead of
24
+ * running this client's own chooser prompt — see
25
+ * `aux-device-connect.ts`'s `attachAuxDevice()` doc comment.
26
+ */
27
+ connectDevice(device: BluetoothDeviceLike, server: BluetoothRemoteGATTServerLike): Promise<void>;
28
+ disconnect(): Promise<void>;
29
+ getState(): Promise<OpossumState>;
30
+ execute(command: OpossumCommand): Promise<OpossumCommandResult>;
31
+ emergencyStop(): Promise<void>;
32
+ setIndicatorColor(color: number): Promise<void>;
33
+ onStateChanged(listener: (state: OpossumState) => void): () => void;
34
+ private readonly handleGattDisconnected;
35
+ private emit;
36
+ }
37
+ //# sourceMappingURL=opossum-client.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"opossum-client.d.ts","sourceRoot":"","sources":["../src/opossum-client.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AACH,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,cAAc,CAAC;AACnD,OAAO,EAEL,KAAK,aAAa,EAClB,KAAK,oBAAoB,EACzB,KAAK,YAAY,EAClB,MAAM,kBAAkB,CAAC;AAC1B,OAAO,KAAK,EACV,mBAAmB,EACnB,6BAA6B,EAC7B,sBAAsB,EACtB,wBAAwB,EACzB,MAAM,kBAAkB,CAAC;AAI1B,MAAM,WAAW,gCAAgC;IAC/C,YAAY,CAAC,EAAE,sBAAsB,CAAC;IACtC,yEAAyE;IACzE,oBAAoB,CAAC,EAAE,wBAAwB,CAAC;CACjD;AAED,qBAAa,yBAA0B,YAAW,aAAa;IAKjD,OAAO,CAAC,QAAQ,CAAC,OAAO;IAJpC,OAAO,CAAC,QAAQ,CAAC,OAAO,CAA+B;IACvD,OAAO,CAAC,QAAQ,CAAC,SAAS,CAA4C;IACtE,OAAO,CAAC,MAAM,CAAoC;gBAErB,OAAO,GAAE,gCAAqC;IAIrE,OAAO,IAAI,OAAO,CAAC,IAAI,CAAC;IAY9B;;;;OAIG;IACG,aAAa,CACjB,MAAM,EAAE,mBAAmB,EAC3B,MAAM,EAAE,6BAA6B,GACpC,OAAO,CAAC,IAAI,CAAC;IAUV,UAAU,IAAI,OAAO,CAAC,IAAI,CAAC;IAM3B,QAAQ,IAAI,OAAO,CAAC,YAAY,CAAC;IAIjC,OAAO,CAAC,OAAO,EAAE,cAAc,GAAG,OAAO,CAAC,oBAAoB,CAAC;IAK/D,aAAa,IAAI,OAAO,CAAC,IAAI,CAAC;IAI9B,iBAAiB,CAAC,KAAK,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;IAOrD,cAAc,CAAC,QAAQ,EAAE,CAAC,KAAK,EAAE,YAAY,KAAK,IAAI,GAAG,MAAM,IAAI;IAOnE,OAAO,CAAC,QAAQ,CAAC,sBAAsB,CAKrC;IAEF,OAAO,CAAC,IAAI;CAKb"}
@@ -0,0 +1,66 @@
1
+ import { OpossumVibrateAdapter, } from '@dg-kit/protocol';
2
+ import { attachAuxDevice, connectAuxDevice, disconnectAuxDevice } from './aux-device-connect.js';
3
+ import { OPOSSUM_REQUEST_DEVICE_OPTIONS } from './request-device-options.js';
4
+ export class WebBluetoothOpossumClient {
5
+ options;
6
+ adapter = new OpossumVibrateAdapter();
7
+ listeners = new Set();
8
+ device = null;
9
+ constructor(options = {}) {
10
+ this.options = options;
11
+ this.adapter.onStateChanged((state) => this.emit(state));
12
+ }
13
+ async connect() {
14
+ this.device = await connectAuxDevice({
15
+ navigatorRef: this.options.navigatorRef,
16
+ requestDeviceOptions: this.options.requestDeviceOptions ?? OPOSSUM_REQUEST_DEVICE_OPTIONS,
17
+ }, this.adapter, this.device, this.handleGattDisconnected);
18
+ }
19
+ /**
20
+ * Attach to an already-obtained `(device, server)` pair instead of
21
+ * running this client's own chooser prompt — see
22
+ * `aux-device-connect.ts`'s `attachAuxDevice()` doc comment.
23
+ */
24
+ async connectDevice(device, server) {
25
+ this.device = await attachAuxDevice(device, server, this.adapter, this.device, this.handleGattDisconnected);
26
+ }
27
+ async disconnect() {
28
+ const device = this.device;
29
+ this.device = null;
30
+ await disconnectAuxDevice(device, this.adapter, this.handleGattDisconnected);
31
+ }
32
+ async getState() {
33
+ return this.adapter.getState();
34
+ }
35
+ async execute(command) {
36
+ const state = await this.adapter.execute(command);
37
+ return { state };
38
+ }
39
+ async emergencyStop() {
40
+ await this.adapter.emergencyStop();
41
+ }
42
+ async setIndicatorColor(color) {
43
+ // enableButtonReporting stays on — a purely cosmetic color change must
44
+ // not silently disable the button-press notifications a caller relies
45
+ // on, mirroring civet-edging's setIndicatorColor() doc comment.
46
+ await this.adapter.setLed(color, true);
47
+ }
48
+ onStateChanged(listener) {
49
+ this.listeners.add(listener);
50
+ return () => {
51
+ this.listeners.delete(listener);
52
+ };
53
+ }
54
+ handleGattDisconnected = () => {
55
+ const device = this.device;
56
+ this.device = null;
57
+ device?.removeEventListener('gattserverdisconnected', this.handleGattDisconnected);
58
+ void this.adapter.onDisconnected();
59
+ };
60
+ emit(state) {
61
+ for (const listener of this.listeners) {
62
+ listener(state);
63
+ }
64
+ }
65
+ }
66
+ //# sourceMappingURL=opossum-client.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"opossum-client.js","sourceRoot":"","sources":["../src/opossum-client.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,18 @@
1
+ import { type RequestDeviceOptionsLike } from '@dg-kit/protocol';
2
+ /**
3
+ * Per-kind Web Bluetooth scan filters for the three new 47L12x-family device
4
+ * kinds, each scoped to just that kind's name prefix.
5
+ *
6
+ * Deliberately narrower than `@dg-kit/protocol`'s `DG_LAB_REQUEST_DEVICE_OPTIONS`
7
+ * (which matches every known kind in a single picker). A caller giving each
8
+ * kind its own dedicated connect button should use these so the chooser it
9
+ * opens only ever lists devices of that one kind.
10
+ *
11
+ * All four 47L12x-family kinds (Coyote V3 included) share the identical
12
+ * primary/battery GATT services, so only the name-prefix filter differs
13
+ * between these three constants.
14
+ */
15
+ export declare const PAW_PRINTS_REQUEST_DEVICE_OPTIONS: RequestDeviceOptionsLike;
16
+ export declare const CIVET_EDGING_REQUEST_DEVICE_OPTIONS: RequestDeviceOptionsLike;
17
+ export declare const OPOSSUM_REQUEST_DEVICE_OPTIONS: RequestDeviceOptionsLike;
18
+ //# sourceMappingURL=request-device-options.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"request-device-options.d.ts","sourceRoot":"","sources":["../src/request-device-options.ts"],"names":[],"mappings":"AAAA,OAAO,EAML,KAAK,wBAAwB,EAC9B,MAAM,kBAAkB,CAAC;AAE1B;;;;;;;;;;;;GAYG;AACH,eAAO,MAAM,iCAAiC,EAAE,wBAG/C,CAAC;AAEF,eAAO,MAAM,mCAAmC,EAAE,wBAGjD,CAAC;AAEF,eAAO,MAAM,8BAA8B,EAAE,wBAG5C,CAAC"}
@@ -0,0 +1,27 @@
1
+ import { CIVET_DEVICE_NAME_PREFIX, OPOSSUM_DEVICE_NAME_PREFIX, PAW_PRINTS_DEVICE_NAME_PREFIX, V3_BATTERY_SERVICE, V3_PRIMARY_SERVICE, } from '@dg-kit/protocol';
2
+ /**
3
+ * Per-kind Web Bluetooth scan filters for the three new 47L12x-family device
4
+ * kinds, each scoped to just that kind's name prefix.
5
+ *
6
+ * Deliberately narrower than `@dg-kit/protocol`'s `DG_LAB_REQUEST_DEVICE_OPTIONS`
7
+ * (which matches every known kind in a single picker). A caller giving each
8
+ * kind its own dedicated connect button should use these so the chooser it
9
+ * opens only ever lists devices of that one kind.
10
+ *
11
+ * All four 47L12x-family kinds (Coyote V3 included) share the identical
12
+ * primary/battery GATT services, so only the name-prefix filter differs
13
+ * between these three constants.
14
+ */
15
+ export const PAW_PRINTS_REQUEST_DEVICE_OPTIONS = {
16
+ filters: [{ namePrefix: PAW_PRINTS_DEVICE_NAME_PREFIX }],
17
+ optionalServices: [V3_PRIMARY_SERVICE, V3_BATTERY_SERVICE],
18
+ };
19
+ export const CIVET_EDGING_REQUEST_DEVICE_OPTIONS = {
20
+ filters: [{ namePrefix: CIVET_DEVICE_NAME_PREFIX }],
21
+ optionalServices: [V3_PRIMARY_SERVICE, V3_BATTERY_SERVICE],
22
+ };
23
+ export const OPOSSUM_REQUEST_DEVICE_OPTIONS = {
24
+ filters: [{ namePrefix: OPOSSUM_DEVICE_NAME_PREFIX }],
25
+ optionalServices: [V3_PRIMARY_SERVICE, V3_BATTERY_SERVICE],
26
+ };
27
+ //# sourceMappingURL=request-device-options.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"request-device-options.js","sourceRoot":"","sources":["../src/request-device-options.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,wBAAwB,EACxB,0BAA0B,EAC1B,6BAA6B,EAC7B,kBAAkB,EAClB,kBAAkB,GAEnB,MAAM,kBAAkB,CAAC;AAE1B;;;;;;;;;;;;GAYG;AACH,MAAM,CAAC,MAAM,iCAAiC,GAA6B;IACzE,OAAO,EAAE,CAAC,EAAE,UAAU,EAAE,6BAA6B,EAAE,CAAC;IACxD,gBAAgB,EAAE,CAAC,kBAAkB,EAAE,kBAAkB,CAAC;CAC3D,CAAC;AAEF,MAAM,CAAC,MAAM,mCAAmC,GAA6B;IAC3E,OAAO,EAAE,CAAC,EAAE,UAAU,EAAE,wBAAwB,EAAE,CAAC;IACnD,gBAAgB,EAAE,CAAC,kBAAkB,EAAE,kBAAkB,CAAC;CAC3D,CAAC;AAEF,MAAM,CAAC,MAAM,8BAA8B,GAA6B;IACtE,OAAO,EAAE,CAAC,EAAE,UAAU,EAAE,0BAA0B,EAAE,CAAC;IACrD,gBAAgB,EAAE,CAAC,kBAAkB,EAAE,kBAAkB,CAAC;CAC3D,CAAC"}
@@ -0,0 +1,52 @@
1
+ /**
2
+ * Web Bluetooth-backed `SensorDeviceClient<TReading>`. A single generic
3
+ * client wraps either of `@dg-kit/protocol`'s sensor adapters
4
+ * (`PawPrintsSensorAdapter`, `CivetPressureSensorAdapter`) — they share the
5
+ * exact same `WebBluetoothSensorAdapter<TReading>` shape
6
+ * (onConnected/onDisconnected/getState/subscribe/onStateChanged), only their
7
+ * LED-setting method name differs (`setLedSolid` vs `setIndicatorColor`),
8
+ * which is why `setIndicatorColor` is threaded in as a constructor callback
9
+ * rather than called directly on the adapter.
10
+ */
11
+ import { type CivetPressureReading, type PawPrintsReading, type WebBluetoothSensorAdapter } from '@dg-kit/protocol';
12
+ import type { BluetoothDeviceLike, BluetoothRemoteGATTServerLike, NavigatorBluetoothLike, RequestDeviceOptionsLike } from '@dg-kit/protocol';
13
+ import type { SensorState } from '@dg-kit/core';
14
+ import type { SensorDeviceClient } from '@dg-kit/core';
15
+ export interface WebBluetoothSensorClientOptions<TReading> {
16
+ adapter: WebBluetoothSensorAdapter<TReading>;
17
+ requestDeviceOptions: RequestDeviceOptionsLike;
18
+ navigatorRef?: NavigatorBluetoothLike;
19
+ setIndicatorColor: (color: number) => Promise<void>;
20
+ }
21
+ export declare class WebBluetoothSensorClient<TReading> implements SensorDeviceClient<TReading> {
22
+ private readonly options;
23
+ private readonly listeners;
24
+ private device;
25
+ constructor(options: WebBluetoothSensorClientOptions<TReading>);
26
+ connect(): Promise<void>;
27
+ /**
28
+ * Attach to an already-obtained `(device, server)` pair instead of
29
+ * running this client's own chooser prompt — see
30
+ * `aux-device-connect.ts`'s `attachAuxDevice()` doc comment.
31
+ */
32
+ connectDevice(device: BluetoothDeviceLike, server: BluetoothRemoteGATTServerLike): Promise<void>;
33
+ disconnect(): Promise<void>;
34
+ getState(): Promise<SensorState>;
35
+ subscribe(listener: (reading: TReading) => void): () => void;
36
+ onStateChanged(listener: (state: SensorState) => void): () => void;
37
+ setIndicatorColor(color: number): Promise<void>;
38
+ private readonly handleGattDisconnected;
39
+ private emit;
40
+ }
41
+ export interface WebBluetoothAuxSensorClientOptions {
42
+ navigatorRef?: NavigatorBluetoothLike;
43
+ /** Overrides the default kind-scoped scan filter — mainly for tests. */
44
+ requestDeviceOptions?: RequestDeviceOptionsLike;
45
+ }
46
+ export declare class WebBluetoothPawPrintsClient extends WebBluetoothSensorClient<PawPrintsReading> {
47
+ constructor(options?: WebBluetoothAuxSensorClientOptions);
48
+ }
49
+ export declare class WebBluetoothCivetEdgingClient extends WebBluetoothSensorClient<CivetPressureReading> {
50
+ constructor(options?: WebBluetoothAuxSensorClientOptions);
51
+ }
52
+ //# sourceMappingURL=sensor-client.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"sensor-client.d.ts","sourceRoot":"","sources":["../src/sensor-client.ts"],"names":[],"mappings":"AAAA;;;;;;;;;GASG;AACH,OAAO,EAGL,KAAK,oBAAoB,EACzB,KAAK,gBAAgB,EACrB,KAAK,yBAAyB,EAC/B,MAAM,kBAAkB,CAAC;AAC1B,OAAO,KAAK,EACV,mBAAmB,EACnB,6BAA6B,EAC7B,sBAAsB,EACtB,wBAAwB,EACzB,MAAM,kBAAkB,CAAC;AAC1B,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,cAAc,CAAC;AAChD,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,cAAc,CAAC;AAOvD,MAAM,WAAW,+BAA+B,CAAC,QAAQ;IACvD,OAAO,EAAE,yBAAyB,CAAC,QAAQ,CAAC,CAAC;IAC7C,oBAAoB,EAAE,wBAAwB,CAAC;IAC/C,YAAY,CAAC,EAAE,sBAAsB,CAAC;IACtC,iBAAiB,EAAE,CAAC,KAAK,EAAE,MAAM,KAAK,OAAO,CAAC,IAAI,CAAC,CAAC;CACrD;AAED,qBAAa,wBAAwB,CAAC,QAAQ,CAAE,YAAW,kBAAkB,CAAC,QAAQ,CAAC;IAIzE,OAAO,CAAC,QAAQ,CAAC,OAAO;IAHpC,OAAO,CAAC,QAAQ,CAAC,SAAS,CAA2C;IACrE,OAAO,CAAC,MAAM,CAAoC;gBAErB,OAAO,EAAE,+BAA+B,CAAC,QAAQ,CAAC;IAIzE,OAAO,IAAI,OAAO,CAAC,IAAI,CAAC;IAY9B;;;;OAIG;IACG,aAAa,CACjB,MAAM,EAAE,mBAAmB,EAC3B,MAAM,EAAE,6BAA6B,GACpC,OAAO,CAAC,IAAI,CAAC;IAUV,UAAU,IAAI,OAAO,CAAC,IAAI,CAAC;IAM3B,QAAQ,IAAI,OAAO,CAAC,WAAW,CAAC;IAItC,SAAS,CAAC,QAAQ,EAAE,CAAC,OAAO,EAAE,QAAQ,KAAK,IAAI,GAAG,MAAM,IAAI;IAI5D,cAAc,CAAC,QAAQ,EAAE,CAAC,KAAK,EAAE,WAAW,KAAK,IAAI,GAAG,MAAM,IAAI;IAO5D,iBAAiB,CAAC,KAAK,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;IAIrD,OAAO,CAAC,QAAQ,CAAC,sBAAsB,CAKrC;IAEF,OAAO,CAAC,IAAI;CAKb;AAED,MAAM,WAAW,kCAAkC;IACjD,YAAY,CAAC,EAAE,sBAAsB,CAAC;IACtC,wEAAwE;IACxE,oBAAoB,CAAC,EAAE,wBAAwB,CAAC;CACjD;AAED,qBAAa,2BAA4B,SAAQ,wBAAwB,CAAC,gBAAgB,CAAC;gBAC7E,OAAO,GAAE,kCAAuC;CAU7D;AAED,qBAAa,6BAA8B,SAAQ,wBAAwB,CAAC,oBAAoB,CAAC;gBACnF,OAAO,GAAE,kCAAuC;CAW7D"}
@@ -0,0 +1,93 @@
1
+ /**
2
+ * Web Bluetooth-backed `SensorDeviceClient<TReading>`. A single generic
3
+ * client wraps either of `@dg-kit/protocol`'s sensor adapters
4
+ * (`PawPrintsSensorAdapter`, `CivetPressureSensorAdapter`) — they share the
5
+ * exact same `WebBluetoothSensorAdapter<TReading>` shape
6
+ * (onConnected/onDisconnected/getState/subscribe/onStateChanged), only their
7
+ * LED-setting method name differs (`setLedSolid` vs `setIndicatorColor`),
8
+ * which is why `setIndicatorColor` is threaded in as a constructor callback
9
+ * rather than called directly on the adapter.
10
+ */
11
+ import { CivetPressureSensorAdapter, PawPrintsSensorAdapter, } from '@dg-kit/protocol';
12
+ import { attachAuxDevice, connectAuxDevice, disconnectAuxDevice } from './aux-device-connect.js';
13
+ import { CIVET_EDGING_REQUEST_DEVICE_OPTIONS, PAW_PRINTS_REQUEST_DEVICE_OPTIONS, } from './request-device-options.js';
14
+ export class WebBluetoothSensorClient {
15
+ options;
16
+ listeners = new Set();
17
+ device = null;
18
+ constructor(options) {
19
+ this.options = options;
20
+ this.options.adapter.onStateChanged((state) => this.emit(state));
21
+ }
22
+ async connect() {
23
+ this.device = await connectAuxDevice({
24
+ navigatorRef: this.options.navigatorRef,
25
+ requestDeviceOptions: this.options.requestDeviceOptions,
26
+ }, this.options.adapter, this.device, this.handleGattDisconnected);
27
+ }
28
+ /**
29
+ * Attach to an already-obtained `(device, server)` pair instead of
30
+ * running this client's own chooser prompt — see
31
+ * `aux-device-connect.ts`'s `attachAuxDevice()` doc comment.
32
+ */
33
+ async connectDevice(device, server) {
34
+ this.device = await attachAuxDevice(device, server, this.options.adapter, this.device, this.handleGattDisconnected);
35
+ }
36
+ async disconnect() {
37
+ const device = this.device;
38
+ this.device = null;
39
+ await disconnectAuxDevice(device, this.options.adapter, this.handleGattDisconnected);
40
+ }
41
+ async getState() {
42
+ return this.options.adapter.getState();
43
+ }
44
+ subscribe(listener) {
45
+ return this.options.adapter.subscribe(listener);
46
+ }
47
+ onStateChanged(listener) {
48
+ this.listeners.add(listener);
49
+ return () => {
50
+ this.listeners.delete(listener);
51
+ };
52
+ }
53
+ async setIndicatorColor(color) {
54
+ await this.options.setIndicatorColor(color);
55
+ }
56
+ handleGattDisconnected = () => {
57
+ const device = this.device;
58
+ this.device = null;
59
+ device?.removeEventListener('gattserverdisconnected', this.handleGattDisconnected);
60
+ void this.options.adapter.onDisconnected();
61
+ };
62
+ emit(state) {
63
+ for (const listener of this.listeners) {
64
+ listener(state);
65
+ }
66
+ }
67
+ }
68
+ export class WebBluetoothPawPrintsClient extends WebBluetoothSensorClient {
69
+ constructor(options = {}) {
70
+ const adapter = new PawPrintsSensorAdapter();
71
+ super({
72
+ adapter,
73
+ navigatorRef: options.navigatorRef,
74
+ requestDeviceOptions: options.requestDeviceOptions ?? PAW_PRINTS_REQUEST_DEVICE_OPTIONS,
75
+ // Paw-prints exposes a dedicated "set solid color" LED command.
76
+ setIndicatorColor: (color) => adapter.setLedSolid(color),
77
+ });
78
+ }
79
+ }
80
+ export class WebBluetoothCivetEdgingClient extends WebBluetoothSensorClient {
81
+ constructor(options = {}) {
82
+ const adapter = new CivetPressureSensorAdapter();
83
+ super({
84
+ adapter,
85
+ navigatorRef: options.navigatorRef,
86
+ requestDeviceOptions: options.requestDeviceOptions ?? CIVET_EDGING_REQUEST_DEVICE_OPTIONS,
87
+ // civet-edging has no standalone "set color" opcode — setIndicatorColor()
88
+ // re-sends the pressure-reporting packet with streaming state preserved.
89
+ setIndicatorColor: (color) => adapter.setIndicatorColor(color),
90
+ });
91
+ }
92
+ }
93
+ //# sourceMappingURL=sensor-client.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"sensor-client.js","sourceRoot":"","sources":["../src/sensor-client.ts"],"names":[],"mappings":"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"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@dg-kit/transport-webbluetooth",
3
- "version": "1.11.0",
3
+ "version": "1.13.0",
4
4
  "description": "Web Bluetooth DeviceClient for DG-Lab Coyote (browser-only)",
5
5
  "license": "MIT",
6
6
  "author": "0xNullAI",
@@ -27,8 +27,8 @@
27
27
  "access": "public"
28
28
  },
29
29
  "dependencies": {
30
- "@dg-kit/core": "1.11.0",
31
- "@dg-kit/protocol": "1.11.0"
30
+ "@dg-kit/core": "1.13.0",
31
+ "@dg-kit/protocol": "1.13.0"
32
32
  },
33
33
  "scripts": {
34
34
  "build": "tsc -p tsconfig.json",