import type { DeviceClient } from '@dg-kit/core'; import type { DeviceCommand, DeviceCommandResult, DeviceState } from '@dg-kit/core'; import { type BluetoothDeviceLike, type BluetoothRemoteGATTServerLike, type GattReadyRetryOptions, type NavigatorBluetoothLike, type RequestDeviceOptionsLike, type WebBluetoothProtocolAdapter } from '@dg-kit/protocol'; export type ReconnectState = 'reconnecting' | 'reconnected' | 'failed'; export interface WebBluetoothDeviceClientOptions { protocol: WebBluetoothProtocolAdapter; navigatorRef?: NavigatorBluetoothLike; requestDeviceOptions?: RequestDeviceOptionsLike; /** * When true, a passive `gattserverdisconnected` event triggers a silent * reconnect attempt using the cached `BluetoothDevice` reference (which * survives without re-prompting the user). The user-initiated * `disconnect()` path always cancels any in-flight reconnect. */ 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; /** * Tuning for the GATT-not-ready retry wrapped around the protocol * adapter's `onConnected()` — see `runWithGattReadyRetry`'s doc. Defaults * are fine for normal use; exposed mainly for tests. */ gattReadyRetryOptions?: GattReadyRetryOptions; } /** * A `DeviceClient` scoped to ONE device connection, mirroring * `@dg-kit/transport-tauri-blec`'s `TauriBlecDeviceClient`. Several instances * may hold several devices at the same time — nothing here is module-level * state, and the protocol adapter is per-instance too. * * The one-device scoping is not an arbitrary limit, it is forced by the * protocol adapter: `protocol.onConnected()` rebinds the adapter (and with it * `emergencyStop()`) to the new device, so once a second device is handed to * the same client there is no longer any way to reach the first one to zero * it. Hence `connectDevice()` refuses a second *live* device rather than * silently evicting it — see the guard there. */ export declare class WebBluetoothDeviceClient implements DeviceClient { private readonly options; private readonly listeners; private readonly nav; private device; private disconnecting; private reconnectTimer; private reconnecting; constructor(options: WebBluetoothDeviceClientOptions); /** * Identity of the currently-held device, or `null` while none is held. * * This is `BluetoothDevice.id` — an opaque per-origin handle the browser * keeps stable across reconnects (and across visits, once the device is * remembered), which is what lets a caller keep addressing "the same * Coyote" through a drop-and-reconnect. Named to match * `TauriBlecDeviceClient.deviceId` so callers holding several devices can * key them the same way on both platforms. */ get deviceId(): string | null; connect(): Promise; /** * Attach to an already-obtained `(device, server)` pair instead of running * this client's own `bluetooth.requestDevice()` chooser prompt. * * Lets a caller that already ran ONE shared chooser scoped to every DG-Lab * device kind (Coyote + sensors + Opossum — see `DG_LAB_REQUEST_DEVICE_OPTIONS`) * and identified the picked device as a Coyote via `detectDeviceKind()` * hand the device straight to this client, rather than needing a second, * Coyote-only chooser prompt. `gatt.connect()` must already have been * called by the caller; this method only runs the protocol handshake. * * Throws `设备已连接` if this client already holds a *different, still * connected* device — connect a second `WebBluetoothDeviceClient` instead * (see the class doc). Re-attaching the device already held, or replacing * one whose link has already dropped, is allowed: that is the reconnect * path, and it is the only case where the previous device cannot be left * outputting. */ connectDevice(nextDevice: BluetoothDeviceLike, server: BluetoothRemoteGATTServerLike): Promise; disconnect(): Promise; getState(): Promise; execute(command: DeviceCommand): Promise; emergencyStop(): Promise; onStateChanged(listener: (state: DeviceState) => void): () => void; private readonly onDisconnected; private scheduleReconnect; private tryReconnect; private cancelReconnect; private emit; } //# sourceMappingURL=client.d.ts.map