@onekeyfe/hd-transport-react-native 1.1.27-alpha.31 → 1.1.27-alpha.32

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 CHANGED
@@ -43,9 +43,12 @@ declare class ReactNativeBleTransport {
43
43
  runPromise: Deferred<any> | null;
44
44
  emitter?: EventEmitter;
45
45
  private deviceProtocol;
46
+ private deviceProtocolHints;
46
47
  private protocolV2Assemblers;
47
- private protocolV2FrameQueue;
48
- private protocolV2FramePromise;
48
+ private protocolV2FrameQueues;
49
+ private protocolV2FramePromises;
50
+ private activeProtocolV2Call;
51
+ private nextProtocolV2CallToken;
49
52
  private monitorTokens;
50
53
  private nextMonitorToken;
51
54
  constructor(options: TransportOptions);
@@ -70,12 +73,15 @@ declare class ReactNativeBleTransport {
70
73
  private getCachedTransport;
71
74
  private createProtocolMismatchError;
72
75
  private detectProtocol;
76
+ private resetProbeStateAfterProtocolProbe;
73
77
  private probeProtocolV1;
74
78
  private probeProtocolV2;
75
79
  private handleProtocolV2Notification;
80
+ private getProtocolV2FrameQueue;
76
81
  private resolveProtocolV2Frame;
77
- private rejectProtocolV2Frame;
82
+ private rejectAllProtocolV2Frames;
78
83
  private resetProtocolV2Frames;
84
+ private isActiveProtocolV2Call;
79
85
  private readProtocolV2Frame;
80
86
  private writeProtocolV2Frame;
81
87
  private callProtocolV2;
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"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"}
package/dist/index.js CHANGED
@@ -283,7 +283,7 @@ function resetProtocolV2BleTuning() {
283
283
  function getProtocolV2BleTuning() {
284
284
  return Object.assign({}, protocolV2BleTuning);
285
285
  }
286
- function inferProtocolTypeFromDeviceName(name) {
286
+ function inferProtocolHintFromDeviceName(name) {
287
287
  return /\bpro\s*2\b/i.test(name !== null && name !== void 0 ? name : '') ? 'V2' : undefined;
288
288
  }
289
289
  function getDeviceDisplayName(device) {
@@ -339,9 +339,12 @@ class ReactNativeBleTransport {
339
339
  this.scanTimeout = DEVICE_SCAN_TIMEOUT_MS;
340
340
  this.runPromise = null;
341
341
  this.deviceProtocol = new Map();
342
+ this.deviceProtocolHints = new Map();
342
343
  this.protocolV2Assemblers = new Map();
343
- this.protocolV2FrameQueue = [];
344
- this.protocolV2FramePromise = null;
344
+ this.protocolV2FrameQueues = new Map();
345
+ this.protocolV2FramePromises = new Map();
346
+ this.activeProtocolV2Call = null;
347
+ this.nextProtocolV2CallToken = 1;
345
348
  this.monitorTokens = new Map();
346
349
  this.nextMonitorToken = 1;
347
350
  this.scanTimeout = (_a = options.scanTimeout) !== null && _a !== void 0 ? _a : DEVICE_SCAN_TIMEOUT_MS;
@@ -458,8 +461,11 @@ class ReactNativeBleTransport {
458
461
  var _a;
459
462
  if (deviceList.every(d => d.id !== device.id)) {
460
463
  const displayName = (_a = getDeviceDisplayName(device)) !== null && _a !== void 0 ? _a : 'Unknown BLE Device';
461
- const protocolType = inferProtocolTypeFromDeviceName(displayName);
462
- deviceList.push(Object.assign(Object.assign(Object.assign({}, device), { name: displayName, commType: 'ble' }), (protocolType ? { protocolType } : {})));
464
+ const protocolHint = inferProtocolHintFromDeviceName(displayName);
465
+ if (protocolHint) {
466
+ this.deviceProtocolHints.set(device.id, protocolHint);
467
+ }
468
+ deviceList.push(Object.assign(Object.assign({}, device), { name: displayName, commType: 'ble' }));
463
469
  }
464
470
  };
465
471
  timer.timeout(() => {
@@ -470,7 +476,7 @@ class ReactNativeBleTransport {
470
476
  });
471
477
  }
472
478
  acquire(input) {
473
- var _a, _b, _c, _d, _e;
479
+ var _a, _b, _c, _d, _e, _f;
474
480
  return __awaiter(this, void 0, void 0, function* () {
475
481
  const { uuid, forceCleanRunPromise, expectedProtocol } = input;
476
482
  if (!uuid) {
@@ -484,8 +490,9 @@ class ReactNativeBleTransport {
484
490
  if (forceCleanRunPromise && this.runPromise) {
485
491
  const error = hdShared.ERRORS.TypedError(hdShared.HardwareErrorCode.BleForceCleanRunPromise);
486
492
  this.runPromise.reject(error);
487
- this.rejectProtocolV2Frame(error);
493
+ this.rejectAllProtocolV2Frames(error);
488
494
  this.runPromise = null;
495
+ this.activeProtocolV2Call = null;
489
496
  Log === null || Log === void 0 ? void 0 : Log.debug('Force clean Bluetooth run promise, forceCleanRunPromise: ', forceCleanRunPromise);
490
497
  }
491
498
  const blePlxManager = yield this.getPlxManager();
@@ -638,7 +645,13 @@ class ReactNativeBleTransport {
638
645
  if (!notifyCharacteristic.isNotifiable) {
639
646
  throw hdShared.ERRORS.TypedError('BLECharacteristicNotNotifiable: notify characteristic not notifiable');
640
647
  }
648
+ const protocolHint = expectedProtocol
649
+ ? undefined
650
+ : (_e = this.deviceProtocolHints.get(uuid)) !== null && _e !== void 0 ? _e : inferProtocolHintFromDeviceName(getDeviceDisplayName(device));
641
651
  yield this.release(uuid);
652
+ if (protocolHint) {
653
+ this.deviceProtocolHints.set(uuid, protocolHint);
654
+ }
642
655
  const transport$1 = new BleTransport(device, writeCharacteristic, notifyCharacteristic);
643
656
  const monitorToken = this.nextMonitorToken;
644
657
  this.nextMonitorToken += 1;
@@ -654,8 +667,8 @@ class ReactNativeBleTransport {
654
667
  setTimeout(resolve, IOS_NOTIFY_READY_DELAY_MS);
655
668
  });
656
669
  }
657
- const protocolType = yield this.detectProtocol(uuid, expectedProtocol);
658
- (_e = this.emitter) === null || _e === void 0 ? void 0 : _e.emit('device-connect', {
670
+ const protocolType = yield this.detectProtocol(uuid, expectedProtocol, protocolHint);
671
+ (_f = this.emitter) === null || _f === void 0 ? void 0 : _f.emit('device-connect', {
659
672
  name: device.name,
660
673
  id: device.id,
661
674
  connectId: device.id,
@@ -676,7 +689,7 @@ class ReactNativeBleTransport {
676
689
  if (this.runPromise) {
677
690
  const error = hdShared.ERRORS.TypedError(hdShared.HardwareErrorCode.BleConnectedError);
678
691
  this.runPromise.reject(error);
679
- this.rejectProtocolV2Frame(error);
692
+ this.rejectAllProtocolV2Frames(error);
680
693
  }
681
694
  }
682
695
  catch (e) {
@@ -716,13 +729,13 @@ class ReactNativeBleTransport {
716
729
  ((_g = error.reason) === null || _g === void 0 ? void 0 : _g.includes('notify change failed for device'))) {
717
730
  const notifyError = hdShared.ERRORS.TypedError(hdShared.HardwareErrorCode.BleCharacteristicNotifyChangeFailure);
718
731
  this.runPromise.reject(notifyError);
719
- this.rejectProtocolV2Frame(notifyError);
732
+ this.rejectAllProtocolV2Frames(notifyError);
720
733
  Log === null || Log === void 0 ? void 0 : Log.debug(`${hdShared.HardwareErrorCode.BleCharacteristicNotifyChangeFailure} ${error.message} ${error.reason}`);
721
734
  return;
722
735
  }
723
736
  const notifyError = hdShared.ERRORS.TypedError(ERROR);
724
737
  this.runPromise.reject(notifyError);
725
- this.rejectProtocolV2Frame(notifyError);
738
+ this.rejectAllProtocolV2Frames(notifyError);
726
739
  Log === null || Log === void 0 ? void 0 : Log.debug(': monitor notify error, and has unreleased Promise', Error);
727
740
  }
728
741
  return;
@@ -758,7 +771,7 @@ class ReactNativeBleTransport {
758
771
  Log === null || Log === void 0 ? void 0 : Log.debug('monitor data error: ', error);
759
772
  const notifyError = hdShared.ERRORS.TypedError(hdShared.HardwareErrorCode.BleWriteCharacteristicError);
760
773
  (_j = this.runPromise) === null || _j === void 0 ? void 0 : _j.reject(notifyError);
761
- this.rejectProtocolV2Frame(notifyError);
774
+ this.rejectAllProtocolV2Frames(notifyError);
762
775
  }
763
776
  }, notifyTransactionId);
764
777
  return subscription;
@@ -771,10 +784,11 @@ class ReactNativeBleTransport {
771
784
  const error = hdShared.ERRORS.TypedError(hdShared.HardwareErrorCode.BleForceCleanRunPromise);
772
785
  this.runPromise.reject(error);
773
786
  this.runPromise = null;
774
- this.rejectProtocolV2Frame(error);
787
+ this.rejectAllProtocolV2Frames(error);
788
+ this.activeProtocolV2Call = null;
775
789
  }
776
790
  else {
777
- this.resetProtocolV2Frames();
791
+ this.resetProtocolV2Frames(uuid);
778
792
  }
779
793
  if (transport) {
780
794
  if (this.monitorTokens.get(uuid) === transport.monitorToken) {
@@ -795,10 +809,12 @@ class ReactNativeBleTransport {
795
809
  }
796
810
  }
797
811
  delete transportCache[uuid];
798
- this.deviceProtocol.delete(uuid);
799
812
  }
813
+ this.deviceProtocol.delete(uuid);
814
+ this.deviceProtocolHints.delete(uuid);
800
815
  (_e = this.protocolV2Assemblers.get(uuid)) === null || _e === void 0 ? void 0 : _e.reset();
801
816
  this.protocolV2Assemblers.delete(uuid);
817
+ this.resetProtocolV2Frames(uuid);
802
818
  try {
803
819
  yield ((_f = this.blePlxManager) === null || _f === void 0 ? void 0 : _f.cancelTransaction(uuid));
804
820
  }
@@ -957,7 +973,7 @@ class ReactNativeBleTransport {
957
973
  this.stopped = true;
958
974
  }
959
975
  disconnect(session) {
960
- var _a, _b, _c, _d, _e;
976
+ var _a, _b, _c, _d, _e, _f;
961
977
  return __awaiter(this, void 0, void 0, function* () {
962
978
  Log === null || Log === void 0 ? void 0 : Log.debug('transport-react-native transport resetSession: ', session);
963
979
  const transport = transportCache[session];
@@ -1007,10 +1023,15 @@ class ReactNativeBleTransport {
1007
1023
  delete transportCache[session];
1008
1024
  }
1009
1025
  this.deviceProtocol.delete(session);
1026
+ this.deviceProtocolHints.delete(session);
1010
1027
  this.protocolV2Assemblers.delete(session);
1028
+ this.resetProtocolV2Frames(session);
1029
+ if (((_d = this.activeProtocolV2Call) === null || _d === void 0 ? void 0 : _d.uuid) === session) {
1030
+ this.activeProtocolV2Call = null;
1031
+ }
1011
1032
  try {
1012
- (_d = this.emitter) === null || _d === void 0 ? void 0 : _d.emit('device-disconnect', {
1013
- name: (_e = transport === null || transport === void 0 ? void 0 : transport.device) === null || _e === void 0 ? void 0 : _e.name,
1033
+ (_e = this.emitter) === null || _e === void 0 ? void 0 : _e.emit('device-disconnect', {
1034
+ name: (_f = transport === null || transport === void 0 ? void 0 : transport.device) === null || _f === void 0 ? void 0 : _f.name,
1014
1035
  id: session,
1015
1036
  connectId: session,
1016
1037
  });
@@ -1036,7 +1057,7 @@ class ReactNativeBleTransport {
1036
1057
  createProtocolMismatchError(expected) {
1037
1058
  return hdShared.ERRORS.TypedError(hdShared.HardwareErrorCode.RuntimeError, `Device protocol mismatch: expected ${expected}, but device did not respond to expected protocol`);
1038
1059
  }
1039
- detectProtocol(uuid, expectedProtocol) {
1060
+ detectProtocol(uuid, expectedProtocol, protocolHint) {
1040
1061
  return __awaiter(this, void 0, void 0, function* () {
1041
1062
  if (expectedProtocol === 'V1') {
1042
1063
  if (yield this.probeProtocolV1(uuid)) {
@@ -1054,20 +1075,73 @@ class ReactNativeBleTransport {
1054
1075
  }
1055
1076
  throw this.createProtocolMismatchError(expectedProtocol);
1056
1077
  }
1078
+ if (protocolHint === 'V2' && (yield this.probeProtocolV2(uuid))) {
1079
+ this.deviceProtocol.set(uuid, 'V2');
1080
+ Log === null || Log === void 0 ? void 0 : Log.debug(`[ReactNativeBleTransport] detectProtocol: uuid=${uuid} -> V2 (hint)`);
1081
+ return 'V2';
1082
+ }
1057
1083
  if (this.deviceProtocol.get(uuid) === 'V2' && (yield this.probeProtocolV2(uuid))) {
1058
1084
  this.deviceProtocol.set(uuid, 'V2');
1059
1085
  Log === null || Log === void 0 ? void 0 : Log.debug(`[ReactNativeBleTransport] detectProtocol: uuid=${uuid} -> V2 (cached)`);
1060
1086
  return 'V2';
1061
1087
  }
1062
1088
  let protocol = 'V1';
1063
- if (!(yield this.probeProtocolV1(uuid)) && (yield this.probeProtocolV2(uuid))) {
1064
- protocol = 'V2';
1089
+ const protocolV1Detected = yield this.probeProtocolV1(uuid);
1090
+ if (!protocolV1Detected) {
1091
+ yield this.resetProbeStateAfterProtocolProbe(uuid, 'V1');
1092
+ if (yield this.probeProtocolV2(uuid)) {
1093
+ protocol = 'V2';
1094
+ }
1065
1095
  }
1066
1096
  this.deviceProtocol.set(uuid, protocol);
1067
1097
  Log === null || Log === void 0 ? void 0 : Log.debug(`[ReactNativeBleTransport] detectProtocol: uuid=${uuid} -> ${protocol}`);
1068
1098
  return protocol;
1069
1099
  });
1070
1100
  }
1101
+ resetProbeStateAfterProtocolProbe(uuid, protocol) {
1102
+ var _a, _b, _c, _d;
1103
+ return __awaiter(this, void 0, void 0, function* () {
1104
+ const transport = transportCache[uuid];
1105
+ (_a = this.protocolV2Assemblers.get(uuid)) === null || _a === void 0 ? void 0 : _a.reset();
1106
+ this.resetProtocolV2Frames(uuid);
1107
+ if (((_b = this.activeProtocolV2Call) === null || _b === void 0 ? void 0 : _b.uuid) === uuid) {
1108
+ this.activeProtocolV2Call = null;
1109
+ }
1110
+ if (this.runPromise) {
1111
+ const error = hdShared.ERRORS.TypedError(hdShared.HardwareErrorCode.BleForceCleanRunPromise);
1112
+ this.runPromise.reject(error);
1113
+ this.runPromise = null;
1114
+ }
1115
+ if (!transport)
1116
+ return;
1117
+ const previousNotifyTransactionId = transport.notifyTransactionId;
1118
+ if (this.monitorTokens.get(uuid) === transport.monitorToken) {
1119
+ this.monitorTokens.delete(uuid);
1120
+ }
1121
+ (_c = transport.notifySubscription) === null || _c === void 0 ? void 0 : _c.remove();
1122
+ transport.notifySubscription = undefined;
1123
+ if (previousNotifyTransactionId) {
1124
+ try {
1125
+ yield ((_d = this.blePlxManager) === null || _d === void 0 ? void 0 : _d.cancelTransaction(previousNotifyTransactionId));
1126
+ }
1127
+ catch (error) {
1128
+ Log === null || Log === void 0 ? void 0 : Log.debug(`[ReactNativeBleTransport] cancel notify after Protocol ${protocol} probe failed:`, (error === null || error === void 0 ? void 0 : error.message) || error);
1129
+ }
1130
+ }
1131
+ const monitorToken = this.nextMonitorToken;
1132
+ this.nextMonitorToken += 1;
1133
+ const notifyTransactionId = `${uuid}:notify:${monitorToken}`;
1134
+ transport.monitorToken = monitorToken;
1135
+ transport.notifyTransactionId = notifyTransactionId;
1136
+ this.monitorTokens.set(uuid, monitorToken);
1137
+ transport.notifySubscription = this._monitorCharacteristic(transport.notifyCharacteristic, uuid, monitorToken, notifyTransactionId);
1138
+ if (reactNative.Platform.OS === 'ios') {
1139
+ yield new Promise(resolve => {
1140
+ setTimeout(resolve, IOS_NOTIFY_READY_DELAY_MS);
1141
+ });
1142
+ }
1143
+ });
1144
+ }
1071
1145
  probeProtocolV1(uuid) {
1072
1146
  return __awaiter(this, void 0, void 0, function* () {
1073
1147
  if (!this._messages) {
@@ -1100,17 +1174,17 @@ class ReactNativeBleTransport {
1100
1174
  onProbeFailed: () => {
1101
1175
  var _a;
1102
1176
  (_a = this.protocolV2Assemblers.get(uuid)) === null || _a === void 0 ? void 0 : _a.reset();
1103
- this.resetProtocolV2Frames();
1177
+ this.resetProtocolV2Frames(uuid);
1104
1178
  },
1105
1179
  });
1106
1180
  });
1107
1181
  }
1108
1182
  handleProtocolV2Notification(uuid, data) {
1109
- var _a, _b;
1183
+ var _a, _b, _c;
1110
1184
  try {
1111
- if (!this.runPromise) {
1112
- (_a = this.protocolV2Assemblers.get(uuid)) === null || _a === void 0 ? void 0 : _a.reset();
1113
- this.resetProtocolV2Frames();
1185
+ if (!this.runPromise || ((_a = this.activeProtocolV2Call) === null || _a === void 0 ? void 0 : _a.uuid) !== uuid) {
1186
+ (_b = this.protocolV2Assemblers.get(uuid)) === null || _b === void 0 ? void 0 : _b.reset();
1187
+ this.resetProtocolV2Frames(uuid);
1114
1188
  return;
1115
1189
  }
1116
1190
  if (data.length === 0)
@@ -1120,50 +1194,63 @@ class ReactNativeBleTransport {
1120
1194
  return;
1121
1195
  let frameData = assembler.push(data);
1122
1196
  while (frameData) {
1123
- this.resolveProtocolV2Frame(frameData);
1197
+ this.resolveProtocolV2Frame(uuid, frameData);
1124
1198
  frameData = assembler.push(new Uint8Array(0));
1125
1199
  }
1126
1200
  }
1127
1201
  catch (error) {
1128
1202
  Log === null || Log === void 0 ? void 0 : Log.debug('[ReactNativeBleTransport] Protocol V2 notification error:', error);
1129
1203
  const notifyError = hdShared.ERRORS.TypedError(hdShared.HardwareErrorCode.BleWriteCharacteristicError);
1130
- (_b = this.runPromise) === null || _b === void 0 ? void 0 : _b.reject(notifyError);
1131
- this.rejectProtocolV2Frame(notifyError);
1204
+ (_c = this.runPromise) === null || _c === void 0 ? void 0 : _c.reject(notifyError);
1205
+ this.rejectAllProtocolV2Frames(notifyError);
1132
1206
  }
1133
1207
  }
1134
- resolveProtocolV2Frame(frame) {
1135
- if (this.protocolV2FramePromise) {
1136
- this.protocolV2FramePromise.resolve(frame);
1137
- this.protocolV2FramePromise = null;
1208
+ getProtocolV2FrameQueue(uuid) {
1209
+ let queue = this.protocolV2FrameQueues.get(uuid);
1210
+ if (!queue) {
1211
+ queue = [];
1212
+ this.protocolV2FrameQueues.set(uuid, queue);
1213
+ }
1214
+ return queue;
1215
+ }
1216
+ resolveProtocolV2Frame(uuid, frame) {
1217
+ const framePromise = this.protocolV2FramePromises.get(uuid);
1218
+ if (framePromise) {
1219
+ framePromise.resolve(frame);
1220
+ this.protocolV2FramePromises.delete(uuid);
1138
1221
  return;
1139
1222
  }
1140
- this.protocolV2FrameQueue.push(frame);
1223
+ this.getProtocolV2FrameQueue(uuid).push(frame);
1141
1224
  }
1142
- rejectProtocolV2Frame(error) {
1143
- this.protocolV2FrameQueue = [];
1144
- if (this.protocolV2FramePromise) {
1145
- this.protocolV2FramePromise.reject(error);
1146
- this.protocolV2FramePromise = null;
1225
+ rejectAllProtocolV2Frames(error) {
1226
+ this.protocolV2FrameQueues.clear();
1227
+ for (const framePromise of this.protocolV2FramePromises.values()) {
1228
+ framePromise.reject(error);
1147
1229
  }
1230
+ this.protocolV2FramePromises.clear();
1231
+ }
1232
+ resetProtocolV2Frames(uuid) {
1233
+ this.protocolV2FrameQueues.delete(uuid);
1234
+ this.protocolV2FramePromises.delete(uuid);
1148
1235
  }
1149
- resetProtocolV2Frames() {
1150
- this.protocolV2FrameQueue = [];
1151
- this.protocolV2FramePromise = null;
1236
+ isActiveProtocolV2Call(uuid, token) {
1237
+ var _a;
1238
+ return ((_a = this.activeProtocolV2Call) === null || _a === void 0 ? void 0 : _a.uuid) === uuid && this.activeProtocolV2Call.token === token;
1152
1239
  }
1153
- readProtocolV2Frame() {
1240
+ readProtocolV2Frame(uuid) {
1154
1241
  return __awaiter(this, void 0, void 0, function* () {
1155
- const queuedFrame = this.protocolV2FrameQueue.shift();
1242
+ const queuedFrame = this.getProtocolV2FrameQueue(uuid).shift();
1156
1243
  if (queuedFrame) {
1157
1244
  return queuedFrame;
1158
1245
  }
1159
1246
  const framePromise = hdShared.createDeferred();
1160
- this.protocolV2FramePromise = framePromise;
1247
+ this.protocolV2FramePromises.set(uuid, framePromise);
1161
1248
  try {
1162
1249
  return yield framePromise.promise;
1163
1250
  }
1164
1251
  finally {
1165
- if (this.protocolV2FramePromise === framePromise) {
1166
- this.protocolV2FramePromise = null;
1252
+ if (this.protocolV2FramePromises.get(uuid) === framePromise) {
1253
+ this.protocolV2FramePromises.delete(uuid);
1167
1254
  }
1168
1255
  }
1169
1256
  });
@@ -1222,15 +1309,18 @@ class ReactNativeBleTransport {
1222
1309
  }
1223
1310
  const error = hdShared.ERRORS.TypedError(hdShared.HardwareErrorCode.BleForceCleanRunPromise);
1224
1311
  this.runPromise.reject(error);
1225
- this.rejectProtocolV2Frame(error);
1312
+ this.rejectAllProtocolV2Frames(error);
1226
1313
  this.runPromise = null;
1314
+ this.activeProtocolV2Call = null;
1227
1315
  }
1228
1316
  const transport$1 = this.getCachedTransport(uuid);
1229
1317
  const runPromise = hdShared.createDeferred();
1230
1318
  runPromise.promise.catch(() => undefined);
1231
1319
  this.runPromise = runPromise;
1320
+ const callToken = this.nextProtocolV2CallToken++;
1321
+ this.activeProtocolV2Call = { uuid, token: callToken };
1232
1322
  (_a = this.protocolV2Assemblers.get(uuid)) === null || _a === void 0 ? void 0 : _a.reset();
1233
- this.resetProtocolV2Frames();
1323
+ this.resetProtocolV2Frames(uuid);
1234
1324
  let completed = false;
1235
1325
  const callOptions = Object.assign(Object.assign({}, options), { timeoutMs: (_b = options === null || options === void 0 ? void 0 : options.timeoutMs) !== null && _b !== void 0 ? _b : BLE_RESPONSE_TIMEOUT_MS });
1236
1326
  const highVolumeWrite = transport.LogBlockCommand.has(name);
@@ -1253,7 +1343,7 @@ class ReactNativeBleTransport {
1253
1343
  router: transport.PROTOCOL_V2_CHANNEL_BLE_UART,
1254
1344
  writeFrame: (frame) => this.writeProtocolV2Frame(transport$1, frame, { highVolume: highVolumeWrite }),
1255
1345
  readFrame: () => __awaiter(this, void 0, void 0, function* () {
1256
- const rxFrame = yield this.readProtocolV2Frame();
1346
+ const rxFrame = yield this.readProtocolV2Frame(uuid);
1257
1347
  if (!(rxFrame instanceof Uint8Array)) {
1258
1348
  throw new Error('Protocol V2 response is not Uint8Array');
1259
1349
  }
@@ -1268,16 +1358,21 @@ class ReactNativeBleTransport {
1268
1358
  return result;
1269
1359
  }
1270
1360
  catch (e) {
1271
- (_c = this.protocolV2Assemblers.get(uuid)) === null || _c === void 0 ? void 0 : _c.reset();
1272
- this.resetProtocolV2Frames();
1361
+ if (this.isActiveProtocolV2Call(uuid, callToken)) {
1362
+ (_c = this.protocolV2Assemblers.get(uuid)) === null || _c === void 0 ? void 0 : _c.reset();
1363
+ this.resetProtocolV2Frames(uuid);
1364
+ }
1273
1365
  Log === null || Log === void 0 ? void 0 : Log.error('[ReactNativeBleTransport] Protocol V2 call error:', e);
1274
1366
  throw e;
1275
1367
  }
1276
1368
  finally {
1277
- if (!completed) {
1278
- (_d = this.protocolV2Assemblers.get(uuid)) === null || _d === void 0 ? void 0 : _d.reset();
1369
+ if (this.isActiveProtocolV2Call(uuid, callToken)) {
1370
+ if (!completed) {
1371
+ (_d = this.protocolV2Assemblers.get(uuid)) === null || _d === void 0 ? void 0 : _d.reset();
1372
+ }
1373
+ this.resetProtocolV2Frames(uuid);
1374
+ this.activeProtocolV2Call = null;
1279
1375
  }
1280
- this.resetProtocolV2Frames();
1281
1376
  if (this.runPromise === runPromise) {
1282
1377
  this.runPromise = null;
1283
1378
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@onekeyfe/hd-transport-react-native",
3
- "version": "1.1.27-alpha.31",
3
+ "version": "1.1.27-alpha.32",
4
4
  "homepage": "https://github.com/OneKeyHQ/hardware-js-sdk#readme",
5
5
  "license": "MIT",
6
6
  "main": "dist/index.js",
@@ -19,11 +19,11 @@
19
19
  "lint:fix": "eslint . --fix"
20
20
  },
21
21
  "dependencies": {
22
- "@onekeyfe/hd-core": "1.1.27-alpha.31",
23
- "@onekeyfe/hd-shared": "1.1.27-alpha.31",
24
- "@onekeyfe/hd-transport": "1.1.27-alpha.31",
22
+ "@onekeyfe/hd-core": "1.1.27-alpha.32",
23
+ "@onekeyfe/hd-shared": "1.1.27-alpha.32",
24
+ "@onekeyfe/hd-transport": "1.1.27-alpha.32",
25
25
  "@onekeyfe/react-native-ble-utils": "^0.1.4",
26
26
  "react-native-ble-plx": "3.5.1"
27
27
  },
28
- "gitHead": "73a8ecbc0e5e47038966b2f9a5ab30dc2f947d8f"
28
+ "gitHead": "04f92052a18dcf17e4a347f3003b4c4bbf062681"
29
29
  }
package/src/index.ts CHANGED
@@ -125,7 +125,7 @@ export function getProtocolV2BleTuning() {
125
125
  return { ...protocolV2BleTuning };
126
126
  }
127
127
 
128
- function inferProtocolTypeFromDeviceName(name?: string | null): ProtocolType | undefined {
128
+ function inferProtocolHintFromDeviceName(name?: string | null): ProtocolType | undefined {
129
129
  return /\bpro\s*2\b/i.test(name ?? '') ? 'V2' : undefined;
130
130
  }
131
131
 
@@ -214,11 +214,17 @@ export default class ReactNativeBleTransport {
214
214
  /** Per-device protocol type detected by active wire-level probe after connect. */
215
215
  private deviceProtocol: Map<string, ProtocolType> = new Map();
216
216
 
217
+ private deviceProtocolHints: Map<string, ProtocolType> = new Map();
218
+
217
219
  private protocolV2Assemblers: Map<string, ProtocolV2FrameAssembler> = new Map();
218
220
 
219
- private protocolV2FrameQueue: Uint8Array[] = [];
221
+ private protocolV2FrameQueues: Map<string, Uint8Array[]> = new Map();
222
+
223
+ private protocolV2FramePromises: Map<string, Deferred<Uint8Array>> = new Map();
220
224
 
221
- private protocolV2FramePromise: Deferred<Uint8Array> | null = null;
225
+ private activeProtocolV2Call: { uuid: string; token: number } | null = null;
226
+
227
+ private nextProtocolV2CallToken = 1;
222
228
 
223
229
  private monitorTokens: Map<string, number> = new Map();
224
230
 
@@ -370,12 +376,14 @@ export default class ReactNativeBleTransport {
370
376
  const addDevice = (device: Device) => {
371
377
  if (deviceList.every(d => d.id !== device.id)) {
372
378
  const displayName = getDeviceDisplayName(device) ?? 'Unknown BLE Device';
373
- const protocolType = inferProtocolTypeFromDeviceName(displayName);
379
+ const protocolHint = inferProtocolHintFromDeviceName(displayName);
380
+ if (protocolHint) {
381
+ this.deviceProtocolHints.set(device.id, protocolHint);
382
+ }
374
383
  deviceList.push({
375
384
  ...device,
376
385
  name: displayName,
377
386
  commType: 'ble',
378
- ...(protocolType ? { protocolType } : {}),
379
387
  } as IOneKeyDevice);
380
388
  }
381
389
  };
@@ -408,8 +416,9 @@ export default class ReactNativeBleTransport {
408
416
  if (forceCleanRunPromise && this.runPromise) {
409
417
  const error = ERRORS.TypedError(HardwareErrorCode.BleForceCleanRunPromise);
410
418
  this.runPromise.reject(error);
411
- this.rejectProtocolV2Frame(error);
419
+ this.rejectAllProtocolV2Frames(error);
412
420
  this.runPromise = null;
421
+ this.activeProtocolV2Call = null;
413
422
  Log?.debug('Force clean Bluetooth run promise, forceCleanRunPromise: ', forceCleanRunPromise);
414
423
  }
415
424
 
@@ -591,8 +600,16 @@ export default class ReactNativeBleTransport {
591
600
  );
592
601
  }
593
602
 
603
+ const protocolHint = expectedProtocol
604
+ ? undefined
605
+ : this.deviceProtocolHints.get(uuid) ??
606
+ inferProtocolHintFromDeviceName(getDeviceDisplayName(device));
607
+
594
608
  // release transport before new transport instance
595
609
  await this.release(uuid);
610
+ if (protocolHint) {
611
+ this.deviceProtocolHints.set(uuid, protocolHint);
612
+ }
596
613
 
597
614
  const transport = new BleTransport(device, writeCharacteristic, notifyCharacteristic);
598
615
  const monitorToken = this.nextMonitorToken;
@@ -617,7 +634,7 @@ export default class ReactNativeBleTransport {
617
634
  });
618
635
  }
619
636
 
620
- const protocolType = await this.detectProtocol(uuid, expectedProtocol);
637
+ const protocolType = await this.detectProtocol(uuid, expectedProtocol, protocolHint);
621
638
 
622
639
  this.emitter?.emit('device-connect', {
623
640
  name: device.name,
@@ -641,7 +658,7 @@ export default class ReactNativeBleTransport {
641
658
  if (this.runPromise) {
642
659
  const error = ERRORS.TypedError(HardwareErrorCode.BleConnectedError);
643
660
  this.runPromise.reject(error);
644
- this.rejectProtocolV2Frame(error);
661
+ this.rejectAllProtocolV2Frames(error);
645
662
  }
646
663
  } catch (e) {
647
664
  Log?.debug('device disconnect error: ', e);
@@ -696,7 +713,7 @@ export default class ReactNativeBleTransport {
696
713
  HardwareErrorCode.BleCharacteristicNotifyChangeFailure
697
714
  );
698
715
  this.runPromise.reject(notifyError);
699
- this.rejectProtocolV2Frame(notifyError);
716
+ this.rejectAllProtocolV2Frames(notifyError);
700
717
  Log?.debug(
701
718
  `${HardwareErrorCode.BleCharacteristicNotifyChangeFailure} ${error.message} ${error.reason}`
702
719
  );
@@ -704,7 +721,7 @@ export default class ReactNativeBleTransport {
704
721
  }
705
722
  const notifyError = ERRORS.TypedError(ERROR);
706
723
  this.runPromise.reject(notifyError);
707
- this.rejectProtocolV2Frame(notifyError);
724
+ this.rejectAllProtocolV2Frames(notifyError);
708
725
  Log?.debug(': monitor notify error, and has unreleased Promise', Error);
709
726
  }
710
727
 
@@ -750,7 +767,7 @@ export default class ReactNativeBleTransport {
750
767
  Log?.debug('monitor data error: ', error);
751
768
  const notifyError = ERRORS.TypedError(HardwareErrorCode.BleWriteCharacteristicError);
752
769
  this.runPromise?.reject(notifyError);
753
- this.rejectProtocolV2Frame(notifyError);
770
+ this.rejectAllProtocolV2Frames(notifyError);
754
771
  }
755
772
  }, notifyTransactionId);
756
773
 
@@ -763,9 +780,10 @@ export default class ReactNativeBleTransport {
763
780
  const error = ERRORS.TypedError(HardwareErrorCode.BleForceCleanRunPromise);
764
781
  this.runPromise.reject(error);
765
782
  this.runPromise = null;
766
- this.rejectProtocolV2Frame(error);
783
+ this.rejectAllProtocolV2Frames(error);
784
+ this.activeProtocolV2Call = null;
767
785
  } else {
768
- this.resetProtocolV2Frames();
786
+ this.resetProtocolV2Frames(uuid);
769
787
  }
770
788
 
771
789
  if (transport) {
@@ -795,11 +813,13 @@ export default class ReactNativeBleTransport {
795
813
  }
796
814
 
797
815
  delete transportCache[uuid];
798
- this.deviceProtocol.delete(uuid);
799
816
  }
800
817
 
818
+ this.deviceProtocol.delete(uuid);
819
+ this.deviceProtocolHints.delete(uuid);
801
820
  this.protocolV2Assemblers.get(uuid)?.reset();
802
821
  this.protocolV2Assemblers.delete(uuid);
822
+ this.resetProtocolV2Frames(uuid);
803
823
 
804
824
  try {
805
825
  await this.blePlxManager?.cancelTransaction(uuid);
@@ -1053,7 +1073,12 @@ export default class ReactNativeBleTransport {
1053
1073
  delete transportCache[session];
1054
1074
  }
1055
1075
  this.deviceProtocol.delete(session);
1076
+ this.deviceProtocolHints.delete(session);
1056
1077
  this.protocolV2Assemblers.delete(session);
1078
+ this.resetProtocolV2Frames(session);
1079
+ if (this.activeProtocolV2Call?.uuid === session) {
1080
+ this.activeProtocolV2Call = null;
1081
+ }
1057
1082
 
1058
1083
  // emit the disconnect event
1059
1084
  try {
@@ -1094,7 +1119,8 @@ export default class ReactNativeBleTransport {
1094
1119
 
1095
1120
  private async detectProtocol(
1096
1121
  uuid: string,
1097
- expectedProtocol?: ProtocolType
1122
+ expectedProtocol?: ProtocolType,
1123
+ protocolHint?: ProtocolType
1098
1124
  ): Promise<ProtocolType> {
1099
1125
  if (expectedProtocol === 'V1') {
1100
1126
  if (await this.probeProtocolV1(uuid)) {
@@ -1114,6 +1140,12 @@ export default class ReactNativeBleTransport {
1114
1140
  throw this.createProtocolMismatchError(expectedProtocol);
1115
1141
  }
1116
1142
 
1143
+ if (protocolHint === 'V2' && (await this.probeProtocolV2(uuid))) {
1144
+ this.deviceProtocol.set(uuid, 'V2');
1145
+ Log?.debug(`[ReactNativeBleTransport] detectProtocol: uuid=${uuid} -> V2 (hint)`);
1146
+ return 'V2';
1147
+ }
1148
+
1117
1149
  if (this.deviceProtocol.get(uuid) === 'V2' && (await this.probeProtocolV2(uuid))) {
1118
1150
  this.deviceProtocol.set(uuid, 'V2');
1119
1151
  Log?.debug(`[ReactNativeBleTransport] detectProtocol: uuid=${uuid} -> V2 (cached)`);
@@ -1121,14 +1153,69 @@ export default class ReactNativeBleTransport {
1121
1153
  }
1122
1154
 
1123
1155
  let protocol: ProtocolType = 'V1';
1124
- if (!(await this.probeProtocolV1(uuid)) && (await this.probeProtocolV2(uuid))) {
1125
- protocol = 'V2';
1156
+ const protocolV1Detected = await this.probeProtocolV1(uuid);
1157
+ if (!protocolV1Detected) {
1158
+ await this.resetProbeStateAfterProtocolProbe(uuid, 'V1');
1159
+ if (await this.probeProtocolV2(uuid)) {
1160
+ protocol = 'V2';
1161
+ }
1126
1162
  }
1127
1163
  this.deviceProtocol.set(uuid, protocol);
1128
1164
  Log?.debug(`[ReactNativeBleTransport] detectProtocol: uuid=${uuid} -> ${protocol}`);
1129
1165
  return protocol;
1130
1166
  }
1131
1167
 
1168
+ private async resetProbeStateAfterProtocolProbe(uuid: string, protocol: ProtocolType) {
1169
+ const transport = transportCache[uuid];
1170
+ this.protocolV2Assemblers.get(uuid)?.reset();
1171
+ this.resetProtocolV2Frames(uuid);
1172
+ if (this.activeProtocolV2Call?.uuid === uuid) {
1173
+ this.activeProtocolV2Call = null;
1174
+ }
1175
+ if (this.runPromise) {
1176
+ const error = ERRORS.TypedError(HardwareErrorCode.BleForceCleanRunPromise);
1177
+ this.runPromise.reject(error);
1178
+ this.runPromise = null;
1179
+ }
1180
+
1181
+ if (!transport) return;
1182
+
1183
+ const previousNotifyTransactionId = transport.notifyTransactionId;
1184
+ if (this.monitorTokens.get(uuid) === transport.monitorToken) {
1185
+ this.monitorTokens.delete(uuid);
1186
+ }
1187
+ transport.notifySubscription?.remove();
1188
+ transport.notifySubscription = undefined;
1189
+ if (previousNotifyTransactionId) {
1190
+ try {
1191
+ await this.blePlxManager?.cancelTransaction(previousNotifyTransactionId);
1192
+ } catch (error) {
1193
+ Log?.debug(
1194
+ `[ReactNativeBleTransport] cancel notify after Protocol ${protocol} probe failed:`,
1195
+ error?.message || error
1196
+ );
1197
+ }
1198
+ }
1199
+
1200
+ const monitorToken = this.nextMonitorToken;
1201
+ this.nextMonitorToken += 1;
1202
+ const notifyTransactionId = `${uuid}:notify:${monitorToken}`;
1203
+ transport.monitorToken = monitorToken;
1204
+ transport.notifyTransactionId = notifyTransactionId;
1205
+ this.monitorTokens.set(uuid, monitorToken);
1206
+ transport.notifySubscription = this._monitorCharacteristic(
1207
+ transport.notifyCharacteristic,
1208
+ uuid,
1209
+ monitorToken,
1210
+ notifyTransactionId
1211
+ );
1212
+ if (Platform.OS === 'ios') {
1213
+ await new Promise<void>(resolve => {
1214
+ setTimeout(resolve, IOS_NOTIFY_READY_DELAY_MS);
1215
+ });
1216
+ }
1217
+ }
1218
+
1132
1219
  private async probeProtocolV1(uuid: string) {
1133
1220
  if (!this._messages) {
1134
1221
  return false;
@@ -1159,16 +1246,16 @@ export default class ReactNativeBleTransport {
1159
1246
  logPrefix: 'ProtocolV2 RN-BLE',
1160
1247
  onProbeFailed: () => {
1161
1248
  this.protocolV2Assemblers.get(uuid)?.reset();
1162
- this.resetProtocolV2Frames();
1249
+ this.resetProtocolV2Frames(uuid);
1163
1250
  },
1164
1251
  });
1165
1252
  }
1166
1253
 
1167
1254
  private handleProtocolV2Notification(uuid: string, data: Uint8Array) {
1168
1255
  try {
1169
- if (!this.runPromise) {
1256
+ if (!this.runPromise || this.activeProtocolV2Call?.uuid !== uuid) {
1170
1257
  this.protocolV2Assemblers.get(uuid)?.reset();
1171
- this.resetProtocolV2Frames();
1258
+ this.resetProtocolV2Frames(uuid);
1172
1259
  return;
1173
1260
  }
1174
1261
 
@@ -1179,52 +1266,66 @@ export default class ReactNativeBleTransport {
1179
1266
 
1180
1267
  let frameData = assembler.push(data);
1181
1268
  while (frameData) {
1182
- this.resolveProtocolV2Frame(frameData);
1269
+ this.resolveProtocolV2Frame(uuid, frameData);
1183
1270
  frameData = assembler.push(new Uint8Array(0));
1184
1271
  }
1185
1272
  } catch (error) {
1186
1273
  Log?.debug('[ReactNativeBleTransport] Protocol V2 notification error:', error);
1187
1274
  const notifyError = ERRORS.TypedError(HardwareErrorCode.BleWriteCharacteristicError);
1188
1275
  this.runPromise?.reject(notifyError);
1189
- this.rejectProtocolV2Frame(notifyError);
1276
+ this.rejectAllProtocolV2Frames(notifyError);
1277
+ }
1278
+ }
1279
+
1280
+ private getProtocolV2FrameQueue(uuid: string) {
1281
+ let queue = this.protocolV2FrameQueues.get(uuid);
1282
+ if (!queue) {
1283
+ queue = [];
1284
+ this.protocolV2FrameQueues.set(uuid, queue);
1190
1285
  }
1286
+ return queue;
1191
1287
  }
1192
1288
 
1193
- private resolveProtocolV2Frame(frame: Uint8Array) {
1194
- if (this.protocolV2FramePromise) {
1195
- this.protocolV2FramePromise.resolve(frame);
1196
- this.protocolV2FramePromise = null;
1289
+ private resolveProtocolV2Frame(uuid: string, frame: Uint8Array) {
1290
+ const framePromise = this.protocolV2FramePromises.get(uuid);
1291
+ if (framePromise) {
1292
+ framePromise.resolve(frame);
1293
+ this.protocolV2FramePromises.delete(uuid);
1197
1294
  return;
1198
1295
  }
1199
- this.protocolV2FrameQueue.push(frame);
1296
+ this.getProtocolV2FrameQueue(uuid).push(frame);
1200
1297
  }
1201
1298
 
1202
- private rejectProtocolV2Frame(error: Error) {
1203
- this.protocolV2FrameQueue = [];
1204
- if (this.protocolV2FramePromise) {
1205
- this.protocolV2FramePromise.reject(error);
1206
- this.protocolV2FramePromise = null;
1299
+ private rejectAllProtocolV2Frames(error: Error) {
1300
+ this.protocolV2FrameQueues.clear();
1301
+ for (const framePromise of this.protocolV2FramePromises.values()) {
1302
+ framePromise.reject(error);
1207
1303
  }
1304
+ this.protocolV2FramePromises.clear();
1305
+ }
1306
+
1307
+ private resetProtocolV2Frames(uuid: string) {
1308
+ this.protocolV2FrameQueues.delete(uuid);
1309
+ this.protocolV2FramePromises.delete(uuid);
1208
1310
  }
1209
1311
 
1210
- private resetProtocolV2Frames() {
1211
- this.protocolV2FrameQueue = [];
1212
- this.protocolV2FramePromise = null;
1312
+ private isActiveProtocolV2Call(uuid: string, token: number) {
1313
+ return this.activeProtocolV2Call?.uuid === uuid && this.activeProtocolV2Call.token === token;
1213
1314
  }
1214
1315
 
1215
- private async readProtocolV2Frame() {
1216
- const queuedFrame = this.protocolV2FrameQueue.shift();
1316
+ private async readProtocolV2Frame(uuid: string) {
1317
+ const queuedFrame = this.getProtocolV2FrameQueue(uuid).shift();
1217
1318
  if (queuedFrame) {
1218
1319
  return queuedFrame;
1219
1320
  }
1220
1321
 
1221
1322
  const framePromise = createDeferred<Uint8Array>();
1222
- this.protocolV2FramePromise = framePromise;
1323
+ this.protocolV2FramePromises.set(uuid, framePromise);
1223
1324
  try {
1224
1325
  return await framePromise.promise;
1225
1326
  } finally {
1226
- if (this.protocolV2FramePromise === framePromise) {
1227
- this.protocolV2FramePromise = null;
1327
+ if (this.protocolV2FramePromises.get(uuid) === framePromise) {
1328
+ this.protocolV2FramePromises.delete(uuid);
1228
1329
  }
1229
1330
  }
1230
1331
  }
@@ -1298,16 +1399,19 @@ export default class ReactNativeBleTransport {
1298
1399
  }
1299
1400
  const error = ERRORS.TypedError(HardwareErrorCode.BleForceCleanRunPromise);
1300
1401
  this.runPromise.reject(error);
1301
- this.rejectProtocolV2Frame(error);
1402
+ this.rejectAllProtocolV2Frames(error);
1302
1403
  this.runPromise = null;
1404
+ this.activeProtocolV2Call = null;
1303
1405
  }
1304
1406
 
1305
1407
  const transport = this.getCachedTransport(uuid);
1306
1408
  const runPromise = createDeferred<Uint8Array>();
1307
1409
  runPromise.promise.catch(() => undefined);
1308
1410
  this.runPromise = runPromise;
1411
+ const callToken = this.nextProtocolV2CallToken++;
1412
+ this.activeProtocolV2Call = { uuid, token: callToken };
1309
1413
  this.protocolV2Assemblers.get(uuid)?.reset();
1310
- this.resetProtocolV2Frames();
1414
+ this.resetProtocolV2Frames(uuid);
1311
1415
  let completed = false;
1312
1416
  const callOptions = {
1313
1417
  ...options,
@@ -1341,7 +1445,7 @@ export default class ReactNativeBleTransport {
1341
1445
  writeFrame: (frame: Uint8Array) =>
1342
1446
  this.writeProtocolV2Frame(transport, frame, { highVolume: highVolumeWrite }),
1343
1447
  readFrame: async () => {
1344
- const rxFrame = await this.readProtocolV2Frame();
1448
+ const rxFrame = await this.readProtocolV2Frame(uuid);
1345
1449
  if (!(rxFrame instanceof Uint8Array)) {
1346
1450
  throw new Error('Protocol V2 response is not Uint8Array');
1347
1451
  }
@@ -1360,15 +1464,20 @@ export default class ReactNativeBleTransport {
1360
1464
  completed = true;
1361
1465
  return result;
1362
1466
  } catch (e) {
1363
- this.protocolV2Assemblers.get(uuid)?.reset();
1364
- this.resetProtocolV2Frames();
1467
+ if (this.isActiveProtocolV2Call(uuid, callToken)) {
1468
+ this.protocolV2Assemblers.get(uuid)?.reset();
1469
+ this.resetProtocolV2Frames(uuid);
1470
+ }
1365
1471
  Log?.error('[ReactNativeBleTransport] Protocol V2 call error:', e);
1366
1472
  throw e;
1367
1473
  } finally {
1368
- if (!completed) {
1369
- this.protocolV2Assemblers.get(uuid)?.reset();
1474
+ if (this.isActiveProtocolV2Call(uuid, callToken)) {
1475
+ if (!completed) {
1476
+ this.protocolV2Assemblers.get(uuid)?.reset();
1477
+ }
1478
+ this.resetProtocolV2Frames(uuid);
1479
+ this.activeProtocolV2Call = null;
1370
1480
  }
1371
- this.resetProtocolV2Frames();
1372
1481
  if (this.runPromise === runPromise) {
1373
1482
  this.runPromise = null;
1374
1483
  }