@onekeyfe/hd-transport-react-native 1.2.0-alpha.68 → 1.2.0-alpha.69
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/BleTransport.d.ts +1 -1
- package/dist/BleTransport.d.ts.map +1 -1
- package/dist/bleStrategy.d.ts +6 -0
- package/dist/bleStrategy.d.ts.map +1 -1
- package/dist/constants.d.ts +2 -1
- package/dist/constants.d.ts.map +1 -1
- package/dist/index.d.ts +9 -80
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +210 -341
- package/jest.config.js +0 -5
- package/package.json +5 -5
- package/src/BleTransport.ts +1 -1
- package/src/__tests__/bleStrategy.test.ts +77 -7
- package/src/__tests__/protocolV2Link.test.ts +121 -28
- package/src/bleStrategy.ts +23 -10
- package/src/constants.ts +2 -1
- package/src/index.ts +229 -486
- package/src/__tests__/connectTimeout.test.ts +0 -281
- package/src/__tests__/protocolReprobe.test.ts +0 -132
- package/src/__tests__/protocolV1SchemaFixture.ts +0 -39
- package/src/__tests__/staleCallTimeout.test.ts +0 -210
- package/src/__tests__/writePacketTimeout.test.ts +0 -305
package/dist/index.js
CHANGED
|
@@ -93,7 +93,8 @@ const onDeviceBondState = (bleMacAddress) => new Promise((resolve, reject) => {
|
|
|
93
93
|
|
|
94
94
|
const IOS_PACKET_LENGTH = 128;
|
|
95
95
|
const ANDROID_PACKET_LENGTH = 192;
|
|
96
|
-
const
|
|
96
|
+
const IOS_PROTOCOL_V2_PACKET_LENGTH = 244;
|
|
97
|
+
const ANDROID_PROTOCOL_V2_PACKET_LENGTH = 514;
|
|
97
98
|
const ClassicServiceUUID = '00000001-0000-1000-8000-00805f9b34fb';
|
|
98
99
|
const OneKeyServices = {
|
|
99
100
|
classic: {
|
|
@@ -134,15 +135,20 @@ const isSameBleUuid = (left, right) => {
|
|
|
134
135
|
function hasWritableCapability(characteristic) {
|
|
135
136
|
return !!(characteristic.isWritableWithResponse || characteristic.isWritableWithoutResponse);
|
|
136
137
|
}
|
|
137
|
-
function resolveProtocolV2PacketCapacity({ platform, iosPacketLength =
|
|
138
|
-
if (
|
|
139
|
-
|
|
138
|
+
function resolveProtocolV2PacketCapacity({ platform, iosPacketLength = IOS_PROTOCOL_V2_PACKET_LENGTH, androidPacketLength = ANDROID_PROTOCOL_V2_PACKET_LENGTH, mtu, }) {
|
|
139
|
+
if (typeof mtu !== 'number' || !Number.isFinite(mtu) || mtu <= 3) {
|
|
140
|
+
throw new Error(`Protocol V2 BLE requires a negotiated MTU, received: ${String(mtu)}`);
|
|
140
141
|
}
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
142
|
+
const payloadLength = Math.floor(mtu) - 3;
|
|
143
|
+
const configuredPacketLength = platform === 'ios' ? iosPacketLength : androidPacketLength;
|
|
144
|
+
return Math.min(configuredPacketLength, payloadLength);
|
|
145
|
+
}
|
|
146
|
+
function shouldWriteProtocolV2WithResponse({ platform, highVolume, requestedWithResponse, characteristic, }) {
|
|
147
|
+
if (!characteristic.isWritableWithResponse)
|
|
148
|
+
return false;
|
|
149
|
+
if (!characteristic.isWritableWithoutResponse)
|
|
150
|
+
return true;
|
|
151
|
+
return requestedWithResponse === true || (platform === 'ios' && !highVolume);
|
|
146
152
|
}
|
|
147
153
|
|
|
148
154
|
const timer = process.env.NODE_ENV === 'development'
|
|
@@ -202,7 +208,6 @@ const isHeaderChunk = (chunk) => {
|
|
|
202
208
|
class BleTransport {
|
|
203
209
|
constructor(device, writeCharacteristic, notifyCharacteristic) {
|
|
204
210
|
this.name = 'ReactNativeBleTransport';
|
|
205
|
-
this.mtuSize = 23;
|
|
206
211
|
this.id = device.id;
|
|
207
212
|
this.device = device;
|
|
208
213
|
this.writeCharacteristic = writeCharacteristic;
|
|
@@ -226,7 +231,6 @@ const FIRMWARE_UPLOAD_WRITE_BURST_SIZE = reactNative.Platform.OS === 'ios' ? 4 :
|
|
|
226
231
|
const FIRMWARE_UPLOAD_WRITE_PAUSE_MS = reactNative.Platform.OS === 'ios' ? 8 : 10;
|
|
227
232
|
const FIRMWARE_UPLOAD_WRITE_FLUSH_DELAY_MS = reactNative.Platform.OS === 'ios' ? 24 : 30;
|
|
228
233
|
const FIRMWARE_UPLOAD_WRITE_MAX_RETRIES = 8;
|
|
229
|
-
const IOS_PROTOCOL_V2_CONTROL_WRITE_DELAY_MS = 5;
|
|
230
234
|
const ANDROID_FIRMWARE_UPLOAD_PACKET_LENGTH = 192;
|
|
231
235
|
const FIRMWARE_UPLOAD_WRITE_PACKET_CAPACITY = reactNative.Platform.OS === 'ios' ? IOS_PACKET_LENGTH : ANDROID_FIRMWARE_UPLOAD_PACKET_LENGTH;
|
|
232
236
|
const ANDROID_GATT_CONGESTED_STATUS = 143;
|
|
@@ -275,18 +279,12 @@ const getFirmwareUploadWriteRetryType = (error) => {
|
|
|
275
279
|
const resolveFirmwareUploadRetryDelay = (attempt, baseDelayMs = 200, maxDelayMs = 1200) => Math.min(baseDelayMs * Math.pow(2, attempt), maxDelayMs);
|
|
276
280
|
const PROTOCOL_PROBE_TIMEOUT_MS = 1000;
|
|
277
281
|
const PROTOCOL_V2_PROBE_TIMEOUT_MS = 10000;
|
|
278
|
-
const BLE_WRITE_PACKET_TIMEOUT_MS = 10000;
|
|
279
|
-
const WEDGED_WRITE_MESSAGE = 'BLE write timeout after';
|
|
280
|
-
const isWedgedWriteError = (error) => (error === null || error === void 0 ? void 0 : error.errorCode) === hdShared.HardwareErrorCode.BleWriteCharacteristicError &&
|
|
281
|
-
typeof (error === null || error === void 0 ? void 0 : error.message) === 'string' &&
|
|
282
|
-
error.message.startsWith(WEDGED_WRITE_MESSAGE);
|
|
283
|
-
const BLE_WRITE_TIMEOUT_MANAGER_RESET_THRESHOLD = 2;
|
|
284
282
|
const DEVICE_SCAN_TIMEOUT_MS = 3000;
|
|
285
283
|
const IOS_NOTIFY_READY_DELAY_MS = 150;
|
|
286
284
|
const ANDROID_NOTIFY_READY_DELAY_MS = 300;
|
|
287
285
|
const DEFAULT_PROTOCOL_V2_BLE_TUNING = {
|
|
288
|
-
iosPacketLength:
|
|
289
|
-
androidPacketLength:
|
|
286
|
+
iosPacketLength: IOS_PROTOCOL_V2_PACKET_LENGTH,
|
|
287
|
+
androidPacketLength: ANDROID_PROTOCOL_V2_PACKET_LENGTH,
|
|
290
288
|
};
|
|
291
289
|
let protocolV2BleTuning = Object.assign({}, DEFAULT_PROTOCOL_V2_BLE_TUNING);
|
|
292
290
|
const normalizePositiveInteger = (value, fallback) => {
|
|
@@ -315,25 +313,17 @@ function inferProtocolHintFromDeviceName(name) {
|
|
|
315
313
|
function getDeviceDisplayName(device) {
|
|
316
314
|
return (device === null || device === void 0 ? void 0 : device.name) || (device === null || device === void 0 ? void 0 : device.localName) || null;
|
|
317
315
|
}
|
|
318
|
-
const
|
|
319
|
-
const
|
|
316
|
+
const IOS_REQUEST_MTU = 247;
|
|
317
|
+
const ANDROID_REQUEST_MTU = 517;
|
|
318
|
+
const BLE_MTU_REFRESH_THRESHOLD = 247;
|
|
319
|
+
const BLE_MTU_REFRESH_RETRY_DELAY_MS = 200;
|
|
320
|
+
const ANDROID_HIGH_PRIORITY_IDLE_MS = 1000;
|
|
321
|
+
const getRequestedBleMtu = () => reactNative.Platform.OS === 'android' ? ANDROID_REQUEST_MTU : IOS_REQUEST_MTU;
|
|
320
322
|
const connectOptions = {
|
|
321
|
-
requestMTU:
|
|
322
|
-
timeout:
|
|
323
|
+
requestMTU: getRequestedBleMtu(),
|
|
324
|
+
timeout: 3000,
|
|
323
325
|
refreshGatt: 'OnConnected',
|
|
324
326
|
};
|
|
325
|
-
const fallbackConnectOptions = {
|
|
326
|
-
timeout: BLE_NATIVE_CONNECT_TIMEOUT_MS,
|
|
327
|
-
};
|
|
328
|
-
const BLE_CONNECT_TIMEOUT_MS = BLE_NATIVE_CONNECT_TIMEOUT_MS * 2 + 2000;
|
|
329
|
-
const BLE_GATT_SETUP_TIMEOUT_MS = 10000;
|
|
330
|
-
const PROTOCOL_REPROBE_FALLBACK_ATTEMPTS = 3;
|
|
331
|
-
const BLE_CONNECT_TIMEOUT_MANAGER_RESET_THRESHOLD = 2;
|
|
332
|
-
const CONNECT_TIMEOUT_MESSAGE = 'BLE connect timeout after';
|
|
333
|
-
const isConnectTimeoutError = (error) => (error === null || error === void 0 ? void 0 : error.errorCode) === hdShared.HardwareErrorCode.BleConnectedError &&
|
|
334
|
-
typeof (error === null || error === void 0 ? void 0 : error.message) === 'string' &&
|
|
335
|
-
error.message.startsWith(CONNECT_TIMEOUT_MESSAGE);
|
|
336
|
-
const isNativeOperationTimeoutError = (error) => (error === null || error === void 0 ? void 0 : error.errorCode) === reactNativeBlePlx.BleErrorCode.OperationTimedOut;
|
|
337
327
|
const tryToGetConfiguration = (device) => {
|
|
338
328
|
if (!device || !device.serviceUUIDs)
|
|
339
329
|
return null;
|
|
@@ -345,23 +335,25 @@ const tryToGetConfiguration = (device) => {
|
|
|
345
335
|
return null;
|
|
346
336
|
return infos;
|
|
347
337
|
};
|
|
348
|
-
const
|
|
349
|
-
if (reactNative.Platform.OS !== 'android')
|
|
338
|
+
const requestNegotiatedMtu = (device, stage, attempt) => __awaiter(void 0, void 0, void 0, function* () {
|
|
339
|
+
if (reactNative.Platform.OS !== 'ios' && reactNative.Platform.OS !== 'android')
|
|
350
340
|
return device;
|
|
351
341
|
try {
|
|
352
|
-
const mtuDevice = yield device.requestMTU(
|
|
353
|
-
Log === null || Log === void 0 ? void 0 : Log.debug('[ReactNativeBleTransport] MTU configured', {
|
|
354
|
-
deviceId: device.id,
|
|
355
|
-
requested: ANDROID_REQUEST_MTU,
|
|
356
|
-
actual: mtuDevice.mtu,
|
|
357
|
-
});
|
|
342
|
+
const mtuDevice = yield device.requestMTU(getRequestedBleMtu());
|
|
358
343
|
return mtuDevice;
|
|
359
344
|
}
|
|
360
345
|
catch (error) {
|
|
361
|
-
Log === null || Log === void 0 ? void 0 : Log.debug('[ReactNativeBleTransport]
|
|
346
|
+
Log === null || Log === void 0 ? void 0 : Log.debug('[ReactNativeBleTransport] MTU refresh failed, continuing with current value', {
|
|
347
|
+
platform: reactNative.Platform.OS,
|
|
348
|
+
stage,
|
|
349
|
+
attempt,
|
|
350
|
+
actual: device.mtu,
|
|
351
|
+
error: error instanceof Error ? error.message : String(error),
|
|
352
|
+
});
|
|
362
353
|
return device;
|
|
363
354
|
}
|
|
364
355
|
});
|
|
356
|
+
const resolveNegotiatedMtu = (device) => requestNegotiatedMtu(device, 'connected', 0);
|
|
365
357
|
function remapError(error) {
|
|
366
358
|
var _a;
|
|
367
359
|
if (error instanceof reactNativeBlePlx.BleError) {
|
|
@@ -391,12 +383,7 @@ class ReactNativeBleTransport {
|
|
|
391
383
|
this.runPromiseDeviceId = null;
|
|
392
384
|
this.firmwareUploadWriteRecoveryIds = new Set();
|
|
393
385
|
this.deviceProtocol = new Map();
|
|
394
|
-
this.probingProtocols = new Map();
|
|
395
|
-
this.writeTimeoutCounts = new Map();
|
|
396
|
-
this.connectionSetupTimeoutCounts = new Map();
|
|
397
386
|
this.deviceProtocolHints = new Map();
|
|
398
|
-
this.sessionProtocols = new Map();
|
|
399
|
-
this.protocolReprobeFailures = new Map();
|
|
400
387
|
this.protocolV2Assemblers = new Map();
|
|
401
388
|
this.protocolV2FrameQueues = new Map();
|
|
402
389
|
this.protocolV2FramePromises = new Map();
|
|
@@ -423,6 +410,9 @@ class ReactNativeBleTransport {
|
|
|
423
410
|
});
|
|
424
411
|
this.monitorTokens = new Map();
|
|
425
412
|
this.disconnectEventTokens = new Map();
|
|
413
|
+
this.protocolV2HighVolumeLogSignatures = new Map();
|
|
414
|
+
this.androidHighPriorityDevices = new Set();
|
|
415
|
+
this.androidPriorityResetTimers = new Map();
|
|
426
416
|
this.nextMonitorToken = 1;
|
|
427
417
|
this.scanTimeout = (_a = options.scanTimeout) !== null && _a !== void 0 ? _a : DEVICE_SCAN_TIMEOUT_MS;
|
|
428
418
|
}
|
|
@@ -588,19 +578,19 @@ class ReactNativeBleTransport {
|
|
|
588
578
|
const isConnected = yield device.isConnected().catch(() => false);
|
|
589
579
|
if (!isConnected) {
|
|
590
580
|
try {
|
|
591
|
-
device = yield
|
|
581
|
+
device = yield device.connect(connectOptions);
|
|
592
582
|
}
|
|
593
583
|
catch (e) {
|
|
594
584
|
if (e.errorCode === reactNativeBlePlx.BleErrorCode.DeviceMTUChangeFailed ||
|
|
595
585
|
e.errorCode === reactNativeBlePlx.BleErrorCode.OperationCancelled) {
|
|
596
|
-
device = yield
|
|
586
|
+
device = yield device.connect();
|
|
597
587
|
}
|
|
598
588
|
else if (e.errorCode !== reactNativeBlePlx.BleErrorCode.DeviceAlreadyConnected) {
|
|
599
589
|
throw e;
|
|
600
590
|
}
|
|
601
591
|
}
|
|
602
592
|
}
|
|
603
|
-
const { writeCharacteristic, notifyCharacteristic } = yield this.
|
|
593
|
+
const { writeCharacteristic, notifyCharacteristic } = yield this.resolveCharacteristics(device);
|
|
604
594
|
transport.device = device;
|
|
605
595
|
transport.writeCharacteristic = writeCharacteristic;
|
|
606
596
|
transport.notifyCharacteristic = notifyCharacteristic;
|
|
@@ -737,11 +727,9 @@ class ReactNativeBleTransport {
|
|
|
737
727
|
}
|
|
738
728
|
installTransportForAcquire(uuid, device, characteristics) {
|
|
739
729
|
return __awaiter(this, void 0, void 0, function* () {
|
|
740
|
-
const { writeCharacteristic, notifyCharacteristic } = characteristics !== null && characteristics !== void 0 ? characteristics : (yield this.
|
|
730
|
+
const { writeCharacteristic, notifyCharacteristic } = characteristics !== null && characteristics !== void 0 ? characteristics : (yield this.resolveCharacteristics(device));
|
|
741
731
|
const transport$1 = new BleTransport(device, writeCharacteristic, notifyCharacteristic);
|
|
742
|
-
|
|
743
|
-
transport$1.mtuSize = typeof device.mtu === 'number' ? device.mtu : transport$1.mtuSize;
|
|
744
|
-
}
|
|
732
|
+
transport$1.mtuSize = typeof device.mtu === 'number' ? device.mtu : undefined;
|
|
745
733
|
const monitorToken = this.nextMonitorToken;
|
|
746
734
|
this.nextMonitorToken += 1;
|
|
747
735
|
const notifyTransactionId = `${uuid}:notify:${monitorToken}`;
|
|
@@ -750,6 +738,7 @@ class ReactNativeBleTransport {
|
|
|
750
738
|
this.monitorTokens.set(uuid, monitorToken);
|
|
751
739
|
transport$1.notifySubscription = this._monitorCharacteristic(transport$1.notifyCharacteristic, uuid, monitorToken, notifyTransactionId);
|
|
752
740
|
transportCache[uuid] = transport$1;
|
|
741
|
+
this.protocolV2HighVolumeLogSignatures.set(uuid, new Set());
|
|
753
742
|
this.protocolV2Assemblers.set(uuid, new transport.ProtocolV2FrameAssembler(transport.PROTOCOL_V2_BLE_FRAME_MAX_BYTES));
|
|
754
743
|
if (reactNative.Platform.OS === 'ios') {
|
|
755
744
|
yield new Promise(resolve => {
|
|
@@ -759,6 +748,31 @@ class ReactNativeBleTransport {
|
|
|
759
748
|
else if (reactNative.Platform.OS === 'android') {
|
|
760
749
|
yield delay(ANDROID_NOTIFY_READY_DELAY_MS);
|
|
761
750
|
}
|
|
751
|
+
const initialMtu = transport$1.mtuSize;
|
|
752
|
+
let refreshAttempts = 0;
|
|
753
|
+
if ((reactNative.Platform.OS === 'ios' || reactNative.Platform.OS === 'android') &&
|
|
754
|
+
(typeof transport$1.mtuSize !== 'number' || transport$1.mtuSize < BLE_MTU_REFRESH_THRESHOLD)) {
|
|
755
|
+
refreshAttempts += 1;
|
|
756
|
+
let refreshedDevice = yield requestNegotiatedMtu(transport$1.device, 'servicesAndNotifyReady', 1);
|
|
757
|
+
transport$1.device = refreshedDevice;
|
|
758
|
+
transport$1.mtuSize =
|
|
759
|
+
typeof refreshedDevice.mtu === 'number' ? refreshedDevice.mtu : transport$1.mtuSize;
|
|
760
|
+
if (typeof transport$1.mtuSize !== 'number' || transport$1.mtuSize < BLE_MTU_REFRESH_THRESHOLD) {
|
|
761
|
+
yield delay(BLE_MTU_REFRESH_RETRY_DELAY_MS);
|
|
762
|
+
refreshAttempts += 1;
|
|
763
|
+
refreshedDevice = yield requestNegotiatedMtu(transport$1.device, 'servicesAndNotifyReady', 2);
|
|
764
|
+
transport$1.device = refreshedDevice;
|
|
765
|
+
transport$1.mtuSize =
|
|
766
|
+
typeof refreshedDevice.mtu === 'number' ? refreshedDevice.mtu : transport$1.mtuSize;
|
|
767
|
+
}
|
|
768
|
+
}
|
|
769
|
+
Log === null || Log === void 0 ? void 0 : Log.debug('[ReactNativeBleTransport] BLE MTU ready', {
|
|
770
|
+
platform: reactNative.Platform.OS,
|
|
771
|
+
requested: getRequestedBleMtu(),
|
|
772
|
+
initial: initialMtu,
|
|
773
|
+
actual: transport$1.mtuSize,
|
|
774
|
+
refreshAttempts,
|
|
775
|
+
});
|
|
762
776
|
return transport$1;
|
|
763
777
|
});
|
|
764
778
|
}
|
|
@@ -820,17 +834,14 @@ class ReactNativeBleTransport {
|
|
|
820
834
|
if (!device) {
|
|
821
835
|
Log === null || Log === void 0 ? void 0 : Log.debug('try to connect to device: ', uuid);
|
|
822
836
|
try {
|
|
823
|
-
device = yield
|
|
837
|
+
device = yield blePlxManager.connectToDevice(uuid, connectOptions);
|
|
824
838
|
}
|
|
825
839
|
catch (e) {
|
|
826
840
|
Log === null || Log === void 0 ? void 0 : Log.debug('try to connect to device has error: ', e);
|
|
827
|
-
if (isConnectTimeoutError(e)) {
|
|
828
|
-
throw e;
|
|
829
|
-
}
|
|
830
841
|
if (e.errorCode === reactNativeBlePlx.BleErrorCode.DeviceMTUChangeFailed ||
|
|
831
842
|
e.errorCode === reactNativeBlePlx.BleErrorCode.OperationCancelled) {
|
|
832
843
|
Log === null || Log === void 0 ? void 0 : Log.debug('first try to reconnect without params');
|
|
833
|
-
device = yield
|
|
844
|
+
device = yield blePlxManager.connectToDevice(uuid);
|
|
834
845
|
}
|
|
835
846
|
else if (e.errorCode === reactNativeBlePlx.BleErrorCode.DeviceAlreadyConnected) {
|
|
836
847
|
Log === null || Log === void 0 ? void 0 : Log.debug('device already connected');
|
|
@@ -846,27 +857,23 @@ class ReactNativeBleTransport {
|
|
|
846
857
|
}
|
|
847
858
|
if (!(yield device.isConnected())) {
|
|
848
859
|
Log === null || Log === void 0 ? void 0 : Log.debug('not connected, try to connect to device: ', uuid);
|
|
849
|
-
const disconnectedDevice = device;
|
|
850
860
|
try {
|
|
851
|
-
device = yield
|
|
861
|
+
device = yield device.connect(connectOptions);
|
|
852
862
|
}
|
|
853
863
|
catch (e) {
|
|
854
864
|
Log === null || Log === void 0 ? void 0 : Log.debug('not connected, try to connect to device has error: ', e);
|
|
855
|
-
if (isConnectTimeoutError(e)) {
|
|
856
|
-
throw e;
|
|
857
|
-
}
|
|
858
865
|
if (e.errorCode === reactNativeBlePlx.BleErrorCode.DeviceMTUChangeFailed ||
|
|
859
866
|
e.errorCode === reactNativeBlePlx.BleErrorCode.OperationCancelled) {
|
|
860
867
|
Log === null || Log === void 0 ? void 0 : Log.debug('second try to reconnect without params');
|
|
861
868
|
try {
|
|
862
|
-
device = yield
|
|
869
|
+
device = yield device.connect();
|
|
863
870
|
}
|
|
864
871
|
catch (e) {
|
|
865
872
|
Log === null || Log === void 0 ? void 0 : Log.debug('last try to reconnect error: ', e);
|
|
866
873
|
if (e.errorCode === reactNativeBlePlx.BleErrorCode.OperationCancelled) {
|
|
867
874
|
Log === null || Log === void 0 ? void 0 : Log.debug('last try to reconnect');
|
|
868
|
-
yield
|
|
869
|
-
device = yield
|
|
875
|
+
yield device.cancelConnection();
|
|
876
|
+
device = yield device.connect();
|
|
870
877
|
}
|
|
871
878
|
}
|
|
872
879
|
}
|
|
@@ -875,9 +882,9 @@ class ReactNativeBleTransport {
|
|
|
875
882
|
}
|
|
876
883
|
}
|
|
877
884
|
}
|
|
878
|
-
device = yield
|
|
885
|
+
device = yield resolveNegotiatedMtu(device);
|
|
879
886
|
const acquiredDevice = device;
|
|
880
|
-
const { writeCharacteristic, notifyCharacteristic } = yield this.
|
|
887
|
+
const { writeCharacteristic, notifyCharacteristic } = yield this.resolveCharacteristics(acquiredDevice);
|
|
881
888
|
const protocolHint = expectedProtocol
|
|
882
889
|
? undefined
|
|
883
890
|
: (_b = (_a = input.protocolHint) !== null && _a !== void 0 ? _a : this.deviceProtocolHints.get(uuid)) !== null && _b !== void 0 ? _b : inferProtocolHintFromDeviceName(getDeviceDisplayName(acquiredDevice));
|
|
@@ -897,7 +904,7 @@ class ReactNativeBleTransport {
|
|
|
897
904
|
if (!currentTransport) {
|
|
898
905
|
throw hdShared.ERRORS.TypedError(hdShared.HardwareErrorCode.TransportNotFound);
|
|
899
906
|
}
|
|
900
|
-
this.attachDisconnectSubscription(currentTransport,
|
|
907
|
+
this.attachDisconnectSubscription(currentTransport, currentTransport.device, uuid);
|
|
901
908
|
return { uuid, protocolType };
|
|
902
909
|
}
|
|
903
910
|
catch (error) {
|
|
@@ -922,7 +929,7 @@ class ReactNativeBleTransport {
|
|
|
922
929
|
Log === null || Log === void 0 ? void 0 : Log.debug('monitor error ignored for stale transport: ', uuid, notifyTransactionId);
|
|
923
930
|
return;
|
|
924
931
|
}
|
|
925
|
-
if (this.
|
|
932
|
+
if (this.deviceProtocol.get(uuid) === 'V2') {
|
|
926
933
|
let errorCode = hdShared.HardwareErrorCode.BleCharacteristicNotifyError;
|
|
927
934
|
if ((_a = error.reason) === null || _a === void 0 ? void 0 : _a.includes('The connection has timed out unexpectedly')) {
|
|
928
935
|
errorCode = hdShared.HardwareErrorCode.BleTimeoutError;
|
|
@@ -973,7 +980,7 @@ class ReactNativeBleTransport {
|
|
|
973
980
|
}
|
|
974
981
|
try {
|
|
975
982
|
const data = buffer.Buffer.from(c.value, 'base64');
|
|
976
|
-
const protocol = this.
|
|
983
|
+
const protocol = this.deviceProtocol.get(uuid);
|
|
977
984
|
if (!protocol) {
|
|
978
985
|
Log === null || Log === void 0 ? void 0 : Log.debug('monitor data ignored before protocol detection: ', uuid);
|
|
979
986
|
return;
|
|
@@ -1001,7 +1008,7 @@ class ReactNativeBleTransport {
|
|
|
1001
1008
|
catch (error) {
|
|
1002
1009
|
Log === null || Log === void 0 ? void 0 : Log.debug('monitor data error: ', error);
|
|
1003
1010
|
const notifyError = hdShared.ERRORS.TypedError(hdShared.HardwareErrorCode.BleWriteCharacteristicError);
|
|
1004
|
-
if (this.
|
|
1011
|
+
if (this.deviceProtocol.get(uuid) === 'V2') {
|
|
1005
1012
|
this.rejectProtocolV2Frames(uuid, notifyError);
|
|
1006
1013
|
}
|
|
1007
1014
|
else if (this.runPromiseDeviceId === uuid) {
|
|
@@ -1036,6 +1043,7 @@ class ReactNativeBleTransport {
|
|
|
1036
1043
|
this.resetProtocolV2Frames(uuid);
|
|
1037
1044
|
return Promise.resolve(true);
|
|
1038
1045
|
}
|
|
1046
|
+
yield this.restoreAndroidConnectionPriority(uuid, transport);
|
|
1039
1047
|
if (transport) {
|
|
1040
1048
|
if (this.monitorTokens.get(uuid) === transport.monitorToken) {
|
|
1041
1049
|
this.monitorTokens.delete(uuid);
|
|
@@ -1056,8 +1064,8 @@ class ReactNativeBleTransport {
|
|
|
1056
1064
|
}
|
|
1057
1065
|
delete transportCache[uuid];
|
|
1058
1066
|
}
|
|
1067
|
+
this.protocolV2HighVolumeLogSignatures.delete(uuid);
|
|
1059
1068
|
this.deviceProtocol.delete(uuid);
|
|
1060
|
-
this.probingProtocols.delete(uuid);
|
|
1061
1069
|
(_f = this.protocolV2Assemblers.get(uuid)) === null || _f === void 0 ? void 0 : _f.reset();
|
|
1062
1070
|
this.protocolV2Assemblers.delete(uuid);
|
|
1063
1071
|
this.resetProtocolV2Frames(uuid);
|
|
@@ -1106,19 +1114,8 @@ class ReactNativeBleTransport {
|
|
|
1106
1114
|
const transport = this.getCachedTransport(uuid);
|
|
1107
1115
|
const runPromise = hdShared.createDeferred();
|
|
1108
1116
|
runPromise.promise.catch(() => undefined);
|
|
1109
|
-
const supersededRunPromise = this.runPromise;
|
|
1110
|
-
if (supersededRunPromise) {
|
|
1111
|
-
supersededRunPromise.reject(hdShared.ERRORS.TypedError(hdShared.HardwareErrorCode.BleForceCleanRunPromise));
|
|
1112
|
-
}
|
|
1113
1117
|
this.runPromise = runPromise;
|
|
1114
1118
|
this.runPromiseDeviceId = uuid;
|
|
1115
|
-
const releaseOwnershipIfCurrent = () => {
|
|
1116
|
-
if (this.runPromise === runPromise) {
|
|
1117
|
-
this.runPromise = null;
|
|
1118
|
-
this.runPromiseDeviceId = null;
|
|
1119
|
-
}
|
|
1120
|
-
};
|
|
1121
|
-
const isCurrentOwner = () => this.runPromise === runPromise;
|
|
1122
1119
|
const messages = this._messages;
|
|
1123
1120
|
const buffers = ProtocolV1.encodeTransportPackets(messages, name, data);
|
|
1124
1121
|
let timeout;
|
|
@@ -1139,9 +1136,6 @@ class ReactNativeBleTransport {
|
|
|
1139
1136
|
}
|
|
1140
1137
|
catch (e) {
|
|
1141
1138
|
onError(e);
|
|
1142
|
-
if (isWedgedWriteError(e)) {
|
|
1143
|
-
throw e;
|
|
1144
|
-
}
|
|
1145
1139
|
throw hdShared.ERRORS.TypedError(hdShared.HardwareErrorCode.BleWriteCharacteristicError);
|
|
1146
1140
|
}
|
|
1147
1141
|
}
|
|
@@ -1169,9 +1163,6 @@ class ReactNativeBleTransport {
|
|
|
1169
1163
|
}
|
|
1170
1164
|
catch (e) {
|
|
1171
1165
|
onError(e);
|
|
1172
|
-
if (isWedgedWriteError(e)) {
|
|
1173
|
-
throw e;
|
|
1174
|
-
}
|
|
1175
1166
|
throw hdShared.ERRORS.TypedError(hdShared.HardwareErrorCode.BleWriteCharacteristicError);
|
|
1176
1167
|
}
|
|
1177
1168
|
}
|
|
@@ -1182,8 +1173,8 @@ class ReactNativeBleTransport {
|
|
|
1182
1173
|
});
|
|
1183
1174
|
}
|
|
1184
1175
|
if (name === 'EmmcFileWrite') {
|
|
1185
|
-
yield writeChunkedData(buffers, data =>
|
|
1186
|
-
|
|
1176
|
+
yield writeChunkedData(buffers, data => transport.writeWithRetry(data), e => {
|
|
1177
|
+
this.runPromise = null;
|
|
1187
1178
|
Log === null || Log === void 0 ? void 0 : Log.error('writeCharacteristic write error: ', e);
|
|
1188
1179
|
});
|
|
1189
1180
|
}
|
|
@@ -1199,7 +1190,7 @@ class ReactNativeBleTransport {
|
|
|
1199
1190
|
let attempt = 0;
|
|
1200
1191
|
while (true) {
|
|
1201
1192
|
try {
|
|
1202
|
-
yield
|
|
1193
|
+
yield transport.writeWithRetry(data);
|
|
1203
1194
|
return;
|
|
1204
1195
|
}
|
|
1205
1196
|
catch (error) {
|
|
@@ -1218,7 +1209,7 @@ class ReactNativeBleTransport {
|
|
|
1218
1209
|
}
|
|
1219
1210
|
}
|
|
1220
1211
|
}), e => {
|
|
1221
|
-
|
|
1212
|
+
this.runPromise = null;
|
|
1222
1213
|
Log === null || Log === void 0 ? void 0 : Log.error('writeCharacteristic write error: ', e);
|
|
1223
1214
|
});
|
|
1224
1215
|
}
|
|
@@ -1227,16 +1218,16 @@ class ReactNativeBleTransport {
|
|
|
1227
1218
|
const outData = o.toString('base64');
|
|
1228
1219
|
try {
|
|
1229
1220
|
const shouldUseWriteWithResponse = reactNative.Platform.OS === 'ios' && transport.writeCharacteristic.isWritableWithResponse;
|
|
1230
|
-
|
|
1231
|
-
|
|
1232
|
-
|
|
1221
|
+
if (shouldUseWriteWithResponse) {
|
|
1222
|
+
yield transport.writeCharacteristic.writeWithResponse(outData);
|
|
1223
|
+
}
|
|
1224
|
+
else {
|
|
1225
|
+
yield transport.writeCharacteristic.writeWithoutResponse(outData);
|
|
1226
|
+
}
|
|
1233
1227
|
}
|
|
1234
1228
|
catch (e) {
|
|
1235
1229
|
Log === null || Log === void 0 ? void 0 : Log.debug('writeCharacteristic write error: ', e);
|
|
1236
|
-
|
|
1237
|
-
if (isWedgedWriteError(e)) {
|
|
1238
|
-
throw e;
|
|
1239
|
-
}
|
|
1230
|
+
this.runPromise = null;
|
|
1240
1231
|
if (e.errorCode === reactNativeBlePlx.BleErrorCode.DeviceDisconnected) {
|
|
1241
1232
|
throw hdShared.ERRORS.TypedError(hdShared.HardwareErrorCode.BleDeviceNotBonded);
|
|
1242
1233
|
}
|
|
@@ -1276,9 +1267,7 @@ class ReactNativeBleTransport {
|
|
|
1276
1267
|
Log === null || Log === void 0 ? void 0 : Log.error('call error: ', e);
|
|
1277
1268
|
}
|
|
1278
1269
|
const isProbeTimeout = name === 'GetFeatures' && (options === null || options === void 0 ? void 0 : options.timeoutMs) === PROTOCOL_PROBE_TIMEOUT_MS;
|
|
1279
|
-
const isStaleCall = this.runPromise !== runPromise;
|
|
1280
1270
|
if (!isProbeTimeout &&
|
|
1281
|
-
!isStaleCall &&
|
|
1282
1271
|
(e === null || e === void 0 ? void 0 : e.errorCode) === hdShared.HardwareErrorCode.BleTimeoutError) {
|
|
1283
1272
|
yield this.disconnect(uuid);
|
|
1284
1273
|
}
|
|
@@ -1349,10 +1338,7 @@ class ReactNativeBleTransport {
|
|
|
1349
1338
|
delete transportCache[session];
|
|
1350
1339
|
}
|
|
1351
1340
|
this.deviceProtocol.delete(session);
|
|
1352
|
-
this.probingProtocols.delete(session);
|
|
1353
1341
|
this.deviceProtocolHints.delete(session);
|
|
1354
|
-
this.sessionProtocols.delete(session);
|
|
1355
|
-
this.protocolReprobeFailures.delete(session);
|
|
1356
1342
|
this.protocolV2Assemblers.delete(session);
|
|
1357
1343
|
this.resetProtocolV2Frames(session);
|
|
1358
1344
|
try {
|
|
@@ -1373,91 +1359,6 @@ class ReactNativeBleTransport {
|
|
|
1373
1359
|
this.runPromise = null;
|
|
1374
1360
|
this.runPromiseDeviceId = null;
|
|
1375
1361
|
}
|
|
1376
|
-
connectWithTimeout(uuid, connect) {
|
|
1377
|
-
return __awaiter(this, void 0, void 0, function* () {
|
|
1378
|
-
let timer;
|
|
1379
|
-
let timedOut = false;
|
|
1380
|
-
const pending = connect();
|
|
1381
|
-
pending.catch(() => undefined);
|
|
1382
|
-
try {
|
|
1383
|
-
const result = yield Promise.race([
|
|
1384
|
-
pending,
|
|
1385
|
-
new Promise((_, reject) => {
|
|
1386
|
-
timer = setTimeout(() => {
|
|
1387
|
-
timedOut = true;
|
|
1388
|
-
reject(hdShared.ERRORS.TypedError(hdShared.HardwareErrorCode.BleConnectedError, `BLE connect timeout after ${BLE_CONNECT_TIMEOUT_MS}ms for ${uuid}`));
|
|
1389
|
-
}, BLE_CONNECT_TIMEOUT_MS);
|
|
1390
|
-
}),
|
|
1391
|
-
]);
|
|
1392
|
-
return result;
|
|
1393
|
-
}
|
|
1394
|
-
catch (error) {
|
|
1395
|
-
if (timedOut || isNativeOperationTimeoutError(error)) {
|
|
1396
|
-
this.abandonStalledConnection(uuid, timedOut ? 'connect-backstop' : 'connect-native');
|
|
1397
|
-
}
|
|
1398
|
-
throw error;
|
|
1399
|
-
}
|
|
1400
|
-
finally {
|
|
1401
|
-
if (timer)
|
|
1402
|
-
clearTimeout(timer);
|
|
1403
|
-
}
|
|
1404
|
-
});
|
|
1405
|
-
}
|
|
1406
|
-
resolveCharacteristicsWithTimeout(uuid, device) {
|
|
1407
|
-
return __awaiter(this, void 0, void 0, function* () {
|
|
1408
|
-
let timer;
|
|
1409
|
-
let timedOut = false;
|
|
1410
|
-
const pending = this.resolveCharacteristics(device);
|
|
1411
|
-
pending.catch(() => undefined);
|
|
1412
|
-
try {
|
|
1413
|
-
const result = yield Promise.race([
|
|
1414
|
-
pending,
|
|
1415
|
-
new Promise((_, reject) => {
|
|
1416
|
-
timer = setTimeout(() => {
|
|
1417
|
-
timedOut = true;
|
|
1418
|
-
reject(hdShared.ERRORS.TypedError(hdShared.HardwareErrorCode.BleConnectedError, `BLE GATT setup timeout after ${BLE_GATT_SETUP_TIMEOUT_MS}ms for ${uuid}`));
|
|
1419
|
-
}, BLE_GATT_SETUP_TIMEOUT_MS);
|
|
1420
|
-
}),
|
|
1421
|
-
]);
|
|
1422
|
-
this.connectionSetupTimeoutCounts.delete(uuid);
|
|
1423
|
-
return result;
|
|
1424
|
-
}
|
|
1425
|
-
catch (error) {
|
|
1426
|
-
if (timedOut || isNativeOperationTimeoutError(error)) {
|
|
1427
|
-
this.abandonStalledConnection(uuid, timedOut ? 'gatt-backstop' : 'gatt-native');
|
|
1428
|
-
}
|
|
1429
|
-
throw error;
|
|
1430
|
-
}
|
|
1431
|
-
finally {
|
|
1432
|
-
if (timer)
|
|
1433
|
-
clearTimeout(timer);
|
|
1434
|
-
}
|
|
1435
|
-
});
|
|
1436
|
-
}
|
|
1437
|
-
abandonStalledConnection(uuid, stage) {
|
|
1438
|
-
var _a, _b;
|
|
1439
|
-
const timeouts = ((_a = this.connectionSetupTimeoutCounts.get(uuid)) !== null && _a !== void 0 ? _a : 0) + 1;
|
|
1440
|
-
this.connectionSetupTimeoutCounts.set(uuid, timeouts);
|
|
1441
|
-
Log === null || Log === void 0 ? void 0 : Log.error('[ReactNativeBleTransport] BLE setup timed out:', uuid, {
|
|
1442
|
-
stage,
|
|
1443
|
-
setupTimeoutsSinceSuccess: timeouts,
|
|
1444
|
-
});
|
|
1445
|
-
(_b = this.blePlxManager) === null || _b === void 0 ? void 0 : _b.cancelDeviceConnection(uuid).catch(() => {
|
|
1446
|
-
});
|
|
1447
|
-
const stalled = transportCache[uuid];
|
|
1448
|
-
if (stalled) {
|
|
1449
|
-
delete transportCache[uuid];
|
|
1450
|
-
}
|
|
1451
|
-
this.deviceProtocol.delete(uuid);
|
|
1452
|
-
this.probingProtocols.delete(uuid);
|
|
1453
|
-
this.protocolV2Assemblers.delete(uuid);
|
|
1454
|
-
this.resetProtocolV2Frames(uuid);
|
|
1455
|
-
if (timeouts >= BLE_CONNECT_TIMEOUT_MANAGER_RESET_THRESHOLD) {
|
|
1456
|
-
Log === null || Log === void 0 ? void 0 : Log.error('[ReactNativeBleTransport] BLE setup wedged repeatedly, resetting BLE manager');
|
|
1457
|
-
this.resetPlxManager();
|
|
1458
|
-
this.connectionSetupTimeoutCounts.delete(uuid);
|
|
1459
|
-
}
|
|
1460
|
-
}
|
|
1461
1362
|
getCachedTransport(uuid) {
|
|
1462
1363
|
const transport = transportCache[uuid];
|
|
1463
1364
|
if (!transport) {
|
|
@@ -1465,82 +1366,6 @@ class ReactNativeBleTransport {
|
|
|
1465
1366
|
}
|
|
1466
1367
|
return transport;
|
|
1467
1368
|
}
|
|
1468
|
-
writeBlePacket(uuid, data, write, isCurrentOwner) {
|
|
1469
|
-
return __awaiter(this, void 0, void 0, function* () {
|
|
1470
|
-
let timer;
|
|
1471
|
-
let timedOut = false;
|
|
1472
|
-
try {
|
|
1473
|
-
yield Promise.race([
|
|
1474
|
-
write(data),
|
|
1475
|
-
new Promise((_, reject) => {
|
|
1476
|
-
timer = setTimeout(() => {
|
|
1477
|
-
timedOut = true;
|
|
1478
|
-
reject(hdShared.ERRORS.TypedError(hdShared.HardwareErrorCode.BleWriteCharacteristicError, `BLE write timeout after ${BLE_WRITE_PACKET_TIMEOUT_MS}ms`));
|
|
1479
|
-
}, BLE_WRITE_PACKET_TIMEOUT_MS);
|
|
1480
|
-
}),
|
|
1481
|
-
]);
|
|
1482
|
-
this.writeTimeoutCounts.delete(uuid);
|
|
1483
|
-
}
|
|
1484
|
-
catch (error) {
|
|
1485
|
-
if (timedOut) {
|
|
1486
|
-
if (isCurrentOwner && !isCurrentOwner()) {
|
|
1487
|
-
Log === null || Log === void 0 ? void 0 : Log.debug('[ReactNativeBleTransport] stale BLE write timed out, link kept:', uuid);
|
|
1488
|
-
}
|
|
1489
|
-
else {
|
|
1490
|
-
this.tearDownWedgedLink(uuid);
|
|
1491
|
-
}
|
|
1492
|
-
}
|
|
1493
|
-
throw error;
|
|
1494
|
-
}
|
|
1495
|
-
finally {
|
|
1496
|
-
if (timer)
|
|
1497
|
-
clearTimeout(timer);
|
|
1498
|
-
}
|
|
1499
|
-
});
|
|
1500
|
-
}
|
|
1501
|
-
tearDownWedgedLink(uuid) {
|
|
1502
|
-
var _a;
|
|
1503
|
-
const timeouts = ((_a = this.writeTimeoutCounts.get(uuid)) !== null && _a !== void 0 ? _a : 0) + 1;
|
|
1504
|
-
this.writeTimeoutCounts.set(uuid, timeouts);
|
|
1505
|
-
Log === null || Log === void 0 ? void 0 : Log.error('[ReactNativeBleTransport] BLE write timed out, tearing down link:', uuid, {
|
|
1506
|
-
consecutiveWriteTimeouts: timeouts,
|
|
1507
|
-
});
|
|
1508
|
-
const wedged = transportCache[uuid];
|
|
1509
|
-
this.disconnect(uuid).catch(error => {
|
|
1510
|
-
Log === null || Log === void 0 ? void 0 : Log.debug('[ReactNativeBleTransport] wedged link teardown failed (ignored):', error);
|
|
1511
|
-
});
|
|
1512
|
-
if (wedged && transportCache[uuid] === wedged) {
|
|
1513
|
-
delete transportCache[uuid];
|
|
1514
|
-
}
|
|
1515
|
-
this.deviceProtocol.delete(uuid);
|
|
1516
|
-
this.probingProtocols.delete(uuid);
|
|
1517
|
-
this.protocolV2Assemblers.delete(uuid);
|
|
1518
|
-
this.resetProtocolV2Frames(uuid);
|
|
1519
|
-
if (timeouts >= BLE_WRITE_TIMEOUT_MANAGER_RESET_THRESHOLD) {
|
|
1520
|
-
Log === null || Log === void 0 ? void 0 : Log.error('[ReactNativeBleTransport] BLE writes wedged repeatedly, resetting BLE manager');
|
|
1521
|
-
this.resetPlxManager();
|
|
1522
|
-
this.writeTimeoutCounts.delete(uuid);
|
|
1523
|
-
}
|
|
1524
|
-
}
|
|
1525
|
-
resetPlxManager() {
|
|
1526
|
-
const manager = this.blePlxManager;
|
|
1527
|
-
this.blePlxManager = undefined;
|
|
1528
|
-
Object.keys(transportCache).forEach(key => {
|
|
1529
|
-
delete transportCache[key];
|
|
1530
|
-
});
|
|
1531
|
-
this.deviceProtocol.clear();
|
|
1532
|
-
this.probingProtocols.clear();
|
|
1533
|
-
this.sessionProtocols.clear();
|
|
1534
|
-
this.protocolReprobeFailures.clear();
|
|
1535
|
-
this.monitorTokens.clear();
|
|
1536
|
-
this.protocolV2Assemblers.clear();
|
|
1537
|
-
try {
|
|
1538
|
-
manager === null || manager === void 0 ? void 0 : manager.destroy();
|
|
1539
|
-
}
|
|
1540
|
-
catch (error) {
|
|
1541
|
-
Log === null || Log === void 0 ? void 0 : Log.debug('[ReactNativeBleTransport] BLE manager destroy failed (ignored):', error);
|
|
1542
|
-
}
|
|
1543
|
-
}
|
|
1544
1369
|
createProtocolMismatchError(expected) {
|
|
1545
1370
|
return hdShared.ERRORS.TypedError(hdShared.HardwareErrorCode.RuntimeError, `Device protocol mismatch: expected ${expected}, but device did not respond to expected protocol`);
|
|
1546
1371
|
}
|
|
@@ -1548,19 +1373,11 @@ class ReactNativeBleTransport {
|
|
|
1548
1373
|
return hdShared.ERRORS.TypedError(hdShared.HardwareErrorCode.BleTimeoutError, 'Unable to detect BLE protocol: device did not respond to Protocol V1 GetFeatures or Protocol V2 Ping');
|
|
1549
1374
|
}
|
|
1550
1375
|
clearProbeProtocol(uuid, protocol) {
|
|
1551
|
-
if (this.probingProtocols.get(uuid) === protocol) {
|
|
1552
|
-
this.probingProtocols.delete(uuid);
|
|
1553
|
-
}
|
|
1554
1376
|
if (this.deviceProtocol.get(uuid) === protocol) {
|
|
1555
1377
|
this.deviceProtocol.delete(uuid);
|
|
1556
1378
|
}
|
|
1557
1379
|
}
|
|
1558
|
-
getActiveProtocol(uuid) {
|
|
1559
|
-
var _a;
|
|
1560
|
-
return (_a = this.deviceProtocol.get(uuid)) !== null && _a !== void 0 ? _a : this.probingProtocols.get(uuid);
|
|
1561
|
-
}
|
|
1562
1380
|
detectProtocol(uuid, expectedProtocol, protocolHint, rebuildTransport) {
|
|
1563
|
-
var _a;
|
|
1564
1381
|
return __awaiter(this, void 0, void 0, function* () {
|
|
1565
1382
|
if (reactNative.Platform.OS === 'ios' && expectedProtocol) {
|
|
1566
1383
|
this.deviceProtocol.set(uuid, expectedProtocol);
|
|
@@ -1574,7 +1391,6 @@ class ReactNativeBleTransport {
|
|
|
1574
1391
|
if (expectedProtocol === 'V1') {
|
|
1575
1392
|
if (yield this.probeProtocolV1(uuid)) {
|
|
1576
1393
|
this.deviceProtocol.set(uuid, 'V1');
|
|
1577
|
-
this.sessionProtocols.set(uuid, 'V1');
|
|
1578
1394
|
Log === null || Log === void 0 ? void 0 : Log.debug('[ReactNativeBleTransport] protocol detected', {
|
|
1579
1395
|
deviceId: uuid,
|
|
1580
1396
|
protocol: 'V1',
|
|
@@ -1587,7 +1403,6 @@ class ReactNativeBleTransport {
|
|
|
1587
1403
|
if (expectedProtocol === 'V2') {
|
|
1588
1404
|
if (yield this.probeProtocolV2(uuid)) {
|
|
1589
1405
|
this.deviceProtocol.set(uuid, 'V2');
|
|
1590
|
-
this.sessionProtocols.set(uuid, 'V2');
|
|
1591
1406
|
Log === null || Log === void 0 ? void 0 : Log.debug('[ReactNativeBleTransport] protocol detected', {
|
|
1592
1407
|
deviceId: uuid,
|
|
1593
1408
|
protocol: 'V2',
|
|
@@ -1597,13 +1412,7 @@ class ReactNativeBleTransport {
|
|
|
1597
1412
|
}
|
|
1598
1413
|
throw this.createProtocolMismatchError(expectedProtocol);
|
|
1599
1414
|
}
|
|
1600
|
-
const
|
|
1601
|
-
const reprobeFailures = (_a = this.protocolReprobeFailures.get(uuid)) !== null && _a !== void 0 ? _a : 0;
|
|
1602
|
-
const fullProbeOrder = protocolHint === 'V2' || this.deviceProtocol.get(uuid) === 'V2' ? ['V2', 'V1'] : ['V1', 'V2'];
|
|
1603
|
-
const trustSessionProtocol = sessionProtocol !== undefined &&
|
|
1604
|
-
!protocolHint &&
|
|
1605
|
-
reprobeFailures < PROTOCOL_REPROBE_FALLBACK_ATTEMPTS;
|
|
1606
|
-
const probeOrder = trustSessionProtocol ? [sessionProtocol] : fullProbeOrder;
|
|
1415
|
+
const probeOrder = protocolHint === 'V2' || this.deviceProtocol.get(uuid) === 'V2' ? ['V2', 'V1'] : ['V1', 'V2'];
|
|
1607
1416
|
for (let i = 0; i < probeOrder.length; i += 1) {
|
|
1608
1417
|
const protocol = probeOrder[i];
|
|
1609
1418
|
if (i > 0) {
|
|
@@ -1618,8 +1427,6 @@ class ReactNativeBleTransport {
|
|
|
1618
1427
|
const detected = protocol === 'V1' ? yield this.probeProtocolV1(uuid) : yield this.probeProtocolV2(uuid);
|
|
1619
1428
|
if (detected) {
|
|
1620
1429
|
this.deviceProtocol.set(uuid, protocol);
|
|
1621
|
-
this.sessionProtocols.set(uuid, protocol);
|
|
1622
|
-
this.protocolReprobeFailures.delete(uuid);
|
|
1623
1430
|
Log === null || Log === void 0 ? void 0 : Log.debug('[ReactNativeBleTransport] protocol detected', {
|
|
1624
1431
|
deviceId: uuid,
|
|
1625
1432
|
protocol,
|
|
@@ -1628,14 +1435,7 @@ class ReactNativeBleTransport {
|
|
|
1628
1435
|
return protocol;
|
|
1629
1436
|
}
|
|
1630
1437
|
}
|
|
1631
|
-
if (trustSessionProtocol) {
|
|
1632
|
-
this.protocolReprobeFailures.set(uuid, reprobeFailures + 1);
|
|
1633
|
-
}
|
|
1634
|
-
else {
|
|
1635
|
-
this.protocolReprobeFailures.delete(uuid);
|
|
1636
|
-
}
|
|
1637
1438
|
this.deviceProtocol.delete(uuid);
|
|
1638
|
-
this.probingProtocols.delete(uuid);
|
|
1639
1439
|
throw this.createProtocolDetectionError();
|
|
1640
1440
|
});
|
|
1641
1441
|
}
|
|
@@ -1687,17 +1487,13 @@ class ReactNativeBleTransport {
|
|
|
1687
1487
|
return false;
|
|
1688
1488
|
}
|
|
1689
1489
|
try {
|
|
1690
|
-
this.
|
|
1490
|
+
this.deviceProtocol.set(uuid, 'V1');
|
|
1691
1491
|
yield this.callProtocolV1(uuid, 'GetFeatures', {}, { timeoutMs: PROTOCOL_PROBE_TIMEOUT_MS });
|
|
1692
|
-
this.probingProtocols.delete(uuid);
|
|
1693
1492
|
return true;
|
|
1694
1493
|
}
|
|
1695
1494
|
catch (error) {
|
|
1696
1495
|
this.clearProbeProtocol(uuid, 'V1');
|
|
1697
1496
|
Log === null || Log === void 0 ? void 0 : Log.debug('[ReactNativeBleTransport] Protocol V1 GetFeatures probe failed:', error);
|
|
1698
|
-
if (isWedgedWriteError(error)) {
|
|
1699
|
-
throw error;
|
|
1700
|
-
}
|
|
1701
1497
|
return false;
|
|
1702
1498
|
}
|
|
1703
1499
|
});
|
|
@@ -1708,7 +1504,7 @@ class ReactNativeBleTransport {
|
|
|
1708
1504
|
if (!this._messages || !this._messagesV2) {
|
|
1709
1505
|
return false;
|
|
1710
1506
|
}
|
|
1711
|
-
this.
|
|
1507
|
+
this.deviceProtocol.set(uuid, 'V2');
|
|
1712
1508
|
(_a = this.protocolV2Assemblers.get(uuid)) === null || _a === void 0 ? void 0 : _a.reset();
|
|
1713
1509
|
const detected = yield transport.probeProtocolV2({
|
|
1714
1510
|
call: (name, data, options) => this.callProtocolV2(uuid, name, data, options),
|
|
@@ -1724,9 +1520,6 @@ class ReactNativeBleTransport {
|
|
|
1724
1520
|
if (!detected) {
|
|
1725
1521
|
this.clearProbeProtocol(uuid, 'V2');
|
|
1726
1522
|
}
|
|
1727
|
-
else {
|
|
1728
|
-
this.probingProtocols.delete(uuid);
|
|
1729
|
-
}
|
|
1730
1523
|
return detected;
|
|
1731
1524
|
});
|
|
1732
1525
|
}
|
|
@@ -1798,10 +1591,14 @@ class ReactNativeBleTransport {
|
|
|
1798
1591
|
}
|
|
1799
1592
|
});
|
|
1800
1593
|
}
|
|
1801
|
-
writeProtocolV2Packet(
|
|
1594
|
+
writeProtocolV2Packet(transport, base64, context, assertCurrentGeneration) {
|
|
1802
1595
|
return __awaiter(this, void 0, void 0, function* () {
|
|
1803
|
-
const shouldUseWriteWithResponse =
|
|
1804
|
-
|
|
1596
|
+
const shouldUseWriteWithResponse = shouldWriteProtocolV2WithResponse({
|
|
1597
|
+
platform: reactNative.Platform.OS,
|
|
1598
|
+
highVolume: context.highVolume,
|
|
1599
|
+
requestedWithResponse: context.writeWithResponse,
|
|
1600
|
+
characteristic: transport.writeCharacteristic,
|
|
1601
|
+
});
|
|
1805
1602
|
let attempt = 0;
|
|
1806
1603
|
for (;;) {
|
|
1807
1604
|
assertCurrentGeneration();
|
|
@@ -1809,17 +1606,12 @@ class ReactNativeBleTransport {
|
|
|
1809
1606
|
throw new Error(`Protocol V2 BLE write aborted for ${context.messageName}`);
|
|
1810
1607
|
}
|
|
1811
1608
|
try {
|
|
1812
|
-
|
|
1813
|
-
|
|
1814
|
-
|
|
1815
|
-
|
|
1816
|
-
|
|
1817
|
-
|
|
1818
|
-
}
|
|
1819
|
-
catch (_a) {
|
|
1820
|
-
return false;
|
|
1821
|
-
}
|
|
1822
|
-
});
|
|
1609
|
+
if (shouldUseWriteWithResponse) {
|
|
1610
|
+
yield transport.writeCharacteristic.writeWithResponse(base64);
|
|
1611
|
+
}
|
|
1612
|
+
else {
|
|
1613
|
+
yield transport.writeCharacteristic.writeWithoutResponse(base64);
|
|
1614
|
+
}
|
|
1823
1615
|
assertCurrentGeneration();
|
|
1824
1616
|
return;
|
|
1825
1617
|
}
|
|
@@ -1840,34 +1632,28 @@ class ReactNativeBleTransport {
|
|
|
1840
1632
|
}
|
|
1841
1633
|
});
|
|
1842
1634
|
}
|
|
1843
|
-
writeProtocolV2Frame(
|
|
1635
|
+
writeProtocolV2Frame(transport$1, frame, context, assertCurrentGeneration) {
|
|
1844
1636
|
return __awaiter(this, void 0, void 0, function* () {
|
|
1845
1637
|
const tuning = getProtocolV2BleTuning();
|
|
1846
1638
|
const packetCapacity = resolveProtocolV2PacketCapacity({
|
|
1847
1639
|
platform: reactNative.Platform.OS,
|
|
1848
1640
|
iosPacketLength: tuning.iosPacketLength,
|
|
1849
1641
|
androidPacketLength: tuning.androidPacketLength,
|
|
1850
|
-
mtu:
|
|
1642
|
+
mtu: transport$1.mtuSize,
|
|
1851
1643
|
});
|
|
1852
|
-
const initialDelayMs = reactNative.Platform.OS === 'ios' && !context.highVolume && frame.length <= packetCapacity
|
|
1853
|
-
? IOS_PROTOCOL_V2_CONTROL_WRITE_DELAY_MS
|
|
1854
|
-
: 0;
|
|
1855
1644
|
yield transport.writeProtocolV2BleFrame({
|
|
1856
1645
|
frame,
|
|
1857
1646
|
packetCapacity,
|
|
1858
1647
|
assertActive: assertCurrentGeneration,
|
|
1859
1648
|
signal: context.signal,
|
|
1860
1649
|
abortMessage: `Protocol V2 BLE write aborted for ${context.messageName}`,
|
|
1861
|
-
initialDelayMs,
|
|
1862
|
-
burstSize: FIRMWARE_UPLOAD_WRITE_BURST_SIZE,
|
|
1863
|
-
burstPauseMs: FIRMWARE_UPLOAD_WRITE_PAUSE_MS,
|
|
1864
|
-
flushDelayMs: FIRMWARE_UPLOAD_WRITE_FLUSH_DELAY_MS,
|
|
1865
1650
|
wait: delay,
|
|
1866
|
-
writePacket: packet => this.writeProtocolV2Packet(
|
|
1651
|
+
writePacket: packet => this.writeProtocolV2Packet(transport$1, buffer.Buffer.from(packet).toString('base64'), context, assertCurrentGeneration),
|
|
1867
1652
|
});
|
|
1868
1653
|
});
|
|
1869
1654
|
}
|
|
1870
1655
|
callProtocolV2(uuid, name, data, options) {
|
|
1656
|
+
var _a;
|
|
1871
1657
|
return __awaiter(this, void 0, void 0, function* () {
|
|
1872
1658
|
if (!this._messages || !this._messagesV2) {
|
|
1873
1659
|
throw hdShared.ERRORS.TypedError(hdShared.HardwareErrorCode.TransportNotConfigured);
|
|
@@ -1876,11 +1662,35 @@ class ReactNativeBleTransport {
|
|
|
1876
1662
|
const highVolumeWrite = transport.LogBlockCommand.has(name);
|
|
1877
1663
|
if (highVolumeWrite) {
|
|
1878
1664
|
const tuning = getProtocolV2BleTuning();
|
|
1879
|
-
|
|
1880
|
-
|
|
1881
|
-
|
|
1882
|
-
|
|
1665
|
+
const currentTransport = this.getCachedTransport(uuid);
|
|
1666
|
+
const writeWithResponse = shouldWriteProtocolV2WithResponse({
|
|
1667
|
+
platform: reactNative.Platform.OS,
|
|
1668
|
+
highVolume: true,
|
|
1669
|
+
requestedWithResponse: options === null || options === void 0 ? void 0 : options.writeWithResponse,
|
|
1670
|
+
characteristic: currentTransport.writeCharacteristic,
|
|
1883
1671
|
});
|
|
1672
|
+
const packetCapacity = resolveProtocolV2PacketCapacity({
|
|
1673
|
+
platform: reactNative.Platform.OS,
|
|
1674
|
+
iosPacketLength: tuning.iosPacketLength,
|
|
1675
|
+
androidPacketLength: tuning.androidPacketLength,
|
|
1676
|
+
mtu: currentTransport.mtuSize,
|
|
1677
|
+
});
|
|
1678
|
+
const writeMode = writeWithResponse ? 'withResponse' : 'withoutResponse';
|
|
1679
|
+
const logSignature = `${name}:${writeMode}:${String(currentTransport.mtuSize)}:${packetCapacity}`;
|
|
1680
|
+
const loggedSignatures = (_a = this.protocolV2HighVolumeLogSignatures.get(uuid)) !== null && _a !== void 0 ? _a : new Set();
|
|
1681
|
+
if (!loggedSignatures.has(logSignature)) {
|
|
1682
|
+
loggedSignatures.add(logSignature);
|
|
1683
|
+
this.protocolV2HighVolumeLogSignatures.set(uuid, loggedSignatures);
|
|
1684
|
+
Log === null || Log === void 0 ? void 0 : Log.debug('[ReactNativeBleTransport] Protocol V2 high-volume write configured', {
|
|
1685
|
+
name,
|
|
1686
|
+
writeMode,
|
|
1687
|
+
reportedMtu: currentTransport.mtuSize,
|
|
1688
|
+
packetCapacity,
|
|
1689
|
+
});
|
|
1690
|
+
}
|
|
1691
|
+
}
|
|
1692
|
+
if (highVolumeWrite) {
|
|
1693
|
+
yield this.enableAndroidHighConnectionPriority(uuid);
|
|
1884
1694
|
}
|
|
1885
1695
|
try {
|
|
1886
1696
|
return yield this.protocolV2Links.call(uuid, () => this.createProtocolV2Adapter(uuid), name, data, callOptions);
|
|
@@ -1889,6 +1699,71 @@ class ReactNativeBleTransport {
|
|
|
1889
1699
|
Log === null || Log === void 0 ? void 0 : Log.error('[ReactNativeBleTransport] Protocol V2 call error:', e);
|
|
1890
1700
|
throw e;
|
|
1891
1701
|
}
|
|
1702
|
+
finally {
|
|
1703
|
+
if (highVolumeWrite) {
|
|
1704
|
+
this.scheduleAndroidBalancedConnectionPriority(uuid);
|
|
1705
|
+
}
|
|
1706
|
+
}
|
|
1707
|
+
});
|
|
1708
|
+
}
|
|
1709
|
+
clearAndroidPriorityResetTimer(uuid) {
|
|
1710
|
+
const timerId = this.androidPriorityResetTimers.get(uuid);
|
|
1711
|
+
if (timerId !== undefined) {
|
|
1712
|
+
clearTimeout(timerId);
|
|
1713
|
+
this.androidPriorityResetTimers.delete(uuid);
|
|
1714
|
+
}
|
|
1715
|
+
}
|
|
1716
|
+
enableAndroidHighConnectionPriority(uuid) {
|
|
1717
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
1718
|
+
if (reactNative.Platform.OS !== 'android')
|
|
1719
|
+
return;
|
|
1720
|
+
this.clearAndroidPriorityResetTimer(uuid);
|
|
1721
|
+
if (this.androidHighPriorityDevices.has(uuid))
|
|
1722
|
+
return;
|
|
1723
|
+
const transport = transportCache[uuid];
|
|
1724
|
+
if (!transport)
|
|
1725
|
+
return;
|
|
1726
|
+
try {
|
|
1727
|
+
transport.device = yield transport.device.requestConnectionPriority(reactNativeBlePlx.ConnectionPriority.High);
|
|
1728
|
+
this.androidHighPriorityDevices.add(uuid);
|
|
1729
|
+
Log === null || Log === void 0 ? void 0 : Log.debug('[ReactNativeBleTransport] Android BLE connection priority changed', {
|
|
1730
|
+
priority: 'high',
|
|
1731
|
+
});
|
|
1732
|
+
}
|
|
1733
|
+
catch (error) {
|
|
1734
|
+
Log === null || Log === void 0 ? void 0 : Log.debug('[ReactNativeBleTransport] Android BLE high priority request failed', {
|
|
1735
|
+
error: error instanceof Error ? error.message : String(error),
|
|
1736
|
+
});
|
|
1737
|
+
}
|
|
1738
|
+
});
|
|
1739
|
+
}
|
|
1740
|
+
scheduleAndroidBalancedConnectionPriority(uuid) {
|
|
1741
|
+
if (reactNative.Platform.OS !== 'android' || !this.androidHighPriorityDevices.has(uuid))
|
|
1742
|
+
return;
|
|
1743
|
+
this.clearAndroidPriorityResetTimer(uuid);
|
|
1744
|
+
const timerId = setTimeout(() => {
|
|
1745
|
+
this.androidPriorityResetTimers.delete(uuid);
|
|
1746
|
+
this.restoreAndroidConnectionPriority(uuid, transportCache[uuid]).catch(error => Log === null || Log === void 0 ? void 0 : Log.debug('[ReactNativeBleTransport] Android BLE priority restore failed', error));
|
|
1747
|
+
}, ANDROID_HIGH_PRIORITY_IDLE_MS);
|
|
1748
|
+
this.androidPriorityResetTimers.set(uuid, timerId);
|
|
1749
|
+
}
|
|
1750
|
+
restoreAndroidConnectionPriority(uuid, transport) {
|
|
1751
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
1752
|
+
this.clearAndroidPriorityResetTimer(uuid);
|
|
1753
|
+
if (reactNative.Platform.OS !== 'android' || !this.androidHighPriorityDevices.delete(uuid) || !transport) {
|
|
1754
|
+
return;
|
|
1755
|
+
}
|
|
1756
|
+
try {
|
|
1757
|
+
transport.device = yield transport.device.requestConnectionPriority(reactNativeBlePlx.ConnectionPriority.Balanced);
|
|
1758
|
+
Log === null || Log === void 0 ? void 0 : Log.debug('[ReactNativeBleTransport] Android BLE connection priority changed', {
|
|
1759
|
+
priority: 'balanced',
|
|
1760
|
+
});
|
|
1761
|
+
}
|
|
1762
|
+
catch (error) {
|
|
1763
|
+
Log === null || Log === void 0 ? void 0 : Log.debug('[ReactNativeBleTransport] Android BLE balanced priority request failed', {
|
|
1764
|
+
error: error instanceof Error ? error.message : String(error),
|
|
1765
|
+
});
|
|
1766
|
+
}
|
|
1892
1767
|
});
|
|
1893
1768
|
}
|
|
1894
1769
|
createProtocolV2Adapter(uuid) {
|
|
@@ -1912,7 +1787,7 @@ class ReactNativeBleTransport {
|
|
|
1912
1787
|
writeFrame: (frame, context) => __awaiter(this, void 0, void 0, function* () {
|
|
1913
1788
|
assertCurrentGeneration();
|
|
1914
1789
|
const currentTransport = this.getCachedTransport(uuid);
|
|
1915
|
-
yield this.writeProtocolV2Frame(
|
|
1790
|
+
yield this.writeProtocolV2Frame(currentTransport, frame, context, assertCurrentGeneration);
|
|
1916
1791
|
}),
|
|
1917
1792
|
readFrame: () => __awaiter(this, void 0, void 0, function* () {
|
|
1918
1793
|
assertCurrentGeneration();
|
|
@@ -1933,16 +1808,10 @@ class ReactNativeBleTransport {
|
|
|
1933
1808
|
};
|
|
1934
1809
|
}
|
|
1935
1810
|
getProtocolType(path) {
|
|
1936
|
-
return this.
|
|
1811
|
+
return this.deviceProtocol.get(path);
|
|
1937
1812
|
}
|
|
1938
1813
|
}
|
|
1939
1814
|
|
|
1940
|
-
exports.BLE_CONNECT_TIMEOUT_MANAGER_RESET_THRESHOLD = BLE_CONNECT_TIMEOUT_MANAGER_RESET_THRESHOLD;
|
|
1941
|
-
exports.BLE_CONNECT_TIMEOUT_MS = BLE_CONNECT_TIMEOUT_MS;
|
|
1942
|
-
exports.BLE_GATT_SETUP_TIMEOUT_MS = BLE_GATT_SETUP_TIMEOUT_MS;
|
|
1943
|
-
exports.BLE_WRITE_PACKET_TIMEOUT_MS = BLE_WRITE_PACKET_TIMEOUT_MS;
|
|
1944
|
-
exports.BLE_WRITE_TIMEOUT_MANAGER_RESET_THRESHOLD = BLE_WRITE_TIMEOUT_MANAGER_RESET_THRESHOLD;
|
|
1945
|
-
exports.PROTOCOL_REPROBE_FALLBACK_ATTEMPTS = PROTOCOL_REPROBE_FALLBACK_ATTEMPTS;
|
|
1946
1815
|
exports.configureProtocolV2BleTuning = configureProtocolV2BleTuning;
|
|
1947
1816
|
exports["default"] = ReactNativeBleTransport;
|
|
1948
1817
|
exports.getFirmwareUploadWriteRetryType = getFirmwareUploadWriteRetryType;
|