@onekeyfe/hd-transport-react-native 1.2.0-alpha.54 → 1.2.0-alpha.56
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 +1 -38
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +75 -162
- package/jest.config.js +0 -5
- package/package.json +5 -5
- package/src/BleTransport.ts +1 -1
- package/src/__tests__/BleTransport.test.ts +2 -2
- package/src/__tests__/enumerate.test.ts +132 -0
- package/src/__tests__/protocolV2Link.test.ts +241 -41
- package/src/index.ts +74 -236
- package/src/__tests__/staleCallTimeout.test.ts +0 -211
- package/src/__tests__/writePacketTimeout.test.ts +0 -306
package/dist/index.d.ts
CHANGED
|
@@ -35,17 +35,6 @@ type ResolvedBleCharacteristics = {
|
|
|
35
35
|
notifyCharacteristic: Characteristic;
|
|
36
36
|
};
|
|
37
37
|
declare const getFirmwareUploadWriteRetryType: (error: unknown) => FirmwareUploadWriteRetryType | null;
|
|
38
|
-
/**
|
|
39
|
-
* Per-packet write budget. iOS only resolves writeWithoutResponse once CoreBluetooth
|
|
40
|
-
* reports the peripheral ready again; a peripheral wedged by its own firmware reboot
|
|
41
|
-
* stops reporting ready while staying connected, so the write promise never settles.
|
|
42
|
-
* Response timeouts cannot cover that — they are armed after the writes complete —
|
|
43
|
-
* and an unbounded write leaves the whole transport unusable until the process dies.
|
|
44
|
-
* A healthy packet completes in milliseconds, so this only fires on a dead link.
|
|
45
|
-
*/
|
|
46
|
-
declare const BLE_WRITE_PACKET_TIMEOUT_MS = 10000;
|
|
47
|
-
/** Consecutive wedged writes on one device before the BLE manager itself is recreated. */
|
|
48
|
-
declare const BLE_WRITE_TIMEOUT_MANAGER_RESET_THRESHOLD = 2;
|
|
49
38
|
type ProtocolV2BleTuning = {
|
|
50
39
|
iosPacketLength?: number;
|
|
51
40
|
androidPacketLength?: number;
|
|
@@ -72,15 +61,6 @@ declare class ReactNativeBleTransport {
|
|
|
72
61
|
firmwareUploadWriteRecoveryIds: Set<string>;
|
|
73
62
|
/** Per-device protocol type detected by active wire-level probe after connect. */
|
|
74
63
|
private deviceProtocol;
|
|
75
|
-
/**
|
|
76
|
-
* Protocol a probe is currently trying, before the device has confirmed it. Calls
|
|
77
|
-
* must route with it, but acquire() must not treat it as a detected protocol: a
|
|
78
|
-
* probe that never answers would otherwise leave the reuse fast path handing out a
|
|
79
|
-
* transport that was never validated.
|
|
80
|
-
*/
|
|
81
|
-
private probingProtocols;
|
|
82
|
-
/** Consecutive write timeouts per device; reset by any write that completes. */
|
|
83
|
-
private writeTimeoutCounts;
|
|
84
64
|
private deviceProtocolHints;
|
|
85
65
|
private protocolV2Assemblers;
|
|
86
66
|
private protocolV2FrameQueues;
|
|
@@ -120,26 +100,9 @@ declare class ReactNativeBleTransport {
|
|
|
120
100
|
disconnect(session: string): Promise<void>;
|
|
121
101
|
cancel(): void;
|
|
122
102
|
private getCachedTransport;
|
|
123
|
-
/**
|
|
124
|
-
* Write one packet under a bounded budget. A write that never settles means the
|
|
125
|
-
* peripheral is wedged even though the GATT link still reports connected, so the
|
|
126
|
-
* link is torn down: releasing JS state alone would leave the poisoned peripheral
|
|
127
|
-
* cached and every later call would hang on it again.
|
|
128
|
-
*/
|
|
129
|
-
private writeBlePacket;
|
|
130
|
-
/**
|
|
131
|
-
* Drop a link whose writes stopped completing. The JS state is purged synchronously
|
|
132
|
-
* so the next acquire() cannot reuse the dead transport, while the native teardown is
|
|
133
|
-
* intentionally NOT awaited: it talks to the very layer that just stopped settling
|
|
134
|
-
* promises, so awaiting it could hang exactly like the write it is recovering from.
|
|
135
|
-
*/
|
|
136
|
-
private tearDownWedgedLink;
|
|
137
|
-
private resetPlxManager;
|
|
138
103
|
private createProtocolMismatchError;
|
|
139
104
|
private createProtocolDetectionError;
|
|
140
105
|
private clearProbeProtocol;
|
|
141
|
-
/** Protocol to route a call with: confirmed if known, otherwise the one being probed. */
|
|
142
|
-
private getActiveProtocol;
|
|
143
106
|
private detectProtocol;
|
|
144
107
|
private resetProbeStateAfterProtocolProbe;
|
|
145
108
|
private probeProtocolV1;
|
|
@@ -157,4 +120,4 @@ declare class ReactNativeBleTransport {
|
|
|
157
120
|
getProtocolType(path: string): ProtocolType | undefined;
|
|
158
121
|
}
|
|
159
122
|
|
|
160
|
-
export {
|
|
123
|
+
export { IOneKeyDevice, 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,EAE5B,MAAM,sBAAsB,CAAC;AAE9B,OAAO,SAAS,EAAE,EAEhB,KAAK,oBAAoB,EAIzB,KAAK,YAAY,EAKjB,KAAK,oBAAoB,EAG1B,MAAM,wBAAwB,CAAC;
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"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"}
|
package/dist/index.js
CHANGED
|
@@ -210,7 +210,7 @@ class BleTransport {
|
|
|
210
210
|
}
|
|
211
211
|
writeWithRetry(data) {
|
|
212
212
|
return __awaiter(this, void 0, void 0, function* () {
|
|
213
|
-
yield this.writeCharacteristic.
|
|
213
|
+
yield this.writeCharacteristic.writeWithResponse(data);
|
|
214
214
|
});
|
|
215
215
|
}
|
|
216
216
|
}
|
|
@@ -222,6 +222,7 @@ const FIRMWARE_UPLOAD_WRITE_BURST_SIZE = reactNative.Platform.OS === 'ios' ? 4 :
|
|
|
222
222
|
const FIRMWARE_UPLOAD_WRITE_PAUSE_MS = reactNative.Platform.OS === 'ios' ? 8 : 10;
|
|
223
223
|
const FIRMWARE_UPLOAD_WRITE_FLUSH_DELAY_MS = reactNative.Platform.OS === 'ios' ? 24 : 30;
|
|
224
224
|
const FIRMWARE_UPLOAD_WRITE_MAX_RETRIES = 8;
|
|
225
|
+
const IOS_PROTOCOL_V2_CONTROL_WRITE_DELAY_MS = 5;
|
|
225
226
|
const ANDROID_FIRMWARE_UPLOAD_PACKET_LENGTH = 192;
|
|
226
227
|
const FIRMWARE_UPLOAD_WRITE_PACKET_CAPACITY = reactNative.Platform.OS === 'ios' ? IOS_PACKET_LENGTH : ANDROID_FIRMWARE_UPLOAD_PACKET_LENGTH;
|
|
227
228
|
const ANDROID_GATT_CONGESTED_STATUS = 143;
|
|
@@ -244,12 +245,6 @@ const getFirmwareUploadWriteRetryType = (error) => {
|
|
|
244
245
|
const resolveFirmwareUploadRetryDelay = (attempt, baseDelayMs = 200, maxDelayMs = 1200) => Math.min(baseDelayMs * Math.pow(2, attempt), maxDelayMs);
|
|
245
246
|
const PROTOCOL_PROBE_TIMEOUT_MS = 1000;
|
|
246
247
|
const PROTOCOL_V2_PROBE_TIMEOUT_MS = 10000;
|
|
247
|
-
const BLE_WRITE_PACKET_TIMEOUT_MS = 10000;
|
|
248
|
-
const WEDGED_WRITE_MESSAGE = 'BLE write timeout after';
|
|
249
|
-
const isWedgedWriteError = (error) => (error === null || error === void 0 ? void 0 : error.errorCode) === hdShared.HardwareErrorCode.BleWriteCharacteristicError &&
|
|
250
|
-
typeof (error === null || error === void 0 ? void 0 : error.message) === 'string' &&
|
|
251
|
-
error.message.startsWith(WEDGED_WRITE_MESSAGE);
|
|
252
|
-
const BLE_WRITE_TIMEOUT_MANAGER_RESET_THRESHOLD = 2;
|
|
253
248
|
const DEVICE_SCAN_TIMEOUT_MS = 3000;
|
|
254
249
|
const IOS_NOTIFY_READY_DELAY_MS = 150;
|
|
255
250
|
const ANDROID_NOTIFY_READY_DELAY_MS = 300;
|
|
@@ -347,8 +342,6 @@ class ReactNativeBleTransport {
|
|
|
347
342
|
this.runPromiseDeviceId = null;
|
|
348
343
|
this.firmwareUploadWriteRecoveryIds = new Set();
|
|
349
344
|
this.deviceProtocol = new Map();
|
|
350
|
-
this.probingProtocols = new Map();
|
|
351
|
-
this.writeTimeoutCounts = new Map();
|
|
352
345
|
this.deviceProtocolHints = new Map();
|
|
353
346
|
this.protocolV2Assemblers = new Map();
|
|
354
347
|
this.protocolV2FrameQueues = new Map();
|
|
@@ -622,12 +615,17 @@ class ReactNativeBleTransport {
|
|
|
622
615
|
return;
|
|
623
616
|
}
|
|
624
617
|
const displayName = getDeviceDisplayName(device);
|
|
625
|
-
const
|
|
626
|
-
|
|
627
|
-
|
|
628
|
-
|
|
629
|
-
|
|
630
|
-
|
|
618
|
+
const isUnnamedIOSPeripheral = reactNative.Platform.OS === 'ios' && !(displayName === null || displayName === void 0 ? void 0 : displayName.trim());
|
|
619
|
+
const isFindMyPeripheral = hdShared.isPro2FindMyAdvertisementName(device === null || device === void 0 ? void 0 : device.name) ||
|
|
620
|
+
hdShared.isPro2FindMyAdvertisementName(device === null || device === void 0 ? void 0 : device.localName);
|
|
621
|
+
const isOneKey = !isUnnamedIOSPeripheral &&
|
|
622
|
+
!isFindMyPeripheral &&
|
|
623
|
+
hdShared.isOnekeyBluetoothDevice({
|
|
624
|
+
id: device === null || device === void 0 ? void 0 : device.id,
|
|
625
|
+
name: device === null || device === void 0 ? void 0 : device.name,
|
|
626
|
+
localName: device === null || device === void 0 ? void 0 : device.localName,
|
|
627
|
+
serviceUuids: device === null || device === void 0 ? void 0 : device.serviceUUIDs,
|
|
628
|
+
});
|
|
631
629
|
if (isOneKey) {
|
|
632
630
|
addDevice(device);
|
|
633
631
|
}
|
|
@@ -645,12 +643,15 @@ class ReactNativeBleTransport {
|
|
|
645
643
|
const localName = 'localName' in device && typeof device.localName === 'string'
|
|
646
644
|
? device.localName
|
|
647
645
|
: null;
|
|
648
|
-
|
|
649
|
-
|
|
650
|
-
|
|
651
|
-
|
|
652
|
-
|
|
653
|
-
|
|
646
|
+
const isFindMyPeripheral = hdShared.isPro2FindMyAdvertisementName(device.name) ||
|
|
647
|
+
hdShared.isPro2FindMyAdvertisementName(localName);
|
|
648
|
+
if (!isFindMyPeripheral &&
|
|
649
|
+
hdShared.isOnekeyBluetoothDevice({
|
|
650
|
+
id: device.id,
|
|
651
|
+
name: device.name,
|
|
652
|
+
localName,
|
|
653
|
+
serviceUuids: device.serviceUUIDs,
|
|
654
|
+
})) {
|
|
654
655
|
Log === null || Log === void 0 ? void 0 : Log.debug('search connected peripheral: ', device.id);
|
|
655
656
|
addDevice(device);
|
|
656
657
|
}
|
|
@@ -860,7 +861,7 @@ class ReactNativeBleTransport {
|
|
|
860
861
|
Log === null || Log === void 0 ? void 0 : Log.debug('monitor error ignored for stale transport: ', uuid, notifyTransactionId);
|
|
861
862
|
return;
|
|
862
863
|
}
|
|
863
|
-
if (this.
|
|
864
|
+
if (this.deviceProtocol.get(uuid) === 'V2') {
|
|
864
865
|
let errorCode = hdShared.HardwareErrorCode.BleCharacteristicNotifyError;
|
|
865
866
|
if ((_a = error.reason) === null || _a === void 0 ? void 0 : _a.includes('The connection has timed out unexpectedly')) {
|
|
866
867
|
errorCode = hdShared.HardwareErrorCode.BleTimeoutError;
|
|
@@ -911,7 +912,7 @@ class ReactNativeBleTransport {
|
|
|
911
912
|
}
|
|
912
913
|
try {
|
|
913
914
|
const data = buffer.Buffer.from(c.value, 'base64');
|
|
914
|
-
const protocol = this.
|
|
915
|
+
const protocol = this.deviceProtocol.get(uuid);
|
|
915
916
|
if (!protocol) {
|
|
916
917
|
Log === null || Log === void 0 ? void 0 : Log.debug('monitor data ignored before protocol detection: ', uuid);
|
|
917
918
|
return;
|
|
@@ -939,7 +940,7 @@ class ReactNativeBleTransport {
|
|
|
939
940
|
catch (error) {
|
|
940
941
|
Log === null || Log === void 0 ? void 0 : Log.debug('monitor data error: ', error);
|
|
941
942
|
const notifyError = hdShared.ERRORS.TypedError(hdShared.HardwareErrorCode.BleWriteCharacteristicError);
|
|
942
|
-
if (this.
|
|
943
|
+
if (this.deviceProtocol.get(uuid) === 'V2') {
|
|
943
944
|
this.rejectProtocolV2Frames(uuid, notifyError);
|
|
944
945
|
}
|
|
945
946
|
else if (this.runPromiseDeviceId === uuid) {
|
|
@@ -995,7 +996,6 @@ class ReactNativeBleTransport {
|
|
|
995
996
|
delete transportCache[uuid];
|
|
996
997
|
}
|
|
997
998
|
this.deviceProtocol.delete(uuid);
|
|
998
|
-
this.probingProtocols.delete(uuid);
|
|
999
999
|
(_f = this.protocolV2Assemblers.get(uuid)) === null || _f === void 0 ? void 0 : _f.reset();
|
|
1000
1000
|
this.protocolV2Assemblers.delete(uuid);
|
|
1001
1001
|
this.resetProtocolV2Frames(uuid);
|
|
@@ -1044,19 +1044,8 @@ class ReactNativeBleTransport {
|
|
|
1044
1044
|
const transport = this.getCachedTransport(uuid);
|
|
1045
1045
|
const runPromise = hdShared.createDeferred();
|
|
1046
1046
|
runPromise.promise.catch(() => undefined);
|
|
1047
|
-
const supersededRunPromise = this.runPromise;
|
|
1048
|
-
if (supersededRunPromise) {
|
|
1049
|
-
supersededRunPromise.reject(hdShared.ERRORS.TypedError(hdShared.HardwareErrorCode.BleForceCleanRunPromise));
|
|
1050
|
-
}
|
|
1051
1047
|
this.runPromise = runPromise;
|
|
1052
1048
|
this.runPromiseDeviceId = uuid;
|
|
1053
|
-
const releaseOwnershipIfCurrent = () => {
|
|
1054
|
-
if (this.runPromise === runPromise) {
|
|
1055
|
-
this.runPromise = null;
|
|
1056
|
-
this.runPromiseDeviceId = null;
|
|
1057
|
-
}
|
|
1058
|
-
};
|
|
1059
|
-
const isCurrentOwner = () => this.runPromise === runPromise;
|
|
1060
1049
|
const messages = this._messages;
|
|
1061
1050
|
const buffers = ProtocolV1.encodeTransportPackets(messages, name, data);
|
|
1062
1051
|
let timeout;
|
|
@@ -1077,9 +1066,6 @@ class ReactNativeBleTransport {
|
|
|
1077
1066
|
}
|
|
1078
1067
|
catch (e) {
|
|
1079
1068
|
onError(e);
|
|
1080
|
-
if (isWedgedWriteError(e)) {
|
|
1081
|
-
throw e;
|
|
1082
|
-
}
|
|
1083
1069
|
throw hdShared.ERRORS.TypedError(hdShared.HardwareErrorCode.BleWriteCharacteristicError);
|
|
1084
1070
|
}
|
|
1085
1071
|
}
|
|
@@ -1107,9 +1093,6 @@ class ReactNativeBleTransport {
|
|
|
1107
1093
|
}
|
|
1108
1094
|
catch (e) {
|
|
1109
1095
|
onError(e);
|
|
1110
|
-
if (isWedgedWriteError(e)) {
|
|
1111
|
-
throw e;
|
|
1112
|
-
}
|
|
1113
1096
|
throw hdShared.ERRORS.TypedError(hdShared.HardwareErrorCode.BleWriteCharacteristicError);
|
|
1114
1097
|
}
|
|
1115
1098
|
}
|
|
@@ -1120,8 +1103,8 @@ class ReactNativeBleTransport {
|
|
|
1120
1103
|
});
|
|
1121
1104
|
}
|
|
1122
1105
|
if (name === 'EmmcFileWrite') {
|
|
1123
|
-
yield writeChunkedData(buffers, data =>
|
|
1124
|
-
|
|
1106
|
+
yield writeChunkedData(buffers, data => transport.writeWithRetry(data), e => {
|
|
1107
|
+
this.runPromise = null;
|
|
1125
1108
|
Log === null || Log === void 0 ? void 0 : Log.error('writeCharacteristic write error: ', e);
|
|
1126
1109
|
});
|
|
1127
1110
|
}
|
|
@@ -1137,7 +1120,7 @@ class ReactNativeBleTransport {
|
|
|
1137
1120
|
let attempt = 0;
|
|
1138
1121
|
while (true) {
|
|
1139
1122
|
try {
|
|
1140
|
-
yield
|
|
1123
|
+
yield transport.writeCharacteristic.writeWithResponse(data);
|
|
1141
1124
|
return;
|
|
1142
1125
|
}
|
|
1143
1126
|
catch (error) {
|
|
@@ -1156,7 +1139,7 @@ class ReactNativeBleTransport {
|
|
|
1156
1139
|
}
|
|
1157
1140
|
}
|
|
1158
1141
|
}), e => {
|
|
1159
|
-
|
|
1142
|
+
this.runPromise = null;
|
|
1160
1143
|
Log === null || Log === void 0 ? void 0 : Log.error('writeCharacteristic write error: ', e);
|
|
1161
1144
|
});
|
|
1162
1145
|
}
|
|
@@ -1164,14 +1147,17 @@ class ReactNativeBleTransport {
|
|
|
1164
1147
|
for (const o of buffers) {
|
|
1165
1148
|
const outData = o.toString('base64');
|
|
1166
1149
|
try {
|
|
1167
|
-
|
|
1150
|
+
const shouldUseWriteWithResponse = reactNative.Platform.OS === 'ios' && transport.writeCharacteristic.isWritableWithResponse;
|
|
1151
|
+
if (shouldUseWriteWithResponse) {
|
|
1152
|
+
yield transport.writeCharacteristic.writeWithResponse(outData);
|
|
1153
|
+
}
|
|
1154
|
+
else {
|
|
1155
|
+
yield transport.writeCharacteristic.writeWithoutResponse(outData);
|
|
1156
|
+
}
|
|
1168
1157
|
}
|
|
1169
1158
|
catch (e) {
|
|
1170
1159
|
Log === null || Log === void 0 ? void 0 : Log.debug('writeCharacteristic write error: ', e);
|
|
1171
|
-
|
|
1172
|
-
if (isWedgedWriteError(e)) {
|
|
1173
|
-
throw e;
|
|
1174
|
-
}
|
|
1160
|
+
this.runPromise = null;
|
|
1175
1161
|
if (e.errorCode === reactNativeBlePlx.BleErrorCode.DeviceDisconnected) {
|
|
1176
1162
|
throw hdShared.ERRORS.TypedError(hdShared.HardwareErrorCode.BleDeviceNotBonded);
|
|
1177
1163
|
}
|
|
@@ -1211,9 +1197,7 @@ class ReactNativeBleTransport {
|
|
|
1211
1197
|
Log === null || Log === void 0 ? void 0 : Log.error('call error: ', e);
|
|
1212
1198
|
}
|
|
1213
1199
|
const isProbeTimeout = name === 'GetFeatures' && (options === null || options === void 0 ? void 0 : options.timeoutMs) === PROTOCOL_PROBE_TIMEOUT_MS;
|
|
1214
|
-
const isStaleCall = this.runPromise !== runPromise;
|
|
1215
1200
|
if (!isProbeTimeout &&
|
|
1216
|
-
!isStaleCall &&
|
|
1217
1201
|
(e === null || e === void 0 ? void 0 : e.errorCode) === hdShared.HardwareErrorCode.BleTimeoutError) {
|
|
1218
1202
|
yield this.disconnect(uuid);
|
|
1219
1203
|
}
|
|
@@ -1284,7 +1268,6 @@ class ReactNativeBleTransport {
|
|
|
1284
1268
|
delete transportCache[session];
|
|
1285
1269
|
}
|
|
1286
1270
|
this.deviceProtocol.delete(session);
|
|
1287
|
-
this.probingProtocols.delete(session);
|
|
1288
1271
|
this.deviceProtocolHints.delete(session);
|
|
1289
1272
|
this.protocolV2Assemblers.delete(session);
|
|
1290
1273
|
this.resetProtocolV2Frames(session);
|
|
@@ -1313,80 +1296,6 @@ class ReactNativeBleTransport {
|
|
|
1313
1296
|
}
|
|
1314
1297
|
return transport;
|
|
1315
1298
|
}
|
|
1316
|
-
writeBlePacket(uuid, data, write, isCurrentOwner) {
|
|
1317
|
-
return __awaiter(this, void 0, void 0, function* () {
|
|
1318
|
-
let timer;
|
|
1319
|
-
let timedOut = false;
|
|
1320
|
-
try {
|
|
1321
|
-
yield Promise.race([
|
|
1322
|
-
write(data),
|
|
1323
|
-
new Promise((_, reject) => {
|
|
1324
|
-
timer = setTimeout(() => {
|
|
1325
|
-
timedOut = true;
|
|
1326
|
-
reject(hdShared.ERRORS.TypedError(hdShared.HardwareErrorCode.BleWriteCharacteristicError, `BLE write timeout after ${BLE_WRITE_PACKET_TIMEOUT_MS}ms`));
|
|
1327
|
-
}, BLE_WRITE_PACKET_TIMEOUT_MS);
|
|
1328
|
-
}),
|
|
1329
|
-
]);
|
|
1330
|
-
this.writeTimeoutCounts.delete(uuid);
|
|
1331
|
-
}
|
|
1332
|
-
catch (error) {
|
|
1333
|
-
if (timedOut) {
|
|
1334
|
-
if (isCurrentOwner && !isCurrentOwner()) {
|
|
1335
|
-
Log === null || Log === void 0 ? void 0 : Log.debug('[ReactNativeBleTransport] stale BLE write timed out, link kept:', uuid);
|
|
1336
|
-
}
|
|
1337
|
-
else {
|
|
1338
|
-
this.tearDownWedgedLink(uuid);
|
|
1339
|
-
}
|
|
1340
|
-
}
|
|
1341
|
-
throw error;
|
|
1342
|
-
}
|
|
1343
|
-
finally {
|
|
1344
|
-
if (timer)
|
|
1345
|
-
clearTimeout(timer);
|
|
1346
|
-
}
|
|
1347
|
-
});
|
|
1348
|
-
}
|
|
1349
|
-
tearDownWedgedLink(uuid) {
|
|
1350
|
-
var _a;
|
|
1351
|
-
const timeouts = ((_a = this.writeTimeoutCounts.get(uuid)) !== null && _a !== void 0 ? _a : 0) + 1;
|
|
1352
|
-
this.writeTimeoutCounts.set(uuid, timeouts);
|
|
1353
|
-
Log === null || Log === void 0 ? void 0 : Log.error('[ReactNativeBleTransport] BLE write timed out, tearing down link:', uuid, {
|
|
1354
|
-
consecutiveWriteTimeouts: timeouts,
|
|
1355
|
-
});
|
|
1356
|
-
const wedged = transportCache[uuid];
|
|
1357
|
-
this.disconnect(uuid).catch(error => {
|
|
1358
|
-
Log === null || Log === void 0 ? void 0 : Log.debug('[ReactNativeBleTransport] wedged link teardown failed (ignored):', error);
|
|
1359
|
-
});
|
|
1360
|
-
if (wedged && transportCache[uuid] === wedged) {
|
|
1361
|
-
delete transportCache[uuid];
|
|
1362
|
-
}
|
|
1363
|
-
this.deviceProtocol.delete(uuid);
|
|
1364
|
-
this.probingProtocols.delete(uuid);
|
|
1365
|
-
this.protocolV2Assemblers.delete(uuid);
|
|
1366
|
-
this.resetProtocolV2Frames(uuid);
|
|
1367
|
-
if (timeouts >= BLE_WRITE_TIMEOUT_MANAGER_RESET_THRESHOLD) {
|
|
1368
|
-
Log === null || Log === void 0 ? void 0 : Log.error('[ReactNativeBleTransport] BLE writes wedged repeatedly, resetting BLE manager');
|
|
1369
|
-
this.resetPlxManager();
|
|
1370
|
-
this.writeTimeoutCounts.delete(uuid);
|
|
1371
|
-
}
|
|
1372
|
-
}
|
|
1373
|
-
resetPlxManager() {
|
|
1374
|
-
const manager = this.blePlxManager;
|
|
1375
|
-
this.blePlxManager = undefined;
|
|
1376
|
-
Object.keys(transportCache).forEach(key => {
|
|
1377
|
-
delete transportCache[key];
|
|
1378
|
-
});
|
|
1379
|
-
this.deviceProtocol.clear();
|
|
1380
|
-
this.probingProtocols.clear();
|
|
1381
|
-
this.monitorTokens.clear();
|
|
1382
|
-
this.protocolV2Assemblers.clear();
|
|
1383
|
-
try {
|
|
1384
|
-
manager === null || manager === void 0 ? void 0 : manager.destroy();
|
|
1385
|
-
}
|
|
1386
|
-
catch (error) {
|
|
1387
|
-
Log === null || Log === void 0 ? void 0 : Log.debug('[ReactNativeBleTransport] BLE manager destroy failed (ignored):', error);
|
|
1388
|
-
}
|
|
1389
|
-
}
|
|
1390
1299
|
createProtocolMismatchError(expected) {
|
|
1391
1300
|
return hdShared.ERRORS.TypedError(hdShared.HardwareErrorCode.RuntimeError, `Device protocol mismatch: expected ${expected}, but device did not respond to expected protocol`);
|
|
1392
1301
|
}
|
|
@@ -1394,19 +1303,30 @@ class ReactNativeBleTransport {
|
|
|
1394
1303
|
return hdShared.ERRORS.TypedError(hdShared.HardwareErrorCode.BleTimeoutError, 'Unable to detect BLE protocol: device did not respond to Protocol V1 GetFeatures or Protocol V2 Ping');
|
|
1395
1304
|
}
|
|
1396
1305
|
clearProbeProtocol(uuid, protocol) {
|
|
1397
|
-
if (this.probingProtocols.get(uuid) === protocol) {
|
|
1398
|
-
this.probingProtocols.delete(uuid);
|
|
1399
|
-
}
|
|
1400
1306
|
if (this.deviceProtocol.get(uuid) === protocol) {
|
|
1401
1307
|
this.deviceProtocol.delete(uuid);
|
|
1402
1308
|
}
|
|
1403
1309
|
}
|
|
1404
|
-
getActiveProtocol(uuid) {
|
|
1405
|
-
var _a;
|
|
1406
|
-
return (_a = this.deviceProtocol.get(uuid)) !== null && _a !== void 0 ? _a : this.probingProtocols.get(uuid);
|
|
1407
|
-
}
|
|
1408
1310
|
detectProtocol(uuid, expectedProtocol, protocolHint, rebuildTransport) {
|
|
1311
|
+
var _a;
|
|
1409
1312
|
return __awaiter(this, void 0, void 0, function* () {
|
|
1313
|
+
if (reactNative.Platform.OS === 'ios') {
|
|
1314
|
+
const protocol = (_a = expectedProtocol !== null && expectedProtocol !== void 0 ? expectedProtocol : protocolHint) !== null && _a !== void 0 ? _a : 'V1';
|
|
1315
|
+
let source = 'ios-legacy-default';
|
|
1316
|
+
if (expectedProtocol) {
|
|
1317
|
+
source = 'expected';
|
|
1318
|
+
}
|
|
1319
|
+
else if (protocolHint) {
|
|
1320
|
+
source = 'hint';
|
|
1321
|
+
}
|
|
1322
|
+
this.deviceProtocol.set(uuid, protocol);
|
|
1323
|
+
Log === null || Log === void 0 ? void 0 : Log.debug('[ReactNativeBleTransport] protocol selected', {
|
|
1324
|
+
deviceId: uuid,
|
|
1325
|
+
protocol,
|
|
1326
|
+
source,
|
|
1327
|
+
});
|
|
1328
|
+
return protocol;
|
|
1329
|
+
}
|
|
1410
1330
|
if (expectedProtocol === 'V1') {
|
|
1411
1331
|
if (yield this.probeProtocolV1(uuid)) {
|
|
1412
1332
|
this.deviceProtocol.set(uuid, 'V1');
|
|
@@ -1455,7 +1375,6 @@ class ReactNativeBleTransport {
|
|
|
1455
1375
|
}
|
|
1456
1376
|
}
|
|
1457
1377
|
this.deviceProtocol.delete(uuid);
|
|
1458
|
-
this.probingProtocols.delete(uuid);
|
|
1459
1378
|
throw this.createProtocolDetectionError();
|
|
1460
1379
|
});
|
|
1461
1380
|
}
|
|
@@ -1507,17 +1426,13 @@ class ReactNativeBleTransport {
|
|
|
1507
1426
|
return false;
|
|
1508
1427
|
}
|
|
1509
1428
|
try {
|
|
1510
|
-
this.
|
|
1429
|
+
this.deviceProtocol.set(uuid, 'V1');
|
|
1511
1430
|
yield this.callProtocolV1(uuid, 'GetFeatures', {}, { timeoutMs: PROTOCOL_PROBE_TIMEOUT_MS });
|
|
1512
|
-
this.probingProtocols.delete(uuid);
|
|
1513
1431
|
return true;
|
|
1514
1432
|
}
|
|
1515
1433
|
catch (error) {
|
|
1516
1434
|
this.clearProbeProtocol(uuid, 'V1');
|
|
1517
1435
|
Log === null || Log === void 0 ? void 0 : Log.debug('[ReactNativeBleTransport] Protocol V1 GetFeatures probe failed:', error);
|
|
1518
|
-
if (isWedgedWriteError(error)) {
|
|
1519
|
-
throw error;
|
|
1520
|
-
}
|
|
1521
1436
|
return false;
|
|
1522
1437
|
}
|
|
1523
1438
|
});
|
|
@@ -1528,7 +1443,7 @@ class ReactNativeBleTransport {
|
|
|
1528
1443
|
if (!this._messages || !this._messagesV2) {
|
|
1529
1444
|
return false;
|
|
1530
1445
|
}
|
|
1531
|
-
this.
|
|
1446
|
+
this.deviceProtocol.set(uuid, 'V2');
|
|
1532
1447
|
(_a = this.protocolV2Assemblers.get(uuid)) === null || _a === void 0 ? void 0 : _a.reset();
|
|
1533
1448
|
const detected = yield transport.probeProtocolV2({
|
|
1534
1449
|
call: (name, data, options) => this.callProtocolV2(uuid, name, data, options),
|
|
@@ -1544,9 +1459,6 @@ class ReactNativeBleTransport {
|
|
|
1544
1459
|
if (!detected) {
|
|
1545
1460
|
this.clearProbeProtocol(uuid, 'V2');
|
|
1546
1461
|
}
|
|
1547
|
-
else {
|
|
1548
|
-
this.probingProtocols.delete(uuid);
|
|
1549
|
-
}
|
|
1550
1462
|
return detected;
|
|
1551
1463
|
});
|
|
1552
1464
|
}
|
|
@@ -1618,8 +1530,10 @@ class ReactNativeBleTransport {
|
|
|
1618
1530
|
}
|
|
1619
1531
|
});
|
|
1620
1532
|
}
|
|
1621
|
-
writeProtocolV2Packet(
|
|
1533
|
+
writeProtocolV2Packet(transport, base64, context, assertCurrentGeneration) {
|
|
1622
1534
|
return __awaiter(this, void 0, void 0, function* () {
|
|
1535
|
+
const shouldUseWriteWithResponse = transport.writeCharacteristic.isWritableWithResponse &&
|
|
1536
|
+
(context.writeWithResponse === true || (reactNative.Platform.OS === 'ios' && !context.highVolume));
|
|
1623
1537
|
let attempt = 0;
|
|
1624
1538
|
for (;;) {
|
|
1625
1539
|
assertCurrentGeneration();
|
|
@@ -1627,15 +1541,12 @@ class ReactNativeBleTransport {
|
|
|
1627
1541
|
throw new Error(`Protocol V2 BLE write aborted for ${context.messageName}`);
|
|
1628
1542
|
}
|
|
1629
1543
|
try {
|
|
1630
|
-
|
|
1631
|
-
|
|
1632
|
-
|
|
1633
|
-
|
|
1634
|
-
|
|
1635
|
-
|
|
1636
|
-
return false;
|
|
1637
|
-
}
|
|
1638
|
-
});
|
|
1544
|
+
if (shouldUseWriteWithResponse) {
|
|
1545
|
+
yield transport.writeCharacteristic.writeWithResponse(base64);
|
|
1546
|
+
}
|
|
1547
|
+
else {
|
|
1548
|
+
yield transport.writeCharacteristic.writeWithoutResponse(base64);
|
|
1549
|
+
}
|
|
1639
1550
|
assertCurrentGeneration();
|
|
1640
1551
|
return;
|
|
1641
1552
|
}
|
|
@@ -1656,7 +1567,7 @@ class ReactNativeBleTransport {
|
|
|
1656
1567
|
}
|
|
1657
1568
|
});
|
|
1658
1569
|
}
|
|
1659
|
-
writeProtocolV2Frame(
|
|
1570
|
+
writeProtocolV2Frame(transport$1, frame, context, assertCurrentGeneration) {
|
|
1660
1571
|
return __awaiter(this, void 0, void 0, function* () {
|
|
1661
1572
|
const tuning = getProtocolV2BleTuning();
|
|
1662
1573
|
const packetCapacity = resolveProtocolV2PacketCapacity({
|
|
@@ -1665,17 +1576,21 @@ class ReactNativeBleTransport {
|
|
|
1665
1576
|
androidPacketLength: tuning.androidPacketLength,
|
|
1666
1577
|
mtu: reactNative.Platform.OS === 'android' ? transport$1.mtuSize : undefined,
|
|
1667
1578
|
});
|
|
1579
|
+
const initialDelayMs = reactNative.Platform.OS === 'ios' && !context.highVolume && frame.length <= packetCapacity
|
|
1580
|
+
? IOS_PROTOCOL_V2_CONTROL_WRITE_DELAY_MS
|
|
1581
|
+
: 0;
|
|
1668
1582
|
yield transport.writeProtocolV2BleFrame({
|
|
1669
1583
|
frame,
|
|
1670
1584
|
packetCapacity,
|
|
1671
1585
|
assertActive: assertCurrentGeneration,
|
|
1672
1586
|
signal: context.signal,
|
|
1673
1587
|
abortMessage: `Protocol V2 BLE write aborted for ${context.messageName}`,
|
|
1588
|
+
initialDelayMs,
|
|
1674
1589
|
burstSize: FIRMWARE_UPLOAD_WRITE_BURST_SIZE,
|
|
1675
1590
|
burstPauseMs: FIRMWARE_UPLOAD_WRITE_PAUSE_MS,
|
|
1676
1591
|
flushDelayMs: FIRMWARE_UPLOAD_WRITE_FLUSH_DELAY_MS,
|
|
1677
1592
|
wait: delay,
|
|
1678
|
-
writePacket: packet => this.writeProtocolV2Packet(
|
|
1593
|
+
writePacket: packet => this.writeProtocolV2Packet(transport$1, buffer.Buffer.from(packet).toString('base64'), context, assertCurrentGeneration),
|
|
1679
1594
|
});
|
|
1680
1595
|
});
|
|
1681
1596
|
}
|
|
@@ -1690,7 +1605,7 @@ class ReactNativeBleTransport {
|
|
|
1690
1605
|
const tuning = getProtocolV2BleTuning();
|
|
1691
1606
|
Log === null || Log === void 0 ? void 0 : Log.debug('[ReactNativeBleTransport] Protocol V2 high-volume write configured', {
|
|
1692
1607
|
name,
|
|
1693
|
-
writeMode: 'withoutResponse',
|
|
1608
|
+
writeMode: (options === null || options === void 0 ? void 0 : options.writeWithResponse) ? 'withResponse' : 'withoutResponse',
|
|
1694
1609
|
packetCapacity: reactNative.Platform.OS === 'ios' ? tuning.iosPacketLength : tuning.androidPacketLength,
|
|
1695
1610
|
});
|
|
1696
1611
|
}
|
|
@@ -1724,7 +1639,7 @@ class ReactNativeBleTransport {
|
|
|
1724
1639
|
writeFrame: (frame, context) => __awaiter(this, void 0, void 0, function* () {
|
|
1725
1640
|
assertCurrentGeneration();
|
|
1726
1641
|
const currentTransport = this.getCachedTransport(uuid);
|
|
1727
|
-
yield this.writeProtocolV2Frame(
|
|
1642
|
+
yield this.writeProtocolV2Frame(currentTransport, frame, context, assertCurrentGeneration);
|
|
1728
1643
|
}),
|
|
1729
1644
|
readFrame: () => __awaiter(this, void 0, void 0, function* () {
|
|
1730
1645
|
assertCurrentGeneration();
|
|
@@ -1745,12 +1660,10 @@ class ReactNativeBleTransport {
|
|
|
1745
1660
|
};
|
|
1746
1661
|
}
|
|
1747
1662
|
getProtocolType(path) {
|
|
1748
|
-
return this.
|
|
1663
|
+
return this.deviceProtocol.get(path);
|
|
1749
1664
|
}
|
|
1750
1665
|
}
|
|
1751
1666
|
|
|
1752
|
-
exports.BLE_WRITE_PACKET_TIMEOUT_MS = BLE_WRITE_PACKET_TIMEOUT_MS;
|
|
1753
|
-
exports.BLE_WRITE_TIMEOUT_MANAGER_RESET_THRESHOLD = BLE_WRITE_TIMEOUT_MANAGER_RESET_THRESHOLD;
|
|
1754
1667
|
exports.configureProtocolV2BleTuning = configureProtocolV2BleTuning;
|
|
1755
1668
|
exports["default"] = ReactNativeBleTransport;
|
|
1756
1669
|
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
|
};
|
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.56",
|
|
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.56",
|
|
24
|
+
"@onekeyfe/hd-shared": "1.2.0-alpha.56",
|
|
25
|
+
"@onekeyfe/hd-transport": "1.2.0-alpha.56",
|
|
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": "2c472748d67072307c21f8d33bc021cf18fe2ad7"
|
|
30
30
|
}
|
package/src/BleTransport.ts
CHANGED
|
@@ -24,7 +24,7 @@ describe('BleTransport side-effecting writes', () => {
|
|
|
24
24
|
errorCode: BleErrorCode.DeviceDisconnected,
|
|
25
25
|
});
|
|
26
26
|
const writeCharacteristic = {
|
|
27
|
-
|
|
27
|
+
writeWithResponse: jest.fn(() => Promise.reject(error)),
|
|
28
28
|
};
|
|
29
29
|
const device = {
|
|
30
30
|
id: 'classic-id',
|
|
@@ -35,7 +35,7 @@ describe('BleTransport side-effecting writes', () => {
|
|
|
35
35
|
|
|
36
36
|
await expect(transport.writeWithRetry('payload')).rejects.toBe(error);
|
|
37
37
|
|
|
38
|
-
expect(writeCharacteristic.
|
|
38
|
+
expect(writeCharacteristic.writeWithResponse).toHaveBeenCalledTimes(1);
|
|
39
39
|
expect(device.connect).not.toHaveBeenCalled();
|
|
40
40
|
});
|
|
41
41
|
});
|