@onekeyfe/hd-transport-react-native 1.2.0-alpha.74 → 1.2.0-alpha.75
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/BleTransport.d.ts.map +1 -1
- package/dist/index.d.ts +1 -88
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +44 -298
- package/jest.config.js +0 -5
- package/package.json +5 -5
- package/src/BleTransport.ts +6 -9
- package/src/__tests__/BleTransport.test.ts +3 -24
- package/src/__tests__/protocolV2Link.test.ts +5 -35
- package/src/index.ts +39 -449
- package/src/__tests__/connectTimeout.test.ts +0 -280
- package/src/__tests__/protocolReprobe.test.ts +0 -132
- package/src/__tests__/protocolV1SchemaFixture.ts +0 -39
- package/src/__tests__/staleCallTimeout.test.ts +0 -210
- package/src/__tests__/writePacketTimeout.test.ts +0 -305
package/dist/index.js
CHANGED
|
@@ -216,6 +216,10 @@ class BleTransport {
|
|
|
216
216
|
}
|
|
217
217
|
writeWithRetry(data) {
|
|
218
218
|
return __awaiter(this, void 0, void 0, function* () {
|
|
219
|
+
if (reactNative.Platform.OS === 'ios' && this.writeCharacteristic.isWritableWithResponse) {
|
|
220
|
+
yield this.writeCharacteristic.writeWithResponse(data);
|
|
221
|
+
return;
|
|
222
|
+
}
|
|
219
223
|
yield this.writeCharacteristic.writeWithoutResponse(data);
|
|
220
224
|
});
|
|
221
225
|
}
|
|
@@ -276,12 +280,6 @@ const getFirmwareUploadWriteRetryType = (error) => {
|
|
|
276
280
|
const resolveFirmwareUploadRetryDelay = (attempt, baseDelayMs = 200, maxDelayMs = 1200) => Math.min(baseDelayMs * Math.pow(2, attempt), maxDelayMs);
|
|
277
281
|
const PROTOCOL_PROBE_TIMEOUT_MS = 1000;
|
|
278
282
|
const PROTOCOL_V2_PROBE_TIMEOUT_MS = 10000;
|
|
279
|
-
const BLE_WRITE_PACKET_TIMEOUT_MS = 10000;
|
|
280
|
-
const WEDGED_WRITE_MESSAGE = 'BLE write timeout after';
|
|
281
|
-
const isWedgedWriteError = (error) => (error === null || error === void 0 ? void 0 : error.errorCode) === hdShared.HardwareErrorCode.BleWriteCharacteristicError &&
|
|
282
|
-
typeof (error === null || error === void 0 ? void 0 : error.message) === 'string' &&
|
|
283
|
-
error.message.startsWith(WEDGED_WRITE_MESSAGE);
|
|
284
|
-
const BLE_WRITE_TIMEOUT_MANAGER_RESET_THRESHOLD = 2;
|
|
285
283
|
const DEVICE_SCAN_TIMEOUT_MS = 3000;
|
|
286
284
|
const IOS_NOTIFY_READY_DELAY_MS = 150;
|
|
287
285
|
const ANDROID_NOTIFY_READY_DELAY_MS = 300;
|
|
@@ -321,24 +319,11 @@ const ANDROID_REQUEST_MTU = 517;
|
|
|
321
319
|
const BLE_MTU_REFRESH_RETRY_DELAY_MS = 200;
|
|
322
320
|
const ANDROID_HIGH_PRIORITY_IDLE_MS = 1000;
|
|
323
321
|
const getRequestedBleMtu = () => reactNative.Platform.OS === 'android' ? ANDROID_REQUEST_MTU : IOS_REQUEST_MTU;
|
|
324
|
-
const BLE_NATIVE_CONNECT_TIMEOUT_MS = 3000;
|
|
325
322
|
const connectOptions = {
|
|
326
323
|
requestMTU: getRequestedBleMtu(),
|
|
327
|
-
timeout:
|
|
324
|
+
timeout: 3000,
|
|
328
325
|
refreshGatt: 'OnConnected',
|
|
329
326
|
};
|
|
330
|
-
const fallbackConnectOptions = {
|
|
331
|
-
timeout: BLE_NATIVE_CONNECT_TIMEOUT_MS,
|
|
332
|
-
};
|
|
333
|
-
const BLE_CONNECT_TIMEOUT_MS = BLE_NATIVE_CONNECT_TIMEOUT_MS * 2 + 2000;
|
|
334
|
-
const BLE_GATT_SETUP_TIMEOUT_MS = 10000;
|
|
335
|
-
const PROTOCOL_REPROBE_FALLBACK_ATTEMPTS = 3;
|
|
336
|
-
const BLE_CONNECT_TIMEOUT_MANAGER_RESET_THRESHOLD = 2;
|
|
337
|
-
const CONNECT_TIMEOUT_MESSAGE = 'BLE connect timeout after';
|
|
338
|
-
const isConnectTimeoutError = (error) => (error === null || error === void 0 ? void 0 : error.errorCode) === hdShared.HardwareErrorCode.BleConnectedError &&
|
|
339
|
-
typeof (error === null || error === void 0 ? void 0 : error.message) === 'string' &&
|
|
340
|
-
error.message.startsWith(CONNECT_TIMEOUT_MESSAGE);
|
|
341
|
-
const isNativeOperationTimeoutError = (error) => (error === null || error === void 0 ? void 0 : error.errorCode) === reactNativeBlePlx.BleErrorCode.OperationTimedOut;
|
|
342
327
|
const tryToGetConfiguration = (device) => {
|
|
343
328
|
if (!device || !device.serviceUUIDs)
|
|
344
329
|
return null;
|
|
@@ -398,12 +383,7 @@ class ReactNativeBleTransport {
|
|
|
398
383
|
this.runPromiseDeviceId = null;
|
|
399
384
|
this.firmwareUploadWriteRecoveryIds = new Set();
|
|
400
385
|
this.deviceProtocol = new Map();
|
|
401
|
-
this.probingProtocols = new Map();
|
|
402
|
-
this.writeTimeoutCounts = new Map();
|
|
403
|
-
this.connectionSetupTimeoutCounts = new Map();
|
|
404
386
|
this.deviceProtocolHints = new Map();
|
|
405
|
-
this.sessionProtocols = new Map();
|
|
406
|
-
this.protocolReprobeFailures = new Map();
|
|
407
387
|
this.protocolV2Assemblers = new Map();
|
|
408
388
|
this.protocolV2FrameQueues = new Map();
|
|
409
389
|
this.protocolV2FramePromises = new Map();
|
|
@@ -598,19 +578,19 @@ class ReactNativeBleTransport {
|
|
|
598
578
|
const isConnected = yield device.isConnected().catch(() => false);
|
|
599
579
|
if (!isConnected) {
|
|
600
580
|
try {
|
|
601
|
-
device = yield
|
|
581
|
+
device = yield device.connect(connectOptions);
|
|
602
582
|
}
|
|
603
583
|
catch (e) {
|
|
604
584
|
if (e.errorCode === reactNativeBlePlx.BleErrorCode.DeviceMTUChangeFailed ||
|
|
605
585
|
e.errorCode === reactNativeBlePlx.BleErrorCode.OperationCancelled) {
|
|
606
|
-
device = yield
|
|
586
|
+
device = yield device.connect();
|
|
607
587
|
}
|
|
608
588
|
else if (e.errorCode !== reactNativeBlePlx.BleErrorCode.DeviceAlreadyConnected) {
|
|
609
589
|
throw e;
|
|
610
590
|
}
|
|
611
591
|
}
|
|
612
592
|
}
|
|
613
|
-
const { writeCharacteristic, notifyCharacteristic } = yield this.
|
|
593
|
+
const { writeCharacteristic, notifyCharacteristic } = yield this.resolveCharacteristics(device);
|
|
614
594
|
transport.device = device;
|
|
615
595
|
transport.writeCharacteristic = writeCharacteristic;
|
|
616
596
|
transport.notifyCharacteristic = notifyCharacteristic;
|
|
@@ -747,7 +727,7 @@ class ReactNativeBleTransport {
|
|
|
747
727
|
}
|
|
748
728
|
installTransportForAcquire(uuid, device, characteristics) {
|
|
749
729
|
return __awaiter(this, void 0, void 0, function* () {
|
|
750
|
-
const { writeCharacteristic, notifyCharacteristic } = characteristics !== null && characteristics !== void 0 ? characteristics : (yield this.
|
|
730
|
+
const { writeCharacteristic, notifyCharacteristic } = characteristics !== null && characteristics !== void 0 ? characteristics : (yield this.resolveCharacteristics(device));
|
|
751
731
|
const transport$1 = new BleTransport(device, writeCharacteristic, notifyCharacteristic);
|
|
752
732
|
transport$1.mtuSize = typeof device.mtu === 'number' ? device.mtu : undefined;
|
|
753
733
|
const monitorToken = this.nextMonitorToken;
|
|
@@ -854,17 +834,14 @@ class ReactNativeBleTransport {
|
|
|
854
834
|
if (!device) {
|
|
855
835
|
Log === null || Log === void 0 ? void 0 : Log.debug('try to connect to device: ', uuid);
|
|
856
836
|
try {
|
|
857
|
-
device = yield
|
|
837
|
+
device = yield blePlxManager.connectToDevice(uuid, connectOptions);
|
|
858
838
|
}
|
|
859
839
|
catch (e) {
|
|
860
840
|
Log === null || Log === void 0 ? void 0 : Log.debug('try to connect to device has error: ', e);
|
|
861
|
-
if (isConnectTimeoutError(e)) {
|
|
862
|
-
throw e;
|
|
863
|
-
}
|
|
864
841
|
if (e.errorCode === reactNativeBlePlx.BleErrorCode.DeviceMTUChangeFailed ||
|
|
865
842
|
e.errorCode === reactNativeBlePlx.BleErrorCode.OperationCancelled) {
|
|
866
843
|
Log === null || Log === void 0 ? void 0 : Log.debug('first try to reconnect without params');
|
|
867
|
-
device = yield
|
|
844
|
+
device = yield blePlxManager.connectToDevice(uuid);
|
|
868
845
|
}
|
|
869
846
|
else if (e.errorCode === reactNativeBlePlx.BleErrorCode.DeviceAlreadyConnected) {
|
|
870
847
|
Log === null || Log === void 0 ? void 0 : Log.debug('device already connected');
|
|
@@ -880,27 +857,23 @@ class ReactNativeBleTransport {
|
|
|
880
857
|
}
|
|
881
858
|
if (!(yield device.isConnected())) {
|
|
882
859
|
Log === null || Log === void 0 ? void 0 : Log.debug('not connected, try to connect to device: ', uuid);
|
|
883
|
-
const disconnectedDevice = device;
|
|
884
860
|
try {
|
|
885
|
-
device = yield
|
|
861
|
+
device = yield device.connect(connectOptions);
|
|
886
862
|
}
|
|
887
863
|
catch (e) {
|
|
888
864
|
Log === null || Log === void 0 ? void 0 : Log.debug('not connected, try to connect to device has error: ', e);
|
|
889
|
-
if (isConnectTimeoutError(e)) {
|
|
890
|
-
throw e;
|
|
891
|
-
}
|
|
892
865
|
if (e.errorCode === reactNativeBlePlx.BleErrorCode.DeviceMTUChangeFailed ||
|
|
893
866
|
e.errorCode === reactNativeBlePlx.BleErrorCode.OperationCancelled) {
|
|
894
867
|
Log === null || Log === void 0 ? void 0 : Log.debug('second try to reconnect without params');
|
|
895
868
|
try {
|
|
896
|
-
device = yield
|
|
869
|
+
device = yield device.connect();
|
|
897
870
|
}
|
|
898
871
|
catch (e) {
|
|
899
872
|
Log === null || Log === void 0 ? void 0 : Log.debug('last try to reconnect error: ', e);
|
|
900
873
|
if (e.errorCode === reactNativeBlePlx.BleErrorCode.OperationCancelled) {
|
|
901
874
|
Log === null || Log === void 0 ? void 0 : Log.debug('last try to reconnect');
|
|
902
|
-
yield
|
|
903
|
-
device = yield
|
|
875
|
+
yield device.cancelConnection();
|
|
876
|
+
device = yield device.connect();
|
|
904
877
|
}
|
|
905
878
|
}
|
|
906
879
|
}
|
|
@@ -911,7 +884,7 @@ class ReactNativeBleTransport {
|
|
|
911
884
|
}
|
|
912
885
|
device = yield resolveNegotiatedMtu(device);
|
|
913
886
|
const acquiredDevice = device;
|
|
914
|
-
const { writeCharacteristic, notifyCharacteristic } = yield this.
|
|
887
|
+
const { writeCharacteristic, notifyCharacteristic } = yield this.resolveCharacteristics(acquiredDevice);
|
|
915
888
|
const protocolHint = expectedProtocol
|
|
916
889
|
? undefined
|
|
917
890
|
: (_b = (_a = input.protocolHint) !== null && _a !== void 0 ? _a : this.deviceProtocolHints.get(uuid)) !== null && _b !== void 0 ? _b : inferProtocolHintFromDeviceName(getDeviceDisplayName(acquiredDevice));
|
|
@@ -956,7 +929,7 @@ class ReactNativeBleTransport {
|
|
|
956
929
|
Log === null || Log === void 0 ? void 0 : Log.debug('monitor error ignored for stale transport: ', uuid, notifyTransactionId);
|
|
957
930
|
return;
|
|
958
931
|
}
|
|
959
|
-
if (this.
|
|
932
|
+
if (this.deviceProtocol.get(uuid) === 'V2') {
|
|
960
933
|
let errorCode = hdShared.HardwareErrorCode.BleCharacteristicNotifyError;
|
|
961
934
|
if ((_a = error.reason) === null || _a === void 0 ? void 0 : _a.includes('The connection has timed out unexpectedly')) {
|
|
962
935
|
errorCode = hdShared.HardwareErrorCode.BleTimeoutError;
|
|
@@ -1007,7 +980,7 @@ class ReactNativeBleTransport {
|
|
|
1007
980
|
}
|
|
1008
981
|
try {
|
|
1009
982
|
const data = buffer.Buffer.from(c.value, 'base64');
|
|
1010
|
-
const protocol = this.
|
|
983
|
+
const protocol = this.deviceProtocol.get(uuid);
|
|
1011
984
|
if (!protocol) {
|
|
1012
985
|
Log === null || Log === void 0 ? void 0 : Log.debug('monitor data ignored before protocol detection: ', uuid);
|
|
1013
986
|
return;
|
|
@@ -1035,7 +1008,7 @@ class ReactNativeBleTransport {
|
|
|
1035
1008
|
catch (error) {
|
|
1036
1009
|
Log === null || Log === void 0 ? void 0 : Log.debug('monitor data error: ', error);
|
|
1037
1010
|
const notifyError = hdShared.ERRORS.TypedError(hdShared.HardwareErrorCode.BleWriteCharacteristicError);
|
|
1038
|
-
if (this.
|
|
1011
|
+
if (this.deviceProtocol.get(uuid) === 'V2') {
|
|
1039
1012
|
this.rejectProtocolV2Frames(uuid, notifyError);
|
|
1040
1013
|
}
|
|
1041
1014
|
else if (this.runPromiseDeviceId === uuid) {
|
|
@@ -1093,7 +1066,6 @@ class ReactNativeBleTransport {
|
|
|
1093
1066
|
}
|
|
1094
1067
|
this.protocolV2HighVolumeLogSignatures.delete(uuid);
|
|
1095
1068
|
this.deviceProtocol.delete(uuid);
|
|
1096
|
-
this.probingProtocols.delete(uuid);
|
|
1097
1069
|
(_f = this.protocolV2Assemblers.get(uuid)) === null || _f === void 0 ? void 0 : _f.reset();
|
|
1098
1070
|
this.protocolV2Assemblers.delete(uuid);
|
|
1099
1071
|
this.resetProtocolV2Frames(uuid);
|
|
@@ -1142,19 +1114,8 @@ class ReactNativeBleTransport {
|
|
|
1142
1114
|
const transport = this.getCachedTransport(uuid);
|
|
1143
1115
|
const runPromise = hdShared.createDeferred();
|
|
1144
1116
|
runPromise.promise.catch(() => undefined);
|
|
1145
|
-
const supersededRunPromise = this.runPromise;
|
|
1146
|
-
if (supersededRunPromise) {
|
|
1147
|
-
supersededRunPromise.reject(hdShared.ERRORS.TypedError(hdShared.HardwareErrorCode.BleForceCleanRunPromise));
|
|
1148
|
-
}
|
|
1149
1117
|
this.runPromise = runPromise;
|
|
1150
1118
|
this.runPromiseDeviceId = uuid;
|
|
1151
|
-
const releaseOwnershipIfCurrent = () => {
|
|
1152
|
-
if (this.runPromise === runPromise) {
|
|
1153
|
-
this.runPromise = null;
|
|
1154
|
-
this.runPromiseDeviceId = null;
|
|
1155
|
-
}
|
|
1156
|
-
};
|
|
1157
|
-
const isCurrentOwner = () => this.runPromise === runPromise;
|
|
1158
1119
|
const messages = this._messages;
|
|
1159
1120
|
const buffers = ProtocolV1.encodeTransportPackets(messages, name, data);
|
|
1160
1121
|
let timeout;
|
|
@@ -1175,9 +1136,6 @@ class ReactNativeBleTransport {
|
|
|
1175
1136
|
}
|
|
1176
1137
|
catch (e) {
|
|
1177
1138
|
onError(e);
|
|
1178
|
-
if (isWedgedWriteError(e)) {
|
|
1179
|
-
throw e;
|
|
1180
|
-
}
|
|
1181
1139
|
throw hdShared.ERRORS.TypedError(hdShared.HardwareErrorCode.BleWriteCharacteristicError);
|
|
1182
1140
|
}
|
|
1183
1141
|
}
|
|
@@ -1205,9 +1163,6 @@ class ReactNativeBleTransport {
|
|
|
1205
1163
|
}
|
|
1206
1164
|
catch (e) {
|
|
1207
1165
|
onError(e);
|
|
1208
|
-
if (isWedgedWriteError(e)) {
|
|
1209
|
-
throw e;
|
|
1210
|
-
}
|
|
1211
1166
|
throw hdShared.ERRORS.TypedError(hdShared.HardwareErrorCode.BleWriteCharacteristicError);
|
|
1212
1167
|
}
|
|
1213
1168
|
}
|
|
@@ -1218,8 +1173,8 @@ class ReactNativeBleTransport {
|
|
|
1218
1173
|
});
|
|
1219
1174
|
}
|
|
1220
1175
|
if (name === 'EmmcFileWrite') {
|
|
1221
|
-
yield writeChunkedData(buffers, data =>
|
|
1222
|
-
|
|
1176
|
+
yield writeChunkedData(buffers, data => transport.writeWithRetry(data), e => {
|
|
1177
|
+
this.runPromise = null;
|
|
1223
1178
|
Log === null || Log === void 0 ? void 0 : Log.error('writeCharacteristic write error: ', e);
|
|
1224
1179
|
});
|
|
1225
1180
|
}
|
|
@@ -1235,7 +1190,7 @@ class ReactNativeBleTransport {
|
|
|
1235
1190
|
let attempt = 0;
|
|
1236
1191
|
while (true) {
|
|
1237
1192
|
try {
|
|
1238
|
-
yield
|
|
1193
|
+
yield transport.writeWithRetry(data);
|
|
1239
1194
|
return;
|
|
1240
1195
|
}
|
|
1241
1196
|
catch (error) {
|
|
@@ -1254,7 +1209,7 @@ class ReactNativeBleTransport {
|
|
|
1254
1209
|
}
|
|
1255
1210
|
}
|
|
1256
1211
|
}), e => {
|
|
1257
|
-
|
|
1212
|
+
this.runPromise = null;
|
|
1258
1213
|
Log === null || Log === void 0 ? void 0 : Log.error('writeCharacteristic write error: ', e);
|
|
1259
1214
|
});
|
|
1260
1215
|
}
|
|
@@ -1263,16 +1218,16 @@ class ReactNativeBleTransport {
|
|
|
1263
1218
|
const outData = o.toString('base64');
|
|
1264
1219
|
try {
|
|
1265
1220
|
const shouldUseWriteWithResponse = reactNative.Platform.OS === 'ios' && transport.writeCharacteristic.isWritableWithResponse;
|
|
1266
|
-
|
|
1267
|
-
|
|
1268
|
-
|
|
1221
|
+
if (shouldUseWriteWithResponse) {
|
|
1222
|
+
yield transport.writeCharacteristic.writeWithResponse(outData);
|
|
1223
|
+
}
|
|
1224
|
+
else {
|
|
1225
|
+
yield transport.writeCharacteristic.writeWithoutResponse(outData);
|
|
1226
|
+
}
|
|
1269
1227
|
}
|
|
1270
1228
|
catch (e) {
|
|
1271
1229
|
Log === null || Log === void 0 ? void 0 : Log.debug('writeCharacteristic write error: ', e);
|
|
1272
|
-
|
|
1273
|
-
if (isWedgedWriteError(e)) {
|
|
1274
|
-
throw e;
|
|
1275
|
-
}
|
|
1230
|
+
this.runPromise = null;
|
|
1276
1231
|
if (e.errorCode === reactNativeBlePlx.BleErrorCode.DeviceDisconnected) {
|
|
1277
1232
|
throw hdShared.ERRORS.TypedError(hdShared.HardwareErrorCode.BleDeviceNotBonded);
|
|
1278
1233
|
}
|
|
@@ -1312,9 +1267,7 @@ class ReactNativeBleTransport {
|
|
|
1312
1267
|
Log === null || Log === void 0 ? void 0 : Log.error('call error: ', e);
|
|
1313
1268
|
}
|
|
1314
1269
|
const isProbeTimeout = name === 'GetFeatures' && (options === null || options === void 0 ? void 0 : options.timeoutMs) === PROTOCOL_PROBE_TIMEOUT_MS;
|
|
1315
|
-
const isStaleCall = this.runPromise !== runPromise;
|
|
1316
1270
|
if (!isProbeTimeout &&
|
|
1317
|
-
!isStaleCall &&
|
|
1318
1271
|
(e === null || e === void 0 ? void 0 : e.errorCode) === hdShared.HardwareErrorCode.BleTimeoutError) {
|
|
1319
1272
|
yield this.disconnect(uuid);
|
|
1320
1273
|
}
|
|
@@ -1385,10 +1338,7 @@ class ReactNativeBleTransport {
|
|
|
1385
1338
|
delete transportCache[session];
|
|
1386
1339
|
}
|
|
1387
1340
|
this.deviceProtocol.delete(session);
|
|
1388
|
-
this.probingProtocols.delete(session);
|
|
1389
1341
|
this.deviceProtocolHints.delete(session);
|
|
1390
|
-
this.sessionProtocols.delete(session);
|
|
1391
|
-
this.protocolReprobeFailures.delete(session);
|
|
1392
1342
|
this.protocolV2Assemblers.delete(session);
|
|
1393
1343
|
this.resetProtocolV2Frames(session);
|
|
1394
1344
|
try {
|
|
@@ -1409,91 +1359,6 @@ class ReactNativeBleTransport {
|
|
|
1409
1359
|
this.runPromise = null;
|
|
1410
1360
|
this.runPromiseDeviceId = null;
|
|
1411
1361
|
}
|
|
1412
|
-
connectWithTimeout(uuid, connect) {
|
|
1413
|
-
return __awaiter(this, void 0, void 0, function* () {
|
|
1414
|
-
let timer;
|
|
1415
|
-
let timedOut = false;
|
|
1416
|
-
const pending = connect();
|
|
1417
|
-
pending.catch(() => undefined);
|
|
1418
|
-
try {
|
|
1419
|
-
const result = yield Promise.race([
|
|
1420
|
-
pending,
|
|
1421
|
-
new Promise((_, reject) => {
|
|
1422
|
-
timer = setTimeout(() => {
|
|
1423
|
-
timedOut = true;
|
|
1424
|
-
reject(hdShared.ERRORS.TypedError(hdShared.HardwareErrorCode.BleConnectedError, `BLE connect timeout after ${BLE_CONNECT_TIMEOUT_MS}ms for ${uuid}`));
|
|
1425
|
-
}, BLE_CONNECT_TIMEOUT_MS);
|
|
1426
|
-
}),
|
|
1427
|
-
]);
|
|
1428
|
-
return result;
|
|
1429
|
-
}
|
|
1430
|
-
catch (error) {
|
|
1431
|
-
if (timedOut || isNativeOperationTimeoutError(error)) {
|
|
1432
|
-
this.abandonStalledConnection(uuid, timedOut ? 'connect-backstop' : 'connect-native');
|
|
1433
|
-
}
|
|
1434
|
-
throw error;
|
|
1435
|
-
}
|
|
1436
|
-
finally {
|
|
1437
|
-
if (timer)
|
|
1438
|
-
clearTimeout(timer);
|
|
1439
|
-
}
|
|
1440
|
-
});
|
|
1441
|
-
}
|
|
1442
|
-
resolveCharacteristicsWithTimeout(uuid, device) {
|
|
1443
|
-
return __awaiter(this, void 0, void 0, function* () {
|
|
1444
|
-
let timer;
|
|
1445
|
-
let timedOut = false;
|
|
1446
|
-
const pending = this.resolveCharacteristics(device);
|
|
1447
|
-
pending.catch(() => undefined);
|
|
1448
|
-
try {
|
|
1449
|
-
const result = yield Promise.race([
|
|
1450
|
-
pending,
|
|
1451
|
-
new Promise((_, reject) => {
|
|
1452
|
-
timer = setTimeout(() => {
|
|
1453
|
-
timedOut = true;
|
|
1454
|
-
reject(hdShared.ERRORS.TypedError(hdShared.HardwareErrorCode.BleConnectedError, `BLE GATT setup timeout after ${BLE_GATT_SETUP_TIMEOUT_MS}ms for ${uuid}`));
|
|
1455
|
-
}, BLE_GATT_SETUP_TIMEOUT_MS);
|
|
1456
|
-
}),
|
|
1457
|
-
]);
|
|
1458
|
-
this.connectionSetupTimeoutCounts.delete(uuid);
|
|
1459
|
-
return result;
|
|
1460
|
-
}
|
|
1461
|
-
catch (error) {
|
|
1462
|
-
if (timedOut || isNativeOperationTimeoutError(error)) {
|
|
1463
|
-
this.abandonStalledConnection(uuid, timedOut ? 'gatt-backstop' : 'gatt-native');
|
|
1464
|
-
}
|
|
1465
|
-
throw error;
|
|
1466
|
-
}
|
|
1467
|
-
finally {
|
|
1468
|
-
if (timer)
|
|
1469
|
-
clearTimeout(timer);
|
|
1470
|
-
}
|
|
1471
|
-
});
|
|
1472
|
-
}
|
|
1473
|
-
abandonStalledConnection(uuid, stage) {
|
|
1474
|
-
var _a, _b;
|
|
1475
|
-
const timeouts = ((_a = this.connectionSetupTimeoutCounts.get(uuid)) !== null && _a !== void 0 ? _a : 0) + 1;
|
|
1476
|
-
this.connectionSetupTimeoutCounts.set(uuid, timeouts);
|
|
1477
|
-
Log === null || Log === void 0 ? void 0 : Log.error('[ReactNativeBleTransport] BLE setup timed out:', uuid, {
|
|
1478
|
-
stage,
|
|
1479
|
-
setupTimeoutsSinceSuccess: timeouts,
|
|
1480
|
-
});
|
|
1481
|
-
(_b = this.blePlxManager) === null || _b === void 0 ? void 0 : _b.cancelDeviceConnection(uuid).catch(() => {
|
|
1482
|
-
});
|
|
1483
|
-
const stalled = transportCache[uuid];
|
|
1484
|
-
if (stalled) {
|
|
1485
|
-
delete transportCache[uuid];
|
|
1486
|
-
}
|
|
1487
|
-
this.deviceProtocol.delete(uuid);
|
|
1488
|
-
this.probingProtocols.delete(uuid);
|
|
1489
|
-
this.protocolV2Assemblers.delete(uuid);
|
|
1490
|
-
this.resetProtocolV2Frames(uuid);
|
|
1491
|
-
if (timeouts >= BLE_CONNECT_TIMEOUT_MANAGER_RESET_THRESHOLD) {
|
|
1492
|
-
Log === null || Log === void 0 ? void 0 : Log.error('[ReactNativeBleTransport] BLE setup wedged repeatedly, resetting BLE manager');
|
|
1493
|
-
this.resetPlxManager();
|
|
1494
|
-
this.connectionSetupTimeoutCounts.delete(uuid);
|
|
1495
|
-
}
|
|
1496
|
-
}
|
|
1497
1362
|
getCachedTransport(uuid) {
|
|
1498
1363
|
const transport = transportCache[uuid];
|
|
1499
1364
|
if (!transport) {
|
|
@@ -1501,82 +1366,6 @@ class ReactNativeBleTransport {
|
|
|
1501
1366
|
}
|
|
1502
1367
|
return transport;
|
|
1503
1368
|
}
|
|
1504
|
-
writeBlePacket(uuid, data, write, isCurrentOwner) {
|
|
1505
|
-
return __awaiter(this, void 0, void 0, function* () {
|
|
1506
|
-
let timer;
|
|
1507
|
-
let timedOut = false;
|
|
1508
|
-
try {
|
|
1509
|
-
yield Promise.race([
|
|
1510
|
-
write(data),
|
|
1511
|
-
new Promise((_, reject) => {
|
|
1512
|
-
timer = setTimeout(() => {
|
|
1513
|
-
timedOut = true;
|
|
1514
|
-
reject(hdShared.ERRORS.TypedError(hdShared.HardwareErrorCode.BleWriteCharacteristicError, `BLE write timeout after ${BLE_WRITE_PACKET_TIMEOUT_MS}ms`));
|
|
1515
|
-
}, BLE_WRITE_PACKET_TIMEOUT_MS);
|
|
1516
|
-
}),
|
|
1517
|
-
]);
|
|
1518
|
-
this.writeTimeoutCounts.delete(uuid);
|
|
1519
|
-
}
|
|
1520
|
-
catch (error) {
|
|
1521
|
-
if (timedOut) {
|
|
1522
|
-
if (isCurrentOwner && !isCurrentOwner()) {
|
|
1523
|
-
Log === null || Log === void 0 ? void 0 : Log.debug('[ReactNativeBleTransport] stale BLE write timed out, link kept:', uuid);
|
|
1524
|
-
}
|
|
1525
|
-
else {
|
|
1526
|
-
this.tearDownWedgedLink(uuid);
|
|
1527
|
-
}
|
|
1528
|
-
}
|
|
1529
|
-
throw error;
|
|
1530
|
-
}
|
|
1531
|
-
finally {
|
|
1532
|
-
if (timer)
|
|
1533
|
-
clearTimeout(timer);
|
|
1534
|
-
}
|
|
1535
|
-
});
|
|
1536
|
-
}
|
|
1537
|
-
tearDownWedgedLink(uuid) {
|
|
1538
|
-
var _a;
|
|
1539
|
-
const timeouts = ((_a = this.writeTimeoutCounts.get(uuid)) !== null && _a !== void 0 ? _a : 0) + 1;
|
|
1540
|
-
this.writeTimeoutCounts.set(uuid, timeouts);
|
|
1541
|
-
Log === null || Log === void 0 ? void 0 : Log.error('[ReactNativeBleTransport] BLE write timed out, tearing down link:', uuid, {
|
|
1542
|
-
consecutiveWriteTimeouts: timeouts,
|
|
1543
|
-
});
|
|
1544
|
-
const wedged = transportCache[uuid];
|
|
1545
|
-
this.disconnect(uuid).catch(error => {
|
|
1546
|
-
Log === null || Log === void 0 ? void 0 : Log.debug('[ReactNativeBleTransport] wedged link teardown failed (ignored):', error);
|
|
1547
|
-
});
|
|
1548
|
-
if (wedged && transportCache[uuid] === wedged) {
|
|
1549
|
-
delete transportCache[uuid];
|
|
1550
|
-
}
|
|
1551
|
-
this.deviceProtocol.delete(uuid);
|
|
1552
|
-
this.probingProtocols.delete(uuid);
|
|
1553
|
-
this.protocolV2Assemblers.delete(uuid);
|
|
1554
|
-
this.resetProtocolV2Frames(uuid);
|
|
1555
|
-
if (timeouts >= BLE_WRITE_TIMEOUT_MANAGER_RESET_THRESHOLD) {
|
|
1556
|
-
Log === null || Log === void 0 ? void 0 : Log.error('[ReactNativeBleTransport] BLE writes wedged repeatedly, resetting BLE manager');
|
|
1557
|
-
this.resetPlxManager();
|
|
1558
|
-
this.writeTimeoutCounts.delete(uuid);
|
|
1559
|
-
}
|
|
1560
|
-
}
|
|
1561
|
-
resetPlxManager() {
|
|
1562
|
-
const manager = this.blePlxManager;
|
|
1563
|
-
this.blePlxManager = undefined;
|
|
1564
|
-
Object.keys(transportCache).forEach(key => {
|
|
1565
|
-
delete transportCache[key];
|
|
1566
|
-
});
|
|
1567
|
-
this.deviceProtocol.clear();
|
|
1568
|
-
this.probingProtocols.clear();
|
|
1569
|
-
this.sessionProtocols.clear();
|
|
1570
|
-
this.protocolReprobeFailures.clear();
|
|
1571
|
-
this.monitorTokens.clear();
|
|
1572
|
-
this.protocolV2Assemblers.clear();
|
|
1573
|
-
try {
|
|
1574
|
-
manager === null || manager === void 0 ? void 0 : manager.destroy();
|
|
1575
|
-
}
|
|
1576
|
-
catch (error) {
|
|
1577
|
-
Log === null || Log === void 0 ? void 0 : Log.debug('[ReactNativeBleTransport] BLE manager destroy failed (ignored):', error);
|
|
1578
|
-
}
|
|
1579
|
-
}
|
|
1580
1369
|
createProtocolMismatchError(expected) {
|
|
1581
1370
|
return hdShared.ERRORS.TypedError(hdShared.HardwareErrorCode.RuntimeError, `Device protocol mismatch: expected ${expected}, but device did not respond to expected protocol`);
|
|
1582
1371
|
}
|
|
@@ -1584,19 +1373,11 @@ class ReactNativeBleTransport {
|
|
|
1584
1373
|
return hdShared.ERRORS.TypedError(hdShared.HardwareErrorCode.BleTimeoutError, 'Unable to detect BLE protocol: device did not respond to Protocol V1 GetFeatures or Protocol V2 Ping');
|
|
1585
1374
|
}
|
|
1586
1375
|
clearProbeProtocol(uuid, protocol) {
|
|
1587
|
-
if (this.probingProtocols.get(uuid) === protocol) {
|
|
1588
|
-
this.probingProtocols.delete(uuid);
|
|
1589
|
-
}
|
|
1590
1376
|
if (this.deviceProtocol.get(uuid) === protocol) {
|
|
1591
1377
|
this.deviceProtocol.delete(uuid);
|
|
1592
1378
|
}
|
|
1593
1379
|
}
|
|
1594
|
-
getActiveProtocol(uuid) {
|
|
1595
|
-
var _a;
|
|
1596
|
-
return (_a = this.deviceProtocol.get(uuid)) !== null && _a !== void 0 ? _a : this.probingProtocols.get(uuid);
|
|
1597
|
-
}
|
|
1598
1380
|
detectProtocol(uuid, expectedProtocol, protocolHint, rebuildTransport) {
|
|
1599
|
-
var _a;
|
|
1600
1381
|
return __awaiter(this, void 0, void 0, function* () {
|
|
1601
1382
|
if (reactNative.Platform.OS === 'ios' && expectedProtocol) {
|
|
1602
1383
|
this.deviceProtocol.set(uuid, expectedProtocol);
|
|
@@ -1610,7 +1391,6 @@ class ReactNativeBleTransport {
|
|
|
1610
1391
|
if (expectedProtocol === 'V1') {
|
|
1611
1392
|
if (yield this.probeProtocolV1(uuid)) {
|
|
1612
1393
|
this.deviceProtocol.set(uuid, 'V1');
|
|
1613
|
-
this.sessionProtocols.set(uuid, 'V1');
|
|
1614
1394
|
Log === null || Log === void 0 ? void 0 : Log.debug('[ReactNativeBleTransport] protocol detected', {
|
|
1615
1395
|
deviceId: uuid,
|
|
1616
1396
|
protocol: 'V1',
|
|
@@ -1623,7 +1403,6 @@ class ReactNativeBleTransport {
|
|
|
1623
1403
|
if (expectedProtocol === 'V2') {
|
|
1624
1404
|
if (yield this.probeProtocolV2(uuid)) {
|
|
1625
1405
|
this.deviceProtocol.set(uuid, 'V2');
|
|
1626
|
-
this.sessionProtocols.set(uuid, 'V2');
|
|
1627
1406
|
Log === null || Log === void 0 ? void 0 : Log.debug('[ReactNativeBleTransport] protocol detected', {
|
|
1628
1407
|
deviceId: uuid,
|
|
1629
1408
|
protocol: 'V2',
|
|
@@ -1633,13 +1412,7 @@ class ReactNativeBleTransport {
|
|
|
1633
1412
|
}
|
|
1634
1413
|
throw this.createProtocolMismatchError(expectedProtocol);
|
|
1635
1414
|
}
|
|
1636
|
-
const
|
|
1637
|
-
const reprobeFailures = (_a = this.protocolReprobeFailures.get(uuid)) !== null && _a !== void 0 ? _a : 0;
|
|
1638
|
-
const fullProbeOrder = protocolHint === 'V2' || this.deviceProtocol.get(uuid) === 'V2' ? ['V2', 'V1'] : ['V1', 'V2'];
|
|
1639
|
-
const trustSessionProtocol = sessionProtocol !== undefined &&
|
|
1640
|
-
!protocolHint &&
|
|
1641
|
-
reprobeFailures < PROTOCOL_REPROBE_FALLBACK_ATTEMPTS;
|
|
1642
|
-
const probeOrder = trustSessionProtocol ? [sessionProtocol] : fullProbeOrder;
|
|
1415
|
+
const probeOrder = protocolHint === 'V2' || this.deviceProtocol.get(uuid) === 'V2' ? ['V2', 'V1'] : ['V1', 'V2'];
|
|
1643
1416
|
for (let i = 0; i < probeOrder.length; i += 1) {
|
|
1644
1417
|
const protocol = probeOrder[i];
|
|
1645
1418
|
if (i > 0) {
|
|
@@ -1654,8 +1427,6 @@ class ReactNativeBleTransport {
|
|
|
1654
1427
|
const detected = protocol === 'V1' ? yield this.probeProtocolV1(uuid) : yield this.probeProtocolV2(uuid);
|
|
1655
1428
|
if (detected) {
|
|
1656
1429
|
this.deviceProtocol.set(uuid, protocol);
|
|
1657
|
-
this.sessionProtocols.set(uuid, protocol);
|
|
1658
|
-
this.protocolReprobeFailures.delete(uuid);
|
|
1659
1430
|
Log === null || Log === void 0 ? void 0 : Log.debug('[ReactNativeBleTransport] protocol detected', {
|
|
1660
1431
|
deviceId: uuid,
|
|
1661
1432
|
protocol,
|
|
@@ -1664,14 +1435,7 @@ class ReactNativeBleTransport {
|
|
|
1664
1435
|
return protocol;
|
|
1665
1436
|
}
|
|
1666
1437
|
}
|
|
1667
|
-
if (trustSessionProtocol) {
|
|
1668
|
-
this.protocolReprobeFailures.set(uuid, reprobeFailures + 1);
|
|
1669
|
-
}
|
|
1670
|
-
else {
|
|
1671
|
-
this.protocolReprobeFailures.delete(uuid);
|
|
1672
|
-
}
|
|
1673
1438
|
this.deviceProtocol.delete(uuid);
|
|
1674
|
-
this.probingProtocols.delete(uuid);
|
|
1675
1439
|
throw this.createProtocolDetectionError();
|
|
1676
1440
|
});
|
|
1677
1441
|
}
|
|
@@ -1723,17 +1487,13 @@ class ReactNativeBleTransport {
|
|
|
1723
1487
|
return false;
|
|
1724
1488
|
}
|
|
1725
1489
|
try {
|
|
1726
|
-
this.
|
|
1490
|
+
this.deviceProtocol.set(uuid, 'V1');
|
|
1727
1491
|
yield this.callProtocolV1(uuid, 'GetFeatures', {}, { timeoutMs: PROTOCOL_PROBE_TIMEOUT_MS });
|
|
1728
|
-
this.probingProtocols.delete(uuid);
|
|
1729
1492
|
return true;
|
|
1730
1493
|
}
|
|
1731
1494
|
catch (error) {
|
|
1732
1495
|
this.clearProbeProtocol(uuid, 'V1');
|
|
1733
1496
|
Log === null || Log === void 0 ? void 0 : Log.debug('[ReactNativeBleTransport] Protocol V1 GetFeatures probe failed:', error);
|
|
1734
|
-
if (isWedgedWriteError(error)) {
|
|
1735
|
-
throw error;
|
|
1736
|
-
}
|
|
1737
1497
|
return false;
|
|
1738
1498
|
}
|
|
1739
1499
|
});
|
|
@@ -1744,7 +1504,7 @@ class ReactNativeBleTransport {
|
|
|
1744
1504
|
if (!this._messages || !this._messagesV2) {
|
|
1745
1505
|
return false;
|
|
1746
1506
|
}
|
|
1747
|
-
this.
|
|
1507
|
+
this.deviceProtocol.set(uuid, 'V2');
|
|
1748
1508
|
(_a = this.protocolV2Assemblers.get(uuid)) === null || _a === void 0 ? void 0 : _a.reset();
|
|
1749
1509
|
const detected = yield transport.probeProtocolV2({
|
|
1750
1510
|
call: (name, data, options) => this.callProtocolV2(uuid, name, data, options),
|
|
@@ -1760,9 +1520,6 @@ class ReactNativeBleTransport {
|
|
|
1760
1520
|
if (!detected) {
|
|
1761
1521
|
this.clearProbeProtocol(uuid, 'V2');
|
|
1762
1522
|
}
|
|
1763
|
-
else {
|
|
1764
|
-
this.probingProtocols.delete(uuid);
|
|
1765
|
-
}
|
|
1766
1523
|
return detected;
|
|
1767
1524
|
});
|
|
1768
1525
|
}
|
|
@@ -1834,7 +1591,7 @@ class ReactNativeBleTransport {
|
|
|
1834
1591
|
}
|
|
1835
1592
|
});
|
|
1836
1593
|
}
|
|
1837
|
-
writeProtocolV2Packet(
|
|
1594
|
+
writeProtocolV2Packet(transport, base64, context, assertCurrentGeneration) {
|
|
1838
1595
|
return __awaiter(this, void 0, void 0, function* () {
|
|
1839
1596
|
const shouldUseWriteWithResponse = shouldWriteProtocolV2WithResponse({
|
|
1840
1597
|
platform: reactNative.Platform.OS,
|
|
@@ -1849,17 +1606,12 @@ class ReactNativeBleTransport {
|
|
|
1849
1606
|
throw new Error(`Protocol V2 BLE write aborted for ${context.messageName}`);
|
|
1850
1607
|
}
|
|
1851
1608
|
try {
|
|
1852
|
-
|
|
1853
|
-
|
|
1854
|
-
|
|
1855
|
-
|
|
1856
|
-
|
|
1857
|
-
|
|
1858
|
-
}
|
|
1859
|
-
catch (_a) {
|
|
1860
|
-
return false;
|
|
1861
|
-
}
|
|
1862
|
-
});
|
|
1609
|
+
if (shouldUseWriteWithResponse) {
|
|
1610
|
+
yield transport.writeCharacteristic.writeWithResponse(base64);
|
|
1611
|
+
}
|
|
1612
|
+
else {
|
|
1613
|
+
yield transport.writeCharacteristic.writeWithoutResponse(base64);
|
|
1614
|
+
}
|
|
1863
1615
|
assertCurrentGeneration();
|
|
1864
1616
|
return;
|
|
1865
1617
|
}
|
|
@@ -1880,7 +1632,7 @@ class ReactNativeBleTransport {
|
|
|
1880
1632
|
}
|
|
1881
1633
|
});
|
|
1882
1634
|
}
|
|
1883
|
-
writeProtocolV2Frame(
|
|
1635
|
+
writeProtocolV2Frame(transport$1, frame, context, assertCurrentGeneration) {
|
|
1884
1636
|
return __awaiter(this, void 0, void 0, function* () {
|
|
1885
1637
|
const tuning = getProtocolV2BleTuning();
|
|
1886
1638
|
const packetCapacity = resolveProtocolV2PacketCapacity({
|
|
@@ -1896,7 +1648,7 @@ class ReactNativeBleTransport {
|
|
|
1896
1648
|
signal: context.signal,
|
|
1897
1649
|
abortMessage: `Protocol V2 BLE write aborted for ${context.messageName}`,
|
|
1898
1650
|
wait: delay,
|
|
1899
|
-
writePacket: packet => this.writeProtocolV2Packet(
|
|
1651
|
+
writePacket: packet => this.writeProtocolV2Packet(transport$1, buffer.Buffer.from(packet).toString('base64'), context, assertCurrentGeneration),
|
|
1900
1652
|
});
|
|
1901
1653
|
});
|
|
1902
1654
|
}
|
|
@@ -2050,7 +1802,7 @@ class ReactNativeBleTransport {
|
|
|
2050
1802
|
writeFrame: (frame, context) => __awaiter(this, void 0, void 0, function* () {
|
|
2051
1803
|
assertCurrentGeneration();
|
|
2052
1804
|
const currentTransport = this.getCachedTransport(uuid);
|
|
2053
|
-
yield this.writeProtocolV2Frame(
|
|
1805
|
+
yield this.writeProtocolV2Frame(currentTransport, frame, context, assertCurrentGeneration);
|
|
2054
1806
|
}),
|
|
2055
1807
|
readFrame: () => __awaiter(this, void 0, void 0, function* () {
|
|
2056
1808
|
assertCurrentGeneration();
|
|
@@ -2071,16 +1823,10 @@ class ReactNativeBleTransport {
|
|
|
2071
1823
|
};
|
|
2072
1824
|
}
|
|
2073
1825
|
getProtocolType(path) {
|
|
2074
|
-
return this.
|
|
1826
|
+
return this.deviceProtocol.get(path);
|
|
2075
1827
|
}
|
|
2076
1828
|
}
|
|
2077
1829
|
|
|
2078
|
-
exports.BLE_CONNECT_TIMEOUT_MANAGER_RESET_THRESHOLD = BLE_CONNECT_TIMEOUT_MANAGER_RESET_THRESHOLD;
|
|
2079
|
-
exports.BLE_CONNECT_TIMEOUT_MS = BLE_CONNECT_TIMEOUT_MS;
|
|
2080
|
-
exports.BLE_GATT_SETUP_TIMEOUT_MS = BLE_GATT_SETUP_TIMEOUT_MS;
|
|
2081
|
-
exports.BLE_WRITE_PACKET_TIMEOUT_MS = BLE_WRITE_PACKET_TIMEOUT_MS;
|
|
2082
|
-
exports.BLE_WRITE_TIMEOUT_MANAGER_RESET_THRESHOLD = BLE_WRITE_TIMEOUT_MANAGER_RESET_THRESHOLD;
|
|
2083
|
-
exports.PROTOCOL_REPROBE_FALLBACK_ATTEMPTS = PROTOCOL_REPROBE_FALLBACK_ATTEMPTS;
|
|
2084
1830
|
exports.configureProtocolV2BleTuning = configureProtocolV2BleTuning;
|
|
2085
1831
|
exports["default"] = ReactNativeBleTransport;
|
|
2086
1832
|
exports.getFirmwareUploadWriteRetryType = getFirmwareUploadWriteRetryType;
|
package/jest.config.js
CHANGED
|
@@ -2,9 +2,4 @@ module.exports = {
|
|
|
2
2
|
preset: '../../jest.config.js',
|
|
3
3
|
testEnvironment: 'node',
|
|
4
4
|
modulePathIgnorePatterns: ['node_modules', '<rootDir>/dist'],
|
|
5
|
-
moduleNameMapper: {
|
|
6
|
-
// The workspace symlinks resolve to prebuilt dist outputs that can lag behind src.
|
|
7
|
-
'^@onekeyfe/hd-transport$': '<rootDir>/../hd-transport/src/index.ts',
|
|
8
|
-
'^@onekeyfe/hd-shared$': '<rootDir>/../shared/src/index.ts',
|
|
9
|
-
},
|
|
10
5
|
};
|