@onekeyfe/hd-transport-react-native 1.2.0-alpha.143 → 1.2.0-alpha.145
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/index.d.ts +4 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +24 -14
- package/package.json +5 -5
- package/src/__tests__/protocolV2Link.test.ts +41 -4
- package/src/index.ts +32 -19
package/dist/index.d.ts
CHANGED
|
@@ -121,6 +121,10 @@ declare class ReactNativeBleTransport {
|
|
|
121
121
|
private deviceProtocolHints;
|
|
122
122
|
/** Protocol this device actually answered on, kept across reconnects of one session. */
|
|
123
123
|
private sessionProtocols;
|
|
124
|
+
/** Endpoints that answered a V2 probe in this transport lifetime. Survives disconnect. */
|
|
125
|
+
private confirmedProtocolV2;
|
|
126
|
+
/** First expected-V2 miss for an unconfirmed endpoint; the next miss is a stale bond. */
|
|
127
|
+
private retryableV2Mismatch;
|
|
124
128
|
/** Consecutive detections that failed while trusting sessionProtocols. */
|
|
125
129
|
private protocolReprobeFailures;
|
|
126
130
|
private protocolV2Assemblers;
|
package/dist/index.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":";AAEA,OAAO,EAIL,UAAU,IAAI,aAAa,EAG5B,MAAM,sBAAsB,CAAC;AAE9B,OAAO,SAAS,EAAE,EAChB,KAAK,oBAAoB,EAIzB,KAAK,YAAY,EAKjB,KAAK,oBAAoB,EAI1B,MAAM,wBAAwB,CAAC;AA0BhC,OAAO,YAAY,MAAM,gBAAgB,CAAC;AAI1C,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,qBAAqB,CAAC;AACpD,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,EAAE,YAAY,EAAE,MAAM,sBAAsB,CAAC;AACjF,OAAO,KAAK,YAAY,MAAM,QAAQ,CAAC;AACvC,OAAO,KAAK,EAAE,eAAe,EAAE,gBAAgB,EAAE,MAAM,SAAS,CAAC;AAgBjE,KAAK,4BAA4B,GAAG,WAAW,CAAC;AAChD,KAAK,0BAA0B,GAAG;IAChC,mBAAmB,EAAE,cAAc,CAAC;IACpC,oBAAoB,EAAE,cAAc,CAAC;CACtC,CAAC;AAkCF,eAAO,MAAM,+BAA+B,UACnC,OAAO,KACb,4BAA4B,GAAG,IAsBjC,CAAC;AAcF,eAAO,MAAM,2BAA2B,QAAS,CAAC;AAClD,eAAO,MAAM,8BAA8B,OAAQ,CAAC;AAOpD,eAAO,MAAM,yCAAyC,IAAI,CAAC;AAI3D,MAAM,MAAM,mBAAmB,GAAG;IAChC,eAAe,CAAC,EAAE,MAAM,CAAC;IACzB,mBAAmB,CAAC,EAAE,MAAM,CAAC;CAC9B,CAAC;AAiBF,wBAAgB,4BAA4B,CAAC,MAAM,GAAE,mBAAwB,QAY5E;AAED,wBAAgB,wBAAwB,SAGvC;AAED,wBAAgB,sBAAsB;;;EAErC;
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"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"}
|
package/dist/index.js
CHANGED
|
@@ -311,9 +311,6 @@ function resetProtocolV2BleTuning() {
|
|
|
311
311
|
function getProtocolV2BleTuning() {
|
|
312
312
|
return Object.assign({}, protocolV2BleTuning);
|
|
313
313
|
}
|
|
314
|
-
function inferProtocolHintFromDeviceName(name) {
|
|
315
|
-
return /\bpro\s*2\b/i.test(name !== null && name !== void 0 ? name : '') ? 'V2' : undefined;
|
|
316
|
-
}
|
|
317
314
|
function getDeviceDisplayName(device) {
|
|
318
315
|
return (device === null || device === void 0 ? void 0 : device.name) || (device === null || device === void 0 ? void 0 : device.localName) || null;
|
|
319
316
|
}
|
|
@@ -404,6 +401,8 @@ class ReactNativeBleTransport {
|
|
|
404
401
|
this.connectionSetupTimeoutCounts = new Map();
|
|
405
402
|
this.deviceProtocolHints = new Map();
|
|
406
403
|
this.sessionProtocols = new Map();
|
|
404
|
+
this.confirmedProtocolV2 = new Set();
|
|
405
|
+
this.retryableV2Mismatch = new Set();
|
|
407
406
|
this.protocolReprobeFailures = new Map();
|
|
408
407
|
this.protocolV2Assemblers = new Map();
|
|
409
408
|
this.protocolV2FrameQueues = new Map();
|
|
@@ -721,16 +720,11 @@ class ReactNativeBleTransport {
|
|
|
721
720
|
var _a;
|
|
722
721
|
if (deviceList.every(d => d.id !== device.id)) {
|
|
723
722
|
const displayName = (_a = getDeviceDisplayName(device)) !== null && _a !== void 0 ? _a : 'Unknown BLE Device';
|
|
724
|
-
const protocolHint = inferProtocolHintFromDeviceName(displayName);
|
|
725
|
-
if (protocolHint) {
|
|
726
|
-
this.deviceProtocolHints.set(device.id, protocolHint);
|
|
727
|
-
}
|
|
728
723
|
deviceList.push(Object.assign(Object.assign({}, device), { name: displayName, commType: 'ble' }));
|
|
729
724
|
Log === null || Log === void 0 ? void 0 : Log.debug('[ReactNativeBleTransport] OneKey BLE device discovered', {
|
|
730
725
|
deviceId: device.id,
|
|
731
726
|
name: displayName,
|
|
732
727
|
serviceUUIDs: device.serviceUUIDs,
|
|
733
|
-
protocolHint,
|
|
734
728
|
});
|
|
735
729
|
}
|
|
736
730
|
};
|
|
@@ -802,7 +796,7 @@ class ReactNativeBleTransport {
|
|
|
802
796
|
});
|
|
803
797
|
}
|
|
804
798
|
acquireUnlocked(input) {
|
|
805
|
-
var _a
|
|
799
|
+
var _a;
|
|
806
800
|
return __awaiter(this, void 0, void 0, function* () {
|
|
807
801
|
const { uuid, forceCleanRunPromise, expectedProtocol } = input;
|
|
808
802
|
const cachedTransport = transportCache[uuid];
|
|
@@ -916,7 +910,7 @@ class ReactNativeBleTransport {
|
|
|
916
910
|
const { writeCharacteristic, notifyCharacteristic } = yield this.resolveCharacteristicsWithTimeout(uuid, acquiredDevice);
|
|
917
911
|
const protocolHint = expectedProtocol
|
|
918
912
|
? undefined
|
|
919
|
-
: (
|
|
913
|
+
: (_a = input.protocolHint) !== null && _a !== void 0 ? _a : this.deviceProtocolHints.get(uuid);
|
|
920
914
|
yield this.releaseUnlocked(uuid, true);
|
|
921
915
|
if (protocolHint) {
|
|
922
916
|
this.deviceProtocolHints.set(uuid, protocolHint);
|
|
@@ -1664,6 +1658,8 @@ class ReactNativeBleTransport {
|
|
|
1664
1658
|
this.deviceProtocol.clear();
|
|
1665
1659
|
this.probingProtocols.clear();
|
|
1666
1660
|
this.sessionProtocols.clear();
|
|
1661
|
+
this.confirmedProtocolV2.clear();
|
|
1662
|
+
this.retryableV2Mismatch.clear();
|
|
1667
1663
|
this.protocolReprobeFailures.clear();
|
|
1668
1664
|
this.writeTimeoutCounts.clear();
|
|
1669
1665
|
this.connectionSetupTimeoutCounts.clear();
|
|
@@ -1676,8 +1672,16 @@ class ReactNativeBleTransport {
|
|
|
1676
1672
|
Log === null || Log === void 0 ? void 0 : Log.debug('[ReactNativeBleTransport] BLE manager destroy failed (ignored):', error);
|
|
1677
1673
|
}
|
|
1678
1674
|
}
|
|
1679
|
-
createProtocolMismatchError(expected) {
|
|
1680
|
-
|
|
1675
|
+
createProtocolMismatchError(expected, uuid) {
|
|
1676
|
+
const isStaleV2Bond = expected === 'V2' &&
|
|
1677
|
+
(this.confirmedProtocolV2.has(uuid) || this.retryableV2Mismatch.has(uuid));
|
|
1678
|
+
if (expected === 'V2' && !isStaleV2Bond) {
|
|
1679
|
+
this.retryableV2Mismatch.add(uuid);
|
|
1680
|
+
}
|
|
1681
|
+
else if (isStaleV2Bond) {
|
|
1682
|
+
this.retryableV2Mismatch.delete(uuid);
|
|
1683
|
+
}
|
|
1684
|
+
return hdShared.ERRORS.TypedError(isStaleV2Bond ? hdShared.HardwareErrorCode.BleDeviceBondError : hdShared.HardwareErrorCode.RuntimeError, `Device protocol mismatch: expected ${expected}, but device did not respond to expected protocol`);
|
|
1681
1685
|
}
|
|
1682
1686
|
createProtocolDetectionError() {
|
|
1683
1687
|
return hdShared.ERRORS.TypedError(hdShared.HardwareErrorCode.BleTimeoutError, 'Unable to detect BLE protocol: device did not respond to Protocol V1 GetFeatures or Protocol V2 Ping');
|
|
@@ -1717,12 +1721,14 @@ class ReactNativeBleTransport {
|
|
|
1717
1721
|
});
|
|
1718
1722
|
return 'V1';
|
|
1719
1723
|
}
|
|
1720
|
-
throw this.createProtocolMismatchError(expectedProtocol);
|
|
1724
|
+
throw this.createProtocolMismatchError(expectedProtocol, uuid);
|
|
1721
1725
|
}
|
|
1722
1726
|
if (expectedProtocol === 'V2') {
|
|
1723
1727
|
if (yield this.probeProtocolV2(uuid)) {
|
|
1724
1728
|
this.deviceProtocol.set(uuid, 'V2');
|
|
1725
1729
|
this.sessionProtocols.set(uuid, 'V2');
|
|
1730
|
+
this.confirmedProtocolV2.add(uuid);
|
|
1731
|
+
this.retryableV2Mismatch.delete(uuid);
|
|
1726
1732
|
Log === null || Log === void 0 ? void 0 : Log.debug('[ReactNativeBleTransport] protocol detected', {
|
|
1727
1733
|
deviceId: uuid,
|
|
1728
1734
|
protocol: 'V2',
|
|
@@ -1730,7 +1736,7 @@ class ReactNativeBleTransport {
|
|
|
1730
1736
|
});
|
|
1731
1737
|
return 'V2';
|
|
1732
1738
|
}
|
|
1733
|
-
throw this.createProtocolMismatchError(expectedProtocol);
|
|
1739
|
+
throw this.createProtocolMismatchError(expectedProtocol, uuid);
|
|
1734
1740
|
}
|
|
1735
1741
|
const sessionProtocol = this.sessionProtocols.get(uuid);
|
|
1736
1742
|
const reprobeFailures = (_a = this.protocolReprobeFailures.get(uuid)) !== null && _a !== void 0 ? _a : 0;
|
|
@@ -1754,6 +1760,10 @@ class ReactNativeBleTransport {
|
|
|
1754
1760
|
if (detected) {
|
|
1755
1761
|
this.deviceProtocol.set(uuid, protocol);
|
|
1756
1762
|
this.sessionProtocols.set(uuid, protocol);
|
|
1763
|
+
if (protocol === 'V2') {
|
|
1764
|
+
this.confirmedProtocolV2.add(uuid);
|
|
1765
|
+
this.retryableV2Mismatch.delete(uuid);
|
|
1766
|
+
}
|
|
1757
1767
|
this.protocolReprobeFailures.delete(uuid);
|
|
1758
1768
|
Log === null || Log === void 0 ? void 0 : Log.debug('[ReactNativeBleTransport] protocol detected', {
|
|
1759
1769
|
deviceId: uuid,
|
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.145",
|
|
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.145",
|
|
24
|
+
"@onekeyfe/hd-shared": "1.2.0-alpha.145",
|
|
25
|
+
"@onekeyfe/hd-transport": "1.2.0-alpha.145",
|
|
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": "9a136f881865c15e603ef271ae820c2b5a991dcc"
|
|
30
30
|
}
|
|
@@ -405,7 +405,7 @@ describe('ReactNativeBleTransport Protocol V2 link lifecycle', () => {
|
|
|
405
405
|
await transport.release(uuid, true);
|
|
406
406
|
});
|
|
407
407
|
|
|
408
|
-
test('
|
|
408
|
+
test('detects Protocol V2 on iOS without using the BLE name as a protocol hint', async () => {
|
|
409
409
|
const { transport, uuid, device, sentSeqs, writeCharacteristic } = createHarness({
|
|
410
410
|
deviceName: 'Pro2 6E9E',
|
|
411
411
|
});
|
|
@@ -415,22 +415,41 @@ describe('ReactNativeBleTransport Protocol V2 link lifecycle', () => {
|
|
|
415
415
|
protocolType: 'V2',
|
|
416
416
|
});
|
|
417
417
|
expect(device.requestMTU).toHaveBeenCalledWith(247);
|
|
418
|
-
expect(writeCharacteristic.writeWithResponse).
|
|
418
|
+
expect(writeCharacteristic.writeWithResponse.mock.calls.length).toBeGreaterThan(1);
|
|
419
419
|
|
|
420
420
|
await expect(
|
|
421
421
|
transport.call(uuid, 'Ping', { message: 'first-core-command' })
|
|
422
422
|
).resolves.toBeDefined();
|
|
423
|
-
expect(sentSeqs).toEqual([1, 2]);
|
|
423
|
+
expect(sentSeqs.filter(seq => seq > 0)).toEqual([1, 2]);
|
|
424
424
|
await transport.release(uuid, true);
|
|
425
425
|
});
|
|
426
426
|
|
|
427
427
|
test.each(['ios', 'android'] as const)(
|
|
428
|
-
'
|
|
428
|
+
'keeps a first expected Protocol V2 probe miss retryable on %s',
|
|
429
429
|
async platform => {
|
|
430
430
|
setPlatformOS(platform);
|
|
431
431
|
const { transport, uuid, device } = createHarness();
|
|
432
432
|
jest.spyOn(transport as any, 'probeProtocolV2').mockResolvedValue(false);
|
|
433
433
|
|
|
434
|
+
await expect(transport.acquire({ uuid, expectedProtocol: 'V2' })).rejects.toMatchObject({
|
|
435
|
+
errorCode: HardwareErrorCode.RuntimeError,
|
|
436
|
+
});
|
|
437
|
+
|
|
438
|
+
expect(device.cancelConnection).not.toHaveBeenCalled();
|
|
439
|
+
expect(transport.getProtocolType(uuid)).toBeUndefined();
|
|
440
|
+
}
|
|
441
|
+
);
|
|
442
|
+
|
|
443
|
+
test.each(['ios', 'android'] as const)(
|
|
444
|
+
'reports a stale bond on %s after a second expected Protocol V2 probe miss',
|
|
445
|
+
async platform => {
|
|
446
|
+
setPlatformOS(platform);
|
|
447
|
+
const { transport, uuid, device } = createHarness();
|
|
448
|
+
jest.spyOn(transport as any, 'probeProtocolV2').mockResolvedValue(false);
|
|
449
|
+
|
|
450
|
+
await expect(transport.acquire({ uuid, expectedProtocol: 'V2' })).rejects.toMatchObject({
|
|
451
|
+
errorCode: HardwareErrorCode.RuntimeError,
|
|
452
|
+
});
|
|
434
453
|
await expect(transport.acquire({ uuid, expectedProtocol: 'V2' })).rejects.toMatchObject({
|
|
435
454
|
errorCode: HardwareErrorCode.BleDeviceBondError,
|
|
436
455
|
});
|
|
@@ -440,6 +459,24 @@ describe('ReactNativeBleTransport Protocol V2 link lifecycle', () => {
|
|
|
440
459
|
}
|
|
441
460
|
);
|
|
442
461
|
|
|
462
|
+
test.each(['ios', 'android'] as const)(
|
|
463
|
+
'reports a stale bond on %s when a previously confirmed Protocol V2 device stops responding',
|
|
464
|
+
async platform => {
|
|
465
|
+
setPlatformOS(platform);
|
|
466
|
+
const { transport, uuid, device } = createHarness();
|
|
467
|
+
await transport.acquire({ uuid, expectedProtocol: 'V2' });
|
|
468
|
+
await transport.release(uuid, true);
|
|
469
|
+
jest.spyOn(transport as any, 'probeProtocolV2').mockResolvedValue(false);
|
|
470
|
+
|
|
471
|
+
await expect(transport.acquire({ uuid, expectedProtocol: 'V2' })).rejects.toMatchObject({
|
|
472
|
+
errorCode: HardwareErrorCode.BleDeviceBondError,
|
|
473
|
+
});
|
|
474
|
+
|
|
475
|
+
expect(device.cancelConnection).toHaveBeenCalled();
|
|
476
|
+
expect(transport.getProtocolType(uuid)).toBeUndefined();
|
|
477
|
+
}
|
|
478
|
+
);
|
|
479
|
+
|
|
443
480
|
test('waits for an in-flight release before reacquiring the same device', async () => {
|
|
444
481
|
const { transport, uuid } = createHarness();
|
|
445
482
|
await transport.acquire({ uuid, expectedProtocol: 'V2' });
|
package/src/index.ts
CHANGED
|
@@ -203,10 +203,6 @@ export function getProtocolV2BleTuning() {
|
|
|
203
203
|
return { ...protocolV2BleTuning };
|
|
204
204
|
}
|
|
205
205
|
|
|
206
|
-
function inferProtocolHintFromDeviceName(name?: string | null): ProtocolType | undefined {
|
|
207
|
-
return /\bpro\s*2\b/i.test(name ?? '') ? 'V2' : undefined;
|
|
208
|
-
}
|
|
209
|
-
|
|
210
206
|
function getDeviceDisplayName(device?: Device | null) {
|
|
211
207
|
return device?.name || device?.localName || null;
|
|
212
208
|
}
|
|
@@ -381,6 +377,12 @@ export default class ReactNativeBleTransport {
|
|
|
381
377
|
/** Protocol this device actually answered on, kept across reconnects of one session. */
|
|
382
378
|
private sessionProtocols: Map<string, ProtocolType> = new Map();
|
|
383
379
|
|
|
380
|
+
/** Endpoints that answered a V2 probe in this transport lifetime. Survives disconnect. */
|
|
381
|
+
private confirmedProtocolV2 = new Set<string>();
|
|
382
|
+
|
|
383
|
+
/** First expected-V2 miss for an unconfirmed endpoint; the next miss is a stale bond. */
|
|
384
|
+
private retryableV2Mismatch = new Set<string>();
|
|
385
|
+
|
|
384
386
|
/** Consecutive detections that failed while trusting sessionProtocols. */
|
|
385
387
|
private protocolReprobeFailures: Map<string, number> = new Map();
|
|
386
388
|
|
|
@@ -765,10 +767,7 @@ export default class ReactNativeBleTransport {
|
|
|
765
767
|
const addDevice = (device: Device) => {
|
|
766
768
|
if (deviceList.every(d => d.id !== device.id)) {
|
|
767
769
|
const displayName = getDeviceDisplayName(device) ?? 'Unknown BLE Device';
|
|
768
|
-
|
|
769
|
-
if (protocolHint) {
|
|
770
|
-
this.deviceProtocolHints.set(device.id, protocolHint);
|
|
771
|
-
}
|
|
770
|
+
|
|
772
771
|
deviceList.push({
|
|
773
772
|
...device,
|
|
774
773
|
name: displayName,
|
|
@@ -778,7 +777,6 @@ export default class ReactNativeBleTransport {
|
|
|
778
777
|
deviceId: device.id,
|
|
779
778
|
name: displayName,
|
|
780
779
|
serviceUUIDs: device.serviceUUIDs,
|
|
781
|
-
protocolHint,
|
|
782
780
|
});
|
|
783
781
|
}
|
|
784
782
|
};
|
|
@@ -1015,9 +1013,7 @@ export default class ReactNativeBleTransport {
|
|
|
1015
1013
|
|
|
1016
1014
|
const protocolHint = expectedProtocol
|
|
1017
1015
|
? undefined
|
|
1018
|
-
: input.protocolHint ??
|
|
1019
|
-
this.deviceProtocolHints.get(uuid) ??
|
|
1020
|
-
inferProtocolHintFromDeviceName(getDeviceDisplayName(acquiredDevice));
|
|
1016
|
+
: input.protocolHint ?? this.deviceProtocolHints.get(uuid);
|
|
1021
1017
|
|
|
1022
1018
|
// release transport before new transport instance
|
|
1023
1019
|
await this.releaseUnlocked(uuid, true);
|
|
@@ -1248,7 +1244,7 @@ export default class ReactNativeBleTransport {
|
|
|
1248
1244
|
|
|
1249
1245
|
this.deviceProtocol.delete(uuid);
|
|
1250
1246
|
this.probingProtocols.delete(uuid);
|
|
1251
|
-
//
|
|
1247
|
+
// Confirmed protocol and caller hints stay in deviceProtocol / protocolHint.
|
|
1252
1248
|
this.protocolV2Assemblers.get(uuid)?.reset();
|
|
1253
1249
|
this.protocolV2Assemblers.delete(uuid);
|
|
1254
1250
|
this.resetProtocolV2Frames(uuid);
|
|
@@ -1969,6 +1965,8 @@ export default class ReactNativeBleTransport {
|
|
|
1969
1965
|
this.deviceProtocol.clear();
|
|
1970
1966
|
this.probingProtocols.clear();
|
|
1971
1967
|
this.sessionProtocols.clear();
|
|
1968
|
+
this.confirmedProtocolV2.clear();
|
|
1969
|
+
this.retryableV2Mismatch.clear();
|
|
1972
1970
|
this.protocolReprobeFailures.clear();
|
|
1973
1971
|
this.writeTimeoutCounts.clear();
|
|
1974
1972
|
this.connectionSetupTimeoutCounts.clear();
|
|
@@ -1981,11 +1979,20 @@ export default class ReactNativeBleTransport {
|
|
|
1981
1979
|
}
|
|
1982
1980
|
}
|
|
1983
1981
|
|
|
1984
|
-
private createProtocolMismatchError(expected: ProtocolType) {
|
|
1985
|
-
//
|
|
1986
|
-
//
|
|
1982
|
+
private createProtocolMismatchError(expected: ProtocolType, uuid: string) {
|
|
1983
|
+
// Caller `expectedProtocol: 'V2'` is not proof this endpoint already answered.
|
|
1984
|
+
// A first-connect or flaky Ping must stay retryable. A later miss after a
|
|
1985
|
+
// confirmed V2 answer, or a second miss on the same uuid, is a stale bond.
|
|
1986
|
+
const isStaleV2Bond =
|
|
1987
|
+
expected === 'V2' &&
|
|
1988
|
+
(this.confirmedProtocolV2.has(uuid) || this.retryableV2Mismatch.has(uuid));
|
|
1989
|
+
if (expected === 'V2' && !isStaleV2Bond) {
|
|
1990
|
+
this.retryableV2Mismatch.add(uuid);
|
|
1991
|
+
} else if (isStaleV2Bond) {
|
|
1992
|
+
this.retryableV2Mismatch.delete(uuid);
|
|
1993
|
+
}
|
|
1987
1994
|
return ERRORS.TypedError(
|
|
1988
|
-
|
|
1995
|
+
isStaleV2Bond ? HardwareErrorCode.BleDeviceBondError : HardwareErrorCode.RuntimeError,
|
|
1989
1996
|
`Device protocol mismatch: expected ${expected}, but device did not respond to expected protocol`
|
|
1990
1997
|
);
|
|
1991
1998
|
}
|
|
@@ -2041,13 +2048,15 @@ export default class ReactNativeBleTransport {
|
|
|
2041
2048
|
});
|
|
2042
2049
|
return 'V1';
|
|
2043
2050
|
}
|
|
2044
|
-
throw this.createProtocolMismatchError(expectedProtocol);
|
|
2051
|
+
throw this.createProtocolMismatchError(expectedProtocol, uuid);
|
|
2045
2052
|
}
|
|
2046
2053
|
|
|
2047
2054
|
if (expectedProtocol === 'V2') {
|
|
2048
2055
|
if (await this.probeProtocolV2(uuid)) {
|
|
2049
2056
|
this.deviceProtocol.set(uuid, 'V2');
|
|
2050
2057
|
this.sessionProtocols.set(uuid, 'V2');
|
|
2058
|
+
this.confirmedProtocolV2.add(uuid);
|
|
2059
|
+
this.retryableV2Mismatch.delete(uuid);
|
|
2051
2060
|
Log?.debug('[ReactNativeBleTransport] protocol detected', {
|
|
2052
2061
|
deviceId: uuid,
|
|
2053
2062
|
protocol: 'V2',
|
|
@@ -2055,7 +2064,7 @@ export default class ReactNativeBleTransport {
|
|
|
2055
2064
|
});
|
|
2056
2065
|
return 'V2';
|
|
2057
2066
|
}
|
|
2058
|
-
throw this.createProtocolMismatchError(expectedProtocol);
|
|
2067
|
+
throw this.createProtocolMismatchError(expectedProtocol, uuid);
|
|
2059
2068
|
}
|
|
2060
2069
|
|
|
2061
2070
|
// Protocol must be actively probed after connection. Name, PID, and descriptors only
|
|
@@ -2090,6 +2099,10 @@ export default class ReactNativeBleTransport {
|
|
|
2090
2099
|
if (detected) {
|
|
2091
2100
|
this.deviceProtocol.set(uuid, protocol);
|
|
2092
2101
|
this.sessionProtocols.set(uuid, protocol);
|
|
2102
|
+
if (protocol === 'V2') {
|
|
2103
|
+
this.confirmedProtocolV2.add(uuid);
|
|
2104
|
+
this.retryableV2Mismatch.delete(uuid);
|
|
2105
|
+
}
|
|
2093
2106
|
this.protocolReprobeFailures.delete(uuid);
|
|
2094
2107
|
Log?.debug('[ReactNativeBleTransport] protocol detected', {
|
|
2095
2108
|
deviceId: uuid,
|