@onekeyfe/hd-transport-react-native 1.2.0-alpha.17 → 1.2.0-alpha.170
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 +2 -4
- package/dist/BleTransport.d.ts.map +1 -1
- package/dist/bleStrategy.d.ts +7 -0
- package/dist/bleStrategy.d.ts.map +1 -1
- package/dist/constants.d.ts +2 -2
- package/dist/constants.d.ts.map +1 -1
- package/dist/index.d.ts +137 -7
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +921 -304
- package/dist/transportLog.d.ts +1 -12
- package/dist/transportLog.d.ts.map +1 -1
- package/dist/types.d.ts +1 -0
- package/dist/types.d.ts.map +1 -1
- package/jest.config.js +10 -0
- package/package.json +6 -5
- package/src/BleTransport.ts +10 -42
- package/src/__tests__/BleTransport.test.ts +114 -0
- package/src/__tests__/bleStrategy.test.ts +93 -5
- package/src/__tests__/connectTimeout.test.ts +303 -0
- package/src/__tests__/constants.test.ts +20 -0
- package/src/__tests__/enumerate.test.ts +150 -0
- package/src/__tests__/protocolReprobe.test.ts +156 -0
- package/src/__tests__/protocolV1SchemaFixture.ts +39 -0
- package/src/__tests__/protocolV2Link.test.ts +900 -32
- package/src/__tests__/staleCallTimeout.test.ts +210 -0
- package/src/__tests__/writePacketTimeout.test.ts +305 -0
- package/src/bleStrategy.ts +26 -11
- package/src/constants.ts +9 -14
- package/src/index.ts +1214 -280
- package/src/transportLog.ts +1 -18
- package/src/types.ts +1 -0
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 = 244;
|
|
97
98
|
const ClassicServiceUUID = '00000001-0000-1000-8000-00805f9b34fb';
|
|
98
99
|
const OneKeyServices = {
|
|
99
100
|
classic: {
|
|
@@ -117,36 +118,38 @@ const getInfosForServiceUuid = (serviceUuid, deviceType) => {
|
|
|
117
118
|
return null;
|
|
118
119
|
}
|
|
119
120
|
const normalizedServiceUuid = normalizeBleUuid(serviceUuid);
|
|
120
|
-
const service = (_a = services[serviceUuid]) !== null && _a !== void 0 ? _a : Object.values(services).find(item => normalizeBleUuid(item.serviceUuid) === normalizedServiceUuid
|
|
121
|
+
const service = (_a = services[serviceUuid]) !== null && _a !== void 0 ? _a : Object.values(services).find(item => normalizeBleUuid(item.serviceUuid) === normalizedServiceUuid ||
|
|
122
|
+
hdShared.matchesKnownBleUuid(serviceUuid, hdShared.createKnownBleUuidAliases(item.serviceUuid)));
|
|
121
123
|
if (!service) {
|
|
122
124
|
return null;
|
|
123
125
|
}
|
|
124
126
|
return service;
|
|
125
127
|
};
|
|
126
128
|
const normalizeBleUuid = (uuid) => (uuid !== null && uuid !== void 0 ? uuid : '').replace(/-/g, '').toLowerCase();
|
|
127
|
-
const getBleUuidKey = (uuid) => {
|
|
128
|
-
const normalized = normalizeBleUuid(uuid);
|
|
129
|
-
return normalized.length >= 8 ? normalized.substring(4, 8) : normalized;
|
|
130
|
-
};
|
|
131
129
|
const isSameBleUuid = (left, right) => {
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
return (
|
|
135
|
-
(getBleUuidKey(left) !== '' && getBleUuidKey(left) === getBleUuidKey(right)));
|
|
130
|
+
if (!left || !right)
|
|
131
|
+
return false;
|
|
132
|
+
return hdShared.matchesKnownBleUuid(left, hdShared.createKnownBleUuidAliases(right));
|
|
136
133
|
};
|
|
137
134
|
|
|
138
135
|
function hasWritableCapability(characteristic) {
|
|
139
136
|
return !!(characteristic.isWritableWithResponse || characteristic.isWritableWithoutResponse);
|
|
140
137
|
}
|
|
141
|
-
function resolveProtocolV2PacketCapacity({ platform, iosPacketLength =
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
138
|
+
function resolveProtocolV2PacketCapacity({ platform, iosPacketLength = IOS_PROTOCOL_V2_PACKET_LENGTH, androidPacketLength = ANDROID_PROTOCOL_V2_PACKET_LENGTH, mtu, }) {
|
|
139
|
+
const negotiatedMtu = typeof mtu === 'number' && Number.isFinite(mtu) && mtu > 3 ? Math.floor(mtu) : 23;
|
|
140
|
+
const payloadLength = negotiatedMtu - 3;
|
|
141
|
+
const configuredPacketLength = platform === 'ios' ? iosPacketLength : androidPacketLength;
|
|
142
|
+
return Math.min(configuredPacketLength, payloadLength);
|
|
143
|
+
}
|
|
144
|
+
function shouldRefreshNegotiatedMtu(mtu) {
|
|
145
|
+
return typeof mtu !== 'number' || !Number.isFinite(mtu) || mtu <= 23;
|
|
146
|
+
}
|
|
147
|
+
function shouldWriteProtocolV2WithResponse({ platform, highThroughput, requestedWithResponse, characteristic, }) {
|
|
148
|
+
if (!characteristic.isWritableWithResponse)
|
|
149
|
+
return false;
|
|
150
|
+
if (!characteristic.isWritableWithoutResponse)
|
|
151
|
+
return true;
|
|
152
|
+
return requestedWithResponse === true || (platform === 'ios' && !highThroughput);
|
|
150
153
|
}
|
|
151
154
|
|
|
152
155
|
const timer = process.env.NODE_ENV === 'development'
|
|
@@ -203,59 +206,20 @@ const isHeaderChunk = (chunk) => {
|
|
|
203
206
|
return false;
|
|
204
207
|
};
|
|
205
208
|
|
|
206
|
-
const Log$1 = bleLogger;
|
|
207
209
|
class BleTransport {
|
|
208
210
|
constructor(device, writeCharacteristic, notifyCharacteristic) {
|
|
209
211
|
this.name = 'ReactNativeBleTransport';
|
|
210
|
-
this.mtuSize = 23;
|
|
211
212
|
this.id = device.id;
|
|
212
213
|
this.device = device;
|
|
213
214
|
this.writeCharacteristic = writeCharacteristic;
|
|
214
215
|
this.notifyCharacteristic = notifyCharacteristic;
|
|
215
216
|
}
|
|
216
|
-
writeWithRetry(data
|
|
217
|
+
writeWithRetry(data) {
|
|
217
218
|
return __awaiter(this, void 0, void 0, function* () {
|
|
218
|
-
|
|
219
|
-
yield this.writeCharacteristic.writeWithoutResponse(data);
|
|
220
|
-
}
|
|
221
|
-
catch (error) {
|
|
222
|
-
Log$1 === null || Log$1 === void 0 ? void 0 : Log$1.debug(`Write retry attempt ${BleTransport.MAX_RETRIES - retryCount + 1}, error: ${error}`);
|
|
223
|
-
if (retryCount > 0) {
|
|
224
|
-
yield hdShared.wait(BleTransport.RETRY_DELAY);
|
|
225
|
-
if (error.errorCode === reactNativeBlePlx.BleErrorCode.DeviceDisconnected ||
|
|
226
|
-
error.errorCode === reactNativeBlePlx.BleErrorCode.CharacteristicNotFound) {
|
|
227
|
-
try {
|
|
228
|
-
yield this.device.connect();
|
|
229
|
-
yield this.device.discoverAllServicesAndCharacteristics();
|
|
230
|
-
}
|
|
231
|
-
catch (e) {
|
|
232
|
-
Log$1 === null || Log$1 === void 0 ? void 0 : Log$1.debug(`Connect or discoverAllServicesAndCharacteristics error: ${e}`);
|
|
233
|
-
}
|
|
234
|
-
}
|
|
235
|
-
else {
|
|
236
|
-
Log$1 === null || Log$1 === void 0 ? void 0 : Log$1.debug(`writeCharacteristic error: ${error}`);
|
|
237
|
-
}
|
|
238
|
-
return this.writeWithRetry(data, retryCount - 1);
|
|
239
|
-
}
|
|
240
|
-
throw error;
|
|
241
|
-
}
|
|
219
|
+
yield this.writeCharacteristic.writeWithoutResponse(data);
|
|
242
220
|
});
|
|
243
221
|
}
|
|
244
222
|
}
|
|
245
|
-
BleTransport.MAX_RETRIES = 5;
|
|
246
|
-
BleTransport.RETRY_DELAY = 2000;
|
|
247
|
-
|
|
248
|
-
function createTransportCallLog(name, protocol, data) {
|
|
249
|
-
if (name === 'ResourceUpdate' || name === 'ResourceAck') {
|
|
250
|
-
return {
|
|
251
|
-
name,
|
|
252
|
-
protocol,
|
|
253
|
-
file_name: data.file_name,
|
|
254
|
-
hash: data.hash,
|
|
255
|
-
};
|
|
256
|
-
}
|
|
257
|
-
return { name, protocol };
|
|
258
|
-
}
|
|
259
223
|
|
|
260
224
|
const { check, ProtocolV1, parseConfigure } = transport__default["default"];
|
|
261
225
|
const Log = bleLogger;
|
|
@@ -264,10 +228,35 @@ const FIRMWARE_UPLOAD_WRITE_BURST_SIZE = reactNative.Platform.OS === 'ios' ? 4 :
|
|
|
264
228
|
const FIRMWARE_UPLOAD_WRITE_PAUSE_MS = reactNative.Platform.OS === 'ios' ? 8 : 10;
|
|
265
229
|
const FIRMWARE_UPLOAD_WRITE_FLUSH_DELAY_MS = reactNative.Platform.OS === 'ios' ? 24 : 30;
|
|
266
230
|
const FIRMWARE_UPLOAD_WRITE_MAX_RETRIES = 8;
|
|
267
|
-
const FIRMWARE_UPLOAD_RECONNECT_RETRY_DELAY_MS = 2000;
|
|
268
231
|
const ANDROID_FIRMWARE_UPLOAD_PACKET_LENGTH = 192;
|
|
269
232
|
const FIRMWARE_UPLOAD_WRITE_PACKET_CAPACITY = reactNative.Platform.OS === 'ios' ? IOS_PACKET_LENGTH : ANDROID_FIRMWARE_UPLOAD_PACKET_LENGTH;
|
|
270
233
|
const ANDROID_GATT_CONGESTED_STATUS = 143;
|
|
234
|
+
const isAsciiWhitespace = (code) => code === 0x09 ||
|
|
235
|
+
code === 0x0a ||
|
|
236
|
+
code === 0x0b ||
|
|
237
|
+
code === 0x0c ||
|
|
238
|
+
code === 0x0d ||
|
|
239
|
+
code === 0x20;
|
|
240
|
+
const hasGattCongestedStatus = (text) => {
|
|
241
|
+
let searchFrom = 0;
|
|
242
|
+
while (searchFrom < text.length) {
|
|
243
|
+
const statusIndex = text.indexOf('status', searchFrom);
|
|
244
|
+
if (statusIndex < 0)
|
|
245
|
+
return false;
|
|
246
|
+
let cursor = statusIndex + 'status'.length;
|
|
247
|
+
while (cursor < text.length && isAsciiWhitespace(text.charCodeAt(cursor)))
|
|
248
|
+
cursor += 1;
|
|
249
|
+
if (text[cursor] === ':' || text[cursor] === '=') {
|
|
250
|
+
cursor += 1;
|
|
251
|
+
while (cursor < text.length && isAsciiWhitespace(text.charCodeAt(cursor)))
|
|
252
|
+
cursor += 1;
|
|
253
|
+
}
|
|
254
|
+
if (text.startsWith(String(ANDROID_GATT_CONGESTED_STATUS), cursor))
|
|
255
|
+
return true;
|
|
256
|
+
searchFrom = statusIndex + 'status'.length;
|
|
257
|
+
}
|
|
258
|
+
return false;
|
|
259
|
+
};
|
|
271
260
|
const delay = (ms) => new Promise(resolve => {
|
|
272
261
|
setTimeout(resolve, ms);
|
|
273
262
|
});
|
|
@@ -275,10 +264,6 @@ const getFirmwareUploadWriteRetryType = (error) => {
|
|
|
275
264
|
if (!error || typeof error !== 'object')
|
|
276
265
|
return null;
|
|
277
266
|
const bleWriteError = error;
|
|
278
|
-
if (bleWriteError.errorCode === reactNativeBlePlx.BleErrorCode.DeviceDisconnected ||
|
|
279
|
-
bleWriteError.errorCode === reactNativeBlePlx.BleErrorCode.CharacteristicNotFound) {
|
|
280
|
-
return 'reconnectable';
|
|
281
|
-
}
|
|
282
267
|
if (bleWriteError.androidErrorCode === ANDROID_GATT_CONGESTED_STATUS ||
|
|
283
268
|
bleWriteError.status === ANDROID_GATT_CONGESTED_STATUS) {
|
|
284
269
|
return 'congested';
|
|
@@ -286,18 +271,24 @@ const getFirmwareUploadWriteRetryType = (error) => {
|
|
|
286
271
|
const text = [bleWriteError.reason, bleWriteError.message, bleWriteError.name]
|
|
287
272
|
.filter(value => typeof value === 'string')
|
|
288
273
|
.join(' ');
|
|
289
|
-
return
|
|
274
|
+
return text.includes('GATT_CONGESTED') || hasGattCongestedStatus(text) ? 'congested' : null;
|
|
290
275
|
};
|
|
291
276
|
const resolveFirmwareUploadRetryDelay = (attempt, baseDelayMs = 200, maxDelayMs = 1200) => Math.min(baseDelayMs * Math.pow(2, attempt), maxDelayMs);
|
|
292
|
-
const
|
|
293
|
-
const PROTOCOL_PROBE_TIMEOUT_MS = 1000;
|
|
277
|
+
const PROTOCOL_PROBE_TIMEOUT_MS = 3000;
|
|
294
278
|
const PROTOCOL_V2_PROBE_TIMEOUT_MS = 10000;
|
|
295
|
-
const
|
|
279
|
+
const BLE_WRITE_PACKET_TIMEOUT_MS = 10000;
|
|
280
|
+
const BLE_NATIVE_TEARDOWN_TIMEOUT_MS = 3000;
|
|
281
|
+
const WEDGED_WRITE_MESSAGE = 'BLE write timeout after';
|
|
282
|
+
const isWedgedWriteError = (error) => (error === null || error === void 0 ? void 0 : error.errorCode) === hdShared.HardwareErrorCode.BleWriteCharacteristicError &&
|
|
283
|
+
typeof (error === null || error === void 0 ? void 0 : error.message) === 'string' &&
|
|
284
|
+
error.message.startsWith(WEDGED_WRITE_MESSAGE);
|
|
285
|
+
const BLE_WRITE_TIMEOUT_MANAGER_RESET_THRESHOLD = 2;
|
|
286
|
+
const DEVICE_SCAN_TIMEOUT_MS = 3000;
|
|
296
287
|
const IOS_NOTIFY_READY_DELAY_MS = 150;
|
|
297
288
|
const ANDROID_NOTIFY_READY_DELAY_MS = 300;
|
|
298
289
|
const DEFAULT_PROTOCOL_V2_BLE_TUNING = {
|
|
299
|
-
iosPacketLength:
|
|
300
|
-
androidPacketLength:
|
|
290
|
+
iosPacketLength: IOS_PROTOCOL_V2_PACKET_LENGTH,
|
|
291
|
+
androidPacketLength: ANDROID_PROTOCOL_V2_PACKET_LENGTH,
|
|
301
292
|
};
|
|
302
293
|
let protocolV2BleTuning = Object.assign({}, DEFAULT_PROTOCOL_V2_BLE_TUNING);
|
|
303
294
|
const normalizePositiveInteger = (value, fallback) => {
|
|
@@ -320,25 +311,37 @@ function resetProtocolV2BleTuning() {
|
|
|
320
311
|
function getProtocolV2BleTuning() {
|
|
321
312
|
return Object.assign({}, protocolV2BleTuning);
|
|
322
313
|
}
|
|
323
|
-
function inferProtocolHintFromDeviceName(name) {
|
|
324
|
-
return /\bpro\s*2\b/i.test(name !== null && name !== void 0 ? name : '') ? 'V2' : undefined;
|
|
325
|
-
}
|
|
326
314
|
function getDeviceDisplayName(device) {
|
|
327
315
|
return (device === null || device === void 0 ? void 0 : device.name) || (device === null || device === void 0 ? void 0 : device.localName) || null;
|
|
328
316
|
}
|
|
329
|
-
|
|
330
|
-
|
|
331
|
-
|
|
332
|
-
|
|
333
|
-
|
|
334
|
-
|
|
335
|
-
}
|
|
336
|
-
const ANDROID_REQUEST_MTU = 256;
|
|
317
|
+
const IOS_REQUEST_MTU = 247;
|
|
318
|
+
const ANDROID_REQUEST_MTU = 517;
|
|
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;
|
|
322
|
+
const BLE_NATIVE_CONNECT_TIMEOUT_MS = 3000;
|
|
337
323
|
const connectOptions = {
|
|
338
|
-
requestMTU:
|
|
339
|
-
timeout:
|
|
324
|
+
requestMTU: getRequestedBleMtu(),
|
|
325
|
+
timeout: BLE_NATIVE_CONNECT_TIMEOUT_MS,
|
|
340
326
|
refreshGatt: 'OnConnected',
|
|
341
327
|
};
|
|
328
|
+
const fallbackConnectOptions = {
|
|
329
|
+
timeout: BLE_NATIVE_CONNECT_TIMEOUT_MS,
|
|
330
|
+
};
|
|
331
|
+
const BLE_CONNECT_TIMEOUT_MS = BLE_NATIVE_CONNECT_TIMEOUT_MS * 2 + 2000;
|
|
332
|
+
const BLE_GATT_SETUP_TIMEOUT_MS = 10000;
|
|
333
|
+
const PROTOCOL_REPROBE_FALLBACK_ATTEMPTS = 3;
|
|
334
|
+
const BLE_CONNECT_TIMEOUT_MANAGER_RESET_THRESHOLD = 2;
|
|
335
|
+
const CONNECT_TIMEOUT_MESSAGE = 'BLE connect timeout after';
|
|
336
|
+
const BLE_SETUP_WEDGED_MESSAGE = 'BLE setup wedged repeatedly';
|
|
337
|
+
const isConnectTimeoutError = (error) => (error === null || error === void 0 ? void 0 : error.errorCode) === hdShared.HardwareErrorCode.BleConnectedError &&
|
|
338
|
+
typeof (error === null || error === void 0 ? void 0 : error.message) === 'string' &&
|
|
339
|
+
error.message.startsWith(CONNECT_TIMEOUT_MESSAGE);
|
|
340
|
+
const isWedgedBleSetupError = (error) => (error === null || error === void 0 ? void 0 : error.errorCode) === hdShared.HardwareErrorCode.PollingTimeout &&
|
|
341
|
+
typeof (error === null || error === void 0 ? void 0 : error.message) === 'string' &&
|
|
342
|
+
error.message.startsWith(BLE_SETUP_WEDGED_MESSAGE);
|
|
343
|
+
const shouldRethrowBleSetupError = (error) => isConnectTimeoutError(error) || isWedgedBleSetupError(error);
|
|
344
|
+
const isNativeOperationTimeoutError = (error) => (error === null || error === void 0 ? void 0 : error.errorCode) === reactNativeBlePlx.BleErrorCode.OperationTimedOut;
|
|
342
345
|
const tryToGetConfiguration = (device) => {
|
|
343
346
|
if (!device || !device.serviceUUIDs)
|
|
344
347
|
return null;
|
|
@@ -350,23 +353,25 @@ const tryToGetConfiguration = (device) => {
|
|
|
350
353
|
return null;
|
|
351
354
|
return infos;
|
|
352
355
|
};
|
|
353
|
-
const
|
|
354
|
-
if (reactNative.Platform.OS !== 'android')
|
|
356
|
+
const requestNegotiatedMtu = (device, stage, attempt) => __awaiter(void 0, void 0, void 0, function* () {
|
|
357
|
+
if (reactNative.Platform.OS !== 'ios' && reactNative.Platform.OS !== 'android')
|
|
355
358
|
return device;
|
|
356
359
|
try {
|
|
357
|
-
const mtuDevice = yield device.requestMTU(
|
|
358
|
-
Log === null || Log === void 0 ? void 0 : Log.debug('[ReactNativeBleTransport] MTU configured', {
|
|
359
|
-
deviceId: device.id,
|
|
360
|
-
requested: ANDROID_REQUEST_MTU,
|
|
361
|
-
actual: mtuDevice.mtu,
|
|
362
|
-
});
|
|
360
|
+
const mtuDevice = yield device.requestMTU(getRequestedBleMtu());
|
|
363
361
|
return mtuDevice;
|
|
364
362
|
}
|
|
365
363
|
catch (error) {
|
|
366
|
-
Log === null || Log === void 0 ? void 0 : Log.debug('[ReactNativeBleTransport]
|
|
364
|
+
Log === null || Log === void 0 ? void 0 : Log.debug('[ReactNativeBleTransport] MTU refresh failed, continuing with current value', {
|
|
365
|
+
platform: reactNative.Platform.OS,
|
|
366
|
+
stage,
|
|
367
|
+
attempt,
|
|
368
|
+
actual: device.mtu,
|
|
369
|
+
error: error instanceof Error ? error.message : String(error),
|
|
370
|
+
});
|
|
367
371
|
return device;
|
|
368
372
|
}
|
|
369
373
|
});
|
|
374
|
+
const resolveNegotiatedMtu = (device) => requestNegotiatedMtu(device, 'connected', 0);
|
|
370
375
|
function remapError(error) {
|
|
371
376
|
var _a;
|
|
372
377
|
if (error instanceof reactNativeBlePlx.BleError) {
|
|
@@ -393,9 +398,16 @@ class ReactNativeBleTransport {
|
|
|
393
398
|
this.stopped = false;
|
|
394
399
|
this.scanTimeout = DEVICE_SCAN_TIMEOUT_MS;
|
|
395
400
|
this.runPromise = null;
|
|
401
|
+
this.runPromiseDeviceId = null;
|
|
396
402
|
this.firmwareUploadWriteRecoveryIds = new Set();
|
|
397
403
|
this.deviceProtocol = new Map();
|
|
404
|
+
this.probingProtocols = new Map();
|
|
405
|
+
this.writeTimeoutCounts = new Map();
|
|
406
|
+
this.connectionSetupTimeoutCounts = new Map();
|
|
398
407
|
this.deviceProtocolHints = new Map();
|
|
408
|
+
this.sessionProtocols = new Map();
|
|
409
|
+
this.confirmedProtocolV2 = new Set();
|
|
410
|
+
this.protocolReprobeFailures = new Map();
|
|
399
411
|
this.protocolV2Assemblers = new Map();
|
|
400
412
|
this.protocolV2FrameQueues = new Map();
|
|
401
413
|
this.protocolV2FramePromises = new Map();
|
|
@@ -416,12 +428,17 @@ class ReactNativeBleTransport {
|
|
|
416
428
|
this.rejectProtocolV2Frames(uuid, new Error(reason));
|
|
417
429
|
Log === null || Log === void 0 ? void 0 : Log.debug('[ReactNativeBleTransport] Protocol V2 link invalidated:', uuid, reason);
|
|
418
430
|
if (reason.startsWith('Protocol V2 link-fatal error:')) {
|
|
419
|
-
yield this.
|
|
431
|
+
yield this.releaseNative(uuid, true);
|
|
420
432
|
}
|
|
421
433
|
}),
|
|
422
434
|
});
|
|
423
435
|
this.monitorTokens = new Map();
|
|
436
|
+
this.disconnectEventTokens = new Map();
|
|
437
|
+
this.protocolV2HighVolumeLogSignatures = new Map();
|
|
438
|
+
this.androidHighPriorityDevices = new Set();
|
|
439
|
+
this.androidPriorityResetTimers = new Map();
|
|
424
440
|
this.nextMonitorToken = 1;
|
|
441
|
+
this.lifecycleOperations = new Map();
|
|
425
442
|
this.scanTimeout = (_a = options.scanTimeout) !== null && _a !== void 0 ? _a : DEVICE_SCAN_TIMEOUT_MS;
|
|
426
443
|
}
|
|
427
444
|
init(logger, emitter) {
|
|
@@ -434,10 +451,18 @@ class ReactNativeBleTransport {
|
|
|
434
451
|
this._messages = messages;
|
|
435
452
|
}
|
|
436
453
|
configureProtocolV2(signedData) {
|
|
454
|
+
const configuration = typeof signedData === 'string' ? signedData : JSON.stringify(signedData);
|
|
455
|
+
if (this.protocolV2SchemaConfiguration === configuration) {
|
|
456
|
+
return;
|
|
457
|
+
}
|
|
458
|
+
const isReconfiguration = this.protocolV2SchemaConfiguration !== undefined;
|
|
437
459
|
this._messagesV2 = parseConfigure(signedData);
|
|
438
|
-
this.
|
|
439
|
-
|
|
440
|
-
.
|
|
460
|
+
this.protocolV2SchemaConfiguration = configuration;
|
|
461
|
+
if (isReconfiguration) {
|
|
462
|
+
this.protocolV2Links
|
|
463
|
+
.invalidateAllLinks('Protocol V2 schema reconfigured')
|
|
464
|
+
.catch(error => Log === null || Log === void 0 ? void 0 : Log.debug('Protocol V2 schema link cleanup failed:', error));
|
|
465
|
+
}
|
|
441
466
|
}
|
|
442
467
|
listen() {
|
|
443
468
|
}
|
|
@@ -448,7 +473,6 @@ class ReactNativeBleTransport {
|
|
|
448
473
|
return Promise.resolve(this.blePlxManager);
|
|
449
474
|
}
|
|
450
475
|
resolveCharacteristics(device) {
|
|
451
|
-
var _a, _b, _c, _d;
|
|
452
476
|
return __awaiter(this, void 0, void 0, function* () {
|
|
453
477
|
yield device.discoverAllServicesAndCharacteristics();
|
|
454
478
|
let infos = tryToGetConfiguration(device);
|
|
@@ -465,19 +489,11 @@ class ReactNativeBleTransport {
|
|
|
465
489
|
}
|
|
466
490
|
}
|
|
467
491
|
}
|
|
468
|
-
let fallbackServiceUuid;
|
|
469
492
|
if (!infos) {
|
|
470
493
|
const services = yield device.services();
|
|
471
494
|
Log === null || Log === void 0 ? void 0 : Log.debug('[ReactNativeBleTransport] Known OneKey service UUID not found, discovered services:', services === null || services === void 0 ? void 0 : services.map(service => service.uuid));
|
|
472
|
-
const knownService = services.find(service => getInfosForServiceUuid(service.uuid, 'classic'));
|
|
473
|
-
const fallbackService = (_a = knownService !== null && knownService !== void 0 ? knownService : services.find(service => !isGenericBleService(service.uuid))) !== null && _a !== void 0 ? _a : services[0];
|
|
474
|
-
if (fallbackService) {
|
|
475
|
-
fallbackServiceUuid = fallbackService.uuid;
|
|
476
|
-
characteristics = yield device.characteristicsForService(fallbackService.uuid);
|
|
477
|
-
Log === null || Log === void 0 ? void 0 : Log.debug('[ReactNativeBleTransport] Using fallback BLE service:', fallbackService.uuid);
|
|
478
|
-
}
|
|
479
495
|
}
|
|
480
|
-
if (!infos
|
|
496
|
+
if (!infos) {
|
|
481
497
|
try {
|
|
482
498
|
Log === null || Log === void 0 ? void 0 : Log.debug('cancel connection when service not found');
|
|
483
499
|
yield device.cancelConnection();
|
|
@@ -487,9 +503,7 @@ class ReactNativeBleTransport {
|
|
|
487
503
|
}
|
|
488
504
|
throw hdShared.ERRORS.TypedError(hdShared.HardwareErrorCode.BleServiceNotFound);
|
|
489
505
|
}
|
|
490
|
-
const serviceUuid
|
|
491
|
-
const writeUuid = (_c = infos === null || infos === void 0 ? void 0 : infos.writeUuid) !== null && _c !== void 0 ? _c : '00000002-0000-1000-8000-00805f9b34fb';
|
|
492
|
-
const notifyUuid = (_d = infos === null || infos === void 0 ? void 0 : infos.notifyUuid) !== null && _d !== void 0 ? _d : '00000003-0000-1000-8000-00805f9b34fb';
|
|
506
|
+
const { serviceUuid, writeUuid, notifyUuid } = infos;
|
|
493
507
|
if (!serviceUuid) {
|
|
494
508
|
throw hdShared.ERRORS.TypedError(hdShared.HardwareErrorCode.BleServiceNotFound);
|
|
495
509
|
}
|
|
@@ -530,8 +544,8 @@ class ReactNativeBleTransport {
|
|
|
530
544
|
attachDisconnectSubscription(transport, device, uuid) {
|
|
531
545
|
var _a;
|
|
532
546
|
(_a = transport.disconnectSubscription) === null || _a === void 0 ? void 0 : _a.remove();
|
|
547
|
+
const { monitorToken } = transport;
|
|
533
548
|
transport.disconnectSubscription = device.onDisconnected(() => {
|
|
534
|
-
var _a;
|
|
535
549
|
if (this.firmwareUploadWriteRecoveryIds.has(uuid)) {
|
|
536
550
|
Log === null || Log === void 0 ? void 0 : Log.debug('device disconnect ignored during FirmwareUpload write recovery: ', uuid);
|
|
537
551
|
return;
|
|
@@ -540,17 +554,16 @@ class ReactNativeBleTransport {
|
|
|
540
554
|
Log === null || Log === void 0 ? void 0 : Log.debug('device disconnect ignored for stale transport: ', device === null || device === void 0 ? void 0 : device.id);
|
|
541
555
|
return;
|
|
542
556
|
}
|
|
557
|
+
if (this.monitorTokens.get(uuid) !== monitorToken) {
|
|
558
|
+
Log === null || Log === void 0 ? void 0 : Log.debug('device disconnect ignored for stale generation: ', device === null || device === void 0 ? void 0 : device.id);
|
|
559
|
+
return;
|
|
560
|
+
}
|
|
543
561
|
try {
|
|
544
562
|
Log === null || Log === void 0 ? void 0 : Log.debug('device disconnect: ', device === null || device === void 0 ? void 0 : device.id);
|
|
545
|
-
(
|
|
546
|
-
|
|
547
|
-
id: device === null || device === void 0 ? void 0 : device.id,
|
|
548
|
-
connectId: device === null || device === void 0 ? void 0 : device.id,
|
|
549
|
-
});
|
|
550
|
-
if (this.runPromise) {
|
|
563
|
+
this.emitDeviceDisconnect(uuid, device === null || device === void 0 ? void 0 : device.name, monitorToken);
|
|
564
|
+
if (this.runPromise && this.runPromiseDeviceId === uuid) {
|
|
551
565
|
const error = hdShared.ERRORS.TypedError(hdShared.HardwareErrorCode.BleConnectedError);
|
|
552
566
|
this.runPromise.reject(error);
|
|
553
|
-
this.rejectAllProtocolV2Frames(error);
|
|
554
567
|
}
|
|
555
568
|
}
|
|
556
569
|
catch (e) {
|
|
@@ -561,6 +574,22 @@ class ReactNativeBleTransport {
|
|
|
561
574
|
}
|
|
562
575
|
});
|
|
563
576
|
}
|
|
577
|
+
emitDeviceDisconnect(uuid, name, token) {
|
|
578
|
+
var _a;
|
|
579
|
+
if (token === undefined || this.disconnectEventTokens.get(uuid) === token) {
|
|
580
|
+
return;
|
|
581
|
+
}
|
|
582
|
+
if (this.monitorTokens.get(uuid) !== token) {
|
|
583
|
+
Log === null || Log === void 0 ? void 0 : Log.debug('device disconnect event ignored for stale generation: ', uuid);
|
|
584
|
+
return;
|
|
585
|
+
}
|
|
586
|
+
this.disconnectEventTokens.set(uuid, token);
|
|
587
|
+
(_a = this.emitter) === null || _a === void 0 ? void 0 : _a.emit(transport.TRANSPORT_EVENT.DEVICE_DISCONNECT, {
|
|
588
|
+
name,
|
|
589
|
+
id: uuid,
|
|
590
|
+
connectId: uuid,
|
|
591
|
+
});
|
|
592
|
+
}
|
|
564
593
|
reconnectFirmwareUploadTransport(uuid, transport) {
|
|
565
594
|
var _a, _b;
|
|
566
595
|
return __awaiter(this, void 0, void 0, function* () {
|
|
@@ -574,19 +603,19 @@ class ReactNativeBleTransport {
|
|
|
574
603
|
const isConnected = yield device.isConnected().catch(() => false);
|
|
575
604
|
if (!isConnected) {
|
|
576
605
|
try {
|
|
577
|
-
device = yield device.connect(connectOptions);
|
|
606
|
+
device = yield this.connectWithTimeout(uuid, () => device.connect(connectOptions));
|
|
578
607
|
}
|
|
579
608
|
catch (e) {
|
|
580
609
|
if (e.errorCode === reactNativeBlePlx.BleErrorCode.DeviceMTUChangeFailed ||
|
|
581
610
|
e.errorCode === reactNativeBlePlx.BleErrorCode.OperationCancelled) {
|
|
582
|
-
device = yield device.connect();
|
|
611
|
+
device = yield this.connectWithTimeout(uuid, () => device.connect());
|
|
583
612
|
}
|
|
584
613
|
else if (e.errorCode !== reactNativeBlePlx.BleErrorCode.DeviceAlreadyConnected) {
|
|
585
614
|
throw e;
|
|
586
615
|
}
|
|
587
616
|
}
|
|
588
617
|
}
|
|
589
|
-
const { writeCharacteristic, notifyCharacteristic } = yield this.
|
|
618
|
+
const { writeCharacteristic, notifyCharacteristic } = yield this.resolveCharacteristicsWithTimeout(uuid, device);
|
|
590
619
|
transport.device = device;
|
|
591
620
|
transport.writeCharacteristic = writeCharacteristic;
|
|
592
621
|
transport.notifyCharacteristic = notifyCharacteristic;
|
|
@@ -634,7 +663,7 @@ class ReactNativeBleTransport {
|
|
|
634
663
|
allowDuplicates: true,
|
|
635
664
|
scanMode: reactNativeBlePlx.ScanMode.LowLatency,
|
|
636
665
|
}, (error, device) => {
|
|
637
|
-
var _a, _b
|
|
666
|
+
var _a, _b;
|
|
638
667
|
if (error) {
|
|
639
668
|
Log === null || Log === void 0 ? void 0 : Log.debug('ble scan error: ', error);
|
|
640
669
|
if ([reactNativeBlePlx.BleErrorCode.BluetoothPoweredOff, reactNativeBlePlx.BleErrorCode.BluetoothInUnknownState].includes(error.errorCode)) {
|
|
@@ -655,9 +684,14 @@ class ReactNativeBleTransport {
|
|
|
655
684
|
return;
|
|
656
685
|
}
|
|
657
686
|
const displayName = getDeviceDisplayName(device);
|
|
658
|
-
const
|
|
659
|
-
|
|
660
|
-
|
|
687
|
+
const isUnnamedIOSPeripheral = reactNative.Platform.OS === 'ios' && !(displayName === null || displayName === void 0 ? void 0 : displayName.trim());
|
|
688
|
+
const isOneKey = !isUnnamedIOSPeripheral &&
|
|
689
|
+
hdShared.isOnekeyBluetoothDevice({
|
|
690
|
+
id: device === null || device === void 0 ? void 0 : device.id,
|
|
691
|
+
name: device === null || device === void 0 ? void 0 : device.name,
|
|
692
|
+
localName: device === null || device === void 0 ? void 0 : device.localName,
|
|
693
|
+
serviceUuids: (_b = device === null || device === void 0 ? void 0 : device.serviceUUIDs) !== null && _b !== void 0 ? _b : getBluetoothServiceUuids(),
|
|
694
|
+
});
|
|
661
695
|
if (isOneKey) {
|
|
662
696
|
addDevice(device);
|
|
663
697
|
}
|
|
@@ -672,10 +706,15 @@ class ReactNativeBleTransport {
|
|
|
672
706
|
});
|
|
673
707
|
getConnectedDeviceIds(reactNative.Platform.OS === 'ios' ? getBluetoothServiceUuids() : []).then(devices => {
|
|
674
708
|
for (const device of devices) {
|
|
675
|
-
const
|
|
676
|
-
|
|
677
|
-
|
|
678
|
-
if (
|
|
709
|
+
const localName = 'localName' in device && typeof device.localName === 'string'
|
|
710
|
+
? device.localName
|
|
711
|
+
: null;
|
|
712
|
+
if (hdShared.isOnekeyBluetoothDevice({
|
|
713
|
+
id: device.id,
|
|
714
|
+
name: device.name,
|
|
715
|
+
localName,
|
|
716
|
+
serviceUuids: device.serviceUUIDs,
|
|
717
|
+
})) {
|
|
679
718
|
Log === null || Log === void 0 ? void 0 : Log.debug('search connected peripheral: ', device.id);
|
|
680
719
|
addDevice(device);
|
|
681
720
|
}
|
|
@@ -685,16 +724,11 @@ class ReactNativeBleTransport {
|
|
|
685
724
|
var _a;
|
|
686
725
|
if (deviceList.every(d => d.id !== device.id)) {
|
|
687
726
|
const displayName = (_a = getDeviceDisplayName(device)) !== null && _a !== void 0 ? _a : 'Unknown BLE Device';
|
|
688
|
-
const protocolHint = inferProtocolHintFromDeviceName(displayName);
|
|
689
|
-
if (protocolHint) {
|
|
690
|
-
this.deviceProtocolHints.set(device.id, protocolHint);
|
|
691
|
-
}
|
|
692
727
|
deviceList.push(Object.assign(Object.assign({}, device), { name: displayName, commType: 'ble' }));
|
|
693
728
|
Log === null || Log === void 0 ? void 0 : Log.debug('[ReactNativeBleTransport] OneKey BLE device discovered', {
|
|
694
729
|
deviceId: device.id,
|
|
695
730
|
name: displayName,
|
|
696
731
|
serviceUUIDs: device.serviceUUIDs,
|
|
697
|
-
protocolHint,
|
|
698
732
|
});
|
|
699
733
|
}
|
|
700
734
|
};
|
|
@@ -705,13 +739,70 @@ class ReactNativeBleTransport {
|
|
|
705
739
|
}));
|
|
706
740
|
});
|
|
707
741
|
}
|
|
742
|
+
installTransportForAcquire(uuid, device, characteristics) {
|
|
743
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
744
|
+
const { writeCharacteristic, notifyCharacteristic } = characteristics !== null && characteristics !== void 0 ? characteristics : (yield this.resolveCharacteristicsWithTimeout(uuid, device));
|
|
745
|
+
const transport$1 = new BleTransport(device, writeCharacteristic, notifyCharacteristic);
|
|
746
|
+
transport$1.mtuSize = typeof device.mtu === 'number' ? device.mtu : undefined;
|
|
747
|
+
const monitorToken = this.nextMonitorToken;
|
|
748
|
+
this.nextMonitorToken += 1;
|
|
749
|
+
const notifyTransactionId = `${uuid}:notify:${monitorToken}`;
|
|
750
|
+
transport$1.monitorToken = monitorToken;
|
|
751
|
+
transport$1.notifyTransactionId = notifyTransactionId;
|
|
752
|
+
this.monitorTokens.set(uuid, monitorToken);
|
|
753
|
+
transport$1.notifySubscription = this._monitorCharacteristic(transport$1.notifyCharacteristic, uuid, monitorToken, notifyTransactionId);
|
|
754
|
+
transportCache[uuid] = transport$1;
|
|
755
|
+
this.protocolV2HighVolumeLogSignatures.set(uuid, new Set());
|
|
756
|
+
this.protocolV2Assemblers.set(uuid, new transport.ProtocolV2FrameAssembler(transport.PROTOCOL_V2_BLE_FRAME_MAX_BYTES));
|
|
757
|
+
if (reactNative.Platform.OS === 'ios') {
|
|
758
|
+
yield new Promise(resolve => {
|
|
759
|
+
setTimeout(resolve, IOS_NOTIFY_READY_DELAY_MS);
|
|
760
|
+
});
|
|
761
|
+
}
|
|
762
|
+
else if (reactNative.Platform.OS === 'android') {
|
|
763
|
+
yield delay(ANDROID_NOTIFY_READY_DELAY_MS);
|
|
764
|
+
}
|
|
765
|
+
const initialMtu = transport$1.mtuSize;
|
|
766
|
+
let refreshAttempts = 0;
|
|
767
|
+
if ((reactNative.Platform.OS === 'ios' || reactNative.Platform.OS === 'android') &&
|
|
768
|
+
shouldRefreshNegotiatedMtu(transport$1.mtuSize)) {
|
|
769
|
+
refreshAttempts += 1;
|
|
770
|
+
let refreshedDevice = yield requestNegotiatedMtu(transport$1.device, 'servicesAndNotifyReady', 1);
|
|
771
|
+
transport$1.device = refreshedDevice;
|
|
772
|
+
transport$1.mtuSize =
|
|
773
|
+
typeof refreshedDevice.mtu === 'number' ? refreshedDevice.mtu : transport$1.mtuSize;
|
|
774
|
+
if (shouldRefreshNegotiatedMtu(transport$1.mtuSize)) {
|
|
775
|
+
yield delay(BLE_MTU_REFRESH_RETRY_DELAY_MS);
|
|
776
|
+
refreshAttempts += 1;
|
|
777
|
+
refreshedDevice = yield requestNegotiatedMtu(transport$1.device, 'servicesAndNotifyReady', 2);
|
|
778
|
+
transport$1.device = refreshedDevice;
|
|
779
|
+
transport$1.mtuSize =
|
|
780
|
+
typeof refreshedDevice.mtu === 'number' ? refreshedDevice.mtu : transport$1.mtuSize;
|
|
781
|
+
}
|
|
782
|
+
}
|
|
783
|
+
Log === null || Log === void 0 ? void 0 : Log.debug('[ReactNativeBleTransport] BLE MTU ready', {
|
|
784
|
+
platform: reactNative.Platform.OS,
|
|
785
|
+
requested: getRequestedBleMtu(),
|
|
786
|
+
initial: initialMtu,
|
|
787
|
+
actual: transport$1.mtuSize,
|
|
788
|
+
refreshAttempts,
|
|
789
|
+
});
|
|
790
|
+
return transport$1;
|
|
791
|
+
});
|
|
792
|
+
}
|
|
708
793
|
acquire(input) {
|
|
709
|
-
var _a, _b;
|
|
710
794
|
return __awaiter(this, void 0, void 0, function* () {
|
|
711
|
-
const { uuid
|
|
795
|
+
const { uuid } = input;
|
|
712
796
|
if (!uuid) {
|
|
713
797
|
throw hdShared.ERRORS.TypedError(hdShared.HardwareErrorCode.BleRequiredUUID);
|
|
714
798
|
}
|
|
799
|
+
return this.runLifecycleOperation(uuid, () => this.acquireUnlocked(input));
|
|
800
|
+
});
|
|
801
|
+
}
|
|
802
|
+
acquireUnlocked(input) {
|
|
803
|
+
var _a;
|
|
804
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
805
|
+
const { uuid, forceCleanRunPromise, expectedProtocol, skipProtocolProbe } = input;
|
|
715
806
|
const cachedTransport = transportCache[uuid];
|
|
716
807
|
if (cachedTransport) {
|
|
717
808
|
const cachedProtocol = this.deviceProtocol.get(uuid);
|
|
@@ -723,14 +814,14 @@ class ReactNativeBleTransport {
|
|
|
723
814
|
return { uuid, protocolType: cachedProtocol };
|
|
724
815
|
}
|
|
725
816
|
Log === null || Log === void 0 ? void 0 : Log.debug('transport not reusable, will release: ', uuid);
|
|
726
|
-
yield this.
|
|
817
|
+
yield this.releaseUnlocked(uuid, true);
|
|
727
818
|
}
|
|
728
819
|
let device = null;
|
|
729
820
|
if (forceCleanRunPromise && this.runPromise) {
|
|
730
821
|
const error = hdShared.ERRORS.TypedError(hdShared.HardwareErrorCode.BleForceCleanRunPromise);
|
|
731
822
|
this.runPromise.reject(error);
|
|
732
|
-
this.rejectAllProtocolV2Frames(error);
|
|
733
823
|
this.runPromise = null;
|
|
824
|
+
this.runPromiseDeviceId = null;
|
|
734
825
|
Log === null || Log === void 0 ? void 0 : Log.debug('Force clean Bluetooth run promise, forceCleanRunPromise: ', forceCleanRunPromise);
|
|
735
826
|
}
|
|
736
827
|
const blePlxManager = yield this.getPlxManager();
|
|
@@ -763,14 +854,17 @@ class ReactNativeBleTransport {
|
|
|
763
854
|
if (!device) {
|
|
764
855
|
Log === null || Log === void 0 ? void 0 : Log.debug('try to connect to device: ', uuid);
|
|
765
856
|
try {
|
|
766
|
-
device = yield blePlxManager.connectToDevice(uuid, connectOptions);
|
|
857
|
+
device = yield this.connectWithTimeout(uuid, () => blePlxManager.connectToDevice(uuid, connectOptions));
|
|
767
858
|
}
|
|
768
859
|
catch (e) {
|
|
769
860
|
Log === null || Log === void 0 ? void 0 : Log.debug('try to connect to device has error: ', e);
|
|
861
|
+
if (shouldRethrowBleSetupError(e)) {
|
|
862
|
+
throw e;
|
|
863
|
+
}
|
|
770
864
|
if (e.errorCode === reactNativeBlePlx.BleErrorCode.DeviceMTUChangeFailed ||
|
|
771
865
|
e.errorCode === reactNativeBlePlx.BleErrorCode.OperationCancelled) {
|
|
772
866
|
Log === null || Log === void 0 ? void 0 : Log.debug('first try to reconnect without params');
|
|
773
|
-
device = yield blePlxManager.connectToDevice(uuid);
|
|
867
|
+
device = yield this.connectWithTimeout(uuid, () => blePlxManager.connectToDevice(uuid, fallbackConnectOptions));
|
|
774
868
|
}
|
|
775
869
|
else if (e.errorCode === reactNativeBlePlx.BleErrorCode.DeviceAlreadyConnected) {
|
|
776
870
|
Log === null || Log === void 0 ? void 0 : Log.debug('device already connected');
|
|
@@ -786,23 +880,27 @@ class ReactNativeBleTransport {
|
|
|
786
880
|
}
|
|
787
881
|
if (!(yield device.isConnected())) {
|
|
788
882
|
Log === null || Log === void 0 ? void 0 : Log.debug('not connected, try to connect to device: ', uuid);
|
|
883
|
+
const disconnectedDevice = device;
|
|
789
884
|
try {
|
|
790
|
-
device = yield
|
|
885
|
+
device = yield this.connectWithTimeout(uuid, () => disconnectedDevice.connect(connectOptions));
|
|
791
886
|
}
|
|
792
887
|
catch (e) {
|
|
793
888
|
Log === null || Log === void 0 ? void 0 : Log.debug('not connected, try to connect to device has error: ', e);
|
|
889
|
+
if (shouldRethrowBleSetupError(e)) {
|
|
890
|
+
throw e;
|
|
891
|
+
}
|
|
794
892
|
if (e.errorCode === reactNativeBlePlx.BleErrorCode.DeviceMTUChangeFailed ||
|
|
795
893
|
e.errorCode === reactNativeBlePlx.BleErrorCode.OperationCancelled) {
|
|
796
894
|
Log === null || Log === void 0 ? void 0 : Log.debug('second try to reconnect without params');
|
|
797
895
|
try {
|
|
798
|
-
device = yield
|
|
896
|
+
device = yield this.connectWithTimeout(uuid, () => disconnectedDevice.connect(fallbackConnectOptions));
|
|
799
897
|
}
|
|
800
898
|
catch (e) {
|
|
801
899
|
Log === null || Log === void 0 ? void 0 : Log.debug('last try to reconnect error: ', e);
|
|
802
900
|
if (e.errorCode === reactNativeBlePlx.BleErrorCode.OperationCancelled) {
|
|
803
901
|
Log === null || Log === void 0 ? void 0 : Log.debug('last try to reconnect');
|
|
804
|
-
yield
|
|
805
|
-
device = yield
|
|
902
|
+
yield disconnectedDevice.cancelConnection();
|
|
903
|
+
device = yield this.connectWithTimeout(uuid, () => disconnectedDevice.connect(fallbackConnectOptions));
|
|
806
904
|
}
|
|
807
905
|
}
|
|
808
906
|
}
|
|
@@ -811,44 +909,59 @@ class ReactNativeBleTransport {
|
|
|
811
909
|
}
|
|
812
910
|
}
|
|
813
911
|
}
|
|
814
|
-
device = yield
|
|
815
|
-
const
|
|
912
|
+
device = yield resolveNegotiatedMtu(device);
|
|
913
|
+
const acquiredDevice = device;
|
|
914
|
+
const { writeCharacteristic, notifyCharacteristic } = yield this.resolveCharacteristicsWithTimeout(uuid, acquiredDevice);
|
|
816
915
|
const protocolHint = expectedProtocol
|
|
817
916
|
? undefined
|
|
818
|
-
: (_a =
|
|
819
|
-
yield this.
|
|
917
|
+
: (_a = input.protocolHint) !== null && _a !== void 0 ? _a : this.deviceProtocolHints.get(uuid);
|
|
918
|
+
yield this.releaseUnlocked(uuid, true);
|
|
820
919
|
if (protocolHint) {
|
|
821
920
|
this.deviceProtocolHints.set(uuid, protocolHint);
|
|
822
921
|
}
|
|
823
|
-
|
|
824
|
-
|
|
825
|
-
|
|
826
|
-
}
|
|
827
|
-
|
|
828
|
-
|
|
829
|
-
|
|
830
|
-
|
|
831
|
-
|
|
832
|
-
|
|
833
|
-
|
|
834
|
-
|
|
835
|
-
|
|
836
|
-
|
|
837
|
-
|
|
838
|
-
|
|
839
|
-
|
|
922
|
+
yield this.installTransportForAcquire(uuid, acquiredDevice, {
|
|
923
|
+
writeCharacteristic,
|
|
924
|
+
notifyCharacteristic,
|
|
925
|
+
});
|
|
926
|
+
try {
|
|
927
|
+
if (skipProtocolProbe) {
|
|
928
|
+
if (!expectedProtocol) {
|
|
929
|
+
throw hdShared.ERRORS.TypedError(hdShared.HardwareErrorCode.RuntimeError, 'skipProtocolProbe requires an expected BLE protocol');
|
|
930
|
+
}
|
|
931
|
+
this.deviceProtocol.set(uuid, expectedProtocol);
|
|
932
|
+
this.sessionProtocols.set(uuid, expectedProtocol);
|
|
933
|
+
this.protocolReprobeFailures.delete(uuid);
|
|
934
|
+
Log === null || Log === void 0 ? void 0 : Log.debug('[ReactNativeBleTransport] protocol selected without probe', {
|
|
935
|
+
deviceId: uuid,
|
|
936
|
+
protocol: expectedProtocol,
|
|
937
|
+
source: 'firmware-install-reconnect',
|
|
938
|
+
});
|
|
939
|
+
const currentTransport = transportCache[uuid];
|
|
940
|
+
if (!currentTransport) {
|
|
941
|
+
throw hdShared.ERRORS.TypedError(hdShared.HardwareErrorCode.TransportNotFound);
|
|
942
|
+
}
|
|
943
|
+
this.attachDisconnectSubscription(currentTransport, currentTransport.device, uuid);
|
|
944
|
+
return { uuid, protocolType: expectedProtocol };
|
|
945
|
+
}
|
|
946
|
+
const protocolType = yield this.detectProtocol(uuid, expectedProtocol, protocolHint, () => __awaiter(this, void 0, void 0, function* () {
|
|
947
|
+
yield this.installTransportForAcquire(uuid, acquiredDevice);
|
|
948
|
+
}));
|
|
949
|
+
const currentTransport = transportCache[uuid];
|
|
950
|
+
if (!currentTransport) {
|
|
951
|
+
throw hdShared.ERRORS.TypedError(hdShared.HardwareErrorCode.TransportNotFound);
|
|
952
|
+
}
|
|
953
|
+
this.attachDisconnectSubscription(currentTransport, currentTransport.device, uuid);
|
|
954
|
+
return { uuid, protocolType };
|
|
840
955
|
}
|
|
841
|
-
|
|
842
|
-
|
|
956
|
+
catch (error) {
|
|
957
|
+
if ((error === null || error === void 0 ? void 0 : error.errorCode) === hdShared.HardwareErrorCode.BleDeviceBondError) {
|
|
958
|
+
yield this.disconnectUnlocked(uuid);
|
|
959
|
+
}
|
|
960
|
+
else {
|
|
961
|
+
yield this.releaseUnlocked(uuid, true);
|
|
962
|
+
}
|
|
963
|
+
throw error;
|
|
843
964
|
}
|
|
844
|
-
const protocolType = yield this.detectProtocol(uuid, expectedProtocol, protocolHint);
|
|
845
|
-
(_b = this.emitter) === null || _b === void 0 ? void 0 : _b.emit('device-connect', {
|
|
846
|
-
name: device.name,
|
|
847
|
-
id: device.id,
|
|
848
|
-
connectId: device.id,
|
|
849
|
-
});
|
|
850
|
-
this.attachDisconnectSubscription(transport$1, device, uuid);
|
|
851
|
-
return { uuid, protocolType };
|
|
852
965
|
});
|
|
853
966
|
}
|
|
854
967
|
_monitorCharacteristic(characteristic, uuid, monitorToken, notifyTransactionId) {
|
|
@@ -867,7 +980,7 @@ class ReactNativeBleTransport {
|
|
|
867
980
|
Log === null || Log === void 0 ? void 0 : Log.debug('monitor error ignored for stale transport: ', uuid, notifyTransactionId);
|
|
868
981
|
return;
|
|
869
982
|
}
|
|
870
|
-
if (this.
|
|
983
|
+
if (this.getActiveProtocol(uuid) === 'V2') {
|
|
871
984
|
let errorCode = hdShared.HardwareErrorCode.BleCharacteristicNotifyError;
|
|
872
985
|
if ((_a = error.reason) === null || _a === void 0 ? void 0 : _a.includes('The connection has timed out unexpectedly')) {
|
|
873
986
|
errorCode = hdShared.HardwareErrorCode.BleTimeoutError;
|
|
@@ -885,7 +998,7 @@ class ReactNativeBleTransport {
|
|
|
885
998
|
this.rejectProtocolV2Frames(uuid, hdShared.ERRORS.TypedError(errorCode));
|
|
886
999
|
return;
|
|
887
1000
|
}
|
|
888
|
-
if (this.runPromise) {
|
|
1001
|
+
if (this.runPromise && this.runPromiseDeviceId === uuid) {
|
|
889
1002
|
let ERROR = hdShared.HardwareErrorCode.BleCharacteristicNotifyError;
|
|
890
1003
|
if ((_h = error.reason) === null || _h === void 0 ? void 0 : _h.includes('The connection has timed out unexpectedly')) {
|
|
891
1004
|
ERROR = hdShared.HardwareErrorCode.BleTimeoutError;
|
|
@@ -900,13 +1013,11 @@ class ReactNativeBleTransport {
|
|
|
900
1013
|
((_p = error.reason) === null || _p === void 0 ? void 0 : _p.includes('notify change failed for device'))) {
|
|
901
1014
|
const notifyError = hdShared.ERRORS.TypedError(hdShared.HardwareErrorCode.BleCharacteristicNotifyChangeFailure);
|
|
902
1015
|
this.runPromise.reject(notifyError);
|
|
903
|
-
this.rejectAllProtocolV2Frames(notifyError);
|
|
904
1016
|
Log === null || Log === void 0 ? void 0 : Log.debug(`${hdShared.HardwareErrorCode.BleCharacteristicNotifyChangeFailure} ${error.message} ${error.reason}`);
|
|
905
1017
|
return;
|
|
906
1018
|
}
|
|
907
1019
|
const notifyError = hdShared.ERRORS.TypedError(ERROR);
|
|
908
1020
|
this.runPromise.reject(notifyError);
|
|
909
|
-
this.rejectAllProtocolV2Frames(notifyError);
|
|
910
1021
|
Log === null || Log === void 0 ? void 0 : Log.debug(': monitor notify error, and has unreleased Promise', Error);
|
|
911
1022
|
}
|
|
912
1023
|
return;
|
|
@@ -920,7 +1031,7 @@ class ReactNativeBleTransport {
|
|
|
920
1031
|
}
|
|
921
1032
|
try {
|
|
922
1033
|
const data = buffer.Buffer.from(c.value, 'base64');
|
|
923
|
-
const protocol = this.
|
|
1034
|
+
const protocol = this.getActiveProtocol(uuid);
|
|
924
1035
|
if (!protocol) {
|
|
925
1036
|
Log === null || Log === void 0 ? void 0 : Log.debug('monitor data ignored before protocol detection: ', uuid);
|
|
926
1037
|
return;
|
|
@@ -940,16 +1051,18 @@ class ReactNativeBleTransport {
|
|
|
940
1051
|
const value = buffer.Buffer.from(buffer$1);
|
|
941
1052
|
bufferLength = 0;
|
|
942
1053
|
buffer$1 = [];
|
|
943
|
-
(
|
|
1054
|
+
if (this.runPromiseDeviceId === uuid) {
|
|
1055
|
+
(_q = this.runPromise) === null || _q === void 0 ? void 0 : _q.resolve(value.toString('hex'));
|
|
1056
|
+
}
|
|
944
1057
|
}
|
|
945
1058
|
}
|
|
946
1059
|
catch (error) {
|
|
947
1060
|
Log === null || Log === void 0 ? void 0 : Log.debug('monitor data error: ', error);
|
|
948
1061
|
const notifyError = hdShared.ERRORS.TypedError(hdShared.HardwareErrorCode.BleWriteCharacteristicError);
|
|
949
|
-
if (this.
|
|
1062
|
+
if (this.getActiveProtocol(uuid) === 'V2') {
|
|
950
1063
|
this.rejectProtocolV2Frames(uuid, notifyError);
|
|
951
1064
|
}
|
|
952
|
-
else {
|
|
1065
|
+
else if (this.runPromiseDeviceId === uuid) {
|
|
953
1066
|
(_r = this.runPromise) === null || _r === void 0 ? void 0 : _r.reject(notifyError);
|
|
954
1067
|
}
|
|
955
1068
|
}
|
|
@@ -957,15 +1070,27 @@ class ReactNativeBleTransport {
|
|
|
957
1070
|
return subscription;
|
|
958
1071
|
}
|
|
959
1072
|
release(uuid, onclose = false) {
|
|
960
|
-
var _a, _b, _c, _d, _e, _f, _g;
|
|
961
1073
|
return __awaiter(this, void 0, void 0, function* () {
|
|
962
|
-
|
|
1074
|
+
return this.runLifecycleOperation(uuid, () => this.releaseUnlocked(uuid, onclose));
|
|
1075
|
+
});
|
|
1076
|
+
}
|
|
1077
|
+
releaseUnlocked(uuid, onclose = false) {
|
|
1078
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
963
1079
|
yield this.protocolV2Links.invalidateLink(uuid, 'React Native BLE transport released');
|
|
964
|
-
|
|
1080
|
+
return this.releaseNative(uuid, onclose);
|
|
1081
|
+
});
|
|
1082
|
+
}
|
|
1083
|
+
releaseNative(uuid, onclose = false) {
|
|
1084
|
+
var _a, _b, _c, _d, _e;
|
|
1085
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
1086
|
+
const transport = transportCache[uuid];
|
|
1087
|
+
const manager = this.blePlxManager;
|
|
1088
|
+
if (this.runPromise && this.runPromiseDeviceId === uuid) {
|
|
965
1089
|
const error = hdShared.ERRORS.TypedError(hdShared.HardwareErrorCode.BleForceCleanRunPromise);
|
|
966
1090
|
this.runPromise.reject(error);
|
|
967
1091
|
this.runPromise = null;
|
|
968
|
-
this.
|
|
1092
|
+
this.runPromiseDeviceId = null;
|
|
1093
|
+
this.rejectProtocolV2Frames(uuid, error);
|
|
969
1094
|
}
|
|
970
1095
|
else {
|
|
971
1096
|
this.resetProtocolV2Frames(uuid);
|
|
@@ -985,31 +1110,37 @@ class ReactNativeBleTransport {
|
|
|
985
1110
|
Log === null || Log === void 0 ? void 0 : Log.debug('release: removing notify subscription, characteristic: ', (_c = transport.notifyCharacteristic) === null || _c === void 0 ? void 0 : _c.uuid);
|
|
986
1111
|
(_d = transport.notifySubscription) === null || _d === void 0 ? void 0 : _d.remove();
|
|
987
1112
|
transport.notifySubscription = undefined;
|
|
988
|
-
if (transport
|
|
989
|
-
|
|
990
|
-
yield ((_e = this.blePlxManager) === null || _e === void 0 ? void 0 : _e.cancelTransaction(transport.notifyTransactionId));
|
|
991
|
-
}
|
|
992
|
-
catch (e) {
|
|
993
|
-
Log === null || Log === void 0 ? void 0 : Log.debug('release: cancel notify transaction error (ignored): ', (e === null || e === void 0 ? void 0 : e.message) || e);
|
|
994
|
-
}
|
|
1113
|
+
if (transportCache[uuid] === transport) {
|
|
1114
|
+
delete transportCache[uuid];
|
|
995
1115
|
}
|
|
996
|
-
delete transportCache[uuid];
|
|
997
1116
|
}
|
|
1117
|
+
this.protocolV2HighVolumeLogSignatures.delete(uuid);
|
|
998
1118
|
this.deviceProtocol.delete(uuid);
|
|
999
|
-
|
|
1119
|
+
this.probingProtocols.delete(uuid);
|
|
1120
|
+
(_e = this.protocolV2Assemblers.get(uuid)) === null || _e === void 0 ? void 0 : _e.reset();
|
|
1000
1121
|
this.protocolV2Assemblers.delete(uuid);
|
|
1001
1122
|
this.resetProtocolV2Frames(uuid);
|
|
1002
|
-
|
|
1003
|
-
|
|
1004
|
-
|
|
1005
|
-
|
|
1006
|
-
|
|
1007
|
-
|
|
1123
|
+
yield this.runNativeTeardown(uuid, manager, () => __awaiter(this, void 0, void 0, function* () {
|
|
1124
|
+
const operations = [
|
|
1125
|
+
this.runBestEffortNativeOperation('release: restore connection priority', () => this.restoreAndroidConnectionPriority(uuid, transport)),
|
|
1126
|
+
];
|
|
1127
|
+
if ((transport === null || transport === void 0 ? void 0 : transport.notifyTransactionId) && manager) {
|
|
1128
|
+
operations.push(this.runBestEffortNativeOperation('release: cancel notify transaction', () => manager.cancelTransaction(transport.notifyTransactionId)));
|
|
1129
|
+
}
|
|
1130
|
+
if (manager) {
|
|
1131
|
+
operations.push(this.runBestEffortNativeOperation('release: cancel transaction', () => manager.cancelTransaction(uuid)));
|
|
1132
|
+
}
|
|
1133
|
+
yield Promise.all(operations);
|
|
1134
|
+
}));
|
|
1008
1135
|
return Promise.resolve(true);
|
|
1009
1136
|
});
|
|
1010
1137
|
}
|
|
1011
1138
|
post(session, name, data) {
|
|
1012
1139
|
return __awaiter(this, void 0, void 0, function* () {
|
|
1140
|
+
if (this.getProtocolType(session) === 'V2') {
|
|
1141
|
+
yield this.protocolV2Links.sendFlowControl(session, () => this.createProtocolV2Adapter(session), name, data);
|
|
1142
|
+
return;
|
|
1143
|
+
}
|
|
1013
1144
|
yield this.call(session, name, data);
|
|
1014
1145
|
});
|
|
1015
1146
|
}
|
|
@@ -1025,7 +1156,6 @@ class ReactNativeBleTransport {
|
|
|
1025
1156
|
if (!protocol) {
|
|
1026
1157
|
throw hdShared.ERRORS.TypedError(hdShared.HardwareErrorCode.RuntimeError, `Device protocol has not been detected for ${uuid}`);
|
|
1027
1158
|
}
|
|
1028
|
-
Log === null || Log === void 0 ? void 0 : Log.debug('transport call', createTransportCallLog(name, protocol, data));
|
|
1029
1159
|
if (protocol === 'V2') {
|
|
1030
1160
|
return this.callProtocolV2(uuid, name, data, options);
|
|
1031
1161
|
}
|
|
@@ -1044,7 +1174,19 @@ class ReactNativeBleTransport {
|
|
|
1044
1174
|
const transport = this.getCachedTransport(uuid);
|
|
1045
1175
|
const runPromise = hdShared.createDeferred();
|
|
1046
1176
|
runPromise.promise.catch(() => undefined);
|
|
1177
|
+
const supersededRunPromise = this.runPromise;
|
|
1178
|
+
if (supersededRunPromise) {
|
|
1179
|
+
supersededRunPromise.reject(hdShared.ERRORS.TypedError(hdShared.HardwareErrorCode.BleForceCleanRunPromise));
|
|
1180
|
+
}
|
|
1047
1181
|
this.runPromise = runPromise;
|
|
1182
|
+
this.runPromiseDeviceId = uuid;
|
|
1183
|
+
const releaseOwnershipIfCurrent = () => {
|
|
1184
|
+
if (this.runPromise === runPromise) {
|
|
1185
|
+
this.runPromise = null;
|
|
1186
|
+
this.runPromiseDeviceId = null;
|
|
1187
|
+
}
|
|
1188
|
+
};
|
|
1189
|
+
const isCurrentOwner = () => this.runPromise === runPromise;
|
|
1048
1190
|
const messages = this._messages;
|
|
1049
1191
|
const buffers = ProtocolV1.encodeTransportPackets(messages, name, data);
|
|
1050
1192
|
let timeout;
|
|
@@ -1065,6 +1207,9 @@ class ReactNativeBleTransport {
|
|
|
1065
1207
|
}
|
|
1066
1208
|
catch (e) {
|
|
1067
1209
|
onError(e);
|
|
1210
|
+
if (isWedgedWriteError(e)) {
|
|
1211
|
+
throw e;
|
|
1212
|
+
}
|
|
1068
1213
|
throw hdShared.ERRORS.TypedError(hdShared.HardwareErrorCode.BleWriteCharacteristicError);
|
|
1069
1214
|
}
|
|
1070
1215
|
}
|
|
@@ -1092,6 +1237,9 @@ class ReactNativeBleTransport {
|
|
|
1092
1237
|
}
|
|
1093
1238
|
catch (e) {
|
|
1094
1239
|
onError(e);
|
|
1240
|
+
if (isWedgedWriteError(e)) {
|
|
1241
|
+
throw e;
|
|
1242
|
+
}
|
|
1095
1243
|
throw hdShared.ERRORS.TypedError(hdShared.HardwareErrorCode.BleWriteCharacteristicError);
|
|
1096
1244
|
}
|
|
1097
1245
|
}
|
|
@@ -1102,8 +1250,8 @@ class ReactNativeBleTransport {
|
|
|
1102
1250
|
});
|
|
1103
1251
|
}
|
|
1104
1252
|
if (name === 'EmmcFileWrite') {
|
|
1105
|
-
yield writeChunkedData(buffers, data => transport.writeWithRetry(
|
|
1106
|
-
|
|
1253
|
+
yield writeChunkedData(buffers, data => this.writeBlePacket(uuid, data, payload => transport.writeWithRetry(payload), isCurrentOwner), e => {
|
|
1254
|
+
releaseOwnershipIfCurrent();
|
|
1107
1255
|
Log === null || Log === void 0 ? void 0 : Log.error('writeCharacteristic write error: ', e);
|
|
1108
1256
|
});
|
|
1109
1257
|
}
|
|
@@ -1119,7 +1267,7 @@ class ReactNativeBleTransport {
|
|
|
1119
1267
|
let attempt = 0;
|
|
1120
1268
|
while (true) {
|
|
1121
1269
|
try {
|
|
1122
|
-
yield transport.
|
|
1270
|
+
yield this.writeBlePacket(uuid, data, payload => transport.writeWithRetry(payload), isCurrentOwner);
|
|
1123
1271
|
return;
|
|
1124
1272
|
}
|
|
1125
1273
|
catch (error) {
|
|
@@ -1127,36 +1275,18 @@ class ReactNativeBleTransport {
|
|
|
1127
1275
|
if (!retryType || attempt >= FIRMWARE_UPLOAD_WRITE_MAX_RETRIES) {
|
|
1128
1276
|
throw error;
|
|
1129
1277
|
}
|
|
1130
|
-
const
|
|
1131
|
-
const delayMs = shouldReconnect
|
|
1132
|
-
? FIRMWARE_UPLOAD_RECONNECT_RETRY_DELAY_MS
|
|
1133
|
-
: resolveFirmwareUploadRetryDelay(attempt);
|
|
1278
|
+
const delayMs = resolveFirmwareUploadRetryDelay(attempt);
|
|
1134
1279
|
Log === null || Log === void 0 ? void 0 : Log.debug('[ReactNativeBleTransport] FirmwareUpload write retry:', {
|
|
1135
1280
|
attempt: attempt + 1,
|
|
1136
1281
|
delayMs,
|
|
1137
|
-
reconnect: shouldReconnect,
|
|
1138
1282
|
error,
|
|
1139
1283
|
});
|
|
1140
|
-
if (shouldReconnect) {
|
|
1141
|
-
this.firmwareUploadWriteRecoveryIds.add(uuid);
|
|
1142
|
-
}
|
|
1143
1284
|
yield delay(delayMs);
|
|
1144
1285
|
attempt += 1;
|
|
1145
|
-
if (shouldReconnect) {
|
|
1146
|
-
try {
|
|
1147
|
-
yield this.reconnectFirmwareUploadTransport(uuid, transport);
|
|
1148
|
-
}
|
|
1149
|
-
catch (e) {
|
|
1150
|
-
Log === null || Log === void 0 ? void 0 : Log.debug('[ReactNativeBleTransport] FirmwareUpload reconnect error:', e);
|
|
1151
|
-
if (attempt >= FIRMWARE_UPLOAD_WRITE_MAX_RETRIES) {
|
|
1152
|
-
throw e;
|
|
1153
|
-
}
|
|
1154
|
-
}
|
|
1155
|
-
}
|
|
1156
1286
|
}
|
|
1157
1287
|
}
|
|
1158
1288
|
}), e => {
|
|
1159
|
-
|
|
1289
|
+
releaseOwnershipIfCurrent();
|
|
1160
1290
|
Log === null || Log === void 0 ? void 0 : Log.error('writeCharacteristic write error: ', e);
|
|
1161
1291
|
});
|
|
1162
1292
|
}
|
|
@@ -1164,11 +1294,17 @@ class ReactNativeBleTransport {
|
|
|
1164
1294
|
for (const o of buffers) {
|
|
1165
1295
|
const outData = o.toString('base64');
|
|
1166
1296
|
try {
|
|
1167
|
-
|
|
1297
|
+
const shouldUseWriteWithResponse = reactNative.Platform.OS === 'ios' && transport.writeCharacteristic.isWritableWithResponse;
|
|
1298
|
+
yield this.writeBlePacket(uuid, outData, payload => shouldUseWriteWithResponse
|
|
1299
|
+
? transport.writeCharacteristic.writeWithResponse(payload)
|
|
1300
|
+
: transport.writeCharacteristic.writeWithoutResponse(payload), isCurrentOwner);
|
|
1168
1301
|
}
|
|
1169
1302
|
catch (e) {
|
|
1170
1303
|
Log === null || Log === void 0 ? void 0 : Log.debug('writeCharacteristic write error: ', e);
|
|
1171
|
-
|
|
1304
|
+
releaseOwnershipIfCurrent();
|
|
1305
|
+
if (isWedgedWriteError(e)) {
|
|
1306
|
+
throw e;
|
|
1307
|
+
}
|
|
1172
1308
|
if (e.errorCode === reactNativeBlePlx.BleErrorCode.DeviceDisconnected) {
|
|
1173
1309
|
throw hdShared.ERRORS.TypedError(hdShared.HardwareErrorCode.BleDeviceNotBonded);
|
|
1174
1310
|
}
|
|
@@ -1201,12 +1337,19 @@ class ReactNativeBleTransport {
|
|
|
1201
1337
|
return check.call(jsonData);
|
|
1202
1338
|
}
|
|
1203
1339
|
catch (e) {
|
|
1204
|
-
if (name === '
|
|
1205
|
-
Log === null || Log === void 0 ? void 0 : Log.debug('[ReactNativeBleTransport] Protocol V1
|
|
1340
|
+
if (name === 'GetFeatures' && (options === null || options === void 0 ? void 0 : options.timeoutMs) === PROTOCOL_PROBE_TIMEOUT_MS) {
|
|
1341
|
+
Log === null || Log === void 0 ? void 0 : Log.debug('[ReactNativeBleTransport] Protocol V1 GetFeatures probe call failed:', e);
|
|
1206
1342
|
}
|
|
1207
1343
|
else {
|
|
1208
1344
|
Log === null || Log === void 0 ? void 0 : Log.error('call error: ', e);
|
|
1209
1345
|
}
|
|
1346
|
+
const isProbeTimeout = name === 'GetFeatures' && (options === null || options === void 0 ? void 0 : options.timeoutMs) === PROTOCOL_PROBE_TIMEOUT_MS;
|
|
1347
|
+
const isStaleCall = this.runPromise !== runPromise;
|
|
1348
|
+
if (!isProbeTimeout &&
|
|
1349
|
+
!isStaleCall &&
|
|
1350
|
+
(e === null || e === void 0 ? void 0 : e.errorCode) === hdShared.HardwareErrorCode.BleTimeoutError) {
|
|
1351
|
+
yield this.disconnect(uuid);
|
|
1352
|
+
}
|
|
1210
1353
|
throw e;
|
|
1211
1354
|
}
|
|
1212
1355
|
finally {
|
|
@@ -1214,6 +1357,7 @@ class ReactNativeBleTransport {
|
|
|
1214
1357
|
clearTimeout(timeout);
|
|
1215
1358
|
if (this.runPromise === runPromise) {
|
|
1216
1359
|
this.runPromise = null;
|
|
1360
|
+
this.runPromiseDeviceId = null;
|
|
1217
1361
|
}
|
|
1218
1362
|
}
|
|
1219
1363
|
});
|
|
@@ -1222,10 +1366,17 @@ class ReactNativeBleTransport {
|
|
|
1222
1366
|
this.stopped = true;
|
|
1223
1367
|
}
|
|
1224
1368
|
disconnect(session) {
|
|
1225
|
-
|
|
1369
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
1370
|
+
return this.runLifecycleOperation(session, () => this.disconnectUnlocked(session));
|
|
1371
|
+
});
|
|
1372
|
+
}
|
|
1373
|
+
disconnectUnlocked(session) {
|
|
1374
|
+
var _a, _b, _c;
|
|
1226
1375
|
return __awaiter(this, void 0, void 0, function* () {
|
|
1227
1376
|
yield this.protocolV2Links.invalidateLink(session, 'React Native BLE transport disconnected');
|
|
1228
1377
|
const transport = transportCache[session];
|
|
1378
|
+
const manager = this.blePlxManager;
|
|
1379
|
+
const monitorToken = (_a = transport === null || transport === void 0 ? void 0 : transport.monitorToken) !== null && _a !== void 0 ? _a : this.monitorTokens.get(session);
|
|
1229
1380
|
if (transport === null || transport === void 0 ? void 0 : transport.disconnectSubscription) {
|
|
1230
1381
|
try {
|
|
1231
1382
|
Log === null || Log === void 0 ? void 0 : Log.debug('disconnect: removing disconnect subscription');
|
|
@@ -1238,7 +1389,7 @@ class ReactNativeBleTransport {
|
|
|
1238
1389
|
}
|
|
1239
1390
|
if (transport === null || transport === void 0 ? void 0 : transport.notifySubscription) {
|
|
1240
1391
|
try {
|
|
1241
|
-
Log === null || Log === void 0 ? void 0 : Log.debug('disconnect: removing notify subscription, characteristic: ', (
|
|
1392
|
+
Log === null || Log === void 0 ? void 0 : Log.debug('disconnect: removing notify subscription, characteristic: ', (_b = transport.notifyCharacteristic) === null || _b === void 0 ? void 0 : _b.uuid);
|
|
1242
1393
|
transport.notifySubscription.remove();
|
|
1243
1394
|
transport.notifySubscription = undefined;
|
|
1244
1395
|
}
|
|
@@ -1246,52 +1397,201 @@ class ReactNativeBleTransport {
|
|
|
1246
1397
|
Log === null || Log === void 0 ? void 0 : Log.error('disconnect: remove notify subscription error: ', e);
|
|
1247
1398
|
}
|
|
1248
1399
|
}
|
|
1249
|
-
if (session) {
|
|
1250
|
-
try {
|
|
1251
|
-
yield ((_b = this.blePlxManager) === null || _b === void 0 ? void 0 : _b.cancelTransaction(session));
|
|
1252
|
-
}
|
|
1253
|
-
catch (e) {
|
|
1254
|
-
Log === null || Log === void 0 ? void 0 : Log.debug('resetSession: cancel transaction error (ignored): ', (e === null || e === void 0 ? void 0 : e.message) || e);
|
|
1255
|
-
}
|
|
1256
|
-
}
|
|
1257
|
-
if (transport === null || transport === void 0 ? void 0 : transport.device) {
|
|
1258
|
-
try {
|
|
1259
|
-
yield transport.device.cancelConnection();
|
|
1260
|
-
}
|
|
1261
|
-
catch (e) {
|
|
1262
|
-
Log === null || Log === void 0 ? void 0 : Log.debug('resetSession: device.cancelConnection error (ignored): ', (e === null || e === void 0 ? void 0 : e.message) || e);
|
|
1263
|
-
}
|
|
1264
|
-
}
|
|
1265
|
-
try {
|
|
1266
|
-
yield ((_c = this.blePlxManager) === null || _c === void 0 ? void 0 : _c.cancelDeviceConnection(session));
|
|
1267
|
-
}
|
|
1268
|
-
catch (e) {
|
|
1269
|
-
Log === null || Log === void 0 ? void 0 : Log.debug('resetSession: manager.cancelDeviceConnection error (ignored): ', (e === null || e === void 0 ? void 0 : e.message) || e);
|
|
1270
|
-
}
|
|
1271
|
-
if (transportCache[session]) {
|
|
1400
|
+
if (!transport || transportCache[session] === transport) {
|
|
1272
1401
|
delete transportCache[session];
|
|
1273
1402
|
}
|
|
1274
1403
|
this.deviceProtocol.delete(session);
|
|
1404
|
+
this.probingProtocols.delete(session);
|
|
1275
1405
|
this.deviceProtocolHints.delete(session);
|
|
1406
|
+
this.sessionProtocols.delete(session);
|
|
1407
|
+
this.protocolReprobeFailures.delete(session);
|
|
1276
1408
|
this.protocolV2Assemblers.delete(session);
|
|
1277
1409
|
this.resetProtocolV2Frames(session);
|
|
1278
1410
|
try {
|
|
1279
|
-
(
|
|
1280
|
-
name: (_e = transport === null || transport === void 0 ? void 0 : transport.device) === null || _e === void 0 ? void 0 : _e.name,
|
|
1281
|
-
id: session,
|
|
1282
|
-
connectId: session,
|
|
1283
|
-
});
|
|
1411
|
+
this.emitDeviceDisconnect(session, (_c = transport === null || transport === void 0 ? void 0 : transport.device) === null || _c === void 0 ? void 0 : _c.name, monitorToken);
|
|
1284
1412
|
}
|
|
1285
1413
|
catch (e) {
|
|
1286
1414
|
Log === null || Log === void 0 ? void 0 : Log.error('resetSession: emit disconnect event error: ', e);
|
|
1287
1415
|
}
|
|
1416
|
+
if (monitorToken !== undefined && this.monitorTokens.get(session) === monitorToken) {
|
|
1417
|
+
this.monitorTokens.delete(session);
|
|
1418
|
+
}
|
|
1419
|
+
yield this.runNativeTeardown(session, manager, () => __awaiter(this, void 0, void 0, function* () {
|
|
1420
|
+
const operations = [];
|
|
1421
|
+
if (manager) {
|
|
1422
|
+
operations.push(this.runBestEffortNativeOperation('disconnect: cancel transaction', () => manager.cancelTransaction(session)));
|
|
1423
|
+
operations.push(this.runBestEffortNativeOperation('disconnect: cancel device connection', () => manager.cancelDeviceConnection(session)));
|
|
1424
|
+
}
|
|
1425
|
+
if (transport === null || transport === void 0 ? void 0 : transport.device) {
|
|
1426
|
+
operations.push(this.runBestEffortNativeOperation('disconnect: device cancel connection', () => transport.device.cancelConnection()));
|
|
1427
|
+
}
|
|
1428
|
+
yield Promise.all(operations);
|
|
1429
|
+
}));
|
|
1288
1430
|
yield new Promise(resolve => setTimeout(() => resolve(), 100));
|
|
1289
1431
|
});
|
|
1290
1432
|
}
|
|
1433
|
+
runNativeTeardown(uuid, manager, teardown) {
|
|
1434
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
1435
|
+
let timer;
|
|
1436
|
+
let timedOut = false;
|
|
1437
|
+
const pending = Promise.resolve()
|
|
1438
|
+
.then(teardown)
|
|
1439
|
+
.catch(error => {
|
|
1440
|
+
Log === null || Log === void 0 ? void 0 : Log.debug('BLE native teardown error (ignored): ', (error === null || error === void 0 ? void 0 : error.message) || error);
|
|
1441
|
+
});
|
|
1442
|
+
try {
|
|
1443
|
+
yield Promise.race([
|
|
1444
|
+
pending,
|
|
1445
|
+
new Promise(resolve => {
|
|
1446
|
+
timer = setTimeout(() => {
|
|
1447
|
+
timedOut = true;
|
|
1448
|
+
resolve();
|
|
1449
|
+
}, BLE_NATIVE_TEARDOWN_TIMEOUT_MS);
|
|
1450
|
+
}),
|
|
1451
|
+
]);
|
|
1452
|
+
}
|
|
1453
|
+
finally {
|
|
1454
|
+
if (timer)
|
|
1455
|
+
clearTimeout(timer);
|
|
1456
|
+
}
|
|
1457
|
+
if (timedOut) {
|
|
1458
|
+
Log === null || Log === void 0 ? void 0 : Log.error('[ReactNativeBleTransport] BLE native teardown timed out:', uuid);
|
|
1459
|
+
if (this.blePlxManager === manager) {
|
|
1460
|
+
this.resetPlxManager();
|
|
1461
|
+
}
|
|
1462
|
+
}
|
|
1463
|
+
});
|
|
1464
|
+
}
|
|
1465
|
+
runBestEffortNativeOperation(label, operation) {
|
|
1466
|
+
return Promise.resolve()
|
|
1467
|
+
.then(operation)
|
|
1468
|
+
.catch(error => {
|
|
1469
|
+
Log === null || Log === void 0 ? void 0 : Log.debug(`${label} error (ignored): `, (error === null || error === void 0 ? void 0 : error.message) || error);
|
|
1470
|
+
});
|
|
1471
|
+
}
|
|
1472
|
+
runLifecycleOperation(uuid, operation) {
|
|
1473
|
+
var _a;
|
|
1474
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
1475
|
+
const previousOperation = (_a = this.lifecycleOperations.get(uuid)) !== null && _a !== void 0 ? _a : Promise.resolve();
|
|
1476
|
+
let completeOperation;
|
|
1477
|
+
const operationGate = new Promise(resolve => {
|
|
1478
|
+
completeOperation = resolve;
|
|
1479
|
+
});
|
|
1480
|
+
const operationTail = previousOperation.catch(() => undefined).then(() => operationGate);
|
|
1481
|
+
this.lifecycleOperations.set(uuid, operationTail);
|
|
1482
|
+
yield previousOperation.catch(() => undefined);
|
|
1483
|
+
try {
|
|
1484
|
+
return yield operation();
|
|
1485
|
+
}
|
|
1486
|
+
finally {
|
|
1487
|
+
completeOperation();
|
|
1488
|
+
if (this.lifecycleOperations.get(uuid) === operationTail) {
|
|
1489
|
+
this.lifecycleOperations.delete(uuid);
|
|
1490
|
+
}
|
|
1491
|
+
}
|
|
1492
|
+
});
|
|
1493
|
+
}
|
|
1291
1494
|
cancel() {
|
|
1292
1495
|
Log === null || Log === void 0 ? void 0 : Log.debug('transport-react-native transport cancel');
|
|
1293
1496
|
if (this.runPromise) ;
|
|
1294
1497
|
this.runPromise = null;
|
|
1498
|
+
this.runPromiseDeviceId = null;
|
|
1499
|
+
}
|
|
1500
|
+
connectWithTimeout(uuid, connect) {
|
|
1501
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
1502
|
+
let timer;
|
|
1503
|
+
let timedOut = false;
|
|
1504
|
+
const pending = connect();
|
|
1505
|
+
pending.catch(() => undefined);
|
|
1506
|
+
try {
|
|
1507
|
+
const result = yield Promise.race([
|
|
1508
|
+
pending,
|
|
1509
|
+
new Promise((_, reject) => {
|
|
1510
|
+
timer = setTimeout(() => {
|
|
1511
|
+
timedOut = true;
|
|
1512
|
+
reject(hdShared.ERRORS.TypedError(hdShared.HardwareErrorCode.BleConnectedError, `BLE connect timeout after ${BLE_CONNECT_TIMEOUT_MS}ms for ${uuid}`));
|
|
1513
|
+
}, BLE_CONNECT_TIMEOUT_MS);
|
|
1514
|
+
}),
|
|
1515
|
+
]);
|
|
1516
|
+
return result;
|
|
1517
|
+
}
|
|
1518
|
+
catch (error) {
|
|
1519
|
+
if (timedOut || isNativeOperationTimeoutError(error)) {
|
|
1520
|
+
const resetManager = this.abandonStalledConnection(uuid, timedOut ? 'connect-backstop' : 'connect-native');
|
|
1521
|
+
if (resetManager) {
|
|
1522
|
+
throw this.createWedgedBleSetupError();
|
|
1523
|
+
}
|
|
1524
|
+
}
|
|
1525
|
+
throw error;
|
|
1526
|
+
}
|
|
1527
|
+
finally {
|
|
1528
|
+
if (timer)
|
|
1529
|
+
clearTimeout(timer);
|
|
1530
|
+
}
|
|
1531
|
+
});
|
|
1532
|
+
}
|
|
1533
|
+
resolveCharacteristicsWithTimeout(uuid, device) {
|
|
1534
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
1535
|
+
let timer;
|
|
1536
|
+
let timedOut = false;
|
|
1537
|
+
const pending = this.resolveCharacteristics(device);
|
|
1538
|
+
pending.catch(() => undefined);
|
|
1539
|
+
try {
|
|
1540
|
+
const result = yield Promise.race([
|
|
1541
|
+
pending,
|
|
1542
|
+
new Promise((_, reject) => {
|
|
1543
|
+
timer = setTimeout(() => {
|
|
1544
|
+
timedOut = true;
|
|
1545
|
+
reject(hdShared.ERRORS.TypedError(hdShared.HardwareErrorCode.BleConnectedError, `BLE GATT setup timeout after ${BLE_GATT_SETUP_TIMEOUT_MS}ms for ${uuid}`));
|
|
1546
|
+
}, BLE_GATT_SETUP_TIMEOUT_MS);
|
|
1547
|
+
}),
|
|
1548
|
+
]);
|
|
1549
|
+
this.connectionSetupTimeoutCounts.delete(uuid);
|
|
1550
|
+
return result;
|
|
1551
|
+
}
|
|
1552
|
+
catch (error) {
|
|
1553
|
+
if (timedOut || isNativeOperationTimeoutError(error)) {
|
|
1554
|
+
const resetManager = this.abandonStalledConnection(uuid, timedOut ? 'gatt-backstop' : 'gatt-native');
|
|
1555
|
+
if (resetManager) {
|
|
1556
|
+
throw this.createWedgedBleSetupError();
|
|
1557
|
+
}
|
|
1558
|
+
}
|
|
1559
|
+
throw error;
|
|
1560
|
+
}
|
|
1561
|
+
finally {
|
|
1562
|
+
if (timer)
|
|
1563
|
+
clearTimeout(timer);
|
|
1564
|
+
}
|
|
1565
|
+
});
|
|
1566
|
+
}
|
|
1567
|
+
abandonStalledConnection(uuid, stage) {
|
|
1568
|
+
var _a, _b;
|
|
1569
|
+
const timeouts = ((_a = this.connectionSetupTimeoutCounts.get(uuid)) !== null && _a !== void 0 ? _a : 0) + 1;
|
|
1570
|
+
this.connectionSetupTimeoutCounts.set(uuid, timeouts);
|
|
1571
|
+
Log === null || Log === void 0 ? void 0 : Log.error('[ReactNativeBleTransport] BLE setup timed out:', uuid, {
|
|
1572
|
+
stage,
|
|
1573
|
+
setupTimeoutsSinceSuccess: timeouts,
|
|
1574
|
+
});
|
|
1575
|
+
(_b = this.blePlxManager) === null || _b === void 0 ? void 0 : _b.cancelDeviceConnection(uuid).catch(() => {
|
|
1576
|
+
});
|
|
1577
|
+
const stalled = transportCache[uuid];
|
|
1578
|
+
if (stalled) {
|
|
1579
|
+
delete transportCache[uuid];
|
|
1580
|
+
}
|
|
1581
|
+
this.deviceProtocol.delete(uuid);
|
|
1582
|
+
this.probingProtocols.delete(uuid);
|
|
1583
|
+
this.protocolV2Assemblers.delete(uuid);
|
|
1584
|
+
this.resetProtocolV2Frames(uuid);
|
|
1585
|
+
if (timeouts >= BLE_CONNECT_TIMEOUT_MANAGER_RESET_THRESHOLD) {
|
|
1586
|
+
Log === null || Log === void 0 ? void 0 : Log.error('[ReactNativeBleTransport] BLE setup wedged repeatedly, resetting BLE manager');
|
|
1587
|
+
this.resetPlxManager();
|
|
1588
|
+
this.connectionSetupTimeoutCounts.delete(uuid);
|
|
1589
|
+
return true;
|
|
1590
|
+
}
|
|
1591
|
+
return false;
|
|
1592
|
+
}
|
|
1593
|
+
createWedgedBleSetupError() {
|
|
1594
|
+
return hdShared.ERRORS.TypedError(hdShared.HardwareErrorCode.PollingTimeout, BLE_SETUP_WEDGED_MESSAGE);
|
|
1295
1595
|
}
|
|
1296
1596
|
getCachedTransport(uuid) {
|
|
1297
1597
|
const transport = transportCache[uuid];
|
|
@@ -1300,22 +1600,146 @@ class ReactNativeBleTransport {
|
|
|
1300
1600
|
}
|
|
1301
1601
|
return transport;
|
|
1302
1602
|
}
|
|
1303
|
-
|
|
1304
|
-
return
|
|
1603
|
+
writeBlePacket(uuid, data, write, isCurrentOwner) {
|
|
1604
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
1605
|
+
let timer;
|
|
1606
|
+
let timedOut = false;
|
|
1607
|
+
try {
|
|
1608
|
+
yield Promise.race([
|
|
1609
|
+
write(data),
|
|
1610
|
+
new Promise((_, reject) => {
|
|
1611
|
+
timer = setTimeout(() => {
|
|
1612
|
+
timedOut = true;
|
|
1613
|
+
reject(hdShared.ERRORS.TypedError(hdShared.HardwareErrorCode.BleWriteCharacteristicError, `BLE write timeout after ${BLE_WRITE_PACKET_TIMEOUT_MS}ms`));
|
|
1614
|
+
}, BLE_WRITE_PACKET_TIMEOUT_MS);
|
|
1615
|
+
}),
|
|
1616
|
+
]);
|
|
1617
|
+
this.writeTimeoutCounts.delete(uuid);
|
|
1618
|
+
}
|
|
1619
|
+
catch (error) {
|
|
1620
|
+
if (timedOut) {
|
|
1621
|
+
if (isCurrentOwner && !isCurrentOwner()) {
|
|
1622
|
+
Log === null || Log === void 0 ? void 0 : Log.debug('[ReactNativeBleTransport] stale BLE write timed out, link kept:', uuid);
|
|
1623
|
+
}
|
|
1624
|
+
else {
|
|
1625
|
+
this.tearDownWedgedLink(uuid);
|
|
1626
|
+
}
|
|
1627
|
+
}
|
|
1628
|
+
throw error;
|
|
1629
|
+
}
|
|
1630
|
+
finally {
|
|
1631
|
+
if (timer)
|
|
1632
|
+
clearTimeout(timer);
|
|
1633
|
+
}
|
|
1634
|
+
});
|
|
1635
|
+
}
|
|
1636
|
+
tearDownWedgedLink(uuid) {
|
|
1637
|
+
var _a;
|
|
1638
|
+
const timeouts = ((_a = this.writeTimeoutCounts.get(uuid)) !== null && _a !== void 0 ? _a : 0) + 1;
|
|
1639
|
+
this.writeTimeoutCounts.set(uuid, timeouts);
|
|
1640
|
+
Log === null || Log === void 0 ? void 0 : Log.error('[ReactNativeBleTransport] BLE write timed out, tearing down link:', uuid, {
|
|
1641
|
+
consecutiveWriteTimeouts: timeouts,
|
|
1642
|
+
});
|
|
1643
|
+
const wedged = transportCache[uuid];
|
|
1644
|
+
this.disconnect(uuid).catch(error => {
|
|
1645
|
+
Log === null || Log === void 0 ? void 0 : Log.debug('[ReactNativeBleTransport] wedged link teardown failed (ignored):', error);
|
|
1646
|
+
});
|
|
1647
|
+
if (wedged && transportCache[uuid] === wedged) {
|
|
1648
|
+
delete transportCache[uuid];
|
|
1649
|
+
}
|
|
1650
|
+
this.deviceProtocol.delete(uuid);
|
|
1651
|
+
this.probingProtocols.delete(uuid);
|
|
1652
|
+
this.protocolV2Assemblers.delete(uuid);
|
|
1653
|
+
this.resetProtocolV2Frames(uuid);
|
|
1654
|
+
if (timeouts >= BLE_WRITE_TIMEOUT_MANAGER_RESET_THRESHOLD) {
|
|
1655
|
+
Log === null || Log === void 0 ? void 0 : Log.error('[ReactNativeBleTransport] BLE writes wedged repeatedly, resetting BLE manager');
|
|
1656
|
+
this.resetPlxManager();
|
|
1657
|
+
this.writeTimeoutCounts.delete(uuid);
|
|
1658
|
+
}
|
|
1659
|
+
}
|
|
1660
|
+
resetPlxManager() {
|
|
1661
|
+
const manager = this.blePlxManager;
|
|
1662
|
+
this.blePlxManager = undefined;
|
|
1663
|
+
const reason = 'React Native BLE manager reset';
|
|
1664
|
+
Object.entries(transportCache).forEach(([uuid, cachedTransport]) => {
|
|
1665
|
+
var _a, _b, _c, _d;
|
|
1666
|
+
try {
|
|
1667
|
+
(_a = cachedTransport.disconnectSubscription) === null || _a === void 0 ? void 0 : _a.remove();
|
|
1668
|
+
}
|
|
1669
|
+
catch (error) {
|
|
1670
|
+
Log === null || Log === void 0 ? void 0 : Log.debug('BLE manager reset disconnect subscription removal failed:', error);
|
|
1671
|
+
}
|
|
1672
|
+
cachedTransport.disconnectSubscription = undefined;
|
|
1673
|
+
try {
|
|
1674
|
+
(_b = cachedTransport.notifySubscription) === null || _b === void 0 ? void 0 : _b.remove();
|
|
1675
|
+
}
|
|
1676
|
+
catch (error) {
|
|
1677
|
+
Log === null || Log === void 0 ? void 0 : Log.debug('BLE manager reset notify subscription removal failed:', error);
|
|
1678
|
+
}
|
|
1679
|
+
cachedTransport.notifySubscription = undefined;
|
|
1680
|
+
this.rejectProtocolV2Frames(uuid, new Error(reason));
|
|
1681
|
+
try {
|
|
1682
|
+
this.emitDeviceDisconnect(uuid, (_c = cachedTransport.device) === null || _c === void 0 ? void 0 : _c.name, (_d = cachedTransport.monitorToken) !== null && _d !== void 0 ? _d : this.monitorTokens.get(uuid));
|
|
1683
|
+
}
|
|
1684
|
+
catch (error) {
|
|
1685
|
+
Log === null || Log === void 0 ? void 0 : Log.debug('BLE manager reset disconnect event failed:', error);
|
|
1686
|
+
}
|
|
1687
|
+
delete transportCache[uuid];
|
|
1688
|
+
});
|
|
1689
|
+
this.protocolV2Links.invalidateAllLinks(reason).catch(error => {
|
|
1690
|
+
Log === null || Log === void 0 ? void 0 : Log.debug('[ReactNativeBleTransport] BLE manager link invalidation failed:', error);
|
|
1691
|
+
});
|
|
1692
|
+
this.deviceProtocol.clear();
|
|
1693
|
+
this.probingProtocols.clear();
|
|
1694
|
+
this.sessionProtocols.clear();
|
|
1695
|
+
this.confirmedProtocolV2.clear();
|
|
1696
|
+
this.protocolReprobeFailures.clear();
|
|
1697
|
+
this.writeTimeoutCounts.clear();
|
|
1698
|
+
this.connectionSetupTimeoutCounts.clear();
|
|
1699
|
+
this.monitorTokens.clear();
|
|
1700
|
+
this.protocolV2Assemblers.clear();
|
|
1701
|
+
try {
|
|
1702
|
+
manager === null || manager === void 0 ? void 0 : manager.destroy();
|
|
1703
|
+
}
|
|
1704
|
+
catch (error) {
|
|
1705
|
+
Log === null || Log === void 0 ? void 0 : Log.debug('[ReactNativeBleTransport] BLE manager destroy failed (ignored):', error);
|
|
1706
|
+
}
|
|
1707
|
+
}
|
|
1708
|
+
createProtocolMismatchError(expected, uuid) {
|
|
1709
|
+
const isStaleV2Bond = expected === 'V2' && this.confirmedProtocolV2.has(uuid);
|
|
1710
|
+
return hdShared.ERRORS.TypedError(isStaleV2Bond ? hdShared.HardwareErrorCode.BleDeviceBondError : hdShared.HardwareErrorCode.RuntimeError, `Device protocol mismatch: expected ${expected}, but device did not respond to expected protocol`);
|
|
1305
1711
|
}
|
|
1306
1712
|
createProtocolDetectionError() {
|
|
1307
|
-
return hdShared.ERRORS.TypedError(hdShared.HardwareErrorCode.BleTimeoutError, 'Unable to detect BLE protocol: device did not respond to Protocol V1
|
|
1713
|
+
return hdShared.ERRORS.TypedError(hdShared.HardwareErrorCode.BleTimeoutError, 'Unable to detect BLE protocol: device did not respond to Protocol V1 GetFeatures or Protocol V2 Ping');
|
|
1308
1714
|
}
|
|
1309
1715
|
clearProbeProtocol(uuid, protocol) {
|
|
1716
|
+
if (this.probingProtocols.get(uuid) === protocol) {
|
|
1717
|
+
this.probingProtocols.delete(uuid);
|
|
1718
|
+
}
|
|
1310
1719
|
if (this.deviceProtocol.get(uuid) === protocol) {
|
|
1311
1720
|
this.deviceProtocol.delete(uuid);
|
|
1312
1721
|
}
|
|
1313
1722
|
}
|
|
1314
|
-
|
|
1723
|
+
getActiveProtocol(uuid) {
|
|
1724
|
+
var _a;
|
|
1725
|
+
return (_a = this.deviceProtocol.get(uuid)) !== null && _a !== void 0 ? _a : this.probingProtocols.get(uuid);
|
|
1726
|
+
}
|
|
1727
|
+
detectProtocol(uuid, expectedProtocol, protocolHint, rebuildTransport) {
|
|
1728
|
+
var _a;
|
|
1315
1729
|
return __awaiter(this, void 0, void 0, function* () {
|
|
1730
|
+
if (reactNative.Platform.OS === 'ios' && expectedProtocol === 'V1') {
|
|
1731
|
+
this.deviceProtocol.set(uuid, expectedProtocol);
|
|
1732
|
+
Log === null || Log === void 0 ? void 0 : Log.debug('[ReactNativeBleTransport] protocol selected', {
|
|
1733
|
+
deviceId: uuid,
|
|
1734
|
+
protocol: expectedProtocol,
|
|
1735
|
+
source: 'expected',
|
|
1736
|
+
});
|
|
1737
|
+
return expectedProtocol;
|
|
1738
|
+
}
|
|
1316
1739
|
if (expectedProtocol === 'V1') {
|
|
1317
1740
|
if (yield this.probeProtocolV1(uuid)) {
|
|
1318
1741
|
this.deviceProtocol.set(uuid, 'V1');
|
|
1742
|
+
this.sessionProtocols.set(uuid, 'V1');
|
|
1319
1743
|
Log === null || Log === void 0 ? void 0 : Log.debug('[ReactNativeBleTransport] protocol detected', {
|
|
1320
1744
|
deviceId: uuid,
|
|
1321
1745
|
protocol: 'V1',
|
|
@@ -1323,26 +1747,48 @@ class ReactNativeBleTransport {
|
|
|
1323
1747
|
});
|
|
1324
1748
|
return 'V1';
|
|
1325
1749
|
}
|
|
1326
|
-
throw this.createProtocolMismatchError(expectedProtocol);
|
|
1750
|
+
throw this.createProtocolMismatchError(expectedProtocol, uuid);
|
|
1327
1751
|
}
|
|
1328
1752
|
if (expectedProtocol === 'V2') {
|
|
1329
|
-
this.
|
|
1330
|
-
|
|
1331
|
-
|
|
1332
|
-
|
|
1333
|
-
|
|
1334
|
-
|
|
1335
|
-
|
|
1336
|
-
|
|
1337
|
-
|
|
1753
|
+
if (yield this.probeProtocolV2(uuid)) {
|
|
1754
|
+
this.deviceProtocol.set(uuid, 'V2');
|
|
1755
|
+
this.sessionProtocols.set(uuid, 'V2');
|
|
1756
|
+
this.confirmedProtocolV2.add(uuid);
|
|
1757
|
+
Log === null || Log === void 0 ? void 0 : Log.debug('[ReactNativeBleTransport] protocol detected', {
|
|
1758
|
+
deviceId: uuid,
|
|
1759
|
+
protocol: 'V2',
|
|
1760
|
+
source: 'expected',
|
|
1761
|
+
});
|
|
1762
|
+
return 'V2';
|
|
1763
|
+
}
|
|
1764
|
+
throw this.createProtocolMismatchError(expectedProtocol, uuid);
|
|
1765
|
+
}
|
|
1766
|
+
const sessionProtocol = this.sessionProtocols.get(uuid);
|
|
1767
|
+
const reprobeFailures = (_a = this.protocolReprobeFailures.get(uuid)) !== null && _a !== void 0 ? _a : 0;
|
|
1768
|
+
const fullProbeOrder = protocolHint === 'V2' || this.deviceProtocol.get(uuid) === 'V2' ? ['V2', 'V1'] : ['V1', 'V2'];
|
|
1769
|
+
const trustSessionProtocol = sessionProtocol !== undefined &&
|
|
1770
|
+
!protocolHint &&
|
|
1771
|
+
reprobeFailures < PROTOCOL_REPROBE_FALLBACK_ATTEMPTS;
|
|
1772
|
+
const probeOrder = trustSessionProtocol ? [sessionProtocol] : fullProbeOrder;
|
|
1338
1773
|
for (let i = 0; i < probeOrder.length; i += 1) {
|
|
1339
1774
|
const protocol = probeOrder[i];
|
|
1340
1775
|
if (i > 0) {
|
|
1341
1776
|
yield this.resetProbeStateAfterProtocolProbe(uuid, probeOrder[i - 1]);
|
|
1777
|
+
if (!transportCache[uuid]) {
|
|
1778
|
+
if (!rebuildTransport) {
|
|
1779
|
+
throw hdShared.ERRORS.TypedError(hdShared.HardwareErrorCode.TransportNotFound);
|
|
1780
|
+
}
|
|
1781
|
+
yield rebuildTransport();
|
|
1782
|
+
}
|
|
1342
1783
|
}
|
|
1343
1784
|
const detected = protocol === 'V1' ? yield this.probeProtocolV1(uuid) : yield this.probeProtocolV2(uuid);
|
|
1344
1785
|
if (detected) {
|
|
1345
1786
|
this.deviceProtocol.set(uuid, protocol);
|
|
1787
|
+
this.sessionProtocols.set(uuid, protocol);
|
|
1788
|
+
if (protocol === 'V2') {
|
|
1789
|
+
this.confirmedProtocolV2.add(uuid);
|
|
1790
|
+
}
|
|
1791
|
+
this.protocolReprobeFailures.delete(uuid);
|
|
1346
1792
|
Log === null || Log === void 0 ? void 0 : Log.debug('[ReactNativeBleTransport] protocol detected', {
|
|
1347
1793
|
deviceId: uuid,
|
|
1348
1794
|
protocol,
|
|
@@ -1351,7 +1797,14 @@ class ReactNativeBleTransport {
|
|
|
1351
1797
|
return protocol;
|
|
1352
1798
|
}
|
|
1353
1799
|
}
|
|
1800
|
+
if (trustSessionProtocol) {
|
|
1801
|
+
this.protocolReprobeFailures.set(uuid, reprobeFailures + 1);
|
|
1802
|
+
}
|
|
1803
|
+
else {
|
|
1804
|
+
this.protocolReprobeFailures.delete(uuid);
|
|
1805
|
+
}
|
|
1354
1806
|
this.deviceProtocol.delete(uuid);
|
|
1807
|
+
this.probingProtocols.delete(uuid);
|
|
1355
1808
|
throw this.createProtocolDetectionError();
|
|
1356
1809
|
});
|
|
1357
1810
|
}
|
|
@@ -1403,13 +1856,17 @@ class ReactNativeBleTransport {
|
|
|
1403
1856
|
return false;
|
|
1404
1857
|
}
|
|
1405
1858
|
try {
|
|
1406
|
-
this.
|
|
1407
|
-
yield this.callProtocolV1(uuid, '
|
|
1859
|
+
this.probingProtocols.set(uuid, 'V1');
|
|
1860
|
+
yield this.callProtocolV1(uuid, 'GetFeatures', {}, { timeoutMs: PROTOCOL_PROBE_TIMEOUT_MS });
|
|
1861
|
+
this.probingProtocols.delete(uuid);
|
|
1408
1862
|
return true;
|
|
1409
1863
|
}
|
|
1410
1864
|
catch (error) {
|
|
1411
1865
|
this.clearProbeProtocol(uuid, 'V1');
|
|
1412
|
-
Log === null || Log === void 0 ? void 0 : Log.debug('[ReactNativeBleTransport] Protocol V1
|
|
1866
|
+
Log === null || Log === void 0 ? void 0 : Log.debug('[ReactNativeBleTransport] Protocol V1 GetFeatures probe failed:', error);
|
|
1867
|
+
if (isWedgedWriteError(error)) {
|
|
1868
|
+
throw error;
|
|
1869
|
+
}
|
|
1413
1870
|
return false;
|
|
1414
1871
|
}
|
|
1415
1872
|
});
|
|
@@ -1420,7 +1877,7 @@ class ReactNativeBleTransport {
|
|
|
1420
1877
|
if (!this._messages || !this._messagesV2) {
|
|
1421
1878
|
return false;
|
|
1422
1879
|
}
|
|
1423
|
-
this.
|
|
1880
|
+
this.probingProtocols.set(uuid, 'V2');
|
|
1424
1881
|
(_a = this.protocolV2Assemblers.get(uuid)) === null || _a === void 0 ? void 0 : _a.reset();
|
|
1425
1882
|
const detected = yield transport.probeProtocolV2({
|
|
1426
1883
|
call: (name, data, options) => this.callProtocolV2(uuid, name, data, options),
|
|
@@ -1436,6 +1893,9 @@ class ReactNativeBleTransport {
|
|
|
1436
1893
|
if (!detected) {
|
|
1437
1894
|
this.clearProbeProtocol(uuid, 'V2');
|
|
1438
1895
|
}
|
|
1896
|
+
else {
|
|
1897
|
+
this.probingProtocols.delete(uuid);
|
|
1898
|
+
}
|
|
1439
1899
|
return detected;
|
|
1440
1900
|
});
|
|
1441
1901
|
}
|
|
@@ -1478,16 +1938,8 @@ class ReactNativeBleTransport {
|
|
|
1478
1938
|
}
|
|
1479
1939
|
this.getProtocolV2FrameQueue(uuid).push(frame);
|
|
1480
1940
|
}
|
|
1481
|
-
rejectAllProtocolV2Frames(error) {
|
|
1482
|
-
this.protocolV2FrameQueues.clear();
|
|
1483
|
-
for (const framePromise of this.protocolV2FramePromises.values()) {
|
|
1484
|
-
framePromise.reject(error);
|
|
1485
|
-
}
|
|
1486
|
-
this.protocolV2FramePromises.clear();
|
|
1487
|
-
}
|
|
1488
1941
|
resetProtocolV2Frames(uuid) {
|
|
1489
|
-
this.
|
|
1490
|
-
this.protocolV2FramePromises.delete(uuid);
|
|
1942
|
+
this.rejectProtocolV2Frames(uuid, new Error(`Protocol V2 frame state reset for ${uuid}`));
|
|
1491
1943
|
}
|
|
1492
1944
|
rejectProtocolV2Frames(uuid, error) {
|
|
1493
1945
|
this.protocolV2FrameQueues.delete(uuid);
|
|
@@ -1515,20 +1967,70 @@ class ReactNativeBleTransport {
|
|
|
1515
1967
|
}
|
|
1516
1968
|
});
|
|
1517
1969
|
}
|
|
1518
|
-
|
|
1970
|
+
writeProtocolV2Packet(uuid, transport, base64, context, assertCurrentGeneration) {
|
|
1971
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
1972
|
+
const shouldUseWriteWithResponse = shouldWriteProtocolV2WithResponse({
|
|
1973
|
+
platform: reactNative.Platform.OS,
|
|
1974
|
+
highThroughput: context.highThroughput,
|
|
1975
|
+
requestedWithResponse: context.writeWithResponse,
|
|
1976
|
+
characteristic: transport.writeCharacteristic,
|
|
1977
|
+
});
|
|
1978
|
+
let attempt = 0;
|
|
1979
|
+
for (;;) {
|
|
1980
|
+
assertCurrentGeneration();
|
|
1981
|
+
if (context.signal.aborted) {
|
|
1982
|
+
throw new Error(`Protocol V2 BLE write aborted for ${context.messageName}`);
|
|
1983
|
+
}
|
|
1984
|
+
try {
|
|
1985
|
+
yield this.writeBlePacket(uuid, base64, payload => shouldUseWriteWithResponse
|
|
1986
|
+
? transport.writeCharacteristic.writeWithResponse(payload)
|
|
1987
|
+
: transport.writeCharacteristic.writeWithoutResponse(payload), () => {
|
|
1988
|
+
try {
|
|
1989
|
+
assertCurrentGeneration();
|
|
1990
|
+
return !context.signal.aborted;
|
|
1991
|
+
}
|
|
1992
|
+
catch (_a) {
|
|
1993
|
+
return false;
|
|
1994
|
+
}
|
|
1995
|
+
});
|
|
1996
|
+
assertCurrentGeneration();
|
|
1997
|
+
return;
|
|
1998
|
+
}
|
|
1999
|
+
catch (error) {
|
|
2000
|
+
if (getFirmwareUploadWriteRetryType(error) !== 'congested' ||
|
|
2001
|
+
attempt >= FIRMWARE_UPLOAD_WRITE_MAX_RETRIES) {
|
|
2002
|
+
throw error;
|
|
2003
|
+
}
|
|
2004
|
+
const delayMs = resolveFirmwareUploadRetryDelay(attempt);
|
|
2005
|
+
attempt += 1;
|
|
2006
|
+
Log === null || Log === void 0 ? void 0 : Log.debug('[ReactNativeBleTransport] Protocol V2 congested write retry:', {
|
|
2007
|
+
name: context.messageName,
|
|
2008
|
+
attempt,
|
|
2009
|
+
delayMs,
|
|
2010
|
+
});
|
|
2011
|
+
yield delay(delayMs);
|
|
2012
|
+
}
|
|
2013
|
+
}
|
|
2014
|
+
});
|
|
2015
|
+
}
|
|
2016
|
+
writeProtocolV2Frame(uuid, transport$1, frame, context, assertCurrentGeneration) {
|
|
1519
2017
|
return __awaiter(this, void 0, void 0, function* () {
|
|
1520
2018
|
const tuning = getProtocolV2BleTuning();
|
|
1521
2019
|
const packetCapacity = resolveProtocolV2PacketCapacity({
|
|
1522
2020
|
platform: reactNative.Platform.OS,
|
|
1523
2021
|
iosPacketLength: tuning.iosPacketLength,
|
|
1524
2022
|
androidPacketLength: tuning.androidPacketLength,
|
|
1525
|
-
mtu:
|
|
2023
|
+
mtu: transport$1.mtuSize,
|
|
2024
|
+
});
|
|
2025
|
+
yield transport.writeProtocolV2BleFrame({
|
|
2026
|
+
frame,
|
|
2027
|
+
packetCapacity,
|
|
2028
|
+
assertActive: assertCurrentGeneration,
|
|
2029
|
+
signal: context.signal,
|
|
2030
|
+
abortMessage: `Protocol V2 BLE write aborted for ${context.messageName}`,
|
|
2031
|
+
wait: delay,
|
|
2032
|
+
writePacket: packet => this.writeProtocolV2Packet(uuid, transport$1, buffer.Buffer.from(packet).toString('base64'), context, assertCurrentGeneration),
|
|
1526
2033
|
});
|
|
1527
|
-
for (let offset = 0; offset < frame.length; offset += packetCapacity) {
|
|
1528
|
-
const chunk = frame.slice(offset, offset + packetCapacity);
|
|
1529
|
-
const base64 = buffer.Buffer.from(chunk).toString('base64');
|
|
1530
|
-
yield transport.writeCharacteristic.writeWithoutResponse(base64);
|
|
1531
|
-
}
|
|
1532
2034
|
});
|
|
1533
2035
|
}
|
|
1534
2036
|
callProtocolV2(uuid, name, data, options) {
|
|
@@ -1537,15 +2039,40 @@ class ReactNativeBleTransport {
|
|
|
1537
2039
|
if (!this._messages || !this._messagesV2) {
|
|
1538
2040
|
throw hdShared.ERRORS.TypedError(hdShared.HardwareErrorCode.TransportNotConfigured);
|
|
1539
2041
|
}
|
|
1540
|
-
const callOptions =
|
|
1541
|
-
const
|
|
1542
|
-
if (
|
|
2042
|
+
const callOptions = options;
|
|
2043
|
+
const highThroughputWrite = transport.isProtocolV2HighThroughputCall(name);
|
|
2044
|
+
if (highThroughputWrite) {
|
|
2045
|
+
yield this.ensureProtocolV2HighThroughputMtu(uuid);
|
|
1543
2046
|
const tuning = getProtocolV2BleTuning();
|
|
1544
|
-
|
|
1545
|
-
|
|
1546
|
-
|
|
1547
|
-
|
|
2047
|
+
const currentTransport = this.getCachedTransport(uuid);
|
|
2048
|
+
const writeWithResponse = shouldWriteProtocolV2WithResponse({
|
|
2049
|
+
platform: reactNative.Platform.OS,
|
|
2050
|
+
highThroughput: true,
|
|
2051
|
+
requestedWithResponse: options === null || options === void 0 ? void 0 : options.writeWithResponse,
|
|
2052
|
+
characteristic: currentTransport.writeCharacteristic,
|
|
2053
|
+
});
|
|
2054
|
+
const packetCapacity = resolveProtocolV2PacketCapacity({
|
|
2055
|
+
platform: reactNative.Platform.OS,
|
|
2056
|
+
iosPacketLength: tuning.iosPacketLength,
|
|
2057
|
+
androidPacketLength: tuning.androidPacketLength,
|
|
2058
|
+
mtu: currentTransport.mtuSize,
|
|
1548
2059
|
});
|
|
2060
|
+
const writeMode = writeWithResponse ? 'withResponse' : 'withoutResponse';
|
|
2061
|
+
const logSignature = `${name}:${writeMode}:${String(currentTransport.mtuSize)}:${packetCapacity}`;
|
|
2062
|
+
const loggedSignatures = (_a = this.protocolV2HighVolumeLogSignatures.get(uuid)) !== null && _a !== void 0 ? _a : new Set();
|
|
2063
|
+
if (!loggedSignatures.has(logSignature)) {
|
|
2064
|
+
loggedSignatures.add(logSignature);
|
|
2065
|
+
this.protocolV2HighVolumeLogSignatures.set(uuid, loggedSignatures);
|
|
2066
|
+
Log === null || Log === void 0 ? void 0 : Log.debug('[ReactNativeBleTransport] Protocol V2 high-volume write configured', {
|
|
2067
|
+
name,
|
|
2068
|
+
writeMode,
|
|
2069
|
+
reportedMtu: currentTransport.mtuSize,
|
|
2070
|
+
packetCapacity,
|
|
2071
|
+
});
|
|
2072
|
+
}
|
|
2073
|
+
}
|
|
2074
|
+
if (highThroughputWrite) {
|
|
2075
|
+
yield this.enableAndroidHighConnectionPriority(uuid);
|
|
1549
2076
|
}
|
|
1550
2077
|
try {
|
|
1551
2078
|
return yield this.protocolV2Links.call(uuid, () => this.createProtocolV2Adapter(uuid), name, data, callOptions);
|
|
@@ -1554,6 +2081,85 @@ class ReactNativeBleTransport {
|
|
|
1554
2081
|
Log === null || Log === void 0 ? void 0 : Log.error('[ReactNativeBleTransport] Protocol V2 call error:', e);
|
|
1555
2082
|
throw e;
|
|
1556
2083
|
}
|
|
2084
|
+
finally {
|
|
2085
|
+
if (highThroughputWrite) {
|
|
2086
|
+
this.scheduleAndroidBalancedConnectionPriority(uuid);
|
|
2087
|
+
}
|
|
2088
|
+
}
|
|
2089
|
+
});
|
|
2090
|
+
}
|
|
2091
|
+
ensureProtocolV2HighThroughputMtu(uuid) {
|
|
2092
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
2093
|
+
const transport = this.getCachedTransport(uuid);
|
|
2094
|
+
if (!shouldRefreshNegotiatedMtu(transport.mtuSize))
|
|
2095
|
+
return;
|
|
2096
|
+
const refreshedDevice = yield requestNegotiatedMtu(transport.device, 'highThroughput', 1);
|
|
2097
|
+
transport.device = refreshedDevice;
|
|
2098
|
+
transport.mtuSize =
|
|
2099
|
+
typeof refreshedDevice.mtu === 'number' ? refreshedDevice.mtu : transport.mtuSize;
|
|
2100
|
+
if (shouldRefreshNegotiatedMtu(transport.mtuSize)) {
|
|
2101
|
+
throw hdShared.ERRORS.TypedError(hdShared.HardwareErrorCode.BleConnectedError, `Protocol V2 high-throughput BLE MTU unavailable: ${String(transport.mtuSize)}`);
|
|
2102
|
+
}
|
|
2103
|
+
});
|
|
2104
|
+
}
|
|
2105
|
+
clearAndroidPriorityResetTimer(uuid) {
|
|
2106
|
+
const timerId = this.androidPriorityResetTimers.get(uuid);
|
|
2107
|
+
if (timerId !== undefined) {
|
|
2108
|
+
clearTimeout(timerId);
|
|
2109
|
+
this.androidPriorityResetTimers.delete(uuid);
|
|
2110
|
+
}
|
|
2111
|
+
}
|
|
2112
|
+
enableAndroidHighConnectionPriority(uuid) {
|
|
2113
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
2114
|
+
if (reactNative.Platform.OS !== 'android')
|
|
2115
|
+
return;
|
|
2116
|
+
this.clearAndroidPriorityResetTimer(uuid);
|
|
2117
|
+
if (this.androidHighPriorityDevices.has(uuid))
|
|
2118
|
+
return;
|
|
2119
|
+
const transport = transportCache[uuid];
|
|
2120
|
+
if (!transport)
|
|
2121
|
+
return;
|
|
2122
|
+
try {
|
|
2123
|
+
transport.device = yield transport.device.requestConnectionPriority(reactNativeBlePlx.ConnectionPriority.High);
|
|
2124
|
+
this.androidHighPriorityDevices.add(uuid);
|
|
2125
|
+
Log === null || Log === void 0 ? void 0 : Log.debug('[ReactNativeBleTransport] Android BLE connection priority changed', {
|
|
2126
|
+
priority: 'high',
|
|
2127
|
+
});
|
|
2128
|
+
}
|
|
2129
|
+
catch (error) {
|
|
2130
|
+
Log === null || Log === void 0 ? void 0 : Log.debug('[ReactNativeBleTransport] Android BLE high priority request failed', {
|
|
2131
|
+
error: error instanceof Error ? error.message : String(error),
|
|
2132
|
+
});
|
|
2133
|
+
}
|
|
2134
|
+
});
|
|
2135
|
+
}
|
|
2136
|
+
scheduleAndroidBalancedConnectionPriority(uuid) {
|
|
2137
|
+
if (reactNative.Platform.OS !== 'android' || !this.androidHighPriorityDevices.has(uuid))
|
|
2138
|
+
return;
|
|
2139
|
+
this.clearAndroidPriorityResetTimer(uuid);
|
|
2140
|
+
const timerId = setTimeout(() => {
|
|
2141
|
+
this.androidPriorityResetTimers.delete(uuid);
|
|
2142
|
+
this.restoreAndroidConnectionPriority(uuid, transportCache[uuid]).catch(error => Log === null || Log === void 0 ? void 0 : Log.debug('[ReactNativeBleTransport] Android BLE priority restore failed', error));
|
|
2143
|
+
}, ANDROID_HIGH_PRIORITY_IDLE_MS);
|
|
2144
|
+
this.androidPriorityResetTimers.set(uuid, timerId);
|
|
2145
|
+
}
|
|
2146
|
+
restoreAndroidConnectionPriority(uuid, transport) {
|
|
2147
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
2148
|
+
this.clearAndroidPriorityResetTimer(uuid);
|
|
2149
|
+
if (reactNative.Platform.OS !== 'android' || !this.androidHighPriorityDevices.delete(uuid) || !transport) {
|
|
2150
|
+
return;
|
|
2151
|
+
}
|
|
2152
|
+
try {
|
|
2153
|
+
transport.device = yield transport.device.requestConnectionPriority(reactNativeBlePlx.ConnectionPriority.Balanced);
|
|
2154
|
+
Log === null || Log === void 0 ? void 0 : Log.debug('[ReactNativeBleTransport] Android BLE connection priority changed', {
|
|
2155
|
+
priority: 'balanced',
|
|
2156
|
+
});
|
|
2157
|
+
}
|
|
2158
|
+
catch (error) {
|
|
2159
|
+
Log === null || Log === void 0 ? void 0 : Log.debug('[ReactNativeBleTransport] Android BLE balanced priority request failed', {
|
|
2160
|
+
error: error instanceof Error ? error.message : String(error),
|
|
2161
|
+
});
|
|
2162
|
+
}
|
|
1557
2163
|
});
|
|
1558
2164
|
}
|
|
1559
2165
|
createProtocolV2Adapter(uuid) {
|
|
@@ -1574,10 +2180,10 @@ class ReactNativeBleTransport {
|
|
|
1574
2180
|
(_a = this.protocolV2Assemblers.get(uuid)) === null || _a === void 0 ? void 0 : _a.reset();
|
|
1575
2181
|
this.resetProtocolV2Frames(uuid);
|
|
1576
2182
|
},
|
|
1577
|
-
writeFrame: (frame) => __awaiter(this, void 0, void 0, function* () {
|
|
2183
|
+
writeFrame: (frame, context) => __awaiter(this, void 0, void 0, function* () {
|
|
1578
2184
|
assertCurrentGeneration();
|
|
1579
2185
|
const currentTransport = this.getCachedTransport(uuid);
|
|
1580
|
-
yield this.writeProtocolV2Frame(currentTransport, frame);
|
|
2186
|
+
yield this.writeProtocolV2Frame(uuid, currentTransport, frame, context, assertCurrentGeneration);
|
|
1581
2187
|
}),
|
|
1582
2188
|
readFrame: () => __awaiter(this, void 0, void 0, function* () {
|
|
1583
2189
|
assertCurrentGeneration();
|
|
@@ -1589,6 +2195,8 @@ class ReactNativeBleTransport {
|
|
|
1589
2195
|
}),
|
|
1590
2196
|
reset: (reason) => {
|
|
1591
2197
|
var _a;
|
|
2198
|
+
if (this.monitorTokens.get(uuid) !== generation)
|
|
2199
|
+
return;
|
|
1592
2200
|
(_a = this.protocolV2Assemblers.get(uuid)) === null || _a === void 0 ? void 0 : _a.reset();
|
|
1593
2201
|
this.rejectProtocolV2Frames(uuid, new Error(reason));
|
|
1594
2202
|
},
|
|
@@ -1598,11 +2206,20 @@ class ReactNativeBleTransport {
|
|
|
1598
2206
|
};
|
|
1599
2207
|
}
|
|
1600
2208
|
getProtocolType(path) {
|
|
1601
|
-
return this.
|
|
2209
|
+
return this.getActiveProtocol(path);
|
|
1602
2210
|
}
|
|
1603
2211
|
}
|
|
1604
2212
|
|
|
2213
|
+
exports.BLE_CONNECT_TIMEOUT_MANAGER_RESET_THRESHOLD = BLE_CONNECT_TIMEOUT_MANAGER_RESET_THRESHOLD;
|
|
2214
|
+
exports.BLE_CONNECT_TIMEOUT_MS = BLE_CONNECT_TIMEOUT_MS;
|
|
2215
|
+
exports.BLE_GATT_SETUP_TIMEOUT_MS = BLE_GATT_SETUP_TIMEOUT_MS;
|
|
2216
|
+
exports.BLE_NATIVE_TEARDOWN_TIMEOUT_MS = BLE_NATIVE_TEARDOWN_TIMEOUT_MS;
|
|
2217
|
+
exports.BLE_SETUP_WEDGED_MESSAGE = BLE_SETUP_WEDGED_MESSAGE;
|
|
2218
|
+
exports.BLE_WRITE_PACKET_TIMEOUT_MS = BLE_WRITE_PACKET_TIMEOUT_MS;
|
|
2219
|
+
exports.BLE_WRITE_TIMEOUT_MANAGER_RESET_THRESHOLD = BLE_WRITE_TIMEOUT_MANAGER_RESET_THRESHOLD;
|
|
2220
|
+
exports.PROTOCOL_REPROBE_FALLBACK_ATTEMPTS = PROTOCOL_REPROBE_FALLBACK_ATTEMPTS;
|
|
1605
2221
|
exports.configureProtocolV2BleTuning = configureProtocolV2BleTuning;
|
|
1606
2222
|
exports["default"] = ReactNativeBleTransport;
|
|
2223
|
+
exports.getFirmwareUploadWriteRetryType = getFirmwareUploadWriteRetryType;
|
|
1607
2224
|
exports.getProtocolV2BleTuning = getProtocolV2BleTuning;
|
|
1608
2225
|
exports.resetProtocolV2BleTuning = resetProtocolV2BleTuning;
|