@onekeyfe/hd-core 1.2.0-alpha.70 → 1.2.0-alpha.72
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__/check-all-firmware-release-protocol-v2.test.ts +28 -0
- package/__tests__/protocol-v2-firmware-targets.test.ts +49 -1
- package/__tests__/protocol-v2-resources.test.ts +9 -6
- package/__tests__/protocol-v2.test.ts +431 -61
- package/__tests__/protocolV2FileWrite.test.ts +48 -7
- package/dist/api/CheckAllFirmwareRelease.d.ts +2 -1
- package/dist/api/CheckAllFirmwareRelease.d.ts.map +1 -1
- package/dist/api/FirmwareUpdateV4.d.ts +4 -0
- package/dist/api/FirmwareUpdateV4.d.ts.map +1 -1
- package/dist/api/helpers/protocolV2FileWrite.d.ts +1 -0
- package/dist/api/helpers/protocolV2FileWrite.d.ts.map +1 -1
- package/dist/index.d.ts +2 -1
- package/dist/index.js +193 -43
- package/dist/protocols/protocol-v2/resources.d.ts +1 -1
- package/dist/protocols/protocol-v2/resources.d.ts.map +1 -1
- package/dist/types/api/firmwareUpdate.d.ts.map +1 -1
- package/dist/types/settings.d.ts +1 -1
- package/dist/types/settings.d.ts.map +1 -1
- package/package.json +4 -4
- package/src/api/CheckAllFirmwareRelease.ts +19 -4
- package/src/api/FirmwareUpdateV4.ts +155 -23
- package/src/api/helpers/protocolV2FileWrite.ts +62 -8
- package/src/protocols/protocol-v2/resources.ts +5 -1
- package/src/types/api/firmwareUpdate.ts +1 -0
- package/src/types/settings.ts +2 -1
|
@@ -131,10 +131,43 @@ describe('writeProtocolV2File', () => {
|
|
|
131
131
|
'FilesystemFileWrite',
|
|
132
132
|
'FilesystemFile',
|
|
133
133
|
expect.objectContaining({ ui_percentage: 42 }),
|
|
134
|
-
{
|
|
134
|
+
expect.objectContaining({
|
|
135
|
+
writeWithResponse: true,
|
|
136
|
+
onWriteCompleted: expect.any(Function),
|
|
137
|
+
})
|
|
135
138
|
);
|
|
136
139
|
});
|
|
137
140
|
|
|
141
|
+
test('记录主机整帧写入与设备响应等待的分段耗时', async () => {
|
|
142
|
+
const log = getLogger(LoggerNames.Core);
|
|
143
|
+
const logSpy = jest.spyOn(log, 'log').mockImplementation(() => undefined);
|
|
144
|
+
const typedCall = jest.fn().mockImplementation((_type, _resType, _request, options) => {
|
|
145
|
+
options.onWriteCompleted({ elapsedMs: 25, frameBytes: 128 });
|
|
146
|
+
return Promise.resolve({ message: { processed_byte: 3 } });
|
|
147
|
+
});
|
|
148
|
+
const dateNowSpy = jest
|
|
149
|
+
.spyOn(Date, 'now')
|
|
150
|
+
.mockReturnValueOnce(1_000)
|
|
151
|
+
.mockReturnValueOnce(1_010)
|
|
152
|
+
.mockReturnValueOnce(1_040)
|
|
153
|
+
.mockReturnValueOnce(1_050);
|
|
154
|
+
|
|
155
|
+
try {
|
|
156
|
+
await writeProtocolV2File({
|
|
157
|
+
commands: { typedCall } as any,
|
|
158
|
+
path: 'vol0:/firmware.bin',
|
|
159
|
+
data: new Uint8Array([1, 2, 3]),
|
|
160
|
+
});
|
|
161
|
+
|
|
162
|
+
expect(logSpy).toHaveBeenLastCalledWith(
|
|
163
|
+
'[FileWrite] metrics transport=unknown status=completed path=vol0:/firmware.bin bytes=3/3 elapsed=0.05s speed=0.06 KiB/s hostWriteTotal=0.03s responseWaitTotal=0.03s measuredAttempts=1'
|
|
164
|
+
);
|
|
165
|
+
} finally {
|
|
166
|
+
dateNowSpy.mockRestore();
|
|
167
|
+
logSpy.mockRestore();
|
|
168
|
+
}
|
|
169
|
+
});
|
|
170
|
+
|
|
138
171
|
test('按确认分片的时间窗口记录实时传输速率', async () => {
|
|
139
172
|
const data = new Uint8Array(4097);
|
|
140
173
|
const typedCall = jest.fn().mockResolvedValue({ message: {} });
|
|
@@ -175,7 +208,7 @@ describe('writeProtocolV2File', () => {
|
|
|
175
208
|
});
|
|
176
209
|
|
|
177
210
|
test('通过 Core Log 每十秒输出一次 BLE 传输关键指标', async () => {
|
|
178
|
-
const log = getLogger(LoggerNames.
|
|
211
|
+
const log = getLogger(LoggerNames.Core);
|
|
179
212
|
const logSpy = jest.spyOn(log, 'log').mockImplementation(() => undefined);
|
|
180
213
|
const getSettingsSpy = jest
|
|
181
214
|
.spyOn(DataManager, 'getSettings')
|
|
@@ -197,14 +230,18 @@ describe('writeProtocolV2File', () => {
|
|
|
197
230
|
data,
|
|
198
231
|
});
|
|
199
232
|
|
|
200
|
-
expect(logSpy).toHaveBeenCalledTimes(
|
|
233
|
+
expect(logSpy).toHaveBeenCalledTimes(3);
|
|
201
234
|
expect(logSpy).toHaveBeenNthCalledWith(
|
|
202
235
|
1,
|
|
203
|
-
'[FileWrite]
|
|
236
|
+
'[FileWrite] started transport=BLE path=vol1:/wallpapers/test.bin bytes=5400 offset=0 chunk=1800'
|
|
204
237
|
);
|
|
205
238
|
expect(logSpy).toHaveBeenNthCalledWith(
|
|
206
239
|
2,
|
|
207
|
-
'[FileWrite] metrics transport=BLE status=
|
|
240
|
+
'[FileWrite] metrics transport=BLE status=progress path=vol1:/wallpapers/test.bin bytes=3600/5400 elapsed=10.00s speed=0.35 KiB/s'
|
|
241
|
+
);
|
|
242
|
+
expect(logSpy).toHaveBeenNthCalledWith(
|
|
243
|
+
3,
|
|
244
|
+
'[FileWrite] metrics transport=BLE status=completed path=vol1:/wallpapers/test.bin bytes=5400/5400 elapsed=14.00s speed=0.44 KiB/s'
|
|
208
245
|
);
|
|
209
246
|
} finally {
|
|
210
247
|
dateNowSpy.mockRestore();
|
|
@@ -215,7 +252,7 @@ describe('writeProtocolV2File', () => {
|
|
|
215
252
|
});
|
|
216
253
|
|
|
217
254
|
test('写入失败时通过 Core Log 输出已传输字节和平均速率', async () => {
|
|
218
|
-
const log = getLogger(LoggerNames.
|
|
255
|
+
const log = getLogger(LoggerNames.Core);
|
|
219
256
|
const logSpy = jest.spyOn(log, 'log').mockImplementation(() => undefined);
|
|
220
257
|
const typedCall = jest.fn().mockRejectedValue(new Error('write failed'));
|
|
221
258
|
const dateNowSpy = jest
|
|
@@ -234,7 +271,11 @@ describe('writeProtocolV2File', () => {
|
|
|
234
271
|
|
|
235
272
|
expect(logSpy).toHaveBeenNthCalledWith(
|
|
236
273
|
1,
|
|
237
|
-
'[FileWrite]
|
|
274
|
+
'[FileWrite] started transport=unknown path=vol1:/wallpapers/test.bin bytes=4000 offset=0 chunk=4000'
|
|
275
|
+
);
|
|
276
|
+
expect(logSpy).toHaveBeenNthCalledWith(
|
|
277
|
+
2,
|
|
278
|
+
'[FileWrite] metrics transport=unknown status=failed path=vol1:/wallpapers/test.bin bytes=0/4000 elapsed=1.00s speed=0.00 KiB/s'
|
|
238
279
|
);
|
|
239
280
|
} finally {
|
|
240
281
|
dateNowSpy.mockRestore();
|
|
@@ -13,13 +13,14 @@ type ProtocolV2FirmwareReleasePlan = {
|
|
|
13
13
|
targetsToUpdate: FirmwareUpdateV4Target[];
|
|
14
14
|
release: IFirmwareReleaseInfo | undefined;
|
|
15
15
|
};
|
|
16
|
-
export declare function buildProtocolV2FirmwareRelease({ currentVersions, currentVerification, checkFirmwareHash, remotePayloadHashes, firmwareType, release, }: {
|
|
16
|
+
export declare function buildProtocolV2FirmwareRelease({ currentVersions, currentVerification, checkFirmwareHash, remotePayloadHashes, firmwareType, release, deviceType, }: {
|
|
17
17
|
currentVersions: DeviceStateVersions;
|
|
18
18
|
currentVerification?: Partial<DeviceFeaturesVerify>;
|
|
19
19
|
checkFirmwareHash?: boolean;
|
|
20
20
|
remotePayloadHashes?: Readonly<Record<string, string | null>>;
|
|
21
21
|
firmwareType: EFirmwareType;
|
|
22
22
|
release: IFirmwareReleaseInfo | undefined;
|
|
23
|
+
deviceType?: 'pro2' | 'neo';
|
|
23
24
|
}): ProtocolV2FirmwareReleasePlan;
|
|
24
25
|
export default class CheckAllFirmwareRelease extends BaseMethod {
|
|
25
26
|
getSupportedProtocols(): readonly ["V1", "V2"];
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"CheckAllFirmwareRelease.d.ts","sourceRoot":"","sources":["../../src/api/CheckAllFirmwareRelease.ts"],"names":[],"mappings":"AAAA,OAAO,EAEL,aAAa,EAId,MAAM,qBAAqB,CAAC;AAG7B,OAAO,EAAE,UAAU,EAAE,MAAM,cAAc,CAAC;AAyB1C,OAAO,KAAK,EACV,kBAAkB,EAElB,kCAAkC,EAClC,+BAA+B,EAChC,MAAM,sCAAsC,CAAC;AAC9C,OAAO,KAAK,EAAE,sBAAsB,EAAE,MAAM,6BAA6B,CAAC;AAC1E,OAAO,KAAK,EACV,oBAAoB,EACpB,mBAAmB,EACnB,oBAAoB,EAGrB,MAAM,UAAU,CAAC;AAgIlB,KAAK,6BAA6B,GAAG;IACnC,YAAY,EAAE,aAAa,CAAC;IAC5B,MAAM,EAAE,+BAA+B,CAAC;IACxC,UAAU,EAAE,OAAO,CAAC;IACpB,QAAQ,EAAE,OAAO,CAAC;IAClB,eAAe,EAAE,mBAAmB,CAAC;IACrC,UAAU,EAAE,kCAAkC,EAAE,CAAC;IACjD,eAAe,EAAE,sBAAsB,EAAE,CAAC;IAC1C,OAAO,EAAE,oBAAoB,GAAG,SAAS,CAAC;CAC3C,CAAC;AAEF,wBAAgB,8BAA8B,CAAC,EAC7C,eAAe,EACf,mBAAwB,EACxB,iBAAyB,EACzB,mBAAwB,EACxB,YAAY,EACZ,OAAO,
|
|
1
|
+
{"version":3,"file":"CheckAllFirmwareRelease.d.ts","sourceRoot":"","sources":["../../src/api/CheckAllFirmwareRelease.ts"],"names":[],"mappings":"AAAA,OAAO,EAEL,aAAa,EAId,MAAM,qBAAqB,CAAC;AAG7B,OAAO,EAAE,UAAU,EAAE,MAAM,cAAc,CAAC;AAyB1C,OAAO,KAAK,EACV,kBAAkB,EAElB,kCAAkC,EAClC,+BAA+B,EAChC,MAAM,sCAAsC,CAAC;AAC9C,OAAO,KAAK,EAAE,sBAAsB,EAAE,MAAM,6BAA6B,CAAC;AAC1E,OAAO,KAAK,EACV,oBAAoB,EACpB,mBAAmB,EACnB,oBAAoB,EAGrB,MAAM,UAAU,CAAC;AAgIlB,KAAK,6BAA6B,GAAG;IACnC,YAAY,EAAE,aAAa,CAAC;IAC5B,MAAM,EAAE,+BAA+B,CAAC;IACxC,UAAU,EAAE,OAAO,CAAC;IACpB,QAAQ,EAAE,OAAO,CAAC;IAClB,eAAe,EAAE,mBAAmB,CAAC;IACrC,UAAU,EAAE,kCAAkC,EAAE,CAAC;IACjD,eAAe,EAAE,sBAAsB,EAAE,CAAC;IAC1C,OAAO,EAAE,oBAAoB,GAAG,SAAS,CAAC;CAC3C,CAAC;AAEF,wBAAgB,8BAA8B,CAAC,EAC7C,eAAe,EACf,mBAAwB,EACxB,iBAAyB,EACzB,mBAAwB,EACxB,YAAY,EACZ,OAAO,EACP,UAAU,GACX,EAAE;IACD,eAAe,EAAE,mBAAmB,CAAC;IACrC,mBAAmB,CAAC,EAAE,OAAO,CAAC,oBAAoB,CAAC,CAAC;IACpD,iBAAiB,CAAC,EAAE,OAAO,CAAC;IAC5B,mBAAmB,CAAC,EAAE,QAAQ,CAAC,MAAM,CAAC,MAAM,EAAE,MAAM,GAAG,IAAI,CAAC,CAAC,CAAC;IAC9D,YAAY,EAAE,aAAa,CAAC;IAC5B,OAAO,EAAE,oBAAoB,GAAG,SAAS,CAAC;IAC1C,UAAU,CAAC,EAAE,MAAM,GAAG,KAAK,CAAC;CAC7B,GAAG,6BAA6B,CAiFhC;AAID,MAAM,CAAC,OAAO,OAAO,uBAAwB,SAAQ,UAAU;IAC7D,qBAAqB;IAIrB,IAAI;IAME,GAAG;YAuFK,aAAa;CA4F5B"}
|
|
@@ -1,5 +1,7 @@
|
|
|
1
|
+
import { EDeviceType } from '@onekeyfe/hd-shared';
|
|
1
2
|
import { FirmwareUpdateBaseMethod } from './firmware/FirmwareUpdateBaseMethod';
|
|
2
3
|
import type { FirmwareUpdateV4Params } from '../types/api/firmwareUpdate';
|
|
4
|
+
export declare function assertProtocolV2FirmwareTargetsSupported(deviceType: EDeviceType | string | undefined, params: FirmwareUpdateV4Params): void;
|
|
3
5
|
export declare const isProtocolV2FirmwareFingerprintValid: (binary: ArrayBuffer | Uint8Array, fingerprint: string | undefined) => boolean;
|
|
4
6
|
export declare const assertProtocolV2ReconnectIdentity: (expectedSerialNumber?: string, actualSerialNumber?: string, expectedPath?: string, actualPath?: string) => void;
|
|
5
7
|
export default class FirmwareUpdateV4 extends FirmwareUpdateBaseMethod<FirmwareUpdateV4Params> {
|
|
@@ -45,6 +47,8 @@ export default class FirmwareUpdateV4 extends FirmwareUpdateBaseMethod<FirmwareU
|
|
|
45
47
|
private prepareRemoteProtocolV2Binaries;
|
|
46
48
|
private getProtocolV2DeviceType;
|
|
47
49
|
private prepareProtocolV2BootResources;
|
|
50
|
+
private isProtocolV2BootResourceCurrent;
|
|
51
|
+
private mergeProtocolV2ResourceBundles;
|
|
48
52
|
private prepareExplicitProtocolV2ResourceFiles;
|
|
49
53
|
private prepareProtocolV2ResourceBundles;
|
|
50
54
|
private downloadProtocolV2Resource;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"FirmwareUpdateV4.d.ts","sourceRoot":"","sources":["../../src/api/FirmwareUpdateV4.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"FirmwareUpdateV4.d.ts","sourceRoot":"","sources":["../../src/api/FirmwareUpdateV4.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,WAAW,EAAkD,MAAM,qBAAqB,CAAC;AAyBlG,OAAO,EAAE,wBAAwB,EAAE,MAAM,qCAAqC,CAAC;AAwB/E,OAAO,KAAK,EAEV,sBAAsB,EAEvB,MAAM,6BAA6B,CAAC;AA2CrC,wBAAgB,wCAAwC,CACtD,UAAU,EAAE,WAAW,GAAG,MAAM,GAAG,SAAS,EAC5C,MAAM,EAAE,sBAAsB,QAgB/B;AAgUD,eAAO,MAAM,oCAAoC,WACvC,WAAW,GAAG,UAAU,eACnB,MAAM,GAAG,SAAS,YAKhC,CAAC;AAEF,eAAO,MAAM,iCAAiC,0BACrB,MAAM,uBACR,MAAM,iBACZ,MAAM,eACR,MAAM,SAsBpB,CAAC;AAUF,MAAM,CAAC,OAAO,OAAO,gBAAiB,SAAQ,wBAAwB,CAAC,sBAAsB,CAAC;IAC5F,OAAO,CAAC,8BAA8B,CAAC,CAAS;IAEhD,OAAO,CAAC,sBAAsB,CAAC,CAAS;IAExC,qBAAqB;IAIrB,OAAO,CAAC,yBAAyB,CAA4B;IAE7D,OAAO,CAAC,2BAA2B,CAAS;IAE5C,OAAO,CAAC,iCAAiC,CAA6B;IAEtE,OAAO,CAAC,6BAA6B,CAAC,CAAW;IAEjD,OAAO,CAAC,6BAA6B,CAAS;IAE9C,IAAI;IAoHJ,OAAO,CAAC,8BAA8B;IAwBhC,GAAG;;;;;YAKK,aAAa;YAwHb,4BAA4B;YAkB5B,0BAA0B;YAY1B,8BAA8B;YAK9B,+BAA+B;YAqD/B,gCAAgC;YAmDhC,8BAA8B;IAsB5C,OAAO,CAAC,8BAA8B;IA0BtC,OAAO,CAAC,kCAAkC;IAc1C,OAAO,CAAC,gCAAgC;IAsDxC,OAAO,CAAC,6BAA6B;YAsBvB,2BAA2B;IAWzC,OAAO,CAAC,yBAAyB;IAKjC,OAAO,CAAC,kCAAkC;IAS1C,OAAO,CAAC,8BAA8B;YAMxB,iCAAiC;YAOjC,iCAAiC;YAkBjC,iCAAiC;IAM/C,OAAO,CAAC,uBAAuB;IAI/B,OAAO,CAAC,4BAA4B;IAQpC,OAAO,CAAC,2BAA2B;IAsBnC,OAAO,CAAC,yBAAyB;IAiBjC,OAAO,CAAC,wBAAwB;YAkBlB,iCAAiC;YAmCjC,+BAA+B;IAqD7C,OAAO,CAAC,uBAAuB;YAMjB,8BAA8B;YA0C9B,+BAA+B;IAgD7C,OAAO,CAAC,8BAA8B;IAetC,OAAO,CAAC,sCAAsC;YAmChC,gCAAgC;YAqChC,0BAA0B;IAexC,OAAO,CAAC,6BAA6B;YAMvB,8BAA8B;YA8C9B,kCAAkC;IAgChD,OAAO,CAAC,0BAA0B;IAUlC,OAAO,CAAC,yBAAyB;IAc3B,6BAA6B;YAgCrB,+BAA+B;IAkD7C,OAAO,CAAC,6BAA6B;IAkCrC,OAAO,CAAC,8BAA8B;YA8CxB,uBAAuB;YAiCvB,6BAA6B;YAa7B,uBAAuB;YA0CvB,8BAA8B;YA2D9B,6BAA6B;IAuE3C,OAAO,CAAC,mCAAmC;YAI7B,0BAA0B;IAaxC,OAAO,CAAC,4BAA4B;IAyGpC,OAAO,CAAC,6BAA6B;YAcvB,uCAAuC;YA0JvC,gCAAgC;YAehC,yBAAyB;YAQzB,8BAA8B;IAQ5C,OAAO,CAAC,0BAA0B;YAkBpB,mCAAmC;YAWnC,qCAAqC;YAgDrC,yBAAyB;YA8DzB,8BAA8B;IAU5C,OAAO,CAAC,kCAAkC;YAQ5B,cAAc;YAuCd,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":"AASA,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,6BAA6B,CAAC;AAIlE,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,+BAA+B,GAAG;IAC5C,MAAM,EAAE,MAAM,CAAC;IACf,WAAW,EAAE,MAAM,CAAC;IACpB,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,iBAAiB,CAAC,EAAE,OAAO,CAAC;IAC5B,eAAe,CAAC,EAAE,MAAM,CAAC;IACzB,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,cAAc,CAAC,EAAE,MAAM,IAAI,CAAC;IAC5B,eAAe,CAAC,EAAE,CAAC,OAAO,EAAE,+BAA+B,KAAK,MAAM,GAAG,SAAS,CAAC;IACnF,UAAU,CAAC,EAAE,CAAC,QAAQ,EAAE,2BAA2B,KAAK,IAAI,CAAC;CAC9D,CAAC;
|
|
1
|
+
{"version":3,"file":"protocolV2FileWrite.d.ts","sourceRoot":"","sources":["../../../src/api/helpers/protocolV2FileWrite.ts"],"names":[],"mappings":"AASA,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,6BAA6B,CAAC;AAIlE,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,+BAA+B,GAAG;IAC5C,MAAM,EAAE,MAAM,CAAC;IACf,WAAW,EAAE,MAAM,CAAC;IACpB,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,cAAc,CAAC,EAAE,MAAM,CAAC;IACxB,SAAS,CAAC,EAAE,OAAO,CAAC;IACpB,MAAM,CAAC,EAAE,OAAO,CAAC;IACjB,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,iBAAiB,CAAC,EAAE,OAAO,CAAC;IAC5B,eAAe,CAAC,EAAE,MAAM,CAAC;IACzB,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,cAAc,CAAC,EAAE,MAAM,IAAI,CAAC;IAC5B,eAAe,CAAC,EAAE,CAAC,OAAO,EAAE,+BAA+B,KAAK,MAAM,GAAG,SAAS,CAAC;IACnF,UAAU,CAAC,EAAE,CAAC,QAAQ,EAAE,2BAA2B,KAAK,IAAI,CAAC;CAC9D,CAAC;AAyDF,wBAAgB,2BAA2B,CAAC,KAAK,EAAE,OAAO,WASzD;AA8CD,wBAAsB,mBAAmB,CAAC,OAAO,EAAE,0BAA0B;;;;;;GAuO5E"}
|
package/dist/index.d.ts
CHANGED
|
@@ -211,7 +211,7 @@ type IProtocolV2FirmwareComponent = {
|
|
|
211
211
|
expectedSize?: number;
|
|
212
212
|
version?: IVersionArray;
|
|
213
213
|
};
|
|
214
|
-
type IProtocolV2ResourceType = 'images' | 'animation' | 'wallpaper' | 'translations' | 'roobert' | 'noto';
|
|
214
|
+
type IProtocolV2ResourceType = 'images' | 'animation' | 'wallpaper' | 'translations' | 'roobert' | 'noto' | 'firmware_logo';
|
|
215
215
|
/** Pro2 RES package descriptor. Hashes identify content without a human-managed version. */
|
|
216
216
|
type IProtocolV2Resource = {
|
|
217
217
|
type: IProtocolV2ResourceType;
|
|
@@ -1454,6 +1454,7 @@ interface FirmwareUpdateV4Params {
|
|
|
1454
1454
|
/**
|
|
1455
1455
|
* Arbitrary Protocol V2 resource files written directly with FilesystemFileWrite.
|
|
1456
1456
|
* Use this for manifest-driven boot resources and other non-RESC files.
|
|
1457
|
+
* When provided, these files are authoritative for resource and boot_resources targets.
|
|
1457
1458
|
*/
|
|
1458
1459
|
resourceFiles?: Array<{
|
|
1459
1460
|
binary: ArrayBuffer;
|
package/dist/index.js
CHANGED
|
@@ -40511,6 +40511,7 @@ const PROTOCOL_V2_RESOURCE_TYPES = [
|
|
|
40511
40511
|
'translations',
|
|
40512
40512
|
'roobert',
|
|
40513
40513
|
'noto',
|
|
40514
|
+
'firmware_logo',
|
|
40514
40515
|
];
|
|
40515
40516
|
const PROTOCOL_V2_RESOURCE_DEVICE_PATHS = {
|
|
40516
40517
|
images: 'vol0:/bundles/images/images.okpkg',
|
|
@@ -40519,6 +40520,7 @@ const PROTOCOL_V2_RESOURCE_DEVICE_PATHS = {
|
|
|
40519
40520
|
translations: 'vol0:/bundles/translations/translations.okpkg',
|
|
40520
40521
|
roobert: 'vol0:/bundles/font/roobert.okpkg',
|
|
40521
40522
|
noto: 'vol0:/bundles/font/noto.okpkg',
|
|
40523
|
+
firmware_logo: 'vol0:/bundles/firmware_logo.okpkg',
|
|
40522
40524
|
};
|
|
40523
40525
|
const RESOURCE_TYPE_SET = new Set(PROTOCOL_V2_RESOURCE_TYPES);
|
|
40524
40526
|
const SHA256_HEX_LENGTH = 64;
|
|
@@ -40725,7 +40727,7 @@ function parseProtocolV2Resources(value) {
|
|
|
40725
40727
|
const stable = config.stable.map(validateResource);
|
|
40726
40728
|
const types = new Set(stable.map(resource => resource.type));
|
|
40727
40729
|
if (stable.length !== PROTOCOL_V2_RESOURCE_TYPES.length || types.size !== stable.length) {
|
|
40728
|
-
throw new Error(
|
|
40730
|
+
throw new Error(`Invalid Pro2 resources config: stable must contain ${PROTOCOL_V2_RESOURCE_TYPES.length} unique resource types`);
|
|
40729
40731
|
}
|
|
40730
40732
|
for (const type of PROTOCOL_V2_RESOURCE_TYPES) {
|
|
40731
40733
|
if (!types.has(type)) {
|
|
@@ -47498,7 +47500,7 @@ function buildComponentRelease({ configKey, component, currentVersions, currentV
|
|
|
47498
47500
|
required: releaseRequired && status === 'outdated',
|
|
47499
47501
|
};
|
|
47500
47502
|
}
|
|
47501
|
-
function buildProtocolV2FirmwareRelease({ currentVersions, currentVerification = {}, checkFirmwareHash = false, remotePayloadHashes = {}, firmwareType, release, }) {
|
|
47503
|
+
function buildProtocolV2FirmwareRelease({ currentVersions, currentVerification = {}, checkFirmwareHash = false, remotePayloadHashes = {}, firmwareType, release, deviceType, }) {
|
|
47502
47504
|
if (!release) {
|
|
47503
47505
|
return {
|
|
47504
47506
|
firmwareType,
|
|
@@ -47511,17 +47513,24 @@ function buildProtocolV2FirmwareRelease({ currentVersions, currentVerification =
|
|
|
47511
47513
|
release: undefined,
|
|
47512
47514
|
};
|
|
47513
47515
|
}
|
|
47514
|
-
let components = getOrderedComponentEntries(release).map(([configKey, component]) =>
|
|
47515
|
-
|
|
47516
|
-
|
|
47517
|
-
|
|
47518
|
-
|
|
47519
|
-
|
|
47520
|
-
|
|
47521
|
-
|
|
47522
|
-
|
|
47523
|
-
|
|
47524
|
-
|
|
47516
|
+
let components = getOrderedComponentEntries(release).map(([configKey, component]) => {
|
|
47517
|
+
const result = buildComponentRelease({
|
|
47518
|
+
configKey,
|
|
47519
|
+
component,
|
|
47520
|
+
currentVersions,
|
|
47521
|
+
currentVerification,
|
|
47522
|
+
checkFirmwareHash,
|
|
47523
|
+
remotePayloadHash: Object.prototype.hasOwnProperty.call(remotePayloadHashes, configKey)
|
|
47524
|
+
? remotePayloadHashes[configKey]
|
|
47525
|
+
: normalizeHex(component.payloadHash),
|
|
47526
|
+
releaseRequired: release.required,
|
|
47527
|
+
});
|
|
47528
|
+
if (deviceType === 'neo' &&
|
|
47529
|
+
(result.componentTarget === 'SE03' || result.componentTarget === 'SE04')) {
|
|
47530
|
+
return Object.assign(Object.assign({}, result), { updateTarget: null, status: 'unsupported', required: false });
|
|
47531
|
+
}
|
|
47532
|
+
return result;
|
|
47533
|
+
});
|
|
47525
47534
|
if (!currentVersions.applicationP2) {
|
|
47526
47535
|
const applicationP1 = components.find(component => component.componentTarget === 'APPLICATION_P1');
|
|
47527
47536
|
if (applicationP1) {
|
|
@@ -47663,6 +47672,7 @@ class CheckAllFirmwareRelease extends BaseMethod {
|
|
|
47663
47672
|
checkFirmwareHash,
|
|
47664
47673
|
firmwareType,
|
|
47665
47674
|
release,
|
|
47675
|
+
deviceType: state.identity.deviceType,
|
|
47666
47676
|
});
|
|
47667
47677
|
const resourceDeviceType = state.identity.deviceType === 'neo' ? hdShared.EDeviceType.Neo : hdShared.EDeviceType.Pro2;
|
|
47668
47678
|
const resources = DataManager.getProtocolV2Resources(resourceDeviceType);
|
|
@@ -50939,6 +50949,22 @@ const PROTOCOL_V2_OKPP_HEADER_SIZE = 0x52a0;
|
|
|
50939
50949
|
const PROTOCOL_V2_OKPP_PAYLOAD_HASH_OFFSET = 0x200;
|
|
50940
50950
|
const PROTOCOL_V2_OKPP_HEADER_HASH_OFFSET = 0x240;
|
|
50941
50951
|
const PROTOCOL_V2_OKPP_HASH_SIZE = 64;
|
|
50952
|
+
const PROTOCOL_V2_NEO_UNSUPPORTED_TARGETS = new Set(['se03', 'se04']);
|
|
50953
|
+
function assertProtocolV2FirmwareTargetsSupported(deviceType, params) {
|
|
50954
|
+
var _a;
|
|
50955
|
+
const unsupportedTargets = new Set(((_a = params.targetsToUpdate) !== null && _a !== void 0 ? _a : []).filter(target => PROTOCOL_V2_NEO_UNSUPPORTED_TARGETS.has(target)));
|
|
50956
|
+
if (params.se03Binary)
|
|
50957
|
+
unsupportedTargets.add('se03');
|
|
50958
|
+
if (params.se04Binary)
|
|
50959
|
+
unsupportedTargets.add('se04');
|
|
50960
|
+
if (!unsupportedTargets.size || deviceType === hdShared.EDeviceType.Pro2)
|
|
50961
|
+
return;
|
|
50962
|
+
const targetList = Array.from(unsupportedTargets).join(', ');
|
|
50963
|
+
const message = deviceType === hdShared.EDeviceType.Neo
|
|
50964
|
+
? `Neo only supports SE01 and SE02; unsupported firmware targets: ${targetList}`
|
|
50965
|
+
: `Cannot safely update ${targetList} without a confirmed Pro2 device type`;
|
|
50966
|
+
throw hdShared.ERRORS.TypedError(hdShared.HardwareErrorCode.DeviceNotSupportMethod, message);
|
|
50967
|
+
}
|
|
50942
50968
|
const getProtocolV2DeviceTransferProgress = (bytesBeforeChunk, bytesAfterChunk, totalBytes) => {
|
|
50943
50969
|
if (!Number.isFinite(totalBytes) || totalBytes <= 0) {
|
|
50944
50970
|
return 100;
|
|
@@ -50993,6 +51019,7 @@ const PROTOCOL_V2_REMOTE_COMPONENT_TARGETS = {
|
|
|
50993
51019
|
kind: 'firmware',
|
|
50994
51020
|
},
|
|
50995
51021
|
};
|
|
51022
|
+
const PROTOCOL_V2_FIRMWARE_STAGING_PATHS = new Set(Object.values(PROTOCOL_V2_REMOTE_COMPONENT_TARGETS).map(target => `${PROTOCOL_V2_FIRMWARE_STAGING_VOLUME}${target.fileName}`));
|
|
50996
51023
|
const PROTOCOL_V2_UPDATE_TARGET_BY_TARGET_ID = new Map([
|
|
50997
51024
|
[ProtocolV2FirmwareTargetType.FW_MGMT_TARGET_BOOTLOADER, 'boot'],
|
|
50998
51025
|
[ProtocolV2FirmwareTargetType.FW_MGMT_TARGET_APPLICATION_P1, 'app_v1'],
|
|
@@ -51268,17 +51295,21 @@ class FirmwareUpdateV4 extends FirmwareUpdateBaseMethod {
|
|
|
51268
51295
|
resourceBundleArtifacts: payload.resourceBundleArtifacts,
|
|
51269
51296
|
};
|
|
51270
51297
|
}
|
|
51271
|
-
getProtocolV2FirmwareChunkSize(direction = 'write') {
|
|
51298
|
+
getProtocolV2FirmwareChunkSize(direction = 'write', filePath) {
|
|
51272
51299
|
var _a, _b;
|
|
51273
51300
|
const payloadChunkSize = Number((_a = this.params) === null || _a === void 0 ? void 0 : _a.chunkSize);
|
|
51274
51301
|
const env = DataManager.getSettings('env');
|
|
51275
51302
|
const isBle = ((_b = this.params) === null || _b === void 0 ? void 0 : _b.platform) === 'native' || (env && DataManager.isBleConnect(env));
|
|
51276
51303
|
let maxChunkSize = hdTransport.PROTOCOL_V2_WEBUSB_FILE_CHUNK_SIZE;
|
|
51277
51304
|
if (isBle) {
|
|
51278
|
-
|
|
51279
|
-
|
|
51280
|
-
|
|
51305
|
+
if (direction === 'read') {
|
|
51306
|
+
maxChunkSize = hdTransport.PROTOCOL_V2_BLE_FILE_READ_CHUNK_SIZE;
|
|
51307
|
+
}
|
|
51308
|
+
else {
|
|
51309
|
+
maxChunkSize = PROTOCOL_V2_FIRMWARE_STAGING_PATHS.has(filePath !== null && filePath !== void 0 ? filePath : '')
|
|
51310
|
+
? hdTransport.PROTOCOL_V2_BLE_FIRMWARE_FILE_CHUNK_SIZE
|
|
51281
51311
|
: hdTransport.PROTOCOL_V2_BLE_FILE_CHUNK_SIZE;
|
|
51312
|
+
}
|
|
51282
51313
|
}
|
|
51283
51314
|
if (!Number.isFinite(payloadChunkSize) || payloadChunkSize <= 0) {
|
|
51284
51315
|
return maxChunkSize;
|
|
@@ -51296,6 +51327,11 @@ class FirmwareUpdateV4 extends FirmwareUpdateBaseMethod {
|
|
|
51296
51327
|
return __awaiter(this, void 0, void 0, function* () {
|
|
51297
51328
|
yield this.captureProtocolV2PhysicalIdentity();
|
|
51298
51329
|
const deviceFeatures = yield this.getProtocolV2DeviceFeatures();
|
|
51330
|
+
const currentDeviceType = this.device.getCurrentDeviceType();
|
|
51331
|
+
const capabilityDeviceType = currentDeviceType === hdShared.EDeviceType.Pro2 || currentDeviceType === hdShared.EDeviceType.Neo
|
|
51332
|
+
? currentDeviceType
|
|
51333
|
+
: getDeviceType(deviceFeatures);
|
|
51334
|
+
assertProtocolV2FirmwareTargetsSupported(capabilityDeviceType, this.params);
|
|
51299
51335
|
const deviceFirmwareType = getFirmwareType(deviceFeatures);
|
|
51300
51336
|
const firmwareType = (_a = this.params.firmwareType) !== null && _a !== void 0 ? _a : deviceFirmwareType;
|
|
51301
51337
|
this.validateExpectedTargetVersions();
|
|
@@ -51303,8 +51339,11 @@ class FirmwareUpdateV4 extends FirmwareUpdateBaseMethod {
|
|
|
51303
51339
|
((_b = this.params.resourceBundleArtifacts) === null || _b === void 0 ? void 0 : _b.length)) {
|
|
51304
51340
|
return this.runProtocolV2PreparedArtifacts(deviceFeatures, firmwareType);
|
|
51305
51341
|
}
|
|
51306
|
-
const
|
|
51307
|
-
const
|
|
51342
|
+
const hasExplicitResourceFiles = !!((_c = this.params.resourceFiles) === null || _c === void 0 ? void 0 : _c.length);
|
|
51343
|
+
const wantsStableResources = !!((_d = this.params.targetsToUpdate) === null || _d === void 0 ? void 0 : _d.includes('resource'));
|
|
51344
|
+
const wantsBootResources = !!((_e = this.params.targetsToUpdate) === null || _e === void 0 ? void 0 : _e.includes('boot_resources'));
|
|
51345
|
+
const needsRemoteResources = !hasExplicitResourceFiles && wantsStableResources;
|
|
51346
|
+
const needsRemoteBootResources = !hasExplicitResourceFiles && (wantsBootResources || wantsStableResources);
|
|
51308
51347
|
let fwBinaryMap = [];
|
|
51309
51348
|
let bootloaderBinary = null;
|
|
51310
51349
|
let installItems;
|
|
@@ -51335,7 +51374,7 @@ class FirmwareUpdateV4 extends FirmwareUpdateBaseMethod {
|
|
|
51335
51374
|
}
|
|
51336
51375
|
const bootResourceFiles = yield this.prepareProtocolV2BootResources();
|
|
51337
51376
|
if (bootResourceFiles === null || bootResourceFiles === void 0 ? void 0 : bootResourceFiles.length) {
|
|
51338
|
-
resourceBundles =
|
|
51377
|
+
resourceBundles = this.mergeProtocolV2ResourceBundles(resourceBundles, bootResourceFiles);
|
|
51339
51378
|
}
|
|
51340
51379
|
if (!needsRemoteResources) {
|
|
51341
51380
|
this.postTipMessage(exports.FirmwareUpdateTipMessage.FinishDownloadFirmware);
|
|
@@ -51358,7 +51397,7 @@ class FirmwareUpdateV4 extends FirmwareUpdateBaseMethod {
|
|
|
51358
51397
|
const enteredBootloader = yield this.enterProtocolV2BootloaderMode();
|
|
51359
51398
|
try {
|
|
51360
51399
|
const stableResources = yield this.prepareProtocolV2ResourceBundles();
|
|
51361
|
-
resourceBundles =
|
|
51400
|
+
resourceBundles = this.mergeProtocolV2ResourceBundles(resourceBundles, stableResources);
|
|
51362
51401
|
this.postTipMessage(exports.FirmwareUpdateTipMessage.FinishDownloadFirmware);
|
|
51363
51402
|
}
|
|
51364
51403
|
catch (err) {
|
|
@@ -51787,29 +51826,95 @@ class FirmwareUpdateV4 extends FirmwareUpdateBaseMethod {
|
|
|
51787
51826
|
throw new Error(`Unsupported Protocol V2 device type: ${deviceType}`);
|
|
51788
51827
|
}
|
|
51789
51828
|
prepareProtocolV2BootResources() {
|
|
51790
|
-
var _a, _b, _c;
|
|
51829
|
+
var _a, _b, _c, _d, _e;
|
|
51791
51830
|
return __awaiter(this, void 0, void 0, function* () {
|
|
51792
|
-
|
|
51831
|
+
const wantsStableResources = !!((_a = this.params.targetsToUpdate) === null || _a === void 0 ? void 0 : _a.includes('resource'));
|
|
51832
|
+
const wantsBootResources = !!((_b = this.params.targetsToUpdate) === null || _b === void 0 ? void 0 : _b.includes('boot_resources'));
|
|
51833
|
+
if (!wantsStableResources && !wantsBootResources) {
|
|
51793
51834
|
return undefined;
|
|
51835
|
+
}
|
|
51836
|
+
if ((_c = this.params.resourceFiles) === null || _c === void 0 ? void 0 : _c.length) {
|
|
51837
|
+
return undefined;
|
|
51838
|
+
}
|
|
51794
51839
|
const resource = DataManager.getProtocolV2BootResources(this.getProtocolV2DeviceType());
|
|
51795
|
-
if (!resource)
|
|
51796
|
-
|
|
51840
|
+
if (!resource) {
|
|
51841
|
+
if (wantsBootResources) {
|
|
51842
|
+
throw new Error('Missing Protocol V2 boot resources configuration');
|
|
51843
|
+
}
|
|
51844
|
+
Log$6.debug('[FirmwareUpdateV4] no boot resources configured; continue with stable resources');
|
|
51845
|
+
return undefined;
|
|
51846
|
+
}
|
|
51797
51847
|
const files = [];
|
|
51798
51848
|
for (const file of resource.files) {
|
|
51799
|
-
|
|
51800
|
-
|
|
51801
|
-
|
|
51802
|
-
|
|
51849
|
+
const isCurrent = !this.params.forcedUpdateRes && (yield this.isProtocolV2BootResourceCurrent(file));
|
|
51850
|
+
if (isCurrent) {
|
|
51851
|
+
Log$6.log(`[FirmwareUpdateV4] boot resource unchanged, skipping ${file.devicePath}`);
|
|
51852
|
+
}
|
|
51853
|
+
else {
|
|
51854
|
+
Log$6.log(`[FirmwareUpdateV4] downloading boot resource ${file.devicePath}`);
|
|
51855
|
+
const { binary } = yield getSysResourceBinary(file.url);
|
|
51856
|
+
if (!isProtocolV2ResourceFileValid(binary, file)) {
|
|
51857
|
+
throw new Error(`Boot resource file verification failed: ${file.devicePath}`);
|
|
51858
|
+
}
|
|
51859
|
+
files.push({
|
|
51860
|
+
name: (_e = (_d = file.name) !== null && _d !== void 0 ? _d : file.devicePath.split('/').pop()) !== null && _e !== void 0 ? _e : file.devicePath,
|
|
51861
|
+
binary,
|
|
51862
|
+
devicePath: file.devicePath,
|
|
51863
|
+
});
|
|
51803
51864
|
}
|
|
51804
|
-
files.push({
|
|
51805
|
-
name: (_c = (_b = file.name) !== null && _b !== void 0 ? _b : file.devicePath.split('/').pop()) !== null && _c !== void 0 ? _c : file.devicePath,
|
|
51806
|
-
binary,
|
|
51807
|
-
devicePath: file.devicePath,
|
|
51808
|
-
});
|
|
51809
51865
|
}
|
|
51810
51866
|
return files;
|
|
51811
51867
|
});
|
|
51812
51868
|
}
|
|
51869
|
+
isProtocolV2BootResourceCurrent(file) {
|
|
51870
|
+
var _a, _b, _c, _d;
|
|
51871
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
51872
|
+
try {
|
|
51873
|
+
const commands = this.device.getCommands();
|
|
51874
|
+
const pathInfo = yield commands.typedCall('FilesystemPathInfoQuery', 'FilesystemPathInfo', { path: file.devicePath }, { timeoutMs: PROTOCOL_V2_SHORT_RESPONSE_TIMEOUT });
|
|
51875
|
+
const size = toProtocolV2FiniteNumber((_a = pathInfo.message) === null || _a === void 0 ? void 0 : _a.size);
|
|
51876
|
+
if (!((_b = pathInfo.message) === null || _b === void 0 ? void 0 : _b.exist) ||
|
|
51877
|
+
((_c = pathInfo.message) === null || _c === void 0 ? void 0 : _c.directory) ||
|
|
51878
|
+
!Number.isSafeInteger(size) ||
|
|
51879
|
+
size !== file.size) {
|
|
51880
|
+
return false;
|
|
51881
|
+
}
|
|
51882
|
+
const digest = sha256.sha256.create();
|
|
51883
|
+
const chunkSize = this.getProtocolV2FirmwareChunkSize();
|
|
51884
|
+
let offset = 0;
|
|
51885
|
+
while (offset < file.size) {
|
|
51886
|
+
const response = yield commands.typedCall('FilesystemFileRead', 'FilesystemFile', {
|
|
51887
|
+
file: { path: file.devicePath, offset, total_size: 0 },
|
|
51888
|
+
chunk_len: Math.min(chunkSize, file.size - offset),
|
|
51889
|
+
}, { timeoutMs: PROTOCOL_V2_SHORT_RESPONSE_TIMEOUT });
|
|
51890
|
+
const data = toProtocolV2Bytes((_d = response.message) === null || _d === void 0 ? void 0 : _d.data);
|
|
51891
|
+
if (data.byteLength === 0)
|
|
51892
|
+
return false;
|
|
51893
|
+
const consumed = data.subarray(0, Math.min(data.byteLength, file.size - offset));
|
|
51894
|
+
digest.update(consumed);
|
|
51895
|
+
offset += consumed.byteLength;
|
|
51896
|
+
}
|
|
51897
|
+
return bytesToHex(digest.digest()) === normalizeProtocolV2Hex(file.fileHash);
|
|
51898
|
+
}
|
|
51899
|
+
catch (error) {
|
|
51900
|
+
Log$6.debug(`[FirmwareUpdateV4] unable to compare boot resource ${file.devicePath}; scheduling rewrite`, error);
|
|
51901
|
+
return false;
|
|
51902
|
+
}
|
|
51903
|
+
});
|
|
51904
|
+
}
|
|
51905
|
+
mergeProtocolV2ResourceBundles(...groups) {
|
|
51906
|
+
const merged = groups.flatMap(group => group !== null && group !== void 0 ? group : []);
|
|
51907
|
+
if (!merged.length)
|
|
51908
|
+
return undefined;
|
|
51909
|
+
const seenPaths = new Set();
|
|
51910
|
+
for (const bundle of merged) {
|
|
51911
|
+
if (seenPaths.has(bundle.devicePath)) {
|
|
51912
|
+
throw new Error(`Duplicate Protocol V2 resource devicePath: ${bundle.devicePath}`);
|
|
51913
|
+
}
|
|
51914
|
+
seenPaths.add(bundle.devicePath);
|
|
51915
|
+
}
|
|
51916
|
+
return merged;
|
|
51917
|
+
}
|
|
51813
51918
|
prepareExplicitProtocolV2ResourceFiles() {
|
|
51814
51919
|
var _a;
|
|
51815
51920
|
const files = (_a = this.params.resourceFiles) !== null && _a !== void 0 ? _a : [];
|
|
@@ -52240,7 +52345,7 @@ class FirmwareUpdateV4 extends FirmwareUpdateBaseMethod {
|
|
|
52240
52345
|
const transferStartedAt = Date.now();
|
|
52241
52346
|
yield writeFirmwareByteSource({
|
|
52242
52347
|
source,
|
|
52243
|
-
chunkSize: this.getProtocolV2FirmwareChunkSize(),
|
|
52348
|
+
chunkSize: this.getProtocolV2FirmwareChunkSize('write', filePath),
|
|
52244
52349
|
write: ({ data, sourceOffset, length, first }) => __awaiter(this, void 0, void 0, function* () {
|
|
52245
52350
|
const chunkEnd = sourceOffset + length;
|
|
52246
52351
|
const deviceProgress = getProtocolV2DeviceTransferProgress(processedSize + sourceOffset, processedSize + chunkEnd, totalSize);
|
|
@@ -52623,7 +52728,7 @@ class FirmwareUpdateV4 extends FirmwareUpdateBaseMethod {
|
|
|
52623
52728
|
});
|
|
52624
52729
|
}
|
|
52625
52730
|
isProtocolV2ReconnectIdentityError(error) {
|
|
52626
|
-
return this.normalizeErrorMessage(error).includes('Protocol V2 reconnect physical identity');
|
|
52731
|
+
return this.normalizeErrorMessage(error).includes('Protocol V2 reconnect physical identity mismatch');
|
|
52627
52732
|
}
|
|
52628
52733
|
fileWriteChunk(filePath, totalFileSize, offset, chunk, overwrite, progress) {
|
|
52629
52734
|
var _a;
|
|
@@ -52639,7 +52744,10 @@ class FirmwareUpdateV4 extends FirmwareUpdateBaseMethod {
|
|
|
52639
52744
|
overwrite,
|
|
52640
52745
|
append: false,
|
|
52641
52746
|
ui_percentage: progress !== null && progress !== void 0 ? progress : undefined,
|
|
52642
|
-
}, {
|
|
52747
|
+
}, {
|
|
52748
|
+
writeWithResponse: false,
|
|
52749
|
+
onWriteCompleted: () => undefined,
|
|
52750
|
+
});
|
|
52643
52751
|
if (writeRes.type !== 'FilesystemFile') {
|
|
52644
52752
|
if (writeRes.type === 'CallMethodError') {
|
|
52645
52753
|
if (((_a = writeRes.message.error) !== null && _a !== void 0 ? _a : '').indexOf(SESSION_ERROR) > -1) {
|
|
@@ -52808,7 +52916,7 @@ class DeviceGetOnboardingStatus extends BaseMethod {
|
|
|
52808
52916
|
}
|
|
52809
52917
|
}
|
|
52810
52918
|
|
|
52811
|
-
const Log$4 = getLogger(exports.LoggerNames.
|
|
52919
|
+
const Log$4 = getLogger(exports.LoggerNames.Core);
|
|
52812
52920
|
const MIN_FILE_CHUNK_SIZE = 64;
|
|
52813
52921
|
const FILE_TRANSFER_RATE_WINDOW_MS = 1000;
|
|
52814
52922
|
const FILE_TRANSFER_LOG_INTERVAL_MS = 10000;
|
|
@@ -52825,8 +52933,11 @@ function getFileTransferTransport() {
|
|
|
52825
52933
|
const env = DataManager.getSettings('env');
|
|
52826
52934
|
return env && DataManager.isBleConnect(env) ? 'BLE' : String(env !== null && env !== void 0 ? env : 'unknown');
|
|
52827
52935
|
}
|
|
52828
|
-
function logFileTransferMetrics({ transport, status, transferredBytes, totalBytes, elapsedMs, rateBytesPerSecond, }) {
|
|
52829
|
-
|
|
52936
|
+
function logFileTransferMetrics({ transport, status, path, transferredBytes, totalBytes, elapsedMs, rateBytesPerSecond, hostWriteElapsedMs, responseWaitElapsedMs, measuredAttempts, }) {
|
|
52937
|
+
const segmentedMetrics = measuredAttempts > 0
|
|
52938
|
+
? ` hostWriteTotal=${(hostWriteElapsedMs / 1000).toFixed(2)}s responseWaitTotal=${(responseWaitElapsedMs / 1000).toFixed(2)}s measuredAttempts=${measuredAttempts}`
|
|
52939
|
+
: '';
|
|
52940
|
+
Log$4.log(`[FileWrite] metrics transport=${transport} status=${status} path=${path} bytes=${transferredBytes}/${totalBytes} elapsed=${(elapsedMs / 1000).toFixed(2)}s speed=${formatFileTransferRate(rateBytesPerSecond)} KiB/s${segmentedMetrics}`);
|
|
52830
52941
|
}
|
|
52831
52942
|
function isProtocolV2ResponseTimeout(error) {
|
|
52832
52943
|
var _a, _b;
|
|
@@ -52897,7 +53008,12 @@ function writeProtocolV2File(options) {
|
|
|
52897
53008
|
if (totalSize < startOffset + dataLength) {
|
|
52898
53009
|
throw hdShared.ERRORS.TypedError(hdShared.HardwareErrorCode.RuntimeError, `FilesystemFileWrite totalSize ${totalSize} is smaller than offset + data length ${startOffset + dataLength}`);
|
|
52899
53010
|
}
|
|
52900
|
-
const
|
|
53011
|
+
const defaultChunkSizeLimit = getProtocolV2FileChunkLimit();
|
|
53012
|
+
const configuredChunkSizeLimit = Number(options.chunkSizeLimit);
|
|
53013
|
+
const chunkSizeLimit = Number.isFinite(configuredChunkSizeLimit) && configuredChunkSizeLimit > 0
|
|
53014
|
+
? Math.floor(configuredChunkSizeLimit)
|
|
53015
|
+
: defaultChunkSizeLimit;
|
|
53016
|
+
const chunkSize = normalizeChunkSize((_b = options.chunkSize) !== null && _b !== void 0 ? _b : options.chunkLen, chunkSizeLimit);
|
|
52901
53017
|
let written = 0;
|
|
52902
53018
|
let chunks = 0;
|
|
52903
53019
|
let lastMessage;
|
|
@@ -52908,7 +53024,11 @@ function writeProtocolV2File(options) {
|
|
|
52908
53024
|
let lastConfirmedAt = startTime;
|
|
52909
53025
|
let logWindowStartedAt = startTime;
|
|
52910
53026
|
let logWindowStartedBytes = 0;
|
|
53027
|
+
let hostWriteElapsedMs = 0;
|
|
53028
|
+
let responseWaitElapsedMs = 0;
|
|
53029
|
+
let measuredAttempts = 0;
|
|
52911
53030
|
const transport = getFileTransferTransport();
|
|
53031
|
+
Log$4.log(`[FileWrite] started transport=${transport} path=${options.path} bytes=${dataLength} offset=${startOffset} chunk=${chunkSize}`);
|
|
52912
53032
|
try {
|
|
52913
53033
|
while (written < dataLength) {
|
|
52914
53034
|
(_c = options.throwIfAborted) === null || _c === void 0 ? void 0 : _c.call(options);
|
|
@@ -52930,10 +53050,21 @@ function writeProtocolV2File(options) {
|
|
|
52930
53050
|
let response;
|
|
52931
53051
|
let isWritePending = true;
|
|
52932
53052
|
while (isWritePending) {
|
|
53053
|
+
let currentHostWriteElapsedMs;
|
|
53054
|
+
let responseWaitStartedAt;
|
|
52933
53055
|
try {
|
|
52934
53056
|
const callOptions = options.writeWithResponse === undefined
|
|
52935
|
-
? {
|
|
52936
|
-
|
|
53057
|
+
? {
|
|
53058
|
+
timeoutMs: options.timeoutMs,
|
|
53059
|
+
onWriteCompleted: ({ elapsedMs }) => {
|
|
53060
|
+
currentHostWriteElapsedMs = elapsedMs;
|
|
53061
|
+
responseWaitStartedAt = Date.now();
|
|
53062
|
+
},
|
|
53063
|
+
}
|
|
53064
|
+
: Object.assign(Object.assign({}, (options.timeoutMs === undefined ? {} : { timeoutMs: options.timeoutMs })), { writeWithResponse: options.writeWithResponse, onWriteCompleted: ({ elapsedMs }) => {
|
|
53065
|
+
currentHostWriteElapsedMs = elapsedMs;
|
|
53066
|
+
responseWaitStartedAt = Date.now();
|
|
53067
|
+
} });
|
|
52937
53068
|
response = yield options.commands.typedCall('FilesystemFileWrite', 'FilesystemFile', request, callOptions);
|
|
52938
53069
|
isWritePending = false;
|
|
52939
53070
|
}
|
|
@@ -52943,6 +53074,13 @@ function writeProtocolV2File(options) {
|
|
|
52943
53074
|
retryCount += 1;
|
|
52944
53075
|
(_k = options.throwIfAborted) === null || _k === void 0 ? void 0 : _k.call(options);
|
|
52945
53076
|
}
|
|
53077
|
+
finally {
|
|
53078
|
+
if (currentHostWriteElapsedMs !== undefined && responseWaitStartedAt !== undefined) {
|
|
53079
|
+
hostWriteElapsedMs += currentHostWriteElapsedMs;
|
|
53080
|
+
responseWaitElapsedMs += Math.max(Date.now() - responseWaitStartedAt, 0);
|
|
53081
|
+
measuredAttempts += 1;
|
|
53082
|
+
}
|
|
53083
|
+
}
|
|
52946
53084
|
}
|
|
52947
53085
|
if (!response) {
|
|
52948
53086
|
throw hdShared.ERRORS.TypedError(hdShared.HardwareErrorCode.RuntimeError, 'FilesystemFileWrite completed without a response');
|
|
@@ -52995,10 +53133,14 @@ function writeProtocolV2File(options) {
|
|
|
52995
53133
|
logFileTransferMetrics({
|
|
52996
53134
|
transport,
|
|
52997
53135
|
status: 'progress',
|
|
53136
|
+
path: options.path,
|
|
52998
53137
|
transferredBytes,
|
|
52999
53138
|
totalBytes: dataLength,
|
|
53000
53139
|
elapsedMs,
|
|
53001
53140
|
rateBytesPerSecond: getAverageFileTransferRate(logWindowBytes, logWindowElapsedMs),
|
|
53141
|
+
hostWriteElapsedMs,
|
|
53142
|
+
responseWaitElapsedMs,
|
|
53143
|
+
measuredAttempts,
|
|
53002
53144
|
});
|
|
53003
53145
|
logWindowStartedAt = now;
|
|
53004
53146
|
logWindowStartedBytes = transferredBytes;
|
|
@@ -53018,10 +53160,14 @@ function writeProtocolV2File(options) {
|
|
|
53018
53160
|
logFileTransferMetrics({
|
|
53019
53161
|
transport,
|
|
53020
53162
|
status: 'failed',
|
|
53163
|
+
path: options.path,
|
|
53021
53164
|
transferredBytes: written,
|
|
53022
53165
|
totalBytes: dataLength,
|
|
53023
53166
|
elapsedMs,
|
|
53024
53167
|
rateBytesPerSecond: getAverageFileTransferRate(logWindowBytes, logWindowElapsedMs),
|
|
53168
|
+
hostWriteElapsedMs,
|
|
53169
|
+
responseWaitElapsedMs,
|
|
53170
|
+
measuredAttempts,
|
|
53025
53171
|
});
|
|
53026
53172
|
throw error;
|
|
53027
53173
|
}
|
|
@@ -53031,10 +53177,14 @@ function writeProtocolV2File(options) {
|
|
|
53031
53177
|
logFileTransferMetrics({
|
|
53032
53178
|
transport,
|
|
53033
53179
|
status: 'completed',
|
|
53180
|
+
path: options.path,
|
|
53034
53181
|
transferredBytes: written,
|
|
53035
53182
|
totalBytes: dataLength,
|
|
53036
53183
|
elapsedMs,
|
|
53037
53184
|
rateBytesPerSecond: getAverageFileTransferRate(logWindowBytes, logWindowElapsedMs),
|
|
53185
|
+
hostWriteElapsedMs,
|
|
53186
|
+
responseWaitElapsedMs,
|
|
53187
|
+
measuredAttempts,
|
|
53038
53188
|
});
|
|
53039
53189
|
return Object.assign(Object.assign({}, lastMessage), { path: options.path, offset: startOffset, total_size: totalSize, processed_byte: startOffset + written, chunks });
|
|
53040
53190
|
});
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import type { IProtocolV2Resource, IProtocolV2ResourceFile, IProtocolV2ResourceType, IProtocolV2Resources } from '../../types';
|
|
2
2
|
import type { DeviceCommands } from '../../device/DeviceCommands';
|
|
3
|
-
export declare const PROTOCOL_V2_RESOURCE_TYPES: readonly ["images", "animation", "wallpaper", "translations", "roobert", "noto"];
|
|
3
|
+
export declare const PROTOCOL_V2_RESOURCE_TYPES: readonly ["images", "animation", "wallpaper", "translations", "roobert", "noto", "firmware_logo"];
|
|
4
4
|
export declare const PROTOCOL_V2_RESOURCE_DEVICE_PATHS: Readonly<Record<IProtocolV2ResourceType, string>>;
|
|
5
5
|
export declare const PROTOCOL_V2_RESOURCE_INVENTORY_TIMEOUT_MS: number;
|
|
6
6
|
export type ProtocolV2ResourceInventoryItem = {
|