@onekeyfe/hd-transport-react-native 1.2.4-alpha.0 → 1.2.4-alpha.2
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/bleIosStaleBond.d.ts +16 -0
- package/dist/bleIosStaleBond.d.ts.map +1 -0
- package/dist/index.d.ts +12 -10
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +118 -139
- package/package.json +5 -5
- package/src/__tests__/iosPeerTermination.test.ts +318 -0
- package/src/__tests__/protocolReprobe.test.ts +1 -116
- package/src/bleIosStaleBond.ts +92 -0
- package/src/index.ts +79 -184
package/src/index.ts
CHANGED
|
@@ -59,6 +59,7 @@ import {
|
|
|
59
59
|
stopBleEncryptionTracking,
|
|
60
60
|
waitForAndroidLinkEncryption,
|
|
61
61
|
} from './bleEncryption';
|
|
62
|
+
import { IosPeerTerminationTracker } from './bleIosStaleBond';
|
|
62
63
|
import { isNativeBleDisconnectError, toBleDisconnectHardwareError } from './bleNativeDisconnect';
|
|
63
64
|
import {
|
|
64
65
|
isBleStaleBondHardwareError,
|
|
@@ -233,55 +234,6 @@ const isAndroidLinkLossError = (error: unknown): boolean => {
|
|
|
233
234
|
code === HardwareErrorCode.BleConnectedError
|
|
234
235
|
);
|
|
235
236
|
};
|
|
236
|
-
|
|
237
|
-
const logIosBleBondDiagnostic = (
|
|
238
|
-
phase: string,
|
|
239
|
-
error: unknown,
|
|
240
|
-
outcome: 'fallback' | 'rethrow'
|
|
241
|
-
) => {
|
|
242
|
-
if (Platform.OS !== 'ios') return;
|
|
243
|
-
|
|
244
|
-
const nativeError = (error ?? {}) as {
|
|
245
|
-
name?: unknown;
|
|
246
|
-
errorCode?: unknown;
|
|
247
|
-
attErrorCode?: unknown;
|
|
248
|
-
iosErrorCode?: unknown;
|
|
249
|
-
androidErrorCode?: unknown;
|
|
250
|
-
};
|
|
251
|
-
const scalar = (value: unknown) =>
|
|
252
|
-
typeof value === 'string' || typeof value === 'number' ? value : undefined;
|
|
253
|
-
|
|
254
|
-
Log?.debug('[ReactNativeBleTransport][BleBondDiagnostic] probe error', {
|
|
255
|
-
phase,
|
|
256
|
-
outcome,
|
|
257
|
-
errorName: scalar(nativeError.name),
|
|
258
|
-
errorCode: scalar(nativeError.errorCode),
|
|
259
|
-
attErrorCode: scalar(nativeError.attErrorCode),
|
|
260
|
-
iosErrorCode: scalar(nativeError.iosErrorCode),
|
|
261
|
-
androidErrorCode: scalar(nativeError.androidErrorCode),
|
|
262
|
-
nativeStaleBond: isNativeBleStaleBondError(error),
|
|
263
|
-
hardwareStaleBond: isBleStaleBondHardwareError(error),
|
|
264
|
-
nativeDisconnect: isNativeBleDisconnectError(error),
|
|
265
|
-
});
|
|
266
|
-
};
|
|
267
|
-
|
|
268
|
-
type IosProbeDisconnectEvidence = {
|
|
269
|
-
phase: 'protocol-v1-get-features' | 'protocol-v2-ping';
|
|
270
|
-
errorCode?: string | number;
|
|
271
|
-
recordedAt: number;
|
|
272
|
-
};
|
|
273
|
-
|
|
274
|
-
const IOS_PROBE_DISCONNECT_EVIDENCE_TTL_MS = 5 * 60_000;
|
|
275
|
-
|
|
276
|
-
const isIosProbeDisconnectError = (error: unknown): boolean => {
|
|
277
|
-
if (Platform.OS !== 'ios') return false;
|
|
278
|
-
const code = (error as { errorCode?: unknown })?.errorCode;
|
|
279
|
-
return (
|
|
280
|
-
isNativeBleDisconnectError(error) ||
|
|
281
|
-
code === HardwareErrorCode.BleDeviceNotBonded ||
|
|
282
|
-
code === HardwareErrorCode.BleDeviceDisconnected
|
|
283
|
-
);
|
|
284
|
-
};
|
|
285
237
|
/** Consecutive wedged writes on one device before the BLE manager itself is recreated. */
|
|
286
238
|
export const BLE_WRITE_TIMEOUT_MANAGER_RESET_THRESHOLD = 2;
|
|
287
239
|
const DEVICE_SCAN_TIMEOUT_MS = 3000;
|
|
@@ -624,14 +576,6 @@ export default class ReactNativeBleTransport {
|
|
|
624
576
|
/** Endpoints whose last detection got no answer; 'woken' once their Initialize wake is spent. */
|
|
625
577
|
private silentDetections = new Map<string, 'silent' | 'woken'>();
|
|
626
578
|
|
|
627
|
-
/**
|
|
628
|
-
* iOS can report a reset Pro2 as a generic peripheral disconnect instead of
|
|
629
|
-
* CBErrorPeerRemovedPairingInformation. Keep that first probe failure across
|
|
630
|
-
* the automatic cold reconnect and require a second failed probe before
|
|
631
|
-
* classifying the OS bond as invalid.
|
|
632
|
-
*/
|
|
633
|
-
private iosProbeDisconnectEvidence = new Map<string, IosProbeDisconnectEvidence>();
|
|
634
|
-
|
|
635
579
|
/** Android endpoints whose cached GATT table is suspect; the next connect refreshes it. */
|
|
636
580
|
private androidGattCacheRefreshes = new Set<string>();
|
|
637
581
|
|
|
@@ -645,6 +589,9 @@ export default class ReactNativeBleTransport {
|
|
|
645
589
|
/** When the current Android link attempt began; bounds which key-missing signals apply. */
|
|
646
590
|
private androidLinkStartedAt: Map<string, number> = new Map();
|
|
647
591
|
|
|
592
|
+
/** iOS acquire attempts whose new link the peer ended; two in a row mean a stale bond. */
|
|
593
|
+
private iosPeerTermination = new IosPeerTerminationTracker();
|
|
594
|
+
|
|
648
595
|
/** Strict or previously confirmed V2 target while acquire installs notifications. */
|
|
649
596
|
private acquiringProtocolV2 = new Set<string>();
|
|
650
597
|
|
|
@@ -1169,7 +1116,7 @@ export default class ReactNativeBleTransport {
|
|
|
1169
1116
|
try {
|
|
1170
1117
|
return await this.acquireUnlocked(input);
|
|
1171
1118
|
} catch (error) {
|
|
1172
|
-
throw await this.resolveAndroidBondInvalid(uuid, error);
|
|
1119
|
+
throw this.resolveIosBondInvalid(input, await this.resolveAndroidBondInvalid(uuid, error));
|
|
1173
1120
|
}
|
|
1174
1121
|
});
|
|
1175
1122
|
}
|
|
@@ -1177,6 +1124,7 @@ export default class ReactNativeBleTransport {
|
|
|
1177
1124
|
private async acquireUnlocked(input: FirmwareInstallBleAcquireInput) {
|
|
1178
1125
|
if (this.stopped) throw ERRORS.TypedError(HardwareErrorCode.BleDeviceDisconnected);
|
|
1179
1126
|
const { uuid, forceCleanRunPromise, expectedProtocol, skipProtocolProbe } = input;
|
|
1127
|
+
this.iosPeerTermination.attemptStarted(uuid);
|
|
1180
1128
|
const shouldMapProtocolV2StaleBond = expectedProtocol
|
|
1181
1129
|
? expectedProtocol === 'V2'
|
|
1182
1130
|
: this.confirmedProtocolV2.has(uuid);
|
|
@@ -1549,6 +1497,7 @@ export default class ReactNativeBleTransport {
|
|
|
1549
1497
|
}
|
|
1550
1498
|
);
|
|
1551
1499
|
if (this.stopped) throw ERRORS.TypedError(HardwareErrorCode.BleDeviceDisconnected);
|
|
1500
|
+
this.iosPeerTermination.linkProven(uuid);
|
|
1552
1501
|
const currentTransport = transportCache[uuid];
|
|
1553
1502
|
if (!currentTransport) {
|
|
1554
1503
|
throw ERRORS.TypedError(HardwareErrorCode.TransportNotFound);
|
|
@@ -1581,6 +1530,7 @@ export default class ReactNativeBleTransport {
|
|
|
1581
1530
|
const subscription = characteristic.monitor((error, c) => {
|
|
1582
1531
|
const isCurrentMonitor = this.monitorTokens.get(uuid) === monitorToken;
|
|
1583
1532
|
if (error) {
|
|
1533
|
+
if (isCurrentMonitor) this.noteIosLinkError(uuid, 'notify', error);
|
|
1584
1534
|
Log?.debug(
|
|
1585
1535
|
`error monitor ${characteristic.uuid}, deviceId: ${characteristic.deviceID}: ${
|
|
1586
1536
|
error as unknown as string
|
|
@@ -1867,6 +1817,56 @@ export default class ReactNativeBleTransport {
|
|
|
1867
1817
|
});
|
|
1868
1818
|
}
|
|
1869
1819
|
|
|
1820
|
+
/**
|
|
1821
|
+
* iOS says why a link ended only on the operation it interrupted, so the native codes are read
|
|
1822
|
+
* and logged here. Codes only: the reason text is localized and cannot be matched or searched.
|
|
1823
|
+
*/
|
|
1824
|
+
private noteIosLinkError(uuid: string, stage: 'gatt-setup' | 'notify' | 'write', error: unknown) {
|
|
1825
|
+
if (Platform.OS !== 'ios') return;
|
|
1826
|
+
this.iosPeerTermination.note(uuid, error);
|
|
1827
|
+
// Writes and notifications also fail for reasons that say nothing about the link.
|
|
1828
|
+
if (stage !== 'gatt-setup' && !isNativeBleDisconnectError(error)) return;
|
|
1829
|
+
const native = (error ?? {}) as {
|
|
1830
|
+
errorCode?: unknown;
|
|
1831
|
+
iosErrorCode?: unknown;
|
|
1832
|
+
attErrorCode?: unknown;
|
|
1833
|
+
};
|
|
1834
|
+
const code = (value: unknown) =>
|
|
1835
|
+
typeof value === 'number' || typeof value === 'string' ? value : undefined;
|
|
1836
|
+
Log?.debug('[ReactNativeBleTransport] iOS operation failed', {
|
|
1837
|
+
connectIdSuffix: uuid.slice(-8),
|
|
1838
|
+
stage,
|
|
1839
|
+
errorCode: code(native.errorCode),
|
|
1840
|
+
iosErrorCode: code(native.iosErrorCode),
|
|
1841
|
+
attErrorCode: code(native.attErrorCode),
|
|
1842
|
+
});
|
|
1843
|
+
}
|
|
1844
|
+
|
|
1845
|
+
/**
|
|
1846
|
+
* iPhones that do not report a lost bond only show the device ending each new link. One such
|
|
1847
|
+
* attempt keeps its error so Core retries; the second in a row is the stale bond.
|
|
1848
|
+
*/
|
|
1849
|
+
private resolveIosBondInvalid(input: FirmwareInstallBleAcquireInput, error: unknown): unknown {
|
|
1850
|
+
if (Platform.OS !== 'ios') return error;
|
|
1851
|
+
const { uuid, skipProtocolProbe } = input;
|
|
1852
|
+
// A firmware-install reconnect expects the device to come and go.
|
|
1853
|
+
if (skipProtocolProbe || isBleStaleBondHardwareError(error)) {
|
|
1854
|
+
this.iosPeerTermination.forget(uuid);
|
|
1855
|
+
return error;
|
|
1856
|
+
}
|
|
1857
|
+
if (!this.iosPeerTermination.attemptFailed(uuid)) return error;
|
|
1858
|
+
Log?.debug(
|
|
1859
|
+
'[ReactNativeBleTransport] iOS peer ended two new links in a row, bond is invalid:',
|
|
1860
|
+
{
|
|
1861
|
+
connectIdSuffix: uuid.slice(-8),
|
|
1862
|
+
}
|
|
1863
|
+
);
|
|
1864
|
+
return ERRORS.TypedError(HardwareErrorCode.BleBondInvalid, undefined, {
|
|
1865
|
+
phase: 'connect',
|
|
1866
|
+
reason: 'peer_disconnected',
|
|
1867
|
+
});
|
|
1868
|
+
}
|
|
1869
|
+
|
|
1870
1870
|
/**
|
|
1871
1871
|
* Android 16+ encrypts a bonded link on its own right after connecting. Subscribing to
|
|
1872
1872
|
* notifications before that finishes gets the CCCD write rejected, and the framework's retry
|
|
@@ -2166,9 +2166,9 @@ export default class ReactNativeBleTransport {
|
|
|
2166
2166
|
this.androidPriorityResetTimers.clear();
|
|
2167
2167
|
this.androidHighPriorityDevices.clear();
|
|
2168
2168
|
this.androidLinkStartedAt.clear();
|
|
2169
|
+
this.iosPeerTermination.reset();
|
|
2169
2170
|
stopBleKeyMissingTracking();
|
|
2170
2171
|
stopBleEncryptionTracking();
|
|
2171
|
-
this.iosProbeDisconnectEvidence.clear();
|
|
2172
2172
|
const error = ERRORS.TypedError(HardwareErrorCode.BleDeviceDisconnected);
|
|
2173
2173
|
this.runPromise?.reject(error);
|
|
2174
2174
|
this.runPromise = null;
|
|
@@ -2484,6 +2484,7 @@ export default class ReactNativeBleTransport {
|
|
|
2484
2484
|
}),
|
|
2485
2485
|
]);
|
|
2486
2486
|
succeeded = true;
|
|
2487
|
+
this.iosPeerTermination.linkStarted(uuid);
|
|
2487
2488
|
return result;
|
|
2488
2489
|
} catch (error) {
|
|
2489
2490
|
if (timedOut || isNativeOperationTimeoutError(error)) {
|
|
@@ -2537,6 +2538,11 @@ export default class ReactNativeBleTransport {
|
|
|
2537
2538
|
succeeded = true;
|
|
2538
2539
|
return result;
|
|
2539
2540
|
} catch (error) {
|
|
2541
|
+
this.noteIosLinkError(uuid, 'gatt-setup', error);
|
|
2542
|
+
if (Platform.OS === 'ios' && isNativeBleStaleBondError(error)) {
|
|
2543
|
+
// iOS can report the lost bond on the first request instead of on the connect.
|
|
2544
|
+
throw toBleStaleBondHardwareError(error);
|
|
2545
|
+
}
|
|
2540
2546
|
if (timedOut || isNativeOperationTimeoutError(error)) {
|
|
2541
2547
|
const resetManager = this.abandonStalledConnection(
|
|
2542
2548
|
uuid,
|
|
@@ -2654,6 +2660,7 @@ export default class ReactNativeBleTransport {
|
|
|
2654
2660
|
]);
|
|
2655
2661
|
this.writeTimeoutCounts.delete(uuid);
|
|
2656
2662
|
} catch (error) {
|
|
2663
|
+
this.noteIosLinkError(uuid, 'write', error);
|
|
2657
2664
|
if (timedOut) {
|
|
2658
2665
|
// A superseded call's late write must not tear down the link the current
|
|
2659
2666
|
// call is using; only the owner of the transport may declare it dead.
|
|
@@ -2788,64 +2795,6 @@ export default class ReactNativeBleTransport {
|
|
|
2788
2795
|
);
|
|
2789
2796
|
}
|
|
2790
2797
|
|
|
2791
|
-
private rememberIosProbeDisconnect(
|
|
2792
|
-
uuid: string,
|
|
2793
|
-
phase: IosProbeDisconnectEvidence['phase'],
|
|
2794
|
-
error: unknown
|
|
2795
|
-
): Error | undefined {
|
|
2796
|
-
if (!isIosProbeDisconnectError(error)) return undefined;
|
|
2797
|
-
|
|
2798
|
-
const previous = this.getIosProbeDisconnectEvidence(uuid);
|
|
2799
|
-
const errorCode = (error as { errorCode?: unknown })?.errorCode;
|
|
2800
|
-
const evidence: IosProbeDisconnectEvidence = {
|
|
2801
|
-
phase,
|
|
2802
|
-
...(typeof errorCode === 'string' || typeof errorCode === 'number' ? { errorCode } : {}),
|
|
2803
|
-
recordedAt: Date.now(),
|
|
2804
|
-
};
|
|
2805
|
-
this.iosProbeDisconnectEvidence.set(uuid, evidence);
|
|
2806
|
-
Log?.debug('[ReactNativeBleTransport][BleBondDiagnostic] probe disconnect recorded', {
|
|
2807
|
-
phase,
|
|
2808
|
-
errorCode: evidence.errorCode,
|
|
2809
|
-
repeated: Boolean(previous),
|
|
2810
|
-
});
|
|
2811
|
-
|
|
2812
|
-
if (!previous) return undefined;
|
|
2813
|
-
return this.confirmIosProbeDisconnect(uuid, 'repeated-probe-disconnect');
|
|
2814
|
-
}
|
|
2815
|
-
|
|
2816
|
-
private getIosProbeDisconnectEvidence(uuid: string): IosProbeDisconnectEvidence | undefined {
|
|
2817
|
-
const evidence = this.iosProbeDisconnectEvidence.get(uuid);
|
|
2818
|
-
if (!evidence) return undefined;
|
|
2819
|
-
|
|
2820
|
-
const ageMs = Date.now() - evidence.recordedAt;
|
|
2821
|
-
if (ageMs <= IOS_PROBE_DISCONNECT_EVIDENCE_TTL_MS) return evidence;
|
|
2822
|
-
|
|
2823
|
-
this.iosProbeDisconnectEvidence.delete(uuid);
|
|
2824
|
-
Log?.debug('[ReactNativeBleTransport][BleBondDiagnostic] probe disconnect expired', {
|
|
2825
|
-
triggerPhase: evidence.phase,
|
|
2826
|
-
triggerErrorCode: evidence.errorCode,
|
|
2827
|
-
ageMs,
|
|
2828
|
-
});
|
|
2829
|
-
return undefined;
|
|
2830
|
-
}
|
|
2831
|
-
|
|
2832
|
-
private confirmIosProbeDisconnect(
|
|
2833
|
-
uuid: string,
|
|
2834
|
-
confirmation: 'repeated-probe-disconnect' | 'follow-up-no-response'
|
|
2835
|
-
): Error | undefined {
|
|
2836
|
-
const evidence = this.getIosProbeDisconnectEvidence(uuid);
|
|
2837
|
-
if (!evidence) return undefined;
|
|
2838
|
-
|
|
2839
|
-
Log?.debug('[ReactNativeBleTransport][BleBondDiagnostic] stale bond confirmed', {
|
|
2840
|
-
confirmation,
|
|
2841
|
-
triggerPhase: evidence.phase,
|
|
2842
|
-
triggerErrorCode: evidence.errorCode,
|
|
2843
|
-
evidenceAgeMs: Date.now() - evidence.recordedAt,
|
|
2844
|
-
finalErrorCode: HardwareErrorCode.BleBondInvalid,
|
|
2845
|
-
});
|
|
2846
|
-
return ERRORS.TypedError(HardwareErrorCode.BleBondInvalid);
|
|
2847
|
-
}
|
|
2848
|
-
|
|
2849
2798
|
private clearProbeProtocol(uuid: string, protocol: ProtocolType) {
|
|
2850
2799
|
if (this.probingProtocols.get(uuid) === protocol) {
|
|
2851
2800
|
this.probingProtocols.delete(uuid);
|
|
@@ -2877,7 +2826,6 @@ export default class ReactNativeBleTransport {
|
|
|
2877
2826
|
// received no response. skipProtocolProbe does not need it either — its only
|
|
2878
2827
|
// caller is the V2 firmware-install reconnect.
|
|
2879
2828
|
if (expectedProtocol === 'V1') {
|
|
2880
|
-
this.iosProbeDisconnectEvidence.delete(uuid);
|
|
2881
2829
|
this.deviceProtocol.set(uuid, 'V1');
|
|
2882
2830
|
Log?.debug('[ReactNativeBleTransport] protocol selected', {
|
|
2883
2831
|
deviceId: uuid,
|
|
@@ -2893,7 +2841,6 @@ export default class ReactNativeBleTransport {
|
|
|
2893
2841
|
|
|
2894
2842
|
if (expectedProtocol === 'V2') {
|
|
2895
2843
|
if (await this.probeProtocolV2(uuid)) {
|
|
2896
|
-
this.iosProbeDisconnectEvidence.delete(uuid);
|
|
2897
2844
|
this.deviceProtocol.set(uuid, 'V2');
|
|
2898
2845
|
this.sessionProtocols.set(uuid, 'V2');
|
|
2899
2846
|
this.confirmedProtocolV2.add(uuid);
|
|
@@ -2904,18 +2851,6 @@ export default class ReactNativeBleTransport {
|
|
|
2904
2851
|
});
|
|
2905
2852
|
return 'V2';
|
|
2906
2853
|
}
|
|
2907
|
-
const staleBondError = this.confirmIosProbeDisconnect(uuid, 'follow-up-no-response');
|
|
2908
|
-
if (Platform.OS === 'ios') {
|
|
2909
|
-
Log?.debug('[ReactNativeBleTransport][BleBondDiagnostic] protocol detection ended', {
|
|
2910
|
-
outcome: 'expected-v2-no-response',
|
|
2911
|
-
expectedProtocol,
|
|
2912
|
-
protocolHint: protocolHint ?? 'none',
|
|
2913
|
-
finalErrorCode: staleBondError
|
|
2914
|
-
? HardwareErrorCode.BleBondInvalid
|
|
2915
|
-
: HardwareErrorCode.RuntimeError,
|
|
2916
|
-
});
|
|
2917
|
-
}
|
|
2918
|
-
if (staleBondError) throw staleBondError;
|
|
2919
2854
|
throw this.createProtocolMismatchError(expectedProtocol);
|
|
2920
2855
|
}
|
|
2921
2856
|
|
|
@@ -2951,7 +2886,6 @@ export default class ReactNativeBleTransport {
|
|
|
2951
2886
|
const detected =
|
|
2952
2887
|
protocol === 'V1' ? await this.probeProtocolV1(uuid) : await this.probeProtocolV2(uuid);
|
|
2953
2888
|
if (detected) {
|
|
2954
|
-
this.iosProbeDisconnectEvidence.delete(uuid);
|
|
2955
2889
|
this.deviceProtocol.set(uuid, protocol);
|
|
2956
2890
|
this.sessionProtocols.set(uuid, protocol);
|
|
2957
2891
|
if (protocol === 'V2') {
|
|
@@ -2981,25 +2915,6 @@ export default class ReactNativeBleTransport {
|
|
|
2981
2915
|
|
|
2982
2916
|
this.deviceProtocol.delete(uuid);
|
|
2983
2917
|
this.probingProtocols.delete(uuid);
|
|
2984
|
-
const staleBondError = this.confirmIosProbeDisconnect(uuid, 'follow-up-no-response');
|
|
2985
|
-
if (Platform.OS === 'ios') {
|
|
2986
|
-
Log?.debug('[ReactNativeBleTransport][BleBondDiagnostic] protocol detection ended', {
|
|
2987
|
-
outcome: 'all-probes-no-response',
|
|
2988
|
-
expectedProtocol: expectedProtocol ?? 'none',
|
|
2989
|
-
protocolHint: protocolHint ?? 'none',
|
|
2990
|
-
sessionProtocol: sessionProtocol ?? 'none',
|
|
2991
|
-
probeOrder: probeOrder.join(','),
|
|
2992
|
-
trustSessionProtocol,
|
|
2993
|
-
reprobeFailures,
|
|
2994
|
-
transportCached: Boolean(transportCache[uuid]),
|
|
2995
|
-
notifyActive: Boolean(transportCache[uuid]?.notifySubscription),
|
|
2996
|
-
staleBondRecorded: this.iosProbeDisconnectEvidence.has(uuid),
|
|
2997
|
-
finalErrorCode: staleBondError
|
|
2998
|
-
? HardwareErrorCode.BleBondInvalid
|
|
2999
|
-
: HardwareErrorCode.BleTimeoutError,
|
|
3000
|
-
});
|
|
3001
|
-
}
|
|
3002
|
-
if (staleBondError) throw staleBondError;
|
|
3003
2918
|
throw this.createProtocolDetectionError();
|
|
3004
2919
|
}
|
|
3005
2920
|
|
|
@@ -3098,19 +3013,7 @@ export default class ReactNativeBleTransport {
|
|
|
3098
3013
|
} catch (error) {
|
|
3099
3014
|
this.clearProbeProtocol(uuid, 'V1');
|
|
3100
3015
|
Log?.debug('[ReactNativeBleTransport] Protocol V1 GetFeatures probe failed:', error);
|
|
3101
|
-
|
|
3102
|
-
const staleBondError = this.rememberIosProbeDisconnect(
|
|
3103
|
-
uuid,
|
|
3104
|
-
'protocol-v1-get-features',
|
|
3105
|
-
error
|
|
3106
|
-
);
|
|
3107
|
-
logIosBleBondDiagnostic(
|
|
3108
|
-
'protocol-v1-get-features',
|
|
3109
|
-
error,
|
|
3110
|
-
shouldRethrow ? 'rethrow' : 'fallback'
|
|
3111
|
-
);
|
|
3112
|
-
if (staleBondError) throw staleBondError;
|
|
3113
|
-
if (shouldRethrow) {
|
|
3016
|
+
if (shouldRethrowProtocolProbeError(error)) {
|
|
3114
3017
|
throw error;
|
|
3115
3018
|
}
|
|
3116
3019
|
return false;
|
|
@@ -3125,26 +3028,18 @@ export default class ReactNativeBleTransport {
|
|
|
3125
3028
|
this.probingProtocols.set(uuid, 'V2');
|
|
3126
3029
|
this.protocolV2Assemblers.get(uuid)?.reset();
|
|
3127
3030
|
this.throwIfStaleBondError(uuid);
|
|
3128
|
-
|
|
3129
|
-
|
|
3130
|
-
|
|
3131
|
-
|
|
3132
|
-
|
|
3133
|
-
|
|
3134
|
-
|
|
3135
|
-
|
|
3136
|
-
|
|
3137
|
-
|
|
3138
|
-
|
|
3139
|
-
|
|
3140
|
-
shouldRethrow: shouldRethrowProtocolProbeError,
|
|
3141
|
-
});
|
|
3142
|
-
} catch (error) {
|
|
3143
|
-
const staleBondError = this.rememberIosProbeDisconnect(uuid, 'protocol-v2-ping', error);
|
|
3144
|
-
logIosBleBondDiagnostic('protocol-v2-ping', error, 'rethrow');
|
|
3145
|
-
if (staleBondError) throw staleBondError;
|
|
3146
|
-
throw error;
|
|
3147
|
-
}
|
|
3031
|
+
const detected = await probeProtocolV2Helper({
|
|
3032
|
+
call: (name: string, data: Record<string, unknown>, options?: TransportCallOptions) =>
|
|
3033
|
+
this.callProtocolV2(uuid, name, data, options),
|
|
3034
|
+
timeoutMs: PROTOCOL_V2_PROBE_TIMEOUT_MS,
|
|
3035
|
+
logger: Log,
|
|
3036
|
+
logPrefix: 'ProtocolV2 RN-BLE',
|
|
3037
|
+
onProbeFailed: () => {
|
|
3038
|
+
this.protocolV2Assemblers.get(uuid)?.reset();
|
|
3039
|
+
this.resetProtocolV2Frames(uuid);
|
|
3040
|
+
},
|
|
3041
|
+
shouldRethrow: shouldRethrowProtocolProbeError,
|
|
3042
|
+
});
|
|
3148
3043
|
if (!detected) {
|
|
3149
3044
|
this.clearProbeProtocol(uuid, 'V2');
|
|
3150
3045
|
} else {
|