@onekeyfe/hd-transport-react-native 1.2.2-alpha.104 → 1.2.2-alpha.106
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/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 +205 -50
- package/package.json +5 -5
- package/src/__tests__/bleNativeDisconnect.test.ts +33 -0
- package/src/__tests__/connectTimeout.test.ts +110 -2
- package/src/__tests__/protocolV2Link.test.ts +112 -2
- package/src/__tests__/staleCallTimeout.test.ts +34 -5
- package/src/bleNativeDisconnect.ts +40 -0
- package/src/index.ts +187 -54
package/README.md
CHANGED
|
@@ -26,4 +26,4 @@ yar update:protobuf to generate new ./messages.json and ./src/types/messages.ts
|
|
|
26
26
|
|
|
27
27
|
## Docs
|
|
28
28
|
|
|
29
|
-
Documentation is available [
|
|
29
|
+
Documentation is available [Hardware SDK Getting Started](https://developer.onekey.so/en/hardware-sdk/getting-started)
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"bleNativeDisconnect.d.ts","sourceRoot":"","sources":["../src/bleNativeDisconnect.ts"],"names":[],"mappings":"AAiBA,eAAO,MAAM,0BAA0B,UAAW,OAAO,KAAG,OAU3D,CAAC;AAEF,eAAO,MAAM,4BAA4B,UAAW,OAAO,UAU1D,CAAC"}
|
package/dist/index.d.ts
CHANGED
|
@@ -154,12 +154,15 @@ declare class ReactNativeBleTransport {
|
|
|
154
154
|
private nextMonitorToken;
|
|
155
155
|
/** Serializes transport lifecycle changes for the same physical device. */
|
|
156
156
|
private lifecycleOperations;
|
|
157
|
+
private stopPromise?;
|
|
158
|
+
private scanCleanups;
|
|
157
159
|
constructor(options: TransportOptions);
|
|
158
160
|
init(logger: any, emitter: EventEmitter): void;
|
|
159
161
|
configure(signedData: any): void;
|
|
160
162
|
configureProtocolV2(signedData: any): void;
|
|
161
163
|
listen(): void;
|
|
162
164
|
getPlxManager(): Promise<BleManager>;
|
|
165
|
+
private waitForManagerReset;
|
|
163
166
|
resolveCharacteristics(device: Device): Promise<ResolvedBleCharacteristics>;
|
|
164
167
|
attachDisconnectSubscription(transport: BleTransport, device: Device, uuid: string): void;
|
|
165
168
|
private emitDeviceDisconnect;
|
|
@@ -183,13 +186,13 @@ declare class ReactNativeBleTransport {
|
|
|
183
186
|
post(session: string, name: string, data: Record<string, unknown>): Promise<void>;
|
|
184
187
|
call(uuid: string, name: string, data: Record<string, unknown>, options?: TransportCallOptions): Promise<transport.MessageFromOneKey>;
|
|
185
188
|
private callProtocolV1;
|
|
186
|
-
stop(): void
|
|
189
|
+
stop(): Promise<void>;
|
|
187
190
|
disconnect(session: string): Promise<void>;
|
|
188
191
|
private disconnectUnlocked;
|
|
189
192
|
private runNativeTeardown;
|
|
190
193
|
private runBestEffortNativeOperation;
|
|
191
194
|
private runLifecycleOperation;
|
|
192
|
-
cancel(): void
|
|
195
|
+
cancel(): Promise<void>;
|
|
193
196
|
/** Run a native connect under the JS backstop budget. */
|
|
194
197
|
private connectWithTimeout;
|
|
195
198
|
/** Resolve the complete GATT shape under a budget so acquire() always settles. */
|
package/dist/index.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":";AAEA,OAAO,EAGL,UAAU,IAAI,aAAa,EAG5B,MAAM,sBAAsB,CAAC;AAE9B,OAAO,SAAS,EAAE,EAChB,KAAK,oBAAoB,EAIzB,KAAK,YAAY,EAKjB,KAAK,oBAAoB,EAI1B,MAAM,wBAAwB,CAAC;
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"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"}
|
package/dist/index.js
CHANGED
|
@@ -194,6 +194,27 @@ const subscribeBleOn = (bleManager, ms = 1000) => new Promise((resolve, reject)
|
|
|
194
194
|
}, ms);
|
|
195
195
|
});
|
|
196
196
|
|
|
197
|
+
const BLE_PLX_DEVICE_DISCONNECTED = 201;
|
|
198
|
+
const IOS_PERIPHERAL_DISCONNECTED = 7;
|
|
199
|
+
const nativeErrorText$1 = (error) => [error.reason, error.message]
|
|
200
|
+
.filter((value) => typeof value === 'string')
|
|
201
|
+
.join(' ');
|
|
202
|
+
const isNativeBleDisconnectError = (error) => {
|
|
203
|
+
if (!error || typeof error !== 'object') {
|
|
204
|
+
return false;
|
|
205
|
+
}
|
|
206
|
+
const nativeError = error;
|
|
207
|
+
return (nativeError.errorCode === BLE_PLX_DEVICE_DISCONNECTED ||
|
|
208
|
+
nativeError.iosErrorCode === IOS_PERIPHERAL_DISCONNECTED);
|
|
209
|
+
};
|
|
210
|
+
const toBleDisconnectHardwareError = (error) => {
|
|
211
|
+
if ((error === null || error === void 0 ? void 0 : error.errorCode) === hdShared.HardwareErrorCode.BleDeviceDisconnected) {
|
|
212
|
+
return error;
|
|
213
|
+
}
|
|
214
|
+
const nativeError = (error !== null && error !== void 0 ? error : {});
|
|
215
|
+
return hdShared.ERRORS.TypedError(hdShared.HardwareErrorCode.BleDeviceDisconnected, nativeErrorText$1(nativeError) || undefined);
|
|
216
|
+
};
|
|
217
|
+
|
|
197
218
|
const ATT_INSUFFICIENT_AUTHENTICATION = 5;
|
|
198
219
|
const ATT_INSUFFICIENT_ENCRYPTION = 15;
|
|
199
220
|
const IOS_PEER_REMOVED_PAIRING_INFORMATION = 14;
|
|
@@ -258,6 +279,7 @@ class BleTransport {
|
|
|
258
279
|
const { check, ProtocolV1, parseConfigure } = transport__default["default"];
|
|
259
280
|
const Log = bleLogger;
|
|
260
281
|
const transportCache = {};
|
|
282
|
+
let bleManagerResetPromise;
|
|
261
283
|
const FIRMWARE_UPLOAD_WRITE_BURST_SIZE = reactNative.Platform.OS === 'ios' ? 4 : 5;
|
|
262
284
|
const FIRMWARE_UPLOAD_WRITE_PAUSE_MS = reactNative.Platform.OS === 'ios' ? 8 : 10;
|
|
263
285
|
const FIRMWARE_UPLOAD_WRITE_FLUSH_DELAY_MS = reactNative.Platform.OS === 'ios' ? 24 : 30;
|
|
@@ -316,6 +338,17 @@ const WEDGED_WRITE_MESSAGE = 'BLE write timeout after';
|
|
|
316
338
|
const isWedgedWriteError = (error) => (error === null || error === void 0 ? void 0 : error.errorCode) === hdShared.HardwareErrorCode.BleWriteCharacteristicError &&
|
|
317
339
|
typeof (error === null || error === void 0 ? void 0 : error.message) === 'string' &&
|
|
318
340
|
error.message.startsWith(WEDGED_WRITE_MESSAGE);
|
|
341
|
+
const shouldRethrowProtocolProbeError = (error) => {
|
|
342
|
+
const code = error === null || error === void 0 ? void 0 : error.errorCode;
|
|
343
|
+
return (hdShared.isBleStaleBondHardwareError(error) ||
|
|
344
|
+
isNativeBleDisconnectError(error) ||
|
|
345
|
+
code === hdShared.HardwareErrorCode.BleDeviceNotBonded ||
|
|
346
|
+
code === hdShared.HardwareErrorCode.BleDeviceBondedCanceled ||
|
|
347
|
+
code === hdShared.HardwareErrorCode.BleDeviceDisconnected ||
|
|
348
|
+
code === hdShared.HardwareErrorCode.BleCharacteristicNotifyError ||
|
|
349
|
+
code === hdShared.HardwareErrorCode.BleCharacteristicNotifyChangeFailure ||
|
|
350
|
+
code === hdShared.HardwareErrorCode.BleWriteCharacteristicError);
|
|
351
|
+
};
|
|
319
352
|
const BLE_WRITE_TIMEOUT_MANAGER_RESET_THRESHOLD = 2;
|
|
320
353
|
const DEVICE_SCAN_TIMEOUT_MS = 3000;
|
|
321
354
|
const IOS_NOTIFY_READY_DELAY_MS = 150;
|
|
@@ -474,6 +507,7 @@ class ReactNativeBleTransport {
|
|
|
474
507
|
this.androidPriorityResetTimers = new Map();
|
|
475
508
|
this.nextMonitorToken = 1;
|
|
476
509
|
this.lifecycleOperations = new Map();
|
|
510
|
+
this.scanCleanups = new Set();
|
|
477
511
|
this.scanTimeout = (_a = options.scanTimeout) !== null && _a !== void 0 ? _a : DEVICE_SCAN_TIMEOUT_MS;
|
|
478
512
|
}
|
|
479
513
|
init(logger, emitter) {
|
|
@@ -502,10 +536,38 @@ class ReactNativeBleTransport {
|
|
|
502
536
|
listen() {
|
|
503
537
|
}
|
|
504
538
|
getPlxManager() {
|
|
505
|
-
|
|
506
|
-
|
|
507
|
-
|
|
508
|
-
|
|
539
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
540
|
+
while (bleManagerResetPromise) {
|
|
541
|
+
yield this.waitForManagerReset();
|
|
542
|
+
}
|
|
543
|
+
if (this.stopped)
|
|
544
|
+
throw hdShared.ERRORS.TypedError(hdShared.HardwareErrorCode.BleDeviceDisconnected);
|
|
545
|
+
if (!this.blePlxManager)
|
|
546
|
+
this.blePlxManager = new reactNativeBlePlx.BleManager();
|
|
547
|
+
return this.blePlxManager;
|
|
548
|
+
});
|
|
549
|
+
}
|
|
550
|
+
waitForManagerReset() {
|
|
551
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
552
|
+
if (!bleManagerResetPromise)
|
|
553
|
+
return;
|
|
554
|
+
let timeout;
|
|
555
|
+
try {
|
|
556
|
+
yield Promise.race([
|
|
557
|
+
bleManagerResetPromise,
|
|
558
|
+
new Promise((_, reject) => {
|
|
559
|
+
timeout = setTimeout(() => reject(this.createWedgedBleSetupError()), BLE_CONNECT_TIMEOUT_MS);
|
|
560
|
+
}),
|
|
561
|
+
]);
|
|
562
|
+
}
|
|
563
|
+
catch (_a) {
|
|
564
|
+
throw this.createWedgedBleSetupError();
|
|
565
|
+
}
|
|
566
|
+
finally {
|
|
567
|
+
if (timeout)
|
|
568
|
+
clearTimeout(timeout);
|
|
569
|
+
}
|
|
570
|
+
});
|
|
509
571
|
}
|
|
510
572
|
resolveCharacteristics(device) {
|
|
511
573
|
return __awaiter(this, void 0, void 0, function* () {
|
|
@@ -670,30 +732,55 @@ class ReactNativeBleTransport {
|
|
|
670
732
|
}
|
|
671
733
|
enumerate() {
|
|
672
734
|
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
|
-
}
|
|
735
|
+
const scanStartedAt = Date.now();
|
|
736
|
+
let firstDeviceMs;
|
|
737
|
+
const blePlxManager = yield this.getPlxManager();
|
|
738
|
+
yield subscribeBleOn(blePlxManager);
|
|
739
|
+
if (reactNative.Platform.OS === 'android' && reactNative.Platform.Version >= 31) {
|
|
740
|
+
Log === null || Log === void 0 ? void 0 : Log.debug('requesting permissions, please wait...');
|
|
741
|
+
const resultConnect = yield reactNative.PermissionsAndroid.requestMultiple([
|
|
742
|
+
reactNative.PermissionsAndroid.PERMISSIONS.BLUETOOTH_CONNECT,
|
|
743
|
+
reactNative.PermissionsAndroid.PERMISSIONS.BLUETOOTH_SCAN,
|
|
744
|
+
]);
|
|
745
|
+
Log === null || Log === void 0 ? void 0 : Log.debug('requesting permissions, result: ', resultConnect);
|
|
746
|
+
if (resultConnect[reactNative.PermissionsAndroid.PERMISSIONS.BLUETOOTH_CONNECT] !== 'granted' ||
|
|
747
|
+
resultConnect[reactNative.PermissionsAndroid.PERMISSIONS.BLUETOOTH_SCAN] !== 'granted') {
|
|
748
|
+
throw hdShared.ERRORS.TypedError(hdShared.HardwareErrorCode.BlePermissionError);
|
|
696
749
|
}
|
|
750
|
+
}
|
|
751
|
+
if (this.stopped)
|
|
752
|
+
throw hdShared.ERRORS.TypedError(hdShared.HardwareErrorCode.BleDeviceDisconnected);
|
|
753
|
+
return new Promise((resolve, reject) => {
|
|
754
|
+
const deviceList = [];
|
|
755
|
+
let finished = false;
|
|
756
|
+
let scanCleanup;
|
|
757
|
+
const finishScan = (error) => {
|
|
758
|
+
if (scanCleanup)
|
|
759
|
+
return scanCleanup;
|
|
760
|
+
finished = true;
|
|
761
|
+
clearScanTimer();
|
|
762
|
+
scanCleanup = this.runNativeTeardown('scan', blePlxManager, () => __awaiter(this, void 0, void 0, function* () {
|
|
763
|
+
yield blePlxManager.stopDeviceScan();
|
|
764
|
+
})).then(() => {
|
|
765
|
+
this.scanCleanups.delete(cancelScan);
|
|
766
|
+
if (error)
|
|
767
|
+
reject(error);
|
|
768
|
+
else
|
|
769
|
+
resolve(deviceList);
|
|
770
|
+
});
|
|
771
|
+
return scanCleanup;
|
|
772
|
+
};
|
|
773
|
+
const cancelScan = () => finishScan(hdShared.ERRORS.TypedError(hdShared.HardwareErrorCode.BleDeviceDisconnected));
|
|
774
|
+
this.scanCleanups.add(cancelScan);
|
|
775
|
+
const clearScanTimer = timer.timeout(() => {
|
|
776
|
+
Log === null || Log === void 0 ? void 0 : Log.debug('[ReactNativeBleTransport] scan completed', {
|
|
777
|
+
elapsedMs: Date.now() - scanStartedAt,
|
|
778
|
+
firstDeviceMs,
|
|
779
|
+
deviceCount: deviceList.length,
|
|
780
|
+
scanWindowMs: this.scanTimeout,
|
|
781
|
+
});
|
|
782
|
+
finishScan();
|
|
783
|
+
}, this.scanTimeout);
|
|
697
784
|
blePlxManager.startDeviceScan(getBluetoothServiceUuids(), {
|
|
698
785
|
allowDuplicates: true,
|
|
699
786
|
scanMode: reactNativeBlePlx.ScanMode.LowLatency,
|
|
@@ -702,19 +789,17 @@ class ReactNativeBleTransport {
|
|
|
702
789
|
if (error) {
|
|
703
790
|
Log === null || Log === void 0 ? void 0 : Log.debug('ble scan error: ', error);
|
|
704
791
|
if ([reactNativeBlePlx.BleErrorCode.BluetoothPoweredOff, reactNativeBlePlx.BleErrorCode.BluetoothInUnknownState].includes(error.errorCode)) {
|
|
705
|
-
|
|
792
|
+
finishScan(hdShared.ERRORS.TypedError(hdShared.HardwareErrorCode.BlePermissionError));
|
|
706
793
|
}
|
|
707
794
|
else if (error.errorCode === reactNativeBlePlx.BleErrorCode.BluetoothUnauthorized) {
|
|
708
|
-
|
|
795
|
+
finishScan(hdShared.ERRORS.TypedError(hdShared.HardwareErrorCode.BleLocationError));
|
|
709
796
|
}
|
|
710
797
|
else if (error.errorCode === reactNativeBlePlx.BleErrorCode.LocationServicesDisabled) {
|
|
711
|
-
|
|
712
|
-
}
|
|
713
|
-
else if (error.errorCode === reactNativeBlePlx.BleErrorCode.ScanStartFailed) {
|
|
714
|
-
timer.timeout(() => { }, this.scanTimeout);
|
|
798
|
+
finishScan(hdShared.ERRORS.TypedError(hdShared.HardwareErrorCode.BleLocationServicesDisabled));
|
|
715
799
|
}
|
|
800
|
+
else if (error.errorCode === reactNativeBlePlx.BleErrorCode.ScanStartFailed) ;
|
|
716
801
|
else {
|
|
717
|
-
|
|
802
|
+
finishScan(hdShared.ERRORS.TypedError(hdShared.HardwareErrorCode.BleScanError, (_a = error.reason) !== null && _a !== void 0 ? _a : ''));
|
|
718
803
|
}
|
|
719
804
|
return;
|
|
720
805
|
}
|
|
@@ -739,6 +824,8 @@ class ReactNativeBleTransport {
|
|
|
739
824
|
});
|
|
740
825
|
}
|
|
741
826
|
});
|
|
827
|
+
if (finished)
|
|
828
|
+
return;
|
|
742
829
|
getConnectedDeviceIds(reactNative.Platform.OS === 'ios' ? getBluetoothServiceUuids() : []).then(devices => {
|
|
743
830
|
for (const device of devices) {
|
|
744
831
|
const localName = 'localName' in device && typeof device.localName === 'string'
|
|
@@ -754,10 +841,11 @@ class ReactNativeBleTransport {
|
|
|
754
841
|
addDevice(device);
|
|
755
842
|
}
|
|
756
843
|
}
|
|
757
|
-
});
|
|
844
|
+
}, error => Log === null || Log === void 0 ? void 0 : Log.debug('search connected peripheral failed:', error));
|
|
758
845
|
const addDevice = (device) => {
|
|
759
846
|
var _a;
|
|
760
|
-
if (deviceList.every(d => d.id !== device.id)) {
|
|
847
|
+
if (!finished && deviceList.every(d => d.id !== device.id)) {
|
|
848
|
+
firstDeviceMs !== null && firstDeviceMs !== void 0 ? firstDeviceMs : (firstDeviceMs = Date.now() - scanStartedAt);
|
|
761
849
|
const displayName = (_a = getDeviceDisplayName(device)) !== null && _a !== void 0 ? _a : 'Unknown BLE Device';
|
|
762
850
|
deviceList.push(Object.assign(Object.assign({}, device), { name: displayName, commType: 'ble' }));
|
|
763
851
|
Log === null || Log === void 0 ? void 0 : Log.debug('[ReactNativeBleTransport] OneKey BLE device discovered', {
|
|
@@ -767,11 +855,7 @@ class ReactNativeBleTransport {
|
|
|
767
855
|
});
|
|
768
856
|
}
|
|
769
857
|
};
|
|
770
|
-
|
|
771
|
-
blePlxManager.stopDeviceScan();
|
|
772
|
-
resolve(deviceList);
|
|
773
|
-
}, this.scanTimeout);
|
|
774
|
-
}));
|
|
858
|
+
});
|
|
775
859
|
});
|
|
776
860
|
}
|
|
777
861
|
installTransportForAcquire(uuid, device, characteristics) {
|
|
@@ -837,6 +921,8 @@ class ReactNativeBleTransport {
|
|
|
837
921
|
acquireUnlocked(input) {
|
|
838
922
|
var _a;
|
|
839
923
|
return __awaiter(this, void 0, void 0, function* () {
|
|
924
|
+
if (this.stopped)
|
|
925
|
+
throw hdShared.ERRORS.TypedError(hdShared.HardwareErrorCode.BleDeviceDisconnected);
|
|
840
926
|
const { uuid, forceCleanRunPromise, expectedProtocol, skipProtocolProbe } = input;
|
|
841
927
|
const shouldMapProtocolV2StaleBond = expectedProtocol
|
|
842
928
|
? expectedProtocol === 'V2'
|
|
@@ -1042,7 +1128,7 @@ class ReactNativeBleTransport {
|
|
|
1042
1128
|
return { uuid, protocolType };
|
|
1043
1129
|
}
|
|
1044
1130
|
catch (error) {
|
|
1045
|
-
if (hdShared.isBleStaleBondHardwareError(error)) {
|
|
1131
|
+
if (hdShared.isBleStaleBondHardwareError(error) || shouldRethrowProtocolProbeError(error)) {
|
|
1046
1132
|
yield this.disconnectUnlocked(uuid);
|
|
1047
1133
|
}
|
|
1048
1134
|
else {
|
|
@@ -1455,7 +1541,35 @@ class ReactNativeBleTransport {
|
|
|
1455
1541
|
});
|
|
1456
1542
|
}
|
|
1457
1543
|
stop() {
|
|
1544
|
+
var _a;
|
|
1545
|
+
if (this.stopPromise)
|
|
1546
|
+
return this.stopPromise;
|
|
1458
1547
|
this.stopped = true;
|
|
1548
|
+
const deviceIds = new Set([
|
|
1549
|
+
...this.monitorTokens.keys(),
|
|
1550
|
+
...this.sessionProtocols.keys(),
|
|
1551
|
+
...this.lifecycleOperations.keys(),
|
|
1552
|
+
...(this.runPromiseDeviceId ? [this.runPromiseDeviceId] : []),
|
|
1553
|
+
]);
|
|
1554
|
+
const scans = Array.from(this.scanCleanups, cleanup => cleanup());
|
|
1555
|
+
this.androidPriorityResetTimers.forEach(timeout => clearTimeout(timeout));
|
|
1556
|
+
this.androidPriorityResetTimers.clear();
|
|
1557
|
+
this.androidHighPriorityDevices.clear();
|
|
1558
|
+
const error = hdShared.ERRORS.TypedError(hdShared.HardwareErrorCode.BleDeviceDisconnected);
|
|
1559
|
+
(_a = this.runPromise) === null || _a === void 0 ? void 0 : _a.reject(error);
|
|
1560
|
+
this.runPromise = null;
|
|
1561
|
+
this.runPromiseDeviceId = null;
|
|
1562
|
+
deviceIds.forEach(uuid => this.rejectProtocolV2Frames(uuid, error));
|
|
1563
|
+
this.stopPromise = Promise.all([
|
|
1564
|
+
...scans,
|
|
1565
|
+
...Array.from(deviceIds, uuid => this.disconnect(uuid)),
|
|
1566
|
+
]).then(() => __awaiter(this, void 0, void 0, function* () {
|
|
1567
|
+
yield this.protocolV2Links.invalidateAllLinks('React Native BLE transport stopped');
|
|
1568
|
+
yield this.waitForManagerReset();
|
|
1569
|
+
this.blePlxManager = undefined;
|
|
1570
|
+
this.emitter = undefined;
|
|
1571
|
+
}));
|
|
1572
|
+
return this.stopPromise;
|
|
1459
1573
|
}
|
|
1460
1574
|
disconnect(session) {
|
|
1461
1575
|
return __awaiter(this, void 0, void 0, function* () {
|
|
@@ -1585,13 +1699,25 @@ class ReactNativeBleTransport {
|
|
|
1585
1699
|
});
|
|
1586
1700
|
}
|
|
1587
1701
|
cancel() {
|
|
1588
|
-
|
|
1589
|
-
|
|
1590
|
-
|
|
1591
|
-
|
|
1702
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
1703
|
+
Log === null || Log === void 0 ? void 0 : Log.debug('transport-react-native transport cancel');
|
|
1704
|
+
const pending = this.runPromise;
|
|
1705
|
+
const deviceId = this.runPromiseDeviceId;
|
|
1706
|
+
if (pending) {
|
|
1707
|
+
pending.reject(hdShared.ERRORS.TypedError(hdShared.HardwareErrorCode.CallQueueActionCancelled));
|
|
1708
|
+
if (this.runPromise === pending) {
|
|
1709
|
+
this.runPromise = null;
|
|
1710
|
+
this.runPromiseDeviceId = null;
|
|
1711
|
+
}
|
|
1712
|
+
if (deviceId)
|
|
1713
|
+
yield this.disconnect(deviceId);
|
|
1714
|
+
}
|
|
1715
|
+
});
|
|
1592
1716
|
}
|
|
1593
1717
|
connectWithTimeout(uuid, connect) {
|
|
1594
1718
|
return __awaiter(this, void 0, void 0, function* () {
|
|
1719
|
+
const startedAt = Date.now();
|
|
1720
|
+
let succeeded = false;
|
|
1595
1721
|
let timer;
|
|
1596
1722
|
let timedOut = false;
|
|
1597
1723
|
const pending = connect();
|
|
@@ -1606,6 +1732,7 @@ class ReactNativeBleTransport {
|
|
|
1606
1732
|
}, BLE_CONNECT_TIMEOUT_MS);
|
|
1607
1733
|
}),
|
|
1608
1734
|
]);
|
|
1735
|
+
succeeded = true;
|
|
1609
1736
|
return result;
|
|
1610
1737
|
}
|
|
1611
1738
|
catch (error) {
|
|
@@ -1620,11 +1747,19 @@ class ReactNativeBleTransport {
|
|
|
1620
1747
|
finally {
|
|
1621
1748
|
if (timer)
|
|
1622
1749
|
clearTimeout(timer);
|
|
1750
|
+
Log === null || Log === void 0 ? void 0 : Log.debug('[ReactNativeBleTransport] connect completed', {
|
|
1751
|
+
connectIdSuffix: uuid.slice(-8),
|
|
1752
|
+
elapsedMs: Date.now() - startedAt,
|
|
1753
|
+
succeeded,
|
|
1754
|
+
backstopExpired: timedOut,
|
|
1755
|
+
});
|
|
1623
1756
|
}
|
|
1624
1757
|
});
|
|
1625
1758
|
}
|
|
1626
1759
|
resolveCharacteristicsWithTimeout(uuid, device) {
|
|
1627
1760
|
return __awaiter(this, void 0, void 0, function* () {
|
|
1761
|
+
const startedAt = Date.now();
|
|
1762
|
+
let succeeded = false;
|
|
1628
1763
|
let timer;
|
|
1629
1764
|
let timedOut = false;
|
|
1630
1765
|
const pending = this.resolveCharacteristics(device);
|
|
@@ -1640,6 +1775,7 @@ class ReactNativeBleTransport {
|
|
|
1640
1775
|
}),
|
|
1641
1776
|
]);
|
|
1642
1777
|
this.connectionSetupTimeoutCounts.delete(uuid);
|
|
1778
|
+
succeeded = true;
|
|
1643
1779
|
return result;
|
|
1644
1780
|
}
|
|
1645
1781
|
catch (error) {
|
|
@@ -1654,6 +1790,12 @@ class ReactNativeBleTransport {
|
|
|
1654
1790
|
finally {
|
|
1655
1791
|
if (timer)
|
|
1656
1792
|
clearTimeout(timer);
|
|
1793
|
+
Log === null || Log === void 0 ? void 0 : Log.debug('[ReactNativeBleTransport] GATT setup completed', {
|
|
1794
|
+
connectIdSuffix: uuid.slice(-8),
|
|
1795
|
+
elapsedMs: Date.now() - startedAt,
|
|
1796
|
+
succeeded,
|
|
1797
|
+
backstopExpired: timedOut,
|
|
1798
|
+
});
|
|
1657
1799
|
}
|
|
1658
1800
|
});
|
|
1659
1801
|
}
|
|
@@ -1755,6 +1897,8 @@ class ReactNativeBleTransport {
|
|
|
1755
1897
|
}
|
|
1756
1898
|
}
|
|
1757
1899
|
resetPlxManager() {
|
|
1900
|
+
if (bleManagerResetPromise)
|
|
1901
|
+
return;
|
|
1758
1902
|
const manager = this.blePlxManager;
|
|
1759
1903
|
this.blePlxManager = undefined;
|
|
1760
1904
|
const reason = 'React Native BLE manager reset';
|
|
@@ -1796,12 +1940,20 @@ class ReactNativeBleTransport {
|
|
|
1796
1940
|
this.connectionSetupTimeoutCounts.clear();
|
|
1797
1941
|
this.monitorTokens.clear();
|
|
1798
1942
|
this.protocolV2Assemblers.clear();
|
|
1943
|
+
let reset;
|
|
1799
1944
|
try {
|
|
1800
|
-
manager === null || manager === void 0 ? void 0 : manager.destroy();
|
|
1945
|
+
reset = Promise.resolve(manager === null || manager === void 0 ? void 0 : manager.destroy());
|
|
1801
1946
|
}
|
|
1802
1947
|
catch (error) {
|
|
1803
|
-
|
|
1948
|
+
reset = Promise.reject(error);
|
|
1804
1949
|
}
|
|
1950
|
+
bleManagerResetPromise = reset;
|
|
1951
|
+
reset.then(() => {
|
|
1952
|
+
if (bleManagerResetPromise === reset)
|
|
1953
|
+
bleManagerResetPromise = undefined;
|
|
1954
|
+
}, error => {
|
|
1955
|
+
Log === null || Log === void 0 ? void 0 : Log.error('[ReactNativeBleTransport] BLE manager destroy failed:', error);
|
|
1956
|
+
});
|
|
1805
1957
|
}
|
|
1806
1958
|
createProtocolMismatchError(expected) {
|
|
1807
1959
|
return hdShared.ERRORS.TypedError(hdShared.HardwareErrorCode.RuntimeError, `Device protocol mismatch: expected ${expected}, but device did not respond to expected protocol`);
|
|
@@ -1951,7 +2103,7 @@ class ReactNativeBleTransport {
|
|
|
1951
2103
|
catch (error) {
|
|
1952
2104
|
this.clearProbeProtocol(uuid, 'V1');
|
|
1953
2105
|
Log === null || Log === void 0 ? void 0 : Log.debug('[ReactNativeBleTransport] Protocol V1 GetFeatures probe failed:', error);
|
|
1954
|
-
if (
|
|
2106
|
+
if (shouldRethrowProtocolProbeError(error)) {
|
|
1955
2107
|
throw error;
|
|
1956
2108
|
}
|
|
1957
2109
|
return false;
|
|
@@ -1977,7 +2129,7 @@ class ReactNativeBleTransport {
|
|
|
1977
2129
|
(_a = this.protocolV2Assemblers.get(uuid)) === null || _a === void 0 ? void 0 : _a.reset();
|
|
1978
2130
|
this.resetProtocolV2Frames(uuid);
|
|
1979
2131
|
},
|
|
1980
|
-
shouldRethrow:
|
|
2132
|
+
shouldRethrow: shouldRethrowProtocolProbeError,
|
|
1981
2133
|
});
|
|
1982
2134
|
if (!detected) {
|
|
1983
2135
|
this.clearProbeProtocol(uuid, 'V2');
|
|
@@ -2104,6 +2256,9 @@ class ReactNativeBleTransport {
|
|
|
2104
2256
|
this.rememberStaleBondError(uuid, bondError);
|
|
2105
2257
|
throw bondError;
|
|
2106
2258
|
}
|
|
2259
|
+
if (isNativeBleDisconnectError(error)) {
|
|
2260
|
+
throw toBleDisconnectHardwareError(error);
|
|
2261
|
+
}
|
|
2107
2262
|
if (getFirmwareUploadWriteRetryType(error) !== 'congested' ||
|
|
2108
2263
|
attempt >= FIRMWARE_UPLOAD_WRITE_MAX_RETRIES) {
|
|
2109
2264
|
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.106",
|
|
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.
|
|
23
|
+
"@onekeyfe/hd-core": "1.2.2-alpha.106",
|
|
24
|
+
"@onekeyfe/hd-shared": "1.2.2-alpha.106",
|
|
25
|
+
"@onekeyfe/hd-transport": "1.2.2-alpha.106",
|
|
26
26
|
"@onekeyfe/react-native-ble-utils": "^0.1.6",
|
|
27
27
|
"react-native-ble-plx": "3.5.1"
|
|
28
28
|
},
|
|
29
|
-
"gitHead": "
|
|
29
|
+
"gitHead": "e52ad091098aaab6b2845154457ace5e2f8c9098"
|
|
30
30
|
}
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
import { HardwareErrorCode } from '@onekeyfe/hd-shared';
|
|
2
|
+
|
|
3
|
+
import { isNativeBleDisconnectError, toBleDisconnectHardwareError } from '../bleNativeDisconnect';
|
|
4
|
+
|
|
5
|
+
describe('native BLE disconnect mapping', () => {
|
|
6
|
+
test.each([
|
|
7
|
+
[{ errorCode: 201, reason: 'The specified device has disconnected from us.' }],
|
|
8
|
+
[{ errorCode: 201, iosErrorCode: 7, reason: 'The specified device has disconnected from us.' }],
|
|
9
|
+
[{ iosErrorCode: 7, reason: 'Peripheral disconnected' }],
|
|
10
|
+
])('recognizes %j as a native disconnect', nativeError => {
|
|
11
|
+
expect(isNativeBleDisconnectError(nativeError)).toBe(true);
|
|
12
|
+
expect(toBleDisconnectHardwareError(nativeError)).toMatchObject({
|
|
13
|
+
errorCode: HardwareErrorCode.BleDeviceDisconnected,
|
|
14
|
+
});
|
|
15
|
+
});
|
|
16
|
+
|
|
17
|
+
test('does not treat a stale-bond iOS code as a disconnect', () => {
|
|
18
|
+
expect(
|
|
19
|
+
isNativeBleDisconnectError({
|
|
20
|
+
iosErrorCode: 14,
|
|
21
|
+
reason: 'Peer removed pairing information',
|
|
22
|
+
})
|
|
23
|
+
).toBe(false);
|
|
24
|
+
});
|
|
25
|
+
|
|
26
|
+
test('does not treat an already-canonical unpaired error as a native disconnect', () => {
|
|
27
|
+
expect(
|
|
28
|
+
isNativeBleDisconnectError({
|
|
29
|
+
errorCode: HardwareErrorCode.BleDeviceNotBonded,
|
|
30
|
+
})
|
|
31
|
+
).toBe(false);
|
|
32
|
+
});
|
|
33
|
+
});
|