@onekeyfe/hwk-desktop-noble-ble 1.2.3-alpha.2
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/dist/chunk-RNZYQRXV.mjs +39 -0
- package/dist/chunk-RNZYQRXV.mjs.map +1 -0
- package/dist/constants.d.mts +36 -0
- package/dist/constants.d.ts +36 -0
- package/dist/constants.js +59 -0
- package/dist/constants.js.map +1 -0
- package/dist/constants.mjs +15 -0
- package/dist/constants.mjs.map +1 -0
- package/dist/index.d.mts +357 -0
- package/dist/index.d.ts +357 -0
- package/dist/index.js +948 -0
- package/dist/index.js.map +1 -0
- package/dist/index.mjs +900 -0
- package/dist/index.mjs.map +1 -0
- package/package.json +82 -0
package/dist/index.d.ts
ADDED
|
@@ -0,0 +1,357 @@
|
|
|
1
|
+
import { ElectronBleScanOptions, ElectronBleConnectOptions } from '@onekeyfe/hwk-adapter-core';
|
|
2
|
+
export { THIRD_PARTY_BLE_CHANNELS, THIRD_PARTY_BLE_DEVICE_TTL_MS, THIRD_PARTY_BLE_POWER_ON_TIMEOUT_MS, THIRD_PARTY_BLE_SCAN_DURATION_MS, THIRD_PARTY_BLE_SCAN_IDLE_STOP_MS, ThirdPartyBleChannel } from './constants.js';
|
|
3
|
+
|
|
4
|
+
type BleDebugLogLevel = 'debug' | 'info' | 'warn' | 'error';
|
|
5
|
+
type BleDebugLogEntry = {
|
|
6
|
+
level: BleDebugLogLevel;
|
|
7
|
+
scope: string;
|
|
8
|
+
event: string;
|
|
9
|
+
data?: Record<string, unknown>;
|
|
10
|
+
};
|
|
11
|
+
type BleDebugLogger = (entry: BleDebugLogEntry) => void;
|
|
12
|
+
/** Replace sensitive values in place; everything else is forwarded verbatim. */
|
|
13
|
+
declare function redactBleDebugLogData(data?: Record<string, unknown>): Record<string, unknown> | undefined;
|
|
14
|
+
|
|
15
|
+
/**
|
|
16
|
+
* Shape of the API the renderer process talks to. In a real Electron app
|
|
17
|
+
* this is normally exposed via `contextBridge.exposeInMainWorld('desktopApi',
|
|
18
|
+
* { trezorBle: ... })`, but the transport accepts the bridge directly so
|
|
19
|
+
* non-Electron hosts (and unit tests) can plug in their own implementation.
|
|
20
|
+
*/
|
|
21
|
+
interface ThirdPartyBleDeviceInfo {
|
|
22
|
+
/** Stable id (noble peripheral.id) used as connectId. */
|
|
23
|
+
id: string;
|
|
24
|
+
name?: string;
|
|
25
|
+
rssi?: number;
|
|
26
|
+
advertisedServiceUuids?: string[];
|
|
27
|
+
/** Same as `name`, kept explicit to mirror noble's `advertisement.localName`. */
|
|
28
|
+
localName?: string;
|
|
29
|
+
/** Whether the peripheral advertised itself as connectable. */
|
|
30
|
+
isConnectable?: boolean | null;
|
|
31
|
+
serviceSolicitationUuids?: string[];
|
|
32
|
+
txPowerLevel?: number;
|
|
33
|
+
/** Manufacturer-specific advertisement data, hex-encoded (may embed a serial). */
|
|
34
|
+
manufacturerDataHex?: string;
|
|
35
|
+
/** Per-service advertisement data, each hex-encoded. */
|
|
36
|
+
serviceData?: Array<{
|
|
37
|
+
uuid: string;
|
|
38
|
+
dataHex: string;
|
|
39
|
+
}>;
|
|
40
|
+
/** BLE MAC/address when the OS exposes it separately from `id`. */
|
|
41
|
+
address?: string;
|
|
42
|
+
addressType?: string;
|
|
43
|
+
/** noble peripheral connection state at scan time. */
|
|
44
|
+
state?: string;
|
|
45
|
+
}
|
|
46
|
+
interface ThirdPartyBleAvailability {
|
|
47
|
+
available: boolean;
|
|
48
|
+
/** noble state: `poweredOn` / `poweredOff` / `unauthorized` / `unsupported` / `resetting` / `unknown`. */
|
|
49
|
+
state: string;
|
|
50
|
+
initialized: boolean;
|
|
51
|
+
}
|
|
52
|
+
/** One definition of the scan contract; the IPC shape lives in adapter-core. */
|
|
53
|
+
type ThirdPartyBleScanOptions = ElectronBleScanOptions;
|
|
54
|
+
interface ThirdPartyBleApi {
|
|
55
|
+
scan(options?: ThirdPartyBleScanOptions): Promise<ThirdPartyBleDeviceInfo[]>;
|
|
56
|
+
stopScan(): Promise<void>;
|
|
57
|
+
connect(id: string, options: ElectronBleConnectOptions): Promise<{
|
|
58
|
+
id: string;
|
|
59
|
+
name?: string;
|
|
60
|
+
}>;
|
|
61
|
+
disconnect(id: string): Promise<void>;
|
|
62
|
+
/** Subscribe to the BLE notify characteristic for `id`. */
|
|
63
|
+
subscribe(id: string): Promise<void>;
|
|
64
|
+
unsubscribe(id: string): Promise<void>;
|
|
65
|
+
/**
|
|
66
|
+
* Write an already-framed payload. The main process applies the framing rule
|
|
67
|
+
* recorded at connect time — splitting and zero-padding for `padded`, or
|
|
68
|
+
* writing the buffer as given for `raw`.
|
|
69
|
+
*/
|
|
70
|
+
write(id: string, hexData: string): Promise<void>;
|
|
71
|
+
checkAvailability(): Promise<ThirdPartyBleAvailability>;
|
|
72
|
+
/** Look up a previously-scanned device by id without re-scanning. */
|
|
73
|
+
getDevice(id: string): Promise<ThirdPartyBleDeviceInfo | null>;
|
|
74
|
+
/** Read current RSSI (dBm) of a *connected* peripheral. */
|
|
75
|
+
readRssi(id: string): Promise<number>;
|
|
76
|
+
/** Stop scan + disconnect every in-flight connection. */
|
|
77
|
+
cancelPairing(): Promise<void>;
|
|
78
|
+
/** Register a listener for incoming BLE notifications. Returns an unsubscribe fn. */
|
|
79
|
+
onNotification(handler: (id: string, hexData: string) => void): () => void;
|
|
80
|
+
/** Register a listener for unexpected disconnects. Returns an unsubscribe fn. */
|
|
81
|
+
onDeviceDisconnected(handler: (id: string) => void): () => void;
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
/**
|
|
85
|
+
* Subset of @stoprocent/noble we touch. We type as `any` to keep the package
|
|
86
|
+
* installable without the native module — it's loaded lazily inside main().
|
|
87
|
+
*/
|
|
88
|
+
interface NobleLike {
|
|
89
|
+
state: string;
|
|
90
|
+
on(event: string, handler: (...args: any[]) => void): NobleLike;
|
|
91
|
+
removeListener(event: string, handler: (...args: any[]) => void): NobleLike;
|
|
92
|
+
startScanningAsync(serviceUuids: string[], allowDuplicates: boolean): Promise<void>;
|
|
93
|
+
stopScanningAsync(): Promise<void>;
|
|
94
|
+
stop?(): void;
|
|
95
|
+
/**
|
|
96
|
+
* Connect by id/address with NO scan. Both native backends support this and
|
|
97
|
+
* emit a `discover` for the peripheral as a side effect: Windows synthesizes
|
|
98
|
+
* one for an unknown address (`BLEManager::Connect`, lib/win/src/ble_manager.cc)
|
|
99
|
+
* and macOS resolves it via `retrievePeripheralsWithIdentifiers`
|
|
100
|
+
* (lib/mac/src/ble_manager.mm). Optional so a stub noble can omit it.
|
|
101
|
+
*/
|
|
102
|
+
connectAsync?(idOrAddress: string): Promise<NoblePeripheralLike | undefined>;
|
|
103
|
+
cancelConnect?(idOrAddress: string): void;
|
|
104
|
+
reset?(): Promise<void>;
|
|
105
|
+
}
|
|
106
|
+
interface NoblePeripheralLike {
|
|
107
|
+
id: string;
|
|
108
|
+
advertisement: {
|
|
109
|
+
localName?: string;
|
|
110
|
+
serviceUuids?: string[];
|
|
111
|
+
manufacturerData?: Buffer;
|
|
112
|
+
serviceData?: Array<{
|
|
113
|
+
uuid: string;
|
|
114
|
+
data: Buffer;
|
|
115
|
+
}>;
|
|
116
|
+
txPowerLevel?: number;
|
|
117
|
+
serviceSolicitationUuids?: string[];
|
|
118
|
+
};
|
|
119
|
+
/** Some noble builds expose the BLE MAC/address separately from `id`. */
|
|
120
|
+
address?: string;
|
|
121
|
+
addressType?: string;
|
|
122
|
+
connectable?: boolean;
|
|
123
|
+
rssi: number;
|
|
124
|
+
state: string;
|
|
125
|
+
connectAsync(): Promise<void>;
|
|
126
|
+
cancelConnect?(): void;
|
|
127
|
+
disconnectAsync(): Promise<void>;
|
|
128
|
+
discoverSomeServicesAndCharacteristicsAsync(serviceUuids: string[], characteristicUuids: string[]): Promise<{
|
|
129
|
+
characteristics: NobleCharacteristicLike[];
|
|
130
|
+
}>;
|
|
131
|
+
/** Read live RSSI from the connected peripheral. Returns dBm. */
|
|
132
|
+
updateRssiAsync?(): Promise<number>;
|
|
133
|
+
on(event: string, handler: (...args: any[]) => void): NoblePeripheralLike;
|
|
134
|
+
removeListener(event: string, handler: (...args: any[]) => void): NoblePeripheralLike;
|
|
135
|
+
}
|
|
136
|
+
interface NobleCharacteristicLike {
|
|
137
|
+
uuid: string;
|
|
138
|
+
subscribeAsync(): Promise<void>;
|
|
139
|
+
unsubscribeAsync(): Promise<void>;
|
|
140
|
+
writeAsync(data: Buffer, withoutResponse: boolean): Promise<void>;
|
|
141
|
+
on(event: 'data', handler: (data: Buffer, isNotification: boolean) => void): NobleCharacteristicLike;
|
|
142
|
+
removeListener(event: 'data', handler: (data: Buffer, isNotification: boolean) => void): NobleCharacteristicLike;
|
|
143
|
+
}
|
|
144
|
+
type NobleFactory = () => NobleLike;
|
|
145
|
+
interface NobleBleHandlerOptions {
|
|
146
|
+
/** Override for tests; defaults to `require('@stoprocent/noble')`. */
|
|
147
|
+
nobleFactory?: NobleFactory;
|
|
148
|
+
/** Override the overall connect timeout (tests only; defaults to 31s). */
|
|
149
|
+
connectTimeoutMs?: number;
|
|
150
|
+
logger?: BleDebugLogger;
|
|
151
|
+
}
|
|
152
|
+
/**
|
|
153
|
+
* Core BLE logic, decoupled from Electron's IPC layer so it can be unit
|
|
154
|
+
* tested with a fake noble. Mirrors the OneKey `noble-ble-handler.ts`
|
|
155
|
+
* pattern (a single class that owns the peripheral cache + disconnect
|
|
156
|
+
* callbacks), but trimmed to the minimum surface we expose.
|
|
157
|
+
*/
|
|
158
|
+
declare class NobleBleHandler {
|
|
159
|
+
private _noble;
|
|
160
|
+
private readonly _factory;
|
|
161
|
+
private readonly _connectTimeoutMs;
|
|
162
|
+
private readonly _logger?;
|
|
163
|
+
private readonly _discovered;
|
|
164
|
+
private readonly _lastSeen;
|
|
165
|
+
private readonly _connected;
|
|
166
|
+
private _discoverHandler?;
|
|
167
|
+
private _scanning;
|
|
168
|
+
private _idleStopTimer?;
|
|
169
|
+
private _onNotification?;
|
|
170
|
+
private _onDeviceDisconnected?;
|
|
171
|
+
private _initialized;
|
|
172
|
+
private _disposed;
|
|
173
|
+
private _disposePromise?;
|
|
174
|
+
private _releasePromise?;
|
|
175
|
+
private _initPromise?;
|
|
176
|
+
private readonly _nobleInstances;
|
|
177
|
+
private readonly _pendingCancellations;
|
|
178
|
+
private readonly _connectAttempts;
|
|
179
|
+
private _nativeReleased;
|
|
180
|
+
private _lastNobleRecoverAt?;
|
|
181
|
+
/** The connect currently in flight, so cancelPairing can abandon it. */
|
|
182
|
+
private _activeConnect?;
|
|
183
|
+
constructor(options?: NobleBleHandlerOptions);
|
|
184
|
+
setNotificationListener(handler: (id: string, hexData: string) => void): void;
|
|
185
|
+
setDisconnectedListener(handler: (id: string) => void): void;
|
|
186
|
+
init(): Promise<void>;
|
|
187
|
+
checkAvailability(): Promise<ThirdPartyBleAvailability>;
|
|
188
|
+
/**
|
|
189
|
+
* Lazy-start a continuous scan and return the current snapshot immediately.
|
|
190
|
+
*
|
|
191
|
+
* Scans UNFILTERED and applies the caller's match criteria in `_snapshot()` instead. A
|
|
192
|
+
* service-UUID filter cannot be used here: noble's Windows backend applies it
|
|
193
|
+
* per RECEIVED PACKET (`BLEManager::OnScanResult`, lib/win/src/ble_manager.cc),
|
|
194
|
+
* and a Safe 7's ADV packet carries only its name — the service UUID lives in
|
|
195
|
+
* the scan response, which arrives as a separate, irregularly-timed event. So
|
|
196
|
+
* a filtered scan drops every ADV packet and the device appears to be
|
|
197
|
+
* undiscoverable for minutes at a time while it is plainly on air. (OneKey's
|
|
198
|
+
* own devices do advertise their service UUID, which is why the same filter is
|
|
199
|
+
* safe in `hd-transport-electron` and was copied here by mistake.)
|
|
200
|
+
*/
|
|
201
|
+
scan(options?: ElectronBleScanOptions): Promise<ThirdPartyBleDeviceInfo[]>;
|
|
202
|
+
/**
|
|
203
|
+
* Current in-range devices for the asking vendor, dropping any that aged past
|
|
204
|
+
* the liveness TTL. The match test replaces the service-UUID scan filter we cannot use
|
|
205
|
+
* (see `scan`): it matches the name from the ADV packet, or the service UUID
|
|
206
|
+
* once a scan response has merged into the same peripheral.
|
|
207
|
+
*
|
|
208
|
+
* Note the TTL only prunes what the CALLER sees. `_discovered` is a cache, not
|
|
209
|
+
* the source of truth for reachability — a device missing from here can still
|
|
210
|
+
* be connected to by id (`_directConnect`).
|
|
211
|
+
*/
|
|
212
|
+
private _snapshot;
|
|
213
|
+
/** A noble instance with its own bindings, so a stuck one can be replaced. */
|
|
214
|
+
private _createFreshNoble;
|
|
215
|
+
/**
|
|
216
|
+
* Rebuild noble when its adapter state is stuck. Re-enumerating the Windows
|
|
217
|
+
* BLE stack (pairing, or removing the device from OS settings) can catch
|
|
218
|
+
* noble's RadioWatcher mid-churn: it latches `unsupported` and never
|
|
219
|
+
* re-evaluates, so every later scan fails until the process restarts. Fresh
|
|
220
|
+
* bindings restart that watcher, which is the in-process equivalent of the
|
|
221
|
+
* app restart that is otherwise the only cure.
|
|
222
|
+
*/
|
|
223
|
+
private _recoverNobleIfStuck;
|
|
224
|
+
private _armIdleStop;
|
|
225
|
+
private _clearIdleStop;
|
|
226
|
+
/** Stop scanning but keep the discovered cache (used before connect). */
|
|
227
|
+
private _pauseScan;
|
|
228
|
+
/** Stop scanning and forget discovered devices (idle timeout / teardown). */
|
|
229
|
+
private _stopContinuousScan;
|
|
230
|
+
/**
|
|
231
|
+
* Stops the process-wide scan no matter which vendor asked. Scan *results*
|
|
232
|
+
* are filtered per vendor, but the radio is not: one vendor's stopScan ends
|
|
233
|
+
* the other's discovery too. That is safe only because the adapter job queue
|
|
234
|
+
* serializes discovery across vendors, so two are never scanning at once.
|
|
235
|
+
* Anything that breaks that — a background presence probe, say — needs
|
|
236
|
+
* per-vendor refcounting here first.
|
|
237
|
+
*/
|
|
238
|
+
stopScan(): Promise<void>;
|
|
239
|
+
/**
|
|
240
|
+
* Look up a previously-scanned device by id (no extra BLE traffic).
|
|
241
|
+
* Returns null if the device hasn't been seen by a recent scan.
|
|
242
|
+
*/
|
|
243
|
+
getDevice(id: string): ThirdPartyBleDeviceInfo | null;
|
|
244
|
+
/**
|
|
245
|
+
* Read the current RSSI (in dBm) for a connected peripheral. Requires
|
|
246
|
+
* the device to be connected — noble can't read RSSI off a scan-only
|
|
247
|
+
* peripheral. Falls back to the cached scan-time rssi when the noble
|
|
248
|
+
* peripheral doesn't expose updateRssiAsync.
|
|
249
|
+
*/
|
|
250
|
+
readRssi(id: string): Promise<number>;
|
|
251
|
+
/**
|
|
252
|
+
* Abort the in-flight pairing flow: abandon a connect that is still running,
|
|
253
|
+
* stop scanning, disconnect every peripheral the host currently has open.
|
|
254
|
+
* Caller is responsible for surfacing the cancellation to the upper UI layer.
|
|
255
|
+
*
|
|
256
|
+
* Abandoning the connect is what actually ends the flow. Pairing happens
|
|
257
|
+
* inside connectAsync and the entry only reaches _connected after service
|
|
258
|
+
* discovery, so the loop below never sees the device being paired — without
|
|
259
|
+
* the abandon the caller waits out the full connect timeout, which is sized
|
|
260
|
+
* to the OS pairing window and so feels like a hang.
|
|
261
|
+
*/
|
|
262
|
+
cancelPairing(): Promise<void>;
|
|
263
|
+
/**
|
|
264
|
+
* Scan for a specific peripheral id and resolve THE MOMENT it's discovered,
|
|
265
|
+
* stopping the scan immediately (don't wait out the full window). The fast
|
|
266
|
+
* reconnect path for a stored connectId when the device IS advertising.
|
|
267
|
+
*
|
|
268
|
+
* This used to be the only reconnect path, on two assumptions that are both
|
|
269
|
+
* false: that noble cannot connect by id without a scan (it can — see
|
|
270
|
+
* `_directConnect`), and that "the device advertises continuously" (a bonded
|
|
271
|
+
* Safe 7 does not — it holds the link and goes silent). Callers must fall
|
|
272
|
+
* back to `_directConnect` when this returns undefined.
|
|
273
|
+
*/
|
|
274
|
+
private _scanUntilFound;
|
|
275
|
+
/**
|
|
276
|
+
* Connect by id with no scan and no advertisement.
|
|
277
|
+
*
|
|
278
|
+
* This is the ONLY path that reaches a device which is connected but silent.
|
|
279
|
+
* A linked peripheral stops advertising while it HOLDS A LINK (standard BLE; a Safe 7's
|
|
280
|
+
* screen says "wait connection") — field-verified: bonding/THP handshake
|
|
281
|
+
* alone does NOT silence it, holding the connection does. So while a link is
|
|
282
|
+
* up, no amount of scanning will rediscover it — `_scanUntilFound` alone
|
|
283
|
+
* dead-ends with "device not found" on a device that is sitting right there,
|
|
284
|
+
* connected and reachable.
|
|
285
|
+
*
|
|
286
|
+
* noble supports this: `noble.connectAsync(id)` needs no prior `discover`,
|
|
287
|
+
* because both native backends materialize the peripheral themselves (Windows
|
|
288
|
+
* synthesizes one for an unknown address, macOS retrieves it by identifier)
|
|
289
|
+
* and then emit a `discover`, which our own handler turns back into a
|
|
290
|
+
* `_discovered` entry. OneKey's own noble handler calls this "direct
|
|
291
|
+
* connection mode"; Trezor Suite's equivalent is asking the adapter for its
|
|
292
|
+
* peripheral list instead of keeping a cache.
|
|
293
|
+
*
|
|
294
|
+
* Returns undefined (not throw) so the caller reports the normal
|
|
295
|
+
* "device not found" rather than a confusing noble-internal error.
|
|
296
|
+
*/
|
|
297
|
+
private _directConnect;
|
|
298
|
+
private _safeDisconnect;
|
|
299
|
+
connect(id: string, options: ElectronBleConnectOptions): Promise<{
|
|
300
|
+
id: string;
|
|
301
|
+
name?: string;
|
|
302
|
+
}>;
|
|
303
|
+
private _connectInner;
|
|
304
|
+
disconnect(id: string): Promise<void>;
|
|
305
|
+
subscribe(id: string): Promise<void>;
|
|
306
|
+
unsubscribe(id: string): Promise<void>;
|
|
307
|
+
write(id: string, hexData: string): Promise<void>;
|
|
308
|
+
/** Retire a renderer's handler without stopping a process-wide native manager. */
|
|
309
|
+
dispose(): Promise<void>;
|
|
310
|
+
/**
|
|
311
|
+
* Terminal native release, including instances replaced by adapter recovery.
|
|
312
|
+
* A host sharing Noble must defer stop() until all transports have disposed,
|
|
313
|
+
* and deduplicate instances passed to releaseNoble across those transports.
|
|
314
|
+
*/
|
|
315
|
+
disposeForAppQuit(releaseNoble?: (instance: {
|
|
316
|
+
stop?(): void;
|
|
317
|
+
}) => void): Promise<void>;
|
|
318
|
+
private _assertActive;
|
|
319
|
+
private _cleanupDevice;
|
|
320
|
+
private _requireEntry;
|
|
321
|
+
private _requireNoble;
|
|
322
|
+
private _waitForPoweredOn;
|
|
323
|
+
private _log;
|
|
324
|
+
}
|
|
325
|
+
|
|
326
|
+
/** Minimal slice of Electron's `WebContents` we use (kept duck-typed so we
|
|
327
|
+
* don't take a hard dep on `electron`). */
|
|
328
|
+
interface WebContentsLike {
|
|
329
|
+
send(channel: string, ...args: unknown[]): void;
|
|
330
|
+
on?(event: string, listener: (...args: any[]) => void): void;
|
|
331
|
+
}
|
|
332
|
+
/** Minimal slice of Electron's `ipcMain` we use. */
|
|
333
|
+
interface IpcMainLike {
|
|
334
|
+
handle(channel: string, listener: (event: unknown, ...args: any[]) => Promise<unknown> | unknown): void;
|
|
335
|
+
removeHandler(channel: string): void;
|
|
336
|
+
}
|
|
337
|
+
interface InitThirdPartyBleSupportOptions extends NobleBleHandlerOptions {
|
|
338
|
+
/** Inject your own `ipcMain` (defaults to `require('electron').ipcMain`). */
|
|
339
|
+
ipcMain?: IpcMainLike;
|
|
340
|
+
}
|
|
341
|
+
interface ThirdPartyBleSupportHandle {
|
|
342
|
+
handler: NobleBleHandler;
|
|
343
|
+
dispose(): Promise<void>;
|
|
344
|
+
disposeForAppQuit(releaseNoble?: (instance: {
|
|
345
|
+
stop?(): void;
|
|
346
|
+
}) => void): Promise<void>;
|
|
347
|
+
}
|
|
348
|
+
/**
|
|
349
|
+
* Wire a `NobleBleHandler` to Electron's IPC so the renderer can drive BLE
|
|
350
|
+
* via `window.desktopApi.trezorBle`. Call once from the main process after
|
|
351
|
+
* `BrowserWindow` is ready.
|
|
352
|
+
*
|
|
353
|
+
* Call dispose() when retiring a renderer and disposeForAppQuit() before Node teardown.
|
|
354
|
+
*/
|
|
355
|
+
declare function initThirdPartyBleSupport(webContents: WebContentsLike, options?: InitThirdPartyBleSupportOptions): ThirdPartyBleSupportHandle;
|
|
356
|
+
|
|
357
|
+
export { type BleDebugLogEntry, type BleDebugLogLevel, type BleDebugLogger, type InitThirdPartyBleSupportOptions, type IpcMainLike, NobleBleHandler, type NobleBleHandlerOptions, type ThirdPartyBleApi, type ThirdPartyBleAvailability, type ThirdPartyBleDeviceInfo, type ThirdPartyBleSupportHandle, initThirdPartyBleSupport, redactBleDebugLogData };
|