@onekeyfe/hd-core 1.2.0-alpha.133 → 1.2.0-alpha.133-ok59992
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/__tests__/DeviceCommands.test.ts +0 -7
- package/__tests__/device-lifecycle-events.test.ts +2 -91
- package/__tests__/device-settings.test.ts +9 -167
- package/__tests__/protocol-v2.test.ts +1 -34
- package/dist/api/device/DeviceSettings.d.ts.map +1 -1
- package/dist/api/protocol-v2/DeviceUploadWallpaper.d.ts.map +1 -1
- package/dist/core/index.d.ts +1 -3
- package/dist/core/index.d.ts.map +1 -1
- package/dist/device/Device.d.ts +0 -2
- package/dist/device/Device.d.ts.map +1 -1
- package/dist/device/DeviceCommands.d.ts.map +1 -1
- package/dist/index.d.ts +1 -4
- package/dist/index.js +189 -258
- package/package.json +4 -4
- package/src/api/device/DeviceSettings.ts +16 -2
- package/src/api/protocol-v2/DeviceUploadWallpaper.ts +0 -11
- package/src/core/index.ts +25 -67
- package/src/device/Device.ts +2 -30
- package/src/device/DeviceCommands.ts +1 -14
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@onekeyfe/hd-core",
|
|
3
|
-
"version": "1.2.0-alpha.133",
|
|
3
|
+
"version": "1.2.0-alpha.133-ok59992",
|
|
4
4
|
"description": "Core processes and APIs for communicating with OneKey hardware devices.",
|
|
5
5
|
"author": "OneKey",
|
|
6
6
|
"homepage": "https://github.com/OneKeyHQ/hardware-js-sdk#readme",
|
|
@@ -25,8 +25,8 @@
|
|
|
25
25
|
"url": "https://github.com/OneKeyHQ/hardware-js-sdk/issues"
|
|
26
26
|
},
|
|
27
27
|
"dependencies": {
|
|
28
|
-
"@onekeyfe/hd-shared": "1.2.0-alpha.133",
|
|
29
|
-
"@onekeyfe/hd-transport": "1.2.0-alpha.133",
|
|
28
|
+
"@onekeyfe/hd-shared": "1.2.0-alpha.133-ok59992",
|
|
29
|
+
"@onekeyfe/hd-transport": "1.2.0-alpha.133-ok59992",
|
|
30
30
|
"axios": "1.15.2",
|
|
31
31
|
"bignumber.js": "^9.0.2",
|
|
32
32
|
"buffer": "^6.0.3",
|
|
@@ -46,5 +46,5 @@
|
|
|
46
46
|
"@types/w3c-web-usb": "^1.0.10",
|
|
47
47
|
"@types/web-bluetooth": "^0.0.21"
|
|
48
48
|
},
|
|
49
|
-
"gitHead": "
|
|
49
|
+
"gitHead": "521eb4523f54abc5ceca28a48b7120158fea1ac0"
|
|
50
50
|
}
|
|
@@ -168,7 +168,8 @@ export default class DeviceSettings extends BaseMethod<ApplySettings> {
|
|
|
168
168
|
async run() {
|
|
169
169
|
try {
|
|
170
170
|
if (this.device.isProtocolV2()) {
|
|
171
|
-
const refreshStatusAndSettings = () =>
|
|
171
|
+
const refreshStatusAndSettings = () =>
|
|
172
|
+
this.device.getDeviceState({ refreshSections: ['status', 'settings'] });
|
|
172
173
|
assertSettingsSupported(this.payload, DEVICE_SETTINGS_V1_ONLY_FIELDS, 'Protocol V2');
|
|
173
174
|
const capabilities = getDeviceSettingsCapabilities(
|
|
174
175
|
this.device.getCurrentDeviceType(),
|
|
@@ -200,7 +201,20 @@ export default class DeviceSettings extends BaseMethod<ApplySettings> {
|
|
|
200
201
|
const res = await this.device.commands.typedCall('DeviceSettingsPageShow', 'Success', {
|
|
201
202
|
page: DeviceSettingsPage.DevicePassphrase,
|
|
202
203
|
});
|
|
203
|
-
await refreshStatusAndSettings();
|
|
204
|
+
const updated = await refreshStatusAndSettings();
|
|
205
|
+
const lockedAfterDisabling =
|
|
206
|
+
requestedPassphrase === false &&
|
|
207
|
+
current.status.unlocked === true &&
|
|
208
|
+
updated.status.unlocked === false;
|
|
209
|
+
if (
|
|
210
|
+
updated.status.passphraseProtection !== requestedPassphrase &&
|
|
211
|
+
!lockedAfterDisabling
|
|
212
|
+
) {
|
|
213
|
+
throw TypedError(
|
|
214
|
+
HardwareErrorCode.RuntimeError,
|
|
215
|
+
'Protocol V2 passphrase setting did not reach the requested value.'
|
|
216
|
+
);
|
|
217
|
+
}
|
|
204
218
|
return res.message;
|
|
205
219
|
}
|
|
206
220
|
if (requestedAirgap !== undefined) {
|
|
@@ -8,7 +8,6 @@ import { invalidParameter } from '../helpers/filesystemValidation';
|
|
|
8
8
|
import { writeProtocolV2File } from '../helpers/protocolV2FileWrite';
|
|
9
9
|
import { UI_REQUEST, createUiMessage } from '../../events/ui-request';
|
|
10
10
|
import { supportsProtocolV2Message } from '../../protocols/protocol-v2/features';
|
|
11
|
-
import { LoggerNames, getLogger } from '../../utils';
|
|
12
11
|
import {
|
|
13
12
|
PRO2_WALLPAPER_HEIGHT,
|
|
14
13
|
PRO2_WALLPAPER_WIDTH,
|
|
@@ -34,7 +33,6 @@ const SAFE_FILE_NAME = /^[A-Za-z0-9_-]+(?:\.bin)?$/;
|
|
|
34
33
|
const DEVICE_SETTINGS_SET_MESSAGE_TYPE = 60412;
|
|
35
34
|
const FILESYSTEM_FILE_WRITE_MESSAGE_TYPE = 60805;
|
|
36
35
|
const FILESYSTEM_DIR_MAKE_MESSAGE_TYPE = 60809;
|
|
37
|
-
const Log = getLogger(LoggerNames.Method);
|
|
38
36
|
|
|
39
37
|
function normalizeFileName(fileName: string | undefined, data: Uint8Array): string {
|
|
40
38
|
if (fileName !== undefined && (!fileName || !SAFE_FILE_NAME.test(fileName))) {
|
|
@@ -145,15 +143,6 @@ export default class DeviceUploadWallpaper extends BaseMethod<DeviceUploadWallpa
|
|
|
145
143
|
const response = await this.device.commands.typedCall('DeviceSettingsSet', 'Success', {
|
|
146
144
|
settings: { wallpaper_path: this.path },
|
|
147
145
|
});
|
|
148
|
-
try {
|
|
149
|
-
await this.device.refreshProtocolV2SettingsAfterMutation();
|
|
150
|
-
} catch (error) {
|
|
151
|
-
// The wallpaper is already applied. A transient read-back failure must not
|
|
152
|
-
// make callers retry the completed file upload.
|
|
153
|
-
Log.warn('Protocol V2 wallpaper settings refresh failed after apply', {
|
|
154
|
-
error: error instanceof Error ? error.message : String(error),
|
|
155
|
-
});
|
|
156
|
-
}
|
|
157
146
|
return {
|
|
158
147
|
path: this.path,
|
|
159
148
|
size: encoded.data.byteLength,
|
package/src/core/index.ts
CHANGED
|
@@ -83,7 +83,6 @@ import type { BaseMethod } from '../api/BaseMethod';
|
|
|
83
83
|
|
|
84
84
|
const Log = getLogger(LoggerNames.Core);
|
|
85
85
|
const PRE_INITIALIZE_TTL_MS = 60 * 1000;
|
|
86
|
-
const PRE_PENDING_CALL_TIMEOUT_MS = 15 * 1000;
|
|
87
86
|
|
|
88
87
|
// Dedup/coalesce state for "pre-warm signal" methods (isPreWarmSignal),
|
|
89
88
|
// keyed by getPreWarmKey(): coalesce in-flight, skip if warmed within TTL.
|
|
@@ -297,35 +296,26 @@ const handlePreWarmSignal = async (
|
|
|
297
296
|
}
|
|
298
297
|
};
|
|
299
298
|
|
|
299
|
+
const waitWithTimeout = async (promise: Promise<any>, timeout: number) => {
|
|
300
|
+
const timeoutPromise = new Promise((_, reject) => {
|
|
301
|
+
setTimeout(() => reject(new Error('Request timeout')), timeout);
|
|
302
|
+
});
|
|
303
|
+
return Promise.race([promise, timeoutPromise]);
|
|
304
|
+
};
|
|
305
|
+
|
|
300
306
|
const waitForPendingPromise = async (
|
|
301
|
-
|
|
302
|
-
|
|
303
|
-
removePrePendingCallPromise?: (connectId: string, promise: Promise<void>) => void
|
|
307
|
+
getPrePendingCallPromise: () => Promise<void> | undefined,
|
|
308
|
+
removePrePendingCallPromise?: (promise: Promise<void> | undefined) => void
|
|
304
309
|
) => {
|
|
305
|
-
const pendingPromise = getPrePendingCallPromise(
|
|
310
|
+
const pendingPromise = getPrePendingCallPromise();
|
|
306
311
|
if (pendingPromise) {
|
|
307
312
|
Log.debug('pre pending call promise before call method, wait for it');
|
|
308
|
-
let timer: ReturnType<typeof setTimeout> | undefined;
|
|
309
|
-
let timedOut = false;
|
|
310
313
|
try {
|
|
311
|
-
await
|
|
312
|
-
pendingPromise,
|
|
313
|
-
new Promise<void>(resolve => {
|
|
314
|
-
timer = setTimeout(() => {
|
|
315
|
-
timedOut = true;
|
|
316
|
-
resolve();
|
|
317
|
-
}, PRE_PENDING_CALL_TIMEOUT_MS);
|
|
318
|
-
}),
|
|
319
|
-
]);
|
|
314
|
+
await waitWithTimeout(pendingPromise, 5 * 1000);
|
|
320
315
|
} catch (error) {
|
|
321
|
-
//
|
|
322
|
-
} finally {
|
|
323
|
-
if (timer) clearTimeout(timer);
|
|
324
|
-
removePrePendingCallPromise?.(connectId, pendingPromise);
|
|
325
|
-
}
|
|
326
|
-
if (timedOut) {
|
|
327
|
-
Log.warn('pre pending call promise timed out before call method', { connectId });
|
|
316
|
+
// ignore timeout error
|
|
328
317
|
}
|
|
318
|
+
removePrePendingCallPromise?.(pendingPromise);
|
|
329
319
|
Log.debug('pre pending call promise before call method done');
|
|
330
320
|
}
|
|
331
321
|
};
|
|
@@ -337,7 +327,7 @@ const onCallDevice = async (
|
|
|
337
327
|
): Promise<any> => {
|
|
338
328
|
let messageResponse: any;
|
|
339
329
|
|
|
340
|
-
const { requestQueue, getPrePendingCallPromise,
|
|
330
|
+
const { requestQueue, getPrePendingCallPromise, setPrePendingCallPromise } = context;
|
|
341
331
|
|
|
342
332
|
updateMethodRequestContext(method, { status: 'running' });
|
|
343
333
|
|
|
@@ -365,11 +355,7 @@ const onCallDevice = async (
|
|
|
365
355
|
await context.waitForCallbackTasks(method.connectId);
|
|
366
356
|
}
|
|
367
357
|
|
|
368
|
-
await waitForPendingPromise(
|
|
369
|
-
method.connectId ?? '',
|
|
370
|
-
getPrePendingCallPromise,
|
|
371
|
-
removePrePendingCallPromise
|
|
372
|
-
);
|
|
358
|
+
await waitForPendingPromise(getPrePendingCallPromise, setPrePendingCallPromise);
|
|
373
359
|
|
|
374
360
|
const task = requestQueue.createTask(method);
|
|
375
361
|
|
|
@@ -468,11 +454,7 @@ const onCallDevice = async (
|
|
|
468
454
|
await context.waitForCallbackTasks(method.connectId, preWarmCallbackTask);
|
|
469
455
|
}
|
|
470
456
|
|
|
471
|
-
await waitForPendingPromise(
|
|
472
|
-
method.connectId ?? '',
|
|
473
|
-
getPrePendingCallPromise,
|
|
474
|
-
removePrePendingCallPromise
|
|
475
|
-
);
|
|
457
|
+
await waitForPendingPromise(getPrePendingCallPromise, setPrePendingCallPromise);
|
|
476
458
|
|
|
477
459
|
const inner = async (): Promise<void> => {
|
|
478
460
|
// Protocol is established from an active device response during acquire/initialize.
|
|
@@ -924,16 +906,6 @@ function isRetryableBleProtocolV2ProbeError(method: BaseMethod, error: unknown)
|
|
|
924
906
|
);
|
|
925
907
|
}
|
|
926
908
|
|
|
927
|
-
export function isMissingDetectedProtocolV2Error(method: BaseMethod, error: unknown) {
|
|
928
|
-
const typedError = error as { errorCode?: unknown; message?: unknown };
|
|
929
|
-
return (
|
|
930
|
-
method.payload.connectProtocol === 'V2' &&
|
|
931
|
-
typedError?.errorCode === HardwareErrorCode.RuntimeError &&
|
|
932
|
-
typeof typedError.message === 'string' &&
|
|
933
|
-
typedError.message.includes('Device protocol has not been detected')
|
|
934
|
-
);
|
|
935
|
-
}
|
|
936
|
-
|
|
937
909
|
/**
|
|
938
910
|
* If the Bluetooth connection times out, retry up to 6 times
|
|
939
911
|
* @param retryCount - Current retry count (default 0)
|
|
@@ -971,13 +943,12 @@ async function connectDeviceForBle(method: BaseMethod, device: Device, retryCoun
|
|
|
971
943
|
DevicePool.emitter.emit(DEVICE.CONNECT, device);
|
|
972
944
|
}
|
|
973
945
|
} catch (err) {
|
|
974
|
-
const requiresColdReconnect = isMissingDetectedProtocolV2Error(method, err);
|
|
975
946
|
// Device.run()'s REQUIRE_DISCONNECT handling never sees acquire/initialize
|
|
976
947
|
// failures, so with keep-alive a wedged link would be reused by every retry
|
|
977
948
|
// (field case: Initialize timing out at 25s per attempt, forever). Drop it
|
|
978
949
|
// here so the next retry cold-connects.
|
|
979
950
|
if (
|
|
980
|
-
|
|
951
|
+
ERROR_CODES_REQUIRE_DISCONNECT.includes(err.errorCode) &&
|
|
981
952
|
device.mainId &&
|
|
982
953
|
device.deviceConnector
|
|
983
954
|
) {
|
|
@@ -990,12 +961,11 @@ async function connectDeviceForBle(method: BaseMethod, device: Device, retryCoun
|
|
|
990
961
|
if (
|
|
991
962
|
(err.errorCode === HardwareErrorCode.BleTimeoutError ||
|
|
992
963
|
err.errorCode === HardwareErrorCode.BleConnectedError ||
|
|
993
|
-
isRetryableBleProtocolV2ProbeError(method, err)
|
|
994
|
-
requiresColdReconnect) &&
|
|
964
|
+
isRetryableBleProtocolV2ProbeError(method, err)) &&
|
|
995
965
|
retryCount < 6
|
|
996
966
|
) {
|
|
997
967
|
const nextRetry = retryCount + 1;
|
|
998
|
-
Log.debug(`Bluetooth
|
|
968
|
+
Log.debug(`Bluetooth connect timeout and will retry, retry count: ${nextRetry}`);
|
|
999
969
|
await wait(3000);
|
|
1000
970
|
await connectDeviceForBle(method, device, nextRetry);
|
|
1001
971
|
} else {
|
|
@@ -1207,10 +1177,7 @@ export const cancel = (context: CoreContext, connectId?: string) => {
|
|
|
1207
1177
|
if (task && task.method?.device) {
|
|
1208
1178
|
if (!canceledDevices.includes(task.method.device)) {
|
|
1209
1179
|
const { device } = task.method;
|
|
1210
|
-
setPrePendingCallPromise(
|
|
1211
|
-
task.method.connectId ?? connectId,
|
|
1212
|
-
device.interruptionFromUser()
|
|
1213
|
-
);
|
|
1180
|
+
setPrePendingCallPromise(device?.interruptionFromUser());
|
|
1214
1181
|
canceledDevices.push(device);
|
|
1215
1182
|
}
|
|
1216
1183
|
requestQueue.rejectRequest(
|
|
@@ -1564,7 +1531,7 @@ export default class Core extends EventEmitter {
|
|
|
1564
1531
|
private disposePromise?: Promise<void>;
|
|
1565
1532
|
|
|
1566
1533
|
// background task
|
|
1567
|
-
private
|
|
1534
|
+
private prePendingCallPromise: Promise<void> | undefined;
|
|
1568
1535
|
|
|
1569
1536
|
private methodSynchronize = getSynchronize();
|
|
1570
1537
|
|
|
@@ -1581,18 +1548,9 @@ export default class Core extends EventEmitter {
|
|
|
1581
1548
|
tracingContext: this.tracingContext,
|
|
1582
1549
|
requestQueue: this.requestQueue,
|
|
1583
1550
|
methodSynchronize: this.methodSynchronize,
|
|
1584
|
-
getPrePendingCallPromise: (
|
|
1585
|
-
setPrePendingCallPromise: (
|
|
1586
|
-
|
|
1587
|
-
this.prePendingCallPromises.delete(connectId);
|
|
1588
|
-
return;
|
|
1589
|
-
}
|
|
1590
|
-
this.prePendingCallPromises.set(connectId, promise);
|
|
1591
|
-
},
|
|
1592
|
-
removePrePendingCallPromise: (connectId: string, promise: Promise<void>) => {
|
|
1593
|
-
if (this.prePendingCallPromises.get(connectId) === promise) {
|
|
1594
|
-
this.prePendingCallPromises.delete(connectId);
|
|
1595
|
-
}
|
|
1551
|
+
getPrePendingCallPromise: () => this.prePendingCallPromise,
|
|
1552
|
+
setPrePendingCallPromise: (promise: Promise<void> | undefined) => {
|
|
1553
|
+
this.prePendingCallPromise = promise;
|
|
1596
1554
|
},
|
|
1597
1555
|
// callback 任务管理
|
|
1598
1556
|
registerCallbackTask: (connectId: string, callbackPromise: Deferred<any>) => {
|
|
@@ -1707,7 +1665,7 @@ export default class Core extends EventEmitter {
|
|
|
1707
1665
|
preWarmInflight.clear();
|
|
1708
1666
|
preWarmDoneAt.clear();
|
|
1709
1667
|
preConnectCache = { passphraseState: undefined };
|
|
1710
|
-
this.
|
|
1668
|
+
this.prePendingCallPromise = undefined;
|
|
1711
1669
|
this.removeAllListeners();
|
|
1712
1670
|
cleanupSdkInstance(this.sdkInstanceId);
|
|
1713
1671
|
if (_core === this) _core = undefined;
|
package/src/device/Device.ts
CHANGED
|
@@ -284,9 +284,6 @@ export class Device extends EventEmitter {
|
|
|
284
284
|
|
|
285
285
|
runPromise?: Deferred<void> | null;
|
|
286
286
|
|
|
287
|
-
/** Resolves only after the active run has completed its release path. */
|
|
288
|
-
private runCleanupPromise?: Promise<void>;
|
|
289
|
-
|
|
290
287
|
externalState: string[] = [];
|
|
291
288
|
|
|
292
289
|
unavailableCapabilities: UnavailableCapabilities = {};
|
|
@@ -1082,10 +1079,6 @@ export class Device extends EventEmitter {
|
|
|
1082
1079
|
return params.includeRaw ? cloneDeviceState(this.state) : createPublicDeviceState(this.state);
|
|
1083
1080
|
}
|
|
1084
1081
|
|
|
1085
|
-
async refreshProtocolV2SettingsAfterMutation() {
|
|
1086
|
-
return this.getDeviceState({ refreshSections: ['status', 'settings'] });
|
|
1087
|
-
}
|
|
1088
|
-
|
|
1089
1082
|
_updateFeatures(protoFeatures: PROTO.Features | Features, initSession?: boolean) {
|
|
1090
1083
|
const previousDeviceId = this.getCurrentDeviceId();
|
|
1091
1084
|
let feat =
|
|
@@ -1403,20 +1396,12 @@ export class Device extends EventEmitter {
|
|
|
1403
1396
|
|
|
1404
1397
|
const runPromise = createDeferred<void>();
|
|
1405
1398
|
this.runPromise = runPromise;
|
|
1406
|
-
|
|
1399
|
+
this._runInner(fn, options, runPromise).catch(error => {
|
|
1407
1400
|
if (this.runPromise === runPromise) {
|
|
1408
1401
|
this.runPromise = null;
|
|
1409
1402
|
}
|
|
1410
1403
|
runPromise.reject(error);
|
|
1411
1404
|
});
|
|
1412
|
-
this.runCleanupPromise = cleanupPromise;
|
|
1413
|
-
cleanupPromise
|
|
1414
|
-
.finally(() => {
|
|
1415
|
-
if (this.runCleanupPromise === cleanupPromise) {
|
|
1416
|
-
this.runCleanupPromise = undefined;
|
|
1417
|
-
}
|
|
1418
|
-
})
|
|
1419
|
-
.catch(() => undefined);
|
|
1420
1405
|
return runPromise.promise;
|
|
1421
1406
|
}
|
|
1422
1407
|
|
|
@@ -1528,26 +1513,13 @@ export class Device extends EventEmitter {
|
|
|
1528
1513
|
|
|
1529
1514
|
async interruptionFromUser() {
|
|
1530
1515
|
const error = ERRORS.TypedError(HardwareErrorCode.DeviceInterruptedFromUser);
|
|
1531
|
-
|
|
1532
|
-
const { cancelableAction } = this;
|
|
1533
|
-
if (cancelableAction) {
|
|
1534
|
-
await cancelableAction(error);
|
|
1535
|
-
} else if (
|
|
1536
|
-
this.isProtocolV2() &&
|
|
1537
|
-
DataManager.isBleConnect(DataManager.getSettings('env')) &&
|
|
1538
|
-
this.hasDeviceAcquire()
|
|
1539
|
-
) {
|
|
1540
|
-
await this.commands?.cancelDevice?.().catch(cancelError => {
|
|
1541
|
-
Log.debug('Protocol V2 BLE fallback cancel error', cancelError);
|
|
1542
|
-
});
|
|
1543
|
-
}
|
|
1516
|
+
await this.cancelableAction?.(error);
|
|
1544
1517
|
await this.commands?.cancel();
|
|
1545
1518
|
|
|
1546
1519
|
if (this.runPromise) {
|
|
1547
1520
|
this.runPromise.reject(error);
|
|
1548
1521
|
this.runPromise = null;
|
|
1549
1522
|
}
|
|
1550
|
-
await cleanupPromise?.catch(() => undefined);
|
|
1551
1523
|
}
|
|
1552
1524
|
|
|
1553
1525
|
setCancelableAction(callback: (err?: Error) => Promise<unknown>) {
|
|
@@ -264,7 +264,6 @@ export class DeviceCommands {
|
|
|
264
264
|
}
|
|
265
265
|
const activeCall = this.callPromise;
|
|
266
266
|
let timer: ReturnType<typeof setTimeout> | undefined;
|
|
267
|
-
let timedOut = false;
|
|
268
267
|
const cancellation = (async () => {
|
|
269
268
|
await this.dispose(true);
|
|
270
269
|
await activeCall?.catch(() => undefined);
|
|
@@ -274,23 +273,11 @@ export class DeviceCommands {
|
|
|
274
273
|
await Promise.race([
|
|
275
274
|
cancellation,
|
|
276
275
|
new Promise<void>(resolve => {
|
|
277
|
-
timer = setTimeout(
|
|
278
|
-
timedOut = true;
|
|
279
|
-
resolve();
|
|
280
|
-
}, 10 * 1000);
|
|
276
|
+
timer = setTimeout(resolve, 10 * 1000);
|
|
281
277
|
}),
|
|
282
278
|
]);
|
|
283
279
|
} finally {
|
|
284
280
|
if (timer) clearTimeout(timer);
|
|
285
|
-
if (
|
|
286
|
-
timedOut &&
|
|
287
|
-
this.transport.name === 'ReactNativeBleTransport' &&
|
|
288
|
-
this.transport.disconnect
|
|
289
|
-
) {
|
|
290
|
-
await this.transport.disconnect(this.mainId).catch(error => {
|
|
291
|
-
Log.debug('BLE cancellation timeout disconnect error (ignored)', error);
|
|
292
|
-
});
|
|
293
|
-
}
|
|
294
281
|
if (this.callPromise === activeCall) {
|
|
295
282
|
this.callPromise = undefined;
|
|
296
283
|
}
|