@onekeyfe/hd-transport-electron 1.2.0-alpha.8 → 1.2.0-alpha.80
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/ble-ops.d.ts +6 -0
- package/dist/ble-ops.d.ts.map +1 -1
- package/dist/ble-packet-capacity.d.ts +2 -0
- package/dist/ble-packet-capacity.d.ts.map +1 -0
- package/dist/{index-02fc07fe.js → index-6da32f94.js} +1 -1
- package/dist/index.d.ts +16 -2
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +1 -1
- package/dist/{noble-ble-handler-94c42077.js → noble-ble-handler-ce551d9a.js} +477 -263
- package/dist/noble-ble-handler.d.ts +2 -0
- package/dist/noble-ble-handler.d.ts.map +1 -1
- package/dist/noble-ble-timeouts.d.ts +3 -0
- package/dist/noble-ble-timeouts.d.ts.map +1 -0
- package/dist/types/desktop-api.d.ts +10 -1
- package/dist/types/desktop-api.d.ts.map +1 -1
- package/dist/types/noble-extended.d.ts +1 -0
- package/dist/types/noble-extended.d.ts.map +1 -1
- package/package.json +5 -5
- package/src/__tests__/ble-ops.test.ts +21 -0
- package/src/__tests__/ble-packet-capacity.test.ts +13 -0
- package/src/__tests__/noble-ble-handler.test.ts +377 -0
- package/src/ble-ops.ts +40 -10
- package/src/ble-packet-capacity.ts +13 -0
- package/src/index.ts +1 -1
- package/src/noble-ble-handler.ts +540 -290
- package/src/noble-ble-timeouts.ts +2 -0
- package/src/types/desktop-api.ts +10 -2
- package/src/types/noble-extended.ts +1 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
'use strict';
|
|
2
2
|
|
|
3
|
-
var index = require('./index-
|
|
3
|
+
var index = require('./index-6da32f94.js');
|
|
4
4
|
var hdShared = require('@onekeyfe/hd-shared');
|
|
5
5
|
var pRetry = require('p-retry');
|
|
6
6
|
|
|
@@ -8,6 +8,14 @@ function _interopDefaultLegacy (e) { return e && typeof e === 'object' && 'defau
|
|
|
8
8
|
|
|
9
9
|
var pRetry__default = /*#__PURE__*/_interopDefaultLegacy(pRetry);
|
|
10
10
|
|
|
11
|
+
const BLE_ATT_HEADER_BYTES = 3;
|
|
12
|
+
function resolveBlePacketCapacity(mtu, maximumPacketCapacity, fallbackPacketCapacity) {
|
|
13
|
+
if (typeof mtu !== 'number' || !Number.isFinite(mtu) || mtu <= BLE_ATT_HEADER_BYTES) {
|
|
14
|
+
return fallbackPacketCapacity;
|
|
15
|
+
}
|
|
16
|
+
return Math.min(maximumPacketCapacity, Math.floor(mtu) - BLE_ATT_HEADER_BYTES);
|
|
17
|
+
}
|
|
18
|
+
|
|
11
19
|
function safeLog(logger, level, message, ...args) {
|
|
12
20
|
if (logger) {
|
|
13
21
|
logger[level](message, ...args);
|
|
@@ -17,6 +25,37 @@ function safeLog(logger, level, message, ...args) {
|
|
|
17
25
|
}
|
|
18
26
|
}
|
|
19
27
|
|
|
28
|
+
function runBleCallbackOperation(operation, options) {
|
|
29
|
+
return new Promise((resolve, reject) => {
|
|
30
|
+
let settled = false;
|
|
31
|
+
const settle = (error) => {
|
|
32
|
+
if (settled)
|
|
33
|
+
return;
|
|
34
|
+
settled = true;
|
|
35
|
+
clearTimeout(timeout);
|
|
36
|
+
if (error) {
|
|
37
|
+
reject(error);
|
|
38
|
+
}
|
|
39
|
+
else {
|
|
40
|
+
resolve();
|
|
41
|
+
}
|
|
42
|
+
};
|
|
43
|
+
const timeout = setTimeout(() => {
|
|
44
|
+
if (options.timeoutBehavior === 'reject') {
|
|
45
|
+
settle(new Error(`BLE operation timed out after ${options.timeoutMs}ms`));
|
|
46
|
+
}
|
|
47
|
+
else {
|
|
48
|
+
settle();
|
|
49
|
+
}
|
|
50
|
+
}, options.timeoutMs);
|
|
51
|
+
try {
|
|
52
|
+
operation(settle);
|
|
53
|
+
}
|
|
54
|
+
catch (error) {
|
|
55
|
+
settle(error instanceof Error ? error : new Error(String(error)));
|
|
56
|
+
}
|
|
57
|
+
});
|
|
58
|
+
}
|
|
20
59
|
function softRefreshSubscription(params) {
|
|
21
60
|
return index.__awaiter(this, void 0, void 0, function* () {
|
|
22
61
|
const { deviceId, notifyCharacteristic, subscriptionOperations, subscribedDevices, pairedDevices, onNotificationData, logger, } = params;
|
|
@@ -25,17 +64,13 @@ function softRefreshSubscription(params) {
|
|
|
25
64
|
}
|
|
26
65
|
logger === null || logger === void 0 ? void 0 : logger.info('[BLE-OPS] Starting subscription refresh', { deviceId });
|
|
27
66
|
subscriptionOperations.set(deviceId, 'subscribing');
|
|
28
|
-
yield
|
|
29
|
-
|
|
67
|
+
yield runBleCallbackOperation(callback => notifyCharacteristic.unsubscribe(callback), {
|
|
68
|
+
timeoutMs: 250,
|
|
69
|
+
timeoutBehavior: 'resolve',
|
|
30
70
|
});
|
|
31
|
-
yield
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
reject(error);
|
|
35
|
-
return;
|
|
36
|
-
}
|
|
37
|
-
resolve();
|
|
38
|
-
});
|
|
71
|
+
yield runBleCallbackOperation(callback => notifyCharacteristic.subscribe(callback), {
|
|
72
|
+
timeoutMs: 8000,
|
|
73
|
+
timeoutBehavior: 'reject',
|
|
39
74
|
});
|
|
40
75
|
notifyCharacteristic.removeAllListeners('data');
|
|
41
76
|
notifyCharacteristic.on('data', (data) => {
|
|
@@ -51,6 +86,9 @@ function softRefreshSubscription(params) {
|
|
|
51
86
|
});
|
|
52
87
|
}
|
|
53
88
|
|
|
89
|
+
const NOBLE_BLE_TARGETED_SCAN_TIMEOUT_MS = 5000;
|
|
90
|
+
const NOBLE_BLE_CONNECTION_TIMEOUT_MS = 10000;
|
|
91
|
+
|
|
54
92
|
let noble = null;
|
|
55
93
|
let logger = null;
|
|
56
94
|
const bluetoothState = {
|
|
@@ -59,6 +97,7 @@ const bluetoothState = {
|
|
|
59
97
|
initialized: false,
|
|
60
98
|
};
|
|
61
99
|
let persistentStateListener = null;
|
|
100
|
+
let persistentDiscoverListener = null;
|
|
62
101
|
const discoveredDevices = new Map();
|
|
63
102
|
const connectedDevices = new Map();
|
|
64
103
|
const pairedDevices = new Set();
|
|
@@ -66,54 +105,47 @@ const deviceCharacteristics = new Map();
|
|
|
66
105
|
const notificationCallbacks = new Map();
|
|
67
106
|
const subscribedDevices = new Map();
|
|
68
107
|
const subscriptionOperations = new Map();
|
|
108
|
+
const deviceDisconnectListeners = new Map();
|
|
109
|
+
const deviceMtuListeners = new Map();
|
|
69
110
|
const ONEKEY_SERVICE_UUIDS = [hdShared.ONEKEY_SERVICE_UUID];
|
|
70
|
-
const
|
|
71
|
-
const
|
|
72
|
-
const
|
|
111
|
+
const ONEKEY_SERVICE_UUID_ALIASES = hdShared.createKnownBleUuidAliases(hdShared.ONEKEY_SERVICE_UUID);
|
|
112
|
+
const ONEKEY_WRITE_UUID_ALIASES = hdShared.createKnownBleUuidAliases(hdShared.ONEKEY_WRITE_CHARACTERISTIC_UUID);
|
|
113
|
+
const ONEKEY_NOTIFY_UUID_ALIASES = hdShared.createKnownBleUuidAliases(hdShared.ONEKEY_NOTIFY_CHARACTERISTIC_UUID);
|
|
73
114
|
const BLUETOOTH_INIT_TIMEOUT = 10000;
|
|
74
|
-
const DEVICE_SCAN_TIMEOUT =
|
|
75
|
-
const FAST_SCAN_TIMEOUT = 8000;
|
|
115
|
+
const DEVICE_SCAN_TIMEOUT = 5000;
|
|
76
116
|
const DEVICE_CHECK_INTERVAL = 500;
|
|
77
|
-
const CONNECTION_TIMEOUT = 8000;
|
|
78
117
|
const SERVICE_DISCOVERY_TIMEOUT = 10000;
|
|
79
|
-
const
|
|
80
|
-
const
|
|
118
|
+
const BLE_CLEANUP_TIMEOUT = 250;
|
|
119
|
+
const BLE_IDLE_DISCONNECT_MS = 3 * 60000;
|
|
120
|
+
const BLE_BUSY_BACKSTOP_MS = 10 * 60000;
|
|
121
|
+
const BLE_PACKET_SIZE_FALLBACK = 192;
|
|
122
|
+
const BLE_PACKET_SIZE_MAXIMUM = 244;
|
|
123
|
+
const DEFAULT_WRITE_PACING_DELAY_MS = 5;
|
|
81
124
|
const RETRY_CONFIG = { MAX_ATTEMPTS: 15, WRITE_TIMEOUT: 2000 };
|
|
82
125
|
const IS_WINDOWS = process.platform === 'win32';
|
|
83
126
|
const ABORTABLE_WRITE_ERROR_PATTERNS = [
|
|
84
127
|
/status:\s*3/i,
|
|
85
128
|
];
|
|
86
|
-
function
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
const NORMALIZED_ONEKEY_SERVICE_UUIDS = new Set([
|
|
91
|
-
...ONEKEY_SERVICE_UUIDS.map(uuid => getBleUuidKey(uuid)),
|
|
92
|
-
'0001',
|
|
93
|
-
]);
|
|
94
|
-
function isGenericBleService(uuid) {
|
|
95
|
-
return ['1800', '1801', '180a', '180f'].includes(getBleUuidKey(uuid));
|
|
96
|
-
}
|
|
97
|
-
function hasOneKeyAdvertisementService(peripheral) {
|
|
98
|
-
var _a, _b;
|
|
99
|
-
const serviceUuids = (_b = (_a = peripheral.advertisement) === null || _a === void 0 ? void 0 : _a.serviceUuids) !== null && _b !== void 0 ? _b : [];
|
|
100
|
-
return serviceUuids.some(uuid => {
|
|
101
|
-
const uuidKey = getBleUuidKey(uuid);
|
|
102
|
-
return (NORMALIZED_ONEKEY_SERVICE_UUIDS.has(uuidKey) ||
|
|
103
|
-
PRO2_ADVERTISEMENT_SERVICE_UUID_KEYS.has(uuidKey));
|
|
104
|
-
});
|
|
129
|
+
function resolveNobleBleWritePacingDelay(options) {
|
|
130
|
+
return typeof (options === null || options === void 0 ? void 0 : options.pacingDelayMs) === 'number' && Number.isFinite(options.pacingDelayMs)
|
|
131
|
+
? Math.min(Math.max(Math.floor(options.pacingDelayMs), 0), 1000)
|
|
132
|
+
: DEFAULT_WRITE_PACING_DELAY_MS;
|
|
105
133
|
}
|
|
106
134
|
function isOneKeyPeripheral(peripheral) {
|
|
107
|
-
var _a;
|
|
108
|
-
const
|
|
109
|
-
|
|
135
|
+
var _a, _b;
|
|
136
|
+
const serviceUuids = (_a = peripheral.advertisement) === null || _a === void 0 ? void 0 : _a.serviceUuids;
|
|
137
|
+
const localName = (_b = peripheral.advertisement) === null || _b === void 0 ? void 0 : _b.localName;
|
|
138
|
+
if (!(localName === null || localName === void 0 ? void 0 : localName.trim()) || hdShared.isPro2FindMyAdvertisementName(localName)) {
|
|
139
|
+
return false;
|
|
140
|
+
}
|
|
141
|
+
return (hdShared.hasOnekeyCommunicationService(serviceUuids) &&
|
|
142
|
+
hdShared.isOnekeyBluetoothDevice({
|
|
143
|
+
id: peripheral.id,
|
|
144
|
+
localName,
|
|
145
|
+
serviceUuids,
|
|
146
|
+
}));
|
|
110
147
|
}
|
|
111
148
|
function emitRawNotification(deviceId, data) {
|
|
112
|
-
logger === null || logger === void 0 ? void 0 : logger.info('[NobleBLE] Raw notification', {
|
|
113
|
-
deviceId,
|
|
114
|
-
dataLength: data.length,
|
|
115
|
-
firstBytes: data.subarray(0, 8).toString('hex'),
|
|
116
|
-
});
|
|
117
149
|
const appCb = notificationCallbacks.get(deviceId);
|
|
118
150
|
if (appCb)
|
|
119
151
|
appCb(data.toString('hex'));
|
|
@@ -250,9 +282,12 @@ function initializeNoble() {
|
|
|
250
282
|
};
|
|
251
283
|
noble.on('stateChange', onStateChange);
|
|
252
284
|
});
|
|
253
|
-
|
|
254
|
-
|
|
255
|
-
|
|
285
|
+
if (!persistentDiscoverListener) {
|
|
286
|
+
persistentDiscoverListener = (peripheral) => {
|
|
287
|
+
handleDeviceDiscovered(peripheral);
|
|
288
|
+
};
|
|
289
|
+
noble.on('discover', persistentDiscoverListener);
|
|
290
|
+
}
|
|
256
291
|
logger === null || logger === void 0 ? void 0 : logger.info('[NobleBLE] Noble initialized successfully');
|
|
257
292
|
}
|
|
258
293
|
catch (error) {
|
|
@@ -263,6 +298,62 @@ function initializeNoble() {
|
|
|
263
298
|
}
|
|
264
299
|
});
|
|
265
300
|
}
|
|
301
|
+
const idleDisconnectTimers = new Map();
|
|
302
|
+
const idleDisconnectInFlight = new Map();
|
|
303
|
+
function clearIdleDisconnect(deviceId) {
|
|
304
|
+
const timer = idleDisconnectTimers.get(deviceId);
|
|
305
|
+
if (timer) {
|
|
306
|
+
clearTimeout(timer);
|
|
307
|
+
idleDisconnectTimers.delete(deviceId);
|
|
308
|
+
}
|
|
309
|
+
}
|
|
310
|
+
function awaitIdleDisconnect(deviceId) {
|
|
311
|
+
return index.__awaiter(this, void 0, void 0, function* () {
|
|
312
|
+
const pending = idleDisconnectInFlight.get(deviceId);
|
|
313
|
+
if (pending)
|
|
314
|
+
yield pending.catch(() => undefined);
|
|
315
|
+
});
|
|
316
|
+
}
|
|
317
|
+
function broadcastToAllWebContents(channel, payload) {
|
|
318
|
+
try {
|
|
319
|
+
const { webContents: electronWebContents } = require('electron');
|
|
320
|
+
for (const wc of electronWebContents.getAllWebContents()) {
|
|
321
|
+
if (!wc.isDestroyed())
|
|
322
|
+
wc.send(channel, payload);
|
|
323
|
+
}
|
|
324
|
+
}
|
|
325
|
+
catch (error) {
|
|
326
|
+
logger === null || logger === void 0 ? void 0 : logger.error('[NobleBLE] broadcast failed:', { channel, error: String(error) });
|
|
327
|
+
}
|
|
328
|
+
}
|
|
329
|
+
function armIdleDisconnect(deviceId, ms = BLE_IDLE_DISCONNECT_MS, reason = 'idle') {
|
|
330
|
+
clearIdleDisconnect(deviceId);
|
|
331
|
+
idleDisconnectTimers.set(deviceId, setTimeout(() => {
|
|
332
|
+
var _a;
|
|
333
|
+
idleDisconnectTimers.delete(deviceId);
|
|
334
|
+
if (!connectedDevices.has(deviceId))
|
|
335
|
+
return;
|
|
336
|
+
logger === null || logger === void 0 ? void 0 : logger.info('[NobleBLE] Keep-alive timeout, disconnecting device', { deviceId, reason });
|
|
337
|
+
const peripheral = connectedDevices.get(deviceId);
|
|
338
|
+
const deviceName = ((_a = peripheral === null || peripheral === void 0 ? void 0 : peripheral.advertisement) === null || _a === void 0 ? void 0 : _a.localName) || 'Unknown Device';
|
|
339
|
+
const pending = disconnectDevice(deviceId)
|
|
340
|
+
.then(() => {
|
|
341
|
+
broadcastToAllWebContents(hdShared.EOneKeyBleMessageKeys.BLE_DEVICE_DISCONNECTED, {
|
|
342
|
+
id: deviceId,
|
|
343
|
+
name: deviceName,
|
|
344
|
+
});
|
|
345
|
+
})
|
|
346
|
+
.catch(error => {
|
|
347
|
+
logger === null || logger === void 0 ? void 0 : logger.error('[NobleBLE] Keep-alive disconnect failed', { deviceId, error });
|
|
348
|
+
})
|
|
349
|
+
.finally(() => {
|
|
350
|
+
if (idleDisconnectInFlight.get(deviceId) === pending) {
|
|
351
|
+
idleDisconnectInFlight.delete(deviceId);
|
|
352
|
+
}
|
|
353
|
+
});
|
|
354
|
+
idleDisconnectInFlight.set(deviceId, pending);
|
|
355
|
+
}, ms));
|
|
356
|
+
}
|
|
266
357
|
function cleanupDevice(deviceId, webContents, options = {}) {
|
|
267
358
|
var _a;
|
|
268
359
|
const { cleanupConnection = true, cleanupDiscoveredCache = false, sendDisconnectEvent = false, cancelOperations = true, reason = 'unknown', } = options;
|
|
@@ -274,9 +365,20 @@ function cleanupDevice(deviceId, webContents, options = {}) {
|
|
|
274
365
|
sendDisconnectEvent,
|
|
275
366
|
cancelOperations,
|
|
276
367
|
});
|
|
368
|
+
clearIdleDisconnect(deviceId);
|
|
277
369
|
const peripheral = connectedDevices.get(deviceId);
|
|
278
370
|
const deviceName = ((_a = peripheral === null || peripheral === void 0 ? void 0 : peripheral.advertisement) === null || _a === void 0 ? void 0 : _a.localName) || 'Unknown Device';
|
|
279
371
|
if (cleanupConnection) {
|
|
372
|
+
const disconnectEntry = deviceDisconnectListeners.get(deviceId);
|
|
373
|
+
if (disconnectEntry) {
|
|
374
|
+
disconnectEntry.peripheral.removeListener('disconnect', disconnectEntry.listener);
|
|
375
|
+
deviceDisconnectListeners.delete(deviceId);
|
|
376
|
+
}
|
|
377
|
+
const mtuEntry = deviceMtuListeners.get(deviceId);
|
|
378
|
+
if (mtuEntry) {
|
|
379
|
+
mtuEntry.peripheral.removeListener('mtu', mtuEntry.listener);
|
|
380
|
+
deviceMtuListeners.delete(deviceId);
|
|
381
|
+
}
|
|
280
382
|
connectedDevices.delete(deviceId);
|
|
281
383
|
deviceCharacteristics.delete(deviceId);
|
|
282
384
|
notificationCallbacks.delete(deviceId);
|
|
@@ -287,8 +389,8 @@ function cleanupDevice(deviceId, webContents, options = {}) {
|
|
|
287
389
|
if (cleanupDiscoveredCache) {
|
|
288
390
|
discoveredDevices.delete(deviceId);
|
|
289
391
|
}
|
|
290
|
-
if (sendDisconnectEvent
|
|
291
|
-
|
|
392
|
+
if (sendDisconnectEvent) {
|
|
393
|
+
broadcastToAllWebContents(hdShared.EOneKeyBleMessageKeys.BLE_DEVICE_DISCONNECTED, {
|
|
292
394
|
id: deviceId,
|
|
293
395
|
name: deviceName,
|
|
294
396
|
});
|
|
@@ -311,12 +413,36 @@ function handleDeviceDisconnect(deviceId, webContents) {
|
|
|
311
413
|
});
|
|
312
414
|
}
|
|
313
415
|
function setupDisconnectListener(peripheral, deviceId, webContents) {
|
|
314
|
-
|
|
315
|
-
|
|
416
|
+
const existing = deviceDisconnectListeners.get(deviceId);
|
|
417
|
+
if (existing) {
|
|
418
|
+
existing.peripheral.removeListener('disconnect', existing.listener);
|
|
419
|
+
}
|
|
420
|
+
const listener = () => {
|
|
316
421
|
handleDeviceDisconnect(deviceId, webContents);
|
|
317
|
-
}
|
|
422
|
+
};
|
|
423
|
+
deviceDisconnectListeners.set(deviceId, { peripheral, listener });
|
|
424
|
+
peripheral.on('disconnect', listener);
|
|
425
|
+
setupMtuListener(peripheral, deviceId, webContents);
|
|
426
|
+
}
|
|
427
|
+
function setupMtuListener(peripheral, deviceId, webContents) {
|
|
428
|
+
const existing = deviceMtuListeners.get(deviceId);
|
|
429
|
+
if (existing) {
|
|
430
|
+
existing.peripheral.removeListener('mtu', existing.listener);
|
|
431
|
+
}
|
|
432
|
+
const listener = (mtu) => {
|
|
433
|
+
if (!Number.isFinite(mtu) || mtu <= 0)
|
|
434
|
+
return;
|
|
435
|
+
if (webContents.isDestroyed())
|
|
436
|
+
return;
|
|
437
|
+
webContents.send(hdShared.EOneKeyBleMessageKeys.NOBLE_BLE_MTU_CHANGED, {
|
|
438
|
+
id: deviceId,
|
|
439
|
+
mtu,
|
|
440
|
+
});
|
|
441
|
+
};
|
|
442
|
+
deviceMtuListeners.set(deviceId, { peripheral, listener });
|
|
443
|
+
peripheral.on('mtu', listener);
|
|
318
444
|
}
|
|
319
|
-
function
|
|
445
|
+
function writeCharacteristicWithoutResponse(deviceId, writeCharacteristic, buffer) {
|
|
320
446
|
return index.__awaiter(this, void 0, void 0, function* () {
|
|
321
447
|
return new Promise((resolve, reject) => {
|
|
322
448
|
writeCharacteristic.write(buffer, true, (error) => {
|
|
@@ -348,7 +474,7 @@ function attemptWindowsWriteUntilPaired(deviceId, doGetWriteCharacteristic, payl
|
|
|
348
474
|
throw hdShared.ERRORS.TypedError(hdShared.HardwareErrorCode.RuntimeError, `Write characteristic not available for ${deviceId}`);
|
|
349
475
|
}
|
|
350
476
|
try {
|
|
351
|
-
yield
|
|
477
|
+
yield writeCharacteristicWithoutResponse(deviceId, latestWrite, payload);
|
|
352
478
|
}
|
|
353
479
|
catch (e) {
|
|
354
480
|
const errorMessage = e instanceof Error ? e.message : String(e);
|
|
@@ -407,92 +533,98 @@ function attemptWindowsWriteUntilPaired(deviceId, doGetWriteCharacteristic, payl
|
|
|
407
533
|
throw hdShared.ERRORS.TypedError(hdShared.HardwareErrorCode.DeviceNotFound, `No response observed after ${RETRY_CONFIG.MAX_ATTEMPTS} writes: ${deviceId}`);
|
|
408
534
|
});
|
|
409
535
|
}
|
|
410
|
-
function transmitHexDataToDevice(deviceId, hexData) {
|
|
536
|
+
function transmitHexDataToDevice(deviceId, hexData, options) {
|
|
411
537
|
return index.__awaiter(this, void 0, void 0, function* () {
|
|
412
538
|
const characteristics = deviceCharacteristics.get(deviceId);
|
|
413
539
|
const peripheral = connectedDevices.get(deviceId);
|
|
414
540
|
if (!peripheral || !characteristics) {
|
|
415
541
|
throw hdShared.ERRORS.TypedError(hdShared.HardwareErrorCode.BleCharacteristicNotFound, `Device ${deviceId} not connected or characteristics not available`);
|
|
416
542
|
}
|
|
543
|
+
armIdleDisconnect(deviceId, BLE_BUSY_BACKSTOP_MS, 'busy-backstop');
|
|
417
544
|
const toBuffer = Buffer.from(hexData, 'hex');
|
|
418
|
-
logger === null || logger === void 0 ? void 0 : logger.info('[NobleBLE] Writing data:', {
|
|
419
|
-
deviceId,
|
|
420
|
-
dataLength: toBuffer.length,
|
|
421
|
-
firstBytes: toBuffer.subarray(0, 8).toString('hex'),
|
|
422
|
-
});
|
|
423
545
|
const doGetWriteCharacteristic = () => { var _a; return (_a = deviceCharacteristics.get(deviceId)) === null || _a === void 0 ? void 0 : _a.write; };
|
|
546
|
+
const packetCapacity = resolveBlePacketCapacity(peripheral.mtu, BLE_PACKET_SIZE_MAXIMUM, BLE_PACKET_SIZE_FALLBACK);
|
|
547
|
+
const pacingDelayMs = resolveNobleBleWritePacingDelay(options);
|
|
424
548
|
if (!IS_WINDOWS || pairedDevices.has(deviceId)) {
|
|
425
549
|
const writeCharacteristic = doGetWriteCharacteristic();
|
|
426
550
|
if (!writeCharacteristic) {
|
|
427
551
|
throw hdShared.ERRORS.TypedError(hdShared.HardwareErrorCode.BleCharacteristicNotFound, `Write characteristic not available for ${deviceId}`);
|
|
428
552
|
}
|
|
429
|
-
if (toBuffer.length <=
|
|
430
|
-
|
|
431
|
-
|
|
553
|
+
if (toBuffer.length <= packetCapacity) {
|
|
554
|
+
if (pacingDelayMs > 0)
|
|
555
|
+
yield hdShared.wait(pacingDelayMs);
|
|
556
|
+
yield writeCharacteristicWithoutResponse(deviceId, writeCharacteristic, toBuffer);
|
|
432
557
|
return;
|
|
433
558
|
}
|
|
434
559
|
for (let offset = 0; offset < toBuffer.length;) {
|
|
435
|
-
const chunkSize = Math.min(
|
|
560
|
+
const chunkSize = Math.min(packetCapacity, toBuffer.length - offset);
|
|
436
561
|
const chunk = toBuffer.subarray(offset, offset + chunkSize);
|
|
437
562
|
offset += chunkSize;
|
|
438
563
|
const latest = doGetWriteCharacteristic();
|
|
439
564
|
if (!latest) {
|
|
440
565
|
throw hdShared.ERRORS.TypedError(hdShared.HardwareErrorCode.BleCharacteristicNotFound, `Write characteristic not available for ${deviceId}`);
|
|
441
566
|
}
|
|
442
|
-
yield
|
|
443
|
-
if (offset < toBuffer.length) {
|
|
444
|
-
yield hdShared.wait(
|
|
567
|
+
yield writeCharacteristicWithoutResponse(deviceId, latest, chunk);
|
|
568
|
+
if (offset < toBuffer.length && pacingDelayMs > 0) {
|
|
569
|
+
yield hdShared.wait(pacingDelayMs);
|
|
445
570
|
}
|
|
446
571
|
}
|
|
447
572
|
return;
|
|
448
573
|
}
|
|
449
|
-
if (toBuffer.length <=
|
|
450
|
-
|
|
574
|
+
if (toBuffer.length <= packetCapacity) {
|
|
575
|
+
if (pacingDelayMs > 0)
|
|
576
|
+
yield hdShared.wait(pacingDelayMs);
|
|
451
577
|
yield attemptWindowsWriteUntilPaired(deviceId, doGetWriteCharacteristic, toBuffer, 'single');
|
|
452
578
|
return;
|
|
453
579
|
}
|
|
454
580
|
for (let offset = 0, idx = 0; offset < toBuffer.length; idx++) {
|
|
455
|
-
const chunkSize = Math.min(
|
|
581
|
+
const chunkSize = Math.min(packetCapacity, toBuffer.length - offset);
|
|
456
582
|
const chunk = toBuffer.subarray(offset, offset + chunkSize);
|
|
457
583
|
offset += chunkSize;
|
|
458
584
|
yield attemptWindowsWriteUntilPaired(deviceId, doGetWriteCharacteristic, chunk, `chunk-${idx + 1}`);
|
|
459
|
-
if (offset < toBuffer.length) {
|
|
460
|
-
yield hdShared.wait(
|
|
585
|
+
if (offset < toBuffer.length && pacingDelayMs > 0) {
|
|
586
|
+
yield hdShared.wait(pacingDelayMs);
|
|
461
587
|
}
|
|
462
588
|
}
|
|
463
589
|
});
|
|
464
590
|
}
|
|
465
591
|
function handleDeviceDiscovered(peripheral) {
|
|
466
592
|
var _a, _b;
|
|
467
|
-
const deviceName = ((_a = peripheral.advertisement) === null || _a === void 0 ? void 0 : _a.localName) || 'Unknown Device';
|
|
468
|
-
const serviceUuids = ((_b = peripheral.advertisement) === null || _b === void 0 ? void 0 : _b.serviceUuids) || [];
|
|
469
593
|
if (!isOneKeyPeripheral(peripheral)) {
|
|
470
594
|
return;
|
|
471
595
|
}
|
|
472
596
|
const isNewDevice = !discoveredDevices.has(peripheral.id);
|
|
473
597
|
discoveredDevices.set(peripheral.id, peripheral);
|
|
474
598
|
if (isNewDevice) {
|
|
475
|
-
logger === null || logger === void 0 ? void 0 : logger.
|
|
476
|
-
|
|
477
|
-
|
|
478
|
-
serviceUUIDs: serviceUuids,
|
|
599
|
+
logger === null || logger === void 0 ? void 0 : logger.debug('[NobleBLE] OneKey BLE device discovered', {
|
|
600
|
+
deviceId: peripheral.id,
|
|
601
|
+
name: ((_a = peripheral.advertisement) === null || _a === void 0 ? void 0 : _a.localName) || 'Unknown Device',
|
|
602
|
+
serviceUUIDs: ((_b = peripheral.advertisement) === null || _b === void 0 ? void 0 : _b.serviceUuids) || [],
|
|
479
603
|
});
|
|
480
604
|
}
|
|
481
605
|
}
|
|
482
606
|
function ensureDiscoverListener() {
|
|
483
607
|
if (!noble)
|
|
484
608
|
return;
|
|
485
|
-
|
|
486
|
-
if (listenerCount === 0) {
|
|
609
|
+
if (!persistentDiscoverListener) {
|
|
487
610
|
logger === null || logger === void 0 ? void 0 : logger.info('[NobleBLE] Discover listener missing, re-adding it');
|
|
488
|
-
|
|
611
|
+
persistentDiscoverListener = (peripheral) => {
|
|
489
612
|
handleDeviceDiscovered(peripheral);
|
|
490
|
-
}
|
|
613
|
+
};
|
|
614
|
+
noble.on('discover', persistentDiscoverListener);
|
|
491
615
|
}
|
|
492
616
|
else {
|
|
493
|
-
logger === null || logger === void 0 ? void 0 : logger.debug('[NobleBLE] Discover listener already
|
|
617
|
+
logger === null || logger === void 0 ? void 0 : logger.debug('[NobleBLE] Discover listener already registered');
|
|
494
618
|
}
|
|
495
619
|
}
|
|
620
|
+
function waitForNobleScanStop(nobleInstance) {
|
|
621
|
+
return index.__awaiter(this, void 0, void 0, function* () {
|
|
622
|
+
yield runBleCallbackOperation(callback => nobleInstance.stopScanning(() => callback()), {
|
|
623
|
+
timeoutMs: BLE_CLEANUP_TIMEOUT,
|
|
624
|
+
timeoutBehavior: 'resolve',
|
|
625
|
+
});
|
|
626
|
+
});
|
|
627
|
+
}
|
|
496
628
|
function performTargetedScan(targetDeviceId) {
|
|
497
629
|
return index.__awaiter(this, void 0, void 0, function* () {
|
|
498
630
|
if (!noble) {
|
|
@@ -501,33 +633,43 @@ function performTargetedScan(targetDeviceId) {
|
|
|
501
633
|
const nobleInstance = noble;
|
|
502
634
|
logger === null || logger === void 0 ? void 0 : logger.info('[NobleBLE] Starting targeted scan for device:', targetDeviceId);
|
|
503
635
|
return new Promise((resolve, reject) => {
|
|
636
|
+
let settled = false;
|
|
637
|
+
const finish = (peripheral, error) => index.__awaiter(this, void 0, void 0, function* () {
|
|
638
|
+
if (settled)
|
|
639
|
+
return;
|
|
640
|
+
settled = true;
|
|
641
|
+
if (timeoutId)
|
|
642
|
+
clearTimeout(timeoutId);
|
|
643
|
+
nobleInstance.removeListener('discover', onDiscover);
|
|
644
|
+
yield waitForNobleScanStop(nobleInstance);
|
|
645
|
+
if (error) {
|
|
646
|
+
logger === null || logger === void 0 ? void 0 : logger.error('[NobleBLE] Failed to start targeted scan:', error);
|
|
647
|
+
reject(hdShared.ERRORS.TypedError(hdShared.HardwareErrorCode.BleScanError, error.message));
|
|
648
|
+
return;
|
|
649
|
+
}
|
|
650
|
+
if (peripheral) {
|
|
651
|
+
discoveredDevices.set(peripheral.id, peripheral);
|
|
652
|
+
}
|
|
653
|
+
resolve(peripheral);
|
|
654
|
+
});
|
|
504
655
|
const onDiscover = (peripheral) => {
|
|
505
656
|
var _a;
|
|
506
|
-
if (peripheral.id === targetDeviceId) {
|
|
657
|
+
if (peripheral.id === targetDeviceId && isOneKeyPeripheral(peripheral)) {
|
|
507
658
|
logger === null || logger === void 0 ? void 0 : logger.info('[NobleBLE] Target device found during targeted scan:', {
|
|
508
659
|
id: peripheral.id,
|
|
509
660
|
name: (_a = peripheral.advertisement) === null || _a === void 0 ? void 0 : _a.localName,
|
|
510
661
|
});
|
|
511
|
-
|
|
512
|
-
nobleInstance.removeListener('discover', onDiscover);
|
|
513
|
-
nobleInstance.stopScanning();
|
|
514
|
-
discoveredDevices.set(peripheral.id, peripheral);
|
|
515
|
-
resolve(peripheral);
|
|
662
|
+
finish(peripheral).catch(reject);
|
|
516
663
|
}
|
|
517
664
|
};
|
|
518
665
|
const timeoutId = setTimeout(() => {
|
|
519
|
-
nobleInstance.removeListener('discover', onDiscover);
|
|
520
|
-
nobleInstance.stopScanning();
|
|
521
666
|
logger === null || logger === void 0 ? void 0 : logger.info('[NobleBLE] Targeted scan timeout for device:', targetDeviceId);
|
|
522
|
-
|
|
523
|
-
},
|
|
667
|
+
finish(null).catch(reject);
|
|
668
|
+
}, NOBLE_BLE_TARGETED_SCAN_TIMEOUT_MS);
|
|
524
669
|
nobleInstance.on('discover', onDiscover);
|
|
525
670
|
nobleInstance.startScanning([], false, (error) => {
|
|
526
671
|
if (error) {
|
|
527
|
-
|
|
528
|
-
nobleInstance.removeListener('discover', onDiscover);
|
|
529
|
-
logger === null || logger === void 0 ? void 0 : logger.error('[NobleBLE] Failed to start targeted scan:', error);
|
|
530
|
-
reject(hdShared.ERRORS.TypedError(hdShared.HardwareErrorCode.BleScanError, error.message));
|
|
672
|
+
finish(null, error).catch(reject);
|
|
531
673
|
return;
|
|
532
674
|
}
|
|
533
675
|
logger === null || logger === void 0 ? void 0 : logger.info('[NobleBLE] Targeted scan started for device:', targetDeviceId);
|
|
@@ -550,44 +692,44 @@ function enumerateDevices() {
|
|
|
550
692
|
return new Promise((resolve, reject) => {
|
|
551
693
|
const devices = [];
|
|
552
694
|
let intervalId;
|
|
553
|
-
const cleanup = () => {
|
|
695
|
+
const cleanup = () => index.__awaiter(this, void 0, void 0, function* () {
|
|
554
696
|
clearTimeout(timeoutId);
|
|
555
697
|
if (intervalId)
|
|
556
698
|
clearInterval(intervalId);
|
|
557
|
-
nobleInstance
|
|
699
|
+
yield waitForNobleScanStop(nobleInstance);
|
|
700
|
+
});
|
|
701
|
+
const pushDevice = (peripheral, id) => {
|
|
702
|
+
var _a;
|
|
703
|
+
if (devices.some(d => d.id === id))
|
|
704
|
+
return;
|
|
705
|
+
devices.push({
|
|
706
|
+
commType: 'electron-ble',
|
|
707
|
+
id,
|
|
708
|
+
name: ((_a = peripheral.advertisement) === null || _a === void 0 ? void 0 : _a.localName) || 'Unknown Device',
|
|
709
|
+
state: peripheral.state || 'disconnected',
|
|
710
|
+
});
|
|
558
711
|
};
|
|
559
712
|
const checkDevices = () => {
|
|
560
|
-
discoveredDevices.forEach(
|
|
561
|
-
|
|
562
|
-
const existingDevice = devices.find(d => d.id === id);
|
|
563
|
-
if (!existingDevice) {
|
|
564
|
-
const deviceName = ((_a = peripheral.advertisement) === null || _a === void 0 ? void 0 : _a.localName) || 'Unknown Device';
|
|
565
|
-
devices.push({
|
|
566
|
-
commType: 'electron-ble',
|
|
567
|
-
id,
|
|
568
|
-
name: deviceName,
|
|
569
|
-
state: peripheral.state || 'disconnected',
|
|
570
|
-
});
|
|
571
|
-
}
|
|
572
|
-
});
|
|
713
|
+
discoveredDevices.forEach(pushDevice);
|
|
714
|
+
connectedDevices.forEach(pushDevice);
|
|
573
715
|
};
|
|
574
|
-
const timeoutId = setTimeout(() => {
|
|
716
|
+
const timeoutId = setTimeout(() => index.__awaiter(this, void 0, void 0, function* () {
|
|
575
717
|
checkDevices();
|
|
576
|
-
cleanup();
|
|
718
|
+
yield cleanup();
|
|
577
719
|
logger === null || logger === void 0 ? void 0 : logger.info('[NobleBLE] Scan completed, found devices:', devices.length);
|
|
578
720
|
resolve(devices);
|
|
579
|
-
}, DEVICE_SCAN_TIMEOUT);
|
|
721
|
+
}), DEVICE_SCAN_TIMEOUT);
|
|
580
722
|
logger === null || logger === void 0 ? void 0 : logger.info('[NobleBLE] Scanning for OneKey BLE devices');
|
|
581
|
-
nobleInstance.startScanning([], false, (error) => {
|
|
723
|
+
nobleInstance.startScanning([], false, (error) => index.__awaiter(this, void 0, void 0, function* () {
|
|
582
724
|
if (error) {
|
|
583
|
-
cleanup();
|
|
725
|
+
yield cleanup();
|
|
584
726
|
logger === null || logger === void 0 ? void 0 : logger.error('[NobleBLE] Failed to start scanning:', error);
|
|
585
727
|
reject(hdShared.ERRORS.TypedError(hdShared.HardwareErrorCode.BleScanError, error.message));
|
|
586
728
|
return;
|
|
587
729
|
}
|
|
588
730
|
logger === null || logger === void 0 ? void 0 : logger.info('[NobleBLE] Scanning started for OneKey devices');
|
|
589
731
|
intervalId = setInterval(checkDevices, DEVICE_CHECK_INTERVAL);
|
|
590
|
-
});
|
|
732
|
+
}));
|
|
591
733
|
});
|
|
592
734
|
});
|
|
593
735
|
}
|
|
@@ -595,25 +737,20 @@ function stopScanning() {
|
|
|
595
737
|
return index.__awaiter(this, void 0, void 0, function* () {
|
|
596
738
|
if (!noble)
|
|
597
739
|
return;
|
|
598
|
-
|
|
599
|
-
|
|
600
|
-
|
|
601
|
-
return;
|
|
602
|
-
}
|
|
603
|
-
noble.stopScanning(() => {
|
|
604
|
-
logger === null || logger === void 0 ? void 0 : logger.info('[NobleBLE] Scanning stopped');
|
|
605
|
-
resolve();
|
|
606
|
-
});
|
|
607
|
-
});
|
|
740
|
+
const nobleInstance = noble;
|
|
741
|
+
yield waitForNobleScanStop(nobleInstance);
|
|
742
|
+
logger === null || logger === void 0 ? void 0 : logger.info('[NobleBLE] Scanning stopped');
|
|
608
743
|
});
|
|
609
744
|
}
|
|
610
745
|
function cleanupNobleListeners() {
|
|
611
746
|
if (!noble)
|
|
612
747
|
return;
|
|
613
748
|
try {
|
|
614
|
-
|
|
615
|
-
|
|
616
|
-
|
|
749
|
+
if (persistentDiscoverListener) {
|
|
750
|
+
noble.removeListener('discover', persistentDiscoverListener);
|
|
751
|
+
persistentDiscoverListener = null;
|
|
752
|
+
}
|
|
753
|
+
logger === null || logger === void 0 ? void 0 : logger.info('[NobleBLE] Owned Noble listeners cleaned up');
|
|
617
754
|
}
|
|
618
755
|
catch (error) {
|
|
619
756
|
logger === null || logger === void 0 ? void 0 : logger.error('[NobleBLE] Failed to clean up some listeners:', error);
|
|
@@ -624,22 +761,12 @@ function getDevice(deviceId) {
|
|
|
624
761
|
const peripheral = discoveredDevices.get(deviceId);
|
|
625
762
|
if (peripheral) {
|
|
626
763
|
const deviceName = ((_a = peripheral.advertisement) === null || _a === void 0 ? void 0 : _a.localName) || 'Unknown Device';
|
|
627
|
-
return {
|
|
628
|
-
commType: 'electron-ble',
|
|
629
|
-
id: peripheral.id,
|
|
630
|
-
name: deviceName,
|
|
631
|
-
state: peripheral.state || 'disconnected',
|
|
632
|
-
};
|
|
764
|
+
return Object.assign({ commType: 'electron-ble', id: peripheral.id, name: deviceName, state: peripheral.state || 'disconnected' }, (typeof peripheral.mtu === 'number' ? { mtu: peripheral.mtu } : {}));
|
|
633
765
|
}
|
|
634
766
|
const connectedPeripheral = connectedDevices.get(deviceId);
|
|
635
767
|
if (connectedPeripheral) {
|
|
636
768
|
const deviceName = ((_b = connectedPeripheral.advertisement) === null || _b === void 0 ? void 0 : _b.localName) || 'Unknown Device';
|
|
637
|
-
return {
|
|
638
|
-
commType: 'electron-ble',
|
|
639
|
-
id: connectedPeripheral.id,
|
|
640
|
-
name: deviceName,
|
|
641
|
-
state: connectedPeripheral.state || 'connected',
|
|
642
|
-
};
|
|
769
|
+
return Object.assign({ commType: 'electron-ble', id: connectedPeripheral.id, name: deviceName, state: connectedPeripheral.state || 'connected' }, (typeof connectedPeripheral.mtu === 'number' ? { mtu: connectedPeripheral.mtu } : {}));
|
|
643
770
|
}
|
|
644
771
|
return {
|
|
645
772
|
commType: 'electron-ble',
|
|
@@ -683,23 +810,22 @@ function discoverServicesAndCharacteristics(peripheral) {
|
|
|
683
810
|
}
|
|
684
811
|
});
|
|
685
812
|
});
|
|
686
|
-
logger === null || logger === void 0 ? void 0 : logger.info('[NobleBLE] All services:', services === null || services === void 0 ? void 0 : services.map(s => s.uuid));
|
|
687
813
|
if (!services || services.length === 0) {
|
|
688
814
|
throw hdShared.ERRORS.TypedError(hdShared.HardwareErrorCode.BleServiceNotFound, 'No services found');
|
|
689
815
|
}
|
|
690
|
-
|
|
691
|
-
|
|
692
|
-
|
|
693
|
-
|
|
694
|
-
|
|
695
|
-
services.find(s => !isGenericBleService(s.uuid)) ||
|
|
696
|
-
services[0];
|
|
697
|
-
}
|
|
816
|
+
logger === null || logger === void 0 ? void 0 : logger.debug('[NobleBLE] services discovered', {
|
|
817
|
+
deviceId: peripheral.id,
|
|
818
|
+
serviceUUIDs: services.map(service => service.uuid),
|
|
819
|
+
});
|
|
820
|
+
const service = services.find(s => hdShared.matchesKnownBleUuid(s.uuid, ONEKEY_SERVICE_UUID_ALIASES));
|
|
698
821
|
if (!service) {
|
|
699
822
|
throw hdShared.ERRORS.TypedError(hdShared.HardwareErrorCode.BleServiceNotFound);
|
|
700
823
|
}
|
|
701
824
|
const selectedService = service;
|
|
702
|
-
logger === null || logger === void 0 ? void 0 : logger.
|
|
825
|
+
logger === null || logger === void 0 ? void 0 : logger.debug('[NobleBLE] service selected', {
|
|
826
|
+
deviceId: peripheral.id,
|
|
827
|
+
serviceUuid: selectedService.uuid,
|
|
828
|
+
});
|
|
703
829
|
const characteristics = yield new Promise((resolve, reject) => {
|
|
704
830
|
selectedService.discoverCharacteristics([], (error, chars) => {
|
|
705
831
|
if (error) {
|
|
@@ -711,30 +837,26 @@ function discoverServicesAndCharacteristics(peripheral) {
|
|
|
711
837
|
}
|
|
712
838
|
});
|
|
713
839
|
});
|
|
714
|
-
logger === null || logger === void 0 ? void 0 : logger.info('[NobleBLE] Discovered characteristics:', {
|
|
715
|
-
count: (characteristics === null || characteristics === void 0 ? void 0 : characteristics.length) || 0,
|
|
716
|
-
uuids: (characteristics === null || characteristics === void 0 ? void 0 : characteristics.map(c => c.uuid)) || [],
|
|
717
|
-
});
|
|
718
840
|
let writeCharacteristic = null;
|
|
719
841
|
let notifyCharacteristic = null;
|
|
720
842
|
for (const characteristic of characteristics) {
|
|
721
|
-
|
|
722
|
-
const uuidKey = uuid.length >= 8 ? uuid.substring(4, 8) : uuid;
|
|
723
|
-
if (uuidKey === NORMALIZED_WRITE_UUID) {
|
|
843
|
+
if (hdShared.matchesKnownBleUuid(characteristic.uuid, ONEKEY_WRITE_UUID_ALIASES)) {
|
|
724
844
|
writeCharacteristic = characteristic;
|
|
725
845
|
}
|
|
726
|
-
else if (
|
|
846
|
+
else if (hdShared.matchesKnownBleUuid(characteristic.uuid, ONEKEY_NOTIFY_UUID_ALIASES)) {
|
|
727
847
|
notifyCharacteristic = characteristic;
|
|
728
848
|
}
|
|
729
849
|
}
|
|
730
|
-
logger === null || logger === void 0 ? void 0 : logger.info('[NobleBLE] Characteristic discovery result:', {
|
|
731
|
-
writeFound: !!writeCharacteristic,
|
|
732
|
-
notifyFound: !!notifyCharacteristic,
|
|
733
|
-
});
|
|
734
850
|
if (!writeCharacteristic || !notifyCharacteristic) {
|
|
735
851
|
logger === null || logger === void 0 ? void 0 : logger.error('[NobleBLE] Missing characteristics - write:', !!writeCharacteristic, 'notify:', !!notifyCharacteristic);
|
|
736
852
|
throw hdShared.ERRORS.TypedError(hdShared.HardwareErrorCode.BleCharacteristicNotFound, 'Required characteristics not found');
|
|
737
853
|
}
|
|
854
|
+
logger === null || logger === void 0 ? void 0 : logger.debug('[NobleBLE] characteristics selected', {
|
|
855
|
+
deviceId: peripheral.id,
|
|
856
|
+
serviceUuid: selectedService.uuid,
|
|
857
|
+
writeUuid: writeCharacteristic.uuid,
|
|
858
|
+
notifyUuid: notifyCharacteristic.uuid,
|
|
859
|
+
});
|
|
738
860
|
return { write: writeCharacteristic, notify: notifyCharacteristic };
|
|
739
861
|
}))();
|
|
740
862
|
try {
|
|
@@ -755,27 +877,17 @@ function forceReconnectPeripheral(peripheral, deviceId) {
|
|
|
755
877
|
reason: 'force-reconnect',
|
|
756
878
|
});
|
|
757
879
|
if (peripheral.state === 'connected') {
|
|
758
|
-
peripheral.
|
|
759
|
-
|
|
760
|
-
|
|
761
|
-
|
|
762
|
-
resolve();
|
|
763
|
-
});
|
|
764
|
-
});
|
|
880
|
+
yield runBleCallbackOperation(callback => peripheral.disconnect(() => {
|
|
881
|
+
logger === null || logger === void 0 ? void 0 : logger.info('[NobleBLE] Force disconnect completed');
|
|
882
|
+
callback();
|
|
883
|
+
}), { timeoutMs: BLE_CLEANUP_TIMEOUT, timeoutBehavior: 'resolve' });
|
|
765
884
|
}
|
|
766
|
-
yield
|
|
767
|
-
|
|
768
|
-
|
|
769
|
-
logger === null || logger === void 0 ? void 0 : logger.error('[NobleBLE] Force reconnect failed:', error);
|
|
770
|
-
reject(hdShared.ERRORS.TypedError(hdShared.HardwareErrorCode.BleConnectedError, error.message));
|
|
771
|
-
}
|
|
772
|
-
else {
|
|
773
|
-
logger === null || logger === void 0 ? void 0 : logger.info('[NobleBLE] Force reconnect successful');
|
|
774
|
-
connectedDevices.set(deviceId, peripheral);
|
|
775
|
-
resolve();
|
|
776
|
-
}
|
|
777
|
-
});
|
|
885
|
+
yield runBleCallbackOperation(callback => peripheral.connect(callback), {
|
|
886
|
+
timeoutMs: NOBLE_BLE_CONNECTION_TIMEOUT_MS,
|
|
887
|
+
timeoutBehavior: 'reject',
|
|
778
888
|
});
|
|
889
|
+
logger === null || logger === void 0 ? void 0 : logger.info('[NobleBLE] Force reconnect successful');
|
|
890
|
+
connectedDevices.set(deviceId, peripheral);
|
|
779
891
|
yield hdShared.wait(500);
|
|
780
892
|
});
|
|
781
893
|
}
|
|
@@ -852,18 +964,83 @@ function discoverServicesAndCharacteristicsWithRetry(peripheral, deviceId) {
|
|
|
852
964
|
}
|
|
853
965
|
function setupConnectionAndDiscoverServices(peripheral, deviceId, webContents) {
|
|
854
966
|
return index.__awaiter(this, void 0, void 0, function* () {
|
|
967
|
+
setupDisconnectListener(peripheral, deviceId, webContents);
|
|
968
|
+
try {
|
|
969
|
+
return yield discoverServicesAndCharacteristicsWithRetry(peripheral, deviceId);
|
|
970
|
+
}
|
|
971
|
+
catch (initialError) {
|
|
972
|
+
logger === null || logger === void 0 ? void 0 : logger.info('[NobleBLE] Direct service discovery failed, retrying after reconnect', {
|
|
973
|
+
deviceId,
|
|
974
|
+
error: initialError,
|
|
975
|
+
});
|
|
976
|
+
}
|
|
855
977
|
yield forceReconnectPeripheral(peripheral, deviceId);
|
|
856
978
|
setupDisconnectListener(peripheral, deviceId, webContents);
|
|
857
979
|
try {
|
|
858
980
|
return yield discoverServicesAndCharacteristicsWithRetry(peripheral, deviceId);
|
|
859
981
|
}
|
|
860
|
-
catch (
|
|
861
|
-
logger === null || logger === void 0 ? void 0 : logger.error('[NobleBLE] Service discovery failed, attempting fresh scan...',
|
|
982
|
+
catch (reconnectError) {
|
|
983
|
+
logger === null || logger === void 0 ? void 0 : logger.error('[NobleBLE] Service discovery failed after reconnect, attempting fresh scan...', reconnectError);
|
|
862
984
|
return freshScanAndDiscover(deviceId, webContents);
|
|
863
985
|
}
|
|
864
986
|
});
|
|
865
987
|
}
|
|
988
|
+
const DIRECT_CONNECT_TIMEOUT_MS = 2000;
|
|
989
|
+
const DIRECT_CONNECT_COOLDOWN_MS = 15000;
|
|
990
|
+
const directConnectCooldownUntil = new Map();
|
|
991
|
+
function tryDirectConnectById(deviceId) {
|
|
992
|
+
var _a;
|
|
993
|
+
return index.__awaiter(this, void 0, void 0, function* () {
|
|
994
|
+
const nobleInstance = noble;
|
|
995
|
+
if (!(nobleInstance === null || nobleInstance === void 0 ? void 0 : nobleInstance.connectAsync))
|
|
996
|
+
return undefined;
|
|
997
|
+
const cooldownUntil = (_a = directConnectCooldownUntil.get(deviceId)) !== null && _a !== void 0 ? _a : 0;
|
|
998
|
+
if (Date.now() < cooldownUntil)
|
|
999
|
+
return undefined;
|
|
1000
|
+
try {
|
|
1001
|
+
const directPromise = nobleInstance.connectAsync(deviceId);
|
|
1002
|
+
const raced = yield Promise.race([
|
|
1003
|
+
directPromise,
|
|
1004
|
+
new Promise(resolve => {
|
|
1005
|
+
setTimeout(() => resolve('timeout'), DIRECT_CONNECT_TIMEOUT_MS);
|
|
1006
|
+
}),
|
|
1007
|
+
]);
|
|
1008
|
+
if (raced === 'timeout') {
|
|
1009
|
+
directConnectCooldownUntil.set(deviceId, Date.now() + DIRECT_CONNECT_COOLDOWN_MS);
|
|
1010
|
+
logger === null || logger === void 0 ? void 0 : logger.info('[NobleBLE] Direct connect-by-id timed out, falling back to scan', {
|
|
1011
|
+
deviceId,
|
|
1012
|
+
});
|
|
1013
|
+
directPromise
|
|
1014
|
+
.then(late => {
|
|
1015
|
+
const latePeripheral = late !== null && late !== void 0 ? late : discoveredDevices.get(deviceId);
|
|
1016
|
+
if (latePeripheral &&
|
|
1017
|
+
latePeripheral.state === 'connected' &&
|
|
1018
|
+
!connectedDevices.has(deviceId)) {
|
|
1019
|
+
latePeripheral.removeAllListeners('disconnect');
|
|
1020
|
+
latePeripheral.disconnect(() => undefined);
|
|
1021
|
+
}
|
|
1022
|
+
})
|
|
1023
|
+
.catch(() => undefined);
|
|
1024
|
+
return undefined;
|
|
1025
|
+
}
|
|
1026
|
+
const peripheral = raced !== null && raced !== void 0 ? raced : discoveredDevices.get(deviceId);
|
|
1027
|
+
if (!peripheral || peripheral.state !== 'connected')
|
|
1028
|
+
return undefined;
|
|
1029
|
+
logger === null || logger === void 0 ? void 0 : logger.info('[NobleBLE] Direct connect-by-id succeeded', { deviceId });
|
|
1030
|
+
return peripheral;
|
|
1031
|
+
}
|
|
1032
|
+
catch (error) {
|
|
1033
|
+
directConnectCooldownUntil.set(deviceId, Date.now() + DIRECT_CONNECT_COOLDOWN_MS);
|
|
1034
|
+
logger === null || logger === void 0 ? void 0 : logger.info('[NobleBLE] Direct connect-by-id failed, falling back to scan', {
|
|
1035
|
+
deviceId,
|
|
1036
|
+
error: String(error),
|
|
1037
|
+
});
|
|
1038
|
+
return undefined;
|
|
1039
|
+
}
|
|
1040
|
+
});
|
|
1041
|
+
}
|
|
866
1042
|
function connectDevice(deviceId, webContents) {
|
|
1043
|
+
var _a;
|
|
867
1044
|
return index.__awaiter(this, void 0, void 0, function* () {
|
|
868
1045
|
logger === null || logger === void 0 ? void 0 : logger.info('[NobleBLE] Connect device request:', {
|
|
869
1046
|
deviceId,
|
|
@@ -873,7 +1050,7 @@ function connectDevice(deviceId, webContents) {
|
|
|
873
1050
|
totalDiscovered: discoveredDevices.size,
|
|
874
1051
|
totalConnected: connectedDevices.size,
|
|
875
1052
|
});
|
|
876
|
-
let peripheral = discoveredDevices.get(deviceId);
|
|
1053
|
+
let peripheral = (_a = discoveredDevices.get(deviceId)) !== null && _a !== void 0 ? _a : connectedDevices.get(deviceId);
|
|
877
1054
|
if (!peripheral) {
|
|
878
1055
|
logger === null || logger === void 0 ? void 0 : logger.info('[NobleBLE] Device not discovered, attempting targeted scan for:', deviceId);
|
|
879
1056
|
if (!noble) {
|
|
@@ -882,6 +1059,12 @@ function connectDevice(deviceId, webContents) {
|
|
|
882
1059
|
if (!noble) {
|
|
883
1060
|
throw hdShared.ERRORS.TypedError(hdShared.HardwareErrorCode.RuntimeError, 'Noble not available');
|
|
884
1061
|
}
|
|
1062
|
+
peripheral = yield tryDirectConnectById(deviceId);
|
|
1063
|
+
if (peripheral) {
|
|
1064
|
+
discoveredDevices.set(deviceId, peripheral);
|
|
1065
|
+
}
|
|
1066
|
+
}
|
|
1067
|
+
if (!peripheral) {
|
|
885
1068
|
try {
|
|
886
1069
|
const foundPeripheral = yield performTargetedScan(deviceId);
|
|
887
1070
|
if (!foundPeripheral) {
|
|
@@ -902,8 +1085,8 @@ function connectDevice(deviceId, webContents) {
|
|
|
902
1085
|
logger === null || logger === void 0 ? void 0 : logger.info('[NobleBLE] Device already connected, skipping connection step');
|
|
903
1086
|
if (!connectedDevices.has(deviceId)) {
|
|
904
1087
|
connectedDevices.set(deviceId, peripheral);
|
|
905
|
-
setupDisconnectListener(peripheral, deviceId, webContents);
|
|
906
1088
|
}
|
|
1089
|
+
setupDisconnectListener(peripheral, deviceId, webContents);
|
|
907
1090
|
if (deviceCharacteristics.has(deviceId)) {
|
|
908
1091
|
logger === null || logger === void 0 ? void 0 : logger.info('[NobleBLE] Device characteristics already available');
|
|
909
1092
|
const ongoingOperation = subscriptionOperations.get(deviceId);
|
|
@@ -925,18 +1108,37 @@ function connectDevice(deviceId, webContents) {
|
|
|
925
1108
|
notificationCallbacks.delete(deviceId);
|
|
926
1109
|
subscribedDevices.delete(deviceId);
|
|
927
1110
|
}
|
|
928
|
-
|
|
929
|
-
|
|
930
|
-
|
|
1111
|
+
try {
|
|
1112
|
+
const characteristics = yield setupConnectionAndDiscoverServices(peripheral, deviceId, webContents);
|
|
1113
|
+
deviceCharacteristics.set(deviceId, characteristics);
|
|
1114
|
+
logger === null || logger === void 0 ? void 0 : logger.info('[NobleBLE] Device ready for communication:', deviceId);
|
|
1115
|
+
}
|
|
1116
|
+
catch (setupError) {
|
|
1117
|
+
logger === null || logger === void 0 ? void 0 : logger.error('[NobleBLE] Connection setup failed on kept-alive link:', setupError);
|
|
1118
|
+
yield disconnectDevice(deviceId).catch(() => undefined);
|
|
1119
|
+
throw setupError;
|
|
1120
|
+
}
|
|
931
1121
|
return;
|
|
932
1122
|
}
|
|
933
1123
|
return new Promise((resolve, reject) => {
|
|
1124
|
+
let connectionTimedOut = false;
|
|
934
1125
|
const timeout = setTimeout(() => {
|
|
1126
|
+
connectionTimedOut = true;
|
|
935
1127
|
reject(hdShared.ERRORS.TypedError(hdShared.HardwareErrorCode.BleConnectedError, 'Connection timeout'));
|
|
936
|
-
},
|
|
1128
|
+
}, NOBLE_BLE_CONNECTION_TIMEOUT_MS);
|
|
937
1129
|
const connectedPeripheral = peripheral;
|
|
938
1130
|
connectedPeripheral.connect((error) => index.__awaiter(this, void 0, void 0, function* () {
|
|
939
1131
|
clearTimeout(timeout);
|
|
1132
|
+
if (connectionTimedOut) {
|
|
1133
|
+
if (!error) {
|
|
1134
|
+
try {
|
|
1135
|
+
connectedPeripheral.disconnect(() => undefined);
|
|
1136
|
+
}
|
|
1137
|
+
catch (_a) {
|
|
1138
|
+
}
|
|
1139
|
+
}
|
|
1140
|
+
return;
|
|
1141
|
+
}
|
|
940
1142
|
if (error) {
|
|
941
1143
|
logger === null || logger === void 0 ? void 0 : logger.error('[NobleBLE] Connection failed:', error);
|
|
942
1144
|
reject(hdShared.ERRORS.TypedError(hdShared.HardwareErrorCode.BleConnectedError, error.message));
|
|
@@ -966,17 +1168,20 @@ function disconnectDevice(deviceId) {
|
|
|
966
1168
|
if (!peripheral) {
|
|
967
1169
|
return;
|
|
968
1170
|
}
|
|
969
|
-
|
|
970
|
-
|
|
971
|
-
peripheral.disconnect
|
|
972
|
-
|
|
973
|
-
|
|
974
|
-
|
|
975
|
-
|
|
976
|
-
|
|
977
|
-
|
|
978
|
-
|
|
979
|
-
|
|
1171
|
+
const disconnectEntry = deviceDisconnectListeners.get(deviceId);
|
|
1172
|
+
if (disconnectEntry) {
|
|
1173
|
+
disconnectEntry.peripheral.removeListener('disconnect', disconnectEntry.listener);
|
|
1174
|
+
deviceDisconnectListeners.delete(deviceId);
|
|
1175
|
+
}
|
|
1176
|
+
yield runBleCallbackOperation(callback => peripheral.disconnect(() => callback()), {
|
|
1177
|
+
timeoutMs: BLE_CLEANUP_TIMEOUT,
|
|
1178
|
+
timeoutBehavior: 'resolve',
|
|
1179
|
+
});
|
|
1180
|
+
cleanupDevice(deviceId, undefined, {
|
|
1181
|
+
cleanupConnection: true,
|
|
1182
|
+
sendDisconnectEvent: false,
|
|
1183
|
+
cancelOperations: true,
|
|
1184
|
+
reason: 'manual-disconnect',
|
|
980
1185
|
});
|
|
981
1186
|
});
|
|
982
1187
|
}
|
|
@@ -991,18 +1196,11 @@ function unsubscribeNotifications(deviceId) {
|
|
|
991
1196
|
logger === null || logger === void 0 ? void 0 : logger.info('[NobleBLE] Unsubscribing from notifications for device:', deviceId);
|
|
992
1197
|
subscriptionOperations.set(deviceId, 'unsubscribing');
|
|
993
1198
|
try {
|
|
994
|
-
yield
|
|
995
|
-
|
|
996
|
-
|
|
997
|
-
logger === null || logger === void 0 ? void 0 : logger.error('[NobleBLE] Notification unsubscription failed:', error);
|
|
998
|
-
reject(error);
|
|
999
|
-
}
|
|
1000
|
-
else {
|
|
1001
|
-
logger === null || logger === void 0 ? void 0 : logger.info('[NobleBLE] Notification unsubscription successful');
|
|
1002
|
-
resolve();
|
|
1003
|
-
}
|
|
1004
|
-
});
|
|
1199
|
+
yield runBleCallbackOperation(callback => notifyCharacteristic.unsubscribe(callback), {
|
|
1200
|
+
timeoutMs: BLE_CLEANUP_TIMEOUT,
|
|
1201
|
+
timeoutBehavior: 'resolve',
|
|
1005
1202
|
});
|
|
1203
|
+
logger === null || logger === void 0 ? void 0 : logger.info('[NobleBLE] Notification unsubscription completed');
|
|
1006
1204
|
notifyCharacteristic.removeAllListeners('data');
|
|
1007
1205
|
notificationCallbacks.delete(deviceId);
|
|
1008
1206
|
subscribedDevices.delete(deviceId);
|
|
@@ -1054,19 +1252,13 @@ function subscribeNotifications(deviceId, callback) {
|
|
|
1054
1252
|
notificationCallbacks.set(deviceId, callback);
|
|
1055
1253
|
function rebuildAppSubscription(deviceId, notifyCharacteristic) {
|
|
1056
1254
|
return index.__awaiter(this, void 0, void 0, function* () {
|
|
1057
|
-
yield
|
|
1058
|
-
|
|
1059
|
-
|
|
1060
|
-
});
|
|
1255
|
+
yield runBleCallbackOperation(callback => notifyCharacteristic.unsubscribe(callback), {
|
|
1256
|
+
timeoutMs: BLE_CLEANUP_TIMEOUT,
|
|
1257
|
+
timeoutBehavior: 'resolve',
|
|
1061
1258
|
});
|
|
1062
|
-
yield
|
|
1063
|
-
|
|
1064
|
-
|
|
1065
|
-
reject(error);
|
|
1066
|
-
return;
|
|
1067
|
-
}
|
|
1068
|
-
resolve();
|
|
1069
|
-
});
|
|
1259
|
+
yield runBleCallbackOperation(callback => notifyCharacteristic.subscribe(callback), {
|
|
1260
|
+
timeoutMs: NOBLE_BLE_CONNECTION_TIMEOUT_MS,
|
|
1261
|
+
timeoutBehavior: 'reject',
|
|
1070
1262
|
});
|
|
1071
1263
|
notifyCharacteristic.on('data', (data) => {
|
|
1072
1264
|
if (!pairedDevices.has(deviceId)) {
|
|
@@ -1087,19 +1279,21 @@ function subscribeNotifications(deviceId, callback) {
|
|
|
1087
1279
|
});
|
|
1088
1280
|
}
|
|
1089
1281
|
function setupNobleBleHandlers(webContents) {
|
|
1090
|
-
console.log('[NobleBLE] Attempting to set up Noble BLE handlers.');
|
|
1091
1282
|
try {
|
|
1092
|
-
console.log('[NobleBLE] NOBLE_VERSION_771');
|
|
1093
1283
|
logger = require('electron-log');
|
|
1094
|
-
console.log('[NobleBLE] electron-log loaded successfully.');
|
|
1095
1284
|
const { ipcMain } = require('electron');
|
|
1096
|
-
|
|
1285
|
+
const handle = (channel, listener) => {
|
|
1286
|
+
ipcMain.removeHandler(channel);
|
|
1287
|
+
ipcMain.handle(channel, listener);
|
|
1288
|
+
};
|
|
1097
1289
|
safeLog(logger, 'info', 'Setting up Noble BLE IPC handlers');
|
|
1098
|
-
|
|
1099
|
-
ipcMain.handle(hdShared.EOneKeyBleMessageKeys.NOBLE_BLE_ENUMERATE, () => index.__awaiter(this, void 0, void 0, function* () {
|
|
1290
|
+
handle(hdShared.EOneKeyBleMessageKeys.NOBLE_BLE_ENUMERATE, () => index.__awaiter(this, void 0, void 0, function* () {
|
|
1100
1291
|
try {
|
|
1101
1292
|
const devices = yield enumerateDevices();
|
|
1102
|
-
safeLog(logger, '
|
|
1293
|
+
safeLog(logger, 'debug', 'Enumeration completed', {
|
|
1294
|
+
count: devices.length,
|
|
1295
|
+
devices: devices.map(device => ({ id: device.id, name: device.name })),
|
|
1296
|
+
});
|
|
1103
1297
|
return devices;
|
|
1104
1298
|
}
|
|
1105
1299
|
catch (error) {
|
|
@@ -1107,35 +1301,54 @@ function setupNobleBleHandlers(webContents) {
|
|
|
1107
1301
|
throw error;
|
|
1108
1302
|
}
|
|
1109
1303
|
}));
|
|
1110
|
-
|
|
1304
|
+
handle(hdShared.EOneKeyBleMessageKeys.NOBLE_BLE_STOP_SCAN, () => index.__awaiter(this, void 0, void 0, function* () {
|
|
1111
1305
|
yield stopScanning();
|
|
1112
1306
|
}));
|
|
1113
|
-
|
|
1114
|
-
|
|
1307
|
+
handle(hdShared.EOneKeyBleMessageKeys.NOBLE_BLE_GET_DEVICE, (_event, deviceId) => getDevice(deviceId));
|
|
1308
|
+
handle(hdShared.EOneKeyBleMessageKeys.NOBLE_BLE_CONNECT, (_event, deviceId) => index.__awaiter(this, void 0, void 0, function* () {
|
|
1115
1309
|
logger === null || logger === void 0 ? void 0 : logger.info('[NobleBLE] IPC CONNECT request received:', {
|
|
1116
1310
|
deviceId,
|
|
1117
1311
|
hasPeripheral: connectedDevices.has(deviceId),
|
|
1118
1312
|
hasCharacteristics: deviceCharacteristics.has(deviceId),
|
|
1119
1313
|
totalConnectedDevices: connectedDevices.size,
|
|
1120
1314
|
});
|
|
1121
|
-
|
|
1315
|
+
clearIdleDisconnect(deviceId);
|
|
1316
|
+
yield awaitIdleDisconnect(deviceId);
|
|
1317
|
+
try {
|
|
1318
|
+
yield connectDevice(deviceId, webContents);
|
|
1319
|
+
}
|
|
1320
|
+
finally {
|
|
1321
|
+
if (connectedDevices.has(deviceId)) {
|
|
1322
|
+
armIdleDisconnect(deviceId, BLE_BUSY_BACKSTOP_MS, 'busy-backstop');
|
|
1323
|
+
}
|
|
1324
|
+
}
|
|
1122
1325
|
}));
|
|
1123
|
-
|
|
1326
|
+
handle(hdShared.EOneKeyBleMessageKeys.NOBLE_BLE_RELEASE, (_event, deviceId, keepSession) => {
|
|
1327
|
+
if (!connectedDevices.has(deviceId))
|
|
1328
|
+
return;
|
|
1329
|
+
if (keepSession) {
|
|
1330
|
+
armIdleDisconnect(deviceId, BLE_BUSY_BACKSTOP_MS, 'busy-backstop');
|
|
1331
|
+
return;
|
|
1332
|
+
}
|
|
1333
|
+
armIdleDisconnect(deviceId);
|
|
1334
|
+
});
|
|
1335
|
+
handle(hdShared.EOneKeyBleMessageKeys.NOBLE_BLE_DISCONNECT, (_event, deviceId) => index.__awaiter(this, void 0, void 0, function* () {
|
|
1124
1336
|
yield disconnectDevice(deviceId);
|
|
1125
1337
|
}));
|
|
1126
|
-
|
|
1127
|
-
|
|
1128
|
-
yield transmitHexDataToDevice(deviceId, hexData);
|
|
1338
|
+
handle(hdShared.EOneKeyBleMessageKeys.NOBLE_BLE_WRITE, (_event, deviceId, hexData, options) => index.__awaiter(this, void 0, void 0, function* () {
|
|
1339
|
+
yield transmitHexDataToDevice(deviceId, hexData, options);
|
|
1129
1340
|
}));
|
|
1130
|
-
|
|
1341
|
+
handle(hdShared.EOneKeyBleMessageKeys.NOBLE_BLE_SUBSCRIBE, (_event, deviceId) => index.__awaiter(this, void 0, void 0, function* () {
|
|
1131
1342
|
yield subscribeNotifications(deviceId, (data) => {
|
|
1132
1343
|
webContents.send(hdShared.EOneKeyBleMessageKeys.NOBLE_BLE_NOTIFICATION, deviceId, data);
|
|
1133
1344
|
});
|
|
1345
|
+
armIdleDisconnect(deviceId, BLE_BUSY_BACKSTOP_MS, 'busy-backstop');
|
|
1134
1346
|
}));
|
|
1135
|
-
|
|
1347
|
+
handle(hdShared.EOneKeyBleMessageKeys.NOBLE_BLE_UNSUBSCRIBE, (_event, deviceId) => index.__awaiter(this, void 0, void 0, function* () {
|
|
1136
1348
|
yield unsubscribeNotifications(deviceId);
|
|
1349
|
+
armIdleDisconnect(deviceId);
|
|
1137
1350
|
}));
|
|
1138
|
-
|
|
1351
|
+
handle(hdShared.EOneKeyBleMessageKeys.NOBLE_BLE_CANCEL_PAIRING, () => index.__awaiter(this, void 0, void 0, function* () {
|
|
1139
1352
|
const deviceIds = Array.from(connectedDevices.keys());
|
|
1140
1353
|
logger === null || logger === void 0 ? void 0 : logger.info('[NobleBLE] Cancel pairing invoked', {
|
|
1141
1354
|
platform: process.platform,
|
|
@@ -1151,7 +1364,7 @@ function setupNobleBleHandlers(webContents) {
|
|
|
1151
1364
|
}
|
|
1152
1365
|
}
|
|
1153
1366
|
}));
|
|
1154
|
-
|
|
1367
|
+
handle(hdShared.EOneKeyBleMessageKeys.BLE_AVAILABILITY_CHECK, () => index.__awaiter(this, void 0, void 0, function* () {
|
|
1155
1368
|
try {
|
|
1156
1369
|
const bluetoothStatus = yield checkBluetoothAvailability();
|
|
1157
1370
|
safeLog(logger, 'info', 'Bluetooth availability check completed:', bluetoothStatus);
|
|
@@ -1169,23 +1382,23 @@ function setupNobleBleHandlers(webContents) {
|
|
|
1169
1382
|
}));
|
|
1170
1383
|
webContents.on('destroyed', () => {
|
|
1171
1384
|
safeLog(logger, 'info', 'Cleaning up Noble BLE handlers');
|
|
1172
|
-
|
|
1173
|
-
|
|
1174
|
-
|
|
1175
|
-
|
|
1176
|
-
|
|
1177
|
-
|
|
1178
|
-
|
|
1179
|
-
|
|
1385
|
+
(() => index.__awaiter(this, void 0, void 0, function* () {
|
|
1386
|
+
const deviceIds = Array.from(connectedDevices.keys());
|
|
1387
|
+
for (const deviceId of deviceIds) {
|
|
1388
|
+
yield unsubscribeNotifications(deviceId).catch(() => undefined);
|
|
1389
|
+
yield disconnectDevice(deviceId).catch(() => undefined);
|
|
1390
|
+
}
|
|
1391
|
+
yield stopScanning().catch(() => undefined);
|
|
1392
|
+
if (noble && persistentStateListener) {
|
|
1393
|
+
noble.removeListener('stateChange', persistentStateListener);
|
|
1394
|
+
persistentStateListener = null;
|
|
1395
|
+
}
|
|
1396
|
+
cleanupNobleListeners();
|
|
1397
|
+
discoveredDevices.clear();
|
|
1398
|
+
safeLog(logger, 'info', 'Noble BLE cleanup completed');
|
|
1399
|
+
}))().catch(error => {
|
|
1400
|
+
safeLog(logger, 'error', 'Noble BLE cleanup failed', error);
|
|
1180
1401
|
});
|
|
1181
|
-
stopScanning();
|
|
1182
|
-
if (noble && persistentStateListener) {
|
|
1183
|
-
noble.removeListener('stateChange', persistentStateListener);
|
|
1184
|
-
persistentStateListener = null;
|
|
1185
|
-
}
|
|
1186
|
-
cleanupNobleListeners();
|
|
1187
|
-
discoveredDevices.clear();
|
|
1188
|
-
safeLog(logger, 'info', 'Noble BLE cleanup completed');
|
|
1189
1402
|
});
|
|
1190
1403
|
safeLog(logger, 'info', 'Noble BLE IPC handlers setup completed');
|
|
1191
1404
|
}
|
|
@@ -1195,4 +1408,5 @@ function setupNobleBleHandlers(webContents) {
|
|
|
1195
1408
|
}
|
|
1196
1409
|
}
|
|
1197
1410
|
|
|
1411
|
+
exports.resolveNobleBleWritePacingDelay = resolveNobleBleWritePacingDelay;
|
|
1198
1412
|
exports.setupNobleBleHandlers = setupNobleBleHandlers;
|