@onekeyfe/hd-transport-react-native 1.1.26 → 1.1.27-alpha.31
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/BleManager.d.ts.map +1 -1
- package/dist/BleTransport.d.ts +2 -0
- package/dist/BleTransport.d.ts.map +1 -1
- package/dist/constants.d.ts +3 -0
- package/dist/constants.d.ts.map +1 -1
- package/dist/index.d.ts +47 -5
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +574 -66
- package/dist/logger.d.ts +14 -0
- package/dist/logger.d.ts.map +1 -0
- package/dist/types.d.ts +2 -0
- package/dist/types.d.ts.map +1 -1
- package/package.json +5 -5
- package/src/BleManager.ts +3 -2
- package/src/BleTransport.ts +8 -3
- package/src/constants.ts +24 -1
- package/src/index.ts +679 -55
- package/src/logger.ts +19 -0
- package/src/types.ts +3 -0
- package/src/utils/validateNotify.ts +4 -4
package/dist/index.js
CHANGED
|
@@ -1,12 +1,13 @@
|
|
|
1
1
|
'use strict';
|
|
2
2
|
|
|
3
|
+
Object.defineProperty(exports, '__esModule', { value: true });
|
|
4
|
+
|
|
3
5
|
var reactNative = require('react-native');
|
|
4
6
|
var buffer = require('buffer');
|
|
5
7
|
var reactNativeBlePlx = require('react-native-ble-plx');
|
|
6
8
|
var ByteBuffer = require('bytebuffer');
|
|
7
9
|
var transport = require('@onekeyfe/hd-transport');
|
|
8
10
|
var hdShared = require('@onekeyfe/hd-shared');
|
|
9
|
-
var hdCore = require('@onekeyfe/hd-core');
|
|
10
11
|
var BleUtils = require('@onekeyfe/react-native-ble-utils');
|
|
11
12
|
|
|
12
13
|
function _interopDefaultLegacy (e) { return e && typeof e === 'object' && 'default' in e ? e : { 'default': e }; }
|
|
@@ -45,7 +46,17 @@ typeof SuppressedError === "function" ? SuppressedError : function (error, suppr
|
|
|
45
46
|
return e.name = "SuppressedError", e.error = error, e.suppressed = suppressed, e;
|
|
46
47
|
};
|
|
47
48
|
|
|
48
|
-
|
|
49
|
+
let activeLogger;
|
|
50
|
+
const setBleLogger = (logger) => {
|
|
51
|
+
activeLogger = logger;
|
|
52
|
+
};
|
|
53
|
+
const bleLogger = {
|
|
54
|
+
debug: (...args) => { var _a; return (_a = activeLogger === null || activeLogger === void 0 ? void 0 : activeLogger.debug) === null || _a === void 0 ? void 0 : _a.call(activeLogger, ...args); },
|
|
55
|
+
error: (...args) => { var _a; return (_a = activeLogger === null || activeLogger === void 0 ? void 0 : activeLogger.error) === null || _a === void 0 ? void 0 : _a.call(activeLogger, ...args); },
|
|
56
|
+
warn: (...args) => { var _a; return (_a = activeLogger === null || activeLogger === void 0 ? void 0 : activeLogger.warn) === null || _a === void 0 ? void 0 : _a.call(activeLogger, ...args); },
|
|
57
|
+
};
|
|
58
|
+
|
|
59
|
+
const Logger = bleLogger;
|
|
49
60
|
const getConnectedDeviceIds = (serviceUuids) => BleUtils__default["default"].getConnectedPeripherals(serviceUuids);
|
|
50
61
|
const pairDevice = (macAddress) => BleUtils__default["default"].pairDevice(macAddress);
|
|
51
62
|
const onDeviceBondState = (bleMacAddress) => new Promise((resolve, reject) => {
|
|
@@ -145,30 +156,43 @@ for (const deviceType of Object.keys(OneKeyServices)) {
|
|
|
145
156
|
}
|
|
146
157
|
const getBluetoothServiceUuids = () => bluetoothServices;
|
|
147
158
|
const getInfosForServiceUuid = (serviceUuid, deviceType) => {
|
|
159
|
+
var _a;
|
|
148
160
|
const services = OneKeyServices[deviceType];
|
|
149
161
|
if (!services) {
|
|
150
162
|
return null;
|
|
151
163
|
}
|
|
152
|
-
const
|
|
164
|
+
const normalizedServiceUuid = normalizeBleUuid(serviceUuid);
|
|
165
|
+
const service = (_a = services[serviceUuid]) !== null && _a !== void 0 ? _a : Object.values(services).find(item => normalizeBleUuid(item.serviceUuid) === normalizedServiceUuid);
|
|
153
166
|
if (!service) {
|
|
154
167
|
return null;
|
|
155
168
|
}
|
|
156
169
|
return service;
|
|
157
170
|
};
|
|
171
|
+
const normalizeBleUuid = (uuid) => (uuid !== null && uuid !== void 0 ? uuid : '').replace(/-/g, '').toLowerCase();
|
|
172
|
+
const getBleUuidKey = (uuid) => {
|
|
173
|
+
const normalized = normalizeBleUuid(uuid);
|
|
174
|
+
return normalized.length >= 8 ? normalized.substring(4, 8) : normalized;
|
|
175
|
+
};
|
|
176
|
+
const isSameBleUuid = (left, right) => {
|
|
177
|
+
const normalizedLeft = normalizeBleUuid(left);
|
|
178
|
+
const normalizedRight = normalizeBleUuid(right);
|
|
179
|
+
return (normalizedLeft === normalizedRight ||
|
|
180
|
+
(getBleUuidKey(left) !== '' && getBleUuidKey(left) === getBleUuidKey(right)));
|
|
181
|
+
};
|
|
158
182
|
|
|
159
183
|
const isHeaderChunk = (chunk) => {
|
|
160
184
|
if (chunk.length < 9)
|
|
161
185
|
return false;
|
|
162
186
|
const [MagicQuestionMark, sharp1, sharp2] = chunk;
|
|
163
|
-
if (String.fromCharCode(MagicQuestionMark) === String.fromCharCode(transport.
|
|
164
|
-
String.fromCharCode(sharp1) === String.fromCharCode(transport.
|
|
165
|
-
String.fromCharCode(sharp2) === String.fromCharCode(transport.
|
|
187
|
+
if (String.fromCharCode(MagicQuestionMark) === String.fromCharCode(transport.PROTOCOL_V1_REPORT_ID) &&
|
|
188
|
+
String.fromCharCode(sharp1) === String.fromCharCode(transport.PROTOCOL_V1_HEADER_BYTE) &&
|
|
189
|
+
String.fromCharCode(sharp2) === String.fromCharCode(transport.PROTOCOL_V1_HEADER_BYTE)) {
|
|
166
190
|
return true;
|
|
167
191
|
}
|
|
168
192
|
return false;
|
|
169
193
|
};
|
|
170
194
|
|
|
171
|
-
const Log$1 =
|
|
195
|
+
const Log$1 = bleLogger;
|
|
172
196
|
class BleTransport {
|
|
173
197
|
constructor(device, writeCharacteristic, notifyCharacteristic) {
|
|
174
198
|
this.name = 'ReactNativeBleTransport';
|
|
@@ -187,7 +211,7 @@ class BleTransport {
|
|
|
187
211
|
catch (error) {
|
|
188
212
|
Log$1 === null || Log$1 === void 0 ? void 0 : Log$1.debug(`Write retry attempt ${BleTransport.MAX_RETRIES - retryCount + 1}, error: ${error}`);
|
|
189
213
|
if (retryCount > 0) {
|
|
190
|
-
yield
|
|
214
|
+
yield hdShared.wait(BleTransport.RETRY_DELAY);
|
|
191
215
|
if (error.errorCode === reactNativeBlePlx.BleErrorCode.DeviceDisconnected ||
|
|
192
216
|
error.errorCode === reactNativeBlePlx.BleErrorCode.CharacteristicNotFound) {
|
|
193
217
|
try {
|
|
@@ -211,9 +235,67 @@ class BleTransport {
|
|
|
211
235
|
BleTransport.MAX_RETRIES = 5;
|
|
212
236
|
BleTransport.RETRY_DELAY = 2000;
|
|
213
237
|
|
|
214
|
-
const { check,
|
|
215
|
-
const Log =
|
|
238
|
+
const { check, ProtocolV1, parseConfigure } = transport__default["default"];
|
|
239
|
+
const Log = bleLogger;
|
|
216
240
|
const transportCache = {};
|
|
241
|
+
const BLE_RESPONSE_TIMEOUT_MS = 30000;
|
|
242
|
+
const PROTOCOL_PROBE_TIMEOUT_MS = 1000;
|
|
243
|
+
const PROTOCOL_V2_PROBE_TIMEOUT_MS = 5000;
|
|
244
|
+
const DEVICE_SCAN_TIMEOUT_MS = 8000;
|
|
245
|
+
const IOS_NOTIFY_READY_DELAY_MS = 150;
|
|
246
|
+
const HIGH_VOLUME_WRITE_BURST_SIZE = reactNative.Platform.OS === 'ios' ? 4 : 6;
|
|
247
|
+
const HIGH_VOLUME_WRITE_PAUSE_MS = reactNative.Platform.OS === 'ios' ? 6 : 2;
|
|
248
|
+
const HIGH_VOLUME_WRITE_FLUSH_DELAY_MS = reactNative.Platform.OS === 'ios' ? 20 : 8;
|
|
249
|
+
const delay = (ms) => new Promise(resolve => {
|
|
250
|
+
setTimeout(resolve, ms);
|
|
251
|
+
});
|
|
252
|
+
const DEFAULT_PROTOCOL_V2_BLE_TUNING = {
|
|
253
|
+
iosPacketLength: IOS_PACKET_LENGTH,
|
|
254
|
+
androidPacketLength: ANDROID_PACKET_LENGTH,
|
|
255
|
+
highVolumeWriteBurstSize: HIGH_VOLUME_WRITE_BURST_SIZE,
|
|
256
|
+
highVolumeWritePauseMs: HIGH_VOLUME_WRITE_PAUSE_MS,
|
|
257
|
+
highVolumeWriteFlushDelayMs: HIGH_VOLUME_WRITE_FLUSH_DELAY_MS,
|
|
258
|
+
highVolumeWriteWithResponse: false,
|
|
259
|
+
};
|
|
260
|
+
let protocolV2BleTuning = Object.assign({}, DEFAULT_PROTOCOL_V2_BLE_TUNING);
|
|
261
|
+
const normalizePositiveInteger = (value, fallback) => {
|
|
262
|
+
const normalized = Number(value);
|
|
263
|
+
if (!Number.isFinite(normalized) || normalized <= 0)
|
|
264
|
+
return fallback;
|
|
265
|
+
return Math.floor(normalized);
|
|
266
|
+
};
|
|
267
|
+
function configureProtocolV2BleTuning(tuning = {}) {
|
|
268
|
+
var _a;
|
|
269
|
+
protocolV2BleTuning = {
|
|
270
|
+
iosPacketLength: normalizePositiveInteger(tuning.iosPacketLength, protocolV2BleTuning.iosPacketLength),
|
|
271
|
+
androidPacketLength: normalizePositiveInteger(tuning.androidPacketLength, protocolV2BleTuning.androidPacketLength),
|
|
272
|
+
highVolumeWriteBurstSize: normalizePositiveInteger(tuning.highVolumeWriteBurstSize, protocolV2BleTuning.highVolumeWriteBurstSize),
|
|
273
|
+
highVolumeWritePauseMs: normalizePositiveInteger(tuning.highVolumeWritePauseMs, protocolV2BleTuning.highVolumeWritePauseMs),
|
|
274
|
+
highVolumeWriteFlushDelayMs: normalizePositiveInteger(tuning.highVolumeWriteFlushDelayMs, protocolV2BleTuning.highVolumeWriteFlushDelayMs),
|
|
275
|
+
highVolumeWriteWithResponse: (_a = tuning.highVolumeWriteWithResponse) !== null && _a !== void 0 ? _a : protocolV2BleTuning.highVolumeWriteWithResponse,
|
|
276
|
+
};
|
|
277
|
+
Log === null || Log === void 0 ? void 0 : Log.debug('[ReactNativeBleTransport] Protocol V2 BLE tuning configured:', protocolV2BleTuning);
|
|
278
|
+
}
|
|
279
|
+
function resetProtocolV2BleTuning() {
|
|
280
|
+
protocolV2BleTuning = Object.assign({}, DEFAULT_PROTOCOL_V2_BLE_TUNING);
|
|
281
|
+
Log === null || Log === void 0 ? void 0 : Log.debug('[ReactNativeBleTransport] Protocol V2 BLE tuning reset:', protocolV2BleTuning);
|
|
282
|
+
}
|
|
283
|
+
function getProtocolV2BleTuning() {
|
|
284
|
+
return Object.assign({}, protocolV2BleTuning);
|
|
285
|
+
}
|
|
286
|
+
function inferProtocolTypeFromDeviceName(name) {
|
|
287
|
+
return /\bpro\s*2\b/i.test(name !== null && name !== void 0 ? name : '') ? 'V2' : undefined;
|
|
288
|
+
}
|
|
289
|
+
function getDeviceDisplayName(device) {
|
|
290
|
+
return (device === null || device === void 0 ? void 0 : device.name) || (device === null || device === void 0 ? void 0 : device.localName) || null;
|
|
291
|
+
}
|
|
292
|
+
function isGenericBleService(uuid) {
|
|
293
|
+
return ['1800', '1801', '180a'].includes(getBleUuidKey(uuid));
|
|
294
|
+
}
|
|
295
|
+
function hasKnownOneKeyService(device) {
|
|
296
|
+
var _a;
|
|
297
|
+
return ((_a = device === null || device === void 0 ? void 0 : device.serviceUUIDs) !== null && _a !== void 0 ? _a : []).some(serviceUuid => getInfosForServiceUuid(serviceUuid, 'classic'));
|
|
298
|
+
}
|
|
217
299
|
let connectOptions = {
|
|
218
300
|
requestMTU: 256,
|
|
219
301
|
timeout: 3000,
|
|
@@ -222,7 +304,9 @@ let connectOptions = {
|
|
|
222
304
|
const tryToGetConfiguration = (device) => {
|
|
223
305
|
if (!device || !device.serviceUUIDs)
|
|
224
306
|
return null;
|
|
225
|
-
const
|
|
307
|
+
const serviceUUID = device.serviceUUIDs.find(uuid => getInfosForServiceUuid(uuid, 'classic'));
|
|
308
|
+
if (!serviceUUID)
|
|
309
|
+
return null;
|
|
226
310
|
const infos = getInfosForServiceUuid(serviceUUID, 'classic');
|
|
227
311
|
if (!infos)
|
|
228
312
|
return null;
|
|
@@ -252,11 +336,18 @@ class ReactNativeBleTransport {
|
|
|
252
336
|
this.name = 'ReactNativeBleTransport';
|
|
253
337
|
this.configured = false;
|
|
254
338
|
this.stopped = false;
|
|
255
|
-
this.scanTimeout =
|
|
339
|
+
this.scanTimeout = DEVICE_SCAN_TIMEOUT_MS;
|
|
256
340
|
this.runPromise = null;
|
|
257
|
-
this.
|
|
341
|
+
this.deviceProtocol = new Map();
|
|
342
|
+
this.protocolV2Assemblers = new Map();
|
|
343
|
+
this.protocolV2FrameQueue = [];
|
|
344
|
+
this.protocolV2FramePromise = null;
|
|
345
|
+
this.monitorTokens = new Map();
|
|
346
|
+
this.nextMonitorToken = 1;
|
|
347
|
+
this.scanTimeout = (_a = options.scanTimeout) !== null && _a !== void 0 ? _a : DEVICE_SCAN_TIMEOUT_MS;
|
|
258
348
|
}
|
|
259
|
-
init(
|
|
349
|
+
init(logger, emitter) {
|
|
350
|
+
setBleLogger(logger);
|
|
260
351
|
this.emitter = emitter;
|
|
261
352
|
}
|
|
262
353
|
configure(signedData) {
|
|
@@ -264,6 +355,10 @@ class ReactNativeBleTransport {
|
|
|
264
355
|
this.configured = true;
|
|
265
356
|
this._messages = messages;
|
|
266
357
|
}
|
|
358
|
+
configureProtocolV2(signedData) {
|
|
359
|
+
this._messagesV2 = parseConfigure(signedData);
|
|
360
|
+
Log === null || Log === void 0 ? void 0 : Log.debug('[ReactNativeBleTransport] Protocol V2 schema configured');
|
|
361
|
+
}
|
|
267
362
|
listen() {
|
|
268
363
|
}
|
|
269
364
|
getPlxManager() {
|
|
@@ -299,9 +394,10 @@ class ReactNativeBleTransport {
|
|
|
299
394
|
}
|
|
300
395
|
}
|
|
301
396
|
blePlxManager.startDeviceScan(null, {
|
|
397
|
+
allowDuplicates: true,
|
|
302
398
|
scanMode: reactNativeBlePlx.ScanMode.LowLatency,
|
|
303
399
|
}, (error, device) => {
|
|
304
|
-
var _a, _b;
|
|
400
|
+
var _a, _b, _c;
|
|
305
401
|
if (error) {
|
|
306
402
|
Log === null || Log === void 0 ? void 0 : Log.debug('ble scan manager: ', blePlxManager);
|
|
307
403
|
Log === null || Log === void 0 ? void 0 : Log.debug('ble scan error: ', error);
|
|
@@ -322,13 +418,35 @@ class ReactNativeBleTransport {
|
|
|
322
418
|
}
|
|
323
419
|
return;
|
|
324
420
|
}
|
|
325
|
-
|
|
421
|
+
const displayName = getDeviceDisplayName(device);
|
|
422
|
+
const isOneKey = hdShared.isOnekeyDevice((_b = device === null || device === void 0 ? void 0 : device.name) !== null && _b !== void 0 ? _b : null, device === null || device === void 0 ? void 0 : device.id) ||
|
|
423
|
+
hdShared.isOnekeyDevice((_c = device === null || device === void 0 ? void 0 : device.localName) !== null && _c !== void 0 ? _c : null, device === null || device === void 0 ? void 0 : device.id) ||
|
|
424
|
+
hasKnownOneKeyService(device);
|
|
425
|
+
const shouldTraceCandidate = !!displayName && /onekey|bixinkey|pro\s*2|pro\b|touch|^k\d|^t\d/i.test(displayName);
|
|
426
|
+
if (shouldTraceCandidate) {
|
|
427
|
+
Log === null || Log === void 0 ? void 0 : Log.debug('[ReactNativeBleTransport] scan candidate', {
|
|
428
|
+
name: device === null || device === void 0 ? void 0 : device.name,
|
|
429
|
+
localName: device === null || device === void 0 ? void 0 : device.localName,
|
|
430
|
+
id: device === null || device === void 0 ? void 0 : device.id,
|
|
431
|
+
serviceUUIDs: device === null || device === void 0 ? void 0 : device.serviceUUIDs,
|
|
432
|
+
accepted: isOneKey,
|
|
433
|
+
});
|
|
434
|
+
}
|
|
435
|
+
if (isOneKey) {
|
|
326
436
|
Log === null || Log === void 0 ? void 0 : Log.debug('search device start ======================');
|
|
327
|
-
const { name, localName, id } = device !== null && device !== void 0 ? device : {};
|
|
328
|
-
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 : ''}`);
|
|
437
|
+
const { name, localName, id, serviceUUIDs } = device !== null && device !== void 0 ? device : {};
|
|
438
|
+
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(',')}`);
|
|
329
439
|
addDevice(device);
|
|
330
440
|
Log === null || Log === void 0 ? void 0 : Log.debug('search device end ======================\n');
|
|
331
441
|
}
|
|
442
|
+
else if (displayName && /\bpro\s*2\b/i.test(displayName)) {
|
|
443
|
+
Log === null || Log === void 0 ? void 0 : Log.debug('[ReactNativeBleTransport] Pro2-like BLE device was not accepted:', {
|
|
444
|
+
name: device === null || device === void 0 ? void 0 : device.name,
|
|
445
|
+
localName: device === null || device === void 0 ? void 0 : device.localName,
|
|
446
|
+
id: device === null || device === void 0 ? void 0 : device.id,
|
|
447
|
+
serviceUUIDs: device === null || device === void 0 ? void 0 : device.serviceUUIDs,
|
|
448
|
+
});
|
|
449
|
+
}
|
|
332
450
|
});
|
|
333
451
|
getConnectedDeviceIds(getBluetoothServiceUuids()).then(devices => {
|
|
334
452
|
for (const device of devices) {
|
|
@@ -337,8 +455,11 @@ class ReactNativeBleTransport {
|
|
|
337
455
|
}
|
|
338
456
|
});
|
|
339
457
|
const addDevice = (device) => {
|
|
458
|
+
var _a;
|
|
340
459
|
if (deviceList.every(d => d.id !== device.id)) {
|
|
341
|
-
|
|
460
|
+
const displayName = (_a = getDeviceDisplayName(device)) !== null && _a !== void 0 ? _a : 'Unknown BLE Device';
|
|
461
|
+
const protocolType = inferProtocolTypeFromDeviceName(displayName);
|
|
462
|
+
deviceList.push(Object.assign(Object.assign(Object.assign({}, device), { name: displayName, commType: 'ble' }), (protocolType ? { protocolType } : {})));
|
|
342
463
|
}
|
|
343
464
|
};
|
|
344
465
|
timer.timeout(() => {
|
|
@@ -349,9 +470,9 @@ class ReactNativeBleTransport {
|
|
|
349
470
|
});
|
|
350
471
|
}
|
|
351
472
|
acquire(input) {
|
|
352
|
-
var _a;
|
|
473
|
+
var _a, _b, _c, _d, _e;
|
|
353
474
|
return __awaiter(this, void 0, void 0, function* () {
|
|
354
|
-
const { uuid, forceCleanRunPromise } = input;
|
|
475
|
+
const { uuid, forceCleanRunPromise, expectedProtocol } = input;
|
|
355
476
|
if (!uuid) {
|
|
356
477
|
throw hdShared.ERRORS.TypedError(hdShared.HardwareErrorCode.BleRequiredUUID);
|
|
357
478
|
}
|
|
@@ -361,7 +482,10 @@ class ReactNativeBleTransport {
|
|
|
361
482
|
yield this.release(uuid);
|
|
362
483
|
}
|
|
363
484
|
if (forceCleanRunPromise && this.runPromise) {
|
|
364
|
-
|
|
485
|
+
const error = hdShared.ERRORS.TypedError(hdShared.HardwareErrorCode.BleForceCleanRunPromise);
|
|
486
|
+
this.runPromise.reject(error);
|
|
487
|
+
this.rejectProtocolV2Frame(error);
|
|
488
|
+
this.runPromise = null;
|
|
365
489
|
Log === null || Log === void 0 ? void 0 : Log.debug('Force clean Bluetooth run promise, forceCleanRunPromise: ', forceCleanRunPromise);
|
|
366
490
|
}
|
|
367
491
|
const blePlxManager = yield this.getPlxManager();
|
|
@@ -416,7 +540,7 @@ class ReactNativeBleTransport {
|
|
|
416
540
|
if (!(yield device.isConnected())) {
|
|
417
541
|
Log === null || Log === void 0 ? void 0 : Log.debug('not connected, try to connect to device: ', uuid);
|
|
418
542
|
try {
|
|
419
|
-
yield device.connect(connectOptions);
|
|
543
|
+
device = yield device.connect(connectOptions);
|
|
420
544
|
}
|
|
421
545
|
catch (e) {
|
|
422
546
|
Log === null || Log === void 0 ? void 0 : Log.debug('not connected, try to connect to device has error: ', e);
|
|
@@ -425,14 +549,14 @@ class ReactNativeBleTransport {
|
|
|
425
549
|
connectOptions = {};
|
|
426
550
|
Log === null || Log === void 0 ? void 0 : Log.debug('second try to reconnect without params');
|
|
427
551
|
try {
|
|
428
|
-
yield device.connect();
|
|
552
|
+
device = yield device.connect();
|
|
429
553
|
}
|
|
430
554
|
catch (e) {
|
|
431
555
|
Log === null || Log === void 0 ? void 0 : Log.debug('last try to reconnect error: ', e);
|
|
432
556
|
if (e.errorCode === reactNativeBlePlx.BleErrorCode.OperationCancelled) {
|
|
433
557
|
Log === null || Log === void 0 ? void 0 : Log.debug('last try to reconnect');
|
|
434
558
|
yield device.cancelConnection();
|
|
435
|
-
yield device.connect();
|
|
559
|
+
device = yield device.connect();
|
|
436
560
|
}
|
|
437
561
|
}
|
|
438
562
|
}
|
|
@@ -444,6 +568,7 @@ class ReactNativeBleTransport {
|
|
|
444
568
|
yield device.discoverAllServicesAndCharacteristics();
|
|
445
569
|
let infos = tryToGetConfiguration(device);
|
|
446
570
|
let characteristics;
|
|
571
|
+
let fallbackServiceUuid;
|
|
447
572
|
if (!infos) {
|
|
448
573
|
for (const serviceUuid of getBluetoothServiceUuids()) {
|
|
449
574
|
try {
|
|
@@ -457,16 +582,34 @@ class ReactNativeBleTransport {
|
|
|
457
582
|
}
|
|
458
583
|
}
|
|
459
584
|
if (!infos) {
|
|
460
|
-
|
|
461
|
-
|
|
462
|
-
|
|
585
|
+
const services = yield device.services();
|
|
586
|
+
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));
|
|
587
|
+
const knownService = services.find(service => getInfosForServiceUuid(service.uuid, 'classic'));
|
|
588
|
+
const fallbackService = (_a = knownService !== null && knownService !== void 0 ? knownService : services.find(service => !isGenericBleService(service.uuid))) !== null && _a !== void 0 ? _a : services[0];
|
|
589
|
+
if (fallbackService) {
|
|
590
|
+
fallbackServiceUuid = fallbackService.uuid;
|
|
591
|
+
characteristics = yield device.characteristicsForService(fallbackService.uuid);
|
|
592
|
+
Log === null || Log === void 0 ? void 0 : Log.debug('[ReactNativeBleTransport] Using fallback BLE service:', fallbackService.uuid);
|
|
463
593
|
}
|
|
464
|
-
|
|
465
|
-
|
|
594
|
+
}
|
|
595
|
+
if (!infos) {
|
|
596
|
+
if (!fallbackServiceUuid) {
|
|
597
|
+
try {
|
|
598
|
+
Log === null || Log === void 0 ? void 0 : Log.debug('cancel connection when service not found');
|
|
599
|
+
yield device.cancelConnection();
|
|
600
|
+
}
|
|
601
|
+
catch (e) {
|
|
602
|
+
Log === null || Log === void 0 ? void 0 : Log.debug('cancel connection error when service not found: ', e.message || e.reason);
|
|
603
|
+
}
|
|
604
|
+
throw hdShared.ERRORS.TypedError(hdShared.HardwareErrorCode.BleServiceNotFound);
|
|
466
605
|
}
|
|
606
|
+
}
|
|
607
|
+
const serviceUuid = (_b = infos === null || infos === void 0 ? void 0 : infos.serviceUuid) !== null && _b !== void 0 ? _b : fallbackServiceUuid;
|
|
608
|
+
const writeUuid = (_c = infos === null || infos === void 0 ? void 0 : infos.writeUuid) !== null && _c !== void 0 ? _c : '00000002-0000-1000-8000-00805f9b34fb';
|
|
609
|
+
const notifyUuid = (_d = infos === null || infos === void 0 ? void 0 : infos.notifyUuid) !== null && _d !== void 0 ? _d : '00000003-0000-1000-8000-00805f9b34fb';
|
|
610
|
+
if (!serviceUuid) {
|
|
467
611
|
throw hdShared.ERRORS.TypedError(hdShared.HardwareErrorCode.BleServiceNotFound);
|
|
468
612
|
}
|
|
469
|
-
const { serviceUuid, writeUuid, notifyUuid } = infos;
|
|
470
613
|
if (!characteristics) {
|
|
471
614
|
characteristics = yield device.characteristicsForService(serviceUuid);
|
|
472
615
|
}
|
|
@@ -476,10 +619,10 @@ class ReactNativeBleTransport {
|
|
|
476
619
|
let writeCharacteristic;
|
|
477
620
|
let notifyCharacteristic;
|
|
478
621
|
for (const c of characteristics) {
|
|
479
|
-
if (c.uuid
|
|
622
|
+
if (isSameBleUuid(c.uuid, writeUuid)) {
|
|
480
623
|
writeCharacteristic = c;
|
|
481
624
|
}
|
|
482
|
-
else if (c.uuid
|
|
625
|
+
else if (isSameBleUuid(c.uuid, notifyUuid)) {
|
|
483
626
|
notifyCharacteristic = c;
|
|
484
627
|
}
|
|
485
628
|
}
|
|
@@ -496,16 +639,33 @@ class ReactNativeBleTransport {
|
|
|
496
639
|
throw hdShared.ERRORS.TypedError('BLECharacteristicNotNotifiable: notify characteristic not notifiable');
|
|
497
640
|
}
|
|
498
641
|
yield this.release(uuid);
|
|
499
|
-
const transport = new BleTransport(device, writeCharacteristic, notifyCharacteristic);
|
|
500
|
-
|
|
501
|
-
|
|
502
|
-
|
|
642
|
+
const transport$1 = new BleTransport(device, writeCharacteristic, notifyCharacteristic);
|
|
643
|
+
const monitorToken = this.nextMonitorToken;
|
|
644
|
+
this.nextMonitorToken += 1;
|
|
645
|
+
const notifyTransactionId = `${uuid}:notify:${monitorToken}`;
|
|
646
|
+
transport$1.monitorToken = monitorToken;
|
|
647
|
+
transport$1.notifyTransactionId = notifyTransactionId;
|
|
648
|
+
this.monitorTokens.set(uuid, monitorToken);
|
|
649
|
+
transport$1.notifySubscription = this._monitorCharacteristic(transport$1.notifyCharacteristic, uuid, monitorToken, notifyTransactionId);
|
|
650
|
+
transportCache[uuid] = transport$1;
|
|
651
|
+
this.protocolV2Assemblers.set(uuid, new transport.ProtocolV2FrameAssembler());
|
|
652
|
+
if (reactNative.Platform.OS === 'ios') {
|
|
653
|
+
yield new Promise(resolve => {
|
|
654
|
+
setTimeout(resolve, IOS_NOTIFY_READY_DELAY_MS);
|
|
655
|
+
});
|
|
656
|
+
}
|
|
657
|
+
const protocolType = yield this.detectProtocol(uuid, expectedProtocol);
|
|
658
|
+
(_e = this.emitter) === null || _e === void 0 ? void 0 : _e.emit('device-connect', {
|
|
503
659
|
name: device.name,
|
|
504
660
|
id: device.id,
|
|
505
661
|
connectId: device.id,
|
|
506
662
|
});
|
|
507
|
-
transport.disconnectSubscription = device.onDisconnected(() => {
|
|
663
|
+
transport$1.disconnectSubscription = device.onDisconnected(() => {
|
|
508
664
|
var _a;
|
|
665
|
+
if (transportCache[uuid] !== transport$1) {
|
|
666
|
+
Log === null || Log === void 0 ? void 0 : Log.debug('device disconnect ignored for stale transport: ', device === null || device === void 0 ? void 0 : device.id);
|
|
667
|
+
return;
|
|
668
|
+
}
|
|
509
669
|
try {
|
|
510
670
|
Log === null || Log === void 0 ? void 0 : Log.debug('device disconnect: ', device === null || device === void 0 ? void 0 : device.id);
|
|
511
671
|
(_a = this.emitter) === null || _a === void 0 ? void 0 : _a.emit('device-disconnect', {
|
|
@@ -514,7 +674,9 @@ class ReactNativeBleTransport {
|
|
|
514
674
|
connectId: device === null || device === void 0 ? void 0 : device.id,
|
|
515
675
|
});
|
|
516
676
|
if (this.runPromise) {
|
|
517
|
-
|
|
677
|
+
const error = hdShared.ERRORS.TypedError(hdShared.HardwareErrorCode.BleConnectedError);
|
|
678
|
+
this.runPromise.reject(error);
|
|
679
|
+
this.rejectProtocolV2Frame(error);
|
|
518
680
|
}
|
|
519
681
|
}
|
|
520
682
|
catch (e) {
|
|
@@ -524,16 +686,21 @@ class ReactNativeBleTransport {
|
|
|
524
686
|
this.release(uuid);
|
|
525
687
|
}
|
|
526
688
|
});
|
|
527
|
-
return { uuid };
|
|
689
|
+
return { uuid, protocolType };
|
|
528
690
|
});
|
|
529
691
|
}
|
|
530
|
-
_monitorCharacteristic(characteristic, uuid) {
|
|
692
|
+
_monitorCharacteristic(characteristic, uuid, monitorToken, notifyTransactionId) {
|
|
531
693
|
let bufferLength = 0;
|
|
532
694
|
let buffer$1 = [];
|
|
533
695
|
const subscription = characteristic.monitor((error, c) => {
|
|
534
696
|
var _a, _b, _c, _d, _e, _f, _g, _h, _j;
|
|
697
|
+
const isCurrentMonitor = this.monitorTokens.get(uuid) === monitorToken;
|
|
535
698
|
if (error) {
|
|
536
699
|
Log === null || Log === void 0 ? void 0 : Log.debug(`error monitor ${characteristic.uuid}, deviceId: ${characteristic.deviceID}: ${error}`);
|
|
700
|
+
if (!isCurrentMonitor) {
|
|
701
|
+
Log === null || Log === void 0 ? void 0 : Log.debug('monitor error ignored for stale transport: ', uuid, notifyTransactionId);
|
|
702
|
+
return;
|
|
703
|
+
}
|
|
537
704
|
if (this.runPromise) {
|
|
538
705
|
let ERROR = hdShared.HardwareErrorCode.BleCharacteristicNotifyError;
|
|
539
706
|
if ((_a = error.reason) === null || _a === void 0 ? void 0 : _a.includes('The connection has timed out unexpectedly')) {
|
|
@@ -547,20 +714,32 @@ class ReactNativeBleTransport {
|
|
|
547
714
|
((_e = error.reason) === null || _e === void 0 ? void 0 : _e.includes('The handle is invalid')) ||
|
|
548
715
|
((_f = error.reason) === null || _f === void 0 ? void 0 : _f.includes('Writing is not permitted')) ||
|
|
549
716
|
((_g = error.reason) === null || _g === void 0 ? void 0 : _g.includes('notify change failed for device'))) {
|
|
550
|
-
|
|
717
|
+
const notifyError = hdShared.ERRORS.TypedError(hdShared.HardwareErrorCode.BleCharacteristicNotifyChangeFailure);
|
|
718
|
+
this.runPromise.reject(notifyError);
|
|
719
|
+
this.rejectProtocolV2Frame(notifyError);
|
|
551
720
|
Log === null || Log === void 0 ? void 0 : Log.debug(`${hdShared.HardwareErrorCode.BleCharacteristicNotifyChangeFailure} ${error.message} ${error.reason}`);
|
|
552
721
|
return;
|
|
553
722
|
}
|
|
554
|
-
|
|
723
|
+
const notifyError = hdShared.ERRORS.TypedError(ERROR);
|
|
724
|
+
this.runPromise.reject(notifyError);
|
|
725
|
+
this.rejectProtocolV2Frame(notifyError);
|
|
555
726
|
Log === null || Log === void 0 ? void 0 : Log.debug(': monitor notify error, and has unreleased Promise', Error);
|
|
556
727
|
}
|
|
557
728
|
return;
|
|
558
729
|
}
|
|
730
|
+
if (!isCurrentMonitor) {
|
|
731
|
+
Log === null || Log === void 0 ? void 0 : Log.debug('monitor data ignored for stale transport: ', uuid, notifyTransactionId);
|
|
732
|
+
return;
|
|
733
|
+
}
|
|
559
734
|
if (!c) {
|
|
560
735
|
throw hdShared.ERRORS.TypedError(hdShared.HardwareErrorCode.BleMonitorError);
|
|
561
736
|
}
|
|
562
737
|
try {
|
|
563
738
|
const data = buffer.Buffer.from(c.value, 'base64');
|
|
739
|
+
if (this.deviceProtocol.get(uuid) === 'V2') {
|
|
740
|
+
this.handleProtocolV2Notification(uuid, new Uint8Array(data));
|
|
741
|
+
return;
|
|
742
|
+
}
|
|
564
743
|
if (isHeaderChunk(data)) {
|
|
565
744
|
bufferLength = data.readInt32BE(5);
|
|
566
745
|
buffer$1 = [...data.subarray(3)];
|
|
@@ -568,7 +747,7 @@ class ReactNativeBleTransport {
|
|
|
568
747
|
else {
|
|
569
748
|
buffer$1 = buffer$1.concat([...data]);
|
|
570
749
|
}
|
|
571
|
-
if (buffer$1.length - transport.
|
|
750
|
+
if (buffer$1.length - transport.PROTOCOL_V1_MESSAGE_HEADER_SIZE >= bufferLength) {
|
|
572
751
|
const value = buffer.Buffer.from(buffer$1);
|
|
573
752
|
bufferLength = 0;
|
|
574
753
|
buffer$1 = [];
|
|
@@ -577,24 +756,54 @@ class ReactNativeBleTransport {
|
|
|
577
756
|
}
|
|
578
757
|
catch (error) {
|
|
579
758
|
Log === null || Log === void 0 ? void 0 : Log.debug('monitor data error: ', error);
|
|
580
|
-
|
|
759
|
+
const notifyError = hdShared.ERRORS.TypedError(hdShared.HardwareErrorCode.BleWriteCharacteristicError);
|
|
760
|
+
(_j = this.runPromise) === null || _j === void 0 ? void 0 : _j.reject(notifyError);
|
|
761
|
+
this.rejectProtocolV2Frame(notifyError);
|
|
581
762
|
}
|
|
582
|
-
},
|
|
763
|
+
}, notifyTransactionId);
|
|
583
764
|
return subscription;
|
|
584
765
|
}
|
|
585
766
|
release(uuid) {
|
|
586
|
-
var _a, _b, _c;
|
|
767
|
+
var _a, _b, _c, _d, _e, _f;
|
|
587
768
|
return __awaiter(this, void 0, void 0, function* () {
|
|
588
769
|
const transport = transportCache[uuid];
|
|
770
|
+
if (this.runPromise) {
|
|
771
|
+
const error = hdShared.ERRORS.TypedError(hdShared.HardwareErrorCode.BleForceCleanRunPromise);
|
|
772
|
+
this.runPromise.reject(error);
|
|
773
|
+
this.runPromise = null;
|
|
774
|
+
this.rejectProtocolV2Frame(error);
|
|
775
|
+
}
|
|
776
|
+
else {
|
|
777
|
+
this.resetProtocolV2Frames();
|
|
778
|
+
}
|
|
589
779
|
if (transport) {
|
|
780
|
+
if (this.monitorTokens.get(uuid) === transport.monitorToken) {
|
|
781
|
+
this.monitorTokens.delete(uuid);
|
|
782
|
+
}
|
|
590
783
|
Log === null || Log === void 0 ? void 0 : Log.debug('release: removing disconnect subscription for device: ', uuid);
|
|
591
784
|
(_a = transport.disconnectSubscription) === null || _a === void 0 ? void 0 : _a.remove();
|
|
592
785
|
transport.disconnectSubscription = undefined;
|
|
593
786
|
Log === null || Log === void 0 ? void 0 : Log.debug('release: removing notify subscription, characteristic: ', (_b = transport.notifyCharacteristic) === null || _b === void 0 ? void 0 : _b.uuid);
|
|
594
787
|
(_c = transport.notifySubscription) === null || _c === void 0 ? void 0 : _c.remove();
|
|
595
788
|
transport.notifySubscription = undefined;
|
|
789
|
+
if (transport.notifyTransactionId) {
|
|
790
|
+
try {
|
|
791
|
+
yield ((_d = this.blePlxManager) === null || _d === void 0 ? void 0 : _d.cancelTransaction(transport.notifyTransactionId));
|
|
792
|
+
}
|
|
793
|
+
catch (e) {
|
|
794
|
+
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);
|
|
795
|
+
}
|
|
796
|
+
}
|
|
596
797
|
delete transportCache[uuid];
|
|
597
|
-
|
|
798
|
+
this.deviceProtocol.delete(uuid);
|
|
799
|
+
}
|
|
800
|
+
(_e = this.protocolV2Assemblers.get(uuid)) === null || _e === void 0 ? void 0 : _e.reset();
|
|
801
|
+
this.protocolV2Assemblers.delete(uuid);
|
|
802
|
+
try {
|
|
803
|
+
yield ((_f = this.blePlxManager) === null || _f === void 0 ? void 0 : _f.cancelTransaction(uuid));
|
|
804
|
+
}
|
|
805
|
+
catch (e) {
|
|
806
|
+
Log === null || Log === void 0 ? void 0 : Log.debug('release: cancel transaction error (ignored): ', (e === null || e === void 0 ? void 0 : e.message) || e);
|
|
598
807
|
}
|
|
599
808
|
return Promise.resolve(true);
|
|
600
809
|
});
|
|
@@ -604,7 +813,7 @@ class ReactNativeBleTransport {
|
|
|
604
813
|
yield this.call(session, name, data);
|
|
605
814
|
});
|
|
606
815
|
}
|
|
607
|
-
call(uuid, name, data) {
|
|
816
|
+
call(uuid, name, data, options) {
|
|
608
817
|
return __awaiter(this, void 0, void 0, function* () {
|
|
609
818
|
if (this.stopped) {
|
|
610
819
|
return Promise.reject(hdShared.ERRORS.TypedError('Transport stopped.'));
|
|
@@ -617,12 +826,7 @@ class ReactNativeBleTransport {
|
|
|
617
826
|
if (this.runPromise && !forceRun) {
|
|
618
827
|
throw hdShared.ERRORS.TypedError(hdShared.HardwareErrorCode.TransportCallInProgress);
|
|
619
828
|
}
|
|
620
|
-
const
|
|
621
|
-
if (!transport$1) {
|
|
622
|
-
throw hdShared.ERRORS.TypedError(hdShared.HardwareErrorCode.TransportNotFound);
|
|
623
|
-
}
|
|
624
|
-
this.runPromise = hdShared.createDeferred();
|
|
625
|
-
const messages = this._messages;
|
|
829
|
+
const protocol = this.getProtocolType(uuid);
|
|
626
830
|
if (name === 'ResourceUpdate' || name === 'ResourceAck') {
|
|
627
831
|
Log === null || Log === void 0 ? void 0 : Log.debug('transport-react-native', 'call-', ' name: ', name, ' data: ', {
|
|
628
832
|
file_name: data === null || data === void 0 ? void 0 : data.file_name,
|
|
@@ -630,12 +834,29 @@ class ReactNativeBleTransport {
|
|
|
630
834
|
});
|
|
631
835
|
}
|
|
632
836
|
else if (transport.LogBlockCommand.has(name)) {
|
|
633
|
-
Log === null || Log === void 0 ? void 0 : Log.debug('transport-react-native', 'call-', ' name: ', name);
|
|
837
|
+
Log === null || Log === void 0 ? void 0 : Log.debug('transport-react-native', 'call-', ' name: ', name, ' protocol: ', protocol);
|
|
634
838
|
}
|
|
635
839
|
else {
|
|
636
|
-
Log === null || Log === void 0 ? void 0 : Log.debug('transport-react-native', 'call-', ' name: ', name, ' data: ', data);
|
|
840
|
+
Log === null || Log === void 0 ? void 0 : Log.debug('transport-react-native', 'call-', ' name: ', name, ' data: ', data, ' protocol: ', protocol);
|
|
841
|
+
}
|
|
842
|
+
if (protocol === 'V2') {
|
|
843
|
+
return this.callProtocolV2(uuid, name, data, options);
|
|
637
844
|
}
|
|
638
|
-
|
|
845
|
+
return this.callProtocolV1(uuid, name, data, options);
|
|
846
|
+
});
|
|
847
|
+
}
|
|
848
|
+
callProtocolV1(uuid, name, data, options) {
|
|
849
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
850
|
+
if (!this._messages) {
|
|
851
|
+
throw hdShared.ERRORS.TypedError(hdShared.HardwareErrorCode.TransportNotConfigured);
|
|
852
|
+
}
|
|
853
|
+
const transport = this.getCachedTransport(uuid);
|
|
854
|
+
const runPromise = hdShared.createDeferred();
|
|
855
|
+
runPromise.promise.catch(() => undefined);
|
|
856
|
+
this.runPromise = runPromise;
|
|
857
|
+
const messages = this._messages;
|
|
858
|
+
const buffers = ProtocolV1.encodeTransportPackets(messages, name, data);
|
|
859
|
+
let timeout;
|
|
639
860
|
function writeChunkedData(buffers, writeFunction, onError) {
|
|
640
861
|
return __awaiter(this, void 0, void 0, function* () {
|
|
641
862
|
const packetCapacity = reactNative.Platform.OS === 'ios' ? IOS_PACKET_LENGTH : ANDROID_PACKET_LENGTH;
|
|
@@ -660,14 +881,14 @@ class ReactNativeBleTransport {
|
|
|
660
881
|
});
|
|
661
882
|
}
|
|
662
883
|
if (name === 'EmmcFileWrite') {
|
|
663
|
-
yield writeChunkedData(buffers, data => transport
|
|
884
|
+
yield writeChunkedData(buffers, data => transport.writeWithRetry(data), e => {
|
|
664
885
|
this.runPromise = null;
|
|
665
886
|
Log === null || Log === void 0 ? void 0 : Log.error('writeCharacteristic write error: ', e);
|
|
666
887
|
});
|
|
667
888
|
}
|
|
668
889
|
else if (name === 'FirmwareUpload') {
|
|
669
890
|
yield writeChunkedData(buffers, (data) => __awaiter(this, void 0, void 0, function* () {
|
|
670
|
-
yield transport
|
|
891
|
+
yield transport.writeCharacteristic.writeWithoutResponse(data);
|
|
671
892
|
}), e => {
|
|
672
893
|
this.runPromise = null;
|
|
673
894
|
Log === null || Log === void 0 ? void 0 : Log.error('writeCharacteristic write error: ', e);
|
|
@@ -677,7 +898,7 @@ class ReactNativeBleTransport {
|
|
|
677
898
|
for (const o of buffers) {
|
|
678
899
|
const outData = o.toString('base64');
|
|
679
900
|
try {
|
|
680
|
-
yield transport
|
|
901
|
+
yield transport.writeCharacteristic.writeWithoutResponse(outData);
|
|
681
902
|
}
|
|
682
903
|
catch (e) {
|
|
683
904
|
Log === null || Log === void 0 ? void 0 : Log.debug('writeCharacteristic write error: ', e);
|
|
@@ -695,20 +916,40 @@ class ReactNativeBleTransport {
|
|
|
695
916
|
}
|
|
696
917
|
}
|
|
697
918
|
try {
|
|
698
|
-
const response = yield
|
|
919
|
+
const response = yield Promise.race([
|
|
920
|
+
runPromise.promise,
|
|
921
|
+
new Promise((_, reject) => {
|
|
922
|
+
if (options === null || options === void 0 ? void 0 : options.timeoutMs) {
|
|
923
|
+
timeout = setTimeout(() => {
|
|
924
|
+
const error = hdShared.ERRORS.TypedError(hdShared.HardwareErrorCode.BleTimeoutError, `BLE response timeout after ${options.timeoutMs}ms for ${name}`);
|
|
925
|
+
runPromise.reject(error);
|
|
926
|
+
reject(error);
|
|
927
|
+
}, options.timeoutMs);
|
|
928
|
+
}
|
|
929
|
+
}),
|
|
930
|
+
]);
|
|
699
931
|
if (typeof response !== 'string') {
|
|
700
932
|
throw new Error('Returning data is not string.');
|
|
701
933
|
}
|
|
702
934
|
Log === null || Log === void 0 ? void 0 : Log.debug('receive data: ', response);
|
|
703
|
-
const jsonData =
|
|
935
|
+
const jsonData = ProtocolV1.decodeMessage(messages, response);
|
|
704
936
|
return check.call(jsonData);
|
|
705
937
|
}
|
|
706
938
|
catch (e) {
|
|
707
|
-
|
|
939
|
+
if (name === 'Initialize' && (options === null || options === void 0 ? void 0 : options.timeoutMs) === PROTOCOL_PROBE_TIMEOUT_MS) {
|
|
940
|
+
Log === null || Log === void 0 ? void 0 : Log.debug('[ReactNativeBleTransport] Protocol V1 Initialize probe call failed:', e);
|
|
941
|
+
}
|
|
942
|
+
else {
|
|
943
|
+
Log === null || Log === void 0 ? void 0 : Log.error('call error: ', e);
|
|
944
|
+
}
|
|
708
945
|
throw e;
|
|
709
946
|
}
|
|
710
947
|
finally {
|
|
711
|
-
|
|
948
|
+
if (timeout)
|
|
949
|
+
clearTimeout(timeout);
|
|
950
|
+
if (this.runPromise === runPromise) {
|
|
951
|
+
this.runPromise = null;
|
|
952
|
+
}
|
|
712
953
|
}
|
|
713
954
|
});
|
|
714
955
|
}
|
|
@@ -765,6 +1006,8 @@ class ReactNativeBleTransport {
|
|
|
765
1006
|
if (transportCache[session]) {
|
|
766
1007
|
delete transportCache[session];
|
|
767
1008
|
}
|
|
1009
|
+
this.deviceProtocol.delete(session);
|
|
1010
|
+
this.protocolV2Assemblers.delete(session);
|
|
768
1011
|
try {
|
|
769
1012
|
(_d = this.emitter) === null || _d === void 0 ? void 0 : _d.emit('device-disconnect', {
|
|
770
1013
|
name: (_e = transport === null || transport === void 0 ? void 0 : transport.device) === null || _e === void 0 ? void 0 : _e.name,
|
|
@@ -783,6 +1026,271 @@ class ReactNativeBleTransport {
|
|
|
783
1026
|
if (this.runPromise) ;
|
|
784
1027
|
this.runPromise = null;
|
|
785
1028
|
}
|
|
1029
|
+
getCachedTransport(uuid) {
|
|
1030
|
+
const transport = transportCache[uuid];
|
|
1031
|
+
if (!transport) {
|
|
1032
|
+
throw hdShared.ERRORS.TypedError(hdShared.HardwareErrorCode.TransportNotFound);
|
|
1033
|
+
}
|
|
1034
|
+
return transport;
|
|
1035
|
+
}
|
|
1036
|
+
createProtocolMismatchError(expected) {
|
|
1037
|
+
return hdShared.ERRORS.TypedError(hdShared.HardwareErrorCode.RuntimeError, `Device protocol mismatch: expected ${expected}, but device did not respond to expected protocol`);
|
|
1038
|
+
}
|
|
1039
|
+
detectProtocol(uuid, expectedProtocol) {
|
|
1040
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
1041
|
+
if (expectedProtocol === 'V1') {
|
|
1042
|
+
if (yield this.probeProtocolV1(uuid)) {
|
|
1043
|
+
this.deviceProtocol.set(uuid, 'V1');
|
|
1044
|
+
Log === null || Log === void 0 ? void 0 : Log.debug(`[ReactNativeBleTransport] detectProtocol: uuid=${uuid} -> V1 (expected)`);
|
|
1045
|
+
return 'V1';
|
|
1046
|
+
}
|
|
1047
|
+
throw this.createProtocolMismatchError(expectedProtocol);
|
|
1048
|
+
}
|
|
1049
|
+
if (expectedProtocol === 'V2') {
|
|
1050
|
+
if (yield this.probeProtocolV2(uuid)) {
|
|
1051
|
+
this.deviceProtocol.set(uuid, 'V2');
|
|
1052
|
+
Log === null || Log === void 0 ? void 0 : Log.debug(`[ReactNativeBleTransport] detectProtocol: uuid=${uuid} -> V2 (expected)`);
|
|
1053
|
+
return 'V2';
|
|
1054
|
+
}
|
|
1055
|
+
throw this.createProtocolMismatchError(expectedProtocol);
|
|
1056
|
+
}
|
|
1057
|
+
if (this.deviceProtocol.get(uuid) === 'V2' && (yield this.probeProtocolV2(uuid))) {
|
|
1058
|
+
this.deviceProtocol.set(uuid, 'V2');
|
|
1059
|
+
Log === null || Log === void 0 ? void 0 : Log.debug(`[ReactNativeBleTransport] detectProtocol: uuid=${uuid} -> V2 (cached)`);
|
|
1060
|
+
return 'V2';
|
|
1061
|
+
}
|
|
1062
|
+
let protocol = 'V1';
|
|
1063
|
+
if (!(yield this.probeProtocolV1(uuid)) && (yield this.probeProtocolV2(uuid))) {
|
|
1064
|
+
protocol = 'V2';
|
|
1065
|
+
}
|
|
1066
|
+
this.deviceProtocol.set(uuid, protocol);
|
|
1067
|
+
Log === null || Log === void 0 ? void 0 : Log.debug(`[ReactNativeBleTransport] detectProtocol: uuid=${uuid} -> ${protocol}`);
|
|
1068
|
+
return protocol;
|
|
1069
|
+
});
|
|
1070
|
+
}
|
|
1071
|
+
probeProtocolV1(uuid) {
|
|
1072
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
1073
|
+
if (!this._messages) {
|
|
1074
|
+
return false;
|
|
1075
|
+
}
|
|
1076
|
+
try {
|
|
1077
|
+
this.deviceProtocol.set(uuid, 'V1');
|
|
1078
|
+
yield this.callProtocolV1(uuid, 'Initialize', {}, { timeoutMs: PROTOCOL_PROBE_TIMEOUT_MS });
|
|
1079
|
+
return true;
|
|
1080
|
+
}
|
|
1081
|
+
catch (error) {
|
|
1082
|
+
Log === null || Log === void 0 ? void 0 : Log.debug('[ReactNativeBleTransport] Protocol V1 Initialize probe failed:', error);
|
|
1083
|
+
return false;
|
|
1084
|
+
}
|
|
1085
|
+
});
|
|
1086
|
+
}
|
|
1087
|
+
probeProtocolV2(uuid) {
|
|
1088
|
+
var _a;
|
|
1089
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
1090
|
+
if (!this._messages || !this._messagesV2) {
|
|
1091
|
+
return false;
|
|
1092
|
+
}
|
|
1093
|
+
this.deviceProtocol.set(uuid, 'V2');
|
|
1094
|
+
(_a = this.protocolV2Assemblers.get(uuid)) === null || _a === void 0 ? void 0 : _a.reset();
|
|
1095
|
+
return transport.probeProtocolV2({
|
|
1096
|
+
call: (name, data, options) => this.callProtocolV2(uuid, name, data, options),
|
|
1097
|
+
timeoutMs: PROTOCOL_V2_PROBE_TIMEOUT_MS,
|
|
1098
|
+
logger: Log,
|
|
1099
|
+
logPrefix: 'ProtocolV2 RN-BLE',
|
|
1100
|
+
onProbeFailed: () => {
|
|
1101
|
+
var _a;
|
|
1102
|
+
(_a = this.protocolV2Assemblers.get(uuid)) === null || _a === void 0 ? void 0 : _a.reset();
|
|
1103
|
+
this.resetProtocolV2Frames();
|
|
1104
|
+
},
|
|
1105
|
+
});
|
|
1106
|
+
});
|
|
1107
|
+
}
|
|
1108
|
+
handleProtocolV2Notification(uuid, data) {
|
|
1109
|
+
var _a, _b;
|
|
1110
|
+
try {
|
|
1111
|
+
if (!this.runPromise) {
|
|
1112
|
+
(_a = this.protocolV2Assemblers.get(uuid)) === null || _a === void 0 ? void 0 : _a.reset();
|
|
1113
|
+
this.resetProtocolV2Frames();
|
|
1114
|
+
return;
|
|
1115
|
+
}
|
|
1116
|
+
if (data.length === 0)
|
|
1117
|
+
return;
|
|
1118
|
+
const assembler = this.protocolV2Assemblers.get(uuid);
|
|
1119
|
+
if (!assembler)
|
|
1120
|
+
return;
|
|
1121
|
+
let frameData = assembler.push(data);
|
|
1122
|
+
while (frameData) {
|
|
1123
|
+
this.resolveProtocolV2Frame(frameData);
|
|
1124
|
+
frameData = assembler.push(new Uint8Array(0));
|
|
1125
|
+
}
|
|
1126
|
+
}
|
|
1127
|
+
catch (error) {
|
|
1128
|
+
Log === null || Log === void 0 ? void 0 : Log.debug('[ReactNativeBleTransport] Protocol V2 notification error:', error);
|
|
1129
|
+
const notifyError = hdShared.ERRORS.TypedError(hdShared.HardwareErrorCode.BleWriteCharacteristicError);
|
|
1130
|
+
(_b = this.runPromise) === null || _b === void 0 ? void 0 : _b.reject(notifyError);
|
|
1131
|
+
this.rejectProtocolV2Frame(notifyError);
|
|
1132
|
+
}
|
|
1133
|
+
}
|
|
1134
|
+
resolveProtocolV2Frame(frame) {
|
|
1135
|
+
if (this.protocolV2FramePromise) {
|
|
1136
|
+
this.protocolV2FramePromise.resolve(frame);
|
|
1137
|
+
this.protocolV2FramePromise = null;
|
|
1138
|
+
return;
|
|
1139
|
+
}
|
|
1140
|
+
this.protocolV2FrameQueue.push(frame);
|
|
1141
|
+
}
|
|
1142
|
+
rejectProtocolV2Frame(error) {
|
|
1143
|
+
this.protocolV2FrameQueue = [];
|
|
1144
|
+
if (this.protocolV2FramePromise) {
|
|
1145
|
+
this.protocolV2FramePromise.reject(error);
|
|
1146
|
+
this.protocolV2FramePromise = null;
|
|
1147
|
+
}
|
|
1148
|
+
}
|
|
1149
|
+
resetProtocolV2Frames() {
|
|
1150
|
+
this.protocolV2FrameQueue = [];
|
|
1151
|
+
this.protocolV2FramePromise = null;
|
|
1152
|
+
}
|
|
1153
|
+
readProtocolV2Frame() {
|
|
1154
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
1155
|
+
const queuedFrame = this.protocolV2FrameQueue.shift();
|
|
1156
|
+
if (queuedFrame) {
|
|
1157
|
+
return queuedFrame;
|
|
1158
|
+
}
|
|
1159
|
+
const framePromise = hdShared.createDeferred();
|
|
1160
|
+
this.protocolV2FramePromise = framePromise;
|
|
1161
|
+
try {
|
|
1162
|
+
return yield framePromise.promise;
|
|
1163
|
+
}
|
|
1164
|
+
finally {
|
|
1165
|
+
if (this.protocolV2FramePromise === framePromise) {
|
|
1166
|
+
this.protocolV2FramePromise = null;
|
|
1167
|
+
}
|
|
1168
|
+
}
|
|
1169
|
+
});
|
|
1170
|
+
}
|
|
1171
|
+
writeProtocolV2Frame(transport, frame, options) {
|
|
1172
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
1173
|
+
const tuning = getProtocolV2BleTuning();
|
|
1174
|
+
const packetCapacity = reactNative.Platform.OS === 'ios' ? tuning.iosPacketLength : tuning.androidPacketLength;
|
|
1175
|
+
const writeWithResponse = !!(options === null || options === void 0 ? void 0 : options.writeWithResponse) || (!!(options === null || options === void 0 ? void 0 : options.highVolume) && tuning.highVolumeWriteWithResponse);
|
|
1176
|
+
const shouldThrottle = !!(options === null || options === void 0 ? void 0 : options.highVolume) && !writeWithResponse;
|
|
1177
|
+
let packetsWritten = 0;
|
|
1178
|
+
try {
|
|
1179
|
+
for (let offset = 0; offset < frame.length; offset += packetCapacity) {
|
|
1180
|
+
const chunk = frame.slice(offset, offset + packetCapacity);
|
|
1181
|
+
const base64 = buffer.Buffer.from(chunk).toString('base64');
|
|
1182
|
+
if (writeWithResponse) {
|
|
1183
|
+
yield transport.writeCharacteristic.writeWithResponse(base64);
|
|
1184
|
+
}
|
|
1185
|
+
else {
|
|
1186
|
+
yield transport.writeCharacteristic.writeWithoutResponse(base64);
|
|
1187
|
+
}
|
|
1188
|
+
packetsWritten += 1;
|
|
1189
|
+
if (shouldThrottle &&
|
|
1190
|
+
packetsWritten % tuning.highVolumeWriteBurstSize === 0 &&
|
|
1191
|
+
offset + packetCapacity < frame.length) {
|
|
1192
|
+
yield delay(tuning.highVolumeWritePauseMs);
|
|
1193
|
+
}
|
|
1194
|
+
}
|
|
1195
|
+
if (shouldThrottle) {
|
|
1196
|
+
yield delay(tuning.highVolumeWriteFlushDelayMs);
|
|
1197
|
+
}
|
|
1198
|
+
}
|
|
1199
|
+
catch (error) {
|
|
1200
|
+
if ((options === null || options === void 0 ? void 0 : options.highVolume) && !writeWithResponse && packetsWritten === 0) {
|
|
1201
|
+
Log === null || Log === void 0 ? void 0 : Log.debug('[ReactNativeBleTransport] Protocol V2 high-volume writeWithoutResponse failed before data was sent, fallback to writeWithResponse:', error);
|
|
1202
|
+
yield this.writeProtocolV2Frame(transport, frame, {
|
|
1203
|
+
highVolume: true,
|
|
1204
|
+
writeWithResponse: true,
|
|
1205
|
+
});
|
|
1206
|
+
return;
|
|
1207
|
+
}
|
|
1208
|
+
throw error;
|
|
1209
|
+
}
|
|
1210
|
+
});
|
|
1211
|
+
}
|
|
1212
|
+
callProtocolV2(uuid, name, data, options) {
|
|
1213
|
+
var _a, _b, _c, _d;
|
|
1214
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
1215
|
+
if (!this._messages || !this._messagesV2) {
|
|
1216
|
+
throw hdShared.ERRORS.TypedError(hdShared.HardwareErrorCode.TransportNotConfigured);
|
|
1217
|
+
}
|
|
1218
|
+
const forceRun = name === 'Initialize' || name === 'Cancel' || name === 'GetProtoVersion';
|
|
1219
|
+
if (this.runPromise) {
|
|
1220
|
+
if (!forceRun) {
|
|
1221
|
+
throw hdShared.ERRORS.TypedError(hdShared.HardwareErrorCode.TransportCallInProgress);
|
|
1222
|
+
}
|
|
1223
|
+
const error = hdShared.ERRORS.TypedError(hdShared.HardwareErrorCode.BleForceCleanRunPromise);
|
|
1224
|
+
this.runPromise.reject(error);
|
|
1225
|
+
this.rejectProtocolV2Frame(error);
|
|
1226
|
+
this.runPromise = null;
|
|
1227
|
+
}
|
|
1228
|
+
const transport$1 = this.getCachedTransport(uuid);
|
|
1229
|
+
const runPromise = hdShared.createDeferred();
|
|
1230
|
+
runPromise.promise.catch(() => undefined);
|
|
1231
|
+
this.runPromise = runPromise;
|
|
1232
|
+
(_a = this.protocolV2Assemblers.get(uuid)) === null || _a === void 0 ? void 0 : _a.reset();
|
|
1233
|
+
this.resetProtocolV2Frames();
|
|
1234
|
+
let completed = false;
|
|
1235
|
+
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 });
|
|
1236
|
+
const highVolumeWrite = transport.LogBlockCommand.has(name);
|
|
1237
|
+
if (highVolumeWrite) {
|
|
1238
|
+
const tuning = getProtocolV2BleTuning();
|
|
1239
|
+
Log === null || Log === void 0 ? void 0 : Log.debug('[ReactNativeBleTransport] Protocol V2 high-volume write uses throttled writeWithoutResponse:', name, {
|
|
1240
|
+
packetCapacity: reactNative.Platform.OS === 'ios' ? tuning.iosPacketLength : tuning.androidPacketLength,
|
|
1241
|
+
burstSize: tuning.highVolumeWriteBurstSize,
|
|
1242
|
+
pauseMs: tuning.highVolumeWritePauseMs,
|
|
1243
|
+
flushDelayMs: tuning.highVolumeWriteFlushDelayMs,
|
|
1244
|
+
writeWithResponse: tuning.highVolumeWriteWithResponse,
|
|
1245
|
+
});
|
|
1246
|
+
}
|
|
1247
|
+
try {
|
|
1248
|
+
const session = new transport.ProtocolV2Session({
|
|
1249
|
+
schemas: {
|
|
1250
|
+
protocolV1: this._messages,
|
|
1251
|
+
protocolV2: this._messagesV2,
|
|
1252
|
+
},
|
|
1253
|
+
router: transport.PROTOCOL_V2_CHANNEL_BLE_UART,
|
|
1254
|
+
writeFrame: (frame) => this.writeProtocolV2Frame(transport$1, frame, { highVolume: highVolumeWrite }),
|
|
1255
|
+
readFrame: () => __awaiter(this, void 0, void 0, function* () {
|
|
1256
|
+
const rxFrame = yield this.readProtocolV2Frame();
|
|
1257
|
+
if (!(rxFrame instanceof Uint8Array)) {
|
|
1258
|
+
throw new Error('Protocol V2 response is not Uint8Array');
|
|
1259
|
+
}
|
|
1260
|
+
return rxFrame;
|
|
1261
|
+
}),
|
|
1262
|
+
logger: Log,
|
|
1263
|
+
logPrefix: 'ProtocolV2 RN-BLE',
|
|
1264
|
+
createTimeoutError: (_messageName, timeout) => hdShared.ERRORS.TypedError(hdShared.HardwareErrorCode.BleTimeoutError, `BLE response timeout after ${timeout}ms for ${name}`),
|
|
1265
|
+
});
|
|
1266
|
+
const result = yield session.call(name, data, callOptions);
|
|
1267
|
+
completed = true;
|
|
1268
|
+
return result;
|
|
1269
|
+
}
|
|
1270
|
+
catch (e) {
|
|
1271
|
+
(_c = this.protocolV2Assemblers.get(uuid)) === null || _c === void 0 ? void 0 : _c.reset();
|
|
1272
|
+
this.resetProtocolV2Frames();
|
|
1273
|
+
Log === null || Log === void 0 ? void 0 : Log.error('[ReactNativeBleTransport] Protocol V2 call error:', e);
|
|
1274
|
+
throw e;
|
|
1275
|
+
}
|
|
1276
|
+
finally {
|
|
1277
|
+
if (!completed) {
|
|
1278
|
+
(_d = this.protocolV2Assemblers.get(uuid)) === null || _d === void 0 ? void 0 : _d.reset();
|
|
1279
|
+
}
|
|
1280
|
+
this.resetProtocolV2Frames();
|
|
1281
|
+
if (this.runPromise === runPromise) {
|
|
1282
|
+
this.runPromise = null;
|
|
1283
|
+
}
|
|
1284
|
+
}
|
|
1285
|
+
});
|
|
1286
|
+
}
|
|
1287
|
+
getProtocolType(path) {
|
|
1288
|
+
var _a;
|
|
1289
|
+
return (_a = this.deviceProtocol.get(path)) !== null && _a !== void 0 ? _a : 'V1';
|
|
1290
|
+
}
|
|
786
1291
|
}
|
|
787
1292
|
|
|
788
|
-
|
|
1293
|
+
exports.configureProtocolV2BleTuning = configureProtocolV2BleTuning;
|
|
1294
|
+
exports["default"] = ReactNativeBleTransport;
|
|
1295
|
+
exports.getProtocolV2BleTuning = getProtocolV2BleTuning;
|
|
1296
|
+
exports.resetProtocolV2BleTuning = resetProtocolV2BleTuning;
|