@onekeyfe/hd-transport-electron 1.2.2-alpha.9 → 1.2.3-alpha.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/{index-00297050.js → index-985e2bf3.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-263d4736.js} +374 -88
- 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 +653 -18
- package/src/index.ts +14 -1
- package/src/noble-ble-handler.ts +438 -109
- 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-985e2bf3.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,31 @@ 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
890
|
discoveredDevices.clear();
|
|
731
891
|
ensureDiscoverListener();
|
|
732
892
|
return new Promise((resolve, reject) => {
|
|
733
893
|
const devices = [];
|
|
894
|
+
let settled = false;
|
|
734
895
|
let intervalId;
|
|
735
|
-
|
|
736
|
-
|
|
737
|
-
if (
|
|
738
|
-
|
|
739
|
-
|
|
740
|
-
|
|
896
|
+
let cleanupPromise;
|
|
897
|
+
const cleanup = () => {
|
|
898
|
+
if (!cleanupPromise) {
|
|
899
|
+
settled = true;
|
|
900
|
+
pendingCancellations.delete(cancel);
|
|
901
|
+
clearTimeout(timeoutId);
|
|
902
|
+
if (intervalId)
|
|
903
|
+
clearInterval(intervalId);
|
|
904
|
+
cleanupPromise = waitForNobleScanStop(nobleInstance).finally(() => {
|
|
905
|
+
pendingEnumerations.delete(cancel);
|
|
906
|
+
});
|
|
907
|
+
}
|
|
908
|
+
return cleanupPromise;
|
|
909
|
+
};
|
|
741
910
|
const pushDevice = (peripheral, id) => {
|
|
742
911
|
var _a;
|
|
743
912
|
if (devices.some(d => d.id === id))
|
|
@@ -754,13 +923,20 @@ function enumerateDevices() {
|
|
|
754
923
|
connectedDevices.forEach(pushDevice);
|
|
755
924
|
};
|
|
756
925
|
const timeoutId = setTimeout(() => index.__awaiter(this, void 0, void 0, function* () {
|
|
926
|
+
if (settled)
|
|
927
|
+
return;
|
|
757
928
|
checkDevices();
|
|
758
929
|
yield cleanup();
|
|
759
930
|
logger === null || logger === void 0 ? void 0 : logger.info('[NobleBLE] Scan completed, found devices:', devices.length);
|
|
760
931
|
resolve(devices);
|
|
761
932
|
}), DEVICE_SCAN_TIMEOUT);
|
|
933
|
+
const cancel = () => cleanup().then(() => resolve([]), reject);
|
|
934
|
+
pendingCancellations.add(cancel);
|
|
935
|
+
pendingEnumerations.add(cancel);
|
|
762
936
|
logger === null || logger === void 0 ? void 0 : logger.info('[NobleBLE] Scanning for OneKey BLE devices');
|
|
763
937
|
nobleInstance.startScanning([], true, (error) => index.__awaiter(this, void 0, void 0, function* () {
|
|
938
|
+
if (settled)
|
|
939
|
+
return;
|
|
764
940
|
if (error) {
|
|
765
941
|
yield cleanup();
|
|
766
942
|
logger === null || logger === void 0 ? void 0 : logger.error('[NobleBLE] Failed to start scanning:', error);
|
|
@@ -775,7 +951,7 @@ function enumerateDevices() {
|
|
|
775
951
|
}
|
|
776
952
|
function stopScanning() {
|
|
777
953
|
return index.__awaiter(this, void 0, void 0, function* () {
|
|
778
|
-
if (!noble)
|
|
954
|
+
if (!noble || nativeReleased)
|
|
779
955
|
return;
|
|
780
956
|
const nobleInstance = noble;
|
|
781
957
|
yield waitForNobleScanStop(nobleInstance);
|
|
@@ -819,13 +995,16 @@ function getDevice(deviceId) {
|
|
|
819
995
|
}
|
|
820
996
|
function discoverServicesAndCharacteristics(peripheral) {
|
|
821
997
|
return index.__awaiter(this, void 0, void 0, function* () {
|
|
998
|
+
assertBleActive();
|
|
822
999
|
let timeoutId;
|
|
823
1000
|
let onDisconnect;
|
|
824
1001
|
const cleanup = () => {
|
|
825
1002
|
if (timeoutId)
|
|
826
1003
|
clearTimeout(timeoutId);
|
|
827
|
-
if (onDisconnect)
|
|
1004
|
+
if (onDisconnect) {
|
|
828
1005
|
peripheral.removeListener('disconnect', onDisconnect);
|
|
1006
|
+
pendingCancellations.delete(onDisconnect);
|
|
1007
|
+
}
|
|
829
1008
|
};
|
|
830
1009
|
const timeoutPromise = new Promise((_, reject) => {
|
|
831
1010
|
timeoutId = setTimeout(() => {
|
|
@@ -838,6 +1017,7 @@ function discoverServicesAndCharacteristics(peripheral) {
|
|
|
838
1017
|
logger === null || logger === void 0 ? void 0 : logger.error('[NobleBLE] Device disconnected during service discovery');
|
|
839
1018
|
reject(hdShared.ERRORS.TypedError(hdShared.HardwareErrorCode.BleServiceNotFound, 'Device disconnected during service discovery'));
|
|
840
1019
|
};
|
|
1020
|
+
pendingCancellations.add(onDisconnect);
|
|
841
1021
|
peripheral.once('disconnect', onDisconnect);
|
|
842
1022
|
});
|
|
843
1023
|
const discoveryPromise = (() => index.__awaiter(this, void 0, void 0, function* () {
|
|
@@ -852,6 +1032,7 @@ function discoverServicesAndCharacteristics(peripheral) {
|
|
|
852
1032
|
}
|
|
853
1033
|
});
|
|
854
1034
|
});
|
|
1035
|
+
assertBleActive();
|
|
855
1036
|
if (!services || services.length === 0) {
|
|
856
1037
|
throw hdShared.ERRORS.TypedError(hdShared.HardwareErrorCode.BleServiceNotFound, 'No OneKey services found');
|
|
857
1038
|
}
|
|
@@ -924,12 +1105,8 @@ function forceReconnectPeripheral(peripheral, deviceId) {
|
|
|
924
1105
|
callback();
|
|
925
1106
|
}), { timeoutMs: BLE_CLEANUP_TIMEOUT, timeoutBehavior: 'resolve' });
|
|
926
1107
|
}
|
|
927
|
-
yield
|
|
928
|
-
timeoutMs: NOBLE_BLE_CONNECTION_TIMEOUT_MS,
|
|
929
|
-
timeoutBehavior: 'reject',
|
|
930
|
-
});
|
|
1108
|
+
yield connectPeripheralWithCancellation(peripheral, deviceId);
|
|
931
1109
|
logger === null || logger === void 0 ? void 0 : logger.info('[NobleBLE] Force reconnect successful');
|
|
932
|
-
connectedDevices.set(deviceId, peripheral);
|
|
933
1110
|
yield hdShared.wait(500);
|
|
934
1111
|
});
|
|
935
1112
|
}
|
|
@@ -946,17 +1123,7 @@ function freshScanAndDiscover(deviceId, webContents) {
|
|
|
946
1123
|
throw hdShared.ERRORS.TypedError(hdShared.HardwareErrorCode.DeviceNotFound, `Device ${deviceId} not found in fresh scan`);
|
|
947
1124
|
}
|
|
948
1125
|
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
|
-
});
|
|
1126
|
+
yield connectPeripheralWithCancellation(freshPeripheral, deviceId, 'Fresh peripheral connection failed: ');
|
|
960
1127
|
setupDisconnectListener(freshPeripheral, deviceId, webContents);
|
|
961
1128
|
yield hdShared.wait(500);
|
|
962
1129
|
logger === null || logger === void 0 ? void 0 : logger.info('[NobleBLE] Attempting service discovery with fresh peripheral');
|
|
@@ -995,6 +1162,7 @@ function discoverServicesAndCharacteristicsWithRetry(peripheral, deviceId) {
|
|
|
995
1162
|
minTimeout: 500,
|
|
996
1163
|
maxTimeout: 3000,
|
|
997
1164
|
onFailedAttempt: error => {
|
|
1165
|
+
assertBleActive();
|
|
998
1166
|
logger === null || logger === void 0 ? void 0 : logger.error(`[NobleBLE] Service discovery attempt ${error.attemptNumber} failed:`, {
|
|
999
1167
|
message: error.message,
|
|
1000
1168
|
retriesLeft: error.retriesLeft,
|
|
@@ -1010,8 +1178,13 @@ function setupConnectionAndDiscoverServices(peripheral, deviceId, webContents) {
|
|
|
1010
1178
|
yield forceReconnectPeripheral(peripheral, deviceId);
|
|
1011
1179
|
}
|
|
1012
1180
|
catch (resetError) {
|
|
1181
|
+
if (hdShared.isBleStaleBondHardwareError(resetError) ||
|
|
1182
|
+
(resetError === null || resetError === void 0 ? void 0 : resetError.errorCode) === hdShared.HardwareErrorCode.BleDeviceDisconnected) {
|
|
1183
|
+
throw resetError;
|
|
1184
|
+
}
|
|
1013
1185
|
logger === null || logger === void 0 ? void 0 : logger.error('[NobleBLE] Connection reset before discovery failed, continuing', resetError);
|
|
1014
1186
|
}
|
|
1187
|
+
assertBleActive();
|
|
1015
1188
|
setupDisconnectListener(peripheral, deviceId, webContents);
|
|
1016
1189
|
try {
|
|
1017
1190
|
return yield discoverServicesAndCharacteristicsWithRetry(peripheral, deviceId);
|
|
@@ -1034,36 +1207,46 @@ const directConnectCooldownUntil = new Map();
|
|
|
1034
1207
|
function tryDirectConnectById(deviceId) {
|
|
1035
1208
|
var _a;
|
|
1036
1209
|
return index.__awaiter(this, void 0, void 0, function* () {
|
|
1210
|
+
assertBleActive();
|
|
1037
1211
|
const nobleInstance = noble;
|
|
1038
1212
|
if (!(nobleInstance === null || nobleInstance === void 0 ? void 0 : nobleInstance.connectAsync))
|
|
1039
1213
|
return undefined;
|
|
1040
1214
|
const cooldownUntil = (_a = directConnectCooldownUntil.get(deviceId)) !== null && _a !== void 0 ? _a : 0;
|
|
1041
1215
|
if (Date.now() < cooldownUntil)
|
|
1042
1216
|
return undefined;
|
|
1217
|
+
let timer;
|
|
1218
|
+
let cancel;
|
|
1219
|
+
let abandoned = false;
|
|
1043
1220
|
try {
|
|
1044
1221
|
const directPromise = nobleInstance.connectAsync(deviceId);
|
|
1222
|
+
trackNativeConnection(directPromise.then((late) => index.__awaiter(this, void 0, void 0, function* () {
|
|
1223
|
+
if ((!abandoned && !disposing) || nativeReleased)
|
|
1224
|
+
return;
|
|
1225
|
+
const peripheral = late !== null && late !== void 0 ? late : discoveredDevices.get(deviceId);
|
|
1226
|
+
if ((peripheral === null || peripheral === void 0 ? void 0 : peripheral.state) === 'connected' && !connectedDevices.has(deviceId)) {
|
|
1227
|
+
peripheral.removeAllListeners('disconnect');
|
|
1228
|
+
yield runBleCallbackOperation(callback => peripheral.disconnect(() => callback()), {
|
|
1229
|
+
timeoutMs: BLE_DISCONNECT_CONFIRM_TIMEOUT_MS,
|
|
1230
|
+
timeoutBehavior: 'resolve',
|
|
1231
|
+
});
|
|
1232
|
+
}
|
|
1233
|
+
})), () => { var _a; return (_a = nobleInstance.cancelConnect) === null || _a === void 0 ? void 0 : _a.call(nobleInstance, deviceId); });
|
|
1045
1234
|
const raced = yield Promise.race([
|
|
1046
1235
|
directPromise,
|
|
1047
1236
|
new Promise(resolve => {
|
|
1048
|
-
|
|
1237
|
+
cancel = () => {
|
|
1238
|
+
abandoned = true;
|
|
1239
|
+
resolve('timeout');
|
|
1240
|
+
};
|
|
1241
|
+
pendingCancellations.add(cancel);
|
|
1242
|
+
timer = setTimeout(cancel, DIRECT_CONNECT_TIMEOUT_MS);
|
|
1049
1243
|
}),
|
|
1050
1244
|
]);
|
|
1051
|
-
if (raced === 'timeout') {
|
|
1245
|
+
if (raced === 'timeout' || disposing) {
|
|
1052
1246
|
directConnectCooldownUntil.set(deviceId, Date.now() + DIRECT_CONNECT_COOLDOWN_MS);
|
|
1053
1247
|
logger === null || logger === void 0 ? void 0 : logger.info('[NobleBLE] Direct connect-by-id timed out, falling back to scan', {
|
|
1054
1248
|
deviceId,
|
|
1055
1249
|
});
|
|
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
1250
|
return undefined;
|
|
1068
1251
|
}
|
|
1069
1252
|
const peripheral = raced !== null && raced !== void 0 ? raced : discoveredDevices.get(deviceId);
|
|
@@ -1080,6 +1263,11 @@ function tryDirectConnectById(deviceId) {
|
|
|
1080
1263
|
});
|
|
1081
1264
|
return undefined;
|
|
1082
1265
|
}
|
|
1266
|
+
finally {
|
|
1267
|
+
clearTimeout(timer);
|
|
1268
|
+
if (cancel)
|
|
1269
|
+
pendingCancellations.delete(cancel);
|
|
1270
|
+
}
|
|
1083
1271
|
});
|
|
1084
1272
|
}
|
|
1085
1273
|
function connectDevice(deviceId, webContents) {
|
|
@@ -1132,6 +1320,7 @@ function connectDevice(deviceId, webContents) {
|
|
|
1132
1320
|
peripheral = byIdFirst ? yield scanForPeripheral() : yield connectById();
|
|
1133
1321
|
}
|
|
1134
1322
|
}
|
|
1323
|
+
assertBleActive();
|
|
1135
1324
|
if (!peripheral) {
|
|
1136
1325
|
throw hdShared.ERRORS.TypedError(hdShared.HardwareErrorCode.DeviceNotFound, `Device ${deviceId} not found`);
|
|
1137
1326
|
}
|
|
@@ -1142,6 +1331,7 @@ function connectDevice(deviceId, webContents) {
|
|
|
1142
1331
|
if (!connectedDevices.has(deviceId)) {
|
|
1143
1332
|
connectedDevices.set(deviceId, peripheral);
|
|
1144
1333
|
}
|
|
1334
|
+
assertBleActive();
|
|
1145
1335
|
setupDisconnectListener(peripheral, deviceId, webContents);
|
|
1146
1336
|
if (deviceCharacteristics.has(deviceId)) {
|
|
1147
1337
|
logger === null || logger === void 0 ? void 0 : logger.info('[NobleBLE] Device characteristics already available');
|
|
@@ -1166,6 +1356,7 @@ function connectDevice(deviceId, webContents) {
|
|
|
1166
1356
|
}
|
|
1167
1357
|
try {
|
|
1168
1358
|
const characteristics = yield setupConnectionAndDiscoverServices(peripheral, deviceId, webContents);
|
|
1359
|
+
assertBleActive();
|
|
1169
1360
|
deviceCharacteristics.set(deviceId, characteristics);
|
|
1170
1361
|
logger === null || logger === void 0 ? void 0 : logger.info('[NobleBLE] Device ready for communication:', deviceId);
|
|
1171
1362
|
}
|
|
@@ -1176,54 +1367,33 @@ function connectDevice(deviceId, webContents) {
|
|
|
1176
1367
|
}
|
|
1177
1368
|
return;
|
|
1178
1369
|
}
|
|
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
|
-
});
|
|
1370
|
+
const connectedPeripheral = peripheral;
|
|
1371
|
+
yield connectPeripheralWithCancellation(connectedPeripheral, deviceId);
|
|
1372
|
+
logger === null || logger === void 0 ? void 0 : logger.info('[NobleBLE] Connected to device:', deviceId);
|
|
1373
|
+
try {
|
|
1374
|
+
const characteristics = yield setupConnectionAndDiscoverServices(connectedPeripheral, deviceId, webContents);
|
|
1375
|
+
assertBleActive();
|
|
1376
|
+
deviceCharacteristics.set(deviceId, characteristics);
|
|
1377
|
+
logger === null || logger === void 0 ? void 0 : logger.info('[NobleBLE] Device ready for communication:', deviceId);
|
|
1378
|
+
}
|
|
1379
|
+
catch (setupError) {
|
|
1380
|
+
logger === null || logger === void 0 ? void 0 : logger.error('[NobleBLE] Connection setup failed:', setupError);
|
|
1381
|
+
yield disconnectDevice(deviceId).catch(() => undefined);
|
|
1382
|
+
throw setupError;
|
|
1383
|
+
}
|
|
1219
1384
|
});
|
|
1220
1385
|
}
|
|
1221
1386
|
function disconnectDevice(deviceId) {
|
|
1387
|
+
var _a;
|
|
1222
1388
|
return index.__awaiter(this, void 0, void 0, function* () {
|
|
1223
|
-
|
|
1389
|
+
if (nativeReleased)
|
|
1390
|
+
return;
|
|
1391
|
+
const pendingConnection = connectingDevices.get(deviceId);
|
|
1392
|
+
const peripheral = (_a = connectedDevices.get(deviceId)) !== null && _a !== void 0 ? _a : pendingConnection === null || pendingConnection === void 0 ? void 0 : pendingConnection.peripheral;
|
|
1224
1393
|
if (!peripheral) {
|
|
1225
1394
|
return;
|
|
1226
1395
|
}
|
|
1396
|
+
pendingConnection === null || pendingConnection === void 0 ? void 0 : pendingConnection.cancel(hdShared.ERRORS.TypedError(hdShared.HardwareErrorCode.BleDeviceDisconnected, `Device ${deviceId} connection cancelled`));
|
|
1227
1397
|
const disconnectEntry = deviceDisconnectListeners.get(deviceId);
|
|
1228
1398
|
if (disconnectEntry) {
|
|
1229
1399
|
disconnectEntry.peripheral.removeListener('disconnect', disconnectEntry.listener);
|
|
@@ -1247,6 +1417,8 @@ function disconnectDevice(deviceId) {
|
|
|
1247
1417
|
}
|
|
1248
1418
|
function unsubscribeNotifications(deviceId) {
|
|
1249
1419
|
return index.__awaiter(this, void 0, void 0, function* () {
|
|
1420
|
+
if (nativeReleased)
|
|
1421
|
+
return;
|
|
1250
1422
|
const peripheral = connectedDevices.get(deviceId);
|
|
1251
1423
|
const characteristics = deviceCharacteristics.get(deviceId);
|
|
1252
1424
|
if (!peripheral || !characteristics) {
|
|
@@ -1266,7 +1438,8 @@ function unsubscribeNotifications(deviceId) {
|
|
|
1266
1438
|
subscribedDevices.delete(deviceId);
|
|
1267
1439
|
}
|
|
1268
1440
|
finally {
|
|
1269
|
-
|
|
1441
|
+
if (!disposing)
|
|
1442
|
+
subscriptionOperations.set(deviceId, 'idle');
|
|
1270
1443
|
}
|
|
1271
1444
|
});
|
|
1272
1445
|
}
|
|
@@ -1316,10 +1489,12 @@ function subscribeNotifications(deviceId, callback) {
|
|
|
1316
1489
|
timeoutMs: BLE_CLEANUP_TIMEOUT,
|
|
1317
1490
|
timeoutBehavior: 'resolve',
|
|
1318
1491
|
});
|
|
1492
|
+
assertBleActive();
|
|
1319
1493
|
yield runBleCallbackOperation(callback => notifyCharacteristic.subscribe(callback), {
|
|
1320
|
-
timeoutMs:
|
|
1494
|
+
timeoutMs: NOBLE_BLE_SUBSCRIBE_TIMEOUT_MS,
|
|
1321
1495
|
timeoutBehavior: 'reject',
|
|
1322
1496
|
});
|
|
1497
|
+
assertBleActive();
|
|
1323
1498
|
notifyCharacteristic.on('data', (data) => {
|
|
1324
1499
|
if (!pairedDevices.has(deviceId)) {
|
|
1325
1500
|
pairedDevices.add(deviceId);
|
|
@@ -1332,29 +1507,53 @@ function subscribeNotifications(deviceId, callback) {
|
|
|
1332
1507
|
const subscribeStartedAt = Date.now();
|
|
1333
1508
|
try {
|
|
1334
1509
|
yield rebuildAppSubscription(deviceId, notifyCharacteristic);
|
|
1510
|
+
assertBleActive();
|
|
1335
1511
|
subscribedDevices.set(deviceId, true);
|
|
1336
1512
|
logger === null || logger === void 0 ? void 0 : logger.info('[NobleBLE] Notification subscription active', {
|
|
1337
1513
|
deviceId,
|
|
1338
1514
|
ms: Date.now() - subscribeStartedAt,
|
|
1339
1515
|
});
|
|
1340
1516
|
}
|
|
1517
|
+
catch (error) {
|
|
1518
|
+
throw createNobleBleConnectionError(error, 'Notification subscription failed: ');
|
|
1519
|
+
}
|
|
1341
1520
|
finally {
|
|
1342
|
-
|
|
1521
|
+
if (!disposing)
|
|
1522
|
+
subscriptionOperations.set(deviceId, 'idle');
|
|
1343
1523
|
}
|
|
1344
1524
|
});
|
|
1345
1525
|
}
|
|
1346
1526
|
function setupNobleBleHandlers(webContents) {
|
|
1527
|
+
if (disposing)
|
|
1528
|
+
return;
|
|
1529
|
+
let windowDestroyed = false;
|
|
1347
1530
|
try {
|
|
1348
1531
|
logger = require('electron-log');
|
|
1349
1532
|
const { ipcMain } = require('electron');
|
|
1533
|
+
const channels = new Set();
|
|
1534
|
+
removeIpcHandlers = () => channels.forEach(channel => ipcMain.removeHandler(channel));
|
|
1350
1535
|
const handle = (channel, listener) => {
|
|
1536
|
+
channels.add(channel);
|
|
1351
1537
|
ipcMain.removeHandler(channel);
|
|
1352
|
-
ipcMain.handle(channel,
|
|
1538
|
+
ipcMain.handle(channel, (...args) => index.__awaiter(this, void 0, void 0, function* () {
|
|
1539
|
+
try {
|
|
1540
|
+
if (windowCleanup)
|
|
1541
|
+
yield windowCleanup;
|
|
1542
|
+
assertBleActive();
|
|
1543
|
+
if (windowDestroyed) {
|
|
1544
|
+
throw hdShared.ERRORS.TypedError(hdShared.HardwareErrorCode.BleDeviceDisconnected, 'BLE window destroyed');
|
|
1545
|
+
}
|
|
1546
|
+
return yield Promise.resolve(listener(...args));
|
|
1547
|
+
}
|
|
1548
|
+
catch (error) {
|
|
1549
|
+
return createNobleBleIpcErrorResponse(error);
|
|
1550
|
+
}
|
|
1551
|
+
}));
|
|
1353
1552
|
};
|
|
1354
1553
|
safeLog(logger, 'info', 'Setting up Noble BLE IPC handlers');
|
|
1355
1554
|
handle(hdShared.EOneKeyBleMessageKeys.NOBLE_BLE_ENUMERATE, () => index.__awaiter(this, void 0, void 0, function* () {
|
|
1356
1555
|
try {
|
|
1357
|
-
const devices = yield enumerateDevices();
|
|
1556
|
+
const devices = yield enumerateDevices(() => windowDestroyed);
|
|
1358
1557
|
safeLog(logger, 'debug', 'Enumeration completed', {
|
|
1359
1558
|
count: devices.length,
|
|
1360
1559
|
devices: devices.map(device => ({ id: device.id, name: device.name })),
|
|
@@ -1446,13 +1645,29 @@ function setupNobleBleHandlers(webContents) {
|
|
|
1446
1645
|
}
|
|
1447
1646
|
}));
|
|
1448
1647
|
webContents.on('destroyed', () => {
|
|
1648
|
+
windowDestroyed = true;
|
|
1649
|
+
if (disposing)
|
|
1650
|
+
return;
|
|
1449
1651
|
safeLog(logger, 'info', 'Cleaning up Noble BLE handlers');
|
|
1450
|
-
|
|
1652
|
+
const previousCleanup = windowCleanup;
|
|
1653
|
+
const enumerations = Array.from(pendingEnumerations, cancel => cancel());
|
|
1654
|
+
windowCleanup = (() => index.__awaiter(this, void 0, void 0, function* () {
|
|
1655
|
+
if (previousCleanup)
|
|
1656
|
+
yield previousCleanup;
|
|
1657
|
+
yield Promise.allSettled(enumerations);
|
|
1658
|
+
if (disposing)
|
|
1659
|
+
return;
|
|
1451
1660
|
const deviceIds = Array.from(connectedDevices.keys());
|
|
1452
1661
|
for (const deviceId of deviceIds) {
|
|
1662
|
+
if (disposing)
|
|
1663
|
+
return;
|
|
1453
1664
|
yield unsubscribeNotifications(deviceId).catch(() => undefined);
|
|
1665
|
+
if (disposing)
|
|
1666
|
+
return;
|
|
1454
1667
|
yield disconnectDevice(deviceId).catch(() => undefined);
|
|
1455
1668
|
}
|
|
1669
|
+
if (disposing)
|
|
1670
|
+
return;
|
|
1456
1671
|
yield stopScanning().catch(() => undefined);
|
|
1457
1672
|
cleanupNobleListeners();
|
|
1458
1673
|
discoveredDevices.clear();
|
|
@@ -1468,6 +1683,77 @@ function setupNobleBleHandlers(webContents) {
|
|
|
1468
1683
|
throw error;
|
|
1469
1684
|
}
|
|
1470
1685
|
}
|
|
1686
|
+
function disposeNobleBleSupport(releaseNoble = instance => instance.stop()) {
|
|
1687
|
+
if (disposePromise)
|
|
1688
|
+
return disposePromise;
|
|
1689
|
+
disposing = true;
|
|
1690
|
+
removeIpcHandlers === null || removeIpcHandlers === void 0 ? void 0 : removeIpcHandlers();
|
|
1691
|
+
const instance = noble;
|
|
1692
|
+
const deviceIds = new Set([...connectedDevices.keys(), ...connectingDevices.keys()]);
|
|
1693
|
+
const pendingPeripherals = Array.from(connectingDevices.values(), pending => pending.peripheral);
|
|
1694
|
+
for (const cancel of pendingCancellations)
|
|
1695
|
+
cancel();
|
|
1696
|
+
for (const id of idleDisconnectTimers.keys())
|
|
1697
|
+
clearIdleDisconnect(id);
|
|
1698
|
+
for (const pending of connectingDevices.values()) {
|
|
1699
|
+
pending.cancel(hdShared.ERRORS.TypedError(hdShared.HardwareErrorCode.BleDeviceDisconnected, 'Noble BLE is shutting down'));
|
|
1700
|
+
}
|
|
1701
|
+
const connections = Array.from(nativeConnections);
|
|
1702
|
+
for (const connection of connections) {
|
|
1703
|
+
try {
|
|
1704
|
+
connection.cancel();
|
|
1705
|
+
}
|
|
1706
|
+
catch (error) {
|
|
1707
|
+
logger === null || logger === void 0 ? void 0 : logger.warn('[NobleBLE] Native connect cancellation failed', error);
|
|
1708
|
+
}
|
|
1709
|
+
}
|
|
1710
|
+
let timeout;
|
|
1711
|
+
disposePromise = (() => index.__awaiter(this, void 0, void 0, function* () {
|
|
1712
|
+
try {
|
|
1713
|
+
yield Promise.race([
|
|
1714
|
+
Promise.allSettled([
|
|
1715
|
+
windowCleanup,
|
|
1716
|
+
...connections.map(connection => connection.settled),
|
|
1717
|
+
stopScanning(),
|
|
1718
|
+
...pendingPeripherals.map(peripheral => runBleCallbackOperation(callback => peripheral.disconnect(() => callback()), {
|
|
1719
|
+
timeoutMs: BLE_DISCONNECT_CONFIRM_TIMEOUT_MS,
|
|
1720
|
+
timeoutBehavior: 'resolve',
|
|
1721
|
+
})),
|
|
1722
|
+
...Array.from(deviceIds, (id) => index.__awaiter(this, void 0, void 0, function* () {
|
|
1723
|
+
yield unsubscribeNotifications(id).catch(() => undefined);
|
|
1724
|
+
yield disconnectDevice(id).catch(() => undefined);
|
|
1725
|
+
})),
|
|
1726
|
+
]),
|
|
1727
|
+
new Promise(resolve => {
|
|
1728
|
+
timeout = setTimeout(() => {
|
|
1729
|
+
logger === null || logger === void 0 ? void 0 : logger.warn('[NobleBLE] Process dispose timed out; releasing native manager');
|
|
1730
|
+
resolve();
|
|
1731
|
+
}, 3500);
|
|
1732
|
+
}),
|
|
1733
|
+
]);
|
|
1734
|
+
}
|
|
1735
|
+
finally {
|
|
1736
|
+
clearTimeout(timeout);
|
|
1737
|
+
nativeReleased = true;
|
|
1738
|
+
cleanupNobleListeners();
|
|
1739
|
+
if (instance && persistentStateListener) {
|
|
1740
|
+
instance.removeListener('stateChange', persistentStateListener);
|
|
1741
|
+
persistentStateListener = null;
|
|
1742
|
+
}
|
|
1743
|
+
for (const id of deviceIds)
|
|
1744
|
+
cleanupDevice(id);
|
|
1745
|
+
discoveredDevices.clear();
|
|
1746
|
+
directConnectCooldownUntil.clear();
|
|
1747
|
+
if (instance)
|
|
1748
|
+
releaseNoble(instance);
|
|
1749
|
+
logger === null || logger === void 0 ? void 0 : logger.info('[NobleBLE] Process dispose completed');
|
|
1750
|
+
}
|
|
1751
|
+
}))();
|
|
1752
|
+
return disposePromise;
|
|
1753
|
+
}
|
|
1471
1754
|
|
|
1755
|
+
exports.createNobleBleConnectionError = createNobleBleConnectionError;
|
|
1756
|
+
exports.createNobleBleIpcErrorResponse = createNobleBleIpcErrorResponse;
|
|
1757
|
+
exports.disposeNobleBleSupport = disposeNobleBleSupport;
|
|
1472
1758
|
exports.resolveNobleBleWritePacingDelay = resolveNobleBleWritePacingDelay;
|
|
1473
1759
|
exports.setupNobleBleHandlers = setupNobleBleHandlers;
|