@onekeyfe/hd-transport-react-native 1.2.0-alpha.4 → 1.2.0-alpha.40
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/BleTransport.d.ts +1 -3
- package/dist/BleTransport.d.ts.map +1 -1
- package/dist/bleStrategy.d.ts +0 -2
- package/dist/bleStrategy.d.ts.map +1 -1
- package/dist/constants.d.ts +0 -1
- package/dist/constants.d.ts.map +1 -1
- package/dist/index.d.ts +21 -16
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +364 -369
- package/dist/subscribeBleOn.d.ts.map +1 -1
- package/dist/transportLog.d.ts +2 -0
- package/dist/transportLog.d.ts.map +1 -0
- package/dist/types.d.ts +1 -0
- package/dist/types.d.ts.map +1 -1
- package/jest.config.js +5 -0
- package/package.json +7 -6
- package/src/BleTransport.ts +2 -43
- package/src/__tests__/BleTransport.test.ts +41 -0
- package/src/__tests__/bleStrategy.test.ts +1 -6
- package/src/__tests__/constants.test.ts +20 -0
- package/src/__tests__/protocolV2Link.test.ts +520 -0
- package/src/bleStrategy.ts +0 -25
- package/src/constants.ts +7 -13
- package/src/index.ts +428 -388
- package/src/subscribeBleOn.ts +0 -2
- package/src/transportLog.ts +1 -0
- package/src/types.ts +1 -0
package/dist/index.js
CHANGED
|
@@ -117,42 +117,23 @@ const getInfosForServiceUuid = (serviceUuid, deviceType) => {
|
|
|
117
117
|
return null;
|
|
118
118
|
}
|
|
119
119
|
const normalizedServiceUuid = normalizeBleUuid(serviceUuid);
|
|
120
|
-
const service = (_a = services[serviceUuid]) !== null && _a !== void 0 ? _a : Object.values(services).find(item => normalizeBleUuid(item.serviceUuid) === normalizedServiceUuid
|
|
120
|
+
const service = (_a = services[serviceUuid]) !== null && _a !== void 0 ? _a : Object.values(services).find(item => normalizeBleUuid(item.serviceUuid) === normalizedServiceUuid ||
|
|
121
|
+
hdShared.matchesKnownBleUuid(serviceUuid, hdShared.createKnownBleUuidAliases(item.serviceUuid)));
|
|
121
122
|
if (!service) {
|
|
122
123
|
return null;
|
|
123
124
|
}
|
|
124
125
|
return service;
|
|
125
126
|
};
|
|
126
127
|
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
128
|
const isSameBleUuid = (left, right) => {
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
return (
|
|
135
|
-
(getBleUuidKey(left) !== '' && getBleUuidKey(left) === getBleUuidKey(right)));
|
|
129
|
+
if (!left || !right)
|
|
130
|
+
return false;
|
|
131
|
+
return hdShared.matchesKnownBleUuid(left, hdShared.createKnownBleUuidAliases(right));
|
|
136
132
|
};
|
|
137
133
|
|
|
138
134
|
function hasWritableCapability(characteristic) {
|
|
139
135
|
return !!(characteristic.isWritableWithResponse || characteristic.isWritableWithoutResponse);
|
|
140
136
|
}
|
|
141
|
-
function resolveBleWriteMode(characteristic, preferredMode = 'withoutResponse') {
|
|
142
|
-
if (preferredMode === 'withoutResponse' && characteristic.isWritableWithoutResponse) {
|
|
143
|
-
return 'withoutResponse';
|
|
144
|
-
}
|
|
145
|
-
if (preferredMode === 'withResponse' && characteristic.isWritableWithResponse) {
|
|
146
|
-
return 'withResponse';
|
|
147
|
-
}
|
|
148
|
-
if (characteristic.isWritableWithoutResponse) {
|
|
149
|
-
return 'withoutResponse';
|
|
150
|
-
}
|
|
151
|
-
if (characteristic.isWritableWithResponse) {
|
|
152
|
-
return 'withResponse';
|
|
153
|
-
}
|
|
154
|
-
return preferredMode;
|
|
155
|
-
}
|
|
156
137
|
function resolveProtocolV2PacketCapacity({ platform, iosPacketLength = IOS_PACKET_LENGTH, androidPacketLength = ANDROID_PACKET_LENGTH, mtu, }) {
|
|
157
138
|
if (platform === 'ios') {
|
|
158
139
|
return iosPacketLength;
|
|
@@ -189,7 +170,6 @@ const timer = process.env.NODE_ENV === 'development'
|
|
|
189
170
|
const subscribeBleOn = (bleManager, ms = 1000) => new Promise((resolve, reject) => {
|
|
190
171
|
let done = false;
|
|
191
172
|
const subscription = bleManager.onStateChange(state => {
|
|
192
|
-
console.log('ble state -> ', state);
|
|
193
173
|
if (state === 'PoweredOn') {
|
|
194
174
|
if (done)
|
|
195
175
|
return;
|
|
@@ -219,7 +199,6 @@ const isHeaderChunk = (chunk) => {
|
|
|
219
199
|
return false;
|
|
220
200
|
};
|
|
221
201
|
|
|
222
|
-
const Log$1 = bleLogger;
|
|
223
202
|
class BleTransport {
|
|
224
203
|
constructor(device, writeCharacteristic, notifyCharacteristic) {
|
|
225
204
|
this.name = 'ReactNativeBleTransport';
|
|
@@ -229,37 +208,12 @@ class BleTransport {
|
|
|
229
208
|
this.writeCharacteristic = writeCharacteristic;
|
|
230
209
|
this.notifyCharacteristic = notifyCharacteristic;
|
|
231
210
|
}
|
|
232
|
-
writeWithRetry(data
|
|
211
|
+
writeWithRetry(data) {
|
|
233
212
|
return __awaiter(this, void 0, void 0, function* () {
|
|
234
|
-
|
|
235
|
-
yield this.writeCharacteristic.writeWithoutResponse(data);
|
|
236
|
-
}
|
|
237
|
-
catch (error) {
|
|
238
|
-
Log$1 === null || Log$1 === void 0 ? void 0 : Log$1.debug(`Write retry attempt ${BleTransport.MAX_RETRIES - retryCount + 1}, error: ${error}`);
|
|
239
|
-
if (retryCount > 0) {
|
|
240
|
-
yield hdShared.wait(BleTransport.RETRY_DELAY);
|
|
241
|
-
if (error.errorCode === reactNativeBlePlx.BleErrorCode.DeviceDisconnected ||
|
|
242
|
-
error.errorCode === reactNativeBlePlx.BleErrorCode.CharacteristicNotFound) {
|
|
243
|
-
try {
|
|
244
|
-
yield this.device.connect();
|
|
245
|
-
yield this.device.discoverAllServicesAndCharacteristics();
|
|
246
|
-
}
|
|
247
|
-
catch (e) {
|
|
248
|
-
Log$1 === null || Log$1 === void 0 ? void 0 : Log$1.debug(`Connect or discoverAllServicesAndCharacteristics error: ${e}`);
|
|
249
|
-
}
|
|
250
|
-
}
|
|
251
|
-
else {
|
|
252
|
-
Log$1 === null || Log$1 === void 0 ? void 0 : Log$1.debug(`writeCharacteristic error: ${error}`);
|
|
253
|
-
}
|
|
254
|
-
return this.writeWithRetry(data, retryCount - 1);
|
|
255
|
-
}
|
|
256
|
-
throw error;
|
|
257
|
-
}
|
|
213
|
+
yield this.writeCharacteristic.writeWithoutResponse(data);
|
|
258
214
|
});
|
|
259
215
|
}
|
|
260
216
|
}
|
|
261
|
-
BleTransport.MAX_RETRIES = 5;
|
|
262
|
-
BleTransport.RETRY_DELAY = 2000;
|
|
263
217
|
|
|
264
218
|
const { check, ProtocolV1, parseConfigure } = transport__default["default"];
|
|
265
219
|
const Log = bleLogger;
|
|
@@ -268,7 +222,6 @@ const FIRMWARE_UPLOAD_WRITE_BURST_SIZE = reactNative.Platform.OS === 'ios' ? 4 :
|
|
|
268
222
|
const FIRMWARE_UPLOAD_WRITE_PAUSE_MS = reactNative.Platform.OS === 'ios' ? 8 : 10;
|
|
269
223
|
const FIRMWARE_UPLOAD_WRITE_FLUSH_DELAY_MS = reactNative.Platform.OS === 'ios' ? 24 : 30;
|
|
270
224
|
const FIRMWARE_UPLOAD_WRITE_MAX_RETRIES = 8;
|
|
271
|
-
const FIRMWARE_UPLOAD_RECONNECT_RETRY_DELAY_MS = 2000;
|
|
272
225
|
const ANDROID_FIRMWARE_UPLOAD_PACKET_LENGTH = 192;
|
|
273
226
|
const FIRMWARE_UPLOAD_WRITE_PACKET_CAPACITY = reactNative.Platform.OS === 'ios' ? IOS_PACKET_LENGTH : ANDROID_FIRMWARE_UPLOAD_PACKET_LENGTH;
|
|
274
227
|
const ANDROID_GATT_CONGESTED_STATUS = 143;
|
|
@@ -279,10 +232,6 @@ const getFirmwareUploadWriteRetryType = (error) => {
|
|
|
279
232
|
if (!error || typeof error !== 'object')
|
|
280
233
|
return null;
|
|
281
234
|
const bleWriteError = error;
|
|
282
|
-
if (bleWriteError.errorCode === reactNativeBlePlx.BleErrorCode.DeviceDisconnected ||
|
|
283
|
-
bleWriteError.errorCode === reactNativeBlePlx.BleErrorCode.CharacteristicNotFound) {
|
|
284
|
-
return 'reconnectable';
|
|
285
|
-
}
|
|
286
235
|
if (bleWriteError.androidErrorCode === ANDROID_GATT_CONGESTED_STATUS ||
|
|
287
236
|
bleWriteError.status === ANDROID_GATT_CONGESTED_STATUS) {
|
|
288
237
|
return 'congested';
|
|
@@ -293,22 +242,14 @@ const getFirmwareUploadWriteRetryType = (error) => {
|
|
|
293
242
|
return /GATT_CONGESTED|status\s*[:=]?\s*143/.test(text) ? 'congested' : null;
|
|
294
243
|
};
|
|
295
244
|
const resolveFirmwareUploadRetryDelay = (attempt, baseDelayMs = 200, maxDelayMs = 1200) => Math.min(baseDelayMs * Math.pow(2, attempt), maxDelayMs);
|
|
296
|
-
const BLE_RESPONSE_TIMEOUT_MS = 30000;
|
|
297
245
|
const PROTOCOL_PROBE_TIMEOUT_MS = 1000;
|
|
298
246
|
const PROTOCOL_V2_PROBE_TIMEOUT_MS = 10000;
|
|
299
|
-
const DEVICE_SCAN_TIMEOUT_MS =
|
|
247
|
+
const DEVICE_SCAN_TIMEOUT_MS = 3000;
|
|
300
248
|
const IOS_NOTIFY_READY_DELAY_MS = 150;
|
|
301
249
|
const ANDROID_NOTIFY_READY_DELAY_MS = 300;
|
|
302
|
-
const HIGH_VOLUME_WRITE_BURST_SIZE = reactNative.Platform.OS === 'ios' ? 4 : 6;
|
|
303
|
-
const HIGH_VOLUME_WRITE_PAUSE_MS = reactNative.Platform.OS === 'ios' ? 6 : 2;
|
|
304
|
-
const HIGH_VOLUME_WRITE_FLUSH_DELAY_MS = reactNative.Platform.OS === 'ios' ? 20 : 8;
|
|
305
250
|
const DEFAULT_PROTOCOL_V2_BLE_TUNING = {
|
|
306
251
|
iosPacketLength: IOS_PACKET_LENGTH,
|
|
307
252
|
androidPacketLength: ANDROID_PACKET_LENGTH,
|
|
308
|
-
highVolumeWriteBurstSize: HIGH_VOLUME_WRITE_BURST_SIZE,
|
|
309
|
-
highVolumeWritePauseMs: HIGH_VOLUME_WRITE_PAUSE_MS,
|
|
310
|
-
highVolumeWriteFlushDelayMs: HIGH_VOLUME_WRITE_FLUSH_DELAY_MS,
|
|
311
|
-
highVolumeWriteWithResponse: false,
|
|
312
253
|
};
|
|
313
254
|
let protocolV2BleTuning = Object.assign({}, DEFAULT_PROTOCOL_V2_BLE_TUNING);
|
|
314
255
|
const normalizePositiveInteger = (value, fallback) => {
|
|
@@ -318,20 +259,15 @@ const normalizePositiveInteger = (value, fallback) => {
|
|
|
318
259
|
return Math.floor(normalized);
|
|
319
260
|
};
|
|
320
261
|
function configureProtocolV2BleTuning(tuning = {}) {
|
|
321
|
-
var _a;
|
|
322
262
|
protocolV2BleTuning = {
|
|
323
263
|
iosPacketLength: normalizePositiveInteger(tuning.iosPacketLength, protocolV2BleTuning.iosPacketLength),
|
|
324
264
|
androidPacketLength: normalizePositiveInteger(tuning.androidPacketLength, protocolV2BleTuning.androidPacketLength),
|
|
325
|
-
highVolumeWriteBurstSize: normalizePositiveInteger(tuning.highVolumeWriteBurstSize, protocolV2BleTuning.highVolumeWriteBurstSize),
|
|
326
|
-
highVolumeWritePauseMs: normalizePositiveInteger(tuning.highVolumeWritePauseMs, protocolV2BleTuning.highVolumeWritePauseMs),
|
|
327
|
-
highVolumeWriteFlushDelayMs: normalizePositiveInteger(tuning.highVolumeWriteFlushDelayMs, protocolV2BleTuning.highVolumeWriteFlushDelayMs),
|
|
328
|
-
highVolumeWriteWithResponse: (_a = tuning.highVolumeWriteWithResponse) !== null && _a !== void 0 ? _a : protocolV2BleTuning.highVolumeWriteWithResponse,
|
|
329
265
|
};
|
|
330
|
-
Log === null || Log === void 0 ? void 0 : Log.debug('[ReactNativeBleTransport]
|
|
266
|
+
Log === null || Log === void 0 ? void 0 : Log.debug('[ReactNativeBleTransport] BLE tuning configured', protocolV2BleTuning);
|
|
331
267
|
}
|
|
332
268
|
function resetProtocolV2BleTuning() {
|
|
333
269
|
protocolV2BleTuning = Object.assign({}, DEFAULT_PROTOCOL_V2_BLE_TUNING);
|
|
334
|
-
Log === null || Log === void 0 ? void 0 : Log.debug('[ReactNativeBleTransport]
|
|
270
|
+
Log === null || Log === void 0 ? void 0 : Log.debug('[ReactNativeBleTransport] BLE tuning reset', protocolV2BleTuning);
|
|
335
271
|
}
|
|
336
272
|
function getProtocolV2BleTuning() {
|
|
337
273
|
return Object.assign({}, protocolV2BleTuning);
|
|
@@ -342,13 +278,6 @@ function inferProtocolHintFromDeviceName(name) {
|
|
|
342
278
|
function getDeviceDisplayName(device) {
|
|
343
279
|
return (device === null || device === void 0 ? void 0 : device.name) || (device === null || device === void 0 ? void 0 : device.localName) || null;
|
|
344
280
|
}
|
|
345
|
-
function isGenericBleService(uuid) {
|
|
346
|
-
return ['1800', '1801', '180a'].includes(getBleUuidKey(uuid));
|
|
347
|
-
}
|
|
348
|
-
function hasKnownOneKeyService(device) {
|
|
349
|
-
var _a;
|
|
350
|
-
return ((_a = device === null || device === void 0 ? void 0 : device.serviceUUIDs) !== null && _a !== void 0 ? _a : []).some(serviceUuid => getInfosForServiceUuid(serviceUuid, 'classic'));
|
|
351
|
-
}
|
|
352
281
|
const ANDROID_REQUEST_MTU = 256;
|
|
353
282
|
const connectOptions = {
|
|
354
283
|
requestMTU: ANDROID_REQUEST_MTU,
|
|
@@ -371,9 +300,10 @@ const requestAndroidMtu = (device) => __awaiter(void 0, void 0, void 0, function
|
|
|
371
300
|
return device;
|
|
372
301
|
try {
|
|
373
302
|
const mtuDevice = yield device.requestMTU(ANDROID_REQUEST_MTU);
|
|
374
|
-
Log === null || Log === void 0 ? void 0 : Log.debug('[ReactNativeBleTransport]
|
|
303
|
+
Log === null || Log === void 0 ? void 0 : Log.debug('[ReactNativeBleTransport] MTU configured', {
|
|
304
|
+
deviceId: device.id,
|
|
375
305
|
requested: ANDROID_REQUEST_MTU,
|
|
376
|
-
|
|
306
|
+
actual: mtuDevice.mtu,
|
|
377
307
|
});
|
|
378
308
|
return mtuDevice;
|
|
379
309
|
}
|
|
@@ -408,15 +338,36 @@ class ReactNativeBleTransport {
|
|
|
408
338
|
this.stopped = false;
|
|
409
339
|
this.scanTimeout = DEVICE_SCAN_TIMEOUT_MS;
|
|
410
340
|
this.runPromise = null;
|
|
341
|
+
this.runPromiseDeviceId = null;
|
|
411
342
|
this.firmwareUploadWriteRecoveryIds = new Set();
|
|
412
343
|
this.deviceProtocol = new Map();
|
|
413
344
|
this.deviceProtocolHints = new Map();
|
|
414
345
|
this.protocolV2Assemblers = new Map();
|
|
415
346
|
this.protocolV2FrameQueues = new Map();
|
|
416
347
|
this.protocolV2FramePromises = new Map();
|
|
417
|
-
this.
|
|
418
|
-
|
|
348
|
+
this.protocolV2Links = new transport.ProtocolV2LinkManager({
|
|
349
|
+
getSchemas: () => {
|
|
350
|
+
if (!this._messages || !this._messagesV2) {
|
|
351
|
+
throw hdShared.ERRORS.TypedError(hdShared.HardwareErrorCode.TransportNotConfigured);
|
|
352
|
+
}
|
|
353
|
+
return {
|
|
354
|
+
protocolV1: this._messages,
|
|
355
|
+
protocolV2: this._messagesV2,
|
|
356
|
+
};
|
|
357
|
+
},
|
|
358
|
+
classifyError: () => 'link-fatal',
|
|
359
|
+
onLinkInvalidated: (uuid, reason) => __awaiter(this, void 0, void 0, function* () {
|
|
360
|
+
var _b;
|
|
361
|
+
(_b = this.protocolV2Assemblers.get(uuid)) === null || _b === void 0 ? void 0 : _b.reset();
|
|
362
|
+
this.rejectProtocolV2Frames(uuid, new Error(reason));
|
|
363
|
+
Log === null || Log === void 0 ? void 0 : Log.debug('[ReactNativeBleTransport] Protocol V2 link invalidated:', uuid, reason);
|
|
364
|
+
if (reason.startsWith('Protocol V2 link-fatal error:')) {
|
|
365
|
+
yield this.releaseNative(uuid, true);
|
|
366
|
+
}
|
|
367
|
+
}),
|
|
368
|
+
});
|
|
419
369
|
this.monitorTokens = new Map();
|
|
370
|
+
this.disconnectEventTokens = new Map();
|
|
420
371
|
this.nextMonitorToken = 1;
|
|
421
372
|
this.scanTimeout = (_a = options.scanTimeout) !== null && _a !== void 0 ? _a : DEVICE_SCAN_TIMEOUT_MS;
|
|
422
373
|
}
|
|
@@ -430,8 +381,18 @@ class ReactNativeBleTransport {
|
|
|
430
381
|
this._messages = messages;
|
|
431
382
|
}
|
|
432
383
|
configureProtocolV2(signedData) {
|
|
384
|
+
const configuration = typeof signedData === 'string' ? signedData : JSON.stringify(signedData);
|
|
385
|
+
if (this.protocolV2SchemaConfiguration === configuration) {
|
|
386
|
+
return;
|
|
387
|
+
}
|
|
388
|
+
const isReconfiguration = this.protocolV2SchemaConfiguration !== undefined;
|
|
433
389
|
this._messagesV2 = parseConfigure(signedData);
|
|
434
|
-
|
|
390
|
+
this.protocolV2SchemaConfiguration = configuration;
|
|
391
|
+
if (isReconfiguration) {
|
|
392
|
+
this.protocolV2Links
|
|
393
|
+
.invalidateAllLinks('Protocol V2 schema reconfigured')
|
|
394
|
+
.catch(error => Log === null || Log === void 0 ? void 0 : Log.debug('Protocol V2 schema link cleanup failed:', error));
|
|
395
|
+
}
|
|
435
396
|
}
|
|
436
397
|
listen() {
|
|
437
398
|
}
|
|
@@ -442,7 +403,6 @@ class ReactNativeBleTransport {
|
|
|
442
403
|
return Promise.resolve(this.blePlxManager);
|
|
443
404
|
}
|
|
444
405
|
resolveCharacteristics(device) {
|
|
445
|
-
var _a, _b, _c, _d;
|
|
446
406
|
return __awaiter(this, void 0, void 0, function* () {
|
|
447
407
|
yield device.discoverAllServicesAndCharacteristics();
|
|
448
408
|
let infos = tryToGetConfiguration(device);
|
|
@@ -459,19 +419,11 @@ class ReactNativeBleTransport {
|
|
|
459
419
|
}
|
|
460
420
|
}
|
|
461
421
|
}
|
|
462
|
-
let fallbackServiceUuid;
|
|
463
422
|
if (!infos) {
|
|
464
423
|
const services = yield device.services();
|
|
465
424
|
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));
|
|
466
|
-
const knownService = services.find(service => getInfosForServiceUuid(service.uuid, 'classic'));
|
|
467
|
-
const fallbackService = (_a = knownService !== null && knownService !== void 0 ? knownService : services.find(service => !isGenericBleService(service.uuid))) !== null && _a !== void 0 ? _a : services[0];
|
|
468
|
-
if (fallbackService) {
|
|
469
|
-
fallbackServiceUuid = fallbackService.uuid;
|
|
470
|
-
characteristics = yield device.characteristicsForService(fallbackService.uuid);
|
|
471
|
-
Log === null || Log === void 0 ? void 0 : Log.debug('[ReactNativeBleTransport] Using fallback BLE service:', fallbackService.uuid);
|
|
472
|
-
}
|
|
473
425
|
}
|
|
474
|
-
if (!infos
|
|
426
|
+
if (!infos) {
|
|
475
427
|
try {
|
|
476
428
|
Log === null || Log === void 0 ? void 0 : Log.debug('cancel connection when service not found');
|
|
477
429
|
yield device.cancelConnection();
|
|
@@ -481,9 +433,7 @@ class ReactNativeBleTransport {
|
|
|
481
433
|
}
|
|
482
434
|
throw hdShared.ERRORS.TypedError(hdShared.HardwareErrorCode.BleServiceNotFound);
|
|
483
435
|
}
|
|
484
|
-
const serviceUuid
|
|
485
|
-
const writeUuid = (_c = infos === null || infos === void 0 ? void 0 : infos.writeUuid) !== null && _c !== void 0 ? _c : '00000002-0000-1000-8000-00805f9b34fb';
|
|
486
|
-
const notifyUuid = (_d = infos === null || infos === void 0 ? void 0 : infos.notifyUuid) !== null && _d !== void 0 ? _d : '00000003-0000-1000-8000-00805f9b34fb';
|
|
436
|
+
const { serviceUuid, writeUuid, notifyUuid } = infos;
|
|
487
437
|
if (!serviceUuid) {
|
|
488
438
|
throw hdShared.ERRORS.TypedError(hdShared.HardwareErrorCode.BleServiceNotFound);
|
|
489
439
|
}
|
|
@@ -524,8 +474,8 @@ class ReactNativeBleTransport {
|
|
|
524
474
|
attachDisconnectSubscription(transport, device, uuid) {
|
|
525
475
|
var _a;
|
|
526
476
|
(_a = transport.disconnectSubscription) === null || _a === void 0 ? void 0 : _a.remove();
|
|
477
|
+
const { monitorToken } = transport;
|
|
527
478
|
transport.disconnectSubscription = device.onDisconnected(() => {
|
|
528
|
-
var _a;
|
|
529
479
|
if (this.firmwareUploadWriteRecoveryIds.has(uuid)) {
|
|
530
480
|
Log === null || Log === void 0 ? void 0 : Log.debug('device disconnect ignored during FirmwareUpload write recovery: ', uuid);
|
|
531
481
|
return;
|
|
@@ -534,17 +484,16 @@ class ReactNativeBleTransport {
|
|
|
534
484
|
Log === null || Log === void 0 ? void 0 : Log.debug('device disconnect ignored for stale transport: ', device === null || device === void 0 ? void 0 : device.id);
|
|
535
485
|
return;
|
|
536
486
|
}
|
|
487
|
+
if (this.monitorTokens.get(uuid) !== monitorToken) {
|
|
488
|
+
Log === null || Log === void 0 ? void 0 : Log.debug('device disconnect ignored for stale generation: ', device === null || device === void 0 ? void 0 : device.id);
|
|
489
|
+
return;
|
|
490
|
+
}
|
|
537
491
|
try {
|
|
538
492
|
Log === null || Log === void 0 ? void 0 : Log.debug('device disconnect: ', device === null || device === void 0 ? void 0 : device.id);
|
|
539
|
-
(
|
|
540
|
-
|
|
541
|
-
id: device === null || device === void 0 ? void 0 : device.id,
|
|
542
|
-
connectId: device === null || device === void 0 ? void 0 : device.id,
|
|
543
|
-
});
|
|
544
|
-
if (this.runPromise) {
|
|
493
|
+
this.emitDeviceDisconnect(uuid, device === null || device === void 0 ? void 0 : device.name, monitorToken);
|
|
494
|
+
if (this.runPromise && this.runPromiseDeviceId === uuid) {
|
|
545
495
|
const error = hdShared.ERRORS.TypedError(hdShared.HardwareErrorCode.BleConnectedError);
|
|
546
496
|
this.runPromise.reject(error);
|
|
547
|
-
this.rejectAllProtocolV2Frames(error);
|
|
548
497
|
}
|
|
549
498
|
}
|
|
550
499
|
catch (e) {
|
|
@@ -555,6 +504,22 @@ class ReactNativeBleTransport {
|
|
|
555
504
|
}
|
|
556
505
|
});
|
|
557
506
|
}
|
|
507
|
+
emitDeviceDisconnect(uuid, name, token) {
|
|
508
|
+
var _a;
|
|
509
|
+
if (token === undefined || this.disconnectEventTokens.get(uuid) === token) {
|
|
510
|
+
return;
|
|
511
|
+
}
|
|
512
|
+
if (this.monitorTokens.get(uuid) !== token) {
|
|
513
|
+
Log === null || Log === void 0 ? void 0 : Log.debug('device disconnect event ignored for stale generation: ', uuid);
|
|
514
|
+
return;
|
|
515
|
+
}
|
|
516
|
+
this.disconnectEventTokens.set(uuid, token);
|
|
517
|
+
(_a = this.emitter) === null || _a === void 0 ? void 0 : _a.emit(transport.TRANSPORT_EVENT.DEVICE_DISCONNECT, {
|
|
518
|
+
name,
|
|
519
|
+
id: uuid,
|
|
520
|
+
connectId: uuid,
|
|
521
|
+
});
|
|
522
|
+
}
|
|
558
523
|
reconnectFirmwareUploadTransport(uuid, transport) {
|
|
559
524
|
var _a, _b;
|
|
560
525
|
return __awaiter(this, void 0, void 0, function* () {
|
|
@@ -624,13 +589,12 @@ class ReactNativeBleTransport {
|
|
|
624
589
|
return;
|
|
625
590
|
}
|
|
626
591
|
}
|
|
627
|
-
blePlxManager.startDeviceScan(
|
|
592
|
+
blePlxManager.startDeviceScan(getBluetoothServiceUuids(), {
|
|
628
593
|
allowDuplicates: true,
|
|
629
594
|
scanMode: reactNativeBlePlx.ScanMode.LowLatency,
|
|
630
595
|
}, (error, device) => {
|
|
631
|
-
var _a
|
|
596
|
+
var _a;
|
|
632
597
|
if (error) {
|
|
633
|
-
Log === null || Log === void 0 ? void 0 : Log.debug('ble scan manager: ', blePlxManager);
|
|
634
598
|
Log === null || Log === void 0 ? void 0 : Log.debug('ble scan error: ', error);
|
|
635
599
|
if ([reactNativeBlePlx.BleErrorCode.BluetoothPoweredOff, reactNativeBlePlx.BleErrorCode.BluetoothInUnknownState].includes(error.errorCode)) {
|
|
636
600
|
reject(hdShared.ERRORS.TypedError(hdShared.HardwareErrorCode.BlePermissionError));
|
|
@@ -650,25 +614,14 @@ class ReactNativeBleTransport {
|
|
|
650
614
|
return;
|
|
651
615
|
}
|
|
652
616
|
const displayName = getDeviceDisplayName(device);
|
|
653
|
-
const isOneKey = hdShared.
|
|
654
|
-
|
|
655
|
-
|
|
656
|
-
|
|
657
|
-
|
|
658
|
-
|
|
659
|
-
name: device === null || device === void 0 ? void 0 : device.name,
|
|
660
|
-
localName: device === null || device === void 0 ? void 0 : device.localName,
|
|
661
|
-
id: device === null || device === void 0 ? void 0 : device.id,
|
|
662
|
-
serviceUUIDs: device === null || device === void 0 ? void 0 : device.serviceUUIDs,
|
|
663
|
-
accepted: isOneKey,
|
|
664
|
-
});
|
|
665
|
-
}
|
|
617
|
+
const isOneKey = hdShared.isOnekeyBluetoothDevice({
|
|
618
|
+
id: device === null || device === void 0 ? void 0 : device.id,
|
|
619
|
+
name: device === null || device === void 0 ? void 0 : device.name,
|
|
620
|
+
localName: device === null || device === void 0 ? void 0 : device.localName,
|
|
621
|
+
serviceUuids: device === null || device === void 0 ? void 0 : device.serviceUUIDs,
|
|
622
|
+
});
|
|
666
623
|
if (isOneKey) {
|
|
667
|
-
Log === null || Log === void 0 ? void 0 : Log.debug('search device start ======================');
|
|
668
|
-
const { name, localName, id, serviceUUIDs } = device !== null && device !== void 0 ? device : {};
|
|
669
|
-
Log === null || Log === void 0 ? void 0 : Log.debug(`device name: ${name !== null && name !== void 0 ? name : ''}\nlocalName: ${localName !== null && localName !== void 0 ? localName : ''}\nid: ${id !== null && id !== void 0 ? id : ''}\nserviceUUIDs: ${(serviceUUIDs !== null && serviceUUIDs !== void 0 ? serviceUUIDs : []).join(',')}`);
|
|
670
624
|
addDevice(device);
|
|
671
|
-
Log === null || Log === void 0 ? void 0 : Log.debug('search device end ======================\n');
|
|
672
625
|
}
|
|
673
626
|
else if (displayName && /\bpro\s*2\b/i.test(displayName)) {
|
|
674
627
|
Log === null || Log === void 0 ? void 0 : Log.debug('[ReactNativeBleTransport] Pro2-like BLE device was not accepted:', {
|
|
@@ -679,10 +632,20 @@ class ReactNativeBleTransport {
|
|
|
679
632
|
});
|
|
680
633
|
}
|
|
681
634
|
});
|
|
682
|
-
getConnectedDeviceIds(getBluetoothServiceUuids()).then(devices => {
|
|
635
|
+
getConnectedDeviceIds(reactNative.Platform.OS === 'ios' ? getBluetoothServiceUuids() : []).then(devices => {
|
|
683
636
|
for (const device of devices) {
|
|
684
|
-
|
|
685
|
-
|
|
637
|
+
const localName = 'localName' in device && typeof device.localName === 'string'
|
|
638
|
+
? device.localName
|
|
639
|
+
: null;
|
|
640
|
+
if (hdShared.isOnekeyBluetoothDevice({
|
|
641
|
+
id: device.id,
|
|
642
|
+
name: device.name,
|
|
643
|
+
localName,
|
|
644
|
+
serviceUuids: device.serviceUUIDs,
|
|
645
|
+
})) {
|
|
646
|
+
Log === null || Log === void 0 ? void 0 : Log.debug('search connected peripheral: ', device.id);
|
|
647
|
+
addDevice(device);
|
|
648
|
+
}
|
|
686
649
|
}
|
|
687
650
|
});
|
|
688
651
|
const addDevice = (device) => {
|
|
@@ -694,6 +657,12 @@ class ReactNativeBleTransport {
|
|
|
694
657
|
this.deviceProtocolHints.set(device.id, protocolHint);
|
|
695
658
|
}
|
|
696
659
|
deviceList.push(Object.assign(Object.assign({}, device), { name: displayName, commType: 'ble' }));
|
|
660
|
+
Log === null || Log === void 0 ? void 0 : Log.debug('[ReactNativeBleTransport] OneKey BLE device discovered', {
|
|
661
|
+
deviceId: device.id,
|
|
662
|
+
name: displayName,
|
|
663
|
+
serviceUUIDs: device.serviceUUIDs,
|
|
664
|
+
protocolHint,
|
|
665
|
+
});
|
|
697
666
|
}
|
|
698
667
|
};
|
|
699
668
|
timer.timeout(() => {
|
|
@@ -703,6 +672,33 @@ class ReactNativeBleTransport {
|
|
|
703
672
|
}));
|
|
704
673
|
});
|
|
705
674
|
}
|
|
675
|
+
installTransportForAcquire(uuid, device, characteristics) {
|
|
676
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
677
|
+
const { writeCharacteristic, notifyCharacteristic } = characteristics !== null && characteristics !== void 0 ? characteristics : (yield this.resolveCharacteristics(device));
|
|
678
|
+
const transport$1 = new BleTransport(device, writeCharacteristic, notifyCharacteristic);
|
|
679
|
+
if (reactNative.Platform.OS === 'android') {
|
|
680
|
+
transport$1.mtuSize = typeof device.mtu === 'number' ? device.mtu : transport$1.mtuSize;
|
|
681
|
+
}
|
|
682
|
+
const monitorToken = this.nextMonitorToken;
|
|
683
|
+
this.nextMonitorToken += 1;
|
|
684
|
+
const notifyTransactionId = `${uuid}:notify:${monitorToken}`;
|
|
685
|
+
transport$1.monitorToken = monitorToken;
|
|
686
|
+
transport$1.notifyTransactionId = notifyTransactionId;
|
|
687
|
+
this.monitorTokens.set(uuid, monitorToken);
|
|
688
|
+
transport$1.notifySubscription = this._monitorCharacteristic(transport$1.notifyCharacteristic, uuid, monitorToken, notifyTransactionId);
|
|
689
|
+
transportCache[uuid] = transport$1;
|
|
690
|
+
this.protocolV2Assemblers.set(uuid, new transport.ProtocolV2FrameAssembler(transport.PROTOCOL_V2_BLE_FRAME_MAX_BYTES));
|
|
691
|
+
if (reactNative.Platform.OS === 'ios') {
|
|
692
|
+
yield new Promise(resolve => {
|
|
693
|
+
setTimeout(resolve, IOS_NOTIFY_READY_DELAY_MS);
|
|
694
|
+
});
|
|
695
|
+
}
|
|
696
|
+
else if (reactNative.Platform.OS === 'android') {
|
|
697
|
+
yield delay(ANDROID_NOTIFY_READY_DELAY_MS);
|
|
698
|
+
}
|
|
699
|
+
return transport$1;
|
|
700
|
+
});
|
|
701
|
+
}
|
|
706
702
|
acquire(input) {
|
|
707
703
|
var _a, _b;
|
|
708
704
|
return __awaiter(this, void 0, void 0, function* () {
|
|
@@ -727,9 +723,8 @@ class ReactNativeBleTransport {
|
|
|
727
723
|
if (forceCleanRunPromise && this.runPromise) {
|
|
728
724
|
const error = hdShared.ERRORS.TypedError(hdShared.HardwareErrorCode.BleForceCleanRunPromise);
|
|
729
725
|
this.runPromise.reject(error);
|
|
730
|
-
this.rejectAllProtocolV2Frames(error);
|
|
731
726
|
this.runPromise = null;
|
|
732
|
-
this.
|
|
727
|
+
this.runPromiseDeviceId = null;
|
|
733
728
|
Log === null || Log === void 0 ? void 0 : Log.debug('Force clean Bluetooth run promise, forceCleanRunPromise: ', forceCleanRunPromise);
|
|
734
729
|
}
|
|
735
730
|
const blePlxManager = yield this.getPlxManager();
|
|
@@ -811,50 +806,41 @@ class ReactNativeBleTransport {
|
|
|
811
806
|
}
|
|
812
807
|
}
|
|
813
808
|
device = yield requestAndroidMtu(device);
|
|
814
|
-
const
|
|
809
|
+
const acquiredDevice = device;
|
|
810
|
+
const { writeCharacteristic, notifyCharacteristic } = yield this.resolveCharacteristics(acquiredDevice);
|
|
815
811
|
const protocolHint = expectedProtocol
|
|
816
812
|
? undefined
|
|
817
|
-
: (_a = this.deviceProtocolHints.get(uuid)) !== null &&
|
|
813
|
+
: (_b = (_a = input.protocolHint) !== null && _a !== void 0 ? _a : this.deviceProtocolHints.get(uuid)) !== null && _b !== void 0 ? _b : inferProtocolHintFromDeviceName(getDeviceDisplayName(acquiredDevice));
|
|
818
814
|
yield this.release(uuid, true);
|
|
819
815
|
if (protocolHint) {
|
|
820
816
|
this.deviceProtocolHints.set(uuid, protocolHint);
|
|
821
817
|
}
|
|
822
|
-
|
|
823
|
-
|
|
824
|
-
|
|
825
|
-
}
|
|
826
|
-
|
|
827
|
-
|
|
828
|
-
|
|
829
|
-
|
|
830
|
-
|
|
831
|
-
|
|
832
|
-
|
|
833
|
-
|
|
834
|
-
|
|
835
|
-
|
|
836
|
-
yield new Promise(resolve => {
|
|
837
|
-
setTimeout(resolve, IOS_NOTIFY_READY_DELAY_MS);
|
|
838
|
-
});
|
|
818
|
+
yield this.installTransportForAcquire(uuid, acquiredDevice, {
|
|
819
|
+
writeCharacteristic,
|
|
820
|
+
notifyCharacteristic,
|
|
821
|
+
});
|
|
822
|
+
try {
|
|
823
|
+
const protocolType = yield this.detectProtocol(uuid, expectedProtocol, protocolHint, () => __awaiter(this, void 0, void 0, function* () {
|
|
824
|
+
yield this.installTransportForAcquire(uuid, acquiredDevice);
|
|
825
|
+
}));
|
|
826
|
+
const currentTransport = transportCache[uuid];
|
|
827
|
+
if (!currentTransport) {
|
|
828
|
+
throw hdShared.ERRORS.TypedError(hdShared.HardwareErrorCode.TransportNotFound);
|
|
829
|
+
}
|
|
830
|
+
this.attachDisconnectSubscription(currentTransport, acquiredDevice, uuid);
|
|
831
|
+
return { uuid, protocolType };
|
|
839
832
|
}
|
|
840
|
-
|
|
841
|
-
yield
|
|
833
|
+
catch (error) {
|
|
834
|
+
yield this.release(uuid, true);
|
|
835
|
+
throw error;
|
|
842
836
|
}
|
|
843
|
-
const protocolType = yield this.detectProtocol(uuid, expectedProtocol, protocolHint);
|
|
844
|
-
(_b = this.emitter) === null || _b === void 0 ? void 0 : _b.emit('device-connect', {
|
|
845
|
-
name: device.name,
|
|
846
|
-
id: device.id,
|
|
847
|
-
connectId: device.id,
|
|
848
|
-
});
|
|
849
|
-
this.attachDisconnectSubscription(transport$1, device, uuid);
|
|
850
|
-
return { uuid, protocolType };
|
|
851
837
|
});
|
|
852
838
|
}
|
|
853
839
|
_monitorCharacteristic(characteristic, uuid, monitorToken, notifyTransactionId) {
|
|
854
840
|
let bufferLength = 0;
|
|
855
841
|
let buffer$1 = [];
|
|
856
842
|
const subscription = characteristic.monitor((error, c) => {
|
|
857
|
-
var _a, _b, _c, _d, _e, _f, _g, _h, _j;
|
|
843
|
+
var _a, _b, _c, _d, _e, _f, _g, _h, _j, _k, _l, _m, _o, _p, _q, _r;
|
|
858
844
|
const isCurrentMonitor = this.monitorTokens.get(uuid) === monitorToken;
|
|
859
845
|
if (error) {
|
|
860
846
|
Log === null || Log === void 0 ? void 0 : Log.debug(`error monitor ${characteristic.uuid}, deviceId: ${characteristic.deviceID}: ${error}`);
|
|
@@ -866,28 +852,44 @@ class ReactNativeBleTransport {
|
|
|
866
852
|
Log === null || Log === void 0 ? void 0 : Log.debug('monitor error ignored for stale transport: ', uuid, notifyTransactionId);
|
|
867
853
|
return;
|
|
868
854
|
}
|
|
869
|
-
if (this.
|
|
870
|
-
let
|
|
855
|
+
if (this.deviceProtocol.get(uuid) === 'V2') {
|
|
856
|
+
let errorCode = hdShared.HardwareErrorCode.BleCharacteristicNotifyError;
|
|
871
857
|
if ((_a = error.reason) === null || _a === void 0 ? void 0 : _a.includes('The connection has timed out unexpectedly')) {
|
|
872
|
-
|
|
858
|
+
errorCode = hdShared.HardwareErrorCode.BleTimeoutError;
|
|
873
859
|
}
|
|
874
|
-
if ((_b = error.reason) === null || _b === void 0 ? void 0 : _b.includes('Encryption is insufficient')) {
|
|
875
|
-
|
|
860
|
+
else if ((_b = error.reason) === null || _b === void 0 ? void 0 : _b.includes('Encryption is insufficient')) {
|
|
861
|
+
errorCode = hdShared.HardwareErrorCode.BleDeviceBondError;
|
|
876
862
|
}
|
|
877
|
-
if (((_c = error.reason) === null || _c === void 0 ? void 0 : _c.includes('Cannot write client characteristic config descriptor')) ||
|
|
863
|
+
else if (((_c = error.reason) === null || _c === void 0 ? void 0 : _c.includes('Cannot write client characteristic config descriptor')) ||
|
|
878
864
|
((_d = error.reason) === null || _d === void 0 ? void 0 : _d.includes('Cannot find client characteristic config descriptor')) ||
|
|
879
865
|
((_e = error.reason) === null || _e === void 0 ? void 0 : _e.includes('The handle is invalid')) ||
|
|
880
866
|
((_f = error.reason) === null || _f === void 0 ? void 0 : _f.includes('Writing is not permitted')) ||
|
|
881
867
|
((_g = error.reason) === null || _g === void 0 ? void 0 : _g.includes('notify change failed for device'))) {
|
|
868
|
+
errorCode = hdShared.HardwareErrorCode.BleCharacteristicNotifyChangeFailure;
|
|
869
|
+
}
|
|
870
|
+
this.rejectProtocolV2Frames(uuid, hdShared.ERRORS.TypedError(errorCode));
|
|
871
|
+
return;
|
|
872
|
+
}
|
|
873
|
+
if (this.runPromise && this.runPromiseDeviceId === uuid) {
|
|
874
|
+
let ERROR = hdShared.HardwareErrorCode.BleCharacteristicNotifyError;
|
|
875
|
+
if ((_h = error.reason) === null || _h === void 0 ? void 0 : _h.includes('The connection has timed out unexpectedly')) {
|
|
876
|
+
ERROR = hdShared.HardwareErrorCode.BleTimeoutError;
|
|
877
|
+
}
|
|
878
|
+
if ((_j = error.reason) === null || _j === void 0 ? void 0 : _j.includes('Encryption is insufficient')) {
|
|
879
|
+
ERROR = hdShared.HardwareErrorCode.BleDeviceBondError;
|
|
880
|
+
}
|
|
881
|
+
if (((_k = error.reason) === null || _k === void 0 ? void 0 : _k.includes('Cannot write client characteristic config descriptor')) ||
|
|
882
|
+
((_l = error.reason) === null || _l === void 0 ? void 0 : _l.includes('Cannot find client characteristic config descriptor')) ||
|
|
883
|
+
((_m = error.reason) === null || _m === void 0 ? void 0 : _m.includes('The handle is invalid')) ||
|
|
884
|
+
((_o = error.reason) === null || _o === void 0 ? void 0 : _o.includes('Writing is not permitted')) ||
|
|
885
|
+
((_p = error.reason) === null || _p === void 0 ? void 0 : _p.includes('notify change failed for device'))) {
|
|
882
886
|
const notifyError = hdShared.ERRORS.TypedError(hdShared.HardwareErrorCode.BleCharacteristicNotifyChangeFailure);
|
|
883
887
|
this.runPromise.reject(notifyError);
|
|
884
|
-
this.rejectAllProtocolV2Frames(notifyError);
|
|
885
888
|
Log === null || Log === void 0 ? void 0 : Log.debug(`${hdShared.HardwareErrorCode.BleCharacteristicNotifyChangeFailure} ${error.message} ${error.reason}`);
|
|
886
889
|
return;
|
|
887
890
|
}
|
|
888
891
|
const notifyError = hdShared.ERRORS.TypedError(ERROR);
|
|
889
892
|
this.runPromise.reject(notifyError);
|
|
890
|
-
this.rejectAllProtocolV2Frames(notifyError);
|
|
891
893
|
Log === null || Log === void 0 ? void 0 : Log.debug(': monitor notify error, and has unreleased Promise', Error);
|
|
892
894
|
}
|
|
893
895
|
return;
|
|
@@ -907,7 +909,7 @@ class ReactNativeBleTransport {
|
|
|
907
909
|
return;
|
|
908
910
|
}
|
|
909
911
|
if (protocol === 'V2') {
|
|
910
|
-
this.handleProtocolV2Notification(uuid, new Uint8Array(data));
|
|
912
|
+
this.handleProtocolV2Notification(uuid, monitorToken, new Uint8Array(data));
|
|
911
913
|
return;
|
|
912
914
|
}
|
|
913
915
|
if (isHeaderChunk(data)) {
|
|
@@ -921,28 +923,40 @@ class ReactNativeBleTransport {
|
|
|
921
923
|
const value = buffer.Buffer.from(buffer$1);
|
|
922
924
|
bufferLength = 0;
|
|
923
925
|
buffer$1 = [];
|
|
924
|
-
(
|
|
926
|
+
if (this.runPromiseDeviceId === uuid) {
|
|
927
|
+
(_q = this.runPromise) === null || _q === void 0 ? void 0 : _q.resolve(value.toString('hex'));
|
|
928
|
+
}
|
|
925
929
|
}
|
|
926
930
|
}
|
|
927
931
|
catch (error) {
|
|
928
932
|
Log === null || Log === void 0 ? void 0 : Log.debug('monitor data error: ', error);
|
|
929
933
|
const notifyError = hdShared.ERRORS.TypedError(hdShared.HardwareErrorCode.BleWriteCharacteristicError);
|
|
930
|
-
(
|
|
931
|
-
|
|
934
|
+
if (this.deviceProtocol.get(uuid) === 'V2') {
|
|
935
|
+
this.rejectProtocolV2Frames(uuid, notifyError);
|
|
936
|
+
}
|
|
937
|
+
else if (this.runPromiseDeviceId === uuid) {
|
|
938
|
+
(_r = this.runPromise) === null || _r === void 0 ? void 0 : _r.reject(notifyError);
|
|
939
|
+
}
|
|
932
940
|
}
|
|
933
941
|
}, notifyTransactionId);
|
|
934
942
|
return subscription;
|
|
935
943
|
}
|
|
936
944
|
release(uuid, onclose = false) {
|
|
937
|
-
|
|
945
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
946
|
+
yield this.protocolV2Links.invalidateLink(uuid, 'React Native BLE transport released');
|
|
947
|
+
return this.releaseNative(uuid, onclose);
|
|
948
|
+
});
|
|
949
|
+
}
|
|
950
|
+
releaseNative(uuid, onclose = false) {
|
|
951
|
+
var _a, _b, _c, _d, _e, _f, _g;
|
|
938
952
|
return __awaiter(this, void 0, void 0, function* () {
|
|
939
953
|
const transport = transportCache[uuid];
|
|
940
|
-
if (this.runPromise) {
|
|
954
|
+
if (this.runPromise && this.runPromiseDeviceId === uuid) {
|
|
941
955
|
const error = hdShared.ERRORS.TypedError(hdShared.HardwareErrorCode.BleForceCleanRunPromise);
|
|
942
956
|
this.runPromise.reject(error);
|
|
943
957
|
this.runPromise = null;
|
|
944
|
-
this.
|
|
945
|
-
this.
|
|
958
|
+
this.runPromiseDeviceId = null;
|
|
959
|
+
this.rejectProtocolV2Frames(uuid, error);
|
|
946
960
|
}
|
|
947
961
|
else {
|
|
948
962
|
this.resetProtocolV2Frames(uuid);
|
|
@@ -950,9 +964,6 @@ class ReactNativeBleTransport {
|
|
|
950
964
|
if (reactNative.Platform.OS === 'android' && !onclose && transport) {
|
|
951
965
|
(_a = this.protocolV2Assemblers.get(uuid)) === null || _a === void 0 ? void 0 : _a.reset();
|
|
952
966
|
this.resetProtocolV2Frames(uuid);
|
|
953
|
-
if (((_b = this.activeProtocolV2Call) === null || _b === void 0 ? void 0 : _b.uuid) === uuid) {
|
|
954
|
-
this.activeProtocolV2Call = null;
|
|
955
|
-
}
|
|
956
967
|
return Promise.resolve(true);
|
|
957
968
|
}
|
|
958
969
|
if (transport) {
|
|
@@ -960,14 +971,14 @@ class ReactNativeBleTransport {
|
|
|
960
971
|
this.monitorTokens.delete(uuid);
|
|
961
972
|
}
|
|
962
973
|
Log === null || Log === void 0 ? void 0 : Log.debug('release: removing disconnect subscription for device: ', uuid);
|
|
963
|
-
(
|
|
974
|
+
(_b = transport.disconnectSubscription) === null || _b === void 0 ? void 0 : _b.remove();
|
|
964
975
|
transport.disconnectSubscription = undefined;
|
|
965
|
-
Log === null || Log === void 0 ? void 0 : Log.debug('release: removing notify subscription, characteristic: ', (
|
|
966
|
-
(
|
|
976
|
+
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);
|
|
977
|
+
(_d = transport.notifySubscription) === null || _d === void 0 ? void 0 : _d.remove();
|
|
967
978
|
transport.notifySubscription = undefined;
|
|
968
979
|
if (transport.notifyTransactionId) {
|
|
969
980
|
try {
|
|
970
|
-
yield ((
|
|
981
|
+
yield ((_e = this.blePlxManager) === null || _e === void 0 ? void 0 : _e.cancelTransaction(transport.notifyTransactionId));
|
|
971
982
|
}
|
|
972
983
|
catch (e) {
|
|
973
984
|
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);
|
|
@@ -976,12 +987,11 @@ class ReactNativeBleTransport {
|
|
|
976
987
|
delete transportCache[uuid];
|
|
977
988
|
}
|
|
978
989
|
this.deviceProtocol.delete(uuid);
|
|
979
|
-
this.
|
|
980
|
-
(_g = this.protocolV2Assemblers.get(uuid)) === null || _g === void 0 ? void 0 : _g.reset();
|
|
990
|
+
(_f = this.protocolV2Assemblers.get(uuid)) === null || _f === void 0 ? void 0 : _f.reset();
|
|
981
991
|
this.protocolV2Assemblers.delete(uuid);
|
|
982
992
|
this.resetProtocolV2Frames(uuid);
|
|
983
993
|
try {
|
|
984
|
-
yield ((
|
|
994
|
+
yield ((_g = this.blePlxManager) === null || _g === void 0 ? void 0 : _g.cancelTransaction(uuid));
|
|
985
995
|
}
|
|
986
996
|
catch (e) {
|
|
987
997
|
Log === null || Log === void 0 ? void 0 : Log.debug('release: cancel transaction error (ignored): ', (e === null || e === void 0 ? void 0 : e.message) || e);
|
|
@@ -1002,30 +1012,18 @@ class ReactNativeBleTransport {
|
|
|
1002
1012
|
if (this._messages == null) {
|
|
1003
1013
|
throw hdShared.ERRORS.TypedError(hdShared.HardwareErrorCode.TransportNotConfigured);
|
|
1004
1014
|
}
|
|
1005
|
-
const forceRun = name === 'Initialize' || name === 'Cancel';
|
|
1006
|
-
Log === null || Log === void 0 ? void 0 : Log.debug('transport-react-native call this.runPromise', this.runPromise);
|
|
1007
|
-
if (this.runPromise && !forceRun) {
|
|
1008
|
-
throw hdShared.ERRORS.TypedError(hdShared.HardwareErrorCode.TransportCallInProgress);
|
|
1009
|
-
}
|
|
1010
1015
|
const protocol = this.getProtocolType(uuid);
|
|
1011
1016
|
if (!protocol) {
|
|
1012
1017
|
throw hdShared.ERRORS.TypedError(hdShared.HardwareErrorCode.RuntimeError, `Device protocol has not been detected for ${uuid}`);
|
|
1013
1018
|
}
|
|
1014
|
-
|
|
1015
|
-
Log === null || Log === void 0 ? void 0 : Log.debug('transport-react-native', 'call-', ' name: ', name, ' data: ', {
|
|
1016
|
-
file_name: data === null || data === void 0 ? void 0 : data.file_name,
|
|
1017
|
-
hash: data === null || data === void 0 ? void 0 : data.hash,
|
|
1018
|
-
});
|
|
1019
|
-
}
|
|
1020
|
-
else if (transport.LogBlockCommand.has(name)) {
|
|
1021
|
-
Log === null || Log === void 0 ? void 0 : Log.debug('transport-react-native', 'call-', ' name: ', name, ' protocol: ', protocol);
|
|
1022
|
-
}
|
|
1023
|
-
else {
|
|
1024
|
-
Log === null || Log === void 0 ? void 0 : Log.debug('transport-react-native', 'call-', ' name: ', name, ' data: ', data, ' protocol: ', protocol);
|
|
1025
|
-
}
|
|
1019
|
+
Log === null || Log === void 0 ? void 0 : Log.debug('transport call', transport.createTransportCallLog(name, protocol, data));
|
|
1026
1020
|
if (protocol === 'V2') {
|
|
1027
1021
|
return this.callProtocolV2(uuid, name, data, options);
|
|
1028
1022
|
}
|
|
1023
|
+
const forceRun = name === 'Initialize' || name === 'Cancel';
|
|
1024
|
+
if (this.runPromise && !forceRun) {
|
|
1025
|
+
throw hdShared.ERRORS.TypedError(hdShared.HardwareErrorCode.TransportCallInProgress);
|
|
1026
|
+
}
|
|
1029
1027
|
return this.callProtocolV1(uuid, name, data, options);
|
|
1030
1028
|
});
|
|
1031
1029
|
}
|
|
@@ -1038,6 +1036,7 @@ class ReactNativeBleTransport {
|
|
|
1038
1036
|
const runPromise = hdShared.createDeferred();
|
|
1039
1037
|
runPromise.promise.catch(() => undefined);
|
|
1040
1038
|
this.runPromise = runPromise;
|
|
1039
|
+
this.runPromiseDeviceId = uuid;
|
|
1041
1040
|
const messages = this._messages;
|
|
1042
1041
|
const buffers = ProtocolV1.encodeTransportPackets(messages, name, data);
|
|
1043
1042
|
let timeout;
|
|
@@ -1101,7 +1100,7 @@ class ReactNativeBleTransport {
|
|
|
1101
1100
|
});
|
|
1102
1101
|
}
|
|
1103
1102
|
else if (name === 'FirmwareUpload') {
|
|
1104
|
-
Log === null || Log === void 0 ? void 0 : Log.debug('[ReactNativeBleTransport]
|
|
1103
|
+
Log === null || Log === void 0 ? void 0 : Log.debug('[ReactNativeBleTransport] Firmware upload transport configured', {
|
|
1105
1104
|
packetCapacity: FIRMWARE_UPLOAD_WRITE_PACKET_CAPACITY,
|
|
1106
1105
|
burstSize: FIRMWARE_UPLOAD_WRITE_BURST_SIZE,
|
|
1107
1106
|
pauseMs: FIRMWARE_UPLOAD_WRITE_PAUSE_MS,
|
|
@@ -1120,32 +1119,14 @@ class ReactNativeBleTransport {
|
|
|
1120
1119
|
if (!retryType || attempt >= FIRMWARE_UPLOAD_WRITE_MAX_RETRIES) {
|
|
1121
1120
|
throw error;
|
|
1122
1121
|
}
|
|
1123
|
-
const
|
|
1124
|
-
const delayMs = shouldReconnect
|
|
1125
|
-
? FIRMWARE_UPLOAD_RECONNECT_RETRY_DELAY_MS
|
|
1126
|
-
: resolveFirmwareUploadRetryDelay(attempt);
|
|
1122
|
+
const delayMs = resolveFirmwareUploadRetryDelay(attempt);
|
|
1127
1123
|
Log === null || Log === void 0 ? void 0 : Log.debug('[ReactNativeBleTransport] FirmwareUpload write retry:', {
|
|
1128
1124
|
attempt: attempt + 1,
|
|
1129
1125
|
delayMs,
|
|
1130
|
-
reconnect: shouldReconnect,
|
|
1131
1126
|
error,
|
|
1132
1127
|
});
|
|
1133
|
-
if (shouldReconnect) {
|
|
1134
|
-
this.firmwareUploadWriteRecoveryIds.add(uuid);
|
|
1135
|
-
}
|
|
1136
1128
|
yield delay(delayMs);
|
|
1137
1129
|
attempt += 1;
|
|
1138
|
-
if (shouldReconnect) {
|
|
1139
|
-
try {
|
|
1140
|
-
yield this.reconnectFirmwareUploadTransport(uuid, transport);
|
|
1141
|
-
}
|
|
1142
|
-
catch (e) {
|
|
1143
|
-
Log === null || Log === void 0 ? void 0 : Log.debug('[ReactNativeBleTransport] FirmwareUpload reconnect error:', e);
|
|
1144
|
-
if (attempt >= FIRMWARE_UPLOAD_WRITE_MAX_RETRIES) {
|
|
1145
|
-
throw e;
|
|
1146
|
-
}
|
|
1147
|
-
}
|
|
1148
|
-
}
|
|
1149
1130
|
}
|
|
1150
1131
|
}
|
|
1151
1132
|
}), e => {
|
|
@@ -1190,17 +1171,21 @@ class ReactNativeBleTransport {
|
|
|
1190
1171
|
if (typeof response !== 'string') {
|
|
1191
1172
|
throw new Error('Returning data is not string.');
|
|
1192
1173
|
}
|
|
1193
|
-
Log === null || Log === void 0 ? void 0 : Log.debug('receive data: ', response);
|
|
1194
1174
|
const jsonData = ProtocolV1.decodeMessage(messages, response);
|
|
1195
1175
|
return check.call(jsonData);
|
|
1196
1176
|
}
|
|
1197
1177
|
catch (e) {
|
|
1198
|
-
if (name === '
|
|
1199
|
-
Log === null || Log === void 0 ? void 0 : Log.debug('[ReactNativeBleTransport] Protocol V1
|
|
1178
|
+
if (name === 'GetFeatures' && (options === null || options === void 0 ? void 0 : options.timeoutMs) === PROTOCOL_PROBE_TIMEOUT_MS) {
|
|
1179
|
+
Log === null || Log === void 0 ? void 0 : Log.debug('[ReactNativeBleTransport] Protocol V1 GetFeatures probe call failed:', e);
|
|
1200
1180
|
}
|
|
1201
1181
|
else {
|
|
1202
1182
|
Log === null || Log === void 0 ? void 0 : Log.error('call error: ', e);
|
|
1203
1183
|
}
|
|
1184
|
+
const isProbeTimeout = name === 'GetFeatures' && (options === null || options === void 0 ? void 0 : options.timeoutMs) === PROTOCOL_PROBE_TIMEOUT_MS;
|
|
1185
|
+
if (!isProbeTimeout &&
|
|
1186
|
+
(e === null || e === void 0 ? void 0 : e.errorCode) === hdShared.HardwareErrorCode.BleTimeoutError) {
|
|
1187
|
+
yield this.disconnect(uuid);
|
|
1188
|
+
}
|
|
1204
1189
|
throw e;
|
|
1205
1190
|
}
|
|
1206
1191
|
finally {
|
|
@@ -1208,6 +1193,7 @@ class ReactNativeBleTransport {
|
|
|
1208
1193
|
clearTimeout(timeout);
|
|
1209
1194
|
if (this.runPromise === runPromise) {
|
|
1210
1195
|
this.runPromise = null;
|
|
1196
|
+
this.runPromiseDeviceId = null;
|
|
1211
1197
|
}
|
|
1212
1198
|
}
|
|
1213
1199
|
});
|
|
@@ -1216,10 +1202,11 @@ class ReactNativeBleTransport {
|
|
|
1216
1202
|
this.stopped = true;
|
|
1217
1203
|
}
|
|
1218
1204
|
disconnect(session) {
|
|
1219
|
-
var _a, _b, _c, _d, _e
|
|
1205
|
+
var _a, _b, _c, _d, _e;
|
|
1220
1206
|
return __awaiter(this, void 0, void 0, function* () {
|
|
1221
|
-
|
|
1207
|
+
yield this.protocolV2Links.invalidateLink(session, 'React Native BLE transport disconnected');
|
|
1222
1208
|
const transport = transportCache[session];
|
|
1209
|
+
const monitorToken = (_a = transport === null || transport === void 0 ? void 0 : transport.monitorToken) !== null && _a !== void 0 ? _a : this.monitorTokens.get(session);
|
|
1223
1210
|
if (transport === null || transport === void 0 ? void 0 : transport.disconnectSubscription) {
|
|
1224
1211
|
try {
|
|
1225
1212
|
Log === null || Log === void 0 ? void 0 : Log.debug('disconnect: removing disconnect subscription');
|
|
@@ -1232,7 +1219,7 @@ class ReactNativeBleTransport {
|
|
|
1232
1219
|
}
|
|
1233
1220
|
if (transport === null || transport === void 0 ? void 0 : transport.notifySubscription) {
|
|
1234
1221
|
try {
|
|
1235
|
-
Log === null || Log === void 0 ? void 0 : Log.debug('disconnect: removing notify subscription, characteristic: ', (
|
|
1222
|
+
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);
|
|
1236
1223
|
transport.notifySubscription.remove();
|
|
1237
1224
|
transport.notifySubscription = undefined;
|
|
1238
1225
|
}
|
|
@@ -1242,7 +1229,7 @@ class ReactNativeBleTransport {
|
|
|
1242
1229
|
}
|
|
1243
1230
|
if (session) {
|
|
1244
1231
|
try {
|
|
1245
|
-
yield ((
|
|
1232
|
+
yield ((_c = this.blePlxManager) === null || _c === void 0 ? void 0 : _c.cancelTransaction(session));
|
|
1246
1233
|
}
|
|
1247
1234
|
catch (e) {
|
|
1248
1235
|
Log === null || Log === void 0 ? void 0 : Log.debug('resetSession: cancel transaction error (ignored): ', (e === null || e === void 0 ? void 0 : e.message) || e);
|
|
@@ -1257,7 +1244,7 @@ class ReactNativeBleTransport {
|
|
|
1257
1244
|
}
|
|
1258
1245
|
}
|
|
1259
1246
|
try {
|
|
1260
|
-
yield ((
|
|
1247
|
+
yield ((_d = this.blePlxManager) === null || _d === void 0 ? void 0 : _d.cancelDeviceConnection(session));
|
|
1261
1248
|
}
|
|
1262
1249
|
catch (e) {
|
|
1263
1250
|
Log === null || Log === void 0 ? void 0 : Log.debug('resetSession: manager.cancelDeviceConnection error (ignored): ', (e === null || e === void 0 ? void 0 : e.message) || e);
|
|
@@ -1269,19 +1256,15 @@ class ReactNativeBleTransport {
|
|
|
1269
1256
|
this.deviceProtocolHints.delete(session);
|
|
1270
1257
|
this.protocolV2Assemblers.delete(session);
|
|
1271
1258
|
this.resetProtocolV2Frames(session);
|
|
1272
|
-
if (((_d = this.activeProtocolV2Call) === null || _d === void 0 ? void 0 : _d.uuid) === session) {
|
|
1273
|
-
this.activeProtocolV2Call = null;
|
|
1274
|
-
}
|
|
1275
1259
|
try {
|
|
1276
|
-
(_e =
|
|
1277
|
-
name: (_f = transport === null || transport === void 0 ? void 0 : transport.device) === null || _f === void 0 ? void 0 : _f.name,
|
|
1278
|
-
id: session,
|
|
1279
|
-
connectId: session,
|
|
1280
|
-
});
|
|
1260
|
+
this.emitDeviceDisconnect(session, (_e = transport === null || transport === void 0 ? void 0 : transport.device) === null || _e === void 0 ? void 0 : _e.name, monitorToken);
|
|
1281
1261
|
}
|
|
1282
1262
|
catch (e) {
|
|
1283
1263
|
Log === null || Log === void 0 ? void 0 : Log.error('resetSession: emit disconnect event error: ', e);
|
|
1284
1264
|
}
|
|
1265
|
+
if (monitorToken !== undefined && this.monitorTokens.get(session) === monitorToken) {
|
|
1266
|
+
this.monitorTokens.delete(session);
|
|
1267
|
+
}
|
|
1285
1268
|
yield new Promise(resolve => setTimeout(() => resolve(), 100));
|
|
1286
1269
|
});
|
|
1287
1270
|
}
|
|
@@ -1289,6 +1272,7 @@ class ReactNativeBleTransport {
|
|
|
1289
1272
|
Log === null || Log === void 0 ? void 0 : Log.debug('transport-react-native transport cancel');
|
|
1290
1273
|
if (this.runPromise) ;
|
|
1291
1274
|
this.runPromise = null;
|
|
1275
|
+
this.runPromiseDeviceId = null;
|
|
1292
1276
|
}
|
|
1293
1277
|
getCachedTransport(uuid) {
|
|
1294
1278
|
const transport = transportCache[uuid];
|
|
@@ -1301,38 +1285,59 @@ class ReactNativeBleTransport {
|
|
|
1301
1285
|
return hdShared.ERRORS.TypedError(hdShared.HardwareErrorCode.RuntimeError, `Device protocol mismatch: expected ${expected}, but device did not respond to expected protocol`);
|
|
1302
1286
|
}
|
|
1303
1287
|
createProtocolDetectionError() {
|
|
1304
|
-
return hdShared.ERRORS.TypedError(hdShared.HardwareErrorCode.BleTimeoutError, 'Unable to detect BLE protocol: device did not respond to Protocol V1
|
|
1288
|
+
return hdShared.ERRORS.TypedError(hdShared.HardwareErrorCode.BleTimeoutError, 'Unable to detect BLE protocol: device did not respond to Protocol V1 GetFeatures or Protocol V2 Ping');
|
|
1305
1289
|
}
|
|
1306
1290
|
clearProbeProtocol(uuid, protocol) {
|
|
1307
1291
|
if (this.deviceProtocol.get(uuid) === protocol) {
|
|
1308
1292
|
this.deviceProtocol.delete(uuid);
|
|
1309
1293
|
}
|
|
1310
1294
|
}
|
|
1311
|
-
detectProtocol(uuid, expectedProtocol, protocolHint) {
|
|
1295
|
+
detectProtocol(uuid, expectedProtocol, protocolHint, rebuildTransport) {
|
|
1312
1296
|
return __awaiter(this, void 0, void 0, function* () {
|
|
1313
1297
|
if (expectedProtocol === 'V1') {
|
|
1314
1298
|
if (yield this.probeProtocolV1(uuid)) {
|
|
1315
1299
|
this.deviceProtocol.set(uuid, 'V1');
|
|
1316
|
-
Log === null || Log === void 0 ? void 0 : Log.debug(
|
|
1300
|
+
Log === null || Log === void 0 ? void 0 : Log.debug('[ReactNativeBleTransport] protocol detected', {
|
|
1301
|
+
deviceId: uuid,
|
|
1302
|
+
protocol: 'V1',
|
|
1303
|
+
source: 'expected',
|
|
1304
|
+
});
|
|
1317
1305
|
return 'V1';
|
|
1318
1306
|
}
|
|
1319
1307
|
throw this.createProtocolMismatchError(expectedProtocol);
|
|
1320
1308
|
}
|
|
1321
1309
|
if (expectedProtocol === 'V2') {
|
|
1322
|
-
this.
|
|
1323
|
-
|
|
1324
|
-
|
|
1310
|
+
if (yield this.probeProtocolV2(uuid)) {
|
|
1311
|
+
this.deviceProtocol.set(uuid, 'V2');
|
|
1312
|
+
Log === null || Log === void 0 ? void 0 : Log.debug('[ReactNativeBleTransport] protocol detected', {
|
|
1313
|
+
deviceId: uuid,
|
|
1314
|
+
protocol: 'V2',
|
|
1315
|
+
source: 'expected',
|
|
1316
|
+
});
|
|
1317
|
+
return 'V2';
|
|
1318
|
+
}
|
|
1319
|
+
throw this.createProtocolMismatchError(expectedProtocol);
|
|
1325
1320
|
}
|
|
1326
1321
|
const probeOrder = protocolHint === 'V2' || this.deviceProtocol.get(uuid) === 'V2' ? ['V2', 'V1'] : ['V1', 'V2'];
|
|
1327
1322
|
for (let i = 0; i < probeOrder.length; i += 1) {
|
|
1328
1323
|
const protocol = probeOrder[i];
|
|
1329
1324
|
if (i > 0) {
|
|
1330
1325
|
yield this.resetProbeStateAfterProtocolProbe(uuid, probeOrder[i - 1]);
|
|
1326
|
+
if (!transportCache[uuid]) {
|
|
1327
|
+
if (!rebuildTransport) {
|
|
1328
|
+
throw hdShared.ERRORS.TypedError(hdShared.HardwareErrorCode.TransportNotFound);
|
|
1329
|
+
}
|
|
1330
|
+
yield rebuildTransport();
|
|
1331
|
+
}
|
|
1331
1332
|
}
|
|
1332
1333
|
const detected = protocol === 'V1' ? yield this.probeProtocolV1(uuid) : yield this.probeProtocolV2(uuid);
|
|
1333
1334
|
if (detected) {
|
|
1334
1335
|
this.deviceProtocol.set(uuid, protocol);
|
|
1335
|
-
Log === null || Log === void 0 ? void 0 : Log.debug(
|
|
1336
|
+
Log === null || Log === void 0 ? void 0 : Log.debug('[ReactNativeBleTransport] protocol detected', {
|
|
1337
|
+
deviceId: uuid,
|
|
1338
|
+
protocol,
|
|
1339
|
+
source: 'probe',
|
|
1340
|
+
});
|
|
1336
1341
|
return protocol;
|
|
1337
1342
|
}
|
|
1338
1343
|
}
|
|
@@ -1341,14 +1346,12 @@ class ReactNativeBleTransport {
|
|
|
1341
1346
|
});
|
|
1342
1347
|
}
|
|
1343
1348
|
resetProbeStateAfterProtocolProbe(uuid, protocol) {
|
|
1344
|
-
var _a, _b, _c
|
|
1349
|
+
var _a, _b, _c;
|
|
1345
1350
|
return __awaiter(this, void 0, void 0, function* () {
|
|
1346
1351
|
const transport = transportCache[uuid];
|
|
1352
|
+
yield this.protocolV2Links.invalidateLink(uuid, `Reset notify state after Protocol ${protocol} probe`);
|
|
1347
1353
|
(_a = this.protocolV2Assemblers.get(uuid)) === null || _a === void 0 ? void 0 : _a.reset();
|
|
1348
1354
|
this.resetProtocolV2Frames(uuid);
|
|
1349
|
-
if (((_b = this.activeProtocolV2Call) === null || _b === void 0 ? void 0 : _b.uuid) === uuid) {
|
|
1350
|
-
this.activeProtocolV2Call = null;
|
|
1351
|
-
}
|
|
1352
1355
|
if (this.runPromise) {
|
|
1353
1356
|
const error = hdShared.ERRORS.TypedError(hdShared.HardwareErrorCode.BleForceCleanRunPromise);
|
|
1354
1357
|
this.runPromise.reject(error);
|
|
@@ -1360,11 +1363,11 @@ class ReactNativeBleTransport {
|
|
|
1360
1363
|
if (this.monitorTokens.get(uuid) === transport.monitorToken) {
|
|
1361
1364
|
this.monitorTokens.delete(uuid);
|
|
1362
1365
|
}
|
|
1363
|
-
(
|
|
1366
|
+
(_b = transport.notifySubscription) === null || _b === void 0 ? void 0 : _b.remove();
|
|
1364
1367
|
transport.notifySubscription = undefined;
|
|
1365
1368
|
if (previousNotifyTransactionId) {
|
|
1366
1369
|
try {
|
|
1367
|
-
yield ((
|
|
1370
|
+
yield ((_c = this.blePlxManager) === null || _c === void 0 ? void 0 : _c.cancelTransaction(previousNotifyTransactionId));
|
|
1368
1371
|
}
|
|
1369
1372
|
catch (error) {
|
|
1370
1373
|
Log === null || Log === void 0 ? void 0 : Log.debug(`[ReactNativeBleTransport] cancel notify after Protocol ${protocol} probe failed:`, (error === null || error === void 0 ? void 0 : error.message) || error);
|
|
@@ -1391,12 +1394,12 @@ class ReactNativeBleTransport {
|
|
|
1391
1394
|
}
|
|
1392
1395
|
try {
|
|
1393
1396
|
this.deviceProtocol.set(uuid, 'V1');
|
|
1394
|
-
yield this.callProtocolV1(uuid, '
|
|
1397
|
+
yield this.callProtocolV1(uuid, 'GetFeatures', {}, { timeoutMs: PROTOCOL_PROBE_TIMEOUT_MS });
|
|
1395
1398
|
return true;
|
|
1396
1399
|
}
|
|
1397
1400
|
catch (error) {
|
|
1398
1401
|
this.clearProbeProtocol(uuid, 'V1');
|
|
1399
|
-
Log === null || Log === void 0 ? void 0 : Log.debug('[ReactNativeBleTransport] Protocol V1
|
|
1402
|
+
Log === null || Log === void 0 ? void 0 : Log.debug('[ReactNativeBleTransport] Protocol V1 GetFeatures probe failed:', error);
|
|
1400
1403
|
return false;
|
|
1401
1404
|
}
|
|
1402
1405
|
});
|
|
@@ -1426,14 +1429,10 @@ class ReactNativeBleTransport {
|
|
|
1426
1429
|
return detected;
|
|
1427
1430
|
});
|
|
1428
1431
|
}
|
|
1429
|
-
handleProtocolV2Notification(uuid, data) {
|
|
1430
|
-
var _a, _b, _c;
|
|
1432
|
+
handleProtocolV2Notification(uuid, monitorToken, data) {
|
|
1431
1433
|
try {
|
|
1432
|
-
if (
|
|
1433
|
-
(_b = this.protocolV2Assemblers.get(uuid)) === null || _b === void 0 ? void 0 : _b.reset();
|
|
1434
|
-
this.resetProtocolV2Frames(uuid);
|
|
1434
|
+
if (this.monitorTokens.get(uuid) !== monitorToken)
|
|
1435
1435
|
return;
|
|
1436
|
-
}
|
|
1437
1436
|
if (data.length === 0)
|
|
1438
1437
|
return;
|
|
1439
1438
|
const assembler = this.protocolV2Assemblers.get(uuid);
|
|
@@ -1446,8 +1445,10 @@ class ReactNativeBleTransport {
|
|
|
1446
1445
|
catch (error) {
|
|
1447
1446
|
Log === null || Log === void 0 ? void 0 : Log.debug('[ReactNativeBleTransport] Protocol V2 notification error:', error);
|
|
1448
1447
|
const notifyError = hdShared.ERRORS.TypedError(hdShared.HardwareErrorCode.BleWriteCharacteristicError);
|
|
1449
|
-
|
|
1450
|
-
this.
|
|
1448
|
+
this.rejectProtocolV2Frames(uuid, notifyError);
|
|
1449
|
+
this.protocolV2Links
|
|
1450
|
+
.invalidateLink(uuid, `Protocol V2 notification error: ${error}`)
|
|
1451
|
+
.catch(invalidateError => Log === null || Log === void 0 ? void 0 : Log.debug('[ReactNativeBleTransport] Protocol V2 notify cleanup failed:', invalidateError));
|
|
1451
1452
|
}
|
|
1452
1453
|
}
|
|
1453
1454
|
getProtocolV2FrameQueue(uuid) {
|
|
@@ -1467,20 +1468,16 @@ class ReactNativeBleTransport {
|
|
|
1467
1468
|
}
|
|
1468
1469
|
this.getProtocolV2FrameQueue(uuid).push(frame);
|
|
1469
1470
|
}
|
|
1470
|
-
rejectAllProtocolV2Frames(error) {
|
|
1471
|
-
this.protocolV2FrameQueues.clear();
|
|
1472
|
-
for (const framePromise of this.protocolV2FramePromises.values()) {
|
|
1473
|
-
framePromise.reject(error);
|
|
1474
|
-
}
|
|
1475
|
-
this.protocolV2FramePromises.clear();
|
|
1476
|
-
}
|
|
1477
1471
|
resetProtocolV2Frames(uuid) {
|
|
1478
|
-
this.
|
|
1479
|
-
this.protocolV2FramePromises.delete(uuid);
|
|
1472
|
+
this.rejectProtocolV2Frames(uuid, new Error(`Protocol V2 frame state reset for ${uuid}`));
|
|
1480
1473
|
}
|
|
1481
|
-
|
|
1482
|
-
|
|
1483
|
-
|
|
1474
|
+
rejectProtocolV2Frames(uuid, error) {
|
|
1475
|
+
this.protocolV2FrameQueues.delete(uuid);
|
|
1476
|
+
const framePromise = this.protocolV2FramePromises.get(uuid);
|
|
1477
|
+
if (framePromise) {
|
|
1478
|
+
this.protocolV2FramePromises.delete(uuid);
|
|
1479
|
+
framePromise.reject(error);
|
|
1480
|
+
}
|
|
1484
1481
|
}
|
|
1485
1482
|
readProtocolV2Frame(uuid) {
|
|
1486
1483
|
return __awaiter(this, void 0, void 0, function* () {
|
|
@@ -1500,127 +1497,124 @@ class ReactNativeBleTransport {
|
|
|
1500
1497
|
}
|
|
1501
1498
|
});
|
|
1502
1499
|
}
|
|
1503
|
-
|
|
1500
|
+
writeProtocolV2Packet(transport, base64, context, assertCurrentGeneration) {
|
|
1501
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
1502
|
+
let attempt = 0;
|
|
1503
|
+
for (;;) {
|
|
1504
|
+
assertCurrentGeneration();
|
|
1505
|
+
if (context.signal.aborted) {
|
|
1506
|
+
throw new Error(`Protocol V2 BLE write aborted for ${context.messageName}`);
|
|
1507
|
+
}
|
|
1508
|
+
try {
|
|
1509
|
+
yield transport.writeCharacteristic.writeWithoutResponse(base64);
|
|
1510
|
+
assertCurrentGeneration();
|
|
1511
|
+
return;
|
|
1512
|
+
}
|
|
1513
|
+
catch (error) {
|
|
1514
|
+
if (getFirmwareUploadWriteRetryType(error) !== 'congested' ||
|
|
1515
|
+
attempt >= FIRMWARE_UPLOAD_WRITE_MAX_RETRIES) {
|
|
1516
|
+
throw error;
|
|
1517
|
+
}
|
|
1518
|
+
const delayMs = resolveFirmwareUploadRetryDelay(attempt);
|
|
1519
|
+
attempt += 1;
|
|
1520
|
+
Log === null || Log === void 0 ? void 0 : Log.debug('[ReactNativeBleTransport] Protocol V2 congested write retry:', {
|
|
1521
|
+
name: context.messageName,
|
|
1522
|
+
attempt,
|
|
1523
|
+
delayMs,
|
|
1524
|
+
});
|
|
1525
|
+
yield delay(delayMs);
|
|
1526
|
+
}
|
|
1527
|
+
}
|
|
1528
|
+
});
|
|
1529
|
+
}
|
|
1530
|
+
writeProtocolV2Frame(transport$1, frame, context, assertCurrentGeneration) {
|
|
1504
1531
|
return __awaiter(this, void 0, void 0, function* () {
|
|
1505
1532
|
const tuning = getProtocolV2BleTuning();
|
|
1506
1533
|
const packetCapacity = resolveProtocolV2PacketCapacity({
|
|
1507
1534
|
platform: reactNative.Platform.OS,
|
|
1508
1535
|
iosPacketLength: tuning.iosPacketLength,
|
|
1509
1536
|
androidPacketLength: tuning.androidPacketLength,
|
|
1510
|
-
mtu: reactNative.Platform.OS === 'android' ? transport.mtuSize : undefined,
|
|
1537
|
+
mtu: reactNative.Platform.OS === 'android' ? transport$1.mtuSize : undefined,
|
|
1538
|
+
});
|
|
1539
|
+
yield transport.writeProtocolV2BleFrame({
|
|
1540
|
+
frame,
|
|
1541
|
+
packetCapacity,
|
|
1542
|
+
assertActive: assertCurrentGeneration,
|
|
1543
|
+
signal: context.signal,
|
|
1544
|
+
abortMessage: `Protocol V2 BLE write aborted for ${context.messageName}`,
|
|
1545
|
+
burstSize: FIRMWARE_UPLOAD_WRITE_BURST_SIZE,
|
|
1546
|
+
burstPauseMs: FIRMWARE_UPLOAD_WRITE_PAUSE_MS,
|
|
1547
|
+
flushDelayMs: FIRMWARE_UPLOAD_WRITE_FLUSH_DELAY_MS,
|
|
1548
|
+
wait: delay,
|
|
1549
|
+
writePacket: packet => this.writeProtocolV2Packet(transport$1, buffer.Buffer.from(packet).toString('base64'), context, assertCurrentGeneration),
|
|
1511
1550
|
});
|
|
1512
|
-
const writeWithResponse = !!(options === null || options === void 0 ? void 0 : options.writeWithResponse) || (!!(options === null || options === void 0 ? void 0 : options.highVolume) && tuning.highVolumeWriteWithResponse);
|
|
1513
|
-
const writeMode = resolveBleWriteMode(transport.writeCharacteristic, writeWithResponse ? 'withResponse' : 'withoutResponse');
|
|
1514
|
-
const shouldThrottle = !!(options === null || options === void 0 ? void 0 : options.highVolume) && writeMode === 'withoutResponse';
|
|
1515
|
-
let packetsWritten = 0;
|
|
1516
|
-
for (let offset = 0; offset < frame.length; offset += packetCapacity) {
|
|
1517
|
-
const chunk = frame.slice(offset, offset + packetCapacity);
|
|
1518
|
-
const base64 = buffer.Buffer.from(chunk).toString('base64');
|
|
1519
|
-
if (writeMode === 'withResponse') {
|
|
1520
|
-
yield transport.writeCharacteristic.writeWithResponse(base64);
|
|
1521
|
-
}
|
|
1522
|
-
else {
|
|
1523
|
-
yield transport.writeCharacteristic.writeWithoutResponse(base64);
|
|
1524
|
-
}
|
|
1525
|
-
packetsWritten += 1;
|
|
1526
|
-
if (shouldThrottle &&
|
|
1527
|
-
packetsWritten % tuning.highVolumeWriteBurstSize === 0 &&
|
|
1528
|
-
offset + packetCapacity < frame.length) {
|
|
1529
|
-
yield delay(tuning.highVolumeWritePauseMs);
|
|
1530
|
-
}
|
|
1531
|
-
}
|
|
1532
|
-
if (shouldThrottle) {
|
|
1533
|
-
yield delay(tuning.highVolumeWriteFlushDelayMs);
|
|
1534
|
-
}
|
|
1535
1551
|
});
|
|
1536
1552
|
}
|
|
1537
1553
|
callProtocolV2(uuid, name, data, options) {
|
|
1538
|
-
var _a, _b, _c, _d;
|
|
1539
1554
|
return __awaiter(this, void 0, void 0, function* () {
|
|
1540
1555
|
if (!this._messages || !this._messagesV2) {
|
|
1541
1556
|
throw hdShared.ERRORS.TypedError(hdShared.HardwareErrorCode.TransportNotConfigured);
|
|
1542
1557
|
}
|
|
1543
|
-
const
|
|
1544
|
-
if (this.runPromise) {
|
|
1545
|
-
if (!forceRun) {
|
|
1546
|
-
throw hdShared.ERRORS.TypedError(hdShared.HardwareErrorCode.TransportCallInProgress);
|
|
1547
|
-
}
|
|
1548
|
-
const error = hdShared.ERRORS.TypedError(hdShared.HardwareErrorCode.BleForceCleanRunPromise);
|
|
1549
|
-
this.runPromise.reject(error);
|
|
1550
|
-
this.rejectAllProtocolV2Frames(error);
|
|
1551
|
-
this.runPromise = null;
|
|
1552
|
-
this.activeProtocolV2Call = null;
|
|
1553
|
-
}
|
|
1554
|
-
const transport$1 = this.getCachedTransport(uuid);
|
|
1555
|
-
const runPromise = hdShared.createDeferred();
|
|
1556
|
-
runPromise.promise.catch(() => undefined);
|
|
1557
|
-
this.runPromise = runPromise;
|
|
1558
|
-
const callToken = this.nextProtocolV2CallToken++;
|
|
1559
|
-
this.activeProtocolV2Call = { uuid, token: callToken };
|
|
1560
|
-
(_a = this.protocolV2Assemblers.get(uuid)) === null || _a === void 0 ? void 0 : _a.reset();
|
|
1561
|
-
this.resetProtocolV2Frames(uuid);
|
|
1562
|
-
let completed = false;
|
|
1563
|
-
const callOptions = Object.assign(Object.assign({}, options), { timeoutMs: (_b = options === null || options === void 0 ? void 0 : options.timeoutMs) !== null && _b !== void 0 ? _b : BLE_RESPONSE_TIMEOUT_MS });
|
|
1558
|
+
const callOptions = options;
|
|
1564
1559
|
const highVolumeWrite = transport.LogBlockCommand.has(name);
|
|
1565
1560
|
if (highVolumeWrite) {
|
|
1566
1561
|
const tuning = getProtocolV2BleTuning();
|
|
1567
|
-
Log === null || Log === void 0 ? void 0 : Log.debug('[ReactNativeBleTransport] Protocol V2 high-volume write
|
|
1562
|
+
Log === null || Log === void 0 ? void 0 : Log.debug('[ReactNativeBleTransport] Protocol V2 high-volume write configured', {
|
|
1563
|
+
name,
|
|
1564
|
+
writeMode: 'withoutResponse',
|
|
1568
1565
|
packetCapacity: reactNative.Platform.OS === 'ios' ? tuning.iosPacketLength : tuning.androidPacketLength,
|
|
1569
|
-
burstSize: tuning.highVolumeWriteBurstSize,
|
|
1570
|
-
pauseMs: tuning.highVolumeWritePauseMs,
|
|
1571
|
-
flushDelayMs: tuning.highVolumeWriteFlushDelayMs,
|
|
1572
|
-
writeWithResponse: tuning.highVolumeWriteWithResponse,
|
|
1573
1566
|
});
|
|
1574
1567
|
}
|
|
1575
1568
|
try {
|
|
1576
|
-
|
|
1577
|
-
schemas: {
|
|
1578
|
-
protocolV1: this._messages,
|
|
1579
|
-
protocolV2: this._messagesV2,
|
|
1580
|
-
},
|
|
1581
|
-
router: transport.PROTOCOL_V2_CHANNEL_BLE_UART,
|
|
1582
|
-
writeFrame: (frame) => __awaiter(this, void 0, void 0, function* () {
|
|
1583
|
-
yield this.writeProtocolV2Frame(transport$1, frame, {
|
|
1584
|
-
highVolume: highVolumeWrite,
|
|
1585
|
-
});
|
|
1586
|
-
}),
|
|
1587
|
-
readFrame: () => __awaiter(this, void 0, void 0, function* () {
|
|
1588
|
-
const rxFrame = yield this.readProtocolV2Frame(uuid);
|
|
1589
|
-
if (!(rxFrame instanceof Uint8Array)) {
|
|
1590
|
-
throw new Error('Protocol V2 response is not Uint8Array');
|
|
1591
|
-
}
|
|
1592
|
-
return rxFrame;
|
|
1593
|
-
}),
|
|
1594
|
-
logger: Log,
|
|
1595
|
-
logPrefix: 'ProtocolV2 RN-BLE',
|
|
1596
|
-
createTimeoutError: (_messageName, timeout) => hdShared.ERRORS.TypedError(hdShared.HardwareErrorCode.BleTimeoutError, `BLE response timeout after ${timeout}ms for ${name}`),
|
|
1597
|
-
});
|
|
1598
|
-
const result = yield session.call(name, data, callOptions);
|
|
1599
|
-
completed = true;
|
|
1600
|
-
return result;
|
|
1569
|
+
return yield this.protocolV2Links.call(uuid, () => this.createProtocolV2Adapter(uuid), name, data, callOptions);
|
|
1601
1570
|
}
|
|
1602
1571
|
catch (e) {
|
|
1603
|
-
if (this.isActiveProtocolV2Call(uuid, callToken)) {
|
|
1604
|
-
(_c = this.protocolV2Assemblers.get(uuid)) === null || _c === void 0 ? void 0 : _c.reset();
|
|
1605
|
-
this.resetProtocolV2Frames(uuid);
|
|
1606
|
-
}
|
|
1607
1572
|
Log === null || Log === void 0 ? void 0 : Log.error('[ReactNativeBleTransport] Protocol V2 call error:', e);
|
|
1608
1573
|
throw e;
|
|
1609
1574
|
}
|
|
1610
|
-
finally {
|
|
1611
|
-
if (this.isActiveProtocolV2Call(uuid, callToken)) {
|
|
1612
|
-
if (!completed) {
|
|
1613
|
-
(_d = this.protocolV2Assemblers.get(uuid)) === null || _d === void 0 ? void 0 : _d.reset();
|
|
1614
|
-
}
|
|
1615
|
-
this.resetProtocolV2Frames(uuid);
|
|
1616
|
-
this.activeProtocolV2Call = null;
|
|
1617
|
-
}
|
|
1618
|
-
if (this.runPromise === runPromise) {
|
|
1619
|
-
this.runPromise = null;
|
|
1620
|
-
}
|
|
1621
|
-
}
|
|
1622
1575
|
});
|
|
1623
1576
|
}
|
|
1577
|
+
createProtocolV2Adapter(uuid) {
|
|
1578
|
+
var _a;
|
|
1579
|
+
const generation = (_a = this.monitorTokens.get(uuid)) !== null && _a !== void 0 ? _a : 0;
|
|
1580
|
+
const assertCurrentGeneration = () => {
|
|
1581
|
+
if (this.monitorTokens.get(uuid) !== generation) {
|
|
1582
|
+
throw new Error(`Protocol V2 monitor generation changed for ${uuid}`);
|
|
1583
|
+
}
|
|
1584
|
+
};
|
|
1585
|
+
return {
|
|
1586
|
+
router: transport.PROTOCOL_V2_CHANNEL_BLE_UART,
|
|
1587
|
+
maxFrameBytes: transport.PROTOCOL_V2_BLE_FRAME_MAX_BYTES,
|
|
1588
|
+
generation,
|
|
1589
|
+
prepareCall: () => {
|
|
1590
|
+
var _a;
|
|
1591
|
+
assertCurrentGeneration();
|
|
1592
|
+
(_a = this.protocolV2Assemblers.get(uuid)) === null || _a === void 0 ? void 0 : _a.reset();
|
|
1593
|
+
this.resetProtocolV2Frames(uuid);
|
|
1594
|
+
},
|
|
1595
|
+
writeFrame: (frame, context) => __awaiter(this, void 0, void 0, function* () {
|
|
1596
|
+
assertCurrentGeneration();
|
|
1597
|
+
const currentTransport = this.getCachedTransport(uuid);
|
|
1598
|
+
yield this.writeProtocolV2Frame(currentTransport, frame, context, assertCurrentGeneration);
|
|
1599
|
+
}),
|
|
1600
|
+
readFrame: () => __awaiter(this, void 0, void 0, function* () {
|
|
1601
|
+
assertCurrentGeneration();
|
|
1602
|
+
const rxFrame = yield this.readProtocolV2Frame(uuid);
|
|
1603
|
+
if (!(rxFrame instanceof Uint8Array)) {
|
|
1604
|
+
throw new Error('Protocol V2 response is not Uint8Array');
|
|
1605
|
+
}
|
|
1606
|
+
return rxFrame;
|
|
1607
|
+
}),
|
|
1608
|
+
reset: (reason) => {
|
|
1609
|
+
var _a;
|
|
1610
|
+
(_a = this.protocolV2Assemblers.get(uuid)) === null || _a === void 0 ? void 0 : _a.reset();
|
|
1611
|
+
this.rejectProtocolV2Frames(uuid, new Error(reason));
|
|
1612
|
+
},
|
|
1613
|
+
logger: Log,
|
|
1614
|
+
logPrefix: 'ProtocolV2 RN-BLE',
|
|
1615
|
+
createTimeoutError: (messageName, timeout) => hdShared.ERRORS.TypedError(hdShared.HardwareErrorCode.BleTimeoutError, `BLE response timeout after ${timeout}ms for ${messageName}`),
|
|
1616
|
+
};
|
|
1617
|
+
}
|
|
1624
1618
|
getProtocolType(path) {
|
|
1625
1619
|
return this.deviceProtocol.get(path);
|
|
1626
1620
|
}
|
|
@@ -1628,5 +1622,6 @@ class ReactNativeBleTransport {
|
|
|
1628
1622
|
|
|
1629
1623
|
exports.configureProtocolV2BleTuning = configureProtocolV2BleTuning;
|
|
1630
1624
|
exports["default"] = ReactNativeBleTransport;
|
|
1625
|
+
exports.getFirmwareUploadWriteRetryType = getFirmwareUploadWriteRetryType;
|
|
1631
1626
|
exports.getProtocolV2BleTuning = getProtocolV2BleTuning;
|
|
1632
1627
|
exports.resetProtocolV2BleTuning = resetProtocolV2BleTuning;
|