@onekeyfe/hd-transport-react-native 1.2.0-alpha.130 → 1.2.0-alpha.131
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.d.ts +4 -1
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +75 -42
- package/package.json +5 -5
- package/src/__tests__/protocolV2Link.test.ts +39 -0
- package/src/index.ts +96 -42
package/dist/index.d.ts
CHANGED
|
@@ -53,6 +53,7 @@ declare const getFirmwareUploadWriteRetryType: (error: unknown) => FirmwareUploa
|
|
|
53
53
|
* A healthy packet completes in milliseconds, so this only fires on a dead link.
|
|
54
54
|
*/
|
|
55
55
|
declare const BLE_WRITE_PACKET_TIMEOUT_MS = 10000;
|
|
56
|
+
declare const BLE_NATIVE_TEARDOWN_TIMEOUT_MS = 3000;
|
|
56
57
|
/** Consecutive wedged writes on one device before the BLE manager itself is recreated. */
|
|
57
58
|
declare const BLE_WRITE_TIMEOUT_MANAGER_RESET_THRESHOLD = 2;
|
|
58
59
|
type ProtocolV2BleTuning = {
|
|
@@ -166,6 +167,8 @@ declare class ReactNativeBleTransport {
|
|
|
166
167
|
stop(): void;
|
|
167
168
|
disconnect(session: string): Promise<void>;
|
|
168
169
|
private disconnectUnlocked;
|
|
170
|
+
private runNativeTeardown;
|
|
171
|
+
private runBestEffortNativeOperation;
|
|
169
172
|
private runLifecycleOperation;
|
|
170
173
|
cancel(): void;
|
|
171
174
|
/** Run a native connect under the JS backstop budget. */
|
|
@@ -221,4 +224,4 @@ declare class ReactNativeBleTransport {
|
|
|
221
224
|
getProtocolType(path: string): ProtocolType | undefined;
|
|
222
225
|
}
|
|
223
226
|
|
|
224
|
-
export { BLE_CONNECT_TIMEOUT_MANAGER_RESET_THRESHOLD, BLE_CONNECT_TIMEOUT_MS, BLE_GATT_SETUP_TIMEOUT_MS, BLE_WRITE_PACKET_TIMEOUT_MS, BLE_WRITE_TIMEOUT_MANAGER_RESET_THRESHOLD, IOneKeyDevice, PROTOCOL_REPROBE_FALLBACK_ATTEMPTS, ProtocolV2BleTuning, configureProtocolV2BleTuning, ReactNativeBleTransport as default, getFirmwareUploadWriteRetryType, getProtocolV2BleTuning, resetProtocolV2BleTuning };
|
|
227
|
+
export { BLE_CONNECT_TIMEOUT_MANAGER_RESET_THRESHOLD, BLE_CONNECT_TIMEOUT_MS, BLE_GATT_SETUP_TIMEOUT_MS, BLE_NATIVE_TEARDOWN_TIMEOUT_MS, BLE_WRITE_PACKET_TIMEOUT_MS, BLE_WRITE_TIMEOUT_MANAGER_RESET_THRESHOLD, IOneKeyDevice, PROTOCOL_REPROBE_FALLBACK_ATTEMPTS, ProtocolV2BleTuning, configureProtocolV2BleTuning, ReactNativeBleTransport as default, getFirmwareUploadWriteRetryType, getProtocolV2BleTuning, resetProtocolV2BleTuning };
|
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,EAIL,UAAU,IAAI,aAAa,EAG5B,MAAM,sBAAsB,CAAC;AAE9B,OAAO,SAAS,EAAE,EAChB,KAAK,oBAAoB,EAIzB,KAAK,YAAY,EAKjB,KAAK,oBAAoB,EAI1B,MAAM,wBAAwB,CAAC;AA0BhC,OAAO,YAAY,MAAM,gBAAgB,CAAC;AAI1C,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,qBAAqB,CAAC;AACpD,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,EAAE,YAAY,EAAE,MAAM,sBAAsB,CAAC;AACjF,OAAO,KAAK,YAAY,MAAM,QAAQ,CAAC;AACvC,OAAO,KAAK,EAAE,eAAe,EAAE,gBAAgB,EAAE,MAAM,SAAS,CAAC;AAgBjE,KAAK,4BAA4B,GAAG,WAAW,CAAC;AAChD,KAAK,0BAA0B,GAAG;IAChC,mBAAmB,EAAE,cAAc,CAAC;IACpC,oBAAoB,EAAE,cAAc,CAAC;CACtC,CAAC;AAkCF,eAAO,MAAM,+BAA+B,UACnC,OAAO,KACb,4BAA4B,GAAG,IAsBjC,CAAC;AAcF,eAAO,MAAM,2BAA2B,QAAS,CAAC;
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":";AAEA,OAAO,EAIL,UAAU,IAAI,aAAa,EAG5B,MAAM,sBAAsB,CAAC;AAE9B,OAAO,SAAS,EAAE,EAChB,KAAK,oBAAoB,EAIzB,KAAK,YAAY,EAKjB,KAAK,oBAAoB,EAI1B,MAAM,wBAAwB,CAAC;AA0BhC,OAAO,YAAY,MAAM,gBAAgB,CAAC;AAI1C,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,qBAAqB,CAAC;AACpD,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,EAAE,YAAY,EAAE,MAAM,sBAAsB,CAAC;AACjF,OAAO,KAAK,YAAY,MAAM,QAAQ,CAAC;AACvC,OAAO,KAAK,EAAE,eAAe,EAAE,gBAAgB,EAAE,MAAM,SAAS,CAAC;AAgBjE,KAAK,4BAA4B,GAAG,WAAW,CAAC;AAChD,KAAK,0BAA0B,GAAG;IAChC,mBAAmB,EAAE,cAAc,CAAC;IACpC,oBAAoB,EAAE,cAAc,CAAC;CACtC,CAAC;AAkCF,eAAO,MAAM,+BAA+B,UACnC,OAAO,KACb,4BAA4B,GAAG,IAsBjC,CAAC;AAcF,eAAO,MAAM,2BAA2B,QAAS,CAAC;AAClD,eAAO,MAAM,8BAA8B,OAAQ,CAAC;AAOpD,eAAO,MAAM,yCAAyC,IAAI,CAAC;AAI3D,MAAM,MAAM,mBAAmB,GAAG;IAChC,eAAe,CAAC,EAAE,MAAM,CAAC;IACzB,mBAAmB,CAAC,EAAE,MAAM,CAAC;CAC9B,CAAC;AAiBF,wBAAgB,4BAA4B,CAAC,MAAM,GAAE,mBAAwB,QAY5E;AAED,wBAAgB,wBAAwB,SAGvC;AAED,wBAAgB,sBAAsB;;;EAErC;AAsCD,eAAO,MAAM,sBAAsB,QAA2C,CAAC;AAO/E,eAAO,MAAM,yBAAyB,QAAS,CAAC;AAQhD,eAAO,MAAM,kCAAkC,IAAI,CAAC;AAEpD,eAAO,MAAM,2CAA2C,IAAI,CAAC;AAS7D,MAAM,MAAM,aAAa,GAAG,oBAAoB,GAAG,MAAM,CAAC;AAqE1D,MAAM,CAAC,OAAO,OAAO,uBAAuB;IAC1C,aAAa,EAAE,aAAa,GAAG,SAAS,CAAC;IAEzC,SAAS,EAAE,UAAU,CAAC,OAAO,SAAS,CAAC,cAAc,CAAC,GAAG,SAAS,CAAC;IAEnE,WAAW,EAAE,UAAU,CAAC,OAAO,SAAS,CAAC,cAAc,CAAC,GAAG,SAAS,CAAC;IAErE,OAAO,CAAC,6BAA6B,CAAqB;IAE1D,IAAI,SAA6B;IAEjC,UAAU,UAAS;IAEnB,OAAO,UAAS;IAEhB,WAAW,SAA0B;IAErC,UAAU,EAAE,QAAQ,CAAC,GAAG,CAAC,GAAG,IAAI,CAAQ;IAExC,OAAO,CAAC,kBAAkB,CAAuB;IAEjD,OAAO,CAAC,EAAE,YAAY,CAAC;IAEvB,8BAA8B,cAAqB;IAGnD,OAAO,CAAC,cAAc,CAAwC;IAQ9D,OAAO,CAAC,gBAAgB,CAAwC;IAGhE,OAAO,CAAC,kBAAkB,CAAkC;IAG5D,OAAO,CAAC,4BAA4B,CAAkC;IAEtE,OAAO,CAAC,mBAAmB,CAAwC;IAGnE,OAAO,CAAC,gBAAgB,CAAwC;IAGhE,OAAO,CAAC,uBAAuB,CAAkC;IAEjE,OAAO,CAAC,oBAAoB,CAAoD;IAEhF,OAAO,CAAC,qBAAqB,CAAwC;IAErE,OAAO,CAAC,uBAAuB,CAAgD;IAE/E,OAAO,CAAC,eAAe,CAmBpB;IAEH,OAAO,CAAC,aAAa,CAAkC;IAEvD,OAAO,CAAC,qBAAqB,CAAkC;IAE/D,OAAO,CAAC,iCAAiC,CAAuC;IAEhF,OAAO,CAAC,0BAA0B,CAA0B;IAE5D,OAAO,CAAC,0BAA0B,CAAyD;IAE3F,OAAO,CAAC,gBAAgB,CAAK;IAG7B,OAAO,CAAC,mBAAmB,CAAyC;gBAExD,OAAO,EAAE,gBAAgB;IAIrC,IAAI,CAAC,MAAM,EAAE,GAAG,EAAE,OAAO,EAAE,YAAY;IAKvC,SAAS,CAAC,UAAU,EAAE,GAAG;IAMzB,mBAAmB,CAAC,UAAU,EAAE,GAAG;IAgBnC,MAAM;IAIN,aAAa,IAAI,OAAO,CAAC,aAAa,CAAC;IAMjC,sBAAsB,CAAC,MAAM,EAAE,MAAM,GAAG,OAAO,CAAC,0BAA0B,CAAC;IAmFjF,4BAA4B,CAAC,SAAS,EAAE,YAAY,EAAE,MAAM,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM;IAgClF,OAAO,CAAC,oBAAoB;IAgBtB,gCAAgC,CAAC,IAAI,EAAE,MAAM,EAAE,SAAS,EAAE,YAAY;IAsDtE,SAAS;YA0ID,0BAA0B;IAyElC,OAAO,CAAC,KAAK,EAAE,eAAe;;;;YAUtB,eAAe;IAkL7B,sBAAsB,CACpB,cAAc,EAAE,cAAc,EAC9B,IAAI,EAAE,MAAM,EACZ,YAAY,EAAE,MAAM,EACpB,mBAAmB,EAAE,MAAM,GAC1B,YAAY;IAsIT,OAAO,CAAC,IAAI,EAAE,MAAM,EAAE,OAAO,UAAQ;YAI7B,eAAe;YAKf,aAAa;IA4ErB,IAAI,CAAC,OAAO,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC;IAajE,IAAI,CACR,IAAI,EAAE,MAAM,EACZ,IAAI,EAAE,MAAM,EACZ,IAAI,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,EAC7B,OAAO,CAAC,EAAE,oBAAoB;YA6BlB,cAAc;IAyP5B,IAAI;IAIE,UAAU,CAAC,OAAO,EAAE,MAAM;YAIlB,kBAAkB;YAkFlB,iBAAiB;IAkC/B,OAAO,CAAC,4BAA4B;YAQtB,qBAAqB;IAoBnC,MAAM;YAUQ,kBAAkB;YAkClB,iCAAiC;IAwC/C,OAAO,CAAC,wBAAwB;IAgChC,OAAO,CAAC,kBAAkB;YAcZ,cAAc;IA8C5B,OAAO,CAAC,kBAAkB;IA6B1B,OAAO,CAAC,eAAe;IAsBvB,OAAO,CAAC,2BAA2B;IAOnC,OAAO,CAAC,4BAA4B;IAOpC,OAAO,CAAC,kBAAkB;IAU1B,OAAO,CAAC,iBAAiB;YAIX,cAAc;YAsGd,iCAAiC;YAoDjC,eAAe;YAwBf,eAAe;IA0B7B,OAAO,CAAC,4BAA4B;IA2BpC,OAAO,CAAC,uBAAuB;IAS/B,OAAO,CAAC,sBAAsB;IAU9B,OAAO,CAAC,qBAAqB;IAI7B,OAAO,CAAC,sBAAsB;YAShB,mBAAmB;YAiBnB,qBAAqB;YA2DrB,oBAAoB;YAgCpB,cAAc;YAqEd,iCAAiC;IAiB/C,OAAO,CAAC,8BAA8B;YAQxB,mCAAmC;IAsBjD,OAAO,CAAC,yCAAyC;YAanC,gCAAgC;IAoB9C,OAAO,CAAC,uBAAuB;IAmD/B,eAAe,CAAC,IAAI,EAAE,MAAM,GAAG,YAAY,GAAG,SAAS;CAGxD"}
|
package/dist/index.js
CHANGED
|
@@ -277,6 +277,7 @@ const resolveFirmwareUploadRetryDelay = (attempt, baseDelayMs = 200, maxDelayMs
|
|
|
277
277
|
const PROTOCOL_PROBE_TIMEOUT_MS = 3000;
|
|
278
278
|
const PROTOCOL_V2_PROBE_TIMEOUT_MS = 10000;
|
|
279
279
|
const BLE_WRITE_PACKET_TIMEOUT_MS = 10000;
|
|
280
|
+
const BLE_NATIVE_TEARDOWN_TIMEOUT_MS = 3000;
|
|
280
281
|
const WEDGED_WRITE_MESSAGE = 'BLE write timeout after';
|
|
281
282
|
const isWedgedWriteError = (error) => (error === null || error === void 0 ? void 0 : error.errorCode) === hdShared.HardwareErrorCode.BleWriteCharacteristicError &&
|
|
282
283
|
typeof (error === null || error === void 0 ? void 0 : error.message) === 'string' &&
|
|
@@ -1058,9 +1059,10 @@ class ReactNativeBleTransport {
|
|
|
1058
1059
|
});
|
|
1059
1060
|
}
|
|
1060
1061
|
releaseNative(uuid, onclose = false) {
|
|
1061
|
-
var _a, _b, _c, _d, _e
|
|
1062
|
+
var _a, _b, _c, _d, _e;
|
|
1062
1063
|
return __awaiter(this, void 0, void 0, function* () {
|
|
1063
1064
|
const transport = transportCache[uuid];
|
|
1065
|
+
const manager = this.blePlxManager;
|
|
1064
1066
|
if (this.runPromise && this.runPromiseDeviceId === uuid) {
|
|
1065
1067
|
const error = hdShared.ERRORS.TypedError(hdShared.HardwareErrorCode.BleForceCleanRunPromise);
|
|
1066
1068
|
this.runPromise.reject(error);
|
|
@@ -1076,7 +1078,6 @@ class ReactNativeBleTransport {
|
|
|
1076
1078
|
this.resetProtocolV2Frames(uuid);
|
|
1077
1079
|
return Promise.resolve(true);
|
|
1078
1080
|
}
|
|
1079
|
-
yield this.restoreAndroidConnectionPriority(uuid, transport);
|
|
1080
1081
|
if (transport) {
|
|
1081
1082
|
if (this.monitorTokens.get(uuid) === transport.monitorToken) {
|
|
1082
1083
|
this.monitorTokens.delete(uuid);
|
|
@@ -1087,28 +1088,28 @@ class ReactNativeBleTransport {
|
|
|
1087
1088
|
Log === null || Log === void 0 ? void 0 : Log.debug('release: removing notify subscription, characteristic: ', (_c = transport.notifyCharacteristic) === null || _c === void 0 ? void 0 : _c.uuid);
|
|
1088
1089
|
(_d = transport.notifySubscription) === null || _d === void 0 ? void 0 : _d.remove();
|
|
1089
1090
|
transport.notifySubscription = undefined;
|
|
1090
|
-
if (transport
|
|
1091
|
-
|
|
1092
|
-
yield ((_e = this.blePlxManager) === null || _e === void 0 ? void 0 : _e.cancelTransaction(transport.notifyTransactionId));
|
|
1093
|
-
}
|
|
1094
|
-
catch (e) {
|
|
1095
|
-
Log === null || Log === void 0 ? void 0 : Log.debug('release: cancel notify transaction error (ignored): ', (e === null || e === void 0 ? void 0 : e.message) || e);
|
|
1096
|
-
}
|
|
1091
|
+
if (transportCache[uuid] === transport) {
|
|
1092
|
+
delete transportCache[uuid];
|
|
1097
1093
|
}
|
|
1098
|
-
delete transportCache[uuid];
|
|
1099
1094
|
}
|
|
1100
1095
|
this.protocolV2HighVolumeLogSignatures.delete(uuid);
|
|
1101
1096
|
this.deviceProtocol.delete(uuid);
|
|
1102
1097
|
this.probingProtocols.delete(uuid);
|
|
1103
|
-
(
|
|
1098
|
+
(_e = this.protocolV2Assemblers.get(uuid)) === null || _e === void 0 ? void 0 : _e.reset();
|
|
1104
1099
|
this.protocolV2Assemblers.delete(uuid);
|
|
1105
1100
|
this.resetProtocolV2Frames(uuid);
|
|
1106
|
-
|
|
1107
|
-
|
|
1108
|
-
|
|
1109
|
-
|
|
1110
|
-
|
|
1111
|
-
|
|
1101
|
+
yield this.runNativeTeardown(uuid, manager, () => __awaiter(this, void 0, void 0, function* () {
|
|
1102
|
+
const operations = [
|
|
1103
|
+
this.runBestEffortNativeOperation('release: restore connection priority', () => this.restoreAndroidConnectionPriority(uuid, transport)),
|
|
1104
|
+
];
|
|
1105
|
+
if ((transport === null || transport === void 0 ? void 0 : transport.notifyTransactionId) && manager) {
|
|
1106
|
+
operations.push(this.runBestEffortNativeOperation('release: cancel notify transaction', () => manager.cancelTransaction(transport.notifyTransactionId)));
|
|
1107
|
+
}
|
|
1108
|
+
if (manager) {
|
|
1109
|
+
operations.push(this.runBestEffortNativeOperation('release: cancel transaction', () => manager.cancelTransaction(uuid)));
|
|
1110
|
+
}
|
|
1111
|
+
yield Promise.all(operations);
|
|
1112
|
+
}));
|
|
1112
1113
|
return Promise.resolve(true);
|
|
1113
1114
|
});
|
|
1114
1115
|
}
|
|
@@ -1348,10 +1349,11 @@ class ReactNativeBleTransport {
|
|
|
1348
1349
|
});
|
|
1349
1350
|
}
|
|
1350
1351
|
disconnectUnlocked(session) {
|
|
1351
|
-
var _a, _b, _c
|
|
1352
|
+
var _a, _b, _c;
|
|
1352
1353
|
return __awaiter(this, void 0, void 0, function* () {
|
|
1353
1354
|
yield this.protocolV2Links.invalidateLink(session, 'React Native BLE transport disconnected');
|
|
1354
1355
|
const transport = transportCache[session];
|
|
1356
|
+
const manager = this.blePlxManager;
|
|
1355
1357
|
const monitorToken = (_a = transport === null || transport === void 0 ? void 0 : transport.monitorToken) !== null && _a !== void 0 ? _a : this.monitorTokens.get(session);
|
|
1356
1358
|
if (transport === null || transport === void 0 ? void 0 : transport.disconnectSubscription) {
|
|
1357
1359
|
try {
|
|
@@ -1373,29 +1375,7 @@ class ReactNativeBleTransport {
|
|
|
1373
1375
|
Log === null || Log === void 0 ? void 0 : Log.error('disconnect: remove notify subscription error: ', e);
|
|
1374
1376
|
}
|
|
1375
1377
|
}
|
|
1376
|
-
if (session) {
|
|
1377
|
-
try {
|
|
1378
|
-
yield ((_c = this.blePlxManager) === null || _c === void 0 ? void 0 : _c.cancelTransaction(session));
|
|
1379
|
-
}
|
|
1380
|
-
catch (e) {
|
|
1381
|
-
Log === null || Log === void 0 ? void 0 : Log.debug('resetSession: cancel transaction error (ignored): ', (e === null || e === void 0 ? void 0 : e.message) || e);
|
|
1382
|
-
}
|
|
1383
|
-
}
|
|
1384
|
-
if (transport === null || transport === void 0 ? void 0 : transport.device) {
|
|
1385
|
-
try {
|
|
1386
|
-
yield transport.device.cancelConnection();
|
|
1387
|
-
}
|
|
1388
|
-
catch (e) {
|
|
1389
|
-
Log === null || Log === void 0 ? void 0 : Log.debug('resetSession: device.cancelConnection error (ignored): ', (e === null || e === void 0 ? void 0 : e.message) || e);
|
|
1390
|
-
}
|
|
1391
|
-
}
|
|
1392
|
-
try {
|
|
1393
|
-
yield ((_d = this.blePlxManager) === null || _d === void 0 ? void 0 : _d.cancelDeviceConnection(session));
|
|
1394
|
-
}
|
|
1395
|
-
catch (e) {
|
|
1396
|
-
Log === null || Log === void 0 ? void 0 : Log.debug('resetSession: manager.cancelDeviceConnection error (ignored): ', (e === null || e === void 0 ? void 0 : e.message) || e);
|
|
1397
|
-
}
|
|
1398
|
-
if (transportCache[session]) {
|
|
1378
|
+
if (!transport || transportCache[session] === transport) {
|
|
1399
1379
|
delete transportCache[session];
|
|
1400
1380
|
}
|
|
1401
1381
|
this.deviceProtocol.delete(session);
|
|
@@ -1406,7 +1386,7 @@ class ReactNativeBleTransport {
|
|
|
1406
1386
|
this.protocolV2Assemblers.delete(session);
|
|
1407
1387
|
this.resetProtocolV2Frames(session);
|
|
1408
1388
|
try {
|
|
1409
|
-
this.emitDeviceDisconnect(session, (
|
|
1389
|
+
this.emitDeviceDisconnect(session, (_c = transport === null || transport === void 0 ? void 0 : transport.device) === null || _c === void 0 ? void 0 : _c.name, monitorToken);
|
|
1410
1390
|
}
|
|
1411
1391
|
catch (e) {
|
|
1412
1392
|
Log === null || Log === void 0 ? void 0 : Log.error('resetSession: emit disconnect event error: ', e);
|
|
@@ -1414,9 +1394,59 @@ class ReactNativeBleTransport {
|
|
|
1414
1394
|
if (monitorToken !== undefined && this.monitorTokens.get(session) === monitorToken) {
|
|
1415
1395
|
this.monitorTokens.delete(session);
|
|
1416
1396
|
}
|
|
1397
|
+
yield this.runNativeTeardown(session, manager, () => __awaiter(this, void 0, void 0, function* () {
|
|
1398
|
+
const operations = [];
|
|
1399
|
+
if (manager) {
|
|
1400
|
+
operations.push(this.runBestEffortNativeOperation('disconnect: cancel transaction', () => manager.cancelTransaction(session)));
|
|
1401
|
+
operations.push(this.runBestEffortNativeOperation('disconnect: cancel device connection', () => manager.cancelDeviceConnection(session)));
|
|
1402
|
+
}
|
|
1403
|
+
if (transport === null || transport === void 0 ? void 0 : transport.device) {
|
|
1404
|
+
operations.push(this.runBestEffortNativeOperation('disconnect: device cancel connection', () => transport.device.cancelConnection()));
|
|
1405
|
+
}
|
|
1406
|
+
yield Promise.all(operations);
|
|
1407
|
+
}));
|
|
1417
1408
|
yield new Promise(resolve => setTimeout(() => resolve(), 100));
|
|
1418
1409
|
});
|
|
1419
1410
|
}
|
|
1411
|
+
runNativeTeardown(uuid, manager, teardown) {
|
|
1412
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
1413
|
+
let timer;
|
|
1414
|
+
let timedOut = false;
|
|
1415
|
+
const pending = Promise.resolve()
|
|
1416
|
+
.then(teardown)
|
|
1417
|
+
.catch(error => {
|
|
1418
|
+
Log === null || Log === void 0 ? void 0 : Log.debug('BLE native teardown error (ignored): ', (error === null || error === void 0 ? void 0 : error.message) || error);
|
|
1419
|
+
});
|
|
1420
|
+
try {
|
|
1421
|
+
yield Promise.race([
|
|
1422
|
+
pending,
|
|
1423
|
+
new Promise(resolve => {
|
|
1424
|
+
timer = setTimeout(() => {
|
|
1425
|
+
timedOut = true;
|
|
1426
|
+
resolve();
|
|
1427
|
+
}, BLE_NATIVE_TEARDOWN_TIMEOUT_MS);
|
|
1428
|
+
}),
|
|
1429
|
+
]);
|
|
1430
|
+
}
|
|
1431
|
+
finally {
|
|
1432
|
+
if (timer)
|
|
1433
|
+
clearTimeout(timer);
|
|
1434
|
+
}
|
|
1435
|
+
if (timedOut) {
|
|
1436
|
+
Log === null || Log === void 0 ? void 0 : Log.error('[ReactNativeBleTransport] BLE native teardown timed out:', uuid);
|
|
1437
|
+
if (this.blePlxManager === manager) {
|
|
1438
|
+
this.resetPlxManager();
|
|
1439
|
+
}
|
|
1440
|
+
}
|
|
1441
|
+
});
|
|
1442
|
+
}
|
|
1443
|
+
runBestEffortNativeOperation(label, operation) {
|
|
1444
|
+
return Promise.resolve()
|
|
1445
|
+
.then(operation)
|
|
1446
|
+
.catch(error => {
|
|
1447
|
+
Log === null || Log === void 0 ? void 0 : Log.debug(`${label} error (ignored): `, (error === null || error === void 0 ? void 0 : error.message) || error);
|
|
1448
|
+
});
|
|
1449
|
+
}
|
|
1420
1450
|
runLifecycleOperation(uuid, operation) {
|
|
1421
1451
|
var _a;
|
|
1422
1452
|
return __awaiter(this, void 0, void 0, function* () {
|
|
@@ -2100,6 +2130,8 @@ class ReactNativeBleTransport {
|
|
|
2100
2130
|
}),
|
|
2101
2131
|
reset: (reason) => {
|
|
2102
2132
|
var _a;
|
|
2133
|
+
if (this.monitorTokens.get(uuid) !== generation)
|
|
2134
|
+
return;
|
|
2103
2135
|
(_a = this.protocolV2Assemblers.get(uuid)) === null || _a === void 0 ? void 0 : _a.reset();
|
|
2104
2136
|
this.rejectProtocolV2Frames(uuid, new Error(reason));
|
|
2105
2137
|
},
|
|
@@ -2116,6 +2148,7 @@ class ReactNativeBleTransport {
|
|
|
2116
2148
|
exports.BLE_CONNECT_TIMEOUT_MANAGER_RESET_THRESHOLD = BLE_CONNECT_TIMEOUT_MANAGER_RESET_THRESHOLD;
|
|
2117
2149
|
exports.BLE_CONNECT_TIMEOUT_MS = BLE_CONNECT_TIMEOUT_MS;
|
|
2118
2150
|
exports.BLE_GATT_SETUP_TIMEOUT_MS = BLE_GATT_SETUP_TIMEOUT_MS;
|
|
2151
|
+
exports.BLE_NATIVE_TEARDOWN_TIMEOUT_MS = BLE_NATIVE_TEARDOWN_TIMEOUT_MS;
|
|
2119
2152
|
exports.BLE_WRITE_PACKET_TIMEOUT_MS = BLE_WRITE_PACKET_TIMEOUT_MS;
|
|
2120
2153
|
exports.BLE_WRITE_TIMEOUT_MANAGER_RESET_THRESHOLD = BLE_WRITE_TIMEOUT_MANAGER_RESET_THRESHOLD;
|
|
2121
2154
|
exports.PROTOCOL_REPROBE_FALLBACK_ATTEMPTS = PROTOCOL_REPROBE_FALLBACK_ATTEMPTS;
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@onekeyfe/hd-transport-react-native",
|
|
3
|
-
"version": "1.2.0-alpha.
|
|
3
|
+
"version": "1.2.0-alpha.131",
|
|
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.0-alpha.
|
|
24
|
-
"@onekeyfe/hd-shared": "1.2.0-alpha.
|
|
25
|
-
"@onekeyfe/hd-transport": "1.2.0-alpha.
|
|
23
|
+
"@onekeyfe/hd-core": "1.2.0-alpha.131",
|
|
24
|
+
"@onekeyfe/hd-shared": "1.2.0-alpha.131",
|
|
25
|
+
"@onekeyfe/hd-transport": "1.2.0-alpha.131",
|
|
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": "81b472e983e80e6aa771b991dc9c0c9b1bdcf07b"
|
|
30
30
|
}
|
|
@@ -7,6 +7,7 @@ import transportPackage, {
|
|
|
7
7
|
import { HardwareErrorCode, createDeferred } from '@onekeyfe/hd-shared';
|
|
8
8
|
|
|
9
9
|
import ReactNativeBleTransport, {
|
|
10
|
+
BLE_NATIVE_TEARDOWN_TIMEOUT_MS,
|
|
10
11
|
BLE_WRITE_PACKET_TIMEOUT_MS,
|
|
11
12
|
configureProtocolV2BleTuning,
|
|
12
13
|
getFirmwareUploadWriteRetryType,
|
|
@@ -174,6 +175,8 @@ const createHarness = ({
|
|
|
174
175
|
devices: jest.fn(() => Promise.resolve([device])),
|
|
175
176
|
connectedDevices: jest.fn(() => Promise.resolve([])),
|
|
176
177
|
cancelTransaction: jest.fn(() => Promise.resolve()),
|
|
178
|
+
cancelDeviceConnection: jest.fn(() => Promise.resolve()),
|
|
179
|
+
destroy: jest.fn(),
|
|
177
180
|
};
|
|
178
181
|
const transport = new ReactNativeBleTransport({ scanTimeout: 1 });
|
|
179
182
|
const emitter = new EventEmitter();
|
|
@@ -192,6 +195,7 @@ const createHarness = ({
|
|
|
192
195
|
logger,
|
|
193
196
|
uuid,
|
|
194
197
|
device,
|
|
198
|
+
bleManager,
|
|
195
199
|
sentSeqs,
|
|
196
200
|
writeCharacteristic,
|
|
197
201
|
setShouldRespond(value: boolean) {
|
|
@@ -457,6 +461,41 @@ describe('ReactNativeBleTransport Protocol V2 link lifecycle', () => {
|
|
|
457
461
|
);
|
|
458
462
|
});
|
|
459
463
|
|
|
464
|
+
test(
|
|
465
|
+
'releases the lifecycle queue when native teardown never settles',
|
|
466
|
+
async () => {
|
|
467
|
+
const { transport, uuid, device, bleManager } = createHarness();
|
|
468
|
+
await transport.acquire({ uuid, expectedProtocol: 'V2' });
|
|
469
|
+
const stalledNativeCleanup = createDeferred<void>();
|
|
470
|
+
bleManager.cancelTransaction
|
|
471
|
+
.mockImplementationOnce(() => stalledNativeCleanup.promise)
|
|
472
|
+
.mockResolvedValue(undefined);
|
|
473
|
+
const resetPlxManager = jest.spyOn(transport as any, 'resetPlxManager');
|
|
474
|
+
const nextLifecycleOperation = jest.fn().mockResolvedValue('next-operation');
|
|
475
|
+
|
|
476
|
+
const release = transport.release(uuid, true);
|
|
477
|
+
const nextOperation = (transport as any).runLifecycleOperation(uuid, nextLifecycleOperation);
|
|
478
|
+
|
|
479
|
+
await expect(release).resolves.toBe(true);
|
|
480
|
+
await expect(nextOperation).resolves.toBe('next-operation');
|
|
481
|
+
expect(resetPlxManager).toHaveBeenCalledTimes(1);
|
|
482
|
+
expect(nextLifecycleOperation).toHaveBeenCalledTimes(1);
|
|
483
|
+
|
|
484
|
+
await (transport as any).installTransportForAcquire(uuid, device);
|
|
485
|
+
(transport as any).deviceProtocol.set(uuid, 'V2');
|
|
486
|
+
|
|
487
|
+
stalledNativeCleanup.resolve();
|
|
488
|
+
await Promise.resolve();
|
|
489
|
+
await expect(
|
|
490
|
+
transport.call(uuid, 'Ping', { message: 'after-stale-cleanup' })
|
|
491
|
+
).resolves.toMatchObject({
|
|
492
|
+
type: 'Success',
|
|
493
|
+
message: { message: 'ok' },
|
|
494
|
+
});
|
|
495
|
+
},
|
|
496
|
+
BLE_NATIVE_TEARDOWN_TIMEOUT_MS + 5_000
|
|
497
|
+
);
|
|
498
|
+
|
|
460
499
|
test('falls back to the other active probe on iOS when protocol metadata is absent', async () => {
|
|
461
500
|
const { transport, uuid } = createHarness({ deviceName: 'OneKey' });
|
|
462
501
|
const probeProtocolV1 = jest
|
package/src/index.ts
CHANGED
|
@@ -149,6 +149,7 @@ const PROTOCOL_V2_PROBE_TIMEOUT_MS = 10_000;
|
|
|
149
149
|
* A healthy packet completes in milliseconds, so this only fires on a dead link.
|
|
150
150
|
*/
|
|
151
151
|
export const BLE_WRITE_PACKET_TIMEOUT_MS = 10_000;
|
|
152
|
+
export const BLE_NATIVE_TEARDOWN_TIMEOUT_MS = 3_000;
|
|
152
153
|
const WEDGED_WRITE_MESSAGE = 'BLE write timeout after';
|
|
153
154
|
const isWedgedWriteError = (error: unknown): boolean =>
|
|
154
155
|
(error as { errorCode?: unknown })?.errorCode === HardwareErrorCode.BleWriteCharacteristicError &&
|
|
@@ -1200,6 +1201,7 @@ export default class ReactNativeBleTransport {
|
|
|
1200
1201
|
|
|
1201
1202
|
private async releaseNative(uuid: string, onclose = false) {
|
|
1202
1203
|
const transport = transportCache[uuid];
|
|
1204
|
+
const manager = this.blePlxManager;
|
|
1203
1205
|
if (this.runPromise && this.runPromiseDeviceId === uuid) {
|
|
1204
1206
|
const error = ERRORS.TypedError(HardwareErrorCode.BleForceCleanRunPromise);
|
|
1205
1207
|
this.runPromise.reject(error);
|
|
@@ -1216,8 +1218,6 @@ export default class ReactNativeBleTransport {
|
|
|
1216
1218
|
return Promise.resolve(true);
|
|
1217
1219
|
}
|
|
1218
1220
|
|
|
1219
|
-
await this.restoreAndroidConnectionPriority(uuid, transport);
|
|
1220
|
-
|
|
1221
1221
|
if (transport) {
|
|
1222
1222
|
if (this.monitorTokens.get(uuid) === transport.monitorToken) {
|
|
1223
1223
|
this.monitorTokens.delete(uuid);
|
|
@@ -1235,16 +1235,9 @@ export default class ReactNativeBleTransport {
|
|
|
1235
1235
|
);
|
|
1236
1236
|
transport.notifySubscription?.remove();
|
|
1237
1237
|
transport.notifySubscription = undefined;
|
|
1238
|
-
|
|
1239
|
-
|
|
1240
|
-
try {
|
|
1241
|
-
await this.blePlxManager?.cancelTransaction(transport.notifyTransactionId);
|
|
1242
|
-
} catch (e) {
|
|
1243
|
-
Log?.debug('release: cancel notify transaction error (ignored): ', e?.message || e);
|
|
1244
|
-
}
|
|
1238
|
+
if (transportCache[uuid] === transport) {
|
|
1239
|
+
delete transportCache[uuid];
|
|
1245
1240
|
}
|
|
1246
|
-
|
|
1247
|
-
delete transportCache[uuid];
|
|
1248
1241
|
}
|
|
1249
1242
|
|
|
1250
1243
|
this.protocolV2HighVolumeLogSignatures.delete(uuid);
|
|
@@ -1256,11 +1249,28 @@ export default class ReactNativeBleTransport {
|
|
|
1256
1249
|
this.protocolV2Assemblers.delete(uuid);
|
|
1257
1250
|
this.resetProtocolV2Frames(uuid);
|
|
1258
1251
|
|
|
1259
|
-
|
|
1260
|
-
|
|
1261
|
-
|
|
1262
|
-
|
|
1263
|
-
|
|
1252
|
+
await this.runNativeTeardown(uuid, manager, async () => {
|
|
1253
|
+
const operations: Promise<unknown>[] = [
|
|
1254
|
+
this.runBestEffortNativeOperation('release: restore connection priority', () =>
|
|
1255
|
+
this.restoreAndroidConnectionPriority(uuid, transport)
|
|
1256
|
+
),
|
|
1257
|
+
];
|
|
1258
|
+
if (transport?.notifyTransactionId && manager) {
|
|
1259
|
+
operations.push(
|
|
1260
|
+
this.runBestEffortNativeOperation('release: cancel notify transaction', () =>
|
|
1261
|
+
manager.cancelTransaction(transport.notifyTransactionId as string)
|
|
1262
|
+
)
|
|
1263
|
+
);
|
|
1264
|
+
}
|
|
1265
|
+
if (manager) {
|
|
1266
|
+
operations.push(
|
|
1267
|
+
this.runBestEffortNativeOperation('release: cancel transaction', () =>
|
|
1268
|
+
manager.cancelTransaction(uuid)
|
|
1269
|
+
)
|
|
1270
|
+
);
|
|
1271
|
+
}
|
|
1272
|
+
await Promise.all(operations);
|
|
1273
|
+
});
|
|
1264
1274
|
|
|
1265
1275
|
return Promise.resolve(true);
|
|
1266
1276
|
}
|
|
@@ -1571,6 +1581,7 @@ export default class ReactNativeBleTransport {
|
|
|
1571
1581
|
private async disconnectUnlocked(session: string) {
|
|
1572
1582
|
await this.protocolV2Links.invalidateLink(session, 'React Native BLE transport disconnected');
|
|
1573
1583
|
const transport = transportCache[session];
|
|
1584
|
+
const manager = this.blePlxManager;
|
|
1574
1585
|
const monitorToken = transport?.monitorToken ?? this.monitorTokens.get(session);
|
|
1575
1586
|
|
|
1576
1587
|
// Clean up disconnect subscription first to prevent onDisconnected callback
|
|
@@ -1599,33 +1610,8 @@ export default class ReactNativeBleTransport {
|
|
|
1599
1610
|
}
|
|
1600
1611
|
}
|
|
1601
1612
|
|
|
1602
|
-
// cancel the ble transaction
|
|
1603
|
-
if (session) {
|
|
1604
|
-
try {
|
|
1605
|
-
await this.blePlxManager?.cancelTransaction(session);
|
|
1606
|
-
} catch (e) {
|
|
1607
|
-
Log?.debug('resetSession: cancel transaction error (ignored): ', e?.message || e);
|
|
1608
|
-
}
|
|
1609
|
-
}
|
|
1610
|
-
|
|
1611
|
-
// disconnect the device via the device object
|
|
1612
|
-
if (transport?.device) {
|
|
1613
|
-
try {
|
|
1614
|
-
await transport.device.cancelConnection();
|
|
1615
|
-
} catch (e) {
|
|
1616
|
-
Log?.debug('resetSession: device.cancelConnection error (ignored): ', e?.message || e);
|
|
1617
|
-
}
|
|
1618
|
-
}
|
|
1619
|
-
|
|
1620
|
-
// disconnect the device via the ble manager
|
|
1621
|
-
try {
|
|
1622
|
-
await this.blePlxManager?.cancelDeviceConnection(session);
|
|
1623
|
-
} catch (e) {
|
|
1624
|
-
Log?.debug('resetSession: manager.cancelDeviceConnection error (ignored): ', e?.message || e);
|
|
1625
|
-
}
|
|
1626
|
-
|
|
1627
1613
|
// clear the transport cache
|
|
1628
|
-
if (transportCache[session]) {
|
|
1614
|
+
if (!transport || transportCache[session] === transport) {
|
|
1629
1615
|
delete transportCache[session];
|
|
1630
1616
|
}
|
|
1631
1617
|
this.deviceProtocol.delete(session);
|
|
@@ -1645,10 +1631,77 @@ export default class ReactNativeBleTransport {
|
|
|
1645
1631
|
if (monitorToken !== undefined && this.monitorTokens.get(session) === monitorToken) {
|
|
1646
1632
|
this.monitorTokens.delete(session);
|
|
1647
1633
|
}
|
|
1634
|
+
|
|
1635
|
+
await this.runNativeTeardown(session, manager, async () => {
|
|
1636
|
+
const operations: Promise<unknown>[] = [];
|
|
1637
|
+
if (manager) {
|
|
1638
|
+
operations.push(
|
|
1639
|
+
this.runBestEffortNativeOperation('disconnect: cancel transaction', () =>
|
|
1640
|
+
manager.cancelTransaction(session)
|
|
1641
|
+
)
|
|
1642
|
+
);
|
|
1643
|
+
operations.push(
|
|
1644
|
+
this.runBestEffortNativeOperation('disconnect: cancel device connection', () =>
|
|
1645
|
+
manager.cancelDeviceConnection(session)
|
|
1646
|
+
)
|
|
1647
|
+
);
|
|
1648
|
+
}
|
|
1649
|
+
if (transport?.device) {
|
|
1650
|
+
operations.push(
|
|
1651
|
+
this.runBestEffortNativeOperation('disconnect: device cancel connection', () =>
|
|
1652
|
+
transport.device.cancelConnection()
|
|
1653
|
+
)
|
|
1654
|
+
);
|
|
1655
|
+
}
|
|
1656
|
+
await Promise.all(operations);
|
|
1657
|
+
});
|
|
1658
|
+
|
|
1648
1659
|
// eslint-disable-next-line no-promise-executor-return
|
|
1649
1660
|
await new Promise<void>(resolve => setTimeout(() => resolve(), 100));
|
|
1650
1661
|
}
|
|
1651
1662
|
|
|
1663
|
+
private async runNativeTeardown(
|
|
1664
|
+
uuid: string,
|
|
1665
|
+
manager: BlePlxManager | undefined,
|
|
1666
|
+
teardown: () => Promise<void>
|
|
1667
|
+
) {
|
|
1668
|
+
let timer: ReturnType<typeof setTimeout> | undefined;
|
|
1669
|
+
let timedOut = false;
|
|
1670
|
+
const pending = Promise.resolve()
|
|
1671
|
+
.then(teardown)
|
|
1672
|
+
.catch(error => {
|
|
1673
|
+
Log?.debug('BLE native teardown error (ignored): ', error?.message || error);
|
|
1674
|
+
});
|
|
1675
|
+
try {
|
|
1676
|
+
await Promise.race([
|
|
1677
|
+
pending,
|
|
1678
|
+
new Promise<void>(resolve => {
|
|
1679
|
+
timer = setTimeout(() => {
|
|
1680
|
+
timedOut = true;
|
|
1681
|
+
resolve();
|
|
1682
|
+
}, BLE_NATIVE_TEARDOWN_TIMEOUT_MS);
|
|
1683
|
+
}),
|
|
1684
|
+
]);
|
|
1685
|
+
} finally {
|
|
1686
|
+
if (timer) clearTimeout(timer);
|
|
1687
|
+
}
|
|
1688
|
+
|
|
1689
|
+
if (timedOut) {
|
|
1690
|
+
Log?.error('[ReactNativeBleTransport] BLE native teardown timed out:', uuid);
|
|
1691
|
+
if (this.blePlxManager === manager) {
|
|
1692
|
+
this.resetPlxManager();
|
|
1693
|
+
}
|
|
1694
|
+
}
|
|
1695
|
+
}
|
|
1696
|
+
|
|
1697
|
+
private runBestEffortNativeOperation(label: string, operation: () => Promise<unknown>) {
|
|
1698
|
+
return Promise.resolve()
|
|
1699
|
+
.then(operation)
|
|
1700
|
+
.catch(error => {
|
|
1701
|
+
Log?.debug(`${label} error (ignored): `, error?.message || error);
|
|
1702
|
+
});
|
|
1703
|
+
}
|
|
1704
|
+
|
|
1652
1705
|
private async runLifecycleOperation<T>(uuid: string, operation: () => Promise<T>): Promise<T> {
|
|
1653
1706
|
const previousOperation = this.lifecycleOperations.get(uuid) ?? Promise.resolve();
|
|
1654
1707
|
let completeOperation!: () => void;
|
|
@@ -2481,6 +2534,7 @@ export default class ReactNativeBleTransport {
|
|
|
2481
2534
|
return rxFrame;
|
|
2482
2535
|
},
|
|
2483
2536
|
reset: (reason: string) => {
|
|
2537
|
+
if (this.monitorTokens.get(uuid) !== generation) return;
|
|
2484
2538
|
this.protocolV2Assemblers.get(uuid)?.reset();
|
|
2485
2539
|
this.rejectProtocolV2Frames(uuid, new Error(reason));
|
|
2486
2540
|
},
|