@onekeyfe/hd-transport-electron 1.2.2-alpha.8 → 1.2.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/{index-00297050.js → index-474dbbae.js} +33 -1
- package/dist/index.d.ts +24 -1
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +4 -1
- package/dist/{noble-ble-handler-95c5cf0d.js → noble-ble-handler-23c86603.js} +378 -90
- package/dist/noble-ble-handler.d.ts +11 -1
- package/dist/noble-ble-handler.d.ts.map +1 -1
- package/dist/noble-ble-timeouts.d.ts +1 -1
- package/dist/noble-ble-timeouts.d.ts.map +1 -1
- package/dist/types/desktop-api.d.ts +13 -0
- package/dist/types/desktop-api.d.ts.map +1 -1
- package/dist/types/noble-extended.d.ts +2 -0
- package/dist/types/noble-extended.d.ts.map +1 -1
- package/package.json +5 -5
- package/src/__tests__/noble-ble-handler.test.ts +789 -18
- package/src/index.ts +14 -1
- package/src/noble-ble-handler.ts +445 -113
- package/src/noble-ble-timeouts.ts +1 -1
- package/src/types/desktop-api.ts +44 -0
- package/src/types/noble-extended.ts +2 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
'use strict';
|
|
2
2
|
|
|
3
|
-
var index = require('./index-
|
|
3
|
+
var index = require('./index-474dbbae.js');
|
|
4
4
|
var hdShared = require('@onekeyfe/hd-shared');
|
|
5
5
|
var pRetry = require('p-retry');
|
|
6
6
|
|
|
@@ -96,10 +96,66 @@ function softRefreshSubscription(params) {
|
|
|
96
96
|
}
|
|
97
97
|
|
|
98
98
|
const NOBLE_BLE_TARGETED_SCAN_TIMEOUT_MS = 5000;
|
|
99
|
-
const
|
|
99
|
+
const NOBLE_BLE_SUBSCRIBE_TIMEOUT_MS = 10000;
|
|
100
100
|
|
|
101
101
|
let noble = null;
|
|
102
102
|
let logger = null;
|
|
103
|
+
let disposing = false;
|
|
104
|
+
let nativeReleased = false;
|
|
105
|
+
let disposePromise;
|
|
106
|
+
let windowCleanup;
|
|
107
|
+
let removeIpcHandlers;
|
|
108
|
+
const pendingCancellations = new Set();
|
|
109
|
+
const pendingEnumerations = new Set();
|
|
110
|
+
const nativeConnections = new Set();
|
|
111
|
+
function trackNativeConnection(operation, cancel) {
|
|
112
|
+
const connection = {
|
|
113
|
+
cancel,
|
|
114
|
+
settled: operation.then(() => undefined, () => undefined),
|
|
115
|
+
};
|
|
116
|
+
nativeConnections.add(connection);
|
|
117
|
+
connection.settled = connection.settled.finally(() => nativeConnections.delete(connection));
|
|
118
|
+
}
|
|
119
|
+
function assertBleActive() {
|
|
120
|
+
if (disposing) {
|
|
121
|
+
throw hdShared.ERRORS.TypedError(hdShared.HardwareErrorCode.BleDeviceDisconnected, 'Noble BLE is shutting down');
|
|
122
|
+
}
|
|
123
|
+
}
|
|
124
|
+
function createNobleBleConnectionError(error, messagePrefix = '') {
|
|
125
|
+
const errorMessage = error.message;
|
|
126
|
+
const isInvalidMacOsBond = (error.nativeErrorCode === 14 && error.nativeErrorDomain === 'CBErrorDomain') ||
|
|
127
|
+
(error.nativeErrorCode === 15 && error.nativeErrorDomain === 'CBATTErrorDomain');
|
|
128
|
+
if (isInvalidMacOsBond) {
|
|
129
|
+
const nativeErrorMessage = `${messagePrefix}${errorMessage}`;
|
|
130
|
+
return hdShared.ERRORS.TypedError(hdShared.HardwareErrorCode.BleBondInvalid, `${hdShared.HardwareErrorCodeMessage[hdShared.HardwareErrorCode.BleBondInvalid]} (${nativeErrorMessage})`, {
|
|
131
|
+
nativeErrorMessage,
|
|
132
|
+
});
|
|
133
|
+
}
|
|
134
|
+
return hdShared.ERRORS.TypedError(hdShared.HardwareErrorCode.BleConnectedError, `${messagePrefix}${errorMessage}`);
|
|
135
|
+
}
|
|
136
|
+
function createNobleBleIpcErrorResponse(error) {
|
|
137
|
+
const candidate = error;
|
|
138
|
+
const errorCode = typeof (candidate === null || candidate === void 0 ? void 0 : candidate.errorCode) === 'number' ? candidate.errorCode : hdShared.HardwareErrorCode.UnknownError;
|
|
139
|
+
const message = typeof (candidate === null || candidate === void 0 ? void 0 : candidate.message) === 'string' ? candidate.message : String(error !== null && error !== void 0 ? error : 'Unknown error');
|
|
140
|
+
const name = typeof (candidate === null || candidate === void 0 ? void 0 : candidate.name) === 'string' ? candidate.name : 'Error';
|
|
141
|
+
let params;
|
|
142
|
+
if ((candidate === null || candidate === void 0 ? void 0 : candidate.params) !== undefined) {
|
|
143
|
+
try {
|
|
144
|
+
const serializedParams = JSON.stringify(candidate.params);
|
|
145
|
+
params = serializedParams === undefined ? undefined : JSON.parse(serializedParams);
|
|
146
|
+
}
|
|
147
|
+
catch (_a) {
|
|
148
|
+
params = undefined;
|
|
149
|
+
}
|
|
150
|
+
}
|
|
151
|
+
return {
|
|
152
|
+
type: 'NobleBleIpcError',
|
|
153
|
+
success: false,
|
|
154
|
+
error: Object.assign({ name,
|
|
155
|
+
message,
|
|
156
|
+
errorCode }, (params !== undefined ? { params } : {})),
|
|
157
|
+
};
|
|
158
|
+
}
|
|
103
159
|
const bluetoothState = {
|
|
104
160
|
available: false,
|
|
105
161
|
unsupported: false,
|
|
@@ -109,6 +165,86 @@ let persistentStateListener = null;
|
|
|
109
165
|
let persistentDiscoverListener = null;
|
|
110
166
|
const discoveredDevices = new Map();
|
|
111
167
|
const connectedDevices = new Map();
|
|
168
|
+
const connectingDevices = new Map();
|
|
169
|
+
let nextConnectionGeneration = 0;
|
|
170
|
+
function connectPeripheralWithCancellation(peripheral, deviceId, messagePrefix = '') {
|
|
171
|
+
assertBleActive();
|
|
172
|
+
return new Promise((resolve, reject) => {
|
|
173
|
+
var _a;
|
|
174
|
+
const generation = ++nextConnectionGeneration;
|
|
175
|
+
let settled = false;
|
|
176
|
+
const settle = (settler) => {
|
|
177
|
+
var _a;
|
|
178
|
+
if (settled)
|
|
179
|
+
return false;
|
|
180
|
+
settled = true;
|
|
181
|
+
if (((_a = connectingDevices.get(deviceId)) === null || _a === void 0 ? void 0 : _a.generation) === generation) {
|
|
182
|
+
connectingDevices.delete(deviceId);
|
|
183
|
+
}
|
|
184
|
+
settler();
|
|
185
|
+
return true;
|
|
186
|
+
};
|
|
187
|
+
const pendingConnection = {
|
|
188
|
+
peripheral,
|
|
189
|
+
generation,
|
|
190
|
+
cancel: error => {
|
|
191
|
+
settle(() => reject(error));
|
|
192
|
+
},
|
|
193
|
+
};
|
|
194
|
+
(_a = connectingDevices
|
|
195
|
+
.get(deviceId)) === null || _a === void 0 ? void 0 : _a.cancel(hdShared.ERRORS.TypedError(hdShared.HardwareErrorCode.BleDeviceDisconnected, `Device ${deviceId} connect attempt was superseded`));
|
|
196
|
+
connectingDevices.set(deviceId, pendingConnection);
|
|
197
|
+
let completeNative;
|
|
198
|
+
trackNativeConnection(new Promise(resolve => {
|
|
199
|
+
completeNative = resolve;
|
|
200
|
+
}), () => {
|
|
201
|
+
var _a;
|
|
202
|
+
if (typeof peripheral.cancelConnect === 'function')
|
|
203
|
+
peripheral.cancelConnect();
|
|
204
|
+
else
|
|
205
|
+
(_a = noble === null || noble === void 0 ? void 0 : noble.cancelConnect) === null || _a === void 0 ? void 0 : _a.call(noble, deviceId);
|
|
206
|
+
});
|
|
207
|
+
const onConnect = (error) => {
|
|
208
|
+
if (nativeReleased) {
|
|
209
|
+
completeNative();
|
|
210
|
+
return;
|
|
211
|
+
}
|
|
212
|
+
if (error) {
|
|
213
|
+
settle(() => reject(createNobleBleConnectionError(error, messagePrefix)));
|
|
214
|
+
completeNative();
|
|
215
|
+
return;
|
|
216
|
+
}
|
|
217
|
+
if (!settle(() => {
|
|
218
|
+
connectedDevices.set(deviceId, peripheral);
|
|
219
|
+
resolve();
|
|
220
|
+
})) {
|
|
221
|
+
const activeConnection = connectingDevices.get(deviceId);
|
|
222
|
+
if (!activeConnection || activeConnection.peripheral !== peripheral) {
|
|
223
|
+
try {
|
|
224
|
+
peripheral.removeAllListeners('disconnect');
|
|
225
|
+
runBleCallbackOperation(callback => peripheral.disconnect(() => callback()), {
|
|
226
|
+
timeoutMs: BLE_DISCONNECT_CONFIRM_TIMEOUT_MS,
|
|
227
|
+
timeoutBehavior: 'resolve',
|
|
228
|
+
})
|
|
229
|
+
.catch(() => undefined)
|
|
230
|
+
.finally(completeNative);
|
|
231
|
+
return;
|
|
232
|
+
}
|
|
233
|
+
catch (_a) {
|
|
234
|
+
}
|
|
235
|
+
}
|
|
236
|
+
}
|
|
237
|
+
completeNative();
|
|
238
|
+
};
|
|
239
|
+
try {
|
|
240
|
+
peripheral.connect(onConnect);
|
|
241
|
+
}
|
|
242
|
+
catch (error) {
|
|
243
|
+
completeNative();
|
|
244
|
+
settle(() => reject(error));
|
|
245
|
+
}
|
|
246
|
+
});
|
|
247
|
+
}
|
|
112
248
|
const pairedDevices = new Set();
|
|
113
249
|
const deviceCharacteristics = new Map();
|
|
114
250
|
const notificationCallbacks = new Map();
|
|
@@ -247,6 +383,7 @@ function updateBluetoothState(state) {
|
|
|
247
383
|
}
|
|
248
384
|
function initializeNoble() {
|
|
249
385
|
return index.__awaiter(this, void 0, void 0, function* () {
|
|
386
|
+
assertBleActive();
|
|
250
387
|
if (noble)
|
|
251
388
|
return;
|
|
252
389
|
try {
|
|
@@ -263,9 +400,11 @@ function initializeNoble() {
|
|
|
263
400
|
return;
|
|
264
401
|
}
|
|
265
402
|
const timeout = setTimeout(() => {
|
|
403
|
+
cleanup();
|
|
266
404
|
reject(hdShared.ERRORS.TypedError(hdShared.HardwareErrorCode.RuntimeError, 'Bluetooth initialization timeout'));
|
|
267
405
|
}, BLUETOOTH_INIT_TIMEOUT);
|
|
268
406
|
const cleanup = () => {
|
|
407
|
+
pendingCancellations.delete(cancel);
|
|
269
408
|
clearTimeout(timeout);
|
|
270
409
|
if (noble) {
|
|
271
410
|
noble.removeListener('stateChange', onStateChange);
|
|
@@ -290,8 +429,14 @@ function initializeNoble() {
|
|
|
290
429
|
reject(hdShared.ERRORS.TypedError(hdShared.HardwareErrorCode.BlePermissionError));
|
|
291
430
|
}
|
|
292
431
|
};
|
|
432
|
+
const cancel = () => {
|
|
433
|
+
cleanup();
|
|
434
|
+
reject(hdShared.ERRORS.TypedError(hdShared.HardwareErrorCode.BleDeviceDisconnected, 'Noble BLE is shutting down'));
|
|
435
|
+
};
|
|
436
|
+
pendingCancellations.add(cancel);
|
|
293
437
|
noble.on('stateChange', onStateChange);
|
|
294
438
|
});
|
|
439
|
+
assertBleActive();
|
|
295
440
|
if (!persistentDiscoverListener) {
|
|
296
441
|
persistentDiscoverListener = (peripheral) => {
|
|
297
442
|
handleDeviceDiscovered(peripheral);
|
|
@@ -338,6 +483,8 @@ function broadcastToAllWebContents(channel, payload) {
|
|
|
338
483
|
}
|
|
339
484
|
function armIdleDisconnect(deviceId, ms = BLE_IDLE_DISCONNECT_MS, reason = 'idle') {
|
|
340
485
|
clearIdleDisconnect(deviceId);
|
|
486
|
+
if (disposing)
|
|
487
|
+
return;
|
|
341
488
|
idleDisconnectTimers.set(deviceId, setTimeout(() => {
|
|
342
489
|
var _a;
|
|
343
490
|
idleDisconnectTimers.delete(deviceId);
|
|
@@ -373,7 +520,7 @@ function armIdleDisconnect(deviceId, ms = BLE_IDLE_DISCONNECT_MS, reason = 'idle
|
|
|
373
520
|
}, ms));
|
|
374
521
|
}
|
|
375
522
|
function cleanupDevice(deviceId, webContents, options = {}) {
|
|
376
|
-
var _a;
|
|
523
|
+
var _a, _b;
|
|
377
524
|
const { cleanupConnection = true, cleanupDiscoveredCache = false, sendDisconnectEvent = false, cancelOperations = true, reason = 'unknown', disconnectReason = hdShared.EBleDisconnectReason.DeviceDisconnected, } = options;
|
|
378
525
|
logger === null || logger === void 0 ? void 0 : logger.info('[NobleBLE] Starting device cleanup', {
|
|
379
526
|
deviceId,
|
|
@@ -387,6 +534,8 @@ function cleanupDevice(deviceId, webContents, options = {}) {
|
|
|
387
534
|
const peripheral = connectedDevices.get(deviceId);
|
|
388
535
|
const deviceName = ((_a = peripheral === null || peripheral === void 0 ? void 0 : peripheral.advertisement) === null || _a === void 0 ? void 0 : _a.localName) || 'Unknown Device';
|
|
389
536
|
if (cleanupConnection) {
|
|
537
|
+
(_b = connectingDevices
|
|
538
|
+
.get(deviceId)) === null || _b === void 0 ? void 0 : _b.cancel(hdShared.ERRORS.TypedError(hdShared.HardwareErrorCode.BleDeviceDisconnected, `Device ${deviceId} disconnected while connecting`));
|
|
390
539
|
const disconnectEntry = deviceDisconnectListeners.get(deviceId);
|
|
391
540
|
if (disconnectEntry) {
|
|
392
541
|
disconnectEntry.peripheral.removeListener('disconnect', disconnectEntry.listener);
|
|
@@ -465,6 +614,7 @@ function setupMtuListener(peripheral, deviceId, webContents) {
|
|
|
465
614
|
}
|
|
466
615
|
function writeCharacteristicWithoutResponse(deviceId, writeCharacteristic, buffer) {
|
|
467
616
|
return index.__awaiter(this, void 0, void 0, function* () {
|
|
617
|
+
assertBleActive();
|
|
468
618
|
return new Promise((resolve, reject) => {
|
|
469
619
|
writeCharacteristic.write(buffer, true, (error) => {
|
|
470
620
|
if (error) {
|
|
@@ -667,6 +817,7 @@ function waitForNobleScanStop(nobleInstance) {
|
|
|
667
817
|
}
|
|
668
818
|
function performTargetedScan(targetDeviceId, timeoutMs = NOBLE_BLE_TARGETED_SCAN_TIMEOUT_MS) {
|
|
669
819
|
return index.__awaiter(this, void 0, void 0, function* () {
|
|
820
|
+
assertBleActive();
|
|
670
821
|
if (!noble) {
|
|
671
822
|
throw hdShared.ERRORS.TypedError(hdShared.HardwareErrorCode.RuntimeError, 'Noble not available');
|
|
672
823
|
}
|
|
@@ -678,6 +829,7 @@ function performTargetedScan(targetDeviceId, timeoutMs = NOBLE_BLE_TARGETED_SCAN
|
|
|
678
829
|
if (settled)
|
|
679
830
|
return;
|
|
680
831
|
settled = true;
|
|
832
|
+
pendingCancellations.delete(cancel);
|
|
681
833
|
if (timeoutId)
|
|
682
834
|
clearTimeout(timeoutId);
|
|
683
835
|
nobleInstance.removeListener('discover', onDiscover);
|
|
@@ -687,6 +839,7 @@ function performTargetedScan(targetDeviceId, timeoutMs = NOBLE_BLE_TARGETED_SCAN
|
|
|
687
839
|
reject(hdShared.ERRORS.TypedError(hdShared.HardwareErrorCode.BleScanError, error.message));
|
|
688
840
|
return;
|
|
689
841
|
}
|
|
842
|
+
assertBleActive();
|
|
690
843
|
if (peripheral) {
|
|
691
844
|
discoveredDevices.set(peripheral.id, peripheral);
|
|
692
845
|
}
|
|
@@ -706,6 +859,10 @@ function performTargetedScan(targetDeviceId, timeoutMs = NOBLE_BLE_TARGETED_SCAN
|
|
|
706
859
|
logger === null || logger === void 0 ? void 0 : logger.info('[NobleBLE] Targeted scan timeout for device:', targetDeviceId);
|
|
707
860
|
finish(null).catch(reject);
|
|
708
861
|
}, timeoutMs);
|
|
862
|
+
const cancel = () => {
|
|
863
|
+
finish(null, new Error('Noble BLE is shutting down')).catch(reject);
|
|
864
|
+
};
|
|
865
|
+
pendingCancellations.add(cancel);
|
|
709
866
|
nobleInstance.on('discover', onDiscover);
|
|
710
867
|
nobleInstance.startScanning([], true, (error) => {
|
|
711
868
|
if (error) {
|
|
@@ -717,7 +874,7 @@ function performTargetedScan(targetDeviceId, timeoutMs = NOBLE_BLE_TARGETED_SCAN
|
|
|
717
874
|
});
|
|
718
875
|
});
|
|
719
876
|
}
|
|
720
|
-
function enumerateDevices() {
|
|
877
|
+
function enumerateDevices(isWindowDestroyed) {
|
|
721
878
|
return index.__awaiter(this, void 0, void 0, function* () {
|
|
722
879
|
if (!noble) {
|
|
723
880
|
yield initializeNoble();
|
|
@@ -725,19 +882,30 @@ function enumerateDevices() {
|
|
|
725
882
|
if (!noble) {
|
|
726
883
|
throw hdShared.ERRORS.TypedError(hdShared.HardwareErrorCode.RuntimeError, 'Noble not available');
|
|
727
884
|
}
|
|
885
|
+
assertBleActive();
|
|
886
|
+
if (isWindowDestroyed())
|
|
887
|
+
return [];
|
|
728
888
|
const nobleInstance = noble;
|
|
729
889
|
logger === null || logger === void 0 ? void 0 : logger.info('[NobleBLE] Starting device enumeration');
|
|
730
|
-
discoveredDevices.clear();
|
|
731
890
|
ensureDiscoverListener();
|
|
732
891
|
return new Promise((resolve, reject) => {
|
|
733
892
|
const devices = [];
|
|
893
|
+
let settled = false;
|
|
734
894
|
let intervalId;
|
|
735
|
-
|
|
736
|
-
|
|
737
|
-
if (
|
|
738
|
-
|
|
739
|
-
|
|
740
|
-
|
|
895
|
+
let cleanupPromise;
|
|
896
|
+
const cleanup = () => {
|
|
897
|
+
if (!cleanupPromise) {
|
|
898
|
+
settled = true;
|
|
899
|
+
pendingCancellations.delete(cancel);
|
|
900
|
+
clearTimeout(timeoutId);
|
|
901
|
+
if (intervalId)
|
|
902
|
+
clearInterval(intervalId);
|
|
903
|
+
cleanupPromise = waitForNobleScanStop(nobleInstance).finally(() => {
|
|
904
|
+
pendingEnumerations.delete(cancel);
|
|
905
|
+
});
|
|
906
|
+
}
|
|
907
|
+
return cleanupPromise;
|
|
908
|
+
};
|
|
741
909
|
const pushDevice = (peripheral, id) => {
|
|
742
910
|
var _a;
|
|
743
911
|
if (devices.some(d => d.id === id))
|
|
@@ -754,13 +922,20 @@ function enumerateDevices() {
|
|
|
754
922
|
connectedDevices.forEach(pushDevice);
|
|
755
923
|
};
|
|
756
924
|
const timeoutId = setTimeout(() => index.__awaiter(this, void 0, void 0, function* () {
|
|
925
|
+
if (settled)
|
|
926
|
+
return;
|
|
757
927
|
checkDevices();
|
|
758
928
|
yield cleanup();
|
|
759
929
|
logger === null || logger === void 0 ? void 0 : logger.info('[NobleBLE] Scan completed, found devices:', devices.length);
|
|
760
930
|
resolve(devices);
|
|
761
931
|
}), DEVICE_SCAN_TIMEOUT);
|
|
932
|
+
const cancel = () => cleanup().then(() => resolve([]), reject);
|
|
933
|
+
pendingCancellations.add(cancel);
|
|
934
|
+
pendingEnumerations.add(cancel);
|
|
762
935
|
logger === null || logger === void 0 ? void 0 : logger.info('[NobleBLE] Scanning for OneKey BLE devices');
|
|
763
936
|
nobleInstance.startScanning([], true, (error) => index.__awaiter(this, void 0, void 0, function* () {
|
|
937
|
+
if (settled)
|
|
938
|
+
return;
|
|
764
939
|
if (error) {
|
|
765
940
|
yield cleanup();
|
|
766
941
|
logger === null || logger === void 0 ? void 0 : logger.error('[NobleBLE] Failed to start scanning:', error);
|
|
@@ -775,7 +950,7 @@ function enumerateDevices() {
|
|
|
775
950
|
}
|
|
776
951
|
function stopScanning() {
|
|
777
952
|
return index.__awaiter(this, void 0, void 0, function* () {
|
|
778
|
-
if (!noble)
|
|
953
|
+
if (!noble || nativeReleased)
|
|
779
954
|
return;
|
|
780
955
|
const nobleInstance = noble;
|
|
781
956
|
yield waitForNobleScanStop(nobleInstance);
|
|
@@ -819,13 +994,16 @@ function getDevice(deviceId) {
|
|
|
819
994
|
}
|
|
820
995
|
function discoverServicesAndCharacteristics(peripheral) {
|
|
821
996
|
return index.__awaiter(this, void 0, void 0, function* () {
|
|
997
|
+
assertBleActive();
|
|
822
998
|
let timeoutId;
|
|
823
999
|
let onDisconnect;
|
|
824
1000
|
const cleanup = () => {
|
|
825
1001
|
if (timeoutId)
|
|
826
1002
|
clearTimeout(timeoutId);
|
|
827
|
-
if (onDisconnect)
|
|
1003
|
+
if (onDisconnect) {
|
|
828
1004
|
peripheral.removeListener('disconnect', onDisconnect);
|
|
1005
|
+
pendingCancellations.delete(onDisconnect);
|
|
1006
|
+
}
|
|
829
1007
|
};
|
|
830
1008
|
const timeoutPromise = new Promise((_, reject) => {
|
|
831
1009
|
timeoutId = setTimeout(() => {
|
|
@@ -838,6 +1016,7 @@ function discoverServicesAndCharacteristics(peripheral) {
|
|
|
838
1016
|
logger === null || logger === void 0 ? void 0 : logger.error('[NobleBLE] Device disconnected during service discovery');
|
|
839
1017
|
reject(hdShared.ERRORS.TypedError(hdShared.HardwareErrorCode.BleServiceNotFound, 'Device disconnected during service discovery'));
|
|
840
1018
|
};
|
|
1019
|
+
pendingCancellations.add(onDisconnect);
|
|
841
1020
|
peripheral.once('disconnect', onDisconnect);
|
|
842
1021
|
});
|
|
843
1022
|
const discoveryPromise = (() => index.__awaiter(this, void 0, void 0, function* () {
|
|
@@ -852,6 +1031,7 @@ function discoverServicesAndCharacteristics(peripheral) {
|
|
|
852
1031
|
}
|
|
853
1032
|
});
|
|
854
1033
|
});
|
|
1034
|
+
assertBleActive();
|
|
855
1035
|
if (!services || services.length === 0) {
|
|
856
1036
|
throw hdShared.ERRORS.TypedError(hdShared.HardwareErrorCode.BleServiceNotFound, 'No OneKey services found');
|
|
857
1037
|
}
|
|
@@ -924,12 +1104,8 @@ function forceReconnectPeripheral(peripheral, deviceId) {
|
|
|
924
1104
|
callback();
|
|
925
1105
|
}), { timeoutMs: BLE_CLEANUP_TIMEOUT, timeoutBehavior: 'resolve' });
|
|
926
1106
|
}
|
|
927
|
-
yield
|
|
928
|
-
timeoutMs: NOBLE_BLE_CONNECTION_TIMEOUT_MS,
|
|
929
|
-
timeoutBehavior: 'reject',
|
|
930
|
-
});
|
|
1107
|
+
yield connectPeripheralWithCancellation(peripheral, deviceId);
|
|
931
1108
|
logger === null || logger === void 0 ? void 0 : logger.info('[NobleBLE] Force reconnect successful');
|
|
932
|
-
connectedDevices.set(deviceId, peripheral);
|
|
933
1109
|
yield hdShared.wait(500);
|
|
934
1110
|
});
|
|
935
1111
|
}
|
|
@@ -946,17 +1122,7 @@ function freshScanAndDiscover(deviceId, webContents) {
|
|
|
946
1122
|
throw hdShared.ERRORS.TypedError(hdShared.HardwareErrorCode.DeviceNotFound, `Device ${deviceId} not found in fresh scan`);
|
|
947
1123
|
}
|
|
948
1124
|
discoveredDevices.set(deviceId, freshPeripheral);
|
|
949
|
-
yield
|
|
950
|
-
freshPeripheral.connect((error) => {
|
|
951
|
-
if (error) {
|
|
952
|
-
reject(hdShared.ERRORS.TypedError(hdShared.HardwareErrorCode.BleConnectedError, `Fresh peripheral connection failed: ${error.message}`));
|
|
953
|
-
}
|
|
954
|
-
else {
|
|
955
|
-
connectedDevices.set(deviceId, freshPeripheral);
|
|
956
|
-
resolve();
|
|
957
|
-
}
|
|
958
|
-
});
|
|
959
|
-
});
|
|
1125
|
+
yield connectPeripheralWithCancellation(freshPeripheral, deviceId, 'Fresh peripheral connection failed: ');
|
|
960
1126
|
setupDisconnectListener(freshPeripheral, deviceId, webContents);
|
|
961
1127
|
yield hdShared.wait(500);
|
|
962
1128
|
logger === null || logger === void 0 ? void 0 : logger.info('[NobleBLE] Attempting service discovery with fresh peripheral');
|
|
@@ -995,6 +1161,7 @@ function discoverServicesAndCharacteristicsWithRetry(peripheral, deviceId) {
|
|
|
995
1161
|
minTimeout: 500,
|
|
996
1162
|
maxTimeout: 3000,
|
|
997
1163
|
onFailedAttempt: error => {
|
|
1164
|
+
assertBleActive();
|
|
998
1165
|
logger === null || logger === void 0 ? void 0 : logger.error(`[NobleBLE] Service discovery attempt ${error.attemptNumber} failed:`, {
|
|
999
1166
|
message: error.message,
|
|
1000
1167
|
retriesLeft: error.retriesLeft,
|
|
@@ -1010,8 +1177,13 @@ function setupConnectionAndDiscoverServices(peripheral, deviceId, webContents) {
|
|
|
1010
1177
|
yield forceReconnectPeripheral(peripheral, deviceId);
|
|
1011
1178
|
}
|
|
1012
1179
|
catch (resetError) {
|
|
1180
|
+
if (hdShared.isBleStaleBondHardwareError(resetError) ||
|
|
1181
|
+
(resetError === null || resetError === void 0 ? void 0 : resetError.errorCode) === hdShared.HardwareErrorCode.BleDeviceDisconnected) {
|
|
1182
|
+
throw resetError;
|
|
1183
|
+
}
|
|
1013
1184
|
logger === null || logger === void 0 ? void 0 : logger.error('[NobleBLE] Connection reset before discovery failed, continuing', resetError);
|
|
1014
1185
|
}
|
|
1186
|
+
assertBleActive();
|
|
1015
1187
|
setupDisconnectListener(peripheral, deviceId, webContents);
|
|
1016
1188
|
try {
|
|
1017
1189
|
return yield discoverServicesAndCharacteristicsWithRetry(peripheral, deviceId);
|
|
@@ -1034,36 +1206,46 @@ const directConnectCooldownUntil = new Map();
|
|
|
1034
1206
|
function tryDirectConnectById(deviceId) {
|
|
1035
1207
|
var _a;
|
|
1036
1208
|
return index.__awaiter(this, void 0, void 0, function* () {
|
|
1209
|
+
assertBleActive();
|
|
1037
1210
|
const nobleInstance = noble;
|
|
1038
1211
|
if (!(nobleInstance === null || nobleInstance === void 0 ? void 0 : nobleInstance.connectAsync))
|
|
1039
1212
|
return undefined;
|
|
1040
1213
|
const cooldownUntil = (_a = directConnectCooldownUntil.get(deviceId)) !== null && _a !== void 0 ? _a : 0;
|
|
1041
1214
|
if (Date.now() < cooldownUntil)
|
|
1042
1215
|
return undefined;
|
|
1216
|
+
let timer;
|
|
1217
|
+
let cancel;
|
|
1218
|
+
let abandoned = false;
|
|
1043
1219
|
try {
|
|
1044
1220
|
const directPromise = nobleInstance.connectAsync(deviceId);
|
|
1221
|
+
trackNativeConnection(directPromise.then((late) => index.__awaiter(this, void 0, void 0, function* () {
|
|
1222
|
+
if ((!abandoned && !disposing) || nativeReleased)
|
|
1223
|
+
return;
|
|
1224
|
+
const peripheral = late !== null && late !== void 0 ? late : discoveredDevices.get(deviceId);
|
|
1225
|
+
if ((peripheral === null || peripheral === void 0 ? void 0 : peripheral.state) === 'connected' && !connectedDevices.has(deviceId)) {
|
|
1226
|
+
peripheral.removeAllListeners('disconnect');
|
|
1227
|
+
yield runBleCallbackOperation(callback => peripheral.disconnect(() => callback()), {
|
|
1228
|
+
timeoutMs: BLE_DISCONNECT_CONFIRM_TIMEOUT_MS,
|
|
1229
|
+
timeoutBehavior: 'resolve',
|
|
1230
|
+
});
|
|
1231
|
+
}
|
|
1232
|
+
})), () => { var _a; return (_a = nobleInstance.cancelConnect) === null || _a === void 0 ? void 0 : _a.call(nobleInstance, deviceId); });
|
|
1045
1233
|
const raced = yield Promise.race([
|
|
1046
1234
|
directPromise,
|
|
1047
1235
|
new Promise(resolve => {
|
|
1048
|
-
|
|
1236
|
+
cancel = () => {
|
|
1237
|
+
abandoned = true;
|
|
1238
|
+
resolve('timeout');
|
|
1239
|
+
};
|
|
1240
|
+
pendingCancellations.add(cancel);
|
|
1241
|
+
timer = setTimeout(cancel, DIRECT_CONNECT_TIMEOUT_MS);
|
|
1049
1242
|
}),
|
|
1050
1243
|
]);
|
|
1051
|
-
if (raced === 'timeout') {
|
|
1244
|
+
if (raced === 'timeout' || disposing) {
|
|
1052
1245
|
directConnectCooldownUntil.set(deviceId, Date.now() + DIRECT_CONNECT_COOLDOWN_MS);
|
|
1053
1246
|
logger === null || logger === void 0 ? void 0 : logger.info('[NobleBLE] Direct connect-by-id timed out, falling back to scan', {
|
|
1054
1247
|
deviceId,
|
|
1055
1248
|
});
|
|
1056
|
-
directPromise
|
|
1057
|
-
.then(late => {
|
|
1058
|
-
const latePeripheral = late !== null && late !== void 0 ? late : discoveredDevices.get(deviceId);
|
|
1059
|
-
if (latePeripheral &&
|
|
1060
|
-
latePeripheral.state === 'connected' &&
|
|
1061
|
-
!connectedDevices.has(deviceId)) {
|
|
1062
|
-
latePeripheral.removeAllListeners('disconnect');
|
|
1063
|
-
latePeripheral.disconnect(() => undefined);
|
|
1064
|
-
}
|
|
1065
|
-
})
|
|
1066
|
-
.catch(() => undefined);
|
|
1067
1249
|
return undefined;
|
|
1068
1250
|
}
|
|
1069
1251
|
const peripheral = raced !== null && raced !== void 0 ? raced : discoveredDevices.get(deviceId);
|
|
@@ -1080,6 +1262,11 @@ function tryDirectConnectById(deviceId) {
|
|
|
1080
1262
|
});
|
|
1081
1263
|
return undefined;
|
|
1082
1264
|
}
|
|
1265
|
+
finally {
|
|
1266
|
+
clearTimeout(timer);
|
|
1267
|
+
if (cancel)
|
|
1268
|
+
pendingCancellations.delete(cancel);
|
|
1269
|
+
}
|
|
1083
1270
|
});
|
|
1084
1271
|
}
|
|
1085
1272
|
function connectDevice(deviceId, webContents) {
|
|
@@ -1093,7 +1280,10 @@ function connectDevice(deviceId, webContents) {
|
|
|
1093
1280
|
totalDiscovered: discoveredDevices.size,
|
|
1094
1281
|
totalConnected: connectedDevices.size,
|
|
1095
1282
|
});
|
|
1096
|
-
let peripheral = (_a =
|
|
1283
|
+
let peripheral = (_a = connectedDevices.get(deviceId)) !== null && _a !== void 0 ? _a : discoveredDevices.get(deviceId);
|
|
1284
|
+
if ((peripheral === null || peripheral === void 0 ? void 0 : peripheral.state) !== 'connected') {
|
|
1285
|
+
peripheral = undefined;
|
|
1286
|
+
}
|
|
1097
1287
|
if (!peripheral) {
|
|
1098
1288
|
if (!noble) {
|
|
1099
1289
|
yield initializeNoble();
|
|
@@ -1132,6 +1322,7 @@ function connectDevice(deviceId, webContents) {
|
|
|
1132
1322
|
peripheral = byIdFirst ? yield scanForPeripheral() : yield connectById();
|
|
1133
1323
|
}
|
|
1134
1324
|
}
|
|
1325
|
+
assertBleActive();
|
|
1135
1326
|
if (!peripheral) {
|
|
1136
1327
|
throw hdShared.ERRORS.TypedError(hdShared.HardwareErrorCode.DeviceNotFound, `Device ${deviceId} not found`);
|
|
1137
1328
|
}
|
|
@@ -1142,6 +1333,7 @@ function connectDevice(deviceId, webContents) {
|
|
|
1142
1333
|
if (!connectedDevices.has(deviceId)) {
|
|
1143
1334
|
connectedDevices.set(deviceId, peripheral);
|
|
1144
1335
|
}
|
|
1336
|
+
assertBleActive();
|
|
1145
1337
|
setupDisconnectListener(peripheral, deviceId, webContents);
|
|
1146
1338
|
if (deviceCharacteristics.has(deviceId)) {
|
|
1147
1339
|
logger === null || logger === void 0 ? void 0 : logger.info('[NobleBLE] Device characteristics already available');
|
|
@@ -1166,6 +1358,7 @@ function connectDevice(deviceId, webContents) {
|
|
|
1166
1358
|
}
|
|
1167
1359
|
try {
|
|
1168
1360
|
const characteristics = yield setupConnectionAndDiscoverServices(peripheral, deviceId, webContents);
|
|
1361
|
+
assertBleActive();
|
|
1169
1362
|
deviceCharacteristics.set(deviceId, characteristics);
|
|
1170
1363
|
logger === null || logger === void 0 ? void 0 : logger.info('[NobleBLE] Device ready for communication:', deviceId);
|
|
1171
1364
|
}
|
|
@@ -1176,54 +1369,33 @@ function connectDevice(deviceId, webContents) {
|
|
|
1176
1369
|
}
|
|
1177
1370
|
return;
|
|
1178
1371
|
}
|
|
1179
|
-
|
|
1180
|
-
|
|
1181
|
-
|
|
1182
|
-
|
|
1183
|
-
|
|
1184
|
-
|
|
1185
|
-
|
|
1186
|
-
|
|
1187
|
-
|
|
1188
|
-
|
|
1189
|
-
|
|
1190
|
-
|
|
1191
|
-
|
|
1192
|
-
|
|
1193
|
-
catch (_a) {
|
|
1194
|
-
}
|
|
1195
|
-
}
|
|
1196
|
-
return;
|
|
1197
|
-
}
|
|
1198
|
-
if (error) {
|
|
1199
|
-
logger === null || logger === void 0 ? void 0 : logger.error('[NobleBLE] Connection failed:', error);
|
|
1200
|
-
reject(hdShared.ERRORS.TypedError(hdShared.HardwareErrorCode.BleConnectedError, error.message));
|
|
1201
|
-
return;
|
|
1202
|
-
}
|
|
1203
|
-
logger === null || logger === void 0 ? void 0 : logger.info('[NobleBLE] Connected to device:', deviceId);
|
|
1204
|
-
connectedDevices.set(deviceId, connectedPeripheral);
|
|
1205
|
-
try {
|
|
1206
|
-
const characteristics = yield setupConnectionAndDiscoverServices(connectedPeripheral, deviceId, webContents);
|
|
1207
|
-
deviceCharacteristics.set(deviceId, characteristics);
|
|
1208
|
-
logger === null || logger === void 0 ? void 0 : logger.info('[NobleBLE] Device ready for communication:', deviceId);
|
|
1209
|
-
resolve();
|
|
1210
|
-
}
|
|
1211
|
-
catch (setupError) {
|
|
1212
|
-
logger === null || logger === void 0 ? void 0 : logger.error('[NobleBLE] Connection setup failed:', setupError);
|
|
1213
|
-
disconnectDevice(deviceId)
|
|
1214
|
-
.catch(() => undefined)
|
|
1215
|
-
.then(() => reject(setupError));
|
|
1216
|
-
}
|
|
1217
|
-
}));
|
|
1218
|
-
});
|
|
1372
|
+
const connectedPeripheral = peripheral;
|
|
1373
|
+
yield connectPeripheralWithCancellation(connectedPeripheral, deviceId);
|
|
1374
|
+
logger === null || logger === void 0 ? void 0 : logger.info('[NobleBLE] Connected to device:', deviceId);
|
|
1375
|
+
try {
|
|
1376
|
+
const characteristics = yield setupConnectionAndDiscoverServices(connectedPeripheral, deviceId, webContents);
|
|
1377
|
+
assertBleActive();
|
|
1378
|
+
deviceCharacteristics.set(deviceId, characteristics);
|
|
1379
|
+
logger === null || logger === void 0 ? void 0 : logger.info('[NobleBLE] Device ready for communication:', deviceId);
|
|
1380
|
+
}
|
|
1381
|
+
catch (setupError) {
|
|
1382
|
+
logger === null || logger === void 0 ? void 0 : logger.error('[NobleBLE] Connection setup failed:', setupError);
|
|
1383
|
+
yield disconnectDevice(deviceId).catch(() => undefined);
|
|
1384
|
+
throw setupError;
|
|
1385
|
+
}
|
|
1219
1386
|
});
|
|
1220
1387
|
}
|
|
1221
1388
|
function disconnectDevice(deviceId) {
|
|
1389
|
+
var _a;
|
|
1222
1390
|
return index.__awaiter(this, void 0, void 0, function* () {
|
|
1223
|
-
|
|
1391
|
+
if (nativeReleased)
|
|
1392
|
+
return;
|
|
1393
|
+
const pendingConnection = connectingDevices.get(deviceId);
|
|
1394
|
+
const peripheral = (_a = connectedDevices.get(deviceId)) !== null && _a !== void 0 ? _a : pendingConnection === null || pendingConnection === void 0 ? void 0 : pendingConnection.peripheral;
|
|
1224
1395
|
if (!peripheral) {
|
|
1225
1396
|
return;
|
|
1226
1397
|
}
|
|
1398
|
+
pendingConnection === null || pendingConnection === void 0 ? void 0 : pendingConnection.cancel(hdShared.ERRORS.TypedError(hdShared.HardwareErrorCode.BleDeviceDisconnected, `Device ${deviceId} connection cancelled`));
|
|
1227
1399
|
const disconnectEntry = deviceDisconnectListeners.get(deviceId);
|
|
1228
1400
|
if (disconnectEntry) {
|
|
1229
1401
|
disconnectEntry.peripheral.removeListener('disconnect', disconnectEntry.listener);
|
|
@@ -1247,6 +1419,8 @@ function disconnectDevice(deviceId) {
|
|
|
1247
1419
|
}
|
|
1248
1420
|
function unsubscribeNotifications(deviceId) {
|
|
1249
1421
|
return index.__awaiter(this, void 0, void 0, function* () {
|
|
1422
|
+
if (nativeReleased)
|
|
1423
|
+
return;
|
|
1250
1424
|
const peripheral = connectedDevices.get(deviceId);
|
|
1251
1425
|
const characteristics = deviceCharacteristics.get(deviceId);
|
|
1252
1426
|
if (!peripheral || !characteristics) {
|
|
@@ -1266,7 +1440,8 @@ function unsubscribeNotifications(deviceId) {
|
|
|
1266
1440
|
subscribedDevices.delete(deviceId);
|
|
1267
1441
|
}
|
|
1268
1442
|
finally {
|
|
1269
|
-
|
|
1443
|
+
if (!disposing)
|
|
1444
|
+
subscriptionOperations.set(deviceId, 'idle');
|
|
1270
1445
|
}
|
|
1271
1446
|
});
|
|
1272
1447
|
}
|
|
@@ -1316,10 +1491,12 @@ function subscribeNotifications(deviceId, callback) {
|
|
|
1316
1491
|
timeoutMs: BLE_CLEANUP_TIMEOUT,
|
|
1317
1492
|
timeoutBehavior: 'resolve',
|
|
1318
1493
|
});
|
|
1494
|
+
assertBleActive();
|
|
1319
1495
|
yield runBleCallbackOperation(callback => notifyCharacteristic.subscribe(callback), {
|
|
1320
|
-
timeoutMs:
|
|
1496
|
+
timeoutMs: NOBLE_BLE_SUBSCRIBE_TIMEOUT_MS,
|
|
1321
1497
|
timeoutBehavior: 'reject',
|
|
1322
1498
|
});
|
|
1499
|
+
assertBleActive();
|
|
1323
1500
|
notifyCharacteristic.on('data', (data) => {
|
|
1324
1501
|
if (!pairedDevices.has(deviceId)) {
|
|
1325
1502
|
pairedDevices.add(deviceId);
|
|
@@ -1332,29 +1509,53 @@ function subscribeNotifications(deviceId, callback) {
|
|
|
1332
1509
|
const subscribeStartedAt = Date.now();
|
|
1333
1510
|
try {
|
|
1334
1511
|
yield rebuildAppSubscription(deviceId, notifyCharacteristic);
|
|
1512
|
+
assertBleActive();
|
|
1335
1513
|
subscribedDevices.set(deviceId, true);
|
|
1336
1514
|
logger === null || logger === void 0 ? void 0 : logger.info('[NobleBLE] Notification subscription active', {
|
|
1337
1515
|
deviceId,
|
|
1338
1516
|
ms: Date.now() - subscribeStartedAt,
|
|
1339
1517
|
});
|
|
1340
1518
|
}
|
|
1519
|
+
catch (error) {
|
|
1520
|
+
throw createNobleBleConnectionError(error, 'Notification subscription failed: ');
|
|
1521
|
+
}
|
|
1341
1522
|
finally {
|
|
1342
|
-
|
|
1523
|
+
if (!disposing)
|
|
1524
|
+
subscriptionOperations.set(deviceId, 'idle');
|
|
1343
1525
|
}
|
|
1344
1526
|
});
|
|
1345
1527
|
}
|
|
1346
1528
|
function setupNobleBleHandlers(webContents) {
|
|
1529
|
+
if (disposing)
|
|
1530
|
+
return;
|
|
1531
|
+
let windowDestroyed = false;
|
|
1347
1532
|
try {
|
|
1348
1533
|
logger = require('electron-log');
|
|
1349
1534
|
const { ipcMain } = require('electron');
|
|
1535
|
+
const channels = new Set();
|
|
1536
|
+
removeIpcHandlers = () => channels.forEach(channel => ipcMain.removeHandler(channel));
|
|
1350
1537
|
const handle = (channel, listener) => {
|
|
1538
|
+
channels.add(channel);
|
|
1351
1539
|
ipcMain.removeHandler(channel);
|
|
1352
|
-
ipcMain.handle(channel,
|
|
1540
|
+
ipcMain.handle(channel, (...args) => index.__awaiter(this, void 0, void 0, function* () {
|
|
1541
|
+
try {
|
|
1542
|
+
if (windowCleanup)
|
|
1543
|
+
yield windowCleanup;
|
|
1544
|
+
assertBleActive();
|
|
1545
|
+
if (windowDestroyed) {
|
|
1546
|
+
throw hdShared.ERRORS.TypedError(hdShared.HardwareErrorCode.BleDeviceDisconnected, 'BLE window destroyed');
|
|
1547
|
+
}
|
|
1548
|
+
return yield Promise.resolve(listener(...args));
|
|
1549
|
+
}
|
|
1550
|
+
catch (error) {
|
|
1551
|
+
return createNobleBleIpcErrorResponse(error);
|
|
1552
|
+
}
|
|
1553
|
+
}));
|
|
1353
1554
|
};
|
|
1354
1555
|
safeLog(logger, 'info', 'Setting up Noble BLE IPC handlers');
|
|
1355
1556
|
handle(hdShared.EOneKeyBleMessageKeys.NOBLE_BLE_ENUMERATE, () => index.__awaiter(this, void 0, void 0, function* () {
|
|
1356
1557
|
try {
|
|
1357
|
-
const devices = yield enumerateDevices();
|
|
1558
|
+
const devices = yield enumerateDevices(() => windowDestroyed);
|
|
1358
1559
|
safeLog(logger, 'debug', 'Enumeration completed', {
|
|
1359
1560
|
count: devices.length,
|
|
1360
1561
|
devices: devices.map(device => ({ id: device.id, name: device.name })),
|
|
@@ -1446,13 +1647,29 @@ function setupNobleBleHandlers(webContents) {
|
|
|
1446
1647
|
}
|
|
1447
1648
|
}));
|
|
1448
1649
|
webContents.on('destroyed', () => {
|
|
1650
|
+
windowDestroyed = true;
|
|
1651
|
+
if (disposing)
|
|
1652
|
+
return;
|
|
1449
1653
|
safeLog(logger, 'info', 'Cleaning up Noble BLE handlers');
|
|
1450
|
-
|
|
1654
|
+
const previousCleanup = windowCleanup;
|
|
1655
|
+
const enumerations = Array.from(pendingEnumerations, cancel => cancel());
|
|
1656
|
+
windowCleanup = (() => index.__awaiter(this, void 0, void 0, function* () {
|
|
1657
|
+
if (previousCleanup)
|
|
1658
|
+
yield previousCleanup;
|
|
1659
|
+
yield Promise.allSettled(enumerations);
|
|
1660
|
+
if (disposing)
|
|
1661
|
+
return;
|
|
1451
1662
|
const deviceIds = Array.from(connectedDevices.keys());
|
|
1452
1663
|
for (const deviceId of deviceIds) {
|
|
1664
|
+
if (disposing)
|
|
1665
|
+
return;
|
|
1453
1666
|
yield unsubscribeNotifications(deviceId).catch(() => undefined);
|
|
1667
|
+
if (disposing)
|
|
1668
|
+
return;
|
|
1454
1669
|
yield disconnectDevice(deviceId).catch(() => undefined);
|
|
1455
1670
|
}
|
|
1671
|
+
if (disposing)
|
|
1672
|
+
return;
|
|
1456
1673
|
yield stopScanning().catch(() => undefined);
|
|
1457
1674
|
cleanupNobleListeners();
|
|
1458
1675
|
discoveredDevices.clear();
|
|
@@ -1468,6 +1685,77 @@ function setupNobleBleHandlers(webContents) {
|
|
|
1468
1685
|
throw error;
|
|
1469
1686
|
}
|
|
1470
1687
|
}
|
|
1688
|
+
function disposeNobleBleSupport(releaseNoble = instance => instance.stop()) {
|
|
1689
|
+
if (disposePromise)
|
|
1690
|
+
return disposePromise;
|
|
1691
|
+
disposing = true;
|
|
1692
|
+
removeIpcHandlers === null || removeIpcHandlers === void 0 ? void 0 : removeIpcHandlers();
|
|
1693
|
+
const instance = noble;
|
|
1694
|
+
const deviceIds = new Set([...connectedDevices.keys(), ...connectingDevices.keys()]);
|
|
1695
|
+
const pendingPeripherals = Array.from(connectingDevices.values(), pending => pending.peripheral);
|
|
1696
|
+
for (const cancel of pendingCancellations)
|
|
1697
|
+
cancel();
|
|
1698
|
+
for (const id of idleDisconnectTimers.keys())
|
|
1699
|
+
clearIdleDisconnect(id);
|
|
1700
|
+
for (const pending of connectingDevices.values()) {
|
|
1701
|
+
pending.cancel(hdShared.ERRORS.TypedError(hdShared.HardwareErrorCode.BleDeviceDisconnected, 'Noble BLE is shutting down'));
|
|
1702
|
+
}
|
|
1703
|
+
const connections = Array.from(nativeConnections);
|
|
1704
|
+
for (const connection of connections) {
|
|
1705
|
+
try {
|
|
1706
|
+
connection.cancel();
|
|
1707
|
+
}
|
|
1708
|
+
catch (error) {
|
|
1709
|
+
logger === null || logger === void 0 ? void 0 : logger.warn('[NobleBLE] Native connect cancellation failed', error);
|
|
1710
|
+
}
|
|
1711
|
+
}
|
|
1712
|
+
let timeout;
|
|
1713
|
+
disposePromise = (() => index.__awaiter(this, void 0, void 0, function* () {
|
|
1714
|
+
try {
|
|
1715
|
+
yield Promise.race([
|
|
1716
|
+
Promise.allSettled([
|
|
1717
|
+
windowCleanup,
|
|
1718
|
+
...connections.map(connection => connection.settled),
|
|
1719
|
+
stopScanning(),
|
|
1720
|
+
...pendingPeripherals.map(peripheral => runBleCallbackOperation(callback => peripheral.disconnect(() => callback()), {
|
|
1721
|
+
timeoutMs: BLE_DISCONNECT_CONFIRM_TIMEOUT_MS,
|
|
1722
|
+
timeoutBehavior: 'resolve',
|
|
1723
|
+
})),
|
|
1724
|
+
...Array.from(deviceIds, (id) => index.__awaiter(this, void 0, void 0, function* () {
|
|
1725
|
+
yield unsubscribeNotifications(id).catch(() => undefined);
|
|
1726
|
+
yield disconnectDevice(id).catch(() => undefined);
|
|
1727
|
+
})),
|
|
1728
|
+
]),
|
|
1729
|
+
new Promise(resolve => {
|
|
1730
|
+
timeout = setTimeout(() => {
|
|
1731
|
+
logger === null || logger === void 0 ? void 0 : logger.warn('[NobleBLE] Process dispose timed out; releasing native manager');
|
|
1732
|
+
resolve();
|
|
1733
|
+
}, 3500);
|
|
1734
|
+
}),
|
|
1735
|
+
]);
|
|
1736
|
+
}
|
|
1737
|
+
finally {
|
|
1738
|
+
clearTimeout(timeout);
|
|
1739
|
+
nativeReleased = true;
|
|
1740
|
+
cleanupNobleListeners();
|
|
1741
|
+
if (instance && persistentStateListener) {
|
|
1742
|
+
instance.removeListener('stateChange', persistentStateListener);
|
|
1743
|
+
persistentStateListener = null;
|
|
1744
|
+
}
|
|
1745
|
+
for (const id of deviceIds)
|
|
1746
|
+
cleanupDevice(id);
|
|
1747
|
+
discoveredDevices.clear();
|
|
1748
|
+
directConnectCooldownUntil.clear();
|
|
1749
|
+
if (instance)
|
|
1750
|
+
releaseNoble(instance);
|
|
1751
|
+
logger === null || logger === void 0 ? void 0 : logger.info('[NobleBLE] Process dispose completed');
|
|
1752
|
+
}
|
|
1753
|
+
}))();
|
|
1754
|
+
return disposePromise;
|
|
1755
|
+
}
|
|
1471
1756
|
|
|
1757
|
+
exports.createNobleBleConnectionError = createNobleBleConnectionError;
|
|
1758
|
+
exports.createNobleBleIpcErrorResponse = createNobleBleIpcErrorResponse;
|
|
1759
|
+
exports.disposeNobleBleSupport = disposeNobleBleSupport;
|
|
1472
1760
|
exports.resolveNobleBleWritePacingDelay = resolveNobleBleWritePacingDelay;
|
|
1473
1761
|
exports.setupNobleBleHandlers = setupNobleBleHandlers;
|