@onekeyfe/hd-core 1.2.0 → 1.2.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/__tests__/firmware-update/firmware-update-v4-install-poll.test.ts +322 -21
- package/__tests__/protocol-v2.test.ts +1 -0
- package/dist/api/FirmwareUpdateV4.d.ts +1 -0
- package/dist/api/FirmwareUpdateV4.d.ts.map +1 -1
- package/dist/index.js +26 -10
- package/package.json +4 -4
- package/src/api/FirmwareUpdateV4.ts +31 -13
|
@@ -335,7 +335,97 @@ describe('FirmwareUpdateV4 install polling', () => {
|
|
|
335
335
|
expect(method.postProgressMessage).toHaveBeenCalledWith(100, 'installingFirmware');
|
|
336
336
|
});
|
|
337
337
|
|
|
338
|
-
test(
|
|
338
|
+
test.each([
|
|
339
|
+
{
|
|
340
|
+
component: 'boot',
|
|
341
|
+
targets: [{ target_id: 3, path: 'vol0:/bootloader.bin' }],
|
|
342
|
+
},
|
|
343
|
+
{
|
|
344
|
+
component: 'P1',
|
|
345
|
+
targets: [{ target_id: 4, path: 'vol0:/application_p1.bin' }],
|
|
346
|
+
},
|
|
347
|
+
{
|
|
348
|
+
component: 'P2',
|
|
349
|
+
targets: [{ target_id: 5, path: 'vol0:/application_p2.bin' }],
|
|
350
|
+
},
|
|
351
|
+
{
|
|
352
|
+
component: 'coprocessor',
|
|
353
|
+
targets: [{ target_id: 6, path: 'vol0:/coprocessor.bin' }],
|
|
354
|
+
},
|
|
355
|
+
{
|
|
356
|
+
component: 'SE',
|
|
357
|
+
targets: [
|
|
358
|
+
{ target_id: 7, path: 'vol0:/se01.bin' },
|
|
359
|
+
{ target_id: 8, path: 'vol0:/se02.bin' },
|
|
360
|
+
{ target_id: 9, path: 'vol0:/se03.bin' },
|
|
361
|
+
{ target_id: 10, path: 'vol0:/se04.bin' },
|
|
362
|
+
],
|
|
363
|
+
},
|
|
364
|
+
])(
|
|
365
|
+
'accepts stable finished BLE status for $component after an actual install disconnect hides in-progress',
|
|
366
|
+
async ({ targets }) => {
|
|
367
|
+
const method = new FirmwareUpdateV4({
|
|
368
|
+
id: 1,
|
|
369
|
+
payload: {
|
|
370
|
+
method: 'firmwareUpdateV4',
|
|
371
|
+
connectId: 'pro2-ble',
|
|
372
|
+
},
|
|
373
|
+
});
|
|
374
|
+
const finishedStatus = {
|
|
375
|
+
type: 'DeviceFirmwareUpdateStatus',
|
|
376
|
+
message: {
|
|
377
|
+
records: targets.map(target => ({
|
|
378
|
+
...target,
|
|
379
|
+
status: 'FW_MGMT_UPDATER_TASK_STATUS_FINISHED',
|
|
380
|
+
})),
|
|
381
|
+
},
|
|
382
|
+
};
|
|
383
|
+
const typedCall = jest
|
|
384
|
+
.fn()
|
|
385
|
+
.mockResolvedValueOnce(finishedStatus)
|
|
386
|
+
.mockImplementationOnce(() => {
|
|
387
|
+
expect(method.postProgressMessage).not.toHaveBeenCalled();
|
|
388
|
+
throw new Error('device was disconnected');
|
|
389
|
+
})
|
|
390
|
+
.mockResolvedValueOnce(finishedStatus)
|
|
391
|
+
.mockImplementationOnce(() => {
|
|
392
|
+
expect(method.postProgressMessage).toHaveBeenCalledTimes(1);
|
|
393
|
+
expect(method.postProgressMessage).toHaveBeenCalledWith(1, 'installingFirmware');
|
|
394
|
+
return finishedStatus;
|
|
395
|
+
})
|
|
396
|
+
.mockResolvedValueOnce(finishedStatus)
|
|
397
|
+
.mockResolvedValueOnce(finishedStatus)
|
|
398
|
+
.mockRejectedValueOnce(ERRORS.TypedError(HardwareErrorCode.ActionCancelled));
|
|
399
|
+
const reconnectProtocolV2Device = jest.fn().mockResolvedValue(undefined);
|
|
400
|
+
|
|
401
|
+
method.device = {
|
|
402
|
+
getCommands: () => ({ typedCall }),
|
|
403
|
+
setCancelableAction: jest.fn(),
|
|
404
|
+
} as unknown as Device;
|
|
405
|
+
method.postProgressMessage = jest.fn();
|
|
406
|
+
|
|
407
|
+
const firmwareUpdate = method as unknown as {
|
|
408
|
+
waitForProtocolV2FirmwareUpdateComplete: (
|
|
409
|
+
value: typeof targets,
|
|
410
|
+
requireCurrentInstallStatus: boolean
|
|
411
|
+
) => Promise<void>;
|
|
412
|
+
reconnectProtocolV2Device: (options: { skipProtocolProbe: boolean }) => Promise<void>;
|
|
413
|
+
};
|
|
414
|
+
firmwareUpdate.reconnectProtocolV2Device = reconnectProtocolV2Device;
|
|
415
|
+
(method as any).isBleReconnect = jest.fn(() => true);
|
|
416
|
+
|
|
417
|
+
await firmwareUpdate.waitForProtocolV2FirmwareUpdateComplete(targets, true);
|
|
418
|
+
|
|
419
|
+
expect(reconnectProtocolV2Device).toHaveBeenCalledWith({ skipProtocolProbe: true });
|
|
420
|
+
expect(typedCall).toHaveBeenCalledTimes(6);
|
|
421
|
+
expect(method.postProgressMessage).toHaveBeenNthCalledWith(1, 1, 'installingFirmware');
|
|
422
|
+
expect(method.postProgressMessage).toHaveBeenNthCalledWith(2, 100, 'installingFirmware');
|
|
423
|
+
expect(method.postProgressMessage).toHaveBeenCalledTimes(2);
|
|
424
|
+
},
|
|
425
|
+
10_000
|
|
426
|
+
);
|
|
427
|
+
|
|
428
|
+
test('uses a real BLE disconnect while writing the Request as install evidence', async () => {
|
|
339
429
|
const method = new FirmwareUpdateV4({
|
|
340
430
|
id: 1,
|
|
341
431
|
payload: {
|
|
@@ -343,49 +433,41 @@ describe('FirmwareUpdateV4 install polling', () => {
|
|
|
343
433
|
connectId: 'pro2-ble',
|
|
344
434
|
},
|
|
345
435
|
});
|
|
346
|
-
const targets = [{ target_id:
|
|
436
|
+
const targets = [{ target_id: 3, path: 'vol0:/bootloader.bin' }];
|
|
347
437
|
const finishedStatus = {
|
|
348
438
|
type: 'DeviceFirmwareUpdateStatus',
|
|
349
439
|
message: {
|
|
350
440
|
records: [
|
|
351
441
|
{
|
|
352
|
-
|
|
442
|
+
...targets[0],
|
|
353
443
|
status: 'FW_MGMT_UPDATER_TASK_STATUS_FINISHED',
|
|
354
|
-
payload_version: 65_556,
|
|
355
|
-
path: 'vol0:/coprocessor.bin',
|
|
356
444
|
},
|
|
357
445
|
],
|
|
358
446
|
},
|
|
359
447
|
};
|
|
360
448
|
const typedCall = jest
|
|
361
449
|
.fn()
|
|
450
|
+
.mockResolvedValueOnce({ type: 'Success', message: {} })
|
|
362
451
|
.mockResolvedValueOnce(finishedStatus)
|
|
363
|
-
.mockImplementationOnce(() => {
|
|
364
|
-
expect(method.postProgressMessage).not.toHaveBeenCalled();
|
|
365
|
-
throw new Error('device was disconnected');
|
|
366
|
-
})
|
|
367
452
|
.mockResolvedValueOnce(finishedStatus)
|
|
368
|
-
.mockImplementationOnce(() => {
|
|
369
|
-
expect(method.postProgressMessage).toHaveBeenCalledTimes(1);
|
|
370
|
-
expect(method.postProgressMessage).toHaveBeenCalledWith(1, 'installingFirmware');
|
|
371
|
-
return finishedStatus;
|
|
372
|
-
})
|
|
373
453
|
.mockResolvedValueOnce(finishedStatus)
|
|
374
454
|
.mockResolvedValueOnce(finishedStatus)
|
|
375
455
|
.mockRejectedValueOnce(ERRORS.TypedError(HardwareErrorCode.ActionCancelled));
|
|
456
|
+
const call = jest.fn().mockRejectedValue(ERRORS.TypedError(HardwareErrorCode.BleTimeoutError));
|
|
376
457
|
const reconnectProtocolV2Device = jest.fn().mockResolvedValue(undefined);
|
|
377
458
|
|
|
378
|
-
(method as any).params = {
|
|
379
|
-
expectedTargetVersions: { coprocessor: '1.0.20' },
|
|
380
|
-
};
|
|
381
|
-
|
|
382
459
|
method.device = {
|
|
383
|
-
getCommands: () => ({ typedCall }),
|
|
460
|
+
getCommands: () => ({ typedCall, call, cancelDevice: jest.fn() }),
|
|
461
|
+
createProtocolV2UiPhaseMetadata: jest.fn().mockReturnValue(undefined),
|
|
462
|
+
toMessageObject: jest.fn().mockReturnValue({ connectId: 'pro2-ble' }),
|
|
384
463
|
setCancelableAction: jest.fn(),
|
|
464
|
+
clearCancelableAction: jest.fn(),
|
|
385
465
|
} as unknown as Device;
|
|
466
|
+
method.postMessage = jest.fn();
|
|
386
467
|
method.postProgressMessage = jest.fn();
|
|
387
468
|
|
|
388
469
|
const firmwareUpdate = method as unknown as {
|
|
470
|
+
protocolV2StartFirmwareUpdate: (params: { targets: typeof targets }) => Promise<void>;
|
|
389
471
|
waitForProtocolV2FirmwareUpdateComplete: (
|
|
390
472
|
value: typeof targets,
|
|
391
473
|
requireCurrentInstallStatus: boolean
|
|
@@ -395,15 +477,234 @@ describe('FirmwareUpdateV4 install polling', () => {
|
|
|
395
477
|
firmwareUpdate.reconnectProtocolV2Device = reconnectProtocolV2Device;
|
|
396
478
|
(method as any).isBleReconnect = jest.fn(() => true);
|
|
397
479
|
|
|
480
|
+
await firmwareUpdate.protocolV2StartFirmwareUpdate({ targets });
|
|
398
481
|
await firmwareUpdate.waitForProtocolV2FirmwareUpdateComplete(targets, true);
|
|
399
482
|
|
|
400
483
|
expect(reconnectProtocolV2Device).toHaveBeenCalledWith({ skipProtocolProbe: true });
|
|
401
|
-
expect(typedCall).toHaveBeenCalledTimes(6);
|
|
402
484
|
expect(method.postProgressMessage).toHaveBeenNthCalledWith(1, 1, 'installingFirmware');
|
|
403
485
|
expect(method.postProgressMessage).toHaveBeenNthCalledWith(2, 100, 'installingFirmware');
|
|
404
|
-
expect(
|
|
486
|
+
expect(typedCall).toHaveBeenCalledTimes(5);
|
|
487
|
+
}, 10_000);
|
|
488
|
+
|
|
489
|
+
test('does not use a Request response timeout as BLE install evidence', async () => {
|
|
490
|
+
const method = new FirmwareUpdateV4({
|
|
491
|
+
id: 1,
|
|
492
|
+
payload: {
|
|
493
|
+
method: 'firmwareUpdateV4',
|
|
494
|
+
connectId: 'pro2-ble',
|
|
495
|
+
},
|
|
496
|
+
});
|
|
497
|
+
const targets = [{ target_id: 3, path: 'vol0:/bootloader.bin' }];
|
|
498
|
+
const finishedStatus = {
|
|
499
|
+
type: 'DeviceFirmwareUpdateStatus',
|
|
500
|
+
message: {
|
|
501
|
+
records: [
|
|
502
|
+
{
|
|
503
|
+
...targets[0],
|
|
504
|
+
status: 'FW_MGMT_UPDATER_TASK_STATUS_FINISHED',
|
|
505
|
+
},
|
|
506
|
+
],
|
|
507
|
+
},
|
|
508
|
+
};
|
|
509
|
+
const typedCall = jest
|
|
510
|
+
.fn()
|
|
511
|
+
.mockResolvedValueOnce({ type: 'Success', message: {} })
|
|
512
|
+
.mockResolvedValueOnce(finishedStatus)
|
|
513
|
+
.mockResolvedValueOnce(finishedStatus)
|
|
514
|
+
.mockResolvedValueOnce(finishedStatus)
|
|
515
|
+
.mockResolvedValueOnce(finishedStatus)
|
|
516
|
+
.mockRejectedValueOnce(ERRORS.TypedError(HardwareErrorCode.ActionCancelled));
|
|
517
|
+
const call = jest
|
|
518
|
+
.fn()
|
|
519
|
+
.mockRejectedValue(
|
|
520
|
+
ERRORS.TypedError(
|
|
521
|
+
HardwareErrorCode.BleTimeoutError,
|
|
522
|
+
'device was disconnected after Lowlevel response timeout'
|
|
523
|
+
)
|
|
524
|
+
);
|
|
525
|
+
const reconnectProtocolV2Device = jest.fn().mockResolvedValue(undefined);
|
|
526
|
+
|
|
527
|
+
method.device = {
|
|
528
|
+
getCommands: () => ({ typedCall, call, cancelDevice: jest.fn() }),
|
|
529
|
+
createProtocolV2UiPhaseMetadata: jest.fn().mockReturnValue(undefined),
|
|
530
|
+
toMessageObject: jest.fn().mockReturnValue({ connectId: 'pro2-ble' }),
|
|
531
|
+
setCancelableAction: jest.fn(),
|
|
532
|
+
clearCancelableAction: jest.fn(),
|
|
533
|
+
} as unknown as Device;
|
|
534
|
+
method.postMessage = jest.fn();
|
|
535
|
+
method.postProgressMessage = jest.fn();
|
|
536
|
+
|
|
537
|
+
const firmwareUpdate = method as unknown as {
|
|
538
|
+
protocolV2StartFirmwareUpdate: (params: { targets: typeof targets }) => Promise<void>;
|
|
539
|
+
waitForProtocolV2FirmwareUpdateComplete: (
|
|
540
|
+
value: typeof targets,
|
|
541
|
+
requireCurrentInstallStatus: boolean
|
|
542
|
+
) => Promise<void>;
|
|
543
|
+
reconnectProtocolV2Device: (options: { skipProtocolProbe: boolean }) => Promise<void>;
|
|
544
|
+
};
|
|
545
|
+
firmwareUpdate.reconnectProtocolV2Device = reconnectProtocolV2Device;
|
|
546
|
+
(method as any).isBleReconnect = jest.fn(() => true);
|
|
547
|
+
|
|
548
|
+
await firmwareUpdate.protocolV2StartFirmwareUpdate({ targets });
|
|
549
|
+
await expect(
|
|
550
|
+
firmwareUpdate.waitForProtocolV2FirmwareUpdateComplete(targets, true)
|
|
551
|
+
).rejects.toMatchObject({
|
|
552
|
+
errorCode: HardwareErrorCode.ActionCancelled,
|
|
553
|
+
});
|
|
554
|
+
|
|
555
|
+
expect(reconnectProtocolV2Device).toHaveBeenCalledWith({ skipProtocolProbe: true });
|
|
556
|
+
expect(method.postProgressMessage).not.toHaveBeenCalled();
|
|
405
557
|
}, 10_000);
|
|
406
558
|
|
|
559
|
+
test('records a real BLE disconnect that occurs during install reconnect', async () => {
|
|
560
|
+
const method = new FirmwareUpdateV4({
|
|
561
|
+
id: 1,
|
|
562
|
+
payload: {
|
|
563
|
+
method: 'firmwareUpdateV4',
|
|
564
|
+
connectId: 'pro2-ble',
|
|
565
|
+
},
|
|
566
|
+
});
|
|
567
|
+
const targets = [{ target_id: 3, path: 'vol0:/bootloader.bin' }];
|
|
568
|
+
const finishedStatus = {
|
|
569
|
+
type: 'DeviceFirmwareUpdateStatus',
|
|
570
|
+
message: {
|
|
571
|
+
records: [
|
|
572
|
+
{
|
|
573
|
+
...targets[0],
|
|
574
|
+
status: 'FW_MGMT_UPDATER_TASK_STATUS_FINISHED',
|
|
575
|
+
},
|
|
576
|
+
],
|
|
577
|
+
},
|
|
578
|
+
};
|
|
579
|
+
const typedCall = jest
|
|
580
|
+
.fn()
|
|
581
|
+
.mockRejectedValueOnce(
|
|
582
|
+
ERRORS.TypedError(
|
|
583
|
+
HardwareErrorCode.BleTimeoutError,
|
|
584
|
+
'Lowlevel response timeout after 15000ms for DeviceFirmwareUpdateStatusGet'
|
|
585
|
+
)
|
|
586
|
+
)
|
|
587
|
+
.mockResolvedValueOnce(finishedStatus)
|
|
588
|
+
.mockResolvedValueOnce(finishedStatus)
|
|
589
|
+
.mockResolvedValueOnce(finishedStatus)
|
|
590
|
+
.mockResolvedValueOnce(finishedStatus);
|
|
591
|
+
const reconnectProtocolV2Device = jest
|
|
592
|
+
.fn()
|
|
593
|
+
.mockRejectedValueOnce(ERRORS.TypedError(HardwareErrorCode.BleTimeoutError))
|
|
594
|
+
.mockResolvedValueOnce(undefined);
|
|
595
|
+
const setTimeoutSpy = jest.spyOn(global, 'setTimeout').mockImplementation(((
|
|
596
|
+
callback: () => void
|
|
597
|
+
) => {
|
|
598
|
+
callback();
|
|
599
|
+
return 0 as any;
|
|
600
|
+
}) as typeof setTimeout);
|
|
601
|
+
|
|
602
|
+
method.device = {
|
|
603
|
+
getCommands: () => ({ typedCall, cancelDevice: jest.fn() }),
|
|
604
|
+
setCancelableAction: jest.fn(),
|
|
605
|
+
} as unknown as Device;
|
|
606
|
+
method.postProgressMessage = jest.fn();
|
|
607
|
+
|
|
608
|
+
const firmwareUpdate = method as unknown as {
|
|
609
|
+
waitForProtocolV2FirmwareUpdateComplete: (
|
|
610
|
+
value: typeof targets,
|
|
611
|
+
requireCurrentInstallStatus: boolean
|
|
612
|
+
) => Promise<void>;
|
|
613
|
+
reconnectProtocolV2Device: (options: { skipProtocolProbe: boolean }) => Promise<void>;
|
|
614
|
+
};
|
|
615
|
+
firmwareUpdate.reconnectProtocolV2Device = reconnectProtocolV2Device;
|
|
616
|
+
(method as any).isBleReconnect = jest.fn(() => true);
|
|
617
|
+
|
|
618
|
+
try {
|
|
619
|
+
await firmwareUpdate.waitForProtocolV2FirmwareUpdateComplete(targets, true);
|
|
620
|
+
} finally {
|
|
621
|
+
setTimeoutSpy.mockRestore();
|
|
622
|
+
}
|
|
623
|
+
|
|
624
|
+
expect(reconnectProtocolV2Device).toHaveBeenCalledTimes(2);
|
|
625
|
+
expect(method.postProgressMessage).toHaveBeenNthCalledWith(1, 1, 'installingFirmware');
|
|
626
|
+
expect(method.postProgressMessage).toHaveBeenNthCalledWith(2, 100, 'installingFirmware');
|
|
627
|
+
});
|
|
628
|
+
|
|
629
|
+
test('does not use a reconnect response timeout as BLE install evidence', async () => {
|
|
630
|
+
const method = new FirmwareUpdateV4({
|
|
631
|
+
id: 1,
|
|
632
|
+
payload: {
|
|
633
|
+
method: 'firmwareUpdateV4',
|
|
634
|
+
connectId: 'pro2-ble',
|
|
635
|
+
},
|
|
636
|
+
});
|
|
637
|
+
const targets = [{ target_id: 3, path: 'vol0:/bootloader.bin' }];
|
|
638
|
+
const finishedStatus = {
|
|
639
|
+
type: 'DeviceFirmwareUpdateStatus',
|
|
640
|
+
message: {
|
|
641
|
+
records: [
|
|
642
|
+
{
|
|
643
|
+
...targets[0],
|
|
644
|
+
status: 'FW_MGMT_UPDATER_TASK_STATUS_FINISHED',
|
|
645
|
+
},
|
|
646
|
+
],
|
|
647
|
+
},
|
|
648
|
+
};
|
|
649
|
+
const typedCall = jest
|
|
650
|
+
.fn()
|
|
651
|
+
.mockRejectedValueOnce(
|
|
652
|
+
ERRORS.TypedError(
|
|
653
|
+
HardwareErrorCode.BleTimeoutError,
|
|
654
|
+
'Lowlevel response timeout after 15000ms for DeviceFirmwareUpdateStatusGet'
|
|
655
|
+
)
|
|
656
|
+
)
|
|
657
|
+
.mockResolvedValueOnce(finishedStatus)
|
|
658
|
+
.mockResolvedValueOnce(finishedStatus)
|
|
659
|
+
.mockResolvedValueOnce(finishedStatus)
|
|
660
|
+
.mockResolvedValueOnce(finishedStatus)
|
|
661
|
+
.mockRejectedValueOnce(ERRORS.TypedError(HardwareErrorCode.ActionCancelled));
|
|
662
|
+
const reconnectProtocolV2Device = jest
|
|
663
|
+
.fn()
|
|
664
|
+
.mockRejectedValueOnce(
|
|
665
|
+
ERRORS.TypedError(
|
|
666
|
+
HardwareErrorCode.BleTimeoutError,
|
|
667
|
+
'device was disconnected after Lowlevel response timeout'
|
|
668
|
+
)
|
|
669
|
+
)
|
|
670
|
+
.mockResolvedValueOnce(undefined);
|
|
671
|
+
const setTimeoutSpy = jest.spyOn(global, 'setTimeout').mockImplementation(((
|
|
672
|
+
callback: () => void
|
|
673
|
+
) => {
|
|
674
|
+
callback();
|
|
675
|
+
return 0 as any;
|
|
676
|
+
}) as typeof setTimeout);
|
|
677
|
+
|
|
678
|
+
method.device = {
|
|
679
|
+
getCommands: () => ({ typedCall, cancelDevice: jest.fn() }),
|
|
680
|
+
setCancelableAction: jest.fn(),
|
|
681
|
+
} as unknown as Device;
|
|
682
|
+
method.postProgressMessage = jest.fn();
|
|
683
|
+
|
|
684
|
+
const firmwareUpdate = method as unknown as {
|
|
685
|
+
waitForProtocolV2FirmwareUpdateComplete: (
|
|
686
|
+
value: typeof targets,
|
|
687
|
+
requireCurrentInstallStatus: boolean
|
|
688
|
+
) => Promise<void>;
|
|
689
|
+
reconnectProtocolV2Device: (options: { skipProtocolProbe: boolean }) => Promise<void>;
|
|
690
|
+
};
|
|
691
|
+
firmwareUpdate.reconnectProtocolV2Device = reconnectProtocolV2Device;
|
|
692
|
+
(method as any).isBleReconnect = jest.fn(() => true);
|
|
693
|
+
|
|
694
|
+
try {
|
|
695
|
+
await expect(
|
|
696
|
+
firmwareUpdate.waitForProtocolV2FirmwareUpdateComplete(targets, true)
|
|
697
|
+
).rejects.toMatchObject({
|
|
698
|
+
errorCode: HardwareErrorCode.ActionCancelled,
|
|
699
|
+
});
|
|
700
|
+
} finally {
|
|
701
|
+
setTimeoutSpy.mockRestore();
|
|
702
|
+
}
|
|
703
|
+
|
|
704
|
+
expect(reconnectProtocolV2Device).toHaveBeenCalledTimes(2);
|
|
705
|
+
expect(method.postProgressMessage).not.toHaveBeenCalled();
|
|
706
|
+
});
|
|
707
|
+
|
|
407
708
|
test('rejects stable stale finished BLE status after a status response timeout', async () => {
|
|
408
709
|
const method = new FirmwareUpdateV4({
|
|
409
710
|
id: 1,
|
|
@@ -5686,6 +5686,7 @@ describe('Protocol V2 firmware update targets', () => {
|
|
|
5686
5686
|
);
|
|
5687
5687
|
expect(typedCall).not.toHaveBeenCalledWith('DeviceFirmwareUpdateRequest', 'Success', {});
|
|
5688
5688
|
expect((method as any).protocolV2InstallNeedsReconnect).toBe(true);
|
|
5689
|
+
expect((method as any).protocolV2InstallDisconnectObserved).toBe(true);
|
|
5689
5690
|
});
|
|
5690
5691
|
|
|
5691
5692
|
test.each([
|
|
@@ -18,6 +18,7 @@ export default class FirmwareUpdateV4 extends FirmwareUpdateBaseMethod<FirmwareU
|
|
|
18
18
|
private protocolV2LatestFinalDeviceInfo?;
|
|
19
19
|
private protocolV2InstallBaselineVersions;
|
|
20
20
|
private protocolV2InstallNeedsReconnect;
|
|
21
|
+
private protocolV2InstallDisconnectObserved;
|
|
21
22
|
private protocolV2InstallTerminalSuccessObserved;
|
|
22
23
|
private protocolV2LastRuntimeProbeFeatures?;
|
|
23
24
|
private protocolV2LastTransferProgress?;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"FirmwareUpdateV4.d.ts","sourceRoot":"","sources":["../../src/api/FirmwareUpdateV4.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,WAAW,EAMZ,MAAM,qBAAqB,CAAC;AA0B7B,OAAO,EAAE,wBAAwB,EAAE,MAAM,qCAAqC,CAAC;AAiC/E,OAAO,KAAK,EAEV,sBAAsB,EAEvB,MAAM,6BAA6B,CAAC;AAqErC,wBAAgB,wCAAwC,CACtD,UAAU,EAAE,WAAW,GAAG,MAAM,GAAG,SAAS,EAC5C,MAAM,EAAE,sBAAsB,EAC9B,0BAA0B,UAAQ,QAiCnC;
|
|
1
|
+
{"version":3,"file":"FirmwareUpdateV4.d.ts","sourceRoot":"","sources":["../../src/api/FirmwareUpdateV4.ts"],"names":[],"mappings":"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"}
|
package/dist/index.js
CHANGED
|
@@ -52302,6 +52302,13 @@ const isProtocolV2FirmwareStatusEndpointUnavailable = (error) => {
|
|
|
52302
52302
|
message.includes('message handler not found') ||
|
|
52303
52303
|
message.includes('unsupported message'));
|
|
52304
52304
|
};
|
|
52305
|
+
const isProtocolV2InstallResponseTimeout = (error) => {
|
|
52306
|
+
if (!error || typeof error !== 'object')
|
|
52307
|
+
return false;
|
|
52308
|
+
const { code } = error;
|
|
52309
|
+
return (code === 'response-timeout' ||
|
|
52310
|
+
/\bresponse timeout\b/i.test(getProtocolV2UnknownErrorText(error)));
|
|
52311
|
+
};
|
|
52305
52312
|
const isProtocolV2TerminalInstallStatusError = (error) => {
|
|
52306
52313
|
var _a;
|
|
52307
52314
|
return hdShared.isBleStaleBondHardwareError(error) ||
|
|
@@ -52429,6 +52436,7 @@ class FirmwareUpdateV4 extends FirmwareUpdateBaseMethod {
|
|
|
52429
52436
|
this.protocolV2CompletedTargetIds = new Set();
|
|
52430
52437
|
this.protocolV2InstallBaselineVersions = new Map();
|
|
52431
52438
|
this.protocolV2InstallNeedsReconnect = false;
|
|
52439
|
+
this.protocolV2InstallDisconnectObserved = false;
|
|
52432
52440
|
this.protocolV2InstallTerminalSuccessObserved = false;
|
|
52433
52441
|
this.protocolV2LastTransferProgressAt = 0;
|
|
52434
52442
|
}
|
|
@@ -53899,15 +53907,15 @@ class FirmwareUpdateV4 extends FirmwareUpdateBaseMethod {
|
|
|
53899
53907
|
return __awaiter(this, void 0, void 0, function* () {
|
|
53900
53908
|
const expectedTargetIds = new Set(targets.map(target => target.target_id));
|
|
53901
53909
|
const expectedPaths = new Map(targets.map(target => [target.target_id, target.path]));
|
|
53902
|
-
const
|
|
53903
|
-
expectedTargetIds.has(ProtocolV2FirmwareTargetType.FW_MGMT_TARGET_COPROCESSOR);
|
|
53910
|
+
const isBleInstall = this.isBleReconnect();
|
|
53904
53911
|
const startTime = Date.now();
|
|
53905
53912
|
let lastError;
|
|
53906
53913
|
let shouldReconnect = this.protocolV2InstallNeedsReconnect;
|
|
53907
53914
|
this.protocolV2InstallNeedsReconnect = false;
|
|
53908
53915
|
let deviceInfo;
|
|
53909
53916
|
let bleInstallLinkReady = false;
|
|
53910
|
-
let installStatusDisconnectObserved =
|
|
53917
|
+
let installStatusDisconnectObserved = isBleInstall && this.protocolV2InstallDisconnectObserved;
|
|
53918
|
+
this.protocolV2InstallDisconnectObserved = false;
|
|
53911
53919
|
let installReconnectObserved = false;
|
|
53912
53920
|
let finishedStatusSnapshotKey;
|
|
53913
53921
|
let finishedStatusSnapshotPolls = 0;
|
|
@@ -53915,6 +53923,17 @@ class FirmwareUpdateV4 extends FirmwareUpdateBaseMethod {
|
|
|
53915
53923
|
let installEvidenceObserved = this.protocolV2InstallTerminalSuccessObserved;
|
|
53916
53924
|
let currentInstallStatusObserved = false;
|
|
53917
53925
|
const liveTargetIds = new Set();
|
|
53926
|
+
const recordBleInstallDisconnect = (error) => {
|
|
53927
|
+
if (!isBleInstall ||
|
|
53928
|
+
!isProtocolV2DeviceDisconnectedError(error) ||
|
|
53929
|
+
isProtocolV2InstallResponseTimeout(error)) {
|
|
53930
|
+
return;
|
|
53931
|
+
}
|
|
53932
|
+
installStatusDisconnectObserved = true;
|
|
53933
|
+
installReconnectObserved = false;
|
|
53934
|
+
finishedStatusSnapshotKey = undefined;
|
|
53935
|
+
finishedStatusSnapshotPolls = 0;
|
|
53936
|
+
};
|
|
53918
53937
|
while (Date.now() - startTime < PROTOCOL_V2_INSTALL_TIMEOUT) {
|
|
53919
53938
|
this.throwIfAborted();
|
|
53920
53939
|
try {
|
|
@@ -54101,13 +54120,7 @@ class FirmwareUpdateV4 extends FirmwareUpdateBaseMethod {
|
|
|
54101
54120
|
}
|
|
54102
54121
|
}
|
|
54103
54122
|
else {
|
|
54104
|
-
|
|
54105
|
-
isProtocolV2DeviceDisconnectedError(error) &&
|
|
54106
|
-
!isProtocolV2ResponseTimeout(error)) {
|
|
54107
|
-
installStatusDisconnectObserved = true;
|
|
54108
|
-
finishedStatusSnapshotKey = undefined;
|
|
54109
|
-
finishedStatusSnapshotPolls = 0;
|
|
54110
|
-
}
|
|
54123
|
+
recordBleInstallDisconnect(error);
|
|
54111
54124
|
shouldReconnect = true;
|
|
54112
54125
|
deviceInfo = undefined;
|
|
54113
54126
|
bleInstallLinkReady = false;
|
|
@@ -54128,6 +54141,7 @@ class FirmwareUpdateV4 extends FirmwareUpdateBaseMethod {
|
|
|
54128
54141
|
((_b = error.params) === null || _b === void 0 ? void 0 : _b.firmwareUpdateCode) === 'FirmwareInstallStatusUnavailable') {
|
|
54129
54142
|
throw error;
|
|
54130
54143
|
}
|
|
54144
|
+
recordBleInstallDisconnect(error);
|
|
54131
54145
|
shouldReconnect = true;
|
|
54132
54146
|
deviceInfo = undefined;
|
|
54133
54147
|
bleInstallLinkReady = false;
|
|
@@ -54377,6 +54391,7 @@ class FirmwareUpdateV4 extends FirmwareUpdateBaseMethod {
|
|
|
54377
54391
|
return __awaiter(this, void 0, void 0, function* () {
|
|
54378
54392
|
this.protocolV2LastRuntimeProbeFeatures = undefined;
|
|
54379
54393
|
this.protocolV2InstallNeedsReconnect = false;
|
|
54394
|
+
this.protocolV2InstallDisconnectObserved = false;
|
|
54380
54395
|
this.protocolV2InstallTerminalSuccessObserved = false;
|
|
54381
54396
|
const commands = this.device.getCommands();
|
|
54382
54397
|
yield commands.typedCall('DeviceFirmwareUpdateStage', 'Success', { targets });
|
|
@@ -54404,6 +54419,7 @@ class FirmwareUpdateV4 extends FirmwareUpdateBaseMethod {
|
|
|
54404
54419
|
}
|
|
54405
54420
|
Log$6.log('[FirmwareUpdateV4] transport released while writing install request; continue status polling');
|
|
54406
54421
|
this.protocolV2InstallNeedsReconnect = true;
|
|
54422
|
+
this.protocolV2InstallDisconnectObserved = !isProtocolV2InstallResponseTimeout(error);
|
|
54407
54423
|
}
|
|
54408
54424
|
});
|
|
54409
54425
|
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@onekeyfe/hd-core",
|
|
3
|
-
"version": "1.2.
|
|
3
|
+
"version": "1.2.1",
|
|
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.
|
|
29
|
-
"@onekeyfe/hd-transport": "1.2.
|
|
28
|
+
"@onekeyfe/hd-shared": "1.2.1",
|
|
29
|
+
"@onekeyfe/hd-transport": "1.2.1",
|
|
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": "43d2856e593a93fbf056fdb334e0fe407a79cdc0"
|
|
50
50
|
}
|
|
@@ -374,6 +374,15 @@ const isProtocolV2FirmwareStatusEndpointUnavailable = (error: unknown) => {
|
|
|
374
374
|
);
|
|
375
375
|
};
|
|
376
376
|
|
|
377
|
+
const isProtocolV2InstallResponseTimeout = (error: unknown) => {
|
|
378
|
+
if (!error || typeof error !== 'object') return false;
|
|
379
|
+
const { code } = error as { code?: number | string };
|
|
380
|
+
return (
|
|
381
|
+
code === 'response-timeout' ||
|
|
382
|
+
/\bresponse timeout\b/i.test(getProtocolV2UnknownErrorText(error))
|
|
383
|
+
);
|
|
384
|
+
};
|
|
385
|
+
|
|
377
386
|
const isProtocolV2TerminalInstallStatusError = (error: unknown) =>
|
|
378
387
|
isBleStaleBondHardwareError(error) ||
|
|
379
388
|
(error instanceof HardwareError &&
|
|
@@ -565,6 +574,8 @@ export default class FirmwareUpdateV4 extends FirmwareUpdateBaseMethod<FirmwareU
|
|
|
565
574
|
|
|
566
575
|
private protocolV2InstallNeedsReconnect = false;
|
|
567
576
|
|
|
577
|
+
private protocolV2InstallDisconnectObserved = false;
|
|
578
|
+
|
|
568
579
|
private protocolV2InstallTerminalSuccessObserved = false;
|
|
569
580
|
|
|
570
581
|
private protocolV2LastRuntimeProbeFeatures?: Features;
|
|
@@ -2517,9 +2528,7 @@ export default class FirmwareUpdateV4 extends FirmwareUpdateBaseMethod<FirmwareU
|
|
|
2517
2528
|
) {
|
|
2518
2529
|
const expectedTargetIds = new Set(targets.map(target => target.target_id));
|
|
2519
2530
|
const expectedPaths = new Map(targets.map(target => [target.target_id, target.path]));
|
|
2520
|
-
const
|
|
2521
|
-
this.isBleReconnect() &&
|
|
2522
|
-
expectedTargetIds.has(ProtocolV2FirmwareTargetType.FW_MGMT_TARGET_COPROCESSOR);
|
|
2531
|
+
const isBleInstall = this.isBleReconnect();
|
|
2523
2532
|
const startTime = Date.now();
|
|
2524
2533
|
let lastError: unknown;
|
|
2525
2534
|
// The loader may release either USB or BLE as installation starts. Recovery reconnects
|
|
@@ -2528,7 +2537,8 @@ export default class FirmwareUpdateV4 extends FirmwareUpdateBaseMethod<FirmwareU
|
|
|
2528
2537
|
this.protocolV2InstallNeedsReconnect = false;
|
|
2529
2538
|
let deviceInfo: ProtocolV2DeviceInfo | undefined;
|
|
2530
2539
|
let bleInstallLinkReady = false;
|
|
2531
|
-
let installStatusDisconnectObserved =
|
|
2540
|
+
let installStatusDisconnectObserved = isBleInstall && this.protocolV2InstallDisconnectObserved;
|
|
2541
|
+
this.protocolV2InstallDisconnectObserved = false;
|
|
2532
2542
|
let installReconnectObserved = false;
|
|
2533
2543
|
let finishedStatusSnapshotKey: string | undefined;
|
|
2534
2544
|
let finishedStatusSnapshotPolls = 0;
|
|
@@ -2536,6 +2546,19 @@ export default class FirmwareUpdateV4 extends FirmwareUpdateBaseMethod<FirmwareU
|
|
|
2536
2546
|
let installEvidenceObserved = this.protocolV2InstallTerminalSuccessObserved;
|
|
2537
2547
|
let currentInstallStatusObserved = false;
|
|
2538
2548
|
const liveTargetIds = new Set<number>();
|
|
2549
|
+
const recordBleInstallDisconnect = (error: unknown) => {
|
|
2550
|
+
if (
|
|
2551
|
+
!isBleInstall ||
|
|
2552
|
+
!isProtocolV2DeviceDisconnectedError(error) ||
|
|
2553
|
+
isProtocolV2InstallResponseTimeout(error)
|
|
2554
|
+
) {
|
|
2555
|
+
return;
|
|
2556
|
+
}
|
|
2557
|
+
installStatusDisconnectObserved = true;
|
|
2558
|
+
installReconnectObserved = false;
|
|
2559
|
+
finishedStatusSnapshotKey = undefined;
|
|
2560
|
+
finishedStatusSnapshotPolls = 0;
|
|
2561
|
+
};
|
|
2539
2562
|
|
|
2540
2563
|
while (Date.now() - startTime < PROTOCOL_V2_INSTALL_TIMEOUT) {
|
|
2541
2564
|
// A transport release caused by an explicit workflow cancellation must not
|
|
@@ -2787,15 +2810,7 @@ export default class FirmwareUpdateV4 extends FirmwareUpdateBaseMethod<FirmwareU
|
|
|
2787
2810
|
);
|
|
2788
2811
|
}
|
|
2789
2812
|
} else {
|
|
2790
|
-
|
|
2791
|
-
isBleCoprocessorInstall &&
|
|
2792
|
-
isProtocolV2DeviceDisconnectedError(error) &&
|
|
2793
|
-
!isProtocolV2ResponseTimeout(error)
|
|
2794
|
-
) {
|
|
2795
|
-
installStatusDisconnectObserved = true;
|
|
2796
|
-
finishedStatusSnapshotKey = undefined;
|
|
2797
|
-
finishedStatusSnapshotPolls = 0;
|
|
2798
|
-
}
|
|
2813
|
+
recordBleInstallDisconnect(error);
|
|
2799
2814
|
shouldReconnect = true;
|
|
2800
2815
|
deviceInfo = undefined;
|
|
2801
2816
|
bleInstallLinkReady = false;
|
|
@@ -2820,6 +2835,7 @@ export default class FirmwareUpdateV4 extends FirmwareUpdateBaseMethod<FirmwareU
|
|
|
2820
2835
|
) {
|
|
2821
2836
|
throw error;
|
|
2822
2837
|
}
|
|
2838
|
+
recordBleInstallDisconnect(error);
|
|
2823
2839
|
shouldReconnect = true;
|
|
2824
2840
|
deviceInfo = undefined;
|
|
2825
2841
|
bleInstallLinkReady = false;
|
|
@@ -3154,6 +3170,7 @@ export default class FirmwareUpdateV4 extends FirmwareUpdateBaseMethod<FirmwareU
|
|
|
3154
3170
|
}) {
|
|
3155
3171
|
this.protocolV2LastRuntimeProbeFeatures = undefined;
|
|
3156
3172
|
this.protocolV2InstallNeedsReconnect = false;
|
|
3173
|
+
this.protocolV2InstallDisconnectObserved = false;
|
|
3157
3174
|
this.protocolV2InstallTerminalSuccessObserved = false;
|
|
3158
3175
|
const commands = this.device.getCommands();
|
|
3159
3176
|
await commands.typedCall('DeviceFirmwareUpdateStage', 'Success', { targets });
|
|
@@ -3196,6 +3213,7 @@ export default class FirmwareUpdateV4 extends FirmwareUpdateBaseMethod<FirmwareU
|
|
|
3196
3213
|
'[FirmwareUpdateV4] transport released while writing install request; continue status polling'
|
|
3197
3214
|
);
|
|
3198
3215
|
this.protocolV2InstallNeedsReconnect = true;
|
|
3216
|
+
this.protocolV2InstallDisconnectObserved = !isProtocolV2InstallResponseTimeout(error);
|
|
3199
3217
|
}
|
|
3200
3218
|
}
|
|
3201
3219
|
|