@onekeyfe/hd-transport-react-native 1.2.2-alpha.120 → 1.2.2-alpha.122
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 +29 -1
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +265 -59
- package/package.json +5 -5
- package/src/__tests__/connectTimeout.test.ts +85 -1
- package/src/__tests__/protocolV2Link.test.ts +600 -25
- package/src/index.ts +366 -67
package/dist/index.d.ts
CHANGED
|
@@ -74,6 +74,16 @@ declare function getProtocolV2BleTuning(): {
|
|
|
74
74
|
iosPacketLength: number;
|
|
75
75
|
androidPacketLength: number;
|
|
76
76
|
};
|
|
77
|
+
/**
|
|
78
|
+
* With no cached GATT table the stack runs its own discovery (up to ~8s) before the MTU
|
|
79
|
+
* exchange, so the bound sits above that; a stuck exchange never completes.
|
|
80
|
+
*/
|
|
81
|
+
declare const ANDROID_MTU_EXCHANGE_TIMEOUT_MS = 12000;
|
|
82
|
+
/**
|
|
83
|
+
* Android keeps an LE link, with per-link ATT state such as a pending MTU exchange, for its
|
|
84
|
+
* 4s GATT link idle timer after the last client closes; a reconnect inside it reuses the link.
|
|
85
|
+
*/
|
|
86
|
+
declare const ANDROID_LINK_DROP_QUIET_MS = 5000;
|
|
77
87
|
/**
|
|
78
88
|
* JS backstop for connect. The native adapter applies its own 3s budget, but it
|
|
79
89
|
* schedules that timeout on its serial queue, so a busy queue (e.g. right after a
|
|
@@ -135,6 +145,10 @@ declare class ReactNativeBleTransport {
|
|
|
135
145
|
private confirmedProtocolV2;
|
|
136
146
|
/** Consecutive detections that failed while trusting sessionProtocols. */
|
|
137
147
|
private protocolReprobeFailures;
|
|
148
|
+
/** Endpoints whose last detection got no answer; 'woken' once their Initialize wake is spent. */
|
|
149
|
+
private silentDetections;
|
|
150
|
+
/** Android endpoints whose cached GATT table is suspect; the next connect refreshes it. */
|
|
151
|
+
private androidGattCacheRefreshes;
|
|
138
152
|
/**
|
|
139
153
|
* Native encryption/pairing failures seen before Protocol V2 probe starts.
|
|
140
154
|
* Pro2/Neo GATT connect can succeed on a stale iOS bond; the CCCD write then
|
|
@@ -194,6 +208,13 @@ declare class ReactNativeBleTransport {
|
|
|
194
208
|
private runBestEffortNativeOperation;
|
|
195
209
|
private runLifecycleOperation;
|
|
196
210
|
cancel(): Promise<void>;
|
|
211
|
+
/**
|
|
212
|
+
* Android: request the MTU with nothing queued ahead and never close the client while it is
|
|
213
|
+
* outstanding; a link that times out or stays at MTU 23 is dropped.
|
|
214
|
+
*/
|
|
215
|
+
private negotiateAndroidMtu;
|
|
216
|
+
/** Close the client and wait out the link idle timer so the next connect gets a fresh link. */
|
|
217
|
+
private dropAndroidLink;
|
|
197
218
|
/** Run a native connect under the JS backstop budget. */
|
|
198
219
|
private connectWithTimeout;
|
|
199
220
|
/** Resolve the complete GATT shape under a budget so acquire() always settles. */
|
|
@@ -228,6 +249,13 @@ declare class ReactNativeBleTransport {
|
|
|
228
249
|
/** Protocol to route a call with: confirmed if known, otherwise the one being probed. */
|
|
229
250
|
private getActiveProtocol;
|
|
230
251
|
private detectProtocol;
|
|
252
|
+
/**
|
|
253
|
+
* A sleeping Classic drops GetFeatures/Ping and only leaves its screensaver on Initialize, which
|
|
254
|
+
* resets the wallet session, so it is sent once after a fully silent detection. The firmware does
|
|
255
|
+
* not reliably answer it, so its timeout must not drop the link. It only runs when V1 is probed
|
|
256
|
+
* first, so a late reply lands on the V1 probe rather than on a V2 one.
|
|
257
|
+
*/
|
|
258
|
+
private wakeSilentProtocolV1Device;
|
|
231
259
|
private resetProbeStateAfterProtocolProbe;
|
|
232
260
|
private probeProtocolV1;
|
|
233
261
|
private probeProtocolV2;
|
|
@@ -251,4 +279,4 @@ declare class ReactNativeBleTransport {
|
|
|
251
279
|
getProtocolType(path: string): ProtocolType | undefined;
|
|
252
280
|
}
|
|
253
281
|
|
|
254
|
-
export { BLE_CONNECT_TIMEOUT_MANAGER_RESET_THRESHOLD, BLE_CONNECT_TIMEOUT_MS, BLE_GATT_SETUP_TIMEOUT_MS, BLE_NATIVE_TEARDOWN_TIMEOUT_MS, BLE_SETUP_WEDGED_MESSAGE, BLE_WRITE_PACKET_TIMEOUT_MS, BLE_WRITE_TIMEOUT_MANAGER_RESET_THRESHOLD, IOneKeyDevice, PROTOCOL_REPROBE_FALLBACK_ATTEMPTS, ProtocolV2BleTuning, configureProtocolV2BleTuning, ReactNativeBleTransport as default, getFirmwareUploadWriteRetryType, getProtocolV2BleTuning, resetProtocolV2BleTuning };
|
|
282
|
+
export { ANDROID_LINK_DROP_QUIET_MS, ANDROID_MTU_EXCHANGE_TIMEOUT_MS, BLE_CONNECT_TIMEOUT_MANAGER_RESET_THRESHOLD, BLE_CONNECT_TIMEOUT_MS, BLE_GATT_SETUP_TIMEOUT_MS, BLE_NATIVE_TEARDOWN_TIMEOUT_MS, BLE_SETUP_WEDGED_MESSAGE, BLE_WRITE_PACKET_TIMEOUT_MS, BLE_WRITE_TIMEOUT_MANAGER_RESET_THRESHOLD, IOneKeyDevice, PROTOCOL_REPROBE_FALLBACK_ATTEMPTS, 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,EAGL,UAAU,IAAI,aAAa,EAG5B,MAAM,sBAAsB,CAAC;AAE9B,OAAO,SAAS,EAAE,EAChB,KAAK,oBAAoB,EAIzB,KAAK,YAAY,EAKjB,KAAK,oBAAoB,EAI1B,MAAM,wBAAwB,CAAC;AAgChC,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;AAEjE,KAAK,8BAA8B,GAAG,eAAe,GAAG;IAMtD,iBAAiB,CAAC,EAAE,OAAO,CAAC;CAC7B,CAAC;AAkBF,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;AAwBpD,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":";AAEA,OAAO,EAGL,UAAU,IAAI,aAAa,EAG5B,MAAM,sBAAsB,CAAC;AAE9B,OAAO,SAAS,EAAE,EAChB,KAAK,oBAAoB,EAIzB,KAAK,YAAY,EAKjB,KAAK,oBAAoB,EAI1B,MAAM,wBAAwB,CAAC;AAgChC,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;AAEjE,KAAK,8BAA8B,GAAG,eAAe,GAAG;IAMtD,iBAAiB,CAAC,EAAE,OAAO,CAAC;CAC7B,CAAC;AAkBF,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;AAwBpD,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;AA0CD,eAAO,MAAM,+BAA+B,QAAS,CAAC;AAMtD,eAAO,MAAM,0BAA0B,OAAO,CAAC;AAsC/C,eAAO,MAAM,sBAAsB,QAA2C,CAAC;AAO/E,eAAO,MAAM,yBAAyB,QAAS,CAAC;AAQhD,eAAO,MAAM,kCAAkC,IAAI,CAAC;AAEpD,eAAO,MAAM,2CAA2C,IAAI,CAAC;AAE7D,eAAO,MAAM,wBAAwB,gCAAgC,CAAC;AAuBtE,MAAM,MAAM,aAAa,GAAG,oBAAoB,GAAG,MAAM,CAAC;AA8G1D,MAAM,CAAC,OAAO,OAAO,uBAAuB;IAC1C,aAAa,EAAE,aAAa,GAAG,SAAS,CAAC;IAEzC,SAAS,EAAE,UAAU,CAAC,OAAO,SAAS,CAAC,cAAc,CAAC,GAAG,SAAS,CAAC;IAEnE,WAAW,EAAE,UAAU,CAAC,OAAO,SAAS,CAAC,cAAc,CAAC,GAAG,SAAS,CAAC;IAErE,OAAO,CAAC,6BAA6B,CAAqB;IAE1D,IAAI,SAA6B;IAEjC,UAAU,UAAS;IAEnB,OAAO,UAAS;IAEhB,OAAO,CAAC,QAAQ,CAAC,mBAAmB,CAAyB;IAE7D,WAAW,SAA0B;IAErC,UAAU,EAAE,QAAQ,CAAC,GAAG,CAAC,GAAG,IAAI,CAAQ;IAExC,OAAO,CAAC,kBAAkB,CAAuB;IAEjD,OAAO,CAAC,EAAE,YAAY,CAAC;IAEvB,8BAA8B,cAAqB;IAGnD,OAAO,CAAC,cAAc,CAAwC;IAQ9D,OAAO,CAAC,gBAAgB,CAAwC;IAGhE,OAAO,CAAC,kBAAkB,CAAkC;IAG5D,OAAO,CAAC,4BAA4B,CAAkC;IAEtE,OAAO,CAAC,mBAAmB,CAAwC;IAGnE,OAAO,CAAC,gBAAgB,CAAwC;IAGhE,OAAO,CAAC,mBAAmB,CAAqB;IAGhD,OAAO,CAAC,uBAAuB,CAAkC;IAGjE,OAAO,CAAC,gBAAgB,CAAyC;IAGjE,OAAO,CAAC,yBAAyB,CAAqB;IAOtD,OAAO,CAAC,eAAe,CAAiC;IAGxD,OAAO,CAAC,mBAAmB,CAAqB;IAEhD,OAAO,CAAC,oBAAoB,CAAoD;IAEhF,OAAO,CAAC,qBAAqB,CAAwC;IAErE,OAAO,CAAC,uBAAuB,CAAgD;IAE/E,OAAO,CAAC,eAAe,CA2BpB;IAEH,OAAO,CAAC,aAAa,CAAkC;IAEvD,OAAO,CAAC,qBAAqB,CAAkC;IAE/D,OAAO,CAAC,iCAAiC,CAAuC;IAEhF,OAAO,CAAC,0BAA0B,CAA0B;IAE5D,OAAO,CAAC,0BAA0B,CAAyD;IAE3F,OAAO,CAAC,gBAAgB,CAAK;IAG7B,OAAO,CAAC,mBAAmB,CAAyC;IAEpE,OAAO,CAAC,WAAW,CAAC,CAAgB;IAEpC,OAAO,CAAC,YAAY,CAAkC;gBAE1C,OAAO,EAAE,gBAAgB;IAIrC,IAAI,CAAC,MAAM,EAAE,GAAG,EAAE,OAAO,EAAE,YAAY;IAKvC,SAAS,CAAC,UAAU,EAAE,GAAG;IAMzB,mBAAmB,CAAC,UAAU,EAAE,GAAG;IAgBnC,MAAM;IAIA,aAAa,IAAI,OAAO,CAAC,aAAa,CAAC;YAS/B,mBAAmB;IAqB3B,sBAAsB,CAAC,MAAM,EAAE,MAAM,GAAG,OAAO,CAAC,0BAA0B,CAAC;IAmFjF,4BAA4B,CAAC,SAAS,EAAE,YAAY,EAAE,MAAM,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM;IAgClF,OAAO,CAAC,oBAAoB;IAgBtB,gCAAgC,CAAC,IAAI,EAAE,MAAM,EAAE,SAAS,EAAE,YAAY;IAsDtE,SAAS;YA0JD,0BAA0B;IA+ClC,OAAO,CAAC,KAAK,EAAE,8BAA8B;;;;YAUrC,eAAe;IAsX7B,sBAAsB,CACpB,cAAc,EAAE,cAAc,EAC9B,IAAI,EAAE,MAAM,EACZ,YAAY,EAAE,MAAM,EACpB,mBAAmB,EAAE,MAAM,GAC1B,YAAY;IAmIT,OAAO,CAAC,IAAI,EAAE,MAAM,EAAE,OAAO,UAAQ;YAI7B,eAAe;YAKf,aAAa;IA8ErB,IAAI,CAAC,OAAO,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC;IAajE,IAAI,CACR,IAAI,EAAE,MAAM,EACZ,IAAI,EAAE,MAAM,EACZ,IAAI,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,EAC7B,OAAO,CAAC,EAAE,oBAAoB;YA6BlB,cAAc;IA0P5B,IAAI;IA8CE,UAAU,CAAC,OAAO,EAAE,MAAM;YAIlB,kBAAkB;YAmFlB,iBAAiB;IAkC/B,OAAO,CAAC,4BAA4B;YAQtB,qBAAqB;IAoB7B,MAAM;YAoBE,mBAAmB;YA4DnB,eAAe;YA6Bf,kBAAkB;YAkDlB,iCAAiC;IA2D/C,OAAO,CAAC,wBAAwB;IA0ChC,OAAO,CAAC,yBAAyB;IAMjC,OAAO,CAAC,kBAAkB;YAcZ,cAAc;IA8C5B,OAAO,CAAC,kBAAkB;IA+B1B,OAAO,CAAC,eAAe;IAkEvB,OAAO,CAAC,2BAA2B;IASnC,OAAO,CAAC,4BAA4B;IAOpC,OAAO,CAAC,kBAAkB;IAU1B,OAAO,CAAC,iBAAiB;YAIX,cAAc;YAmHd,0BAA0B;YAsB1B,iCAAiC;YAoDjC,eAAe;YAsBf,eAAe;IA4B7B,OAAO,CAAC,4BAA4B;IA2BpC,OAAO,CAAC,uBAAuB;IAS/B,OAAO,CAAC,sBAAsB;IAU9B,OAAO,CAAC,qBAAqB;IAI7B,OAAO,CAAC,sBAAsB;IAS9B,OAAO,CAAC,sBAAsB;IAQ9B,OAAO,CAAC,qBAAqB;YAOf,mBAAmB;YAiBnB,qBAAqB;YAmErB,oBAAoB;YAgCpB,cAAc;YAmFd,iCAAiC;IAsB/C,OAAO,CAAC,8BAA8B;YAQxB,mCAAmC;IAsBjD,OAAO,CAAC,yCAAyC;YAanC,gCAAgC;IAoB9C,OAAO,CAAC,uBAAuB;IAmD/B,eAAe,CAAC,IAAI,EAAE,MAAM,GAAG,YAAY,GAAG,SAAS;CAGxD"}
|
package/dist/index.js
CHANGED
|
@@ -420,10 +420,10 @@ function getDeviceDisplayName(device) {
|
|
|
420
420
|
}
|
|
421
421
|
const IOS_REQUEST_MTU = 247;
|
|
422
422
|
const ANDROID_REQUEST_MTU = 517;
|
|
423
|
-
const BLE_MTU_REFRESH_RETRY_DELAY_MS = 200;
|
|
424
423
|
const ANDROID_HIGH_PRIORITY_IDLE_MS = 1000;
|
|
425
424
|
const getRequestedBleMtu = () => reactNative.Platform.OS === 'android' ? ANDROID_REQUEST_MTU : IOS_REQUEST_MTU;
|
|
426
425
|
const BLE_NATIVE_CONNECT_TIMEOUT_MS = 3000;
|
|
426
|
+
const BLE_MTU_REQUEST_TIMEOUT_MS = BLE_NATIVE_CONNECT_TIMEOUT_MS;
|
|
427
427
|
const connectOptions = {
|
|
428
428
|
requestMTU: getRequestedBleMtu(),
|
|
429
429
|
timeout: BLE_NATIVE_CONNECT_TIMEOUT_MS,
|
|
@@ -432,6 +432,29 @@ const connectOptions = {
|
|
|
432
432
|
const fallbackConnectOptions = {
|
|
433
433
|
timeout: BLE_NATIVE_CONNECT_TIMEOUT_MS,
|
|
434
434
|
};
|
|
435
|
+
const androidRefreshGattConnectOptions = {
|
|
436
|
+
timeout: BLE_NATIVE_CONNECT_TIMEOUT_MS,
|
|
437
|
+
refreshGatt: 'OnConnected',
|
|
438
|
+
};
|
|
439
|
+
const ANDROID_MTU_EXCHANGE_TIMEOUT_MS = 12000;
|
|
440
|
+
const ANDROID_LINK_DROP_QUIET_MS = 5000;
|
|
441
|
+
const ANDROID_LINK_DROP_POLL_MS = 250;
|
|
442
|
+
const isKnownDefaultMtu = (mtu) => typeof mtu === 'number' && Number.isFinite(mtu) && mtu <= 23;
|
|
443
|
+
const isMissingGattShapeError = (error) => {
|
|
444
|
+
const code = error === null || error === void 0 ? void 0 : error.errorCode;
|
|
445
|
+
const message = error === null || error === void 0 ? void 0 : error.message;
|
|
446
|
+
return (code === hdShared.HardwareErrorCode.BleServiceNotFound ||
|
|
447
|
+
code === hdShared.HardwareErrorCode.BleCharacteristicNotFound ||
|
|
448
|
+
(typeof message === 'string' &&
|
|
449
|
+
(message.includes('BLECharacteristicNotFound') ||
|
|
450
|
+
message.includes('BLECharacteristicNotWritable') ||
|
|
451
|
+
message.includes('BLECharacteristicNotNotifiable'))));
|
|
452
|
+
};
|
|
453
|
+
const isStaleGattTableNotifyReason = (reason) => !!reason &&
|
|
454
|
+
(reason.includes('Cannot write client characteristic config descriptor') ||
|
|
455
|
+
reason.includes('Cannot find client characteristic config descriptor') ||
|
|
456
|
+
reason.includes('The handle is invalid') ||
|
|
457
|
+
reason.includes('Writing is not permitted'));
|
|
435
458
|
const BLE_CONNECT_TIMEOUT_MS = BLE_NATIVE_CONNECT_TIMEOUT_MS * 2 + 2000;
|
|
436
459
|
const BLE_GATT_SETUP_TIMEOUT_MS = 10000;
|
|
437
460
|
const PROTOCOL_REPROBE_FALLBACK_ATTEMPTS = 3;
|
|
@@ -446,6 +469,11 @@ const isWedgedBleSetupError = (error) => (error === null || error === void 0 ? v
|
|
|
446
469
|
error.message.startsWith(BLE_SETUP_WEDGED_MESSAGE);
|
|
447
470
|
const shouldRethrowBleSetupError = (error) => isConnectTimeoutError(error) || isWedgedBleSetupError(error);
|
|
448
471
|
const isNativeOperationTimeoutError = (error) => (error === null || error === void 0 ? void 0 : error.errorCode) === reactNativeBlePlx.BleErrorCode.OperationTimedOut;
|
|
472
|
+
const isMtuOrCancelledConnectError = (error) => {
|
|
473
|
+
const errorCode = error === null || error === void 0 ? void 0 : error.errorCode;
|
|
474
|
+
return (errorCode === reactNativeBlePlx.BleErrorCode.DeviceMTUChangeFailed ||
|
|
475
|
+
errorCode === reactNativeBlePlx.BleErrorCode.OperationCancelled);
|
|
476
|
+
};
|
|
449
477
|
const tryToGetConfiguration = (device) => {
|
|
450
478
|
if (!device || !device.serviceUUIDs)
|
|
451
479
|
return null;
|
|
@@ -457,25 +485,65 @@ const tryToGetConfiguration = (device) => {
|
|
|
457
485
|
return null;
|
|
458
486
|
return infos;
|
|
459
487
|
};
|
|
460
|
-
const requestNegotiatedMtu = (device, stage, attempt) => __awaiter(void 0, void 0, void 0, function* () {
|
|
488
|
+
const requestNegotiatedMtu = (device, stage, attempt, cancelTransaction) => __awaiter(void 0, void 0, void 0, function* () {
|
|
461
489
|
if (reactNative.Platform.OS !== 'ios' && reactNative.Platform.OS !== 'android')
|
|
462
|
-
return device;
|
|
490
|
+
return { device, timedOut: false };
|
|
491
|
+
const transactionId = `${device.id}:mtu:${stage}:${attempt}:${Date.now()}`;
|
|
492
|
+
let timeoutId;
|
|
493
|
+
let timedOut = false;
|
|
463
494
|
try {
|
|
464
|
-
const
|
|
465
|
-
|
|
495
|
+
const request = device.requestMTU(getRequestedBleMtu(), transactionId);
|
|
496
|
+
request.catch(() => undefined);
|
|
497
|
+
const mtuDevice = yield Promise.race([
|
|
498
|
+
request,
|
|
499
|
+
new Promise((_, reject) => {
|
|
500
|
+
timeoutId = setTimeout(() => {
|
|
501
|
+
timedOut = true;
|
|
502
|
+
reject(new Error(`BLE MTU request timeout after ${BLE_MTU_REQUEST_TIMEOUT_MS}ms`));
|
|
503
|
+
}, BLE_MTU_REQUEST_TIMEOUT_MS);
|
|
504
|
+
}),
|
|
505
|
+
]);
|
|
506
|
+
return { device: mtuDevice, timedOut: false };
|
|
466
507
|
}
|
|
467
508
|
catch (error) {
|
|
509
|
+
if (timedOut && cancelTransaction) {
|
|
510
|
+
try {
|
|
511
|
+
Promise.resolve(cancelTransaction(transactionId)).catch(cancelError => {
|
|
512
|
+
Log === null || Log === void 0 ? void 0 : Log.debug('[ReactNativeBleTransport] MTU cancellation failed', {
|
|
513
|
+
platform: reactNative.Platform.OS,
|
|
514
|
+
stage,
|
|
515
|
+
attempt,
|
|
516
|
+
error: cancelError instanceof Error ? cancelError.message : String(cancelError),
|
|
517
|
+
});
|
|
518
|
+
});
|
|
519
|
+
}
|
|
520
|
+
catch (cancelError) {
|
|
521
|
+
Log === null || Log === void 0 ? void 0 : Log.debug('[ReactNativeBleTransport] MTU cancellation failed', {
|
|
522
|
+
platform: reactNative.Platform.OS,
|
|
523
|
+
stage,
|
|
524
|
+
attempt,
|
|
525
|
+
error: cancelError instanceof Error ? cancelError.message : String(cancelError),
|
|
526
|
+
});
|
|
527
|
+
}
|
|
528
|
+
}
|
|
468
529
|
Log === null || Log === void 0 ? void 0 : Log.debug('[ReactNativeBleTransport] MTU refresh failed, continuing with current value', {
|
|
469
530
|
platform: reactNative.Platform.OS,
|
|
470
531
|
stage,
|
|
471
532
|
attempt,
|
|
472
533
|
actual: device.mtu,
|
|
534
|
+
timedOut,
|
|
473
535
|
error: error instanceof Error ? error.message : String(error),
|
|
474
536
|
});
|
|
475
|
-
return device;
|
|
537
|
+
return { device, timedOut };
|
|
538
|
+
}
|
|
539
|
+
finally {
|
|
540
|
+
if (timeoutId)
|
|
541
|
+
clearTimeout(timeoutId);
|
|
476
542
|
}
|
|
477
543
|
});
|
|
478
|
-
const resolveNegotiatedMtu = (device) =>
|
|
544
|
+
const resolveNegotiatedMtu = (device, cancelTransaction) => shouldRefreshNegotiatedMtu(device.mtu)
|
|
545
|
+
? requestNegotiatedMtu(device, 'connected', 0, cancelTransaction)
|
|
546
|
+
: Promise.resolve({ device, timedOut: false });
|
|
479
547
|
function remapError(error) {
|
|
480
548
|
var _a;
|
|
481
549
|
if (error instanceof reactNativeBlePlx.BleError) {
|
|
@@ -512,6 +580,8 @@ class ReactNativeBleTransport {
|
|
|
512
580
|
this.sessionProtocols = new Map();
|
|
513
581
|
this.confirmedProtocolV2 = new Set();
|
|
514
582
|
this.protocolReprobeFailures = new Map();
|
|
583
|
+
this.silentDetections = new Map();
|
|
584
|
+
this.androidGattCacheRefreshes = new Set();
|
|
515
585
|
this.staleBondErrors = new Map();
|
|
516
586
|
this.acquiringProtocolV2 = new Set();
|
|
517
587
|
this.protocolV2Assemblers = new Map();
|
|
@@ -930,38 +1000,12 @@ class ReactNativeBleTransport {
|
|
|
930
1000
|
else if (reactNative.Platform.OS === 'android') {
|
|
931
1001
|
yield delay(ANDROID_NOTIFY_READY_DELAY_MS);
|
|
932
1002
|
}
|
|
933
|
-
if (this.stopped)
|
|
934
|
-
throw hdShared.ERRORS.TypedError(hdShared.HardwareErrorCode.BleDeviceDisconnected);
|
|
935
|
-
const initialMtu = transport$1.mtuSize;
|
|
936
|
-
let refreshAttempts = 0;
|
|
937
|
-
if ((reactNative.Platform.OS === 'ios' || reactNative.Platform.OS === 'android') &&
|
|
938
|
-
shouldRefreshNegotiatedMtu(transport$1.mtuSize)) {
|
|
939
|
-
refreshAttempts += 1;
|
|
940
|
-
let refreshedDevice = yield requestNegotiatedMtu(transport$1.device, 'servicesAndNotifyReady', 1);
|
|
941
|
-
if (this.stopped)
|
|
942
|
-
throw hdShared.ERRORS.TypedError(hdShared.HardwareErrorCode.BleDeviceDisconnected);
|
|
943
|
-
transport$1.device = refreshedDevice;
|
|
944
|
-
transport$1.mtuSize =
|
|
945
|
-
typeof refreshedDevice.mtu === 'number' ? refreshedDevice.mtu : transport$1.mtuSize;
|
|
946
|
-
if (shouldRefreshNegotiatedMtu(transport$1.mtuSize)) {
|
|
947
|
-
yield delay(BLE_MTU_REFRESH_RETRY_DELAY_MS);
|
|
948
|
-
if (this.stopped)
|
|
949
|
-
throw hdShared.ERRORS.TypedError(hdShared.HardwareErrorCode.BleDeviceDisconnected);
|
|
950
|
-
refreshAttempts += 1;
|
|
951
|
-
refreshedDevice = yield requestNegotiatedMtu(transport$1.device, 'servicesAndNotifyReady', 2);
|
|
952
|
-
transport$1.device = refreshedDevice;
|
|
953
|
-
transport$1.mtuSize =
|
|
954
|
-
typeof refreshedDevice.mtu === 'number' ? refreshedDevice.mtu : transport$1.mtuSize;
|
|
955
|
-
}
|
|
956
|
-
}
|
|
957
1003
|
if (this.stopped)
|
|
958
1004
|
throw hdShared.ERRORS.TypedError(hdShared.HardwareErrorCode.BleDeviceDisconnected);
|
|
959
1005
|
Log === null || Log === void 0 ? void 0 : Log.debug('[ReactNativeBleTransport] BLE MTU ready', {
|
|
960
1006
|
platform: reactNative.Platform.OS,
|
|
961
1007
|
requested: getRequestedBleMtu(),
|
|
962
|
-
initial: initialMtu,
|
|
963
1008
|
actual: transport$1.mtuSize,
|
|
964
|
-
refreshAttempts,
|
|
965
1009
|
});
|
|
966
1010
|
return transport$1;
|
|
967
1011
|
});
|
|
@@ -1011,7 +1055,9 @@ class ReactNativeBleTransport {
|
|
|
1011
1055
|
const isCachedDeviceConnected = yield cachedTransport.device
|
|
1012
1056
|
.isConnected()
|
|
1013
1057
|
.catch(() => false);
|
|
1058
|
+
const isCachedAndroidLinkUsable = reactNative.Platform.OS !== 'android' || !this.androidGattCacheRefreshes.has(uuid);
|
|
1014
1059
|
if (isCachedDeviceConnected &&
|
|
1060
|
+
isCachedAndroidLinkUsable &&
|
|
1015
1061
|
cachedProtocol &&
|
|
1016
1062
|
(!expectedProtocol || cachedProtocol === expectedProtocol)) {
|
|
1017
1063
|
if (this.stopped)
|
|
@@ -1024,6 +1070,15 @@ class ReactNativeBleTransport {
|
|
|
1024
1070
|
}
|
|
1025
1071
|
}
|
|
1026
1072
|
let device = null;
|
|
1073
|
+
const isAndroid = reactNative.Platform.OS === 'android';
|
|
1074
|
+
const refreshAndroidGattCache = isAndroid && (!!skipProtocolProbe || this.androidGattCacheRefreshes.has(uuid));
|
|
1075
|
+
let nativeConnectOptions = connectOptions;
|
|
1076
|
+
if (isAndroid) {
|
|
1077
|
+
nativeConnectOptions = refreshAndroidGattCache
|
|
1078
|
+
? androidRefreshGattConnectOptions
|
|
1079
|
+
: fallbackConnectOptions;
|
|
1080
|
+
}
|
|
1081
|
+
let androidRefreshConnectRan = false;
|
|
1027
1082
|
if (forceCleanRunPromise && this.runPromise) {
|
|
1028
1083
|
const error = hdShared.ERRORS.TypedError(hdShared.HardwareErrorCode.BleForceCleanRunPromise);
|
|
1029
1084
|
this.runPromise.reject(error);
|
|
@@ -1032,6 +1087,7 @@ class ReactNativeBleTransport {
|
|
|
1032
1087
|
Log === null || Log === void 0 ? void 0 : Log.debug('Force clean Bluetooth run promise, forceCleanRunPromise: ', forceCleanRunPromise);
|
|
1033
1088
|
}
|
|
1034
1089
|
const blePlxManager = yield this.getPlxManager();
|
|
1090
|
+
let skipPostConnectMtu = false;
|
|
1035
1091
|
try {
|
|
1036
1092
|
yield subscribeBleOn(blePlxManager);
|
|
1037
1093
|
}
|
|
@@ -1073,15 +1129,16 @@ class ReactNativeBleTransport {
|
|
|
1073
1129
|
if (!device) {
|
|
1074
1130
|
Log === null || Log === void 0 ? void 0 : Log.debug('try to connect to device: ', uuid);
|
|
1075
1131
|
try {
|
|
1076
|
-
device = yield this.connectWithTimeout(uuid, () => blePlxManager.connectToDevice(uuid,
|
|
1132
|
+
device = yield this.connectWithTimeout(uuid, () => blePlxManager.connectToDevice(uuid, nativeConnectOptions));
|
|
1133
|
+
androidRefreshConnectRan = refreshAndroidGattCache;
|
|
1077
1134
|
}
|
|
1078
1135
|
catch (e) {
|
|
1079
1136
|
Log === null || Log === void 0 ? void 0 : Log.debug('try to connect to device has error: ', e);
|
|
1080
1137
|
if (shouldRethrowBleSetupError(e)) {
|
|
1081
1138
|
throw e;
|
|
1082
1139
|
}
|
|
1083
|
-
if (e
|
|
1084
|
-
|
|
1140
|
+
if (isMtuOrCancelledConnectError(e)) {
|
|
1141
|
+
skipPostConnectMtu = true;
|
|
1085
1142
|
Log === null || Log === void 0 ? void 0 : Log.debug('first try to reconnect without params');
|
|
1086
1143
|
device = yield this.connectWithTimeout(uuid, () => blePlxManager.connectToDevice(uuid, fallbackConnectOptions));
|
|
1087
1144
|
}
|
|
@@ -1097,19 +1154,27 @@ class ReactNativeBleTransport {
|
|
|
1097
1154
|
if (!device) {
|
|
1098
1155
|
throw hdShared.ERRORS.TypedError(hdShared.HardwareErrorCode.BleConnectedError, 'unable to connect to device');
|
|
1099
1156
|
}
|
|
1157
|
+
if (refreshAndroidGattCache &&
|
|
1158
|
+
!androidRefreshConnectRan &&
|
|
1159
|
+
(yield device.isConnected().catch(() => false))) {
|
|
1160
|
+
yield this.dropAndroidLink(uuid, blePlxManager, device, 'gatt cache refresh');
|
|
1161
|
+
if (this.stopped)
|
|
1162
|
+
throw hdShared.ERRORS.TypedError(hdShared.HardwareErrorCode.BleDeviceDisconnected);
|
|
1163
|
+
}
|
|
1100
1164
|
if (!(yield device.isConnected())) {
|
|
1101
1165
|
Log === null || Log === void 0 ? void 0 : Log.debug('not connected, try to connect to device: ', uuid);
|
|
1102
1166
|
const disconnectedDevice = device;
|
|
1103
1167
|
try {
|
|
1104
|
-
device = yield this.connectWithTimeout(uuid, () => disconnectedDevice.connect(
|
|
1168
|
+
device = yield this.connectWithTimeout(uuid, () => disconnectedDevice.connect(nativeConnectOptions));
|
|
1169
|
+
androidRefreshConnectRan = refreshAndroidGattCache;
|
|
1105
1170
|
}
|
|
1106
1171
|
catch (e) {
|
|
1107
1172
|
Log === null || Log === void 0 ? void 0 : Log.debug('not connected, try to connect to device has error: ', e);
|
|
1108
1173
|
if (shouldRethrowBleSetupError(e)) {
|
|
1109
1174
|
throw e;
|
|
1110
1175
|
}
|
|
1111
|
-
if (e
|
|
1112
|
-
|
|
1176
|
+
if (isMtuOrCancelledConnectError(e)) {
|
|
1177
|
+
skipPostConnectMtu = true;
|
|
1113
1178
|
Log === null || Log === void 0 ? void 0 : Log.debug('second try to reconnect without params');
|
|
1114
1179
|
try {
|
|
1115
1180
|
device = yield this.connectWithTimeout(uuid, () => disconnectedDevice.connect(fallbackConnectOptions));
|
|
@@ -1145,11 +1210,54 @@ class ReactNativeBleTransport {
|
|
|
1145
1210
|
}
|
|
1146
1211
|
if (this.stopped)
|
|
1147
1212
|
throw hdShared.ERRORS.TypedError(hdShared.HardwareErrorCode.BleDeviceDisconnected);
|
|
1148
|
-
|
|
1213
|
+
let characteristics;
|
|
1214
|
+
if (isAndroid) {
|
|
1215
|
+
if (refreshAndroidGattCache) {
|
|
1216
|
+
characteristics = yield this.resolveCharacteristicsWithTimeout(uuid, device);
|
|
1217
|
+
if (androidRefreshConnectRan)
|
|
1218
|
+
this.androidGattCacheRefreshes.delete(uuid);
|
|
1219
|
+
if (this.stopped)
|
|
1220
|
+
throw hdShared.ERRORS.TypedError(hdShared.HardwareErrorCode.BleDeviceDisconnected);
|
|
1221
|
+
}
|
|
1222
|
+
device = yield this.negotiateAndroidMtu(uuid, blePlxManager, device);
|
|
1223
|
+
}
|
|
1224
|
+
else if (!skipPostConnectMtu) {
|
|
1225
|
+
const mtuResult = yield resolveNegotiatedMtu(device, transactionId => blePlxManager.cancelTransaction(transactionId));
|
|
1226
|
+
device = mtuResult.device;
|
|
1227
|
+
if (mtuResult.timedOut) {
|
|
1228
|
+
if (this.stopped)
|
|
1229
|
+
throw hdShared.ERRORS.TypedError(hdShared.HardwareErrorCode.BleDeviceDisconnected);
|
|
1230
|
+
Log === null || Log === void 0 ? void 0 : Log.debug('[ReactNativeBleTransport] post-connect MTU timed out, reconnecting without requesting MTU');
|
|
1231
|
+
const timedOutDevice = device;
|
|
1232
|
+
let mtuTeardownSettled = false;
|
|
1233
|
+
yield this.runNativeTeardown(uuid, blePlxManager, () => __awaiter(this, void 0, void 0, function* () {
|
|
1234
|
+
yield this.runBestEffortNativeOperation('mtu timeout: cancel device connection', () => timedOutDevice.cancelConnection());
|
|
1235
|
+
mtuTeardownSettled = true;
|
|
1236
|
+
}));
|
|
1237
|
+
if (this.stopped)
|
|
1238
|
+
throw hdShared.ERRORS.TypedError(hdShared.HardwareErrorCode.BleDeviceDisconnected);
|
|
1239
|
+
if (!mtuTeardownSettled || this.blePlxManager !== blePlxManager) {
|
|
1240
|
+
throw hdShared.ERRORS.TypedError(hdShared.HardwareErrorCode.BleTimeoutError, 'BLE MTU cleanup timed out');
|
|
1241
|
+
}
|
|
1242
|
+
try {
|
|
1243
|
+
device = yield this.connectWithTimeout(uuid, () => timedOutDevice.connect(fallbackConnectOptions));
|
|
1244
|
+
}
|
|
1245
|
+
catch (error) {
|
|
1246
|
+
if (shouldRethrowBleSetupError(error))
|
|
1247
|
+
throw error;
|
|
1248
|
+
if ((error === null || error === void 0 ? void 0 : error.errorCode) === reactNativeBlePlx.BleErrorCode.DeviceAlreadyConnected) {
|
|
1249
|
+
device = timedOutDevice;
|
|
1250
|
+
}
|
|
1251
|
+
else {
|
|
1252
|
+
remapError(error);
|
|
1253
|
+
}
|
|
1254
|
+
}
|
|
1255
|
+
}
|
|
1256
|
+
}
|
|
1149
1257
|
if (this.stopped)
|
|
1150
1258
|
throw hdShared.ERRORS.TypedError(hdShared.HardwareErrorCode.BleDeviceDisconnected);
|
|
1151
1259
|
const acquiredDevice = device;
|
|
1152
|
-
const { writeCharacteristic, notifyCharacteristic } = yield this.resolveCharacteristicsWithTimeout(uuid, acquiredDevice);
|
|
1260
|
+
const { writeCharacteristic, notifyCharacteristic } = characteristics !== null && characteristics !== void 0 ? characteristics : (yield this.resolveCharacteristicsWithTimeout(uuid, acquiredDevice));
|
|
1153
1261
|
if (this.stopped)
|
|
1154
1262
|
throw hdShared.ERRORS.TypedError(hdShared.HardwareErrorCode.BleDeviceDisconnected);
|
|
1155
1263
|
const protocolHint = expectedProtocol
|
|
@@ -1216,7 +1324,7 @@ class ReactNativeBleTransport {
|
|
|
1216
1324
|
let bufferLength = 0;
|
|
1217
1325
|
let buffer$1 = [];
|
|
1218
1326
|
const subscription = characteristic.monitor((error, c) => {
|
|
1219
|
-
var _a, _b, _c, _d, _e, _f
|
|
1327
|
+
var _a, _b, _c, _d, _e, _f;
|
|
1220
1328
|
const isCurrentMonitor = this.monitorTokens.get(uuid) === monitorToken;
|
|
1221
1329
|
if (error) {
|
|
1222
1330
|
Log === null || Log === void 0 ? void 0 : Log.debug(`error monitor ${characteristic.uuid}, deviceId: ${characteristic.deviceID}: ${error}`);
|
|
@@ -1233,16 +1341,16 @@ class ReactNativeBleTransport {
|
|
|
1233
1341
|
this.rememberStaleBondError(uuid, toBleStaleBondHardwareError(error));
|
|
1234
1342
|
return;
|
|
1235
1343
|
}
|
|
1344
|
+
if (reactNative.Platform.OS === 'android' && isStaleGattTableNotifyReason(error.reason)) {
|
|
1345
|
+
this.androidGattCacheRefreshes.add(uuid);
|
|
1346
|
+
}
|
|
1236
1347
|
if (this.getActiveProtocol(uuid) === 'V2') {
|
|
1237
1348
|
let errorCode = hdShared.HardwareErrorCode.BleCharacteristicNotifyError;
|
|
1238
1349
|
if ((_a = error.reason) === null || _a === void 0 ? void 0 : _a.includes('The connection has timed out unexpectedly')) {
|
|
1239
1350
|
errorCode = hdShared.HardwareErrorCode.BleTimeoutError;
|
|
1240
1351
|
}
|
|
1241
|
-
else if ((
|
|
1242
|
-
((
|
|
1243
|
-
((_d = error.reason) === null || _d === void 0 ? void 0 : _d.includes('The handle is invalid')) ||
|
|
1244
|
-
((_e = error.reason) === null || _e === void 0 ? void 0 : _e.includes('Writing is not permitted')) ||
|
|
1245
|
-
((_f = error.reason) === null || _f === void 0 ? void 0 : _f.includes('notify change failed for device'))) {
|
|
1352
|
+
else if (isStaleGattTableNotifyReason(error.reason) ||
|
|
1353
|
+
((_b = error.reason) === null || _b === void 0 ? void 0 : _b.includes('notify change failed for device'))) {
|
|
1246
1354
|
errorCode = hdShared.HardwareErrorCode.BleCharacteristicNotifyChangeFailure;
|
|
1247
1355
|
}
|
|
1248
1356
|
this.rejectProtocolV2Frames(uuid, hdShared.ERRORS.TypedError(errorCode));
|
|
@@ -1250,14 +1358,11 @@ class ReactNativeBleTransport {
|
|
|
1250
1358
|
}
|
|
1251
1359
|
if (this.runPromise && this.runPromiseDeviceId === uuid) {
|
|
1252
1360
|
let ERROR = hdShared.HardwareErrorCode.BleCharacteristicNotifyError;
|
|
1253
|
-
if ((
|
|
1361
|
+
if ((_c = error.reason) === null || _c === void 0 ? void 0 : _c.includes('The connection has timed out unexpectedly')) {
|
|
1254
1362
|
ERROR = hdShared.HardwareErrorCode.BleTimeoutError;
|
|
1255
1363
|
}
|
|
1256
|
-
if ((
|
|
1257
|
-
((
|
|
1258
|
-
((_k = error.reason) === null || _k === void 0 ? void 0 : _k.includes('The handle is invalid')) ||
|
|
1259
|
-
((_l = error.reason) === null || _l === void 0 ? void 0 : _l.includes('Writing is not permitted')) ||
|
|
1260
|
-
((_m = error.reason) === null || _m === void 0 ? void 0 : _m.includes('notify change failed for device'))) {
|
|
1364
|
+
if (isStaleGattTableNotifyReason(error.reason) ||
|
|
1365
|
+
((_d = error.reason) === null || _d === void 0 ? void 0 : _d.includes('notify change failed for device'))) {
|
|
1261
1366
|
const notifyError = hdShared.ERRORS.TypedError(hdShared.HardwareErrorCode.BleCharacteristicNotifyChangeFailure);
|
|
1262
1367
|
this.runPromise.reject(notifyError);
|
|
1263
1368
|
Log === null || Log === void 0 ? void 0 : Log.debug(`${hdShared.HardwareErrorCode.BleCharacteristicNotifyChangeFailure} ${error.message} ${error.reason}`);
|
|
@@ -1299,7 +1404,7 @@ class ReactNativeBleTransport {
|
|
|
1299
1404
|
bufferLength = 0;
|
|
1300
1405
|
buffer$1 = [];
|
|
1301
1406
|
if (this.runPromiseDeviceId === uuid) {
|
|
1302
|
-
(
|
|
1407
|
+
(_e = this.runPromise) === null || _e === void 0 ? void 0 : _e.resolve(value.toString('hex'));
|
|
1303
1408
|
}
|
|
1304
1409
|
}
|
|
1305
1410
|
}
|
|
@@ -1310,7 +1415,7 @@ class ReactNativeBleTransport {
|
|
|
1310
1415
|
this.rejectProtocolV2Frames(uuid, notifyError);
|
|
1311
1416
|
}
|
|
1312
1417
|
else if (this.runPromiseDeviceId === uuid) {
|
|
1313
|
-
(
|
|
1418
|
+
(_f = this.runPromise) === null || _f === void 0 ? void 0 : _f.reject(notifyError);
|
|
1314
1419
|
}
|
|
1315
1420
|
}
|
|
1316
1421
|
}, notifyTransactionId);
|
|
@@ -1586,13 +1691,14 @@ class ReactNativeBleTransport {
|
|
|
1586
1691
|
return check.call(jsonData);
|
|
1587
1692
|
}
|
|
1588
1693
|
catch (e) {
|
|
1589
|
-
|
|
1590
|
-
|
|
1694
|
+
const isProbeTimeout = (options === null || options === void 0 ? void 0 : options.timeoutMs) === PROTOCOL_PROBE_TIMEOUT_MS &&
|
|
1695
|
+
(name === 'GetFeatures' || name === 'Initialize');
|
|
1696
|
+
if (isProbeTimeout) {
|
|
1697
|
+
Log === null || Log === void 0 ? void 0 : Log.debug(`[ReactNativeBleTransport] Protocol V1 ${name} probe call failed:`, e);
|
|
1591
1698
|
}
|
|
1592
1699
|
else {
|
|
1593
1700
|
Log === null || Log === void 0 ? void 0 : Log.error('call error: ', e);
|
|
1594
1701
|
}
|
|
1595
|
-
const isProbeTimeout = name === 'GetFeatures' && (options === null || options === void 0 ? void 0 : options.timeoutMs) === PROTOCOL_PROBE_TIMEOUT_MS;
|
|
1596
1702
|
const isStaleCall = this.runPromise !== runPromise;
|
|
1597
1703
|
if (!isProbeTimeout &&
|
|
1598
1704
|
!isStaleCall &&
|
|
@@ -1793,6 +1899,72 @@ class ReactNativeBleTransport {
|
|
|
1793
1899
|
}
|
|
1794
1900
|
});
|
|
1795
1901
|
}
|
|
1902
|
+
negotiateAndroidMtu(uuid, manager, device) {
|
|
1903
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
1904
|
+
if (!shouldRefreshNegotiatedMtu(device.mtu))
|
|
1905
|
+
return device;
|
|
1906
|
+
const startedAt = Date.now();
|
|
1907
|
+
let timer;
|
|
1908
|
+
let timedOut = false;
|
|
1909
|
+
let negotiated = device;
|
|
1910
|
+
let failure;
|
|
1911
|
+
try {
|
|
1912
|
+
negotiated = yield Promise.race([
|
|
1913
|
+
device.requestMTU(ANDROID_REQUEST_MTU, `${device.id}:mtu:connected:0:${startedAt}`),
|
|
1914
|
+
new Promise((_, reject) => {
|
|
1915
|
+
timer = setTimeout(() => {
|
|
1916
|
+
timedOut = true;
|
|
1917
|
+
reject(new Error(`BLE MTU exchange timeout after ${ANDROID_MTU_EXCHANGE_TIMEOUT_MS}ms`));
|
|
1918
|
+
}, ANDROID_MTU_EXCHANGE_TIMEOUT_MS);
|
|
1919
|
+
}),
|
|
1920
|
+
]);
|
|
1921
|
+
}
|
|
1922
|
+
catch (error) {
|
|
1923
|
+
failure = error instanceof Error ? error.message : String(error);
|
|
1924
|
+
}
|
|
1925
|
+
finally {
|
|
1926
|
+
if (timer)
|
|
1927
|
+
clearTimeout(timer);
|
|
1928
|
+
}
|
|
1929
|
+
Log === null || Log === void 0 ? void 0 : Log.debug(`[ReactNativeBleTransport] BLE MTU exchange ${failure ? 'failed' : 'completed'}`, {
|
|
1930
|
+
connectIdSuffix: uuid.slice(-8),
|
|
1931
|
+
elapsedMs: Date.now() - startedAt,
|
|
1932
|
+
timedOut,
|
|
1933
|
+
actual: negotiated.mtu,
|
|
1934
|
+
error: failure,
|
|
1935
|
+
});
|
|
1936
|
+
if (this.stopped)
|
|
1937
|
+
throw hdShared.ERRORS.TypedError(hdShared.HardwareErrorCode.BleDeviceDisconnected);
|
|
1938
|
+
if (!timedOut && !isKnownDefaultMtu(negotiated.mtu))
|
|
1939
|
+
return negotiated;
|
|
1940
|
+
const resetManager = this.abandonStalledConnection(uuid, timedOut ? 'mtu-backstop' : 'mtu-default');
|
|
1941
|
+
yield this.dropAndroidLink(uuid, manager, negotiated, timedOut ? 'mtu exchange timeout' : 'default mtu');
|
|
1942
|
+
if (resetManager)
|
|
1943
|
+
throw this.createWedgedBleSetupError();
|
|
1944
|
+
throw hdShared.ERRORS.TypedError(hdShared.HardwareErrorCode.BleConnectedError, timedOut
|
|
1945
|
+
? 'BLE MTU exchange did not complete, reconnecting on a fresh link'
|
|
1946
|
+
: `BLE link stayed at the default MTU ${negotiated.mtu}, reconnecting on a fresh link`);
|
|
1947
|
+
});
|
|
1948
|
+
}
|
|
1949
|
+
dropAndroidLink(uuid, manager, device, reason) {
|
|
1950
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
1951
|
+
yield this.runNativeTeardown(uuid, manager, () => __awaiter(this, void 0, void 0, function* () {
|
|
1952
|
+
yield Promise.all([
|
|
1953
|
+
this.runBestEffortNativeOperation(`${reason}: cancel manager connection`, () => manager.cancelDeviceConnection(uuid)),
|
|
1954
|
+
this.runBestEffortNativeOperation(`${reason}: cancel device connection`, () => device.cancelConnection()),
|
|
1955
|
+
]);
|
|
1956
|
+
}));
|
|
1957
|
+
const startedAt = Date.now();
|
|
1958
|
+
while (!this.stopped && Date.now() - startedAt < ANDROID_LINK_DROP_QUIET_MS) {
|
|
1959
|
+
yield delay(ANDROID_LINK_DROP_POLL_MS);
|
|
1960
|
+
}
|
|
1961
|
+
Log === null || Log === void 0 ? void 0 : Log.debug('[ReactNativeBleTransport] Android BLE link drop', {
|
|
1962
|
+
connectIdSuffix: uuid.slice(-8),
|
|
1963
|
+
reason,
|
|
1964
|
+
stopped: this.stopped,
|
|
1965
|
+
});
|
|
1966
|
+
});
|
|
1967
|
+
}
|
|
1796
1968
|
connectWithTimeout(uuid, connect) {
|
|
1797
1969
|
return __awaiter(this, void 0, void 0, function* () {
|
|
1798
1970
|
if (this.stopped)
|
|
@@ -1866,6 +2038,9 @@ class ReactNativeBleTransport {
|
|
|
1866
2038
|
throw this.createWedgedBleSetupError();
|
|
1867
2039
|
}
|
|
1868
2040
|
}
|
|
2041
|
+
if (reactNative.Platform.OS === 'android' && isMissingGattShapeError(error)) {
|
|
2042
|
+
this.androidGattCacheRefreshes.add(uuid);
|
|
2043
|
+
}
|
|
1869
2044
|
throw error;
|
|
1870
2045
|
}
|
|
1871
2046
|
finally {
|
|
@@ -2017,6 +2192,7 @@ class ReactNativeBleTransport {
|
|
|
2017
2192
|
this.acquiringProtocolV2.clear();
|
|
2018
2193
|
this.sessionProtocols.clear();
|
|
2019
2194
|
this.protocolReprobeFailures.clear();
|
|
2195
|
+
this.silentDetections.clear();
|
|
2020
2196
|
this.writeTimeoutCounts.clear();
|
|
2021
2197
|
this.connectionSetupTimeoutCounts.clear();
|
|
2022
2198
|
this.monitorTokens.clear();
|
|
@@ -2090,6 +2266,7 @@ class ReactNativeBleTransport {
|
|
|
2090
2266
|
!protocolHint &&
|
|
2091
2267
|
reprobeFailures < PROTOCOL_REPROBE_FALLBACK_ATTEMPTS;
|
|
2092
2268
|
const probeOrder = trustSessionProtocol ? [sessionProtocol] : fullProbeOrder;
|
|
2269
|
+
yield this.wakeSilentProtocolV1Device(uuid, probeOrder);
|
|
2093
2270
|
for (let i = 0; i < probeOrder.length; i += 1) {
|
|
2094
2271
|
const protocol = probeOrder[i];
|
|
2095
2272
|
if (i > 0) {
|
|
@@ -2109,6 +2286,7 @@ class ReactNativeBleTransport {
|
|
|
2109
2286
|
this.confirmedProtocolV2.add(uuid);
|
|
2110
2287
|
}
|
|
2111
2288
|
this.protocolReprobeFailures.delete(uuid);
|
|
2289
|
+
this.silentDetections.delete(uuid);
|
|
2112
2290
|
Log === null || Log === void 0 ? void 0 : Log.debug('[ReactNativeBleTransport] protocol detected', {
|
|
2113
2291
|
deviceId: uuid,
|
|
2114
2292
|
protocol,
|
|
@@ -2117,6 +2295,8 @@ class ReactNativeBleTransport {
|
|
|
2117
2295
|
return protocol;
|
|
2118
2296
|
}
|
|
2119
2297
|
}
|
|
2298
|
+
if (!this.silentDetections.has(uuid))
|
|
2299
|
+
this.silentDetections.set(uuid, 'silent');
|
|
2120
2300
|
if (trustSessionProtocol) {
|
|
2121
2301
|
this.protocolReprobeFailures.set(uuid, reprobeFailures + 1);
|
|
2122
2302
|
}
|
|
@@ -2128,6 +2308,30 @@ class ReactNativeBleTransport {
|
|
|
2128
2308
|
throw this.createProtocolDetectionError();
|
|
2129
2309
|
});
|
|
2130
2310
|
}
|
|
2311
|
+
wakeSilentProtocolV1Device(uuid, probeOrder) {
|
|
2312
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
2313
|
+
if (reactNative.Platform.OS !== 'android' ||
|
|
2314
|
+
probeOrder[0] !== 'V1' ||
|
|
2315
|
+
this.silentDetections.get(uuid) !== 'silent') {
|
|
2316
|
+
return;
|
|
2317
|
+
}
|
|
2318
|
+
this.silentDetections.set(uuid, 'woken');
|
|
2319
|
+
Log === null || Log === void 0 ? void 0 : Log.debug('[ReactNativeBleTransport] sending Protocol V1 Initialize wake', {
|
|
2320
|
+
connectIdSuffix: uuid.slice(-8),
|
|
2321
|
+
});
|
|
2322
|
+
try {
|
|
2323
|
+
this.probingProtocols.set(uuid, 'V1');
|
|
2324
|
+
yield this.callProtocolV1(uuid, 'Initialize', {}, { timeoutMs: PROTOCOL_PROBE_TIMEOUT_MS });
|
|
2325
|
+
}
|
|
2326
|
+
catch (error) {
|
|
2327
|
+
if (shouldRethrowProtocolProbeError(error))
|
|
2328
|
+
throw error;
|
|
2329
|
+
}
|
|
2330
|
+
finally {
|
|
2331
|
+
this.clearProbeProtocol(uuid, 'V1');
|
|
2332
|
+
}
|
|
2333
|
+
});
|
|
2334
|
+
}
|
|
2131
2335
|
resetProbeStateAfterProtocolProbe(uuid, protocol) {
|
|
2132
2336
|
var _a, _b, _c;
|
|
2133
2337
|
return __awaiter(this, void 0, void 0, function* () {
|
|
@@ -2445,7 +2649,7 @@ class ReactNativeBleTransport {
|
|
|
2445
2649
|
const transport = this.getCachedTransport(uuid);
|
|
2446
2650
|
if (!shouldRefreshNegotiatedMtu(transport.mtuSize))
|
|
2447
2651
|
return;
|
|
2448
|
-
const refreshedDevice = yield requestNegotiatedMtu(transport.device, 'highThroughput', 1);
|
|
2652
|
+
const { device: refreshedDevice } = yield requestNegotiatedMtu(transport.device, 'highThroughput', 1, transactionId => { var _a; return (_a = this.blePlxManager) === null || _a === void 0 ? void 0 : _a.cancelTransaction(transactionId); });
|
|
2449
2653
|
transport.device = refreshedDevice;
|
|
2450
2654
|
transport.mtuSize =
|
|
2451
2655
|
typeof refreshedDevice.mtu === 'number' ? refreshedDevice.mtu : transport.mtuSize;
|
|
@@ -2562,6 +2766,8 @@ class ReactNativeBleTransport {
|
|
|
2562
2766
|
}
|
|
2563
2767
|
}
|
|
2564
2768
|
|
|
2769
|
+
exports.ANDROID_LINK_DROP_QUIET_MS = ANDROID_LINK_DROP_QUIET_MS;
|
|
2770
|
+
exports.ANDROID_MTU_EXCHANGE_TIMEOUT_MS = ANDROID_MTU_EXCHANGE_TIMEOUT_MS;
|
|
2565
2771
|
exports.BLE_CONNECT_TIMEOUT_MANAGER_RESET_THRESHOLD = BLE_CONNECT_TIMEOUT_MANAGER_RESET_THRESHOLD;
|
|
2566
2772
|
exports.BLE_CONNECT_TIMEOUT_MS = BLE_CONNECT_TIMEOUT_MS;
|
|
2567
2773
|
exports.BLE_GATT_SETUP_TIMEOUT_MS = BLE_GATT_SETUP_TIMEOUT_MS;
|