@onekeyfe/hd-transport-react-native 1.2.5 → 1.2.6-alpha.1
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/bleNativeDisconnect.d.ts.map +1 -1
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +61 -23
- package/dist/subscribeBleOn.d.ts.map +1 -1
- package/package.json +5 -5
- package/src/__tests__/bleNativeDisconnect.test.ts +21 -0
- package/src/__tests__/connectTimeout.test.ts +38 -0
- package/src/__tests__/enumerate.test.ts +68 -2
- package/src/__tests__/iosPeerTermination.test.ts +3 -1
- package/src/__tests__/subscribeBleOn.test.ts +114 -0
- package/src/bleNativeDisconnect.ts +2 -1
- package/src/index.ts +23 -16
- package/src/subscribeBleOn.ts +30 -11
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"bleNativeDisconnect.d.ts","sourceRoot":"","sources":["../src/bleNativeDisconnect.ts"],"names":[],"mappings":"AAiBA,eAAO,MAAM,0BAA0B,UAAW,OAAO,KAAG,
|
|
1
|
+
{"version":3,"file":"bleNativeDisconnect.d.ts","sourceRoot":"","sources":["../src/bleNativeDisconnect.ts"],"names":[],"mappings":"AAiBA,eAAO,MAAM,0BAA0B,UAAW,OAAO,KAAG,OAW3D,CAAC;AAEF,eAAO,MAAM,4BAA4B,UAAW,OAAO,UAU1D,CAAC"}
|
package/dist/index.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"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
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":";AAEA,OAAO,EAGL,UAAU,IAAI,aAAa,EAG5B,MAAM,sBAAsB,CAAC;AAE9B,OAAO,SAAS,EAAE,EAChB,KAAK,oBAAoB,EAIzB,KAAK,YAAY,EAKjB,KAAK,oBAAoB,EAI1B,MAAM,wBAAwB,CAAC;AA6ChC,OAAO,YAAY,MAAM,gBAAgB,CAAC;AAI1C,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,qBAAqB,CAAC;AACpD,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,EAAE,YAAY,EAAE,MAAM,sBAAsB,CAAC;AACjF,OAAO,KAAK,YAAY,MAAM,QAAQ,CAAC;AACvC,OAAO,KAAK,EAAE,eAAe,EAAE,gBAAgB,EAAE,MAAM,SAAS,CAAC;AAGjE,KAAK,8BAA8B,GAAG,eAAe,GAAG;IAMtD,iBAAiB,CAAC,EAAE,OAAO,CAAC;CAC7B,CAAC;AAkBF,KAAK,4BAA4B,GAAG,WAAW,CAAC;AAChD,KAAK,0BAA0B,GAAG;IAChC,mBAAmB,EAAE,cAAc,CAAC;IACpC,oBAAoB,EAAE,cAAc,CAAC;CACtC,CAAC;AAkCF,eAAO,MAAM,+BAA+B,UACnC,OAAO,KACb,4BAA4B,GAAG,IAsBjC,CAAC;AAcF,eAAO,MAAM,2BAA2B,QAAS,CAAC;AAClD,eAAO,MAAM,8BAA8B,OAAQ,CAAC;AA4BpD,eAAO,MAAM,kCAAkC,QAAS,CAAC;AAEzD,eAAO,MAAM,4BAA4B,MAAM,CAAC;AAKhD,eAAO,MAAM,oCAAoC,OAAO,CAAC;AAKzD,eAAO,MAAM,gCAAgC,QAAS,CAAC;AAgBvD,eAAO,MAAM,yCAAyC,IAAI,CAAC;AAI3D,MAAM,MAAM,mBAAmB,GAAG;IAChC,eAAe,CAAC,EAAE,MAAM,CAAC;IACzB,mBAAmB,CAAC,EAAE,MAAM,CAAC;CAC9B,CAAC;AAiBF,wBAAgB,4BAA4B,CAAC,MAAM,GAAE,mBAAwB,QAY5E;AAED,wBAAgB,wBAAwB,SAGvC;AAED,wBAAgB,sBAAsB;;;EAErC;AA0CD,eAAO,MAAM,+BAA+B,QAAS,CAAC;AAMtD,eAAO,MAAM,0BAA0B,OAAO,CAAC;AAsC/C,eAAO,MAAM,sBAAsB,QAA2C,CAAC;AAO/E,eAAO,MAAM,yBAAyB,QAAS,CAAC;AAQhD,eAAO,MAAM,kCAAkC,IAAI,CAAC;AAEpD,eAAO,MAAM,2CAA2C,IAAI,CAAC;AAE7D,eAAO,MAAM,wBAAwB,gCAAgC,CAAC;AAuBtE,MAAM,MAAM,aAAa,GAAG,oBAAoB,GAAG,MAAM,CAAC;AA8G1D,MAAM,CAAC,OAAO,OAAO,uBAAuB;IAC1C,aAAa,EAAE,aAAa,GAAG,SAAS,CAAC;IAEzC,SAAS,EAAE,UAAU,CAAC,OAAO,SAAS,CAAC,cAAc,CAAC,GAAG,SAAS,CAAC;IAEnE,WAAW,EAAE,UAAU,CAAC,OAAO,SAAS,CAAC,cAAc,CAAC,GAAG,SAAS,CAAC;IAErE,OAAO,CAAC,6BAA6B,CAAqB;IAE1D,IAAI,SAA6B;IAEjC,UAAU,UAAS;IAEnB,OAAO,UAAS;IAEhB,OAAO,CAAC,QAAQ,CAAC,mBAAmB,CAAyB;IAE7D,WAAW,SAA0B;IAErC,UAAU,EAAE,QAAQ,CAAC,GAAG,CAAC,GAAG,IAAI,CAAQ;IAExC,OAAO,CAAC,kBAAkB,CAAuB;IAEjD,OAAO,CAAC,EAAE,YAAY,CAAC;IAEvB,8BAA8B,cAAqB;IAGnD,OAAO,CAAC,cAAc,CAAwC;IAQ9D,OAAO,CAAC,gBAAgB,CAAwC;IAGhE,OAAO,CAAC,kBAAkB,CAAkC;IAG5D,OAAO,CAAC,4BAA4B,CAAkC;IAEtE,OAAO,CAAC,mBAAmB,CAAwC;IAGnE,OAAO,CAAC,gBAAgB,CAAwC;IAGhE,OAAO,CAAC,mBAAmB,CAAqB;IAGhD,OAAO,CAAC,uBAAuB,CAAkC;IAGjE,OAAO,CAAC,gBAAgB,CAAyC;IAGjE,OAAO,CAAC,yBAAyB,CAAqB;IAOtD,OAAO,CAAC,eAAe,CAAiC;IAGxD,OAAO,CAAC,oBAAoB,CAAkC;IAG9D,OAAO,CAAC,kBAAkB,CAAmC;IAG7D,OAAO,CAAC,mBAAmB,CAAqB;IAEhD,OAAO,CAAC,oBAAoB,CAAoD;IAEhF,OAAO,CAAC,qBAAqB,CAAwC;IAErE,OAAO,CAAC,uBAAuB,CAAgD;IAE/E,OAAO,CAAC,eAAe,CA2BpB;IAEH,OAAO,CAAC,aAAa,CAAkC;IAEvD,OAAO,CAAC,qBAAqB,CAAkC;IAE/D,OAAO,CAAC,iCAAiC,CAAuC;IAEhF,OAAO,CAAC,0BAA0B,CAA0B;IAE5D,OAAO,CAAC,0BAA0B,CAAyD;IAE3F,OAAO,CAAC,gBAAgB,CAAK;IAG7B,OAAO,CAAC,mBAAmB,CAAyC;IAEpE,OAAO,CAAC,WAAW,CAAC,CAAgB;IAEpC,OAAO,CAAC,YAAY,CAAkC;gBAE1C,OAAO,EAAE,gBAAgB;IAIrC,IAAI,CAAC,MAAM,EAAE,GAAG,EAAE,OAAO,EAAE,YAAY;IAUvC,SAAS,CAAC,UAAU,EAAE,GAAG;IAMzB,mBAAmB,CAAC,UAAU,EAAE,GAAG;IAgBnC,MAAM;IAIA,aAAa,IAAI,OAAO,CAAC,aAAa,CAAC;YAS/B,mBAAmB;IAqB3B,sBAAsB,CAAC,MAAM,EAAE,MAAM,GAAG,OAAO,CAAC,0BAA0B,CAAC;IAmFjF,4BAA4B,CAAC,SAAS,EAAE,YAAY,EAAE,MAAM,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM;IAgClF,OAAO,CAAC,oBAAoB;IAgBtB,gCAAgC,CAAC,IAAI,EAAE,MAAM,EAAE,SAAS,EAAE,YAAY;IAsDtE,SAAS;YAwJD,0BAA0B;IA+ClC,OAAO,CAAC,KAAK,EAAE,8BAA8B;;;;YAgBrC,eAAe;IA8Y7B,sBAAsB,CACpB,cAAc,EAAE,cAAc,EAC9B,IAAI,EAAE,MAAM,EACZ,YAAY,EAAE,MAAM,EACpB,mBAAmB,EAAE,MAAM,GAC1B,YAAY;IAoIT,OAAO,CAAC,IAAI,EAAE,MAAM,EAAE,OAAO,UAAQ;YAI7B,eAAe;YAKf,aAAa;IA8ErB,IAAI,CAAC,OAAO,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC;IAajE,IAAI,CACR,IAAI,EAAE,MAAM,EACZ,IAAI,EAAE,MAAM,EACZ,IAAI,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,EAC7B,OAAO,CAAC,EAAE,oBAAoB;YAqClB,yBAAyB;IAwBvC,OAAO,CAAC,gBAAgB;IAyBxB,OAAO,CAAC,qBAAqB;YA4Bf,0BAA0B;YA0B1B,cAAc;IA0P5B,IAAI;IAkDE,UAAU,CAAC,OAAO,EAAE,MAAM;YAIlB,kBAAkB;YAmFlB,iBAAiB;IAkC/B,OAAO,CAAC,4BAA4B;YAQtB,qBAAqB;IAoB7B,MAAM;YAoBE,mBAAmB;YA4DnB,eAAe;YA6Bf,kBAAkB;YAmDlB,iCAAiC;IAyE/C,OAAO,CAAC,wBAAwB;IA0ChC,OAAO,CAAC,yBAAyB;IAMjC,OAAO,CAAC,kBAAkB;YAcZ,cAAc;IA+C5B,OAAO,CAAC,kBAAkB;IA+B1B,OAAO,CAAC,eAAe;IAkEvB,OAAO,CAAC,2BAA2B;IASnC,OAAO,CAAC,4BAA4B;IAOpC,OAAO,CAAC,kBAAkB;IAU1B,OAAO,CAAC,iBAAiB;YAIX,cAAc;YAmHd,0BAA0B;YAsB1B,iCAAiC;YAoDjC,eAAe;YAsBf,eAAe;IA4B7B,OAAO,CAAC,4BAA4B;IA2BpC,OAAO,CAAC,uBAAuB;IAS/B,OAAO,CAAC,sBAAsB;IAU9B,OAAO,CAAC,qBAAqB;IAI7B,OAAO,CAAC,sBAAsB;IAS9B,OAAO,CAAC,sBAAsB;IAQ9B,OAAO,CAAC,qBAAqB;YAOf,mBAAmB;YAiBnB,qBAAqB;YAmErB,oBAAoB;YAgCpB,cAAc;YAmFd,iCAAiC;IAsB/C,OAAO,CAAC,8BAA8B;YAQxB,mCAAmC;IAsBjD,OAAO,CAAC,yCAAyC;YAanC,gCAAgC;IAoB9C,OAAO,CAAC,uBAAuB;IAmD/B,eAAe,CAAC,IAAI,EAAE,MAAM,GAAG,YAAY,GAAG,SAAS;CAGxD"}
|
package/dist/index.js
CHANGED
|
@@ -308,24 +308,48 @@ const timer = process.env.NODE_ENV === 'development'
|
|
|
308
308
|
},
|
|
309
309
|
};
|
|
310
310
|
|
|
311
|
-
const subscribeBleOn = (bleManager, ms =
|
|
311
|
+
const subscribeBleOn = (bleManager, ms = 2000) => new Promise((resolve, reject) => {
|
|
312
312
|
let done = false;
|
|
313
|
+
let pendingError;
|
|
314
|
+
let cancelTimeout = () => undefined;
|
|
315
|
+
let removeSubscription = () => undefined;
|
|
316
|
+
const finish = (error) => {
|
|
317
|
+
if (done)
|
|
318
|
+
return;
|
|
319
|
+
done = true;
|
|
320
|
+
cancelTimeout();
|
|
321
|
+
removeSubscription();
|
|
322
|
+
if (error)
|
|
323
|
+
reject(error);
|
|
324
|
+
else
|
|
325
|
+
resolve();
|
|
326
|
+
};
|
|
313
327
|
const subscription = bleManager.onStateChange(state => {
|
|
314
328
|
if (state === 'PoweredOn') {
|
|
315
|
-
|
|
316
|
-
|
|
317
|
-
|
|
318
|
-
|
|
319
|
-
|
|
320
|
-
|
|
329
|
+
finish();
|
|
330
|
+
}
|
|
331
|
+
else if (state === 'PoweredOff') {
|
|
332
|
+
pendingError = hdShared.ERRORS.TypedError(hdShared.HardwareErrorCode.BlePoweredOff);
|
|
333
|
+
}
|
|
334
|
+
else if (state === 'Unsupported') {
|
|
335
|
+
pendingError = hdShared.ERRORS.TypedError(hdShared.HardwareErrorCode.BleUnsupported);
|
|
336
|
+
}
|
|
337
|
+
else if (state === 'Unauthorized') {
|
|
338
|
+
pendingError = hdShared.ERRORS.TypedError(hdShared.HardwareErrorCode.BlePermissionError);
|
|
339
|
+
}
|
|
340
|
+
else {
|
|
341
|
+
pendingError = undefined;
|
|
321
342
|
}
|
|
322
343
|
}, true);
|
|
323
|
-
|
|
324
|
-
|
|
325
|
-
|
|
326
|
-
|
|
327
|
-
|
|
328
|
-
|
|
344
|
+
removeSubscription = () => subscription.remove();
|
|
345
|
+
if (done) {
|
|
346
|
+
removeSubscription();
|
|
347
|
+
}
|
|
348
|
+
else {
|
|
349
|
+
cancelTimeout = timer.timeout(() => {
|
|
350
|
+
finish(pendingError !== null && pendingError !== void 0 ? pendingError : hdShared.ERRORS.TypedError(hdShared.HardwareErrorCode.BleScanError));
|
|
351
|
+
}, ms);
|
|
352
|
+
}
|
|
329
353
|
});
|
|
330
354
|
|
|
331
355
|
const HCI_PIN_OR_KEY_MISSING = 0x06;
|
|
@@ -562,7 +586,8 @@ const isNativeBleDisconnectError = (error) => {
|
|
|
562
586
|
}
|
|
563
587
|
const nativeError = error;
|
|
564
588
|
return (nativeError.errorCode === BLE_PLX_DEVICE_DISCONNECTED ||
|
|
565
|
-
nativeError.iosErrorCode === IOS_PERIPHERAL_DISCONNECTED
|
|
589
|
+
nativeError.iosErrorCode === IOS_PERIPHERAL_DISCONNECTED ||
|
|
590
|
+
nativeErrorText$1(nativeError).toLowerCase().includes('was disconnected'));
|
|
566
591
|
};
|
|
567
592
|
const toBleDisconnectHardwareError = (error) => {
|
|
568
593
|
if ((error === null || error === void 0 ? void 0 : error.errorCode) === hdShared.HardwareErrorCode.BleDeviceDisconnected) {
|
|
@@ -877,7 +902,7 @@ const resolveNegotiatedMtu = (device, cancelTransaction) => shouldRefreshNegotia
|
|
|
877
902
|
? requestNegotiatedMtu(device, 'connected', 0, cancelTransaction)
|
|
878
903
|
: Promise.resolve({ device, timedOut: false });
|
|
879
904
|
function remapError(error) {
|
|
880
|
-
var _a;
|
|
905
|
+
var _a, _b;
|
|
881
906
|
if (error instanceof reactNativeBlePlx.BleError) {
|
|
882
907
|
if (isNativeBleStaleBondError(error)) {
|
|
883
908
|
throw toBleStaleBondHardwareError(error);
|
|
@@ -886,12 +911,13 @@ function remapError(error) {
|
|
|
886
911
|
throw hdShared.ERRORS.TypedError(hdShared.HardwareErrorCode.BleDeviceBondError);
|
|
887
912
|
}
|
|
888
913
|
}
|
|
889
|
-
if (error
|
|
890
|
-
error
|
|
891
|
-
|
|
914
|
+
if (isNativeBleDisconnectError(error)) {
|
|
915
|
+
throw toBleDisconnectHardwareError(error);
|
|
916
|
+
}
|
|
917
|
+
if (error instanceof Error && ((_a = error.message) === null || _a === void 0 ? void 0 : _a.includes('not found'))) {
|
|
892
918
|
throw hdShared.ERRORS.TypedError(hdShared.HardwareErrorCode.BleDeviceDisconnected);
|
|
893
919
|
}
|
|
894
|
-
throw hdShared.ERRORS.TypedError(hdShared.HardwareErrorCode.BleConnectedError, (
|
|
920
|
+
throw hdShared.ERRORS.TypedError(hdShared.HardwareErrorCode.BleConnectedError, (_b = error.reason) !== null && _b !== void 0 ? _b : error);
|
|
895
921
|
}
|
|
896
922
|
class ReactNativeBleTransport {
|
|
897
923
|
constructor(options) {
|
|
@@ -1190,7 +1216,6 @@ class ReactNativeBleTransport {
|
|
|
1190
1216
|
const scanStartedAt = Date.now();
|
|
1191
1217
|
let firstDeviceMs;
|
|
1192
1218
|
const blePlxManager = yield this.getPlxManager();
|
|
1193
|
-
yield subscribeBleOn(blePlxManager);
|
|
1194
1219
|
if (reactNative.Platform.OS === 'android' && reactNative.Platform.Version >= 31) {
|
|
1195
1220
|
Log === null || Log === void 0 ? void 0 : Log.debug('requesting permissions, please wait...');
|
|
1196
1221
|
const resultConnect = yield reactNative.PermissionsAndroid.requestMultiple([
|
|
@@ -1203,6 +1228,7 @@ class ReactNativeBleTransport {
|
|
|
1203
1228
|
throw hdShared.ERRORS.TypedError(hdShared.HardwareErrorCode.BlePermissionError);
|
|
1204
1229
|
}
|
|
1205
1230
|
}
|
|
1231
|
+
yield subscribeBleOn(blePlxManager);
|
|
1206
1232
|
if (this.stopped)
|
|
1207
1233
|
throw hdShared.ERRORS.TypedError(hdShared.HardwareErrorCode.BleDeviceDisconnected);
|
|
1208
1234
|
return new Promise((resolve, reject) => {
|
|
@@ -1243,11 +1269,14 @@ class ReactNativeBleTransport {
|
|
|
1243
1269
|
var _a, _b;
|
|
1244
1270
|
if (error) {
|
|
1245
1271
|
Log === null || Log === void 0 ? void 0 : Log.debug('ble scan error: ', error);
|
|
1246
|
-
if (
|
|
1247
|
-
finishScan(hdShared.ERRORS.TypedError(hdShared.HardwareErrorCode.
|
|
1272
|
+
if (error.errorCode === reactNativeBlePlx.BleErrorCode.BluetoothPoweredOff) {
|
|
1273
|
+
finishScan(hdShared.ERRORS.TypedError(hdShared.HardwareErrorCode.BlePoweredOff));
|
|
1274
|
+
}
|
|
1275
|
+
else if (error.errorCode === reactNativeBlePlx.BleErrorCode.BluetoothUnsupported) {
|
|
1276
|
+
finishScan(hdShared.ERRORS.TypedError(hdShared.HardwareErrorCode.BleUnsupported));
|
|
1248
1277
|
}
|
|
1249
1278
|
else if (error.errorCode === reactNativeBlePlx.BleErrorCode.BluetoothUnauthorized) {
|
|
1250
|
-
finishScan(hdShared.ERRORS.TypedError(hdShared.HardwareErrorCode.
|
|
1279
|
+
finishScan(hdShared.ERRORS.TypedError(hdShared.HardwareErrorCode.BlePermissionError));
|
|
1251
1280
|
}
|
|
1252
1281
|
else if (error.errorCode === reactNativeBlePlx.BleErrorCode.LocationServicesDisabled) {
|
|
1253
1282
|
finishScan(hdShared.ERRORS.TypedError(hdShared.HardwareErrorCode.BleLocationServicesDisabled));
|
|
@@ -2497,6 +2526,15 @@ class ReactNativeBleTransport {
|
|
|
2497
2526
|
throw this.createWedgedBleSetupError();
|
|
2498
2527
|
}
|
|
2499
2528
|
}
|
|
2529
|
+
if (isNativeBleStaleBondError(error) || hdShared.isBleStaleBondHardwareError(error)) {
|
|
2530
|
+
throw toBleStaleBondHardwareError(error);
|
|
2531
|
+
}
|
|
2532
|
+
if (isNativeBleDisconnectError(error)) {
|
|
2533
|
+
if (reactNative.Platform.OS === 'ios' && isIosPeerTerminationError(error)) {
|
|
2534
|
+
throw error;
|
|
2535
|
+
}
|
|
2536
|
+
throw toBleDisconnectHardwareError(error);
|
|
2537
|
+
}
|
|
2500
2538
|
if (reactNative.Platform.OS === 'android' && isMissingGattShapeError(error)) {
|
|
2501
2539
|
this.androidGattCacheRefreshes.add(uuid);
|
|
2502
2540
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"subscribeBleOn.d.ts","sourceRoot":"","sources":["../src/subscribeBleOn.ts"],"names":[],"mappings":"AAIA,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,SAAS,CAAC;AAE7C,eAAO,MAAM,cAAc,eAAgB,aAAa,kBAAc,QAAQ,IAAI,
|
|
1
|
+
{"version":3,"file":"subscribeBleOn.d.ts","sourceRoot":"","sources":["../src/subscribeBleOn.ts"],"names":[],"mappings":"AAIA,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,SAAS,CAAC;AAE7C,eAAO,MAAM,cAAc,eAAgB,aAAa,kBAAc,QAAQ,IAAI,CAsC9E,CAAC"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@onekeyfe/hd-transport-react-native",
|
|
3
|
-
"version": "1.2.
|
|
3
|
+
"version": "1.2.6-alpha.1",
|
|
4
4
|
"homepage": "https://github.com/OneKeyHQ/hardware-js-sdk#readme",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"main": "dist/index.js",
|
|
@@ -20,11 +20,11 @@
|
|
|
20
20
|
"lint:fix": "eslint . --fix"
|
|
21
21
|
},
|
|
22
22
|
"dependencies": {
|
|
23
|
-
"@onekeyfe/hd-core": "1.2.
|
|
24
|
-
"@onekeyfe/hd-shared": "1.2.
|
|
25
|
-
"@onekeyfe/hd-transport": "1.2.
|
|
23
|
+
"@onekeyfe/hd-core": "1.2.6-alpha.1",
|
|
24
|
+
"@onekeyfe/hd-shared": "1.2.6-alpha.1",
|
|
25
|
+
"@onekeyfe/hd-transport": "1.2.6-alpha.1",
|
|
26
26
|
"@onekeyfe/react-native-ble-utils": "0.1.9",
|
|
27
27
|
"react-native-ble-plx": "3.5.1"
|
|
28
28
|
},
|
|
29
|
-
"gitHead": "
|
|
29
|
+
"gitHead": "32f41a09724c316ccefe39daae56c22f539d76bd"
|
|
30
30
|
}
|
|
@@ -30,4 +30,25 @@ describe('native BLE disconnect mapping', () => {
|
|
|
30
30
|
})
|
|
31
31
|
).toBe(false);
|
|
32
32
|
});
|
|
33
|
+
|
|
34
|
+
test('recognizes the unstructured ble-plx disconnect observed during GATT discovery', () => {
|
|
35
|
+
const nativeError = {
|
|
36
|
+
errorCode: 0,
|
|
37
|
+
message: 'BleError: Device stalled-connect-device was disconnected',
|
|
38
|
+
};
|
|
39
|
+
|
|
40
|
+
expect(isNativeBleDisconnectError(nativeError)).toBe(true);
|
|
41
|
+
expect(toBleDisconnectHardwareError(nativeError)).toMatchObject({
|
|
42
|
+
errorCode: HardwareErrorCode.BleDeviceDisconnected,
|
|
43
|
+
});
|
|
44
|
+
});
|
|
45
|
+
|
|
46
|
+
test('does not infer a disconnect from an unrelated discovery failure', () => {
|
|
47
|
+
expect(
|
|
48
|
+
isNativeBleDisconnectError({
|
|
49
|
+
errorCode: 0,
|
|
50
|
+
message: 'Known OneKey service UUID not found',
|
|
51
|
+
})
|
|
52
|
+
).toBe(false);
|
|
53
|
+
});
|
|
33
54
|
});
|
|
@@ -623,6 +623,44 @@ describe('BLE connect timeout', () => {
|
|
|
623
623
|
expect(bleManager.cancelDeviceConnection).toHaveBeenCalledWith(UUID);
|
|
624
624
|
});
|
|
625
625
|
|
|
626
|
+
test.each([
|
|
627
|
+
{
|
|
628
|
+
nativeFields: { errorCode: BleErrorCode.DeviceDisconnected, iosErrorCode: 14 },
|
|
629
|
+
reason: 'Peer removed pairing information',
|
|
630
|
+
errorCode: HardwareErrorCode.BlePeerRemovedPairingInformation,
|
|
631
|
+
},
|
|
632
|
+
{
|
|
633
|
+
nativeFields: { errorCode: 0, attErrorCode: 5 },
|
|
634
|
+
reason: 'GATT_INSUF_AUTHENTICATION',
|
|
635
|
+
errorCode: HardwareErrorCode.BleDeviceBondError,
|
|
636
|
+
},
|
|
637
|
+
])(
|
|
638
|
+
'maps a stale bond during GATT discovery to canonical error $errorCode',
|
|
639
|
+
async ({ nativeFields, reason, errorCode }) => {
|
|
640
|
+
const { transport, device } = createHarness(() => Promise.resolve());
|
|
641
|
+
const nativeError = Object.assign(new Error(reason), nativeFields, { reason });
|
|
642
|
+
device.discoverAllServicesAndCharacteristics.mockRejectedValueOnce(nativeError);
|
|
643
|
+
|
|
644
|
+
await expect(
|
|
645
|
+
(transport as any).resolveCharacteristicsWithTimeout(UUID, device)
|
|
646
|
+
).rejects.toMatchObject({ errorCode });
|
|
647
|
+
}
|
|
648
|
+
);
|
|
649
|
+
|
|
650
|
+
test('normalizes an unstructured GATT disconnect instead of leaking an unknown error', async () => {
|
|
651
|
+
const { transport, device } = createHarness(() => Promise.resolve());
|
|
652
|
+
const nativeError = Object.assign(new Error(`BleError: Device ${UUID} was disconnected`), {
|
|
653
|
+
errorCode: 0,
|
|
654
|
+
});
|
|
655
|
+
device.discoverAllServicesAndCharacteristics.mockRejectedValueOnce(nativeError);
|
|
656
|
+
|
|
657
|
+
await expect(
|
|
658
|
+
(transport as any).resolveCharacteristicsWithTimeout(UUID, device)
|
|
659
|
+
).rejects.toMatchObject({
|
|
660
|
+
errorCode: HardwareErrorCode.BleDeviceDisconnected,
|
|
661
|
+
});
|
|
662
|
+
});
|
|
663
|
+
|
|
626
664
|
test('a successful GATT retry clears the timeout budget before an abandoned call settles', async () => {
|
|
627
665
|
const { transport, device, bleManager } = createHarness(() => Promise.resolve());
|
|
628
666
|
let resolveAbandonedDiscovery: (() => void) | undefined;
|
|
@@ -1,12 +1,22 @@
|
|
|
1
1
|
import { EventEmitter } from 'events';
|
|
2
|
+
import { PermissionsAndroid, Platform } from 'react-native';
|
|
3
|
+
import { BleErrorCode } from 'react-native-ble-plx';
|
|
4
|
+
import { HardwareErrorCode } from '@onekeyfe/hd-shared';
|
|
2
5
|
|
|
3
6
|
import { getConnectedDeviceIds } from '../BleManager';
|
|
4
7
|
import ReactNativeBleTransport from '../index';
|
|
8
|
+
import { subscribeBleOn } from '../subscribeBleOn';
|
|
5
9
|
|
|
6
10
|
jest.mock(
|
|
7
11
|
'react-native',
|
|
8
12
|
() => ({
|
|
9
|
-
PermissionsAndroid: {
|
|
13
|
+
PermissionsAndroid: {
|
|
14
|
+
PERMISSIONS: {
|
|
15
|
+
BLUETOOTH_CONNECT: 'android.permission.BLUETOOTH_CONNECT',
|
|
16
|
+
BLUETOOTH_SCAN: 'android.permission.BLUETOOTH_SCAN',
|
|
17
|
+
},
|
|
18
|
+
requestMultiple: jest.fn(),
|
|
19
|
+
},
|
|
10
20
|
Platform: { OS: 'ios' },
|
|
11
21
|
}),
|
|
12
22
|
{ virtual: true }
|
|
@@ -14,7 +24,14 @@ jest.mock(
|
|
|
14
24
|
|
|
15
25
|
jest.mock('react-native-ble-plx', () => ({
|
|
16
26
|
BleError: class BleError extends Error {},
|
|
17
|
-
BleErrorCode: {
|
|
27
|
+
BleErrorCode: {
|
|
28
|
+
BluetoothUnsupported: 100,
|
|
29
|
+
BluetoothUnauthorized: 101,
|
|
30
|
+
BluetoothPoweredOff: 102,
|
|
31
|
+
BluetoothInUnknownState: 103,
|
|
32
|
+
ScanStartFailed: 600,
|
|
33
|
+
LocationServicesDisabled: 601,
|
|
34
|
+
},
|
|
18
35
|
BleManager: jest.fn(),
|
|
19
36
|
ScanMode: { LowLatency: 2 },
|
|
20
37
|
}));
|
|
@@ -46,6 +63,55 @@ jest.mock('../subscribeBleOn', () => ({
|
|
|
46
63
|
|
|
47
64
|
const ONEKEY_SERVICE_UUID = '00000001-0000-1000-8000-00805f9b34fb';
|
|
48
65
|
|
|
66
|
+
describe('ReactNativeBleTransport scan error mapping', () => {
|
|
67
|
+
beforeEach(() => {
|
|
68
|
+
jest.clearAllMocks();
|
|
69
|
+
});
|
|
70
|
+
|
|
71
|
+
afterEach(() => {
|
|
72
|
+
Object.assign(Platform, { OS: 'ios', Version: undefined });
|
|
73
|
+
});
|
|
74
|
+
|
|
75
|
+
test('checks Android Bluetooth permissions before waiting for adapter state', async () => {
|
|
76
|
+
Object.assign(Platform, { OS: 'android', Version: 31 });
|
|
77
|
+
jest.mocked(PermissionsAndroid).requestMultiple.mockResolvedValueOnce({
|
|
78
|
+
[PermissionsAndroid.PERMISSIONS.BLUETOOTH_CONNECT]: 'denied',
|
|
79
|
+
[PermissionsAndroid.PERMISSIONS.BLUETOOTH_SCAN]: 'denied',
|
|
80
|
+
});
|
|
81
|
+
const transport = new ReactNativeBleTransport({});
|
|
82
|
+
transport.blePlxManager = {} as never;
|
|
83
|
+
transport.init({ debug: jest.fn(), error: jest.fn() }, new EventEmitter());
|
|
84
|
+
|
|
85
|
+
await expect(transport.enumerate()).rejects.toMatchObject({
|
|
86
|
+
errorCode: HardwareErrorCode.BlePermissionError,
|
|
87
|
+
});
|
|
88
|
+
expect(subscribeBleOn).not.toHaveBeenCalled();
|
|
89
|
+
});
|
|
90
|
+
|
|
91
|
+
test.each([
|
|
92
|
+
[BleErrorCode.BluetoothPoweredOff, HardwareErrorCode.BlePoweredOff],
|
|
93
|
+
[BleErrorCode.BluetoothUnsupported, HardwareErrorCode.BleUnsupported],
|
|
94
|
+
[BleErrorCode.BluetoothInUnknownState, HardwareErrorCode.BleScanError],
|
|
95
|
+
[BleErrorCode.BluetoothUnauthorized, HardwareErrorCode.BlePermissionError],
|
|
96
|
+
])('maps native BLE error %s to hardware error %s', async (nativeCode, errorCode) => {
|
|
97
|
+
jest.mocked(getConnectedDeviceIds).mockResolvedValueOnce([]);
|
|
98
|
+
const blePlxManager = {
|
|
99
|
+
startDeviceScan: jest.fn((_serviceUUIDs, _options, listener) => {
|
|
100
|
+
queueMicrotask(() => {
|
|
101
|
+
listener({ errorCode: nativeCode, reason: 'native scan failure' }, null);
|
|
102
|
+
});
|
|
103
|
+
}),
|
|
104
|
+
stopDeviceScan: jest.fn(() => Promise.resolve()),
|
|
105
|
+
};
|
|
106
|
+
const transport = new ReactNativeBleTransport({ scanTimeout: 10_000 });
|
|
107
|
+
transport.blePlxManager = blePlxManager as never;
|
|
108
|
+
transport.init({ debug: jest.fn(), error: jest.fn() }, new EventEmitter());
|
|
109
|
+
|
|
110
|
+
await expect(transport.enumerate()).rejects.toMatchObject({ errorCode });
|
|
111
|
+
expect(blePlxManager.stopDeviceScan).toHaveBeenCalledTimes(1);
|
|
112
|
+
});
|
|
113
|
+
});
|
|
114
|
+
|
|
49
115
|
describe('ReactNativeBleTransport iOS discovery', () => {
|
|
50
116
|
test('keeps a bonded Pro2 communication peripheral after Find My changes its name', async () => {
|
|
51
117
|
jest.mocked(getConnectedDeviceIds).mockResolvedValueOnce([
|
|
@@ -215,7 +215,9 @@ describe('iOS link ended by the device right after connecting', () => {
|
|
|
215
215
|
.mockImplementation(() => Promise.reject(peerEndedLink()));
|
|
216
216
|
|
|
217
217
|
await acquire(transport);
|
|
218
|
-
await expect(acquire(transport)).resolves.
|
|
218
|
+
await expect(acquire(transport)).resolves.toMatchObject({
|
|
219
|
+
code: HardwareErrorCode.BleDeviceDisconnected,
|
|
220
|
+
});
|
|
219
221
|
await expect(acquire(transport)).resolves.toEqual({ native: 7 });
|
|
220
222
|
});
|
|
221
223
|
|
|
@@ -0,0 +1,114 @@
|
|
|
1
|
+
import { HardwareErrorCode } from '@onekeyfe/hd-shared';
|
|
2
|
+
|
|
3
|
+
import { subscribeBleOn } from '../subscribeBleOn';
|
|
4
|
+
|
|
5
|
+
import type { BlePlxManager } from '../types';
|
|
6
|
+
|
|
7
|
+
type BleState = Parameters<Parameters<BlePlxManager['onStateChange']>[0]>[0];
|
|
8
|
+
|
|
9
|
+
const createBleManager = () => {
|
|
10
|
+
let stateListener: ((state: BleState) => void) | undefined;
|
|
11
|
+
const remove = jest.fn();
|
|
12
|
+
const bleManager = {
|
|
13
|
+
onStateChange: jest.fn(listener => {
|
|
14
|
+
stateListener = listener;
|
|
15
|
+
return { remove };
|
|
16
|
+
}),
|
|
17
|
+
} as unknown as BlePlxManager;
|
|
18
|
+
|
|
19
|
+
return {
|
|
20
|
+
bleManager,
|
|
21
|
+
emitState: (state: BleState) => stateListener?.(state),
|
|
22
|
+
remove,
|
|
23
|
+
};
|
|
24
|
+
};
|
|
25
|
+
|
|
26
|
+
describe('subscribeBleOn', () => {
|
|
27
|
+
beforeAll(() => {
|
|
28
|
+
jest.useFakeTimers({ doNotFake: ['performance'] });
|
|
29
|
+
});
|
|
30
|
+
|
|
31
|
+
afterAll(() => {
|
|
32
|
+
jest.useRealTimers();
|
|
33
|
+
});
|
|
34
|
+
|
|
35
|
+
afterEach(() => {
|
|
36
|
+
jest.clearAllTimers();
|
|
37
|
+
});
|
|
38
|
+
|
|
39
|
+
test('resolves when Bluetooth is powered on', async () => {
|
|
40
|
+
const { bleManager, emitState, remove } = createBleManager();
|
|
41
|
+
const result = subscribeBleOn(bleManager);
|
|
42
|
+
|
|
43
|
+
emitState('PoweredOn');
|
|
44
|
+
|
|
45
|
+
await expect(result).resolves.toBeUndefined();
|
|
46
|
+
expect(remove).toHaveBeenCalledTimes(1);
|
|
47
|
+
expect(jest.getTimerCount()).toBe(0);
|
|
48
|
+
});
|
|
49
|
+
|
|
50
|
+
test('cleans up when the current state is emitted synchronously', async () => {
|
|
51
|
+
const remove = jest.fn();
|
|
52
|
+
const bleManager = {
|
|
53
|
+
onStateChange: jest.fn(listener => {
|
|
54
|
+
listener('PoweredOn');
|
|
55
|
+
return { remove };
|
|
56
|
+
}),
|
|
57
|
+
} as unknown as BlePlxManager;
|
|
58
|
+
|
|
59
|
+
await expect(subscribeBleOn(bleManager)).resolves.toBeUndefined();
|
|
60
|
+
expect(remove).toHaveBeenCalledTimes(1);
|
|
61
|
+
expect(jest.getTimerCount()).toBe(0);
|
|
62
|
+
});
|
|
63
|
+
|
|
64
|
+
test.each([
|
|
65
|
+
['PoweredOff', HardwareErrorCode.BlePoweredOff],
|
|
66
|
+
['Unsupported', HardwareErrorCode.BleUnsupported],
|
|
67
|
+
['Unauthorized', HardwareErrorCode.BlePermissionError],
|
|
68
|
+
] as const)('maps %s to hardware error %s', async (state, errorCode) => {
|
|
69
|
+
const { bleManager, emitState, remove } = createBleManager();
|
|
70
|
+
const result = subscribeBleOn(bleManager, 2000);
|
|
71
|
+
const rejection = expect(result).rejects.toMatchObject({ errorCode });
|
|
72
|
+
|
|
73
|
+
emitState(state);
|
|
74
|
+
jest.advanceTimersByTime(1999);
|
|
75
|
+
expect(remove).not.toHaveBeenCalled();
|
|
76
|
+
jest.advanceTimersByTime(1);
|
|
77
|
+
|
|
78
|
+
await rejection;
|
|
79
|
+
expect(remove).toHaveBeenCalledTimes(1);
|
|
80
|
+
expect(jest.getTimerCount()).toBe(0);
|
|
81
|
+
});
|
|
82
|
+
|
|
83
|
+
test('resolves if Bluetooth powers on during the readiness window', async () => {
|
|
84
|
+
const { bleManager, emitState, remove } = createBleManager();
|
|
85
|
+
const result = subscribeBleOn(bleManager);
|
|
86
|
+
|
|
87
|
+
emitState('PoweredOff');
|
|
88
|
+
jest.advanceTimersByTime(1999);
|
|
89
|
+
expect(remove).not.toHaveBeenCalled();
|
|
90
|
+
emitState('PoweredOn');
|
|
91
|
+
|
|
92
|
+
await expect(result).resolves.toBeUndefined();
|
|
93
|
+
expect(remove).toHaveBeenCalledTimes(1);
|
|
94
|
+
expect(jest.getTimerCount()).toBe(0);
|
|
95
|
+
});
|
|
96
|
+
|
|
97
|
+
test.each(['Unknown', 'Resetting'] as const)(
|
|
98
|
+
'reports %s as a scan error if no stable state arrives before timeout',
|
|
99
|
+
async state => {
|
|
100
|
+
const { bleManager, emitState, remove } = createBleManager();
|
|
101
|
+
const result = subscribeBleOn(bleManager, 1000);
|
|
102
|
+
const rejection = expect(result).rejects.toMatchObject({
|
|
103
|
+
errorCode: HardwareErrorCode.BleScanError,
|
|
104
|
+
});
|
|
105
|
+
|
|
106
|
+
emitState('PoweredOff');
|
|
107
|
+
emitState(state);
|
|
108
|
+
jest.advanceTimersByTime(1000);
|
|
109
|
+
|
|
110
|
+
await rejection;
|
|
111
|
+
expect(remove).toHaveBeenCalledTimes(1);
|
|
112
|
+
}
|
|
113
|
+
);
|
|
114
|
+
});
|
|
@@ -23,7 +23,8 @@ export const isNativeBleDisconnectError = (error: unknown): boolean => {
|
|
|
23
23
|
const nativeError = error as NativeBleErrorFields;
|
|
24
24
|
return (
|
|
25
25
|
nativeError.errorCode === BLE_PLX_DEVICE_DISCONNECTED ||
|
|
26
|
-
nativeError.iosErrorCode === IOS_PERIPHERAL_DISCONNECTED
|
|
26
|
+
nativeError.iosErrorCode === IOS_PERIPHERAL_DISCONNECTED ||
|
|
27
|
+
nativeErrorText(nativeError).toLowerCase().includes('was disconnected')
|
|
27
28
|
);
|
|
28
29
|
};
|
|
29
30
|
|
package/src/index.ts
CHANGED
|
@@ -59,7 +59,7 @@ import {
|
|
|
59
59
|
stopBleEncryptionTracking,
|
|
60
60
|
waitForAndroidLinkEncryption,
|
|
61
61
|
} from './bleEncryption';
|
|
62
|
-
import { IosPeerTerminationTracker } from './bleIosStaleBond';
|
|
62
|
+
import { IosPeerTerminationTracker, isIosPeerTerminationError } from './bleIosStaleBond';
|
|
63
63
|
import { isNativeBleDisconnectError, toBleDisconnectHardwareError } from './bleNativeDisconnect';
|
|
64
64
|
import {
|
|
65
65
|
isBleStaleBondHardwareError,
|
|
@@ -189,8 +189,8 @@ const shouldRethrowProtocolProbeError = (error: unknown): boolean => {
|
|
|
189
189
|
const code = (error as { errorCode?: unknown })?.errorCode;
|
|
190
190
|
// Bonding and GATT failures are not evidence of a protocol mismatch. Preserve
|
|
191
191
|
// them instead of probing another protocol on an unusable connection.
|
|
192
|
-
// Native PLX disconnects (errorCode 201 / iOS 7
|
|
193
|
-
//
|
|
192
|
+
// Native PLX disconnects (errorCode 201 / iOS 7, or the unstructured
|
|
193
|
+
// "was disconnected" fallback) must match before Protocol V2 probing.
|
|
194
194
|
return (
|
|
195
195
|
isBleStaleBondHardwareError(error) ||
|
|
196
196
|
isNativeBleDisconnectError(error) ||
|
|
@@ -506,11 +506,11 @@ function remapError(error: IOBleErrorRemap) {
|
|
|
506
506
|
}
|
|
507
507
|
}
|
|
508
508
|
|
|
509
|
-
if (
|
|
510
|
-
error
|
|
511
|
-
|
|
512
|
-
|
|
513
|
-
) {
|
|
509
|
+
if (isNativeBleDisconnectError(error)) {
|
|
510
|
+
throw toBleDisconnectHardwareError(error);
|
|
511
|
+
}
|
|
512
|
+
|
|
513
|
+
if (error instanceof Error && error.message?.includes('not found')) {
|
|
514
514
|
throw ERRORS.TypedError(HardwareErrorCode.BleDeviceDisconnected);
|
|
515
515
|
}
|
|
516
516
|
|
|
@@ -908,7 +908,6 @@ export default class ReactNativeBleTransport {
|
|
|
908
908
|
const scanStartedAt = Date.now();
|
|
909
909
|
let firstDeviceMs: number | undefined;
|
|
910
910
|
const blePlxManager = await this.getPlxManager();
|
|
911
|
-
await subscribeBleOn(blePlxManager);
|
|
912
911
|
if (Platform.OS === 'android' && Platform.Version >= 31) {
|
|
913
912
|
Log?.debug('requesting permissions, please wait...');
|
|
914
913
|
|
|
@@ -925,6 +924,7 @@ export default class ReactNativeBleTransport {
|
|
|
925
924
|
throw ERRORS.TypedError(HardwareErrorCode.BlePermissionError);
|
|
926
925
|
}
|
|
927
926
|
}
|
|
927
|
+
await subscribeBleOn(blePlxManager);
|
|
928
928
|
|
|
929
929
|
if (this.stopped) throw ERRORS.TypedError(HardwareErrorCode.BleDeviceDisconnected);
|
|
930
930
|
return new Promise<IOneKeyDevice[]>((resolve, reject) => {
|
|
@@ -967,14 +967,12 @@ export default class ReactNativeBleTransport {
|
|
|
967
967
|
(error, device) => {
|
|
968
968
|
if (error) {
|
|
969
969
|
Log?.debug('ble scan error: ', error);
|
|
970
|
-
if (
|
|
971
|
-
|
|
972
|
-
|
|
973
|
-
)
|
|
974
|
-
) {
|
|
975
|
-
finishScan(ERRORS.TypedError(HardwareErrorCode.BlePermissionError));
|
|
970
|
+
if (error.errorCode === BleErrorCode.BluetoothPoweredOff) {
|
|
971
|
+
finishScan(ERRORS.TypedError(HardwareErrorCode.BlePoweredOff));
|
|
972
|
+
} else if (error.errorCode === BleErrorCode.BluetoothUnsupported) {
|
|
973
|
+
finishScan(ERRORS.TypedError(HardwareErrorCode.BleUnsupported));
|
|
976
974
|
} else if (error.errorCode === BleErrorCode.BluetoothUnauthorized) {
|
|
977
|
-
finishScan(ERRORS.TypedError(HardwareErrorCode.
|
|
975
|
+
finishScan(ERRORS.TypedError(HardwareErrorCode.BlePermissionError));
|
|
978
976
|
} else if (error.errorCode === BleErrorCode.LocationServicesDisabled) {
|
|
979
977
|
finishScan(ERRORS.TypedError(HardwareErrorCode.BleLocationServicesDisabled));
|
|
980
978
|
} else if (error.errorCode === BleErrorCode.ScanStartFailed) {
|
|
@@ -2552,6 +2550,15 @@ export default class ReactNativeBleTransport {
|
|
|
2552
2550
|
throw this.createWedgedBleSetupError();
|
|
2553
2551
|
}
|
|
2554
2552
|
}
|
|
2553
|
+
if (isNativeBleStaleBondError(error) || isBleStaleBondHardwareError(error)) {
|
|
2554
|
+
throw toBleStaleBondHardwareError(error);
|
|
2555
|
+
}
|
|
2556
|
+
if (isNativeBleDisconnectError(error)) {
|
|
2557
|
+
if (Platform.OS === 'ios' && isIosPeerTerminationError(error)) {
|
|
2558
|
+
throw error;
|
|
2559
|
+
}
|
|
2560
|
+
throw toBleDisconnectHardwareError(error);
|
|
2561
|
+
}
|
|
2555
2562
|
if (Platform.OS === 'android' && isMissingGattShapeError(error)) {
|
|
2556
2563
|
this.androidGattCacheRefreshes.add(uuid);
|
|
2557
2564
|
}
|
package/src/subscribeBleOn.ts
CHANGED
|
@@ -4,23 +4,42 @@ import timer from './utils/timer';
|
|
|
4
4
|
|
|
5
5
|
import type { BlePlxManager } from './types';
|
|
6
6
|
|
|
7
|
-
export const subscribeBleOn = (bleManager: BlePlxManager, ms =
|
|
7
|
+
export const subscribeBleOn = (bleManager: BlePlxManager, ms = 2000): Promise<void> =>
|
|
8
8
|
new Promise((resolve, reject) => {
|
|
9
9
|
let done = false;
|
|
10
|
+
let pendingError: Error | undefined;
|
|
11
|
+
let cancelTimeout: () => void = () => undefined;
|
|
12
|
+
let removeSubscription: () => void = () => undefined;
|
|
13
|
+
|
|
14
|
+
const finish = (error?: Error) => {
|
|
15
|
+
if (done) return;
|
|
16
|
+
done = true;
|
|
17
|
+
cancelTimeout();
|
|
18
|
+
removeSubscription();
|
|
19
|
+
if (error) reject(error);
|
|
20
|
+
else resolve();
|
|
21
|
+
};
|
|
10
22
|
|
|
11
23
|
const subscription = bleManager.onStateChange(state => {
|
|
12
24
|
if (state === 'PoweredOn') {
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
25
|
+
finish();
|
|
26
|
+
} else if (state === 'PoweredOff') {
|
|
27
|
+
pendingError = ERRORS.TypedError(HardwareErrorCode.BlePoweredOff);
|
|
28
|
+
} else if (state === 'Unsupported') {
|
|
29
|
+
pendingError = ERRORS.TypedError(HardwareErrorCode.BleUnsupported);
|
|
30
|
+
} else if (state === 'Unauthorized') {
|
|
31
|
+
pendingError = ERRORS.TypedError(HardwareErrorCode.BlePermissionError);
|
|
32
|
+
} else {
|
|
33
|
+
pendingError = undefined;
|
|
18
34
|
}
|
|
19
35
|
}, true);
|
|
36
|
+
removeSubscription = () => subscription.remove();
|
|
20
37
|
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
38
|
+
if (done) {
|
|
39
|
+
removeSubscription();
|
|
40
|
+
} else {
|
|
41
|
+
cancelTimeout = timer.timeout(() => {
|
|
42
|
+
finish(pendingError ?? ERRORS.TypedError(HardwareErrorCode.BleScanError));
|
|
43
|
+
}, ms);
|
|
44
|
+
}
|
|
26
45
|
});
|