@onekeyfe/hd-transport-react-native 1.2.2-alpha.105 → 1.2.2-alpha.107
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/README.md +1 -1
- package/dist/BleManager.d.ts.map +1 -1
- package/dist/bleNativeDisconnect.d.ts +3 -0
- package/dist/bleNativeDisconnect.d.ts.map +1 -0
- package/dist/index.d.ts +5 -2
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +298 -78
- package/package.json +6 -6
- package/src/BleManager.ts +58 -4
- package/src/__tests__/bleNativeDisconnect.test.ts +33 -0
- package/src/__tests__/connectTimeout.test.ts +282 -3
- package/src/__tests__/protocolV2Link.test.ts +193 -31
- package/src/__tests__/staleCallTimeout.test.ts +34 -5
- package/src/bleNativeDisconnect.ts +40 -0
- package/src/index.ts +246 -85
package/dist/index.js
CHANGED
|
@@ -57,6 +57,17 @@ const bleLogger = {
|
|
|
57
57
|
};
|
|
58
58
|
|
|
59
59
|
const Logger = bleLogger;
|
|
60
|
+
const bondFailureReasons = {
|
|
61
|
+
1: 'authentication_failed',
|
|
62
|
+
2: 'rejected',
|
|
63
|
+
3: 'canceled',
|
|
64
|
+
4: 'device_unreachable',
|
|
65
|
+
5: 'discovery_in_progress',
|
|
66
|
+
6: 'timeout',
|
|
67
|
+
7: 'repeated_attempts',
|
|
68
|
+
8: 'remote_canceled',
|
|
69
|
+
9: 'removed',
|
|
70
|
+
};
|
|
60
71
|
const getConnectedDeviceIds = (serviceUuids) => BleUtils__default["default"].getConnectedPeripherals(serviceUuids);
|
|
61
72
|
const pairDevice = (macAddress) => BleUtils__default["default"].pairDevice(macAddress);
|
|
62
73
|
const onDeviceBondState = (bleMacAddress) => new Promise((resolve, reject) => {
|
|
@@ -69,24 +80,40 @@ const onDeviceBondState = (bleMacAddress) => new Promise((resolve, reject) => {
|
|
|
69
80
|
};
|
|
70
81
|
const timeout = setTimeout(() => {
|
|
71
82
|
cleanup();
|
|
72
|
-
reject(hdShared.ERRORS.TypedError(hdShared.HardwareErrorCode.BleDeviceNotBonded, '
|
|
83
|
+
reject(hdShared.ERRORS.TypedError(hdShared.HardwareErrorCode.BleDeviceNotBonded, 'Bluetooth pairing timed out', {
|
|
84
|
+
phase: 'bond',
|
|
85
|
+
reason: 'timeout',
|
|
86
|
+
}));
|
|
73
87
|
}, 60 * 1000);
|
|
74
88
|
const cleanupListener = BleUtils__default["default"].onDeviceBondState(peripheral => {
|
|
75
|
-
var _a;
|
|
89
|
+
var _a, _b;
|
|
76
90
|
if (((_a = peripheral.id) === null || _a === void 0 ? void 0 : _a.toLowerCase()) !== bleMacAddress.toLowerCase()) {
|
|
77
91
|
return;
|
|
78
92
|
}
|
|
79
93
|
const { bondState } = peripheral;
|
|
80
94
|
const hasBonded = bondState.preState === 'BOND_BONDING' && bondState.state === 'BOND_BONDED';
|
|
81
|
-
const
|
|
95
|
+
const hasFailed = bondState.preState === 'BOND_BONDING' && bondState.state === 'BOND_NONE';
|
|
82
96
|
Logger.debug('onDeviceBondState bondState:', bondState);
|
|
83
97
|
if (hasBonded) {
|
|
84
98
|
cleanup();
|
|
85
99
|
resolve(peripheral);
|
|
86
100
|
}
|
|
87
|
-
else if (
|
|
101
|
+
else if (hasFailed) {
|
|
88
102
|
cleanup();
|
|
89
|
-
|
|
103
|
+
const nativeReason = 'reason' in bondState && typeof bondState.reason === 'number'
|
|
104
|
+
? bondState.reason
|
|
105
|
+
: undefined;
|
|
106
|
+
const reason = nativeReason === undefined ? 'unknown' : (_b = bondFailureReasons[nativeReason]) !== null && _b !== void 0 ? _b : 'unknown';
|
|
107
|
+
const params = Object.assign({ phase: 'bond', reason }, (nativeReason === undefined ? {} : { nativeReason }));
|
|
108
|
+
if (reason === 'timeout') {
|
|
109
|
+
reject(hdShared.ERRORS.TypedError(hdShared.HardwareErrorCode.BleDeviceNotBonded, 'Bluetooth pairing timed out', params));
|
|
110
|
+
}
|
|
111
|
+
else if (reason === 'canceled') {
|
|
112
|
+
reject(hdShared.ERRORS.TypedError(hdShared.HardwareErrorCode.BleDeviceBondedCanceled, 'Bluetooth pairing canceled', params));
|
|
113
|
+
}
|
|
114
|
+
else {
|
|
115
|
+
reject(hdShared.ERRORS.TypedError(hdShared.HardwareErrorCode.BleDeviceNotBonded, 'Bluetooth pairing failed', params));
|
|
116
|
+
}
|
|
90
117
|
}
|
|
91
118
|
});
|
|
92
119
|
});
|
|
@@ -194,6 +221,27 @@ const subscribeBleOn = (bleManager, ms = 1000) => new Promise((resolve, reject)
|
|
|
194
221
|
}, ms);
|
|
195
222
|
});
|
|
196
223
|
|
|
224
|
+
const BLE_PLX_DEVICE_DISCONNECTED = 201;
|
|
225
|
+
const IOS_PERIPHERAL_DISCONNECTED = 7;
|
|
226
|
+
const nativeErrorText$1 = (error) => [error.reason, error.message]
|
|
227
|
+
.filter((value) => typeof value === 'string')
|
|
228
|
+
.join(' ');
|
|
229
|
+
const isNativeBleDisconnectError = (error) => {
|
|
230
|
+
if (!error || typeof error !== 'object') {
|
|
231
|
+
return false;
|
|
232
|
+
}
|
|
233
|
+
const nativeError = error;
|
|
234
|
+
return (nativeError.errorCode === BLE_PLX_DEVICE_DISCONNECTED ||
|
|
235
|
+
nativeError.iosErrorCode === IOS_PERIPHERAL_DISCONNECTED);
|
|
236
|
+
};
|
|
237
|
+
const toBleDisconnectHardwareError = (error) => {
|
|
238
|
+
if ((error === null || error === void 0 ? void 0 : error.errorCode) === hdShared.HardwareErrorCode.BleDeviceDisconnected) {
|
|
239
|
+
return error;
|
|
240
|
+
}
|
|
241
|
+
const nativeError = (error !== null && error !== void 0 ? error : {});
|
|
242
|
+
return hdShared.ERRORS.TypedError(hdShared.HardwareErrorCode.BleDeviceDisconnected, nativeErrorText$1(nativeError) || undefined);
|
|
243
|
+
};
|
|
244
|
+
|
|
197
245
|
const ATT_INSUFFICIENT_AUTHENTICATION = 5;
|
|
198
246
|
const ATT_INSUFFICIENT_ENCRYPTION = 15;
|
|
199
247
|
const IOS_PEER_REMOVED_PAIRING_INFORMATION = 14;
|
|
@@ -258,6 +306,7 @@ class BleTransport {
|
|
|
258
306
|
const { check, ProtocolV1, parseConfigure } = transport__default["default"];
|
|
259
307
|
const Log = bleLogger;
|
|
260
308
|
const transportCache = {};
|
|
309
|
+
let bleManagerResetPromise;
|
|
261
310
|
const FIRMWARE_UPLOAD_WRITE_BURST_SIZE = reactNative.Platform.OS === 'ios' ? 4 : 5;
|
|
262
311
|
const FIRMWARE_UPLOAD_WRITE_PAUSE_MS = reactNative.Platform.OS === 'ios' ? 8 : 10;
|
|
263
312
|
const FIRMWARE_UPLOAD_WRITE_FLUSH_DELAY_MS = reactNative.Platform.OS === 'ios' ? 24 : 30;
|
|
@@ -316,6 +365,17 @@ const WEDGED_WRITE_MESSAGE = 'BLE write timeout after';
|
|
|
316
365
|
const isWedgedWriteError = (error) => (error === null || error === void 0 ? void 0 : error.errorCode) === hdShared.HardwareErrorCode.BleWriteCharacteristicError &&
|
|
317
366
|
typeof (error === null || error === void 0 ? void 0 : error.message) === 'string' &&
|
|
318
367
|
error.message.startsWith(WEDGED_WRITE_MESSAGE);
|
|
368
|
+
const shouldRethrowProtocolProbeError = (error) => {
|
|
369
|
+
const code = error === null || error === void 0 ? void 0 : error.errorCode;
|
|
370
|
+
return (hdShared.isBleStaleBondHardwareError(error) ||
|
|
371
|
+
isNativeBleDisconnectError(error) ||
|
|
372
|
+
code === hdShared.HardwareErrorCode.BleDeviceNotBonded ||
|
|
373
|
+
code === hdShared.HardwareErrorCode.BleDeviceBondedCanceled ||
|
|
374
|
+
code === hdShared.HardwareErrorCode.BleDeviceDisconnected ||
|
|
375
|
+
code === hdShared.HardwareErrorCode.BleCharacteristicNotifyError ||
|
|
376
|
+
code === hdShared.HardwareErrorCode.BleCharacteristicNotifyChangeFailure ||
|
|
377
|
+
code === hdShared.HardwareErrorCode.BleWriteCharacteristicError);
|
|
378
|
+
};
|
|
319
379
|
const BLE_WRITE_TIMEOUT_MANAGER_RESET_THRESHOLD = 2;
|
|
320
380
|
const DEVICE_SCAN_TIMEOUT_MS = 3000;
|
|
321
381
|
const IOS_NOTIFY_READY_DELAY_MS = 150;
|
|
@@ -474,6 +534,7 @@ class ReactNativeBleTransport {
|
|
|
474
534
|
this.androidPriorityResetTimers = new Map();
|
|
475
535
|
this.nextMonitorToken = 1;
|
|
476
536
|
this.lifecycleOperations = new Map();
|
|
537
|
+
this.scanCleanups = new Set();
|
|
477
538
|
this.scanTimeout = (_a = options.scanTimeout) !== null && _a !== void 0 ? _a : DEVICE_SCAN_TIMEOUT_MS;
|
|
478
539
|
}
|
|
479
540
|
init(logger, emitter) {
|
|
@@ -502,10 +563,38 @@ class ReactNativeBleTransport {
|
|
|
502
563
|
listen() {
|
|
503
564
|
}
|
|
504
565
|
getPlxManager() {
|
|
505
|
-
|
|
506
|
-
|
|
507
|
-
|
|
508
|
-
|
|
566
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
567
|
+
while (bleManagerResetPromise) {
|
|
568
|
+
yield this.waitForManagerReset();
|
|
569
|
+
}
|
|
570
|
+
if (this.stopped)
|
|
571
|
+
throw hdShared.ERRORS.TypedError(hdShared.HardwareErrorCode.BleDeviceDisconnected);
|
|
572
|
+
if (!this.blePlxManager)
|
|
573
|
+
this.blePlxManager = new reactNativeBlePlx.BleManager();
|
|
574
|
+
return this.blePlxManager;
|
|
575
|
+
});
|
|
576
|
+
}
|
|
577
|
+
waitForManagerReset() {
|
|
578
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
579
|
+
if (!bleManagerResetPromise)
|
|
580
|
+
return;
|
|
581
|
+
let timeout;
|
|
582
|
+
try {
|
|
583
|
+
yield Promise.race([
|
|
584
|
+
bleManagerResetPromise,
|
|
585
|
+
new Promise((_, reject) => {
|
|
586
|
+
timeout = setTimeout(() => reject(this.createWedgedBleSetupError()), BLE_CONNECT_TIMEOUT_MS);
|
|
587
|
+
}),
|
|
588
|
+
]);
|
|
589
|
+
}
|
|
590
|
+
catch (_a) {
|
|
591
|
+
throw this.createWedgedBleSetupError();
|
|
592
|
+
}
|
|
593
|
+
finally {
|
|
594
|
+
if (timeout)
|
|
595
|
+
clearTimeout(timeout);
|
|
596
|
+
}
|
|
597
|
+
});
|
|
509
598
|
}
|
|
510
599
|
resolveCharacteristics(device) {
|
|
511
600
|
return __awaiter(this, void 0, void 0, function* () {
|
|
@@ -670,30 +759,55 @@ class ReactNativeBleTransport {
|
|
|
670
759
|
}
|
|
671
760
|
enumerate() {
|
|
672
761
|
return __awaiter(this, void 0, void 0, function* () {
|
|
673
|
-
|
|
674
|
-
|
|
675
|
-
|
|
676
|
-
|
|
677
|
-
|
|
678
|
-
|
|
679
|
-
|
|
680
|
-
|
|
681
|
-
|
|
682
|
-
|
|
683
|
-
|
|
684
|
-
if (reactNative.
|
|
685
|
-
|
|
686
|
-
|
|
687
|
-
reactNative.PermissionsAndroid.PERMISSIONS.BLUETOOTH_CONNECT,
|
|
688
|
-
reactNative.PermissionsAndroid.PERMISSIONS.BLUETOOTH_SCAN,
|
|
689
|
-
]);
|
|
690
|
-
Log === null || Log === void 0 ? void 0 : Log.debug('requesting permissions, result: ', resultConnect);
|
|
691
|
-
if (resultConnect[reactNative.PermissionsAndroid.PERMISSIONS.BLUETOOTH_CONNECT] !== 'granted' ||
|
|
692
|
-
resultConnect[reactNative.PermissionsAndroid.PERMISSIONS.BLUETOOTH_SCAN] !== 'granted') {
|
|
693
|
-
reject(hdShared.ERRORS.TypedError(hdShared.HardwareErrorCode.BlePermissionError));
|
|
694
|
-
return;
|
|
695
|
-
}
|
|
762
|
+
const scanStartedAt = Date.now();
|
|
763
|
+
let firstDeviceMs;
|
|
764
|
+
const blePlxManager = yield this.getPlxManager();
|
|
765
|
+
yield subscribeBleOn(blePlxManager);
|
|
766
|
+
if (reactNative.Platform.OS === 'android' && reactNative.Platform.Version >= 31) {
|
|
767
|
+
Log === null || Log === void 0 ? void 0 : Log.debug('requesting permissions, please wait...');
|
|
768
|
+
const resultConnect = yield reactNative.PermissionsAndroid.requestMultiple([
|
|
769
|
+
reactNative.PermissionsAndroid.PERMISSIONS.BLUETOOTH_CONNECT,
|
|
770
|
+
reactNative.PermissionsAndroid.PERMISSIONS.BLUETOOTH_SCAN,
|
|
771
|
+
]);
|
|
772
|
+
Log === null || Log === void 0 ? void 0 : Log.debug('requesting permissions, result: ', resultConnect);
|
|
773
|
+
if (resultConnect[reactNative.PermissionsAndroid.PERMISSIONS.BLUETOOTH_CONNECT] !== 'granted' ||
|
|
774
|
+
resultConnect[reactNative.PermissionsAndroid.PERMISSIONS.BLUETOOTH_SCAN] !== 'granted') {
|
|
775
|
+
throw hdShared.ERRORS.TypedError(hdShared.HardwareErrorCode.BlePermissionError);
|
|
696
776
|
}
|
|
777
|
+
}
|
|
778
|
+
if (this.stopped)
|
|
779
|
+
throw hdShared.ERRORS.TypedError(hdShared.HardwareErrorCode.BleDeviceDisconnected);
|
|
780
|
+
return new Promise((resolve, reject) => {
|
|
781
|
+
const deviceList = [];
|
|
782
|
+
let finished = false;
|
|
783
|
+
let scanCleanup;
|
|
784
|
+
const finishScan = (error) => {
|
|
785
|
+
if (scanCleanup)
|
|
786
|
+
return scanCleanup;
|
|
787
|
+
finished = true;
|
|
788
|
+
clearScanTimer();
|
|
789
|
+
scanCleanup = this.runNativeTeardown('scan', blePlxManager, () => __awaiter(this, void 0, void 0, function* () {
|
|
790
|
+
yield blePlxManager.stopDeviceScan();
|
|
791
|
+
})).then(() => {
|
|
792
|
+
this.scanCleanups.delete(cancelScan);
|
|
793
|
+
if (error)
|
|
794
|
+
reject(error);
|
|
795
|
+
else
|
|
796
|
+
resolve(deviceList);
|
|
797
|
+
});
|
|
798
|
+
return scanCleanup;
|
|
799
|
+
};
|
|
800
|
+
const cancelScan = () => finishScan(hdShared.ERRORS.TypedError(hdShared.HardwareErrorCode.BleDeviceDisconnected));
|
|
801
|
+
this.scanCleanups.add(cancelScan);
|
|
802
|
+
const clearScanTimer = timer.timeout(() => {
|
|
803
|
+
Log === null || Log === void 0 ? void 0 : Log.debug('[ReactNativeBleTransport] scan completed', {
|
|
804
|
+
elapsedMs: Date.now() - scanStartedAt,
|
|
805
|
+
firstDeviceMs,
|
|
806
|
+
deviceCount: deviceList.length,
|
|
807
|
+
scanWindowMs: this.scanTimeout,
|
|
808
|
+
});
|
|
809
|
+
finishScan();
|
|
810
|
+
}, this.scanTimeout);
|
|
697
811
|
blePlxManager.startDeviceScan(getBluetoothServiceUuids(), {
|
|
698
812
|
allowDuplicates: true,
|
|
699
813
|
scanMode: reactNativeBlePlx.ScanMode.LowLatency,
|
|
@@ -702,19 +816,17 @@ class ReactNativeBleTransport {
|
|
|
702
816
|
if (error) {
|
|
703
817
|
Log === null || Log === void 0 ? void 0 : Log.debug('ble scan error: ', error);
|
|
704
818
|
if ([reactNativeBlePlx.BleErrorCode.BluetoothPoweredOff, reactNativeBlePlx.BleErrorCode.BluetoothInUnknownState].includes(error.errorCode)) {
|
|
705
|
-
|
|
819
|
+
finishScan(hdShared.ERRORS.TypedError(hdShared.HardwareErrorCode.BlePermissionError));
|
|
706
820
|
}
|
|
707
821
|
else if (error.errorCode === reactNativeBlePlx.BleErrorCode.BluetoothUnauthorized) {
|
|
708
|
-
|
|
822
|
+
finishScan(hdShared.ERRORS.TypedError(hdShared.HardwareErrorCode.BleLocationError));
|
|
709
823
|
}
|
|
710
824
|
else if (error.errorCode === reactNativeBlePlx.BleErrorCode.LocationServicesDisabled) {
|
|
711
|
-
|
|
712
|
-
}
|
|
713
|
-
else if (error.errorCode === reactNativeBlePlx.BleErrorCode.ScanStartFailed) {
|
|
714
|
-
timer.timeout(() => { }, this.scanTimeout);
|
|
825
|
+
finishScan(hdShared.ERRORS.TypedError(hdShared.HardwareErrorCode.BleLocationServicesDisabled));
|
|
715
826
|
}
|
|
827
|
+
else if (error.errorCode === reactNativeBlePlx.BleErrorCode.ScanStartFailed) ;
|
|
716
828
|
else {
|
|
717
|
-
|
|
829
|
+
finishScan(hdShared.ERRORS.TypedError(hdShared.HardwareErrorCode.BleScanError, (_a = error.reason) !== null && _a !== void 0 ? _a : ''));
|
|
718
830
|
}
|
|
719
831
|
return;
|
|
720
832
|
}
|
|
@@ -739,6 +851,8 @@ class ReactNativeBleTransport {
|
|
|
739
851
|
});
|
|
740
852
|
}
|
|
741
853
|
});
|
|
854
|
+
if (finished)
|
|
855
|
+
return;
|
|
742
856
|
getConnectedDeviceIds(reactNative.Platform.OS === 'ios' ? getBluetoothServiceUuids() : []).then(devices => {
|
|
743
857
|
for (const device of devices) {
|
|
744
858
|
const localName = 'localName' in device && typeof device.localName === 'string'
|
|
@@ -754,10 +868,11 @@ class ReactNativeBleTransport {
|
|
|
754
868
|
addDevice(device);
|
|
755
869
|
}
|
|
756
870
|
}
|
|
757
|
-
});
|
|
871
|
+
}, error => Log === null || Log === void 0 ? void 0 : Log.debug('search connected peripheral failed:', error));
|
|
758
872
|
const addDevice = (device) => {
|
|
759
873
|
var _a;
|
|
760
|
-
if (deviceList.every(d => d.id !== device.id)) {
|
|
874
|
+
if (!finished && deviceList.every(d => d.id !== device.id)) {
|
|
875
|
+
firstDeviceMs !== null && firstDeviceMs !== void 0 ? firstDeviceMs : (firstDeviceMs = Date.now() - scanStartedAt);
|
|
761
876
|
const displayName = (_a = getDeviceDisplayName(device)) !== null && _a !== void 0 ? _a : 'Unknown BLE Device';
|
|
762
877
|
deviceList.push(Object.assign(Object.assign({}, device), { name: displayName, commType: 'ble' }));
|
|
763
878
|
Log === null || Log === void 0 ? void 0 : Log.debug('[ReactNativeBleTransport] OneKey BLE device discovered', {
|
|
@@ -767,16 +882,14 @@ class ReactNativeBleTransport {
|
|
|
767
882
|
});
|
|
768
883
|
}
|
|
769
884
|
};
|
|
770
|
-
|
|
771
|
-
blePlxManager.stopDeviceScan();
|
|
772
|
-
resolve(deviceList);
|
|
773
|
-
}, this.scanTimeout);
|
|
774
|
-
}));
|
|
885
|
+
});
|
|
775
886
|
});
|
|
776
887
|
}
|
|
777
888
|
installTransportForAcquire(uuid, device, characteristics) {
|
|
778
889
|
return __awaiter(this, void 0, void 0, function* () {
|
|
779
890
|
const { writeCharacteristic, notifyCharacteristic } = characteristics !== null && characteristics !== void 0 ? characteristics : (yield this.resolveCharacteristicsWithTimeout(uuid, device));
|
|
891
|
+
if (this.stopped)
|
|
892
|
+
throw hdShared.ERRORS.TypedError(hdShared.HardwareErrorCode.BleDeviceDisconnected);
|
|
780
893
|
const transport$1 = new BleTransport(device, writeCharacteristic, notifyCharacteristic);
|
|
781
894
|
transport$1.mtuSize = typeof device.mtu === 'number' ? device.mtu : undefined;
|
|
782
895
|
const monitorToken = this.nextMonitorToken;
|
|
@@ -797,17 +910,23 @@ class ReactNativeBleTransport {
|
|
|
797
910
|
else if (reactNative.Platform.OS === 'android') {
|
|
798
911
|
yield delay(ANDROID_NOTIFY_READY_DELAY_MS);
|
|
799
912
|
}
|
|
913
|
+
if (this.stopped)
|
|
914
|
+
throw hdShared.ERRORS.TypedError(hdShared.HardwareErrorCode.BleDeviceDisconnected);
|
|
800
915
|
const initialMtu = transport$1.mtuSize;
|
|
801
916
|
let refreshAttempts = 0;
|
|
802
917
|
if ((reactNative.Platform.OS === 'ios' || reactNative.Platform.OS === 'android') &&
|
|
803
918
|
shouldRefreshNegotiatedMtu(transport$1.mtuSize)) {
|
|
804
919
|
refreshAttempts += 1;
|
|
805
920
|
let refreshedDevice = yield requestNegotiatedMtu(transport$1.device, 'servicesAndNotifyReady', 1);
|
|
921
|
+
if (this.stopped)
|
|
922
|
+
throw hdShared.ERRORS.TypedError(hdShared.HardwareErrorCode.BleDeviceDisconnected);
|
|
806
923
|
transport$1.device = refreshedDevice;
|
|
807
924
|
transport$1.mtuSize =
|
|
808
925
|
typeof refreshedDevice.mtu === 'number' ? refreshedDevice.mtu : transport$1.mtuSize;
|
|
809
926
|
if (shouldRefreshNegotiatedMtu(transport$1.mtuSize)) {
|
|
810
927
|
yield delay(BLE_MTU_REFRESH_RETRY_DELAY_MS);
|
|
928
|
+
if (this.stopped)
|
|
929
|
+
throw hdShared.ERRORS.TypedError(hdShared.HardwareErrorCode.BleDeviceDisconnected);
|
|
811
930
|
refreshAttempts += 1;
|
|
812
931
|
refreshedDevice = yield requestNegotiatedMtu(transport$1.device, 'servicesAndNotifyReady', 2);
|
|
813
932
|
transport$1.device = refreshedDevice;
|
|
@@ -815,6 +934,8 @@ class ReactNativeBleTransport {
|
|
|
815
934
|
typeof refreshedDevice.mtu === 'number' ? refreshedDevice.mtu : transport$1.mtuSize;
|
|
816
935
|
}
|
|
817
936
|
}
|
|
937
|
+
if (this.stopped)
|
|
938
|
+
throw hdShared.ERRORS.TypedError(hdShared.HardwareErrorCode.BleDeviceDisconnected);
|
|
818
939
|
Log === null || Log === void 0 ? void 0 : Log.debug('[ReactNativeBleTransport] BLE MTU ready', {
|
|
819
940
|
platform: reactNative.Platform.OS,
|
|
820
941
|
requested: getRequestedBleMtu(),
|
|
@@ -837,6 +958,8 @@ class ReactNativeBleTransport {
|
|
|
837
958
|
acquireUnlocked(input) {
|
|
838
959
|
var _a;
|
|
839
960
|
return __awaiter(this, void 0, void 0, function* () {
|
|
961
|
+
if (this.stopped)
|
|
962
|
+
throw hdShared.ERRORS.TypedError(hdShared.HardwareErrorCode.BleDeviceDisconnected);
|
|
840
963
|
const { uuid, forceCleanRunPromise, expectedProtocol, skipProtocolProbe } = input;
|
|
841
964
|
const shouldMapProtocolV2StaleBond = expectedProtocol
|
|
842
965
|
? expectedProtocol === 'V2'
|
|
@@ -871,6 +994,8 @@ class ReactNativeBleTransport {
|
|
|
871
994
|
if (isCachedDeviceConnected &&
|
|
872
995
|
cachedProtocol &&
|
|
873
996
|
(!expectedProtocol || cachedProtocol === expectedProtocol)) {
|
|
997
|
+
if (this.stopped)
|
|
998
|
+
throw hdShared.ERRORS.TypedError(hdShared.HardwareErrorCode.BleDeviceDisconnected);
|
|
874
999
|
Log === null || Log === void 0 ? void 0 : Log.debug('[ReactNativeBleTransport] reuse cached BLE transport:', uuid, cachedProtocol);
|
|
875
1000
|
return { uuid, protocolType: cachedProtocol };
|
|
876
1001
|
}
|
|
@@ -894,6 +1019,27 @@ class ReactNativeBleTransport {
|
|
|
894
1019
|
Log === null || Log === void 0 ? void 0 : Log.debug('subscribeBleOn error: ', error);
|
|
895
1020
|
throw error;
|
|
896
1021
|
}
|
|
1022
|
+
if (this.stopped)
|
|
1023
|
+
throw hdShared.ERRORS.TypedError(hdShared.HardwareErrorCode.BleDeviceDisconnected);
|
|
1024
|
+
if (reactNative.Platform.OS === 'android') {
|
|
1025
|
+
try {
|
|
1026
|
+
const bondState = yield pairDevice(uuid);
|
|
1027
|
+
if (bondState.bonding) {
|
|
1028
|
+
yield onDeviceBondState(uuid);
|
|
1029
|
+
}
|
|
1030
|
+
else if (!bondState.bonded) {
|
|
1031
|
+
throw hdShared.ERRORS.TypedError(hdShared.HardwareErrorCode.BleDeviceNotBonded, 'device is not bonded');
|
|
1032
|
+
}
|
|
1033
|
+
}
|
|
1034
|
+
catch (error) {
|
|
1035
|
+
yield this.runNativeTeardown(uuid, blePlxManager, () => __awaiter(this, void 0, void 0, function* () {
|
|
1036
|
+
yield this.runBestEffortNativeOperation('bond failure: cancel manager connection', () => blePlxManager.cancelDeviceConnection(uuid));
|
|
1037
|
+
}));
|
|
1038
|
+
throw error;
|
|
1039
|
+
}
|
|
1040
|
+
}
|
|
1041
|
+
if (this.stopped)
|
|
1042
|
+
throw hdShared.ERRORS.TypedError(hdShared.HardwareErrorCode.BleDeviceDisconnected);
|
|
897
1043
|
if (!device) {
|
|
898
1044
|
const devices = yield blePlxManager.devices([uuid]);
|
|
899
1045
|
[device] = devices;
|
|
@@ -965,33 +1111,27 @@ class ReactNativeBleTransport {
|
|
|
965
1111
|
}
|
|
966
1112
|
}
|
|
967
1113
|
}
|
|
968
|
-
if (
|
|
969
|
-
|
|
970
|
-
|
|
971
|
-
|
|
972
|
-
|
|
973
|
-
|
|
974
|
-
|
|
975
|
-
|
|
976
|
-
|
|
977
|
-
|
|
978
|
-
|
|
979
|
-
throw hdShared.ERRORS.TypedError(hdShared.HardwareErrorCode.BleDeviceNotBonded, 'device is not bonded');
|
|
980
|
-
}
|
|
981
|
-
}
|
|
982
|
-
catch (error) {
|
|
983
|
-
yield this.runNativeTeardown(uuid, blePlxManager, () => __awaiter(this, void 0, void 0, function* () {
|
|
984
|
-
yield Promise.all([
|
|
985
|
-
this.runBestEffortNativeOperation('bond failure: cancel manager connection', () => blePlxManager.cancelDeviceConnection(uuid)),
|
|
986
|
-
this.runBestEffortNativeOperation('bond failure: cancel device connection', () => connectedDevice.cancelConnection()),
|
|
987
|
-
]);
|
|
988
|
-
}));
|
|
989
|
-
throw error;
|
|
990
|
-
}
|
|
1114
|
+
if (this.stopped)
|
|
1115
|
+
throw hdShared.ERRORS.TypedError(hdShared.HardwareErrorCode.BleDeviceDisconnected);
|
|
1116
|
+
if (reactNative.Platform.OS === 'android' && !(yield device.isConnected().catch(() => false))) {
|
|
1117
|
+
const disconnectedDevice = device;
|
|
1118
|
+
yield this.runNativeTeardown(uuid, blePlxManager, () => __awaiter(this, void 0, void 0, function* () {
|
|
1119
|
+
yield Promise.all([
|
|
1120
|
+
this.runBestEffortNativeOperation('connect failure: cancel manager connection', () => blePlxManager.cancelDeviceConnection(uuid)),
|
|
1121
|
+
this.runBestEffortNativeOperation('connect failure: cancel device connection', () => disconnectedDevice.cancelConnection()),
|
|
1122
|
+
]);
|
|
1123
|
+
}));
|
|
1124
|
+
throw hdShared.ERRORS.TypedError(hdShared.HardwareErrorCode.BleConnectedError, 'device is not connected');
|
|
991
1125
|
}
|
|
1126
|
+
if (this.stopped)
|
|
1127
|
+
throw hdShared.ERRORS.TypedError(hdShared.HardwareErrorCode.BleDeviceDisconnected);
|
|
992
1128
|
device = yield resolveNegotiatedMtu(device);
|
|
1129
|
+
if (this.stopped)
|
|
1130
|
+
throw hdShared.ERRORS.TypedError(hdShared.HardwareErrorCode.BleDeviceDisconnected);
|
|
993
1131
|
const acquiredDevice = device;
|
|
994
1132
|
const { writeCharacteristic, notifyCharacteristic } = yield this.resolveCharacteristicsWithTimeout(uuid, acquiredDevice);
|
|
1133
|
+
if (this.stopped)
|
|
1134
|
+
throw hdShared.ERRORS.TypedError(hdShared.HardwareErrorCode.BleDeviceDisconnected);
|
|
995
1135
|
const protocolHint = expectedProtocol
|
|
996
1136
|
? undefined
|
|
997
1137
|
: (_a = input.protocolHint) !== null && _a !== void 0 ? _a : this.deviceProtocolHints.get(uuid);
|
|
@@ -1034,6 +1174,8 @@ class ReactNativeBleTransport {
|
|
|
1034
1174
|
const protocolType = yield this.detectProtocol(uuid, expectedProtocol, protocolHint, () => __awaiter(this, void 0, void 0, function* () {
|
|
1035
1175
|
yield this.installTransportForAcquire(uuid, acquiredDevice);
|
|
1036
1176
|
}));
|
|
1177
|
+
if (this.stopped)
|
|
1178
|
+
throw hdShared.ERRORS.TypedError(hdShared.HardwareErrorCode.BleDeviceDisconnected);
|
|
1037
1179
|
const currentTransport = transportCache[uuid];
|
|
1038
1180
|
if (!currentTransport) {
|
|
1039
1181
|
throw hdShared.ERRORS.TypedError(hdShared.HardwareErrorCode.TransportNotFound);
|
|
@@ -1042,7 +1184,7 @@ class ReactNativeBleTransport {
|
|
|
1042
1184
|
return { uuid, protocolType };
|
|
1043
1185
|
}
|
|
1044
1186
|
catch (error) {
|
|
1045
|
-
if (hdShared.isBleStaleBondHardwareError(error)) {
|
|
1187
|
+
if (hdShared.isBleStaleBondHardwareError(error) || shouldRethrowProtocolProbeError(error)) {
|
|
1046
1188
|
yield this.disconnectUnlocked(uuid);
|
|
1047
1189
|
}
|
|
1048
1190
|
else {
|
|
@@ -1455,7 +1597,42 @@ class ReactNativeBleTransport {
|
|
|
1455
1597
|
});
|
|
1456
1598
|
}
|
|
1457
1599
|
stop() {
|
|
1600
|
+
var _a;
|
|
1601
|
+
if (this.stopPromise)
|
|
1602
|
+
return this.stopPromise;
|
|
1458
1603
|
this.stopped = true;
|
|
1604
|
+
const deviceIds = new Set([
|
|
1605
|
+
...this.monitorTokens.keys(),
|
|
1606
|
+
...this.sessionProtocols.keys(),
|
|
1607
|
+
...this.lifecycleOperations.keys(),
|
|
1608
|
+
...(this.runPromiseDeviceId ? [this.runPromiseDeviceId] : []),
|
|
1609
|
+
]);
|
|
1610
|
+
const scans = Array.from(this.scanCleanups, cleanup => cleanup());
|
|
1611
|
+
this.androidPriorityResetTimers.forEach(timeout => clearTimeout(timeout));
|
|
1612
|
+
this.androidPriorityResetTimers.clear();
|
|
1613
|
+
this.androidHighPriorityDevices.clear();
|
|
1614
|
+
const error = hdShared.ERRORS.TypedError(hdShared.HardwareErrorCode.BleDeviceDisconnected);
|
|
1615
|
+
(_a = this.runPromise) === null || _a === void 0 ? void 0 : _a.reject(error);
|
|
1616
|
+
this.runPromise = null;
|
|
1617
|
+
this.runPromiseDeviceId = null;
|
|
1618
|
+
deviceIds.forEach(uuid => this.rejectProtocolV2Frames(uuid, error));
|
|
1619
|
+
const manager = this.blePlxManager;
|
|
1620
|
+
const pendingConnections = manager
|
|
1621
|
+
? Array.from(this.lifecycleOperations.keys(), uuid => this.runNativeTeardown(uuid, manager, () => __awaiter(this, void 0, void 0, function* () {
|
|
1622
|
+
yield this.runBestEffortNativeOperation('stop: cancel pending device connection', () => manager.cancelDeviceConnection(uuid));
|
|
1623
|
+
})))
|
|
1624
|
+
: [];
|
|
1625
|
+
this.stopPromise = Promise.all([
|
|
1626
|
+
...scans,
|
|
1627
|
+
...pendingConnections,
|
|
1628
|
+
...Array.from(deviceIds, uuid => this.disconnect(uuid)),
|
|
1629
|
+
]).then(() => __awaiter(this, void 0, void 0, function* () {
|
|
1630
|
+
yield this.protocolV2Links.invalidateAllLinks('React Native BLE transport stopped');
|
|
1631
|
+
yield this.waitForManagerReset();
|
|
1632
|
+
this.blePlxManager = undefined;
|
|
1633
|
+
this.emitter = undefined;
|
|
1634
|
+
}));
|
|
1635
|
+
return this.stopPromise;
|
|
1459
1636
|
}
|
|
1460
1637
|
disconnect(session) {
|
|
1461
1638
|
return __awaiter(this, void 0, void 0, function* () {
|
|
@@ -1585,13 +1762,27 @@ class ReactNativeBleTransport {
|
|
|
1585
1762
|
});
|
|
1586
1763
|
}
|
|
1587
1764
|
cancel() {
|
|
1588
|
-
|
|
1589
|
-
|
|
1590
|
-
|
|
1591
|
-
|
|
1765
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
1766
|
+
Log === null || Log === void 0 ? void 0 : Log.debug('transport-react-native transport cancel');
|
|
1767
|
+
const pending = this.runPromise;
|
|
1768
|
+
const deviceId = this.runPromiseDeviceId;
|
|
1769
|
+
if (pending) {
|
|
1770
|
+
pending.reject(hdShared.ERRORS.TypedError(hdShared.HardwareErrorCode.CallQueueActionCancelled));
|
|
1771
|
+
if (this.runPromise === pending) {
|
|
1772
|
+
this.runPromise = null;
|
|
1773
|
+
this.runPromiseDeviceId = null;
|
|
1774
|
+
}
|
|
1775
|
+
if (deviceId)
|
|
1776
|
+
yield this.disconnect(deviceId);
|
|
1777
|
+
}
|
|
1778
|
+
});
|
|
1592
1779
|
}
|
|
1593
1780
|
connectWithTimeout(uuid, connect) {
|
|
1594
1781
|
return __awaiter(this, void 0, void 0, function* () {
|
|
1782
|
+
if (this.stopped)
|
|
1783
|
+
throw hdShared.ERRORS.TypedError(hdShared.HardwareErrorCode.BleDeviceDisconnected);
|
|
1784
|
+
const startedAt = Date.now();
|
|
1785
|
+
let succeeded = false;
|
|
1595
1786
|
let timer;
|
|
1596
1787
|
let timedOut = false;
|
|
1597
1788
|
const pending = connect();
|
|
@@ -1606,6 +1797,7 @@ class ReactNativeBleTransport {
|
|
|
1606
1797
|
}, BLE_CONNECT_TIMEOUT_MS);
|
|
1607
1798
|
}),
|
|
1608
1799
|
]);
|
|
1800
|
+
succeeded = true;
|
|
1609
1801
|
return result;
|
|
1610
1802
|
}
|
|
1611
1803
|
catch (error) {
|
|
@@ -1620,11 +1812,19 @@ class ReactNativeBleTransport {
|
|
|
1620
1812
|
finally {
|
|
1621
1813
|
if (timer)
|
|
1622
1814
|
clearTimeout(timer);
|
|
1815
|
+
Log === null || Log === void 0 ? void 0 : Log.debug('[ReactNativeBleTransport] connect completed', {
|
|
1816
|
+
connectIdSuffix: uuid.slice(-8),
|
|
1817
|
+
elapsedMs: Date.now() - startedAt,
|
|
1818
|
+
succeeded,
|
|
1819
|
+
backstopExpired: timedOut,
|
|
1820
|
+
});
|
|
1623
1821
|
}
|
|
1624
1822
|
});
|
|
1625
1823
|
}
|
|
1626
1824
|
resolveCharacteristicsWithTimeout(uuid, device) {
|
|
1627
1825
|
return __awaiter(this, void 0, void 0, function* () {
|
|
1826
|
+
const startedAt = Date.now();
|
|
1827
|
+
let succeeded = false;
|
|
1628
1828
|
let timer;
|
|
1629
1829
|
let timedOut = false;
|
|
1630
1830
|
const pending = this.resolveCharacteristics(device);
|
|
@@ -1640,6 +1840,7 @@ class ReactNativeBleTransport {
|
|
|
1640
1840
|
}),
|
|
1641
1841
|
]);
|
|
1642
1842
|
this.connectionSetupTimeoutCounts.delete(uuid);
|
|
1843
|
+
succeeded = true;
|
|
1643
1844
|
return result;
|
|
1644
1845
|
}
|
|
1645
1846
|
catch (error) {
|
|
@@ -1654,6 +1855,12 @@ class ReactNativeBleTransport {
|
|
|
1654
1855
|
finally {
|
|
1655
1856
|
if (timer)
|
|
1656
1857
|
clearTimeout(timer);
|
|
1858
|
+
Log === null || Log === void 0 ? void 0 : Log.debug('[ReactNativeBleTransport] GATT setup completed', {
|
|
1859
|
+
connectIdSuffix: uuid.slice(-8),
|
|
1860
|
+
elapsedMs: Date.now() - startedAt,
|
|
1861
|
+
succeeded,
|
|
1862
|
+
backstopExpired: timedOut,
|
|
1863
|
+
});
|
|
1657
1864
|
}
|
|
1658
1865
|
});
|
|
1659
1866
|
}
|
|
@@ -1755,6 +1962,8 @@ class ReactNativeBleTransport {
|
|
|
1755
1962
|
}
|
|
1756
1963
|
}
|
|
1757
1964
|
resetPlxManager() {
|
|
1965
|
+
if (bleManagerResetPromise)
|
|
1966
|
+
return;
|
|
1758
1967
|
const manager = this.blePlxManager;
|
|
1759
1968
|
this.blePlxManager = undefined;
|
|
1760
1969
|
const reason = 'React Native BLE manager reset';
|
|
@@ -1796,12 +2005,20 @@ class ReactNativeBleTransport {
|
|
|
1796
2005
|
this.connectionSetupTimeoutCounts.clear();
|
|
1797
2006
|
this.monitorTokens.clear();
|
|
1798
2007
|
this.protocolV2Assemblers.clear();
|
|
2008
|
+
let reset;
|
|
1799
2009
|
try {
|
|
1800
|
-
manager === null || manager === void 0 ? void 0 : manager.destroy();
|
|
2010
|
+
reset = Promise.resolve(manager === null || manager === void 0 ? void 0 : manager.destroy());
|
|
1801
2011
|
}
|
|
1802
2012
|
catch (error) {
|
|
1803
|
-
|
|
2013
|
+
reset = Promise.reject(error);
|
|
1804
2014
|
}
|
|
2015
|
+
bleManagerResetPromise = reset;
|
|
2016
|
+
reset.then(() => {
|
|
2017
|
+
if (bleManagerResetPromise === reset)
|
|
2018
|
+
bleManagerResetPromise = undefined;
|
|
2019
|
+
}, error => {
|
|
2020
|
+
Log === null || Log === void 0 ? void 0 : Log.error('[ReactNativeBleTransport] BLE manager destroy failed:', error);
|
|
2021
|
+
});
|
|
1805
2022
|
}
|
|
1806
2023
|
createProtocolMismatchError(expected) {
|
|
1807
2024
|
return hdShared.ERRORS.TypedError(hdShared.HardwareErrorCode.RuntimeError, `Device protocol mismatch: expected ${expected}, but device did not respond to expected protocol`);
|
|
@@ -1951,7 +2168,7 @@ class ReactNativeBleTransport {
|
|
|
1951
2168
|
catch (error) {
|
|
1952
2169
|
this.clearProbeProtocol(uuid, 'V1');
|
|
1953
2170
|
Log === null || Log === void 0 ? void 0 : Log.debug('[ReactNativeBleTransport] Protocol V1 GetFeatures probe failed:', error);
|
|
1954
|
-
if (
|
|
2171
|
+
if (shouldRethrowProtocolProbeError(error)) {
|
|
1955
2172
|
throw error;
|
|
1956
2173
|
}
|
|
1957
2174
|
return false;
|
|
@@ -1977,7 +2194,7 @@ class ReactNativeBleTransport {
|
|
|
1977
2194
|
(_a = this.protocolV2Assemblers.get(uuid)) === null || _a === void 0 ? void 0 : _a.reset();
|
|
1978
2195
|
this.resetProtocolV2Frames(uuid);
|
|
1979
2196
|
},
|
|
1980
|
-
shouldRethrow:
|
|
2197
|
+
shouldRethrow: shouldRethrowProtocolProbeError,
|
|
1981
2198
|
});
|
|
1982
2199
|
if (!detected) {
|
|
1983
2200
|
this.clearProbeProtocol(uuid, 'V2');
|
|
@@ -2104,6 +2321,9 @@ class ReactNativeBleTransport {
|
|
|
2104
2321
|
this.rememberStaleBondError(uuid, bondError);
|
|
2105
2322
|
throw bondError;
|
|
2106
2323
|
}
|
|
2324
|
+
if (isNativeBleDisconnectError(error)) {
|
|
2325
|
+
throw toBleDisconnectHardwareError(error);
|
|
2326
|
+
}
|
|
2107
2327
|
if (getFirmwareUploadWriteRetryType(error) !== 'congested' ||
|
|
2108
2328
|
attempt >= FIRMWARE_UPLOAD_WRITE_MAX_RETRIES) {
|
|
2109
2329
|
throw error;
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@onekeyfe/hd-transport-react-native",
|
|
3
|
-
"version": "1.2.2-alpha.
|
|
3
|
+
"version": "1.2.2-alpha.107",
|
|
4
4
|
"homepage": "https://github.com/OneKeyHQ/hardware-js-sdk#readme",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"main": "dist/index.js",
|
|
@@ -20,11 +20,11 @@
|
|
|
20
20
|
"lint:fix": "eslint . --fix"
|
|
21
21
|
},
|
|
22
22
|
"dependencies": {
|
|
23
|
-
"@onekeyfe/hd-core": "1.2.2-alpha.
|
|
24
|
-
"@onekeyfe/hd-shared": "1.2.2-alpha.
|
|
25
|
-
"@onekeyfe/hd-transport": "1.2.2-alpha.
|
|
26
|
-
"@onekeyfe/react-native-ble-utils": "^0.1.
|
|
23
|
+
"@onekeyfe/hd-core": "1.2.2-alpha.107",
|
|
24
|
+
"@onekeyfe/hd-shared": "1.2.2-alpha.107",
|
|
25
|
+
"@onekeyfe/hd-transport": "1.2.2-alpha.107",
|
|
26
|
+
"@onekeyfe/react-native-ble-utils": "^0.1.7",
|
|
27
27
|
"react-native-ble-plx": "3.5.1"
|
|
28
28
|
},
|
|
29
|
-
"gitHead": "
|
|
29
|
+
"gitHead": "0139b6e93599824f13f1e7121a70a59ec424f466"
|
|
30
30
|
}
|