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