@onekeyfe/hd-transport-electron 1.2.2-alpha.12 → 1.2.2-alpha.14
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-eea100c1.js → index-ef6298f9.js} +1 -1
- package/dist/index.js +1 -1
- package/dist/{noble-ble-handler-e4eaea92.js → noble-ble-handler-de8d60e9.js} +19 -30
- 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/package.json +5 -5
- package/src/__tests__/noble-ble-handler.test.ts +46 -75
- package/src/noble-ble-handler.ts +24 -34
- package/src/noble-ble-timeouts.ts +1 -1
|
@@ -32,7 +32,7 @@ typeof SuppressedError === "function" ? SuppressedError : function (error, suppr
|
|
|
32
32
|
|
|
33
33
|
function initNobleBleSupport(webContents) {
|
|
34
34
|
return __awaiter(this, void 0, void 0, function* () {
|
|
35
|
-
const { setupNobleBleHandlers } = yield Promise.resolve().then(function () { return require('./noble-ble-handler-
|
|
35
|
+
const { setupNobleBleHandlers } = yield Promise.resolve().then(function () { return require('./noble-ble-handler-de8d60e9.js'); });
|
|
36
36
|
setupNobleBleHandlers(webContents);
|
|
37
37
|
});
|
|
38
38
|
}
|
package/dist/index.js
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
'use strict';
|
|
2
2
|
|
|
3
|
-
var index = require('./index-
|
|
3
|
+
var index = require('./index-ef6298f9.js');
|
|
4
4
|
var hdShared = require('@onekeyfe/hd-shared');
|
|
5
5
|
var pRetry = require('p-retry');
|
|
6
6
|
|
|
@@ -96,22 +96,19 @@ 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
103
|
function createNobleBleConnectionError(error, messagePrefix = '') {
|
|
104
104
|
const errorMessage = error.message;
|
|
105
|
-
const normalizedErrorMessage = errorMessage.toLowerCase();
|
|
106
|
-
let errorCode = hdShared.HardwareErrorCode.BleConnectedError;
|
|
107
105
|
if (hdShared.isBleStaleBondErrorText(errorMessage)) {
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
: hdShared.HardwareErrorCode.BleDeviceBondError;
|
|
106
|
+
const nativeErrorMessage = `${messagePrefix}${errorMessage}`;
|
|
107
|
+
return hdShared.ERRORS.TypedError(hdShared.HardwareErrorCode.BleBondInvalid, `${hdShared.HardwareErrorCodeMessage[hdShared.HardwareErrorCode.BleBondInvalid]} (${nativeErrorMessage})`, {
|
|
108
|
+
nativeErrorMessage,
|
|
109
|
+
});
|
|
113
110
|
}
|
|
114
|
-
return hdShared.ERRORS.TypedError(
|
|
111
|
+
return hdShared.ERRORS.TypedError(hdShared.HardwareErrorCode.BleConnectedError, `${messagePrefix}${errorMessage}`);
|
|
115
112
|
}
|
|
116
113
|
const bluetoothState = {
|
|
117
114
|
available: false,
|
|
@@ -937,9 +934,14 @@ function forceReconnectPeripheral(peripheral, deviceId) {
|
|
|
937
934
|
callback();
|
|
938
935
|
}), { timeoutMs: BLE_CLEANUP_TIMEOUT, timeoutBehavior: 'resolve' });
|
|
939
936
|
}
|
|
940
|
-
yield
|
|
941
|
-
|
|
942
|
-
|
|
937
|
+
yield new Promise((resolve, reject) => {
|
|
938
|
+
peripheral.connect(error => {
|
|
939
|
+
if (error) {
|
|
940
|
+
reject(createNobleBleConnectionError(error));
|
|
941
|
+
return;
|
|
942
|
+
}
|
|
943
|
+
resolve();
|
|
944
|
+
});
|
|
943
945
|
});
|
|
944
946
|
logger === null || logger === void 0 ? void 0 : logger.info('[NobleBLE] Force reconnect successful');
|
|
945
947
|
connectedDevices.set(deviceId, peripheral);
|
|
@@ -1023,6 +1025,9 @@ function setupConnectionAndDiscoverServices(peripheral, deviceId, webContents) {
|
|
|
1023
1025
|
yield forceReconnectPeripheral(peripheral, deviceId);
|
|
1024
1026
|
}
|
|
1025
1027
|
catch (resetError) {
|
|
1028
|
+
if (hdShared.isBleStaleBondHardwareError(resetError)) {
|
|
1029
|
+
throw resetError;
|
|
1030
|
+
}
|
|
1026
1031
|
logger === null || logger === void 0 ? void 0 : logger.error('[NobleBLE] Connection reset before discovery failed, continuing', resetError);
|
|
1027
1032
|
}
|
|
1028
1033
|
setupDisconnectListener(peripheral, deviceId, webContents);
|
|
@@ -1190,24 +1195,8 @@ function connectDevice(deviceId, webContents) {
|
|
|
1190
1195
|
return;
|
|
1191
1196
|
}
|
|
1192
1197
|
return new Promise((resolve, reject) => {
|
|
1193
|
-
let connectionTimedOut = false;
|
|
1194
|
-
const timeout = setTimeout(() => {
|
|
1195
|
-
connectionTimedOut = true;
|
|
1196
|
-
reject(hdShared.ERRORS.TypedError(hdShared.HardwareErrorCode.BleConnectedError, 'Connection timeout'));
|
|
1197
|
-
}, NOBLE_BLE_CONNECTION_TIMEOUT_MS);
|
|
1198
1198
|
const connectedPeripheral = peripheral;
|
|
1199
1199
|
connectedPeripheral.connect((error) => index.__awaiter(this, void 0, void 0, function* () {
|
|
1200
|
-
clearTimeout(timeout);
|
|
1201
|
-
if (connectionTimedOut) {
|
|
1202
|
-
if (!error) {
|
|
1203
|
-
try {
|
|
1204
|
-
connectedPeripheral.disconnect(() => undefined);
|
|
1205
|
-
}
|
|
1206
|
-
catch (_a) {
|
|
1207
|
-
}
|
|
1208
|
-
}
|
|
1209
|
-
return;
|
|
1210
|
-
}
|
|
1211
1200
|
if (error) {
|
|
1212
1201
|
logger === null || logger === void 0 ? void 0 : logger.error('[NobleBLE] Connection failed:', error);
|
|
1213
1202
|
reject(createNobleBleConnectionError(error));
|
|
@@ -1330,7 +1319,7 @@ function subscribeNotifications(deviceId, callback) {
|
|
|
1330
1319
|
timeoutBehavior: 'resolve',
|
|
1331
1320
|
});
|
|
1332
1321
|
yield runBleCallbackOperation(callback => notifyCharacteristic.subscribe(callback), {
|
|
1333
|
-
timeoutMs:
|
|
1322
|
+
timeoutMs: NOBLE_BLE_SUBSCRIBE_TIMEOUT_MS,
|
|
1334
1323
|
timeoutBehavior: 'reject',
|
|
1335
1324
|
});
|
|
1336
1325
|
notifyCharacteristic.on('data', (data) => {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"noble-ble-handler.d.ts","sourceRoot":"","sources":["../src/noble-ble-handler.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"noble-ble-handler.d.ts","sourceRoot":"","sources":["../src/noble-ble-handler.ts"],"names":[],"mappings":"AAmCA,OAAO,KAAK,EAA+B,WAAW,EAAE,MAAM,UAAU,CAAC;AAEzE,OAAO,KAAK,EAAE,oBAAoB,EAAE,MAAM,qBAAqB,CAAC;AAOhE,wBAAgB,6BAA6B,CAAC,KAAK,EAAE,KAAK,EAAE,aAAa,SAAK,+CAc7E;AA+ED,wBAAgB,+BAA+B,CAAC,OAAO,CAAC,EAAE,oBAAoB,UAI7E;AAuuDD,wBAAgB,qBAAqB,CAAC,WAAW,EAAE,WAAW,GAAG,IAAI,CAkMpE"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"noble-ble-timeouts.d.ts","sourceRoot":"","sources":["../src/noble-ble-timeouts.ts"],"names":[],"mappings":"AAAA,eAAO,MAAM,kCAAkC,OAAQ,CAAC;AACxD,eAAO,MAAM
|
|
1
|
+
{"version":3,"file":"noble-ble-timeouts.d.ts","sourceRoot":"","sources":["../src/noble-ble-timeouts.ts"],"names":[],"mappings":"AAAA,eAAO,MAAM,kCAAkC,OAAQ,CAAC;AACxD,eAAO,MAAM,8BAA8B,QAAS,CAAC"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@onekeyfe/hd-transport-electron",
|
|
3
|
-
"version": "1.2.2-alpha.
|
|
3
|
+
"version": "1.2.2-alpha.14",
|
|
4
4
|
"author": "OneKey",
|
|
5
5
|
"homepage": "https://github.com/OneKeyHQ/hardware-js-sdk#readme",
|
|
6
6
|
"license": "MIT",
|
|
@@ -25,9 +25,9 @@
|
|
|
25
25
|
"electron-log": ">=4.0.0"
|
|
26
26
|
},
|
|
27
27
|
"dependencies": {
|
|
28
|
-
"@onekeyfe/hd-core": "1.2.2-alpha.
|
|
29
|
-
"@onekeyfe/hd-shared": "1.2.2-alpha.
|
|
30
|
-
"@onekeyfe/hd-transport": "1.2.2-alpha.
|
|
28
|
+
"@onekeyfe/hd-core": "1.2.2-alpha.14",
|
|
29
|
+
"@onekeyfe/hd-shared": "1.2.2-alpha.14",
|
|
30
|
+
"@onekeyfe/hd-transport": "1.2.2-alpha.14",
|
|
31
31
|
"@stoprocent/noble": "2.3.16",
|
|
32
32
|
"p-retry": "^4.6.2"
|
|
33
33
|
},
|
|
@@ -36,5 +36,5 @@
|
|
|
36
36
|
"electron": "^25.0.0",
|
|
37
37
|
"typescript": "^5.3.3"
|
|
38
38
|
},
|
|
39
|
-
"gitHead": "
|
|
39
|
+
"gitHead": "1b3bf0576a53bedbc5f4a82308c48e11ffc00b16"
|
|
40
40
|
}
|
|
@@ -2,7 +2,7 @@ import { EventEmitter } from 'events';
|
|
|
2
2
|
import { EOneKeyBleMessageKeys, HardwareErrorCode } from '@onekeyfe/hd-shared';
|
|
3
3
|
|
|
4
4
|
import {
|
|
5
|
-
|
|
5
|
+
NOBLE_BLE_SUBSCRIBE_TIMEOUT_MS,
|
|
6
6
|
NOBLE_BLE_TARGETED_SCAN_TIMEOUT_MS,
|
|
7
7
|
} from '../noble-ble-timeouts';
|
|
8
8
|
|
|
@@ -26,23 +26,36 @@ describe('Electron Noble BLE device discovery', () => {
|
|
|
26
26
|
jest.clearAllMocks();
|
|
27
27
|
});
|
|
28
28
|
|
|
29
|
-
test('
|
|
29
|
+
test('bounds targeted scans and subscription callbacks independently', () => {
|
|
30
30
|
expect(NOBLE_BLE_TARGETED_SCAN_TIMEOUT_MS).toBe(5_000);
|
|
31
|
-
expect(
|
|
31
|
+
expect(NOBLE_BLE_SUBSCRIBE_TIMEOUT_MS).toBe(10_000);
|
|
32
32
|
});
|
|
33
33
|
|
|
34
34
|
test('maps macOS stale pairing failures without reclassifying generic connection errors', async () => {
|
|
35
35
|
const { createNobleBleConnectionError } = await import('../noble-ble-handler');
|
|
36
36
|
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
37
|
+
const staleBondError = createNobleBleConnectionError(
|
|
38
|
+
new Error('CBErrorDomain:14 Peer removed pairing information on the device side')
|
|
39
|
+
);
|
|
40
|
+
expect(staleBondError).toMatchObject({
|
|
41
|
+
errorCode: HardwareErrorCode.BleBondInvalid,
|
|
42
|
+
params: {
|
|
43
|
+
nativeErrorMessage: 'CBErrorDomain:14 Peer removed pairing information on the device side',
|
|
44
|
+
},
|
|
43
45
|
});
|
|
46
|
+
expect(staleBondError.message).toContain(
|
|
47
|
+
'CBErrorDomain:14 Peer removed pairing information on the device side'
|
|
48
|
+
);
|
|
44
49
|
expect(createNobleBleConnectionError(new Error('Encryption is insufficient'))).toMatchObject({
|
|
45
|
-
errorCode: HardwareErrorCode.
|
|
50
|
+
errorCode: HardwareErrorCode.BleBondInvalid,
|
|
51
|
+
params: {
|
|
52
|
+
nativeErrorMessage: 'Encryption is insufficient',
|
|
53
|
+
},
|
|
54
|
+
});
|
|
55
|
+
expect(
|
|
56
|
+
createNobleBleConnectionError(new Error('CBATTErrorDomain:14 localized native message'))
|
|
57
|
+
).toMatchObject({
|
|
58
|
+
errorCode: HardwareErrorCode.BleBondInvalid,
|
|
46
59
|
});
|
|
47
60
|
expect(createNobleBleConnectionError(new Error('connection failed'))).toMatchObject({
|
|
48
61
|
errorCode: HardwareErrorCode.BleConnectedError,
|
|
@@ -198,75 +211,33 @@ describe('Electron Noble BLE device discovery', () => {
|
|
|
198
211
|
expect(peripheral.connect).toHaveBeenCalledTimes(1);
|
|
199
212
|
});
|
|
200
213
|
|
|
201
|
-
test('
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
const
|
|
205
|
-
|
|
206
|
-
handle: jest.fn((channel: string, handler: IpcHandler) => {
|
|
207
|
-
handlers.set(channel, handler);
|
|
208
|
-
}),
|
|
209
|
-
removeHandler: jest.fn((channel: string) => {
|
|
210
|
-
handlers.delete(channel);
|
|
211
|
-
}),
|
|
212
|
-
};
|
|
213
|
-
const noble = new EventEmitter() as EventEmitter & {
|
|
214
|
-
state: string;
|
|
215
|
-
startScanning: jest.Mock;
|
|
216
|
-
stopScanning: jest.Mock;
|
|
217
|
-
};
|
|
218
|
-
let connectCallback: ((error?: Error) => void) | undefined;
|
|
219
|
-
let resolveConnectStarted = () => undefined;
|
|
220
|
-
const connectStarted = new Promise<void>(resolve => {
|
|
221
|
-
resolveConnectStarted = resolve;
|
|
214
|
+
test('settles a pending Noble connect with the native disconnect error', () => {
|
|
215
|
+
// eslint-disable-next-line @typescript-eslint/no-var-requires, global-require
|
|
216
|
+
const Noble = require('@stoprocent/noble/lib/noble');
|
|
217
|
+
const bindings = Object.assign(new EventEmitter(), {
|
|
218
|
+
connect: jest.fn(),
|
|
222
219
|
});
|
|
223
|
-
const
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
|
|
220
|
+
const noble = new Noble(bindings);
|
|
221
|
+
noble._registerListeners();
|
|
222
|
+
const peripheral = noble._createPeripheral(
|
|
223
|
+
'aabbccdd',
|
|
224
|
+
'',
|
|
225
|
+
'unknown',
|
|
226
|
+
true,
|
|
227
|
+
{ localName: 'Pro2 A1B2', serviceUuids: ['0001'] },
|
|
228
|
+
-50,
|
|
229
|
+
false
|
|
233
230
|
);
|
|
234
|
-
|
|
235
|
-
noble.startScanning = jest.fn((_services, _duplicates, callback) => {
|
|
236
|
-
callback?.();
|
|
237
|
-
noble.emit('discover', peripheral);
|
|
238
|
-
});
|
|
239
|
-
noble.stopScanning = jest.fn(callback => callback?.());
|
|
231
|
+
const connectCallback = jest.fn();
|
|
240
232
|
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
error: jest.fn(),
|
|
247
|
-
}));
|
|
248
|
-
|
|
249
|
-
const { setupNobleBleHandlers } = await import('../noble-ble-handler');
|
|
250
|
-
setupNobleBleHandlers({
|
|
251
|
-
on: jest.fn(),
|
|
252
|
-
send: jest.fn(),
|
|
253
|
-
} as unknown as WebContents);
|
|
254
|
-
|
|
255
|
-
const connect = handlers.get(EOneKeyBleMessageKeys.NOBLE_BLE_CONNECT);
|
|
256
|
-
if (!connect) {
|
|
257
|
-
throw new Error('Electron Noble BLE connect handler was not registered');
|
|
258
|
-
}
|
|
259
|
-
|
|
260
|
-
const connectPromise = Promise.resolve(connect(undefined, 'slow-device'));
|
|
261
|
-
await connectStarted;
|
|
262
|
-
expect(peripheral.connect).toHaveBeenCalledTimes(1);
|
|
263
|
-
|
|
264
|
-
jest.advanceTimersByTime(NOBLE_BLE_CONNECTION_TIMEOUT_MS);
|
|
265
|
-
await expect(connectPromise).rejects.toThrow('Connection timeout');
|
|
233
|
+
peripheral.connect(connectCallback);
|
|
234
|
+
const nativeError = new Error(
|
|
235
|
+
'CBATTErrorDomain:14 Peer removed pairing information on the device side'
|
|
236
|
+
);
|
|
237
|
+
bindings.emit('disconnect', 'aabbccdd', nativeError);
|
|
266
238
|
|
|
267
|
-
connectCallback
|
|
268
|
-
|
|
269
|
-
expect(peripheral.disconnect).toHaveBeenCalledTimes(1);
|
|
239
|
+
expect(connectCallback).toHaveBeenCalledWith(nativeError);
|
|
240
|
+
expect(peripheral.state).toBe('disconnected');
|
|
270
241
|
});
|
|
271
242
|
|
|
272
243
|
test('enumerates a Pro2 communication advertisement after Find My changes its name', async () => {
|
package/src/noble-ble-handler.ts
CHANGED
|
@@ -10,12 +10,14 @@ import {
|
|
|
10
10
|
EOneKeyBleMessageKeys,
|
|
11
11
|
ERRORS,
|
|
12
12
|
HardwareErrorCode,
|
|
13
|
+
HardwareErrorCodeMessage,
|
|
13
14
|
ONEKEY_NOTIFY_CHARACTERISTIC_UUID,
|
|
14
15
|
ONEKEY_SERVICE_UUID,
|
|
15
16
|
ONEKEY_WRITE_CHARACTERISTIC_UUID,
|
|
16
17
|
createKnownBleUuidAliases,
|
|
17
18
|
hasOnekeyCommunicationService,
|
|
18
19
|
isBleStaleBondErrorText,
|
|
20
|
+
isBleStaleBondHardwareError,
|
|
19
21
|
isOnekeyBluetoothDevice,
|
|
20
22
|
isPro2FamilyBleName,
|
|
21
23
|
matchesKnownBleUuid,
|
|
@@ -27,7 +29,7 @@ import { resolveBlePacketCapacity, resolveNobleAttMtu } from './ble-packet-capac
|
|
|
27
29
|
import { safeLog } from './types/noble-extended';
|
|
28
30
|
import { runBleCallbackOperation, softRefreshSubscription } from './ble-ops';
|
|
29
31
|
import {
|
|
30
|
-
|
|
32
|
+
NOBLE_BLE_SUBSCRIBE_TIMEOUT_MS,
|
|
31
33
|
NOBLE_BLE_TARGETED_SCAN_TIMEOUT_MS,
|
|
32
34
|
} from './noble-ble-timeouts';
|
|
33
35
|
|
|
@@ -42,17 +44,18 @@ let logger: Logger | null = null;
|
|
|
42
44
|
|
|
43
45
|
export function createNobleBleConnectionError(error: Error, messagePrefix = '') {
|
|
44
46
|
const errorMessage = error.message;
|
|
45
|
-
const normalizedErrorMessage = errorMessage.toLowerCase();
|
|
46
|
-
let errorCode = HardwareErrorCode.BleConnectedError;
|
|
47
47
|
if (isBleStaleBondErrorText(errorMessage)) {
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
48
|
+
const nativeErrorMessage = `${messagePrefix}${errorMessage}`;
|
|
49
|
+
return ERRORS.TypedError(
|
|
50
|
+
HardwareErrorCode.BleBondInvalid,
|
|
51
|
+
`${HardwareErrorCodeMessage[HardwareErrorCode.BleBondInvalid]} (${nativeErrorMessage})`,
|
|
52
|
+
{
|
|
53
|
+
nativeErrorMessage,
|
|
54
|
+
}
|
|
55
|
+
);
|
|
53
56
|
}
|
|
54
57
|
|
|
55
|
-
return ERRORS.TypedError(
|
|
58
|
+
return ERRORS.TypedError(HardwareErrorCode.BleConnectedError, `${messagePrefix}${errorMessage}`);
|
|
56
59
|
}
|
|
57
60
|
|
|
58
61
|
// Bluetooth state management
|
|
@@ -1268,9 +1271,14 @@ async function forceReconnectPeripheral(peripheral: Peripheral, deviceId: string
|
|
|
1268
1271
|
}
|
|
1269
1272
|
|
|
1270
1273
|
// Step 3: Re-establish connection
|
|
1271
|
-
await
|
|
1272
|
-
|
|
1273
|
-
|
|
1274
|
+
await new Promise<void>((resolve, reject) => {
|
|
1275
|
+
peripheral.connect(error => {
|
|
1276
|
+
if (error) {
|
|
1277
|
+
reject(createNobleBleConnectionError(error));
|
|
1278
|
+
return;
|
|
1279
|
+
}
|
|
1280
|
+
resolve();
|
|
1281
|
+
});
|
|
1274
1282
|
});
|
|
1275
1283
|
logger?.info('[NobleBLE] Force reconnect successful');
|
|
1276
1284
|
connectedDevices.set(deviceId, peripheral);
|
|
@@ -1425,6 +1433,9 @@ async function setupConnectionAndDiscoverServices(
|
|
|
1425
1433
|
try {
|
|
1426
1434
|
await forceReconnectPeripheral(peripheral, deviceId);
|
|
1427
1435
|
} catch (resetError) {
|
|
1436
|
+
if (isBleStaleBondHardwareError(resetError)) {
|
|
1437
|
+
throw resetError;
|
|
1438
|
+
}
|
|
1428
1439
|
// A failed reset must not abort the attempt: discovery on the existing
|
|
1429
1440
|
// link, then the fresh-scan fallback, still have a chance to recover.
|
|
1430
1441
|
logger?.error('[NobleBLE] Connection reset before discovery failed, continuing', resetError);
|
|
@@ -1677,30 +1688,9 @@ async function connectDevice(deviceId: string, webContents: WebContents): Promis
|
|
|
1677
1688
|
}
|
|
1678
1689
|
|
|
1679
1690
|
return new Promise((resolve, reject) => {
|
|
1680
|
-
let connectionTimedOut = false;
|
|
1681
|
-
const timeout = setTimeout(() => {
|
|
1682
|
-
connectionTimedOut = true;
|
|
1683
|
-
reject(ERRORS.TypedError(HardwareErrorCode.BleConnectedError, 'Connection timeout'));
|
|
1684
|
-
}, NOBLE_BLE_CONNECTION_TIMEOUT_MS);
|
|
1685
|
-
|
|
1686
1691
|
// TypeScript type assertion - peripheral is guaranteed to be defined at this point
|
|
1687
1692
|
const connectedPeripheral = peripheral as Peripheral;
|
|
1688
1693
|
connectedPeripheral.connect(async (error: Error | undefined) => {
|
|
1689
|
-
clearTimeout(timeout);
|
|
1690
|
-
|
|
1691
|
-
// Noble may invoke the callback after the SDK timed out and released the request.
|
|
1692
|
-
// Ignore it to avoid initializing disposed commands or leaving an orphaned connection.
|
|
1693
|
-
if (connectionTimedOut) {
|
|
1694
|
-
if (!error) {
|
|
1695
|
-
try {
|
|
1696
|
-
connectedPeripheral.disconnect(() => undefined);
|
|
1697
|
-
} catch {
|
|
1698
|
-
// Best-effort cleanup only.
|
|
1699
|
-
}
|
|
1700
|
-
}
|
|
1701
|
-
return;
|
|
1702
|
-
}
|
|
1703
|
-
|
|
1704
1694
|
if (error) {
|
|
1705
1695
|
logger?.error('[NobleBLE] Connection failed:', error);
|
|
1706
1696
|
reject(createNobleBleConnectionError(error));
|
|
@@ -1886,7 +1876,7 @@ async function subscribeNotifications(
|
|
|
1886
1876
|
timeoutBehavior: 'resolve',
|
|
1887
1877
|
});
|
|
1888
1878
|
await runBleCallbackOperation(callback => notifyCharacteristic.subscribe(callback), {
|
|
1889
|
-
timeoutMs:
|
|
1879
|
+
timeoutMs: NOBLE_BLE_SUBSCRIBE_TIMEOUT_MS,
|
|
1890
1880
|
timeoutBehavior: 'reject',
|
|
1891
1881
|
});
|
|
1892
1882
|
|
|
@@ -1,2 +1,2 @@
|
|
|
1
1
|
export const NOBLE_BLE_TARGETED_SCAN_TIMEOUT_MS = 5_000;
|
|
2
|
-
export const
|
|
2
|
+
export const NOBLE_BLE_SUBSCRIBE_TIMEOUT_MS = 10_000;
|