import type { DeviceClient, DeviceCommand, DeviceCommandResult, DeviceState } from '@dg-kit/core'; import type { BluetoothDeviceLike, BluetoothRemoteGATTServerLike, WebBluetoothProtocolAdapter } from '@dg-kit/protocol'; import { type GattReadyRetryOptions } from './gatt-ready.js'; import { type DeviceSelectionController } from './scan.js'; export type { DeviceSelectionController, DiscoveredDevice } from './scan.js'; export type ReconnectState = 'reconnecting' | 'reconnected' | 'failed'; export interface TauriBlecDeviceClientOptions extends GattReadyRetryOptions { protocol: WebBluetoothProtocolAdapter; /** * Called immediately after scan starts. The host UI opens the device picker * and subscribes to live updates via the controller. Resolves with the * chosen device address, or `null` if the user cancels. */ selectDevice: (controller: DeviceSelectionController) => Promise; /** * Optional client-side filter applied to scan results before they reach * `selectDevice`. Coyote V2 names start with `D-LAB ESTIM01`; V3 with `47L121`. * Default: no filter (caller must filter or DevicePicker shows all). */ namePrefixes?: string[]; /** Scan window in milliseconds. Defaults to 8000. */ scanDurationMs?: number; /** * When true, an unexpected disconnect signalled by plugin-blec (device * out of range, OS killed the link, etc.) triggers a silent reconnect * using the last-connected device's address — no new scan / selectDevice * prompt. A user-initiated `disconnect()` call always cancels any * pending or in-flight reconnect and is never followed by one, even if * plugin-blec's own disconnect signal arrives afterward. Defaults to * false (opt-in), mirroring `transport-webbluetooth`. */ autoReconnect?: boolean; /** Maximum reconnect attempts before giving up. Defaults to 3. */ reconnectAttempts?: number; /** * Delay (ms) before each reconnect attempt. Index N is used for the * (N+1)-th attempt. If fewer entries than attempts, the last entry is * reused. Defaults to [500, 1500, 4000]. */ reconnectBackoffMs?: number[]; /** Notified when entering/leaving the reconnecting state. */ onReconnectStateChange?: (state: ReconnectState) => void; } /** * A `DeviceClient` scoped to ONE Coyote connection, identified by BLE * address once connected. The multi-connection fork this package is pinned * to (`0xNullAI/tauri-plugin-blec-multi`) lets several `TauriBlecDeviceClient` * (and Opossum/sensor client) instances stay connected at the same time — * this class never assumes it's the only connection, so it always passes * its own `address` to plugin-blec instead of relying on the address-less * "sole connected device" overloads (which now throw `AmbiguousDevice` once * a second device connects). */ export declare class TauriBlecDeviceClient implements DeviceClient { private readonly options; private readonly listeners; private connected; private connecting; private disconnecting; private fireDisconnect; /** * Address of the currently-connected device, or (while disconnected) the * last-connected address kept only for auto-reconnect. */ private lastAddress; private lastDeviceName; private reconnecting; private reconnectTimer; /** * Set only while connected via `connectDevice()` (the unified-picker * passthrough) instead of this client's own `connect()`. Tracked * separately from `lastAddress`/`fireDisconnect` so `disconnect()` can * tear down through the device's own `gatt.disconnect()` — the shim * `connectDevice()` was handed already wires `fireDisconnect` + * `api.disconnect()` together, so replaying both here would double up. * A reconnect always re-establishes through `establishConnection()` * (fresh `api.connect()` + a brand-new shim), which clears this back to * `null`, so it's stale exactly never past the first passive drop. */ private passthroughDevice; constructor(options: TauriBlecDeviceClientOptions); /** The BLE address of the currently-connected device, or `null` if disconnected. */ get address(): string | null; /** * Identity of the currently-held device, or `null` while none is held. * * The same value as `address` (the BLE address, stable across reconnects), * under the name `WebBluetoothDeviceClient` also uses — so a caller holding * several devices can key them identically on both platforms instead of * branching on which transport it happens to be running. */ get deviceId(): string | null; connect(): Promise; private connectInner; /** * Attach to an already-obtained, already-plugin-blec-connected * `(device, server)` pair instead of running this client's own scan + * `selectDevice()` + `api.connect()`. Lets a caller that already ran ONE * shared scan+picker across every DG-Lab device kind * (`requestDgLabDeviceTauri()`) and identified the picked device as a * Coyote via `detectDeviceKind()` hand the device straight to this * client, rather than needing a second, Coyote-only scan+picker. Mirrors * `@dg-kit/transport-webbluetooth`'s `WebBluetoothDeviceClient.connectDevice()`. */ connectDevice(device: BluetoothDeviceLike, server: BluetoothRemoteGATTServerLike): Promise; /** * The `connectDevice()` counterpart to `establishConnection()`: runs the * GATT-ready-retried protocol handshake against an already-connected * `(device, server)` pair instead of driving `api.connect()` itself. * `device`'s `gattserverdisconnected` event (fired by the shim the caller * built via `createGattShim()`) is this client's only signal of an * unexpected drop, since the plugin-blec-level `onDisconnect` callback was * already claimed by whoever called `api.connect()` — wiring a DOM * listener here reaches the same `handlePluginDisconnectSignal()` path * `establishConnection()`'s direct callback reaches, so autoReconnect * behaves identically regardless of which path made the connection. */ private attachConnection; private readonly handlePassthroughDisconnect; /** * Drives plugin-blec's connect flow plus the GATT-ready retry for a known * device address. Shared by the initial `connect()` (after scan + * selectDevice) and by `tryReconnect()` (which skips straight here with * the last-connected address — no new scan / chooser prompt). */ private establishConnection; /** * Runs after plugin-blec signals a disconnect (device out of range, OS * killed the link, or a user-initiated teardown plugin-blec happened to * echo back). Always tells the protocol layer we've dropped; only * schedules a reconnect when the drop wasn't caused by our own * `disconnect()` and the caller opted in. */ private handlePluginDisconnectSignal; private scheduleReconnect; private tryReconnect; private forceTeardown; private cancelReconnect; disconnect(): Promise; execute(command: DeviceCommand): Promise; emergencyStop(): Promise; getState(): Promise; onStateChanged(listener: (state: DeviceState) => void): () => void; } //# sourceMappingURL=client.d.ts.map