@onekeyfe/hd-core 1.2.0-alpha.55 → 1.2.0-alpha.56

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.
@@ -1,4 +1,5 @@
1
1
  import { DEVICE } from '../src/events';
2
+
2
3
  import type { DeviceState, DeviceStateEvent } from '../src/types';
3
4
 
4
5
  describe('DeviceState contract', () => {
@@ -1,6 +1,6 @@
1
1
  import { EDeviceType, EFirmwareType } from '@onekeyfe/hd-shared';
2
-
3
2
  import { DeviceType, Enum_SafetyCheckLevel } from '@onekeyfe/hd-transport';
3
+
4
4
  import {
5
5
  mapApplySettingsToState,
6
6
  mapDeviceSettingsToState,
@@ -1,13 +1,13 @@
1
1
  import { EDeviceType } from '@onekeyfe/hd-shared';
2
2
 
3
3
  import {
4
+ PROTOCOL_V2_NEVER_TIMEOUT_MS,
4
5
  getAutoLockOptions,
5
6
  getAutoShutDownOptions,
6
7
  getDeviceSettingsCapabilities,
7
8
  getLanguageConfig,
8
9
  mapLanguageFromProtocolV2,
9
10
  mapLanguageToProtocolV2,
10
- PROTOCOL_V2_NEVER_TIMEOUT_MS,
11
11
  } from '../src/utils/deviceSettings';
12
12
 
13
13
  describe('Pro 2 device settings options', () => {
@@ -6071,6 +6071,10 @@ describe('Protocol V2 firmware update targets', () => {
6071
6071
  expect(writePayloads.map(payload => payload.file.offset)).toEqual([0, 1800]);
6072
6072
  expect(writePayloads.map(payload => payload.file.data.byteLength)).toEqual([1800, 1]);
6073
6073
  expect(writePayloads.map(payload => payload.ui_percentage)).toEqual([0, 100]);
6074
+ expect(typedCall.mock.calls.map(call => call[3])).toEqual([
6075
+ { writeWithResponse: true },
6076
+ { writeWithResponse: true },
6077
+ ]);
6074
6078
  });
6075
6079
 
6076
6080
  test('ends device confirmation and starts install progress only after Protocol V2 ACK', async () => {
@@ -89,4 +89,43 @@ describe('writeProtocolV2File', () => {
89
89
  expect(typedCall.mock.calls[1][2]).toEqual(typedCall.mock.calls[0][2]);
90
90
  expect(onProgress).toHaveBeenCalledTimes(1);
91
91
  });
92
+
93
+ test('按确认分片的时间窗口记录实时传输速率', async () => {
94
+ const data = new Uint8Array(4097);
95
+ const typedCall = jest.fn().mockResolvedValue({ message: {} });
96
+ const onProgress = jest.fn();
97
+ const dateNowSpy = jest
98
+ .spyOn(Date, 'now')
99
+ .mockReturnValueOnce(1_000)
100
+ .mockReturnValueOnce(2_000)
101
+ .mockReturnValueOnce(3_000);
102
+
103
+ try {
104
+ await writeProtocolV2File({
105
+ commands: { typedCall } as any,
106
+ path: 'vol1:/wallpapers/test.bin',
107
+ data,
108
+ onProgress,
109
+ });
110
+ } finally {
111
+ dateNowSpy.mockRestore();
112
+ }
113
+
114
+ expect(onProgress).toHaveBeenNthCalledWith(
115
+ 1,
116
+ expect.objectContaining({
117
+ transferredBytes: 4000,
118
+ rateBytesPerSecond: 4000,
119
+ elapsedMs: 1000,
120
+ })
121
+ );
122
+ expect(onProgress).toHaveBeenNthCalledWith(
123
+ 2,
124
+ expect.objectContaining({
125
+ transferredBytes: 4097,
126
+ rateBytesPerSecond: 97,
127
+ elapsedMs: 2000,
128
+ })
129
+ );
130
+ });
92
131
  });
@@ -1 +1 @@
1
- {"version":3,"file":"FirmwareUpdateV4.d.ts","sourceRoot":"","sources":["../../src/api/FirmwareUpdateV4.ts"],"names":[],"mappings":"AAqBA,OAAO,EAAE,wBAAwB,EAAE,MAAM,qCAAqC,CAAC;AAkB/E,OAAO,KAAK,EAAE,sBAAsB,EAA0B,MAAM,6BAA6B,CAAC;AAmUlG,eAAO,MAAM,oCAAoC,WACvC,WAAW,GAAG,UAAU,eACnB,MAAM,GAAG,SAAS,YAKhC,CAAC;AAEF,eAAO,MAAM,iCAAiC,0BACrB,MAAM,uBACR,MAAM,SAa5B,CAAC;AAUF,MAAM,CAAC,OAAO,OAAO,gBAAiB,SAAQ,wBAAwB,CAAC,sBAAsB,CAAC;IAC5F,OAAO,CAAC,8BAA8B,CAAC,CAAS;IAEhD,qBAAqB;IAIrB,IAAI;IA6DJ,OAAO,CAAC,8BAA8B;IAiBhC,GAAG;;;;;YAKK,aAAa;YAwGb,2BAA2B;IAWzC,OAAO,CAAC,yBAAyB;IAKjC,OAAO,CAAC,kCAAkC;IAO1C,OAAO,CAAC,8BAA8B;YAMxB,iCAAiC;YAOjC,iCAAiC;YAOjC,iCAAiC;IAM/C,OAAO,CAAC,uBAAuB;IAI/B,OAAO,CAAC,4BAA4B;IASpC,OAAO,CAAC,2BAA2B;IAsBnC,OAAO,CAAC,yBAAyB;IAiBjC,OAAO,CAAC,wBAAwB;YAkBlB,iCAAiC;YAmCjC,+BAA+B;IAqD7C,OAAO,CAAC,qCAAqC;YAuB/B,8BAA8B;IAyB5C,OAAO,CAAC,wCAAwC;YAgBlC,gCAAgC;YAqChC,0BAA0B;YAe1B,6BAA6B;IAkC3C,OAAO,CAAC,0BAA0B;IAUlC,OAAO,CAAC,yBAAyB;IAU3B,6BAA6B;YA4BrB,+BAA+B;IAkD7C,OAAO,CAAC,6BAA6B;YAkCvB,uBAAuB;IA4GrC,OAAO,CAAC,mCAAmC;YAI7B,0BAA0B;IAaxC,OAAO,CAAC,4BAA4B;IAgEpC,OAAO,CAAC,6BAA6B;YAcvB,uCAAuC;YAoJvC,gCAAgC;YAchC,yBAAyB;YAQzB,8BAA8B;IAQ5C,OAAO,CAAC,0BAA0B;YAiBpB,qCAAqC;YAgDrC,yBAAyB;YA8DzB,8BAA8B;IAU5C,OAAO,CAAC,kCAAkC;YAI5B,6BAA6B;YAwB7B,wBAAwB;IAoDtC,OAAO,CAAC,sCAAsC;YAchC,cAAc;YA+Bd,6BAA6B;YAW7B,0BAA0B;YAS1B,6BAA6B;YAmB7B,gBAAgB;IAiB9B,OAAO,CAAC,qBAAqB;CAM9B"}
1
+ {"version":3,"file":"FirmwareUpdateV4.d.ts","sourceRoot":"","sources":["../../src/api/FirmwareUpdateV4.ts"],"names":[],"mappings":"AAqBA,OAAO,EAAE,wBAAwB,EAAE,MAAM,qCAAqC,CAAC;AAkB/E,OAAO,KAAK,EAAE,sBAAsB,EAA0B,MAAM,6BAA6B,CAAC;AAmUlG,eAAO,MAAM,oCAAoC,WACvC,WAAW,GAAG,UAAU,eACnB,MAAM,GAAG,SAAS,YAKhC,CAAC;AAEF,eAAO,MAAM,iCAAiC,0BACrB,MAAM,uBACR,MAAM,SAa5B,CAAC;AAUF,MAAM,CAAC,OAAO,OAAO,gBAAiB,SAAQ,wBAAwB,CAAC,sBAAsB,CAAC;IAC5F,OAAO,CAAC,8BAA8B,CAAC,CAAS;IAEhD,qBAAqB;IAIrB,IAAI;IA6DJ,OAAO,CAAC,8BAA8B;IAiBhC,GAAG;;;;;YAKK,aAAa;YAwGb,2BAA2B;IAWzC,OAAO,CAAC,yBAAyB;IAKjC,OAAO,CAAC,kCAAkC;IAO1C,OAAO,CAAC,8BAA8B;YAMxB,iCAAiC;YAOjC,iCAAiC;YAOjC,iCAAiC;IAM/C,OAAO,CAAC,uBAAuB;IAI/B,OAAO,CAAC,4BAA4B;IASpC,OAAO,CAAC,2BAA2B;IAsBnC,OAAO,CAAC,yBAAyB;IAiBjC,OAAO,CAAC,wBAAwB;YAkBlB,iCAAiC;YAmCjC,+BAA+B;IAqD7C,OAAO,CAAC,qCAAqC;YAuB/B,8BAA8B;IAyB5C,OAAO,CAAC,wCAAwC;YAgBlC,gCAAgC;YAqChC,0BAA0B;YAe1B,6BAA6B;IAkC3C,OAAO,CAAC,0BAA0B;IAUlC,OAAO,CAAC,yBAAyB;IAU3B,6BAA6B;YA4BrB,+BAA+B;IAkD7C,OAAO,CAAC,6BAA6B;YAkCvB,uBAAuB;IA4GrC,OAAO,CAAC,mCAAmC;YAI7B,0BAA0B;IAaxC,OAAO,CAAC,4BAA4B;IAgEpC,OAAO,CAAC,6BAA6B;YAcvB,uCAAuC;YAoJvC,gCAAgC;YAchC,yBAAyB;YAQzB,8BAA8B;IAQ5C,OAAO,CAAC,0BAA0B;YAiBpB,qCAAqC;YAgDrC,yBAAyB;YA8DzB,8BAA8B;IAU5C,OAAO,CAAC,kCAAkC;YAI5B,6BAA6B;YAwB7B,wBAAwB;IAoDtC,OAAO,CAAC,sCAAsC;YAchC,cAAc;YAoCd,6BAA6B;YAW7B,0BAA0B;YAS1B,6BAA6B;YAmB7B,gBAAgB;IAiB9B,OAAO,CAAC,qBAAqB;CAM9B"}
@@ -1 +1 @@
1
- {"version":3,"file":"protocolV2FileWrite.d.ts","sourceRoot":"","sources":["../../../src/api/helpers/protocolV2FileWrite.ts"],"names":[],"mappings":"AAQA,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,6BAA6B,CAAC;AAElE,MAAM,MAAM,uBAAuB,GAAG,WAAW,GAAG,UAAU,GAAG,IAAI,GAAG,MAAM,CAAC;AAE/E,MAAM,MAAM,2BAA2B,GAAG;IACxC,QAAQ,EAAE,MAAM,CAAC;IACjB,gBAAgB,EAAE,MAAM,CAAC;IACzB,UAAU,EAAE,MAAM,CAAC;IACnB,kBAAkB,CAAC,EAAE,MAAM,CAAC;IAC5B,SAAS,EAAE,MAAM,CAAC;CACnB,CAAC;AAEF,MAAM,MAAM,0BAA0B,GAAG;IACvC,QAAQ,EAAE,IAAI,CAAC,cAAc,EAAE,WAAW,CAAC,CAAC;IAC5C,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,EAAE,uBAAuB,CAAC;IAC9B,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,SAAS,CAAC,EAAE,OAAO,CAAC;IACpB,MAAM,CAAC,EAAE,OAAO,CAAC;IACjB,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,eAAe,CAAC,EAAE,MAAM,CAAC;IACzB,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,cAAc,CAAC,EAAE,MAAM,IAAI,CAAC;IAC5B,UAAU,CAAC,EAAE,CAAC,QAAQ,EAAE,2BAA2B,KAAK,IAAI,CAAC;CAC9D,CAAC;AAIF,wBAAgB,2BAA2B,CAAC,KAAK,EAAE,OAAO,WASzD;AA8CD,wBAAsB,mBAAmB,CAAC,OAAO,EAAE,0BAA0B;;;;;;GA8G5E"}
1
+ {"version":3,"file":"protocolV2FileWrite.d.ts","sourceRoot":"","sources":["../../../src/api/helpers/protocolV2FileWrite.ts"],"names":[],"mappings":"AAQA,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,6BAA6B,CAAC;AAElE,MAAM,MAAM,uBAAuB,GAAG,WAAW,GAAG,UAAU,GAAG,IAAI,GAAG,MAAM,CAAC;AAE/E,MAAM,MAAM,2BAA2B,GAAG;IACxC,QAAQ,EAAE,MAAM,CAAC;IACjB,gBAAgB,EAAE,MAAM,CAAC;IACzB,UAAU,EAAE,MAAM,CAAC;IACnB,kBAAkB,CAAC,EAAE,MAAM,CAAC;IAC5B,SAAS,EAAE,MAAM,CAAC;CACnB,CAAC;AAEF,MAAM,MAAM,0BAA0B,GAAG;IACvC,QAAQ,EAAE,IAAI,CAAC,cAAc,EAAE,WAAW,CAAC,CAAC;IAC5C,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,EAAE,uBAAuB,CAAC;IAC9B,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,SAAS,CAAC,EAAE,OAAO,CAAC;IACpB,MAAM,CAAC,EAAE,OAAO,CAAC;IACjB,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,eAAe,CAAC,EAAE,MAAM,CAAC;IACzB,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,cAAc,CAAC,EAAE,MAAM,IAAI,CAAC;IAC5B,UAAU,CAAC,EAAE,CAAC,QAAQ,EAAE,2BAA2B,KAAK,IAAI,CAAC;CAC9D,CAAC;AAKF,wBAAgB,2BAA2B,CAAC,KAAK,EAAE,OAAO,WASzD;AA8CD,wBAAsB,mBAAmB,CAAC,OAAO,EAAE,0BAA0B;;;;;;GA0H5E"}
package/dist/index.js CHANGED
@@ -50485,7 +50485,7 @@ class FirmwareUpdateV4 extends FirmwareUpdateBaseMethod {
50485
50485
  overwrite,
50486
50486
  append: false,
50487
50487
  ui_percentage: progress !== null && progress !== void 0 ? progress : undefined,
50488
- });
50488
+ }, { writeWithResponse: true });
50489
50489
  if (writeRes.type !== 'FilesystemFile') {
50490
50490
  if (writeRes.type === 'CallMethodError') {
50491
50491
  if (((_a = writeRes.message.error) !== null && _a !== void 0 ? _a : '').indexOf(SESSION_ERROR) > -1) {
@@ -50655,6 +50655,7 @@ class DeviceGetOnboardingStatus extends BaseMethod {
50655
50655
  }
50656
50656
 
50657
50657
  const MIN_FILE_CHUNK_SIZE = 64;
50658
+ const FILE_TRANSFER_RATE_WINDOW_MS = 1000;
50658
50659
  function isProtocolV2ResponseTimeout(error) {
50659
50660
  var _a, _b;
50660
50661
  if (!error || typeof error !== 'object')
@@ -50729,6 +50730,9 @@ function writeProtocolV2File(options) {
50729
50730
  let chunks = 0;
50730
50731
  let lastMessage;
50731
50732
  const startTime = Date.now();
50733
+ let rateWindowStartedAt = startTime;
50734
+ let rateWindowStartedBytes = 0;
50735
+ let rateBytesPerSecond;
50732
50736
  while (written < dataLength) {
50733
50737
  (_c = options.throwIfAborted) === null || _c === void 0 ? void 0 : _c.call(options);
50734
50738
  const chunk = data.slice(written, Math.min(written + chunkSize, dataLength));
@@ -50772,13 +50776,24 @@ function writeProtocolV2File(options) {
50772
50776
  written =
50773
50777
  rawProcessedByte === undefined ? written + chunk.byteLength : processedByte - startOffset;
50774
50778
  chunks += 1;
50775
- const elapsedMs = Date.now() - startTime;
50779
+ const now = Date.now();
50780
+ const elapsedMs = now - startTime;
50776
50781
  const transferredBytes = Math.min(written, dataLength);
50782
+ const rateWindowElapsedMs = now - rateWindowStartedAt;
50783
+ if (rateWindowElapsedMs >= FILE_TRANSFER_RATE_WINDOW_MS) {
50784
+ const rateWindowBytes = Math.max(transferredBytes - rateWindowStartedBytes, 0);
50785
+ rateBytesPerSecond = Math.round((rateWindowBytes / rateWindowElapsedMs) * 1000);
50786
+ rateWindowStartedAt = now;
50787
+ rateWindowStartedBytes = transferredBytes;
50788
+ }
50789
+ else if (rateBytesPerSecond === undefined && elapsedMs > 0) {
50790
+ rateBytesPerSecond = Math.round((transferredBytes / elapsedMs) * 1000);
50791
+ }
50777
50792
  (_l = options.onProgress) === null || _l === void 0 ? void 0 : _l.call(options, {
50778
50793
  progress: getConfirmedProgress(startOffset + written, totalSize, written, dataLength),
50779
50794
  transferredBytes,
50780
50795
  totalBytes: dataLength,
50781
- rateBytesPerSecond: elapsedMs > 0 ? Math.round((transferredBytes / elapsedMs) * 1000) : undefined,
50796
+ rateBytesPerSecond,
50782
50797
  elapsedMs,
50783
50798
  });
50784
50799
  if (options.paceMs && options.paceMs > 0) {
@@ -1 +1 @@
1
- {"version":3,"file":"firmware.d.ts","sourceRoot":"","sources":["../../../src/protocols/protocol-v2/firmware.ts"],"names":[],"mappings":"AAGA,eAAO,MAAM,4BAA4B;;;;;;;;;;;;CAY/B,CAAC;AAEX,MAAM,MAAM,4BAA4B,GACtC,CAAC,OAAO,4BAA4B,CAAC,CAAC,MAAM,OAAO,4BAA4B,CAAC,CAAC"}
1
+ {"version":3,"file":"firmware.d.ts","sourceRoot":"","sources":["../../../src/protocols/protocol-v2/firmware.ts"],"names":[],"mappings":"AAGA,eAAO,MAAM,4BAA4B;;;;;;;;;;;;CAY/B,CAAC;AAIX,MAAM,MAAM,4BAA4B,GACtC,CAAC,OAAO,4BAA4B,CAAC,CAAC,MAAM,OAAO,4BAA4B,CAAC,CAAC"}
@@ -1 +1 @@
1
- {"version":3,"file":"detectDeviceConnectProtocol.d.ts","sourceRoot":"","sources":["../../../src/types/api/detectDeviceConnectProtocol.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,uBAAuB,EAAE,MAAM,qBAAqB,CAAC;AAEnE,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,WAAW,CAAC;AAE1C,MAAM,CAAC,OAAO,UAAU,2BAA2B,CACjD,SAAS,EAAE,MAAM,GAChB,QAAQ,CAAC,uBAAuB,CAAC,CAAC"}
1
+ {"version":3,"file":"detectDeviceConnectProtocol.d.ts","sourceRoot":"","sources":["../../../src/types/api/detectDeviceConnectProtocol.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,uBAAuB,EAAE,MAAM,qBAAqB,CAAC;AACnE,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,WAAW,CAAC;AAE1C,MAAM,CAAC,OAAO,UAAU,2BAA2B,CACjD,SAAS,EAAE,MAAM,GAChB,QAAQ,CAAC,uBAAuB,CAAC,CAAC"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@onekeyfe/hd-core",
3
- "version": "1.2.0-alpha.55",
3
+ "version": "1.2.0-alpha.56",
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.55",
29
- "@onekeyfe/hd-transport": "1.2.0-alpha.55",
28
+ "@onekeyfe/hd-shared": "1.2.0-alpha.56",
29
+ "@onekeyfe/hd-transport": "1.2.0-alpha.56",
30
30
  "axios": "1.15.2",
31
31
  "bignumber.js": "^9.0.2",
32
32
  "bytebuffer": "^5.0.1",
@@ -44,5 +44,5 @@
44
44
  "@types/w3c-web-usb": "^1.0.10",
45
45
  "@types/web-bluetooth": "^0.0.21"
46
46
  },
47
- "gitHead": "0a99a180062ec32fac0c5e14be3366fbfb7bc01a"
47
+ "gitHead": "2c472748d67072307c21f8d33bc021cf18fe2ad7"
48
48
  }
@@ -1698,17 +1698,22 @@ export default class FirmwareUpdateV4 extends FirmwareUpdateBaseMethod<FirmwareU
1698
1698
  progress: number | null
1699
1699
  ): Promise<TypedResponseMessage<'FilesystemFile'>> {
1700
1700
  const typedCall = this.device.getCommands().typedCall.bind(this.device.getCommands());
1701
- const writeRes = await typedCall('FilesystemFileWrite', 'FilesystemFile', {
1702
- file: {
1703
- path: filePath,
1704
- offset,
1705
- total_size: totalFileSize,
1706
- data: chunk,
1701
+ const writeRes = await typedCall(
1702
+ 'FilesystemFileWrite',
1703
+ 'FilesystemFile',
1704
+ {
1705
+ file: {
1706
+ path: filePath,
1707
+ offset,
1708
+ total_size: totalFileSize,
1709
+ data: chunk,
1710
+ },
1711
+ overwrite,
1712
+ append: false,
1713
+ ui_percentage: progress ?? undefined,
1707
1714
  },
1708
- overwrite,
1709
- append: false,
1710
- ui_percentage: progress ?? undefined,
1711
- });
1715
+ { writeWithResponse: true }
1716
+ );
1712
1717
  if (writeRes.type !== 'FilesystemFile') {
1713
1718
  if ((writeRes as any).type === 'CallMethodError') {
1714
1719
  if (((writeRes as any).message.error ?? '').indexOf(SESSION_ERROR) > -1) {
@@ -37,6 +37,7 @@ export type ProtocolV2FileWriteOptions = {
37
37
  };
38
38
 
39
39
  const MIN_FILE_CHUNK_SIZE = 64;
40
+ const FILE_TRANSFER_RATE_WINDOW_MS = 1000;
40
41
 
41
42
  export function isProtocolV2ResponseTimeout(error: unknown) {
42
43
  if (!error || typeof error !== 'object') return false;
@@ -121,6 +122,9 @@ export async function writeProtocolV2File(options: ProtocolV2FileWriteOptions) {
121
122
  let chunks = 0;
122
123
  let lastMessage: Record<string, unknown> | undefined;
123
124
  const startTime = Date.now();
125
+ let rateWindowStartedAt = startTime;
126
+ let rateWindowStartedBytes = 0;
127
+ let rateBytesPerSecond: number | undefined;
124
128
 
125
129
  while (written < dataLength) {
126
130
  options.throwIfAborted?.();
@@ -178,14 +182,23 @@ export async function writeProtocolV2File(options: ProtocolV2FileWriteOptions) {
178
182
  written =
179
183
  rawProcessedByte === undefined ? written + chunk.byteLength : processedByte - startOffset;
180
184
  chunks += 1;
181
- const elapsedMs = Date.now() - startTime;
185
+ const now = Date.now();
186
+ const elapsedMs = now - startTime;
182
187
  const transferredBytes = Math.min(written, dataLength);
188
+ const rateWindowElapsedMs = now - rateWindowStartedAt;
189
+ if (rateWindowElapsedMs >= FILE_TRANSFER_RATE_WINDOW_MS) {
190
+ const rateWindowBytes = Math.max(transferredBytes - rateWindowStartedBytes, 0);
191
+ rateBytesPerSecond = Math.round((rateWindowBytes / rateWindowElapsedMs) * 1000);
192
+ rateWindowStartedAt = now;
193
+ rateWindowStartedBytes = transferredBytes;
194
+ } else if (rateBytesPerSecond === undefined && elapsedMs > 0) {
195
+ rateBytesPerSecond = Math.round((transferredBytes / elapsedMs) * 1000);
196
+ }
183
197
  options.onProgress?.({
184
198
  progress: getConfirmedProgress(startOffset + written, totalSize, written, dataLength),
185
199
  transferredBytes,
186
200
  totalBytes: dataLength,
187
- rateBytesPerSecond:
188
- elapsedMs > 0 ? Math.round((transferredBytes / elapsedMs) * 1000) : undefined,
201
+ rateBytesPerSecond,
189
202
  elapsedMs,
190
203
  });
191
204
  if (options.paceMs && options.paceMs > 0) {
@@ -15,5 +15,7 @@ export const ProtocolV2FirmwareTargetType = {
15
15
  FW_MGMT_TARGET_SE04: 10,
16
16
  } as const;
17
17
 
18
+ // 这里有意同时导出同名值与类型,以保持现有公共 API 不变。
19
+ // eslint-disable-next-line @typescript-eslint/no-redeclare
18
20
  export type ProtocolV2FirmwareTargetType =
19
21
  (typeof ProtocolV2FirmwareTargetType)[keyof typeof ProtocolV2FirmwareTargetType];
@@ -1,5 +1,4 @@
1
1
  import type { HardwareConnectProtocol } from '@onekeyfe/hd-shared';
2
-
3
2
  import type { Response } from '../params';
4
3
 
5
4
  export declare function detectDeviceConnectProtocol(