@onekeyfe/hd-transport-electron 1.2.0-alpha.7 → 1.2.0-alpha.71
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-bd1cfdb6.js} +1 -1
- package/dist/index.d.ts +10 -0
- package/dist/index.js +1 -1
- package/dist/{noble-ble-handler-94c42077.js → noble-ble-handler-7ac9c43d.js} +276 -234
- 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 +5 -0
- 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 +354 -0
- package/src/ble-ops.ts +40 -10
- package/src/ble-packet-capacity.ts +13 -0
- package/src/noble-ble-handler.ts +273 -253
- package/src/noble-ble-timeouts.ts +2 -0
- package/src/types/desktop-api.ts +2 -1
- 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-bd1cfdb6.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,39 @@ 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_PACKET_SIZE_FALLBACK = 192;
|
|
120
|
+
const BLE_PACKET_SIZE_MAXIMUM = 244;
|
|
81
121
|
const RETRY_CONFIG = { MAX_ATTEMPTS: 15, WRITE_TIMEOUT: 2000 };
|
|
82
122
|
const IS_WINDOWS = process.platform === 'win32';
|
|
83
123
|
const ABORTABLE_WRITE_ERROR_PATTERNS = [
|
|
84
124
|
/status:\s*3/i,
|
|
85
125
|
];
|
|
86
|
-
function getBleUuidKey(uuid) {
|
|
87
|
-
const normalized = (uuid !== null && uuid !== void 0 ? uuid : '').replace(/-/g, '').toLowerCase();
|
|
88
|
-
return normalized.length >= 8 ? normalized.substring(4, 8) : normalized;
|
|
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
|
-
});
|
|
105
|
-
}
|
|
106
126
|
function isOneKeyPeripheral(peripheral) {
|
|
107
|
-
var _a;
|
|
108
|
-
const
|
|
109
|
-
|
|
127
|
+
var _a, _b;
|
|
128
|
+
const serviceUuids = (_a = peripheral.advertisement) === null || _a === void 0 ? void 0 : _a.serviceUuids;
|
|
129
|
+
const localName = (_b = peripheral.advertisement) === null || _b === void 0 ? void 0 : _b.localName;
|
|
130
|
+
if (!(localName === null || localName === void 0 ? void 0 : localName.trim()) || hdShared.isPro2FindMyAdvertisementName(localName)) {
|
|
131
|
+
return false;
|
|
132
|
+
}
|
|
133
|
+
return (hdShared.hasOnekeyCommunicationService(serviceUuids) &&
|
|
134
|
+
hdShared.isOnekeyBluetoothDevice({
|
|
135
|
+
id: peripheral.id,
|
|
136
|
+
localName,
|
|
137
|
+
serviceUuids,
|
|
138
|
+
}));
|
|
110
139
|
}
|
|
111
140
|
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
141
|
const appCb = notificationCallbacks.get(deviceId);
|
|
118
142
|
if (appCb)
|
|
119
143
|
appCb(data.toString('hex'));
|
|
@@ -250,9 +274,12 @@ function initializeNoble() {
|
|
|
250
274
|
};
|
|
251
275
|
noble.on('stateChange', onStateChange);
|
|
252
276
|
});
|
|
253
|
-
|
|
254
|
-
|
|
255
|
-
|
|
277
|
+
if (!persistentDiscoverListener) {
|
|
278
|
+
persistentDiscoverListener = (peripheral) => {
|
|
279
|
+
handleDeviceDiscovered(peripheral);
|
|
280
|
+
};
|
|
281
|
+
noble.on('discover', persistentDiscoverListener);
|
|
282
|
+
}
|
|
256
283
|
logger === null || logger === void 0 ? void 0 : logger.info('[NobleBLE] Noble initialized successfully');
|
|
257
284
|
}
|
|
258
285
|
catch (error) {
|
|
@@ -277,6 +304,16 @@ function cleanupDevice(deviceId, webContents, options = {}) {
|
|
|
277
304
|
const peripheral = connectedDevices.get(deviceId);
|
|
278
305
|
const deviceName = ((_a = peripheral === null || peripheral === void 0 ? void 0 : peripheral.advertisement) === null || _a === void 0 ? void 0 : _a.localName) || 'Unknown Device';
|
|
279
306
|
if (cleanupConnection) {
|
|
307
|
+
const disconnectEntry = deviceDisconnectListeners.get(deviceId);
|
|
308
|
+
if (disconnectEntry) {
|
|
309
|
+
disconnectEntry.peripheral.removeListener('disconnect', disconnectEntry.listener);
|
|
310
|
+
deviceDisconnectListeners.delete(deviceId);
|
|
311
|
+
}
|
|
312
|
+
const mtuEntry = deviceMtuListeners.get(deviceId);
|
|
313
|
+
if (mtuEntry) {
|
|
314
|
+
mtuEntry.peripheral.removeListener('mtu', mtuEntry.listener);
|
|
315
|
+
deviceMtuListeners.delete(deviceId);
|
|
316
|
+
}
|
|
280
317
|
connectedDevices.delete(deviceId);
|
|
281
318
|
deviceCharacteristics.delete(deviceId);
|
|
282
319
|
notificationCallbacks.delete(deviceId);
|
|
@@ -311,12 +348,34 @@ function handleDeviceDisconnect(deviceId, webContents) {
|
|
|
311
348
|
});
|
|
312
349
|
}
|
|
313
350
|
function setupDisconnectListener(peripheral, deviceId, webContents) {
|
|
314
|
-
|
|
315
|
-
|
|
351
|
+
const existing = deviceDisconnectListeners.get(deviceId);
|
|
352
|
+
if (existing) {
|
|
353
|
+
existing.peripheral.removeListener('disconnect', existing.listener);
|
|
354
|
+
}
|
|
355
|
+
const listener = () => {
|
|
316
356
|
handleDeviceDisconnect(deviceId, webContents);
|
|
317
|
-
}
|
|
357
|
+
};
|
|
358
|
+
deviceDisconnectListeners.set(deviceId, { peripheral, listener });
|
|
359
|
+
peripheral.on('disconnect', listener);
|
|
360
|
+
setupMtuListener(peripheral, deviceId, webContents);
|
|
361
|
+
}
|
|
362
|
+
function setupMtuListener(peripheral, deviceId, webContents) {
|
|
363
|
+
const existing = deviceMtuListeners.get(deviceId);
|
|
364
|
+
if (existing) {
|
|
365
|
+
existing.peripheral.removeListener('mtu', existing.listener);
|
|
366
|
+
}
|
|
367
|
+
const listener = (mtu) => {
|
|
368
|
+
if (!Number.isFinite(mtu) || mtu <= 0)
|
|
369
|
+
return;
|
|
370
|
+
webContents.send(hdShared.EOneKeyBleMessageKeys.NOBLE_BLE_MTU_CHANGED, {
|
|
371
|
+
id: deviceId,
|
|
372
|
+
mtu,
|
|
373
|
+
});
|
|
374
|
+
};
|
|
375
|
+
deviceMtuListeners.set(deviceId, { peripheral, listener });
|
|
376
|
+
peripheral.on('mtu', listener);
|
|
318
377
|
}
|
|
319
|
-
function
|
|
378
|
+
function writeCharacteristicWithoutResponse(deviceId, writeCharacteristic, buffer) {
|
|
320
379
|
return index.__awaiter(this, void 0, void 0, function* () {
|
|
321
380
|
return new Promise((resolve, reject) => {
|
|
322
381
|
writeCharacteristic.write(buffer, true, (error) => {
|
|
@@ -348,7 +407,7 @@ function attemptWindowsWriteUntilPaired(deviceId, doGetWriteCharacteristic, payl
|
|
|
348
407
|
throw hdShared.ERRORS.TypedError(hdShared.HardwareErrorCode.RuntimeError, `Write characteristic not available for ${deviceId}`);
|
|
349
408
|
}
|
|
350
409
|
try {
|
|
351
|
-
yield
|
|
410
|
+
yield writeCharacteristicWithoutResponse(deviceId, latestWrite, payload);
|
|
352
411
|
}
|
|
353
412
|
catch (e) {
|
|
354
413
|
const errorMessage = e instanceof Error ? e.message : String(e);
|
|
@@ -415,84 +474,78 @@ function transmitHexDataToDevice(deviceId, hexData) {
|
|
|
415
474
|
throw hdShared.ERRORS.TypedError(hdShared.HardwareErrorCode.BleCharacteristicNotFound, `Device ${deviceId} not connected or characteristics not available`);
|
|
416
475
|
}
|
|
417
476
|
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
477
|
const doGetWriteCharacteristic = () => { var _a; return (_a = deviceCharacteristics.get(deviceId)) === null || _a === void 0 ? void 0 : _a.write; };
|
|
478
|
+
const packetCapacity = resolveBlePacketCapacity(peripheral.mtu, BLE_PACKET_SIZE_MAXIMUM, BLE_PACKET_SIZE_FALLBACK);
|
|
424
479
|
if (!IS_WINDOWS || pairedDevices.has(deviceId)) {
|
|
425
480
|
const writeCharacteristic = doGetWriteCharacteristic();
|
|
426
481
|
if (!writeCharacteristic) {
|
|
427
482
|
throw hdShared.ERRORS.TypedError(hdShared.HardwareErrorCode.BleCharacteristicNotFound, `Write characteristic not available for ${deviceId}`);
|
|
428
483
|
}
|
|
429
|
-
if (toBuffer.length <=
|
|
430
|
-
yield
|
|
431
|
-
yield writeCharacteristicWithAck(deviceId, writeCharacteristic, toBuffer);
|
|
484
|
+
if (toBuffer.length <= packetCapacity) {
|
|
485
|
+
yield writeCharacteristicWithoutResponse(deviceId, writeCharacteristic, toBuffer);
|
|
432
486
|
return;
|
|
433
487
|
}
|
|
434
488
|
for (let offset = 0; offset < toBuffer.length;) {
|
|
435
|
-
const chunkSize = Math.min(
|
|
489
|
+
const chunkSize = Math.min(packetCapacity, toBuffer.length - offset);
|
|
436
490
|
const chunk = toBuffer.subarray(offset, offset + chunkSize);
|
|
437
491
|
offset += chunkSize;
|
|
438
492
|
const latest = doGetWriteCharacteristic();
|
|
439
493
|
if (!latest) {
|
|
440
494
|
throw hdShared.ERRORS.TypedError(hdShared.HardwareErrorCode.BleCharacteristicNotFound, `Write characteristic not available for ${deviceId}`);
|
|
441
495
|
}
|
|
442
|
-
yield
|
|
443
|
-
if (offset < toBuffer.length) {
|
|
444
|
-
yield hdShared.wait(UNIFIED_WRITE_DELAY);
|
|
445
|
-
}
|
|
496
|
+
yield writeCharacteristicWithoutResponse(deviceId, latest, chunk);
|
|
446
497
|
}
|
|
447
498
|
return;
|
|
448
499
|
}
|
|
449
|
-
if (toBuffer.length <=
|
|
450
|
-
yield hdShared.wait(UNIFIED_WRITE_DELAY);
|
|
500
|
+
if (toBuffer.length <= packetCapacity) {
|
|
451
501
|
yield attemptWindowsWriteUntilPaired(deviceId, doGetWriteCharacteristic, toBuffer, 'single');
|
|
452
502
|
return;
|
|
453
503
|
}
|
|
454
504
|
for (let offset = 0, idx = 0; offset < toBuffer.length; idx++) {
|
|
455
|
-
const chunkSize = Math.min(
|
|
505
|
+
const chunkSize = Math.min(packetCapacity, toBuffer.length - offset);
|
|
456
506
|
const chunk = toBuffer.subarray(offset, offset + chunkSize);
|
|
457
507
|
offset += chunkSize;
|
|
458
508
|
yield attemptWindowsWriteUntilPaired(deviceId, doGetWriteCharacteristic, chunk, `chunk-${idx + 1}`);
|
|
459
|
-
if (offset < toBuffer.length) {
|
|
460
|
-
yield hdShared.wait(UNIFIED_WRITE_DELAY);
|
|
461
|
-
}
|
|
462
509
|
}
|
|
463
510
|
});
|
|
464
511
|
}
|
|
465
512
|
function handleDeviceDiscovered(peripheral) {
|
|
466
513
|
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
514
|
if (!isOneKeyPeripheral(peripheral)) {
|
|
470
515
|
return;
|
|
471
516
|
}
|
|
472
517
|
const isNewDevice = !discoveredDevices.has(peripheral.id);
|
|
473
518
|
discoveredDevices.set(peripheral.id, peripheral);
|
|
474
519
|
if (isNewDevice) {
|
|
475
|
-
logger === null || logger === void 0 ? void 0 : logger.
|
|
476
|
-
|
|
477
|
-
|
|
478
|
-
serviceUUIDs: serviceUuids,
|
|
520
|
+
logger === null || logger === void 0 ? void 0 : logger.debug('[NobleBLE] OneKey BLE device discovered', {
|
|
521
|
+
deviceId: peripheral.id,
|
|
522
|
+
name: ((_a = peripheral.advertisement) === null || _a === void 0 ? void 0 : _a.localName) || 'Unknown Device',
|
|
523
|
+
serviceUUIDs: ((_b = peripheral.advertisement) === null || _b === void 0 ? void 0 : _b.serviceUuids) || [],
|
|
479
524
|
});
|
|
480
525
|
}
|
|
481
526
|
}
|
|
482
527
|
function ensureDiscoverListener() {
|
|
483
528
|
if (!noble)
|
|
484
529
|
return;
|
|
485
|
-
|
|
486
|
-
if (listenerCount === 0) {
|
|
530
|
+
if (!persistentDiscoverListener) {
|
|
487
531
|
logger === null || logger === void 0 ? void 0 : logger.info('[NobleBLE] Discover listener missing, re-adding it');
|
|
488
|
-
|
|
532
|
+
persistentDiscoverListener = (peripheral) => {
|
|
489
533
|
handleDeviceDiscovered(peripheral);
|
|
490
|
-
}
|
|
534
|
+
};
|
|
535
|
+
noble.on('discover', persistentDiscoverListener);
|
|
491
536
|
}
|
|
492
537
|
else {
|
|
493
|
-
logger === null || logger === void 0 ? void 0 : logger.debug('[NobleBLE] Discover listener already
|
|
538
|
+
logger === null || logger === void 0 ? void 0 : logger.debug('[NobleBLE] Discover listener already registered');
|
|
494
539
|
}
|
|
495
540
|
}
|
|
541
|
+
function waitForNobleScanStop(nobleInstance) {
|
|
542
|
+
return index.__awaiter(this, void 0, void 0, function* () {
|
|
543
|
+
yield runBleCallbackOperation(callback => nobleInstance.stopScanning(() => callback()), {
|
|
544
|
+
timeoutMs: BLE_CLEANUP_TIMEOUT,
|
|
545
|
+
timeoutBehavior: 'resolve',
|
|
546
|
+
});
|
|
547
|
+
});
|
|
548
|
+
}
|
|
496
549
|
function performTargetedScan(targetDeviceId) {
|
|
497
550
|
return index.__awaiter(this, void 0, void 0, function* () {
|
|
498
551
|
if (!noble) {
|
|
@@ -501,33 +554,43 @@ function performTargetedScan(targetDeviceId) {
|
|
|
501
554
|
const nobleInstance = noble;
|
|
502
555
|
logger === null || logger === void 0 ? void 0 : logger.info('[NobleBLE] Starting targeted scan for device:', targetDeviceId);
|
|
503
556
|
return new Promise((resolve, reject) => {
|
|
557
|
+
let settled = false;
|
|
558
|
+
const finish = (peripheral, error) => index.__awaiter(this, void 0, void 0, function* () {
|
|
559
|
+
if (settled)
|
|
560
|
+
return;
|
|
561
|
+
settled = true;
|
|
562
|
+
if (timeoutId)
|
|
563
|
+
clearTimeout(timeoutId);
|
|
564
|
+
nobleInstance.removeListener('discover', onDiscover);
|
|
565
|
+
yield waitForNobleScanStop(nobleInstance);
|
|
566
|
+
if (error) {
|
|
567
|
+
logger === null || logger === void 0 ? void 0 : logger.error('[NobleBLE] Failed to start targeted scan:', error);
|
|
568
|
+
reject(hdShared.ERRORS.TypedError(hdShared.HardwareErrorCode.BleScanError, error.message));
|
|
569
|
+
return;
|
|
570
|
+
}
|
|
571
|
+
if (peripheral) {
|
|
572
|
+
discoveredDevices.set(peripheral.id, peripheral);
|
|
573
|
+
}
|
|
574
|
+
resolve(peripheral);
|
|
575
|
+
});
|
|
504
576
|
const onDiscover = (peripheral) => {
|
|
505
577
|
var _a;
|
|
506
|
-
if (peripheral.id === targetDeviceId) {
|
|
578
|
+
if (peripheral.id === targetDeviceId && isOneKeyPeripheral(peripheral)) {
|
|
507
579
|
logger === null || logger === void 0 ? void 0 : logger.info('[NobleBLE] Target device found during targeted scan:', {
|
|
508
580
|
id: peripheral.id,
|
|
509
581
|
name: (_a = peripheral.advertisement) === null || _a === void 0 ? void 0 : _a.localName,
|
|
510
582
|
});
|
|
511
|
-
|
|
512
|
-
nobleInstance.removeListener('discover', onDiscover);
|
|
513
|
-
nobleInstance.stopScanning();
|
|
514
|
-
discoveredDevices.set(peripheral.id, peripheral);
|
|
515
|
-
resolve(peripheral);
|
|
583
|
+
finish(peripheral).catch(reject);
|
|
516
584
|
}
|
|
517
585
|
};
|
|
518
586
|
const timeoutId = setTimeout(() => {
|
|
519
|
-
nobleInstance.removeListener('discover', onDiscover);
|
|
520
|
-
nobleInstance.stopScanning();
|
|
521
587
|
logger === null || logger === void 0 ? void 0 : logger.info('[NobleBLE] Targeted scan timeout for device:', targetDeviceId);
|
|
522
|
-
|
|
523
|
-
},
|
|
588
|
+
finish(null).catch(reject);
|
|
589
|
+
}, NOBLE_BLE_TARGETED_SCAN_TIMEOUT_MS);
|
|
524
590
|
nobleInstance.on('discover', onDiscover);
|
|
525
591
|
nobleInstance.startScanning([], false, (error) => {
|
|
526
592
|
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));
|
|
593
|
+
finish(null, error).catch(reject);
|
|
531
594
|
return;
|
|
532
595
|
}
|
|
533
596
|
logger === null || logger === void 0 ? void 0 : logger.info('[NobleBLE] Targeted scan started for device:', targetDeviceId);
|
|
@@ -550,12 +613,12 @@ function enumerateDevices() {
|
|
|
550
613
|
return new Promise((resolve, reject) => {
|
|
551
614
|
const devices = [];
|
|
552
615
|
let intervalId;
|
|
553
|
-
const cleanup = () => {
|
|
616
|
+
const cleanup = () => index.__awaiter(this, void 0, void 0, function* () {
|
|
554
617
|
clearTimeout(timeoutId);
|
|
555
618
|
if (intervalId)
|
|
556
619
|
clearInterval(intervalId);
|
|
557
|
-
nobleInstance
|
|
558
|
-
};
|
|
620
|
+
yield waitForNobleScanStop(nobleInstance);
|
|
621
|
+
});
|
|
559
622
|
const checkDevices = () => {
|
|
560
623
|
discoveredDevices.forEach((peripheral, id) => {
|
|
561
624
|
var _a;
|
|
@@ -571,23 +634,23 @@ function enumerateDevices() {
|
|
|
571
634
|
}
|
|
572
635
|
});
|
|
573
636
|
};
|
|
574
|
-
const timeoutId = setTimeout(() => {
|
|
637
|
+
const timeoutId = setTimeout(() => index.__awaiter(this, void 0, void 0, function* () {
|
|
575
638
|
checkDevices();
|
|
576
|
-
cleanup();
|
|
639
|
+
yield cleanup();
|
|
577
640
|
logger === null || logger === void 0 ? void 0 : logger.info('[NobleBLE] Scan completed, found devices:', devices.length);
|
|
578
641
|
resolve(devices);
|
|
579
|
-
}, DEVICE_SCAN_TIMEOUT);
|
|
642
|
+
}), DEVICE_SCAN_TIMEOUT);
|
|
580
643
|
logger === null || logger === void 0 ? void 0 : logger.info('[NobleBLE] Scanning for OneKey BLE devices');
|
|
581
|
-
nobleInstance.startScanning([], false, (error) => {
|
|
644
|
+
nobleInstance.startScanning([], false, (error) => index.__awaiter(this, void 0, void 0, function* () {
|
|
582
645
|
if (error) {
|
|
583
|
-
cleanup();
|
|
646
|
+
yield cleanup();
|
|
584
647
|
logger === null || logger === void 0 ? void 0 : logger.error('[NobleBLE] Failed to start scanning:', error);
|
|
585
648
|
reject(hdShared.ERRORS.TypedError(hdShared.HardwareErrorCode.BleScanError, error.message));
|
|
586
649
|
return;
|
|
587
650
|
}
|
|
588
651
|
logger === null || logger === void 0 ? void 0 : logger.info('[NobleBLE] Scanning started for OneKey devices');
|
|
589
652
|
intervalId = setInterval(checkDevices, DEVICE_CHECK_INTERVAL);
|
|
590
|
-
});
|
|
653
|
+
}));
|
|
591
654
|
});
|
|
592
655
|
});
|
|
593
656
|
}
|
|
@@ -595,25 +658,20 @@ function stopScanning() {
|
|
|
595
658
|
return index.__awaiter(this, void 0, void 0, function* () {
|
|
596
659
|
if (!noble)
|
|
597
660
|
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
|
-
});
|
|
661
|
+
const nobleInstance = noble;
|
|
662
|
+
yield waitForNobleScanStop(nobleInstance);
|
|
663
|
+
logger === null || logger === void 0 ? void 0 : logger.info('[NobleBLE] Scanning stopped');
|
|
608
664
|
});
|
|
609
665
|
}
|
|
610
666
|
function cleanupNobleListeners() {
|
|
611
667
|
if (!noble)
|
|
612
668
|
return;
|
|
613
669
|
try {
|
|
614
|
-
|
|
615
|
-
|
|
616
|
-
|
|
670
|
+
if (persistentDiscoverListener) {
|
|
671
|
+
noble.removeListener('discover', persistentDiscoverListener);
|
|
672
|
+
persistentDiscoverListener = null;
|
|
673
|
+
}
|
|
674
|
+
logger === null || logger === void 0 ? void 0 : logger.info('[NobleBLE] Owned Noble listeners cleaned up');
|
|
617
675
|
}
|
|
618
676
|
catch (error) {
|
|
619
677
|
logger === null || logger === void 0 ? void 0 : logger.error('[NobleBLE] Failed to clean up some listeners:', error);
|
|
@@ -624,22 +682,12 @@ function getDevice(deviceId) {
|
|
|
624
682
|
const peripheral = discoveredDevices.get(deviceId);
|
|
625
683
|
if (peripheral) {
|
|
626
684
|
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
|
-
};
|
|
685
|
+
return Object.assign({ commType: 'electron-ble', id: peripheral.id, name: deviceName, state: peripheral.state || 'disconnected' }, (typeof peripheral.mtu === 'number' ? { mtu: peripheral.mtu } : {}));
|
|
633
686
|
}
|
|
634
687
|
const connectedPeripheral = connectedDevices.get(deviceId);
|
|
635
688
|
if (connectedPeripheral) {
|
|
636
689
|
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
|
-
};
|
|
690
|
+
return Object.assign({ commType: 'electron-ble', id: connectedPeripheral.id, name: deviceName, state: connectedPeripheral.state || 'connected' }, (typeof connectedPeripheral.mtu === 'number' ? { mtu: connectedPeripheral.mtu } : {}));
|
|
643
691
|
}
|
|
644
692
|
return {
|
|
645
693
|
commType: 'electron-ble',
|
|
@@ -683,23 +731,22 @@ function discoverServicesAndCharacteristics(peripheral) {
|
|
|
683
731
|
}
|
|
684
732
|
});
|
|
685
733
|
});
|
|
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
734
|
if (!services || services.length === 0) {
|
|
688
735
|
throw hdShared.ERRORS.TypedError(hdShared.HardwareErrorCode.BleServiceNotFound, 'No services found');
|
|
689
736
|
}
|
|
690
|
-
|
|
691
|
-
|
|
692
|
-
|
|
693
|
-
|
|
694
|
-
|
|
695
|
-
services.find(s => !isGenericBleService(s.uuid)) ||
|
|
696
|
-
services[0];
|
|
697
|
-
}
|
|
737
|
+
logger === null || logger === void 0 ? void 0 : logger.debug('[NobleBLE] services discovered', {
|
|
738
|
+
deviceId: peripheral.id,
|
|
739
|
+
serviceUUIDs: services.map(service => service.uuid),
|
|
740
|
+
});
|
|
741
|
+
const service = services.find(s => hdShared.matchesKnownBleUuid(s.uuid, ONEKEY_SERVICE_UUID_ALIASES));
|
|
698
742
|
if (!service) {
|
|
699
743
|
throw hdShared.ERRORS.TypedError(hdShared.HardwareErrorCode.BleServiceNotFound);
|
|
700
744
|
}
|
|
701
745
|
const selectedService = service;
|
|
702
|
-
logger === null || logger === void 0 ? void 0 : logger.
|
|
746
|
+
logger === null || logger === void 0 ? void 0 : logger.debug('[NobleBLE] service selected', {
|
|
747
|
+
deviceId: peripheral.id,
|
|
748
|
+
serviceUuid: selectedService.uuid,
|
|
749
|
+
});
|
|
703
750
|
const characteristics = yield new Promise((resolve, reject) => {
|
|
704
751
|
selectedService.discoverCharacteristics([], (error, chars) => {
|
|
705
752
|
if (error) {
|
|
@@ -711,30 +758,26 @@ function discoverServicesAndCharacteristics(peripheral) {
|
|
|
711
758
|
}
|
|
712
759
|
});
|
|
713
760
|
});
|
|
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
761
|
let writeCharacteristic = null;
|
|
719
762
|
let notifyCharacteristic = null;
|
|
720
763
|
for (const characteristic of characteristics) {
|
|
721
|
-
|
|
722
|
-
const uuidKey = uuid.length >= 8 ? uuid.substring(4, 8) : uuid;
|
|
723
|
-
if (uuidKey === NORMALIZED_WRITE_UUID) {
|
|
764
|
+
if (hdShared.matchesKnownBleUuid(characteristic.uuid, ONEKEY_WRITE_UUID_ALIASES)) {
|
|
724
765
|
writeCharacteristic = characteristic;
|
|
725
766
|
}
|
|
726
|
-
else if (
|
|
767
|
+
else if (hdShared.matchesKnownBleUuid(characteristic.uuid, ONEKEY_NOTIFY_UUID_ALIASES)) {
|
|
727
768
|
notifyCharacteristic = characteristic;
|
|
728
769
|
}
|
|
729
770
|
}
|
|
730
|
-
logger === null || logger === void 0 ? void 0 : logger.info('[NobleBLE] Characteristic discovery result:', {
|
|
731
|
-
writeFound: !!writeCharacteristic,
|
|
732
|
-
notifyFound: !!notifyCharacteristic,
|
|
733
|
-
});
|
|
734
771
|
if (!writeCharacteristic || !notifyCharacteristic) {
|
|
735
772
|
logger === null || logger === void 0 ? void 0 : logger.error('[NobleBLE] Missing characteristics - write:', !!writeCharacteristic, 'notify:', !!notifyCharacteristic);
|
|
736
773
|
throw hdShared.ERRORS.TypedError(hdShared.HardwareErrorCode.BleCharacteristicNotFound, 'Required characteristics not found');
|
|
737
774
|
}
|
|
775
|
+
logger === null || logger === void 0 ? void 0 : logger.debug('[NobleBLE] characteristics selected', {
|
|
776
|
+
deviceId: peripheral.id,
|
|
777
|
+
serviceUuid: selectedService.uuid,
|
|
778
|
+
writeUuid: writeCharacteristic.uuid,
|
|
779
|
+
notifyUuid: notifyCharacteristic.uuid,
|
|
780
|
+
});
|
|
738
781
|
return { write: writeCharacteristic, notify: notifyCharacteristic };
|
|
739
782
|
}))();
|
|
740
783
|
try {
|
|
@@ -755,27 +798,17 @@ function forceReconnectPeripheral(peripheral, deviceId) {
|
|
|
755
798
|
reason: 'force-reconnect',
|
|
756
799
|
});
|
|
757
800
|
if (peripheral.state === 'connected') {
|
|
758
|
-
peripheral.
|
|
759
|
-
|
|
760
|
-
|
|
761
|
-
|
|
762
|
-
resolve();
|
|
763
|
-
});
|
|
764
|
-
});
|
|
801
|
+
yield runBleCallbackOperation(callback => peripheral.disconnect(() => {
|
|
802
|
+
logger === null || logger === void 0 ? void 0 : logger.info('[NobleBLE] Force disconnect completed');
|
|
803
|
+
callback();
|
|
804
|
+
}), { timeoutMs: BLE_CLEANUP_TIMEOUT, timeoutBehavior: 'resolve' });
|
|
765
805
|
}
|
|
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
|
-
});
|
|
806
|
+
yield runBleCallbackOperation(callback => peripheral.connect(callback), {
|
|
807
|
+
timeoutMs: NOBLE_BLE_CONNECTION_TIMEOUT_MS,
|
|
808
|
+
timeoutBehavior: 'reject',
|
|
778
809
|
});
|
|
810
|
+
logger === null || logger === void 0 ? void 0 : logger.info('[NobleBLE] Force reconnect successful');
|
|
811
|
+
connectedDevices.set(deviceId, peripheral);
|
|
779
812
|
yield hdShared.wait(500);
|
|
780
813
|
});
|
|
781
814
|
}
|
|
@@ -852,13 +885,23 @@ function discoverServicesAndCharacteristicsWithRetry(peripheral, deviceId) {
|
|
|
852
885
|
}
|
|
853
886
|
function setupConnectionAndDiscoverServices(peripheral, deviceId, webContents) {
|
|
854
887
|
return index.__awaiter(this, void 0, void 0, function* () {
|
|
888
|
+
setupDisconnectListener(peripheral, deviceId, webContents);
|
|
889
|
+
try {
|
|
890
|
+
return yield discoverServicesAndCharacteristicsWithRetry(peripheral, deviceId);
|
|
891
|
+
}
|
|
892
|
+
catch (initialError) {
|
|
893
|
+
logger === null || logger === void 0 ? void 0 : logger.info('[NobleBLE] Direct service discovery failed, retrying after reconnect', {
|
|
894
|
+
deviceId,
|
|
895
|
+
error: initialError,
|
|
896
|
+
});
|
|
897
|
+
}
|
|
855
898
|
yield forceReconnectPeripheral(peripheral, deviceId);
|
|
856
899
|
setupDisconnectListener(peripheral, deviceId, webContents);
|
|
857
900
|
try {
|
|
858
901
|
return yield discoverServicesAndCharacteristicsWithRetry(peripheral, deviceId);
|
|
859
902
|
}
|
|
860
|
-
catch (
|
|
861
|
-
logger === null || logger === void 0 ? void 0 : logger.error('[NobleBLE] Service discovery failed, attempting fresh scan...',
|
|
903
|
+
catch (reconnectError) {
|
|
904
|
+
logger === null || logger === void 0 ? void 0 : logger.error('[NobleBLE] Service discovery failed after reconnect, attempting fresh scan...', reconnectError);
|
|
862
905
|
return freshScanAndDiscover(deviceId, webContents);
|
|
863
906
|
}
|
|
864
907
|
});
|
|
@@ -931,12 +974,24 @@ function connectDevice(deviceId, webContents) {
|
|
|
931
974
|
return;
|
|
932
975
|
}
|
|
933
976
|
return new Promise((resolve, reject) => {
|
|
977
|
+
let connectionTimedOut = false;
|
|
934
978
|
const timeout = setTimeout(() => {
|
|
979
|
+
connectionTimedOut = true;
|
|
935
980
|
reject(hdShared.ERRORS.TypedError(hdShared.HardwareErrorCode.BleConnectedError, 'Connection timeout'));
|
|
936
|
-
},
|
|
981
|
+
}, NOBLE_BLE_CONNECTION_TIMEOUT_MS);
|
|
937
982
|
const connectedPeripheral = peripheral;
|
|
938
983
|
connectedPeripheral.connect((error) => index.__awaiter(this, void 0, void 0, function* () {
|
|
939
984
|
clearTimeout(timeout);
|
|
985
|
+
if (connectionTimedOut) {
|
|
986
|
+
if (!error) {
|
|
987
|
+
try {
|
|
988
|
+
connectedPeripheral.disconnect(() => undefined);
|
|
989
|
+
}
|
|
990
|
+
catch (_a) {
|
|
991
|
+
}
|
|
992
|
+
}
|
|
993
|
+
return;
|
|
994
|
+
}
|
|
940
995
|
if (error) {
|
|
941
996
|
logger === null || logger === void 0 ? void 0 : logger.error('[NobleBLE] Connection failed:', error);
|
|
942
997
|
reject(hdShared.ERRORS.TypedError(hdShared.HardwareErrorCode.BleConnectedError, error.message));
|
|
@@ -966,17 +1021,20 @@ function disconnectDevice(deviceId) {
|
|
|
966
1021
|
if (!peripheral) {
|
|
967
1022
|
return;
|
|
968
1023
|
}
|
|
969
|
-
|
|
970
|
-
|
|
971
|
-
peripheral.disconnect
|
|
972
|
-
|
|
973
|
-
|
|
974
|
-
|
|
975
|
-
|
|
976
|
-
|
|
977
|
-
|
|
978
|
-
|
|
979
|
-
|
|
1024
|
+
const disconnectEntry = deviceDisconnectListeners.get(deviceId);
|
|
1025
|
+
if (disconnectEntry) {
|
|
1026
|
+
disconnectEntry.peripheral.removeListener('disconnect', disconnectEntry.listener);
|
|
1027
|
+
deviceDisconnectListeners.delete(deviceId);
|
|
1028
|
+
}
|
|
1029
|
+
yield runBleCallbackOperation(callback => peripheral.disconnect(() => callback()), {
|
|
1030
|
+
timeoutMs: BLE_CLEANUP_TIMEOUT,
|
|
1031
|
+
timeoutBehavior: 'resolve',
|
|
1032
|
+
});
|
|
1033
|
+
cleanupDevice(deviceId, undefined, {
|
|
1034
|
+
cleanupConnection: true,
|
|
1035
|
+
sendDisconnectEvent: false,
|
|
1036
|
+
cancelOperations: true,
|
|
1037
|
+
reason: 'manual-disconnect',
|
|
980
1038
|
});
|
|
981
1039
|
});
|
|
982
1040
|
}
|
|
@@ -991,18 +1049,11 @@ function unsubscribeNotifications(deviceId) {
|
|
|
991
1049
|
logger === null || logger === void 0 ? void 0 : logger.info('[NobleBLE] Unsubscribing from notifications for device:', deviceId);
|
|
992
1050
|
subscriptionOperations.set(deviceId, 'unsubscribing');
|
|
993
1051
|
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
|
-
});
|
|
1052
|
+
yield runBleCallbackOperation(callback => notifyCharacteristic.unsubscribe(callback), {
|
|
1053
|
+
timeoutMs: BLE_CLEANUP_TIMEOUT,
|
|
1054
|
+
timeoutBehavior: 'resolve',
|
|
1005
1055
|
});
|
|
1056
|
+
logger === null || logger === void 0 ? void 0 : logger.info('[NobleBLE] Notification unsubscription completed');
|
|
1006
1057
|
notifyCharacteristic.removeAllListeners('data');
|
|
1007
1058
|
notificationCallbacks.delete(deviceId);
|
|
1008
1059
|
subscribedDevices.delete(deviceId);
|
|
@@ -1054,19 +1105,13 @@ function subscribeNotifications(deviceId, callback) {
|
|
|
1054
1105
|
notificationCallbacks.set(deviceId, callback);
|
|
1055
1106
|
function rebuildAppSubscription(deviceId, notifyCharacteristic) {
|
|
1056
1107
|
return index.__awaiter(this, void 0, void 0, function* () {
|
|
1057
|
-
yield
|
|
1058
|
-
|
|
1059
|
-
|
|
1060
|
-
});
|
|
1108
|
+
yield runBleCallbackOperation(callback => notifyCharacteristic.unsubscribe(callback), {
|
|
1109
|
+
timeoutMs: BLE_CLEANUP_TIMEOUT,
|
|
1110
|
+
timeoutBehavior: 'resolve',
|
|
1061
1111
|
});
|
|
1062
|
-
yield
|
|
1063
|
-
|
|
1064
|
-
|
|
1065
|
-
reject(error);
|
|
1066
|
-
return;
|
|
1067
|
-
}
|
|
1068
|
-
resolve();
|
|
1069
|
-
});
|
|
1112
|
+
yield runBleCallbackOperation(callback => notifyCharacteristic.subscribe(callback), {
|
|
1113
|
+
timeoutMs: NOBLE_BLE_CONNECTION_TIMEOUT_MS,
|
|
1114
|
+
timeoutBehavior: 'reject',
|
|
1070
1115
|
});
|
|
1071
1116
|
notifyCharacteristic.on('data', (data) => {
|
|
1072
1117
|
if (!pairedDevices.has(deviceId)) {
|
|
@@ -1087,19 +1132,17 @@ function subscribeNotifications(deviceId, callback) {
|
|
|
1087
1132
|
});
|
|
1088
1133
|
}
|
|
1089
1134
|
function setupNobleBleHandlers(webContents) {
|
|
1090
|
-
console.log('[NobleBLE] Attempting to set up Noble BLE handlers.');
|
|
1091
1135
|
try {
|
|
1092
|
-
console.log('[NobleBLE] NOBLE_VERSION_771');
|
|
1093
1136
|
logger = require('electron-log');
|
|
1094
|
-
console.log('[NobleBLE] electron-log loaded successfully.');
|
|
1095
1137
|
const { ipcMain } = require('electron');
|
|
1096
|
-
console.log('[NobleBLE] electron.ipcMain loaded successfully.');
|
|
1097
1138
|
safeLog(logger, 'info', 'Setting up Noble BLE IPC handlers');
|
|
1098
|
-
console.log(`[NobleBLE] Registering handler for: ${hdShared.EOneKeyBleMessageKeys.NOBLE_BLE_ENUMERATE}`);
|
|
1099
1139
|
ipcMain.handle(hdShared.EOneKeyBleMessageKeys.NOBLE_BLE_ENUMERATE, () => index.__awaiter(this, void 0, void 0, function* () {
|
|
1100
1140
|
try {
|
|
1101
1141
|
const devices = yield enumerateDevices();
|
|
1102
|
-
safeLog(logger, '
|
|
1142
|
+
safeLog(logger, 'debug', 'Enumeration completed', {
|
|
1143
|
+
count: devices.length,
|
|
1144
|
+
devices: devices.map(device => ({ id: device.id, name: device.name })),
|
|
1145
|
+
});
|
|
1103
1146
|
return devices;
|
|
1104
1147
|
}
|
|
1105
1148
|
catch (error) {
|
|
@@ -1124,7 +1167,6 @@ function setupNobleBleHandlers(webContents) {
|
|
|
1124
1167
|
yield disconnectDevice(deviceId);
|
|
1125
1168
|
}));
|
|
1126
1169
|
ipcMain.handle(hdShared.EOneKeyBleMessageKeys.NOBLE_BLE_WRITE, (_event, deviceId, hexData) => index.__awaiter(this, void 0, void 0, function* () {
|
|
1127
|
-
logger === null || logger === void 0 ? void 0 : logger.info('[NobleBLE] IPC WRITE', { deviceId, len: hexData.length });
|
|
1128
1170
|
yield transmitHexDataToDevice(deviceId, hexData);
|
|
1129
1171
|
}));
|
|
1130
1172
|
ipcMain.handle(hdShared.EOneKeyBleMessageKeys.NOBLE_BLE_SUBSCRIBE, (_event, deviceId) => index.__awaiter(this, void 0, void 0, function* () {
|
|
@@ -1169,23 +1211,23 @@ function setupNobleBleHandlers(webContents) {
|
|
|
1169
1211
|
}));
|
|
1170
1212
|
webContents.on('destroyed', () => {
|
|
1171
1213
|
safeLog(logger, 'info', 'Cleaning up Noble BLE handlers');
|
|
1172
|
-
|
|
1173
|
-
|
|
1174
|
-
|
|
1175
|
-
|
|
1176
|
-
|
|
1177
|
-
|
|
1178
|
-
|
|
1179
|
-
|
|
1214
|
+
(() => index.__awaiter(this, void 0, void 0, function* () {
|
|
1215
|
+
const deviceIds = Array.from(connectedDevices.keys());
|
|
1216
|
+
for (const deviceId of deviceIds) {
|
|
1217
|
+
yield unsubscribeNotifications(deviceId).catch(() => undefined);
|
|
1218
|
+
yield disconnectDevice(deviceId).catch(() => undefined);
|
|
1219
|
+
}
|
|
1220
|
+
yield stopScanning().catch(() => undefined);
|
|
1221
|
+
if (noble && persistentStateListener) {
|
|
1222
|
+
noble.removeListener('stateChange', persistentStateListener);
|
|
1223
|
+
persistentStateListener = null;
|
|
1224
|
+
}
|
|
1225
|
+
cleanupNobleListeners();
|
|
1226
|
+
discoveredDevices.clear();
|
|
1227
|
+
safeLog(logger, 'info', 'Noble BLE cleanup completed');
|
|
1228
|
+
}))().catch(error => {
|
|
1229
|
+
safeLog(logger, 'error', 'Noble BLE cleanup failed', error);
|
|
1180
1230
|
});
|
|
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
1231
|
});
|
|
1190
1232
|
safeLog(logger, 'info', 'Noble BLE IPC handlers setup completed');
|
|
1191
1233
|
}
|