@onekeyfe/hd-core 1.2.0-alpha.10 → 1.2.0-alpha.12
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 +25 -0
- package/__tests__/RequestQueue.test.ts +34 -0
- package/__tests__/pro2Wallpaper.test.ts +50 -0
- package/__tests__/protocol-v2.test.ts +511 -61
- package/__tests__/protocolV2FileWrite.test.ts +55 -0
- package/dist/api/BaseMethod.d.ts +4 -0
- package/dist/api/BaseMethod.d.ts.map +1 -1
- package/dist/api/FileWrite.d.ts.map +1 -1
- package/dist/api/FirmwareUpdateV4.d.ts +0 -4
- package/dist/api/FirmwareUpdateV4.d.ts.map +1 -1
- package/dist/api/GetPassphraseState.d.ts +1 -6
- package/dist/api/GetPassphraseState.d.ts.map +1 -1
- package/dist/api/UploadPortfolio.d.ts +18 -0
- package/dist/api/UploadPortfolio.d.ts.map +1 -0
- package/dist/api/helpers/protocolV2FileWrite.d.ts +32 -0
- package/dist/api/helpers/protocolV2FileWrite.d.ts.map +1 -0
- package/dist/api/index.d.ts +6 -0
- package/dist/api/index.d.ts.map +1 -1
- package/dist/api/protocol-v2/DeviceGetOnboardingStatus.d.ts +6 -0
- package/dist/api/protocol-v2/DeviceGetOnboardingStatus.d.ts.map +1 -0
- package/dist/api/protocol-v2/DeviceSessionGet.d.ts +1 -4
- package/dist/api/protocol-v2/DeviceSessionGet.d.ts.map +1 -1
- package/dist/api/protocol-v2/DeviceSettingsGet.d.ts +6 -0
- package/dist/api/protocol-v2/DeviceSettingsGet.d.ts.map +1 -0
- package/dist/api/protocol-v2/DeviceSettingsPageShow.d.ts +16 -0
- package/dist/api/protocol-v2/DeviceSettingsPageShow.d.ts.map +1 -0
- package/dist/api/protocol-v2/DeviceSettingsSet.d.ts +12 -0
- package/dist/api/protocol-v2/DeviceSettingsSet.d.ts.map +1 -0
- package/dist/api/protocol-v2/DeviceUploadWallpaper.d.ts +26 -0
- package/dist/api/protocol-v2/DeviceUploadWallpaper.d.ts.map +1 -0
- package/dist/core/RequestQueue.d.ts +2 -0
- package/dist/core/RequestQueue.d.ts.map +1 -1
- package/dist/core/index.d.ts +1 -0
- package/dist/core/index.d.ts.map +1 -1
- package/dist/device/Device.d.ts.map +1 -1
- package/dist/device/DeviceCommands.d.ts +4 -4
- package/dist/device/DeviceCommands.d.ts.map +1 -1
- package/dist/deviceProfile/buildDeviceFeatures.d.ts +2 -2
- package/dist/deviceProfile/buildDeviceFeatures.d.ts.map +1 -1
- package/dist/deviceProfile/buildDeviceProfile.d.ts.map +1 -1
- package/dist/events/call.d.ts +7 -0
- package/dist/events/call.d.ts.map +1 -1
- package/dist/events/core.d.ts +2 -2
- package/dist/events/core.d.ts.map +1 -1
- package/dist/events/iframe.d.ts +1 -0
- package/dist/events/iframe.d.ts.map +1 -1
- package/dist/index.d.ts +80 -23
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +922 -472
- package/dist/inject.d.ts +3 -2
- package/dist/inject.d.ts.map +1 -1
- package/dist/lowLevelInject.d.ts +2 -1
- package/dist/lowLevelInject.d.ts.map +1 -1
- package/dist/protocols/protocol-v2/features.d.ts +1 -0
- package/dist/protocols/protocol-v2/features.d.ts.map +1 -1
- package/dist/protocols/protocol-v2/index.d.ts +1 -1
- package/dist/protocols/protocol-v2/index.d.ts.map +1 -1
- package/dist/protocols/protocol-v2/unlockRetry.d.ts +9 -0
- package/dist/protocols/protocol-v2/unlockRetry.d.ts.map +1 -0
- package/dist/protocols/protocol-v2/walletSession.d.ts.map +1 -1
- package/dist/topLevelInject.d.ts.map +1 -1
- package/dist/types/api/firmwareUpdate.d.ts +2 -0
- package/dist/types/api/firmwareUpdate.d.ts.map +1 -1
- package/dist/types/api/getDeviceInfo.d.ts +1 -1
- package/dist/types/api/getDeviceInfo.d.ts.map +1 -1
- package/dist/types/api/getPassphraseState.d.ts +2 -10
- package/dist/types/api/getPassphraseState.d.ts.map +1 -1
- package/dist/types/api/index.d.ts +9 -2
- package/dist/types/api/index.d.ts.map +1 -1
- package/dist/types/api/protocolV2.d.ts +20 -4
- package/dist/types/api/protocolV2.d.ts.map +1 -1
- package/dist/types/device.d.ts +1 -1
- package/dist/types/device.d.ts.map +1 -1
- package/dist/utils/deviceFeaturesUtils.d.ts +0 -2
- package/dist/utils/deviceFeaturesUtils.d.ts.map +1 -1
- package/dist/utils/index.d.ts +2 -0
- package/dist/utils/index.d.ts.map +1 -1
- package/dist/utils/patch.d.ts +1 -1
- package/dist/utils/patch.d.ts.map +1 -1
- package/dist/utils/pro2Wallpaper.d.ts +12 -0
- package/dist/utils/pro2Wallpaper.d.ts.map +1 -0
- package/package.json +4 -4
- package/src/api/BaseMethod.ts +18 -0
- package/src/api/FileWrite.ts +18 -178
- package/src/api/FirmwareUpdateV4.ts +21 -91
- package/src/api/GetPassphraseState.ts +9 -18
- package/src/api/UploadPortfolio.ts +37 -0
- package/src/api/helpers/protocolV2FileWrite.ts +164 -0
- package/src/api/index.ts +6 -0
- package/src/api/protocol-v2/DeviceGetOnboardingStatus.ts +18 -0
- package/src/api/protocol-v2/DeviceSessionGet.ts +3 -14
- package/src/api/protocol-v2/DeviceSettingsGet.ts +16 -0
- package/src/api/protocol-v2/DeviceSettingsPageShow.ts +59 -0
- package/src/api/protocol-v2/DeviceSettingsSet.ts +39 -0
- package/src/api/protocol-v2/DeviceUploadWallpaper.ts +124 -0
- package/src/core/RequestQueue.ts +19 -0
- package/src/core/index.ts +10 -1
- package/src/data/messages/messages-protocol-v2.json +92 -8
- package/src/device/Device.ts +17 -3
- package/src/device/DeviceCommands.ts +9 -3
- package/src/deviceProfile/buildDeviceFeatures.ts +20 -12
- package/src/deviceProfile/buildDeviceProfile.ts +8 -6
- package/src/events/call.ts +6 -0
- package/src/events/core.ts +2 -0
- package/src/events/iframe.ts +1 -0
- package/src/index.ts +4 -0
- package/src/inject.ts +15 -0
- package/src/lowLevelInject.ts +3 -0
- package/src/protocols/protocol-v2/features.ts +19 -1
- package/src/protocols/protocol-v2/index.ts +2 -0
- package/src/protocols/protocol-v2/unlockRetry.ts +46 -0
- package/src/protocols/protocol-v2/walletSession.ts +14 -5
- package/src/topLevelInject.ts +2 -0
- package/src/types/api/firmwareUpdate.ts +12 -0
- package/src/types/api/getDeviceInfo.ts +1 -1
- package/src/types/api/getPassphraseState.ts +2 -11
- package/src/types/api/index.ts +14 -1
- package/src/types/api/protocolV2.ts +52 -3
- package/src/types/device.ts +1 -0
- package/src/utils/deviceFeaturesUtils.ts +3 -8
- package/src/utils/index.ts +6 -0
- package/src/utils/pro2Wallpaper.ts +111 -0
package/src/api/FileWrite.ts
CHANGED
|
@@ -1,9 +1,3 @@
|
|
|
1
|
-
import {
|
|
2
|
-
PROTOCOL_V2_BLE_FILE_CHUNK_SIZE,
|
|
3
|
-
PROTOCOL_V2_WEBUSB_FILE_CHUNK_SIZE,
|
|
4
|
-
} from '@onekeyfe/hd-transport';
|
|
5
|
-
import { ERRORS, HardwareErrorCode } from '@onekeyfe/hd-shared';
|
|
6
|
-
|
|
7
1
|
import { BaseMethod } from './BaseMethod';
|
|
8
2
|
import {
|
|
9
3
|
validateNonEmptyString,
|
|
@@ -12,8 +6,8 @@ import {
|
|
|
12
6
|
validateOptionalPercentage,
|
|
13
7
|
validateRequiredData,
|
|
14
8
|
} from './helpers/filesystemValidation';
|
|
9
|
+
import { writeProtocolV2File } from './helpers/protocolV2FileWrite';
|
|
15
10
|
import { UI_REQUEST, createUiMessage } from '../events/ui-request';
|
|
16
|
-
import { DataManager } from '../data-manager';
|
|
17
11
|
|
|
18
12
|
export type FileWriteParams = {
|
|
19
13
|
path: string;
|
|
@@ -28,75 +22,6 @@ export type FileWriteParams = {
|
|
|
28
22
|
timeoutMs?: number | string;
|
|
29
23
|
};
|
|
30
24
|
|
|
31
|
-
const MIN_FILE_CHUNK_SIZE = 64;
|
|
32
|
-
|
|
33
|
-
function getProtocolV2FileChunkLimit() {
|
|
34
|
-
const env = DataManager.getSettings('env');
|
|
35
|
-
if (env && DataManager.isBleConnect(env)) {
|
|
36
|
-
return PROTOCOL_V2_BLE_FILE_CHUNK_SIZE;
|
|
37
|
-
}
|
|
38
|
-
return PROTOCOL_V2_WEBUSB_FILE_CHUNK_SIZE;
|
|
39
|
-
}
|
|
40
|
-
|
|
41
|
-
async function dataToUint8Array(data: FileWriteParams['data'] | Blob): Promise<Uint8Array> {
|
|
42
|
-
if (typeof data === 'string') {
|
|
43
|
-
return new TextEncoder().encode(data);
|
|
44
|
-
}
|
|
45
|
-
|
|
46
|
-
if (data instanceof ArrayBuffer) {
|
|
47
|
-
return new Uint8Array(data);
|
|
48
|
-
}
|
|
49
|
-
|
|
50
|
-
if (ArrayBuffer.isView(data)) {
|
|
51
|
-
return new Uint8Array(data.buffer, data.byteOffset, data.byteLength);
|
|
52
|
-
}
|
|
53
|
-
|
|
54
|
-
if (typeof Blob !== 'undefined' && data instanceof Blob) {
|
|
55
|
-
return new Uint8Array(await data.arrayBuffer());
|
|
56
|
-
}
|
|
57
|
-
|
|
58
|
-
throw ERRORS.TypedError(
|
|
59
|
-
HardwareErrorCode.CallMethodInvalidParameter,
|
|
60
|
-
'Unsupported FilesystemFileWrite data'
|
|
61
|
-
);
|
|
62
|
-
}
|
|
63
|
-
|
|
64
|
-
function normalizeChunkSize(value: unknown, maxChunkSize: number): number {
|
|
65
|
-
const numeric = Number(value);
|
|
66
|
-
if (!Number.isFinite(numeric) || numeric <= 0) return maxChunkSize;
|
|
67
|
-
return Math.min(Math.max(Math.floor(numeric), MIN_FILE_CHUNK_SIZE), maxChunkSize);
|
|
68
|
-
}
|
|
69
|
-
|
|
70
|
-
function getConfirmedProgress(
|
|
71
|
-
processedByte: number,
|
|
72
|
-
totalSize: number,
|
|
73
|
-
written: number,
|
|
74
|
-
dataLength: number
|
|
75
|
-
) {
|
|
76
|
-
if (Number.isFinite(processedByte) && Number.isFinite(totalSize) && totalSize > 0) {
|
|
77
|
-
if (processedByte >= totalSize) return 100;
|
|
78
|
-
return Math.min(Math.max(Math.floor((processedByte / totalSize) * 100), 0), 99);
|
|
79
|
-
}
|
|
80
|
-
if (dataLength > 0) {
|
|
81
|
-
if (written >= dataLength) return 100;
|
|
82
|
-
return Math.min(Math.max(Math.floor((written / dataLength) * 100), 0), 99);
|
|
83
|
-
}
|
|
84
|
-
return 100;
|
|
85
|
-
}
|
|
86
|
-
|
|
87
|
-
function getDeviceTransferProgress(bytesBeforeChunk: number, bytesAfterChunk: number, totalBytes: number) {
|
|
88
|
-
if (!Number.isFinite(totalBytes) || totalBytes <= 0) {
|
|
89
|
-
return 100;
|
|
90
|
-
}
|
|
91
|
-
if (bytesBeforeChunk <= 0 && bytesAfterChunk < totalBytes) {
|
|
92
|
-
return 0;
|
|
93
|
-
}
|
|
94
|
-
if (bytesAfterChunk >= totalBytes) {
|
|
95
|
-
return 100;
|
|
96
|
-
}
|
|
97
|
-
return Math.min(Math.max(Math.ceil((bytesAfterChunk / totalBytes) * 100), 1), 99);
|
|
98
|
-
}
|
|
99
|
-
|
|
100
25
|
export default class FileWrite extends BaseMethod<FileWriteParams> {
|
|
101
26
|
init() {
|
|
102
27
|
// Protocol V2 (Pro2) 专属方法,core 调度层统一做非 V2 设备守卫
|
|
@@ -121,109 +46,24 @@ export default class FileWrite extends BaseMethod<FileWriteParams> {
|
|
|
121
46
|
}
|
|
122
47
|
|
|
123
48
|
async run() {
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
const offsetValue = Number(this.params.offset ?? 0);
|
|
127
|
-
const startOffset = Number.isFinite(offsetValue) && offsetValue > 0 ? offsetValue : 0;
|
|
128
|
-
const payloadTotalSize = Number(this.params.totalSize);
|
|
129
|
-
const totalSize =
|
|
130
|
-
Number.isFinite(payloadTotalSize) && payloadTotalSize > 0
|
|
131
|
-
? payloadTotalSize
|
|
132
|
-
: startOffset + dataLength;
|
|
133
|
-
|
|
134
|
-
if (totalSize < startOffset + dataLength) {
|
|
135
|
-
throw ERRORS.TypedError(
|
|
136
|
-
HardwareErrorCode.RuntimeError,
|
|
137
|
-
`FilesystemFileWrite totalSize ${totalSize} is smaller than offset + data length ${
|
|
138
|
-
startOffset + dataLength
|
|
139
|
-
}`
|
|
140
|
-
);
|
|
141
|
-
}
|
|
142
|
-
|
|
143
|
-
const chunkSize = normalizeChunkSize(
|
|
144
|
-
this.params.chunkSize ?? this.params.chunkLen,
|
|
145
|
-
getProtocolV2FileChunkLimit()
|
|
146
|
-
);
|
|
147
|
-
const overwrite = this.params.overwrite ?? false;
|
|
148
|
-
const append = this.params.append ?? false;
|
|
149
|
-
let written = 0;
|
|
150
|
-
let chunkIndex = 0;
|
|
151
|
-
let lastMessage: Record<string, unknown> | undefined;
|
|
152
|
-
const startTime = Date.now();
|
|
153
|
-
const timeoutMs =
|
|
154
|
-
this.params.timeoutMs === undefined ? undefined : Number(this.params.timeoutMs);
|
|
155
|
-
|
|
156
|
-
while (written < dataLength) {
|
|
157
|
-
const chunkEnd = Math.min(written + chunkSize, dataLength);
|
|
158
|
-
const chunk = data.slice(written, chunkEnd);
|
|
159
|
-
const offset = startOffset + written;
|
|
160
|
-
const isFirstChunk = chunkIndex === 0;
|
|
161
|
-
const progress =
|
|
162
|
-
this.params.uiPercentage ??
|
|
163
|
-
getDeviceTransferProgress(offset, offset + chunk.byteLength, totalSize);
|
|
164
|
-
|
|
165
|
-
const res = await this.device.commands.typedCall(
|
|
166
|
-
'FilesystemFileWrite',
|
|
167
|
-
'FilesystemFile',
|
|
168
|
-
{
|
|
169
|
-
file: {
|
|
170
|
-
path: this.params.path,
|
|
171
|
-
offset,
|
|
172
|
-
total_size: totalSize,
|
|
173
|
-
data: chunk,
|
|
174
|
-
},
|
|
175
|
-
overwrite: isFirstChunk ? overwrite : false,
|
|
176
|
-
append,
|
|
177
|
-
ui_percentage: progress,
|
|
178
|
-
},
|
|
179
|
-
{
|
|
180
|
-
timeoutMs,
|
|
181
|
-
}
|
|
182
|
-
);
|
|
183
|
-
|
|
184
|
-
lastMessage = res.message;
|
|
185
|
-
const processedByte = Number(res.message?.processed_byte);
|
|
186
|
-
if (Number.isFinite(processedByte) && processedByte > offset) {
|
|
187
|
-
written = processedByte - startOffset;
|
|
188
|
-
} else {
|
|
189
|
-
written += chunk.byteLength;
|
|
190
|
-
}
|
|
191
|
-
|
|
192
|
-
if (written > dataLength) {
|
|
193
|
-
throw ERRORS.TypedError(
|
|
194
|
-
HardwareErrorCode.RuntimeError,
|
|
195
|
-
`FilesystemFileWrite invalid processed_byte ${processedByte}`
|
|
196
|
-
);
|
|
197
|
-
}
|
|
198
|
-
|
|
199
|
-
const confirmedProcessedByte =
|
|
200
|
-
Number.isFinite(processedByte) && processedByte > offset
|
|
201
|
-
? processedByte
|
|
202
|
-
: startOffset + written;
|
|
203
|
-
if (typeof this.postMessage === 'function') {
|
|
204
|
-
const elapsedMs = Date.now() - startTime;
|
|
205
|
-
const transferredBytes = Math.min(written, dataLength);
|
|
206
|
-
this.postMessage(
|
|
207
|
-
createUiMessage(UI_REQUEST.DEVICE_PROGRESS, {
|
|
208
|
-
progress: getConfirmedProgress(confirmedProcessedByte, totalSize, written, dataLength),
|
|
209
|
-
transferredBytes,
|
|
210
|
-
totalBytes: dataLength,
|
|
211
|
-
rateBytesPerSecond:
|
|
212
|
-
elapsedMs > 0 ? Math.round((transferredBytes / elapsedMs) * 1000) : undefined,
|
|
213
|
-
elapsedMs,
|
|
214
|
-
})
|
|
215
|
-
);
|
|
216
|
-
}
|
|
217
|
-
chunkIndex += 1;
|
|
218
|
-
}
|
|
219
|
-
|
|
220
|
-
return Promise.resolve({
|
|
221
|
-
...lastMessage,
|
|
49
|
+
return writeProtocolV2File({
|
|
50
|
+
commands: this.device.commands,
|
|
222
51
|
path: this.params.path,
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
|
|
52
|
+
data: this.params.data,
|
|
53
|
+
offset: this.params.offset,
|
|
54
|
+
totalSize: this.params.totalSize,
|
|
55
|
+
chunkSize: this.params.chunkSize,
|
|
56
|
+
chunkLen: this.params.chunkLen,
|
|
57
|
+
overwrite: this.params.overwrite,
|
|
58
|
+
append: this.params.append,
|
|
59
|
+
uiPercentage: this.params.uiPercentage,
|
|
60
|
+
timeoutMs: this.params.timeoutMs === undefined ? undefined : Number(this.params.timeoutMs),
|
|
61
|
+
throwIfAborted: () => this.throwIfAborted(),
|
|
62
|
+
onProgress: payload => {
|
|
63
|
+
if (typeof this.postMessage === 'function') {
|
|
64
|
+
this.postMessage(createUiMessage(UI_REQUEST.DEVICE_PROGRESS, payload));
|
|
65
|
+
}
|
|
66
|
+
},
|
|
227
67
|
});
|
|
228
68
|
}
|
|
229
69
|
}
|
|
@@ -30,7 +30,7 @@ import {
|
|
|
30
30
|
isProtocolV2DeviceDisconnectedError,
|
|
31
31
|
} from './protocol-v2/helpers';
|
|
32
32
|
|
|
33
|
-
import type { FirmwareUpdateV4Params } from '../types/api/firmwareUpdate';
|
|
33
|
+
import type { FirmwareUpdateV4Params, FirmwareUpdateV4Target } from '../types/api/firmwareUpdate';
|
|
34
34
|
import type { EFirmwareType } from '@onekeyfe/hd-shared';
|
|
35
35
|
import type { PROTO } from '../constants';
|
|
36
36
|
import type { TypedResponseMessage } from '../device/DeviceCommands';
|
|
@@ -188,6 +188,17 @@ const PROTOCOL_V2_REMOTE_COMPONENT_TARGETS: Readonly<
|
|
|
188
188
|
},
|
|
189
189
|
};
|
|
190
190
|
|
|
191
|
+
const PROTOCOL_V2_UPDATE_TARGET_BY_TARGET_ID = new Map<number, FirmwareUpdateV4Target>([
|
|
192
|
+
[ProtocolV2FirmwareTargetType.FW_MGMT_TARGET_BOOTLOADER, 'boot'],
|
|
193
|
+
[ProtocolV2FirmwareTargetType.FW_MGMT_TARGET_APPLICATION_P1, 'app_v1'],
|
|
194
|
+
[ProtocolV2FirmwareTargetType.FW_MGMT_TARGET_APPLICATION_P2, 'app_v2'],
|
|
195
|
+
[ProtocolV2FirmwareTargetType.FW_MGMT_TARGET_COPROCESSOR, 'coprocessor'],
|
|
196
|
+
[ProtocolV2FirmwareTargetType.FW_MGMT_TARGET_SE01, 'se01'],
|
|
197
|
+
[ProtocolV2FirmwareTargetType.FW_MGMT_TARGET_SE02, 'se02'],
|
|
198
|
+
[ProtocolV2FirmwareTargetType.FW_MGMT_TARGET_SE03, 'se03'],
|
|
199
|
+
[ProtocolV2FirmwareTargetType.FW_MGMT_TARGET_SE04, 'se04'],
|
|
200
|
+
]);
|
|
201
|
+
|
|
191
202
|
const PROTOCOL_V2_ROMLOADER_UNSUPPORTED_MESSAGE =
|
|
192
203
|
'FW_MGMT_TARGET_ROMLOADER is not accepted by the current Pro2 bootloader update request. Flash romloader with the loader-specific flow instead of firmwareUpdateV4.';
|
|
193
204
|
|
|
@@ -282,13 +293,6 @@ const versionArrayToNumber = (version?: IVersionArray) => {
|
|
|
282
293
|
return version[0] * 0x10000 + version[1] * 0x100 + version[2];
|
|
283
294
|
};
|
|
284
295
|
|
|
285
|
-
const versionStringToArray = (version?: string | null): IVersionArray | undefined => {
|
|
286
|
-
if (!version) return undefined;
|
|
287
|
-
const parts = version.split('.').map(part => Number(part));
|
|
288
|
-
if (parts.length !== 3 || parts.some(part => !Number.isFinite(part))) return undefined;
|
|
289
|
-
return parts as IVersionArray;
|
|
290
|
-
};
|
|
291
|
-
|
|
292
296
|
const compareProtocolV2Versions = (current?: IVersionArray, target?: IVersionArray) => {
|
|
293
297
|
const currentNumber = versionArrayToNumber(current);
|
|
294
298
|
const targetNumber = versionArrayToNumber(target);
|
|
@@ -418,6 +422,7 @@ export default class FirmwareUpdateV4 extends FirmwareUpdateBaseMethod<FirmwareU
|
|
|
418
422
|
{ name: 'se03Binary', type: 'buffer' },
|
|
419
423
|
{ name: 'se04Binary', type: 'buffer' },
|
|
420
424
|
{ name: 'firmwareType', type: 'string' },
|
|
425
|
+
{ name: 'targetsToUpdate', type: 'array', allowEmpty: true },
|
|
421
426
|
{ name: 'platform', type: 'string' },
|
|
422
427
|
{ name: 'resourceBundleFiles', type: 'array', allowEmpty: true },
|
|
423
428
|
]);
|
|
@@ -436,6 +441,7 @@ export default class FirmwareUpdateV4 extends FirmwareUpdateBaseMethod<FirmwareU
|
|
|
436
441
|
se04Binary: payload.se04Binary,
|
|
437
442
|
resourceBundleFiles: payload.resourceBundleFiles,
|
|
438
443
|
firmwareType: payload.firmwareType,
|
|
444
|
+
targetsToUpdate: payload.targetsToUpdate,
|
|
439
445
|
platform: payload.platform,
|
|
440
446
|
};
|
|
441
447
|
}
|
|
@@ -601,63 +607,6 @@ export default class FirmwareUpdateV4 extends FirmwareUpdateBaseMethod<FirmwareU
|
|
|
601
607
|
return target;
|
|
602
608
|
}
|
|
603
609
|
|
|
604
|
-
private getProtocolV2ComponentTargetVersion(
|
|
605
|
-
release: IFirmwareReleaseInfo,
|
|
606
|
-
component: IProtocolV2FirmwareComponent,
|
|
607
|
-
target: ProtocolV2RemoteComponentTarget
|
|
608
|
-
) {
|
|
609
|
-
if (component.version) return component.version;
|
|
610
|
-
if (target.targetId === ProtocolV2FirmwareTargetType.FW_MGMT_TARGET_BOOTLOADER) {
|
|
611
|
-
return release.bootloaderVersion;
|
|
612
|
-
}
|
|
613
|
-
if (
|
|
614
|
-
target.targetId === ProtocolV2FirmwareTargetType.FW_MGMT_TARGET_APPLICATION_P1 ||
|
|
615
|
-
target.targetId === ProtocolV2FirmwareTargetType.FW_MGMT_TARGET_APPLICATION_P2
|
|
616
|
-
) {
|
|
617
|
-
return release.version;
|
|
618
|
-
}
|
|
619
|
-
return undefined;
|
|
620
|
-
}
|
|
621
|
-
|
|
622
|
-
private getProtocolV2ComponentCurrentVersion(
|
|
623
|
-
features: Features,
|
|
624
|
-
target: ProtocolV2RemoteComponentTarget
|
|
625
|
-
) {
|
|
626
|
-
switch (target.targetId) {
|
|
627
|
-
case ProtocolV2FirmwareTargetType.FW_MGMT_TARGET_BOOTLOADER:
|
|
628
|
-
return getDeviceBootloaderVersion(features);
|
|
629
|
-
case ProtocolV2FirmwareTargetType.FW_MGMT_TARGET_APPLICATION_P1:
|
|
630
|
-
case ProtocolV2FirmwareTargetType.FW_MGMT_TARGET_APPLICATION_P2:
|
|
631
|
-
return getDeviceFirmwareVersion(features);
|
|
632
|
-
case ProtocolV2FirmwareTargetType.FW_MGMT_TARGET_COPROCESSOR:
|
|
633
|
-
return getDeviceBLEFirmwareVersion(features);
|
|
634
|
-
case ProtocolV2FirmwareTargetType.FW_MGMT_TARGET_SE01:
|
|
635
|
-
return versionStringToArray(features.se01Version);
|
|
636
|
-
case ProtocolV2FirmwareTargetType.FW_MGMT_TARGET_SE02:
|
|
637
|
-
return versionStringToArray(features.se02Version);
|
|
638
|
-
case ProtocolV2FirmwareTargetType.FW_MGMT_TARGET_SE03:
|
|
639
|
-
return versionStringToArray(features.se03Version);
|
|
640
|
-
case ProtocolV2FirmwareTargetType.FW_MGMT_TARGET_SE04:
|
|
641
|
-
return versionStringToArray(features.se04Version);
|
|
642
|
-
default:
|
|
643
|
-
return undefined;
|
|
644
|
-
}
|
|
645
|
-
}
|
|
646
|
-
|
|
647
|
-
private isProtocolV2ComponentVersionSatisfied(
|
|
648
|
-
release: IFirmwareReleaseInfo,
|
|
649
|
-
component: IProtocolV2FirmwareComponent,
|
|
650
|
-
target: ProtocolV2RemoteComponentTarget,
|
|
651
|
-
features: Features
|
|
652
|
-
) {
|
|
653
|
-
const targetVersion = this.getProtocolV2ComponentTargetVersion(release, component, target);
|
|
654
|
-
if (!targetVersion) return false;
|
|
655
|
-
|
|
656
|
-
const currentVersion = this.getProtocolV2ComponentCurrentVersion(features, target);
|
|
657
|
-
const compareResult = compareProtocolV2Versions(currentVersion, targetVersion);
|
|
658
|
-
return compareResult !== undefined && compareResult >= 0;
|
|
659
|
-
}
|
|
660
|
-
|
|
661
610
|
private getProtocolV2ResourceFilePath(path: string) {
|
|
662
611
|
if (path.startsWith('vol')) return path;
|
|
663
612
|
if (path.startsWith('/')) return `vol0:${path}`;
|
|
@@ -709,25 +658,6 @@ export default class FirmwareUpdateV4 extends FirmwareUpdateBaseMethod<FirmwareU
|
|
|
709
658
|
return parseProtocolV2OkppHeader(headerBytes);
|
|
710
659
|
}
|
|
711
660
|
|
|
712
|
-
private shouldInstallRemoteProtocolV2Component(
|
|
713
|
-
release: IFirmwareReleaseInfo,
|
|
714
|
-
key: string,
|
|
715
|
-
component: IProtocolV2FirmwareComponent,
|
|
716
|
-
target: ProtocolV2RemoteComponentTarget,
|
|
717
|
-
features: Features
|
|
718
|
-
) {
|
|
719
|
-
const versionSatisfied = this.isProtocolV2ComponentVersionSatisfied(
|
|
720
|
-
release,
|
|
721
|
-
component,
|
|
722
|
-
target,
|
|
723
|
-
features
|
|
724
|
-
);
|
|
725
|
-
if (versionSatisfied) {
|
|
726
|
-
Log.log(`[FirmwareUpdateV4] skip Protocol V2 component ${key}; version is up to date`);
|
|
727
|
-
}
|
|
728
|
-
return !versionSatisfied;
|
|
729
|
-
}
|
|
730
|
-
|
|
731
661
|
private async downloadRemoteProtocolV2Component(
|
|
732
662
|
key: string,
|
|
733
663
|
component: IProtocolV2FirmwareComponent
|
|
@@ -763,16 +693,12 @@ export default class FirmwareUpdateV4 extends FirmwareUpdateBaseMethod<FirmwareU
|
|
|
763
693
|
}
|
|
764
694
|
|
|
765
695
|
const entries = this.getRemoteComponentEntries(release);
|
|
696
|
+
const targetsToUpdate = new Set(this.params.targetsToUpdate ?? []);
|
|
766
697
|
|
|
767
698
|
for (const [key, component] of entries) {
|
|
768
699
|
const target = this.getRemoteComponentTarget(key, component);
|
|
769
|
-
const
|
|
770
|
-
|
|
771
|
-
key,
|
|
772
|
-
component,
|
|
773
|
-
target,
|
|
774
|
-
features
|
|
775
|
-
);
|
|
700
|
+
const updateTarget = PROTOCOL_V2_UPDATE_TARGET_BY_TARGET_ID.get(target.targetId);
|
|
701
|
+
const shouldInstall = updateTarget ? targetsToUpdate.has(updateTarget) : false;
|
|
776
702
|
if (shouldInstall) {
|
|
777
703
|
const remoteBinary = await this.downloadRemoteProtocolV2Component(key, component);
|
|
778
704
|
if (remoteBinary.kind === 'bootloader') {
|
|
@@ -827,6 +753,10 @@ export default class FirmwareUpdateV4 extends FirmwareUpdateBaseMethod<FirmwareU
|
|
|
827
753
|
}));
|
|
828
754
|
}
|
|
829
755
|
|
|
756
|
+
if (!this.params.targetsToUpdate?.includes('resource')) {
|
|
757
|
+
return undefined;
|
|
758
|
+
}
|
|
759
|
+
|
|
830
760
|
// 模式2:远端配置模式,后续按需下载 + 比对
|
|
831
761
|
const release = DataManager.getFirmwareLatestRelease(features, firmwareType);
|
|
832
762
|
if (!release?.resourceBundles?.length) return undefined;
|
|
@@ -11,27 +11,18 @@ export default class GetPassphraseState extends BaseMethod {
|
|
|
11
11
|
}
|
|
12
12
|
|
|
13
13
|
async run() {
|
|
14
|
-
const { passphraseState
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
initSession: this.payload.initSession,
|
|
20
|
-
});
|
|
14
|
+
const { passphraseState } = await getPassphraseStateWithRefreshDeviceInfo(this.device, {
|
|
15
|
+
expectPassphraseState: this.payload.passphraseState,
|
|
16
|
+
onlyMainPin: this.payload.useEmptyPassphrase,
|
|
17
|
+
initSession: this.payload.initSession,
|
|
18
|
+
});
|
|
21
19
|
|
|
22
|
-
const
|
|
23
|
-
const passphraseProtection = this.device.getCurrentPassphraseProtection() ?? null;
|
|
20
|
+
const passphraseProtection = this.device.getCurrentPassphraseProtection();
|
|
24
21
|
const deviceType = this.device.getCurrentDeviceType();
|
|
25
22
|
const isProSeries = deviceType === EDeviceType.Pro || deviceType === EDeviceType.Pro2;
|
|
26
23
|
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
sessionId: this.payload.initSession
|
|
31
|
-
? newSession ?? undefined
|
|
32
|
-
: newSession ?? features?.sessionId ?? undefined,
|
|
33
|
-
unlockedAttachPin: unlockedAttachPin ?? features?.unlockedAttachPin,
|
|
34
|
-
passphraseProtection,
|
|
35
|
-
});
|
|
24
|
+
return Promise.resolve(
|
|
25
|
+
isProSeries || passphraseProtection === true ? passphraseState : undefined
|
|
26
|
+
);
|
|
36
27
|
}
|
|
37
28
|
}
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
import FileWrite from './FileWrite';
|
|
2
|
+
|
|
3
|
+
export type UploadPortfolioParams = {
|
|
4
|
+
packageBytes: ArrayBuffer | Uint8Array | Blob;
|
|
5
|
+
operationId?: string;
|
|
6
|
+
timeoutMs?: number | string;
|
|
7
|
+
};
|
|
8
|
+
|
|
9
|
+
const PORTFOLIO_PENDING_PATH = 'vol1:/portfolio/portfolio.pfol.pending';
|
|
10
|
+
const PORTFOLIO_CHUNK_SIZE = 2048;
|
|
11
|
+
|
|
12
|
+
export default class UploadPortfolio extends FileWrite {
|
|
13
|
+
init() {
|
|
14
|
+
const { packageBytes, timeoutMs } = this.payload as UploadPortfolioParams;
|
|
15
|
+
this.payload = {
|
|
16
|
+
...this.payload,
|
|
17
|
+
path: PORTFOLIO_PENDING_PATH,
|
|
18
|
+
offset: 0,
|
|
19
|
+
data: packageBytes,
|
|
20
|
+
chunkSize: PORTFOLIO_CHUNK_SIZE,
|
|
21
|
+
overwrite: true,
|
|
22
|
+
append: false,
|
|
23
|
+
timeoutMs,
|
|
24
|
+
};
|
|
25
|
+
super.init();
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
async run() {
|
|
29
|
+
const stagedFile = await super.run();
|
|
30
|
+
this.throwIfAborted();
|
|
31
|
+
await this.device.commands.typedCall('PortfolioUpdate', 'Success', {});
|
|
32
|
+
return {
|
|
33
|
+
...stagedFile,
|
|
34
|
+
portfolioUpdated: true,
|
|
35
|
+
};
|
|
36
|
+
}
|
|
37
|
+
}
|
|
@@ -0,0 +1,164 @@
|
|
|
1
|
+
import {
|
|
2
|
+
PROTOCOL_V2_BLE_FILE_CHUNK_SIZE,
|
|
3
|
+
PROTOCOL_V2_WEBUSB_FILE_CHUNK_SIZE,
|
|
4
|
+
} from '@onekeyfe/hd-transport';
|
|
5
|
+
import { ERRORS, HardwareErrorCode } from '@onekeyfe/hd-shared';
|
|
6
|
+
|
|
7
|
+
import { DataManager } from '../../data-manager';
|
|
8
|
+
|
|
9
|
+
import type { DeviceCommands } from '../../device/DeviceCommands';
|
|
10
|
+
|
|
11
|
+
export type ProtocolV2FileWriteData = ArrayBuffer | Uint8Array | Blob | string;
|
|
12
|
+
|
|
13
|
+
export type ProtocolV2FileWriteProgress = {
|
|
14
|
+
progress: number;
|
|
15
|
+
transferredBytes: number;
|
|
16
|
+
totalBytes: number;
|
|
17
|
+
rateBytesPerSecond?: number;
|
|
18
|
+
elapsedMs: number;
|
|
19
|
+
};
|
|
20
|
+
|
|
21
|
+
export type ProtocolV2FileWriteOptions = {
|
|
22
|
+
commands: Pick<DeviceCommands, 'typedCall'>;
|
|
23
|
+
path: string;
|
|
24
|
+
data: ProtocolV2FileWriteData;
|
|
25
|
+
offset?: number;
|
|
26
|
+
totalSize?: number;
|
|
27
|
+
chunkSize?: number;
|
|
28
|
+
chunkLen?: number;
|
|
29
|
+
overwrite?: boolean;
|
|
30
|
+
append?: boolean;
|
|
31
|
+
uiPercentage?: number;
|
|
32
|
+
timeoutMs?: number;
|
|
33
|
+
throwIfAborted?: () => void;
|
|
34
|
+
onProgress?: (progress: ProtocolV2FileWriteProgress) => void;
|
|
35
|
+
};
|
|
36
|
+
|
|
37
|
+
const MIN_FILE_CHUNK_SIZE = 64;
|
|
38
|
+
|
|
39
|
+
function getProtocolV2FileChunkLimit() {
|
|
40
|
+
const env = DataManager.getSettings('env');
|
|
41
|
+
return env && DataManager.isBleConnect(env)
|
|
42
|
+
? PROTOCOL_V2_BLE_FILE_CHUNK_SIZE
|
|
43
|
+
: PROTOCOL_V2_WEBUSB_FILE_CHUNK_SIZE;
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
async function dataToUint8Array(data: ProtocolV2FileWriteData): Promise<Uint8Array> {
|
|
47
|
+
if (typeof data === 'string') return new TextEncoder().encode(data);
|
|
48
|
+
if (data instanceof ArrayBuffer) return new Uint8Array(data);
|
|
49
|
+
if (ArrayBuffer.isView(data)) {
|
|
50
|
+
return new Uint8Array(data.buffer, data.byteOffset, data.byteLength);
|
|
51
|
+
}
|
|
52
|
+
if (typeof Blob !== 'undefined' && data instanceof Blob) {
|
|
53
|
+
return new Uint8Array(await data.arrayBuffer());
|
|
54
|
+
}
|
|
55
|
+
throw ERRORS.TypedError(
|
|
56
|
+
HardwareErrorCode.CallMethodInvalidParameter,
|
|
57
|
+
'Unsupported FilesystemFileWrite data'
|
|
58
|
+
);
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
function normalizeChunkSize(value: unknown, maxChunkSize: number): number {
|
|
62
|
+
const numeric = Number(value);
|
|
63
|
+
if (!Number.isFinite(numeric) || numeric <= 0) return maxChunkSize;
|
|
64
|
+
return Math.min(Math.max(Math.floor(numeric), MIN_FILE_CHUNK_SIZE), maxChunkSize);
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
function getDeviceTransferProgress(before: number, after: number, total: number) {
|
|
68
|
+
if (!Number.isFinite(total) || total <= 0) return 100;
|
|
69
|
+
if (before <= 0 && after < total) return 0;
|
|
70
|
+
if (after >= total) return 100;
|
|
71
|
+
return Math.min(Math.max(Math.ceil((after / total) * 100), 1), 99);
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
function getConfirmedProgress(processed: number, total: number, written: number, length: number) {
|
|
75
|
+
if (Number.isFinite(processed) && Number.isFinite(total) && total > 0) {
|
|
76
|
+
if (processed >= total) return 100;
|
|
77
|
+
return Math.min(Math.max(Math.floor((processed / total) * 100), 0), 99);
|
|
78
|
+
}
|
|
79
|
+
if (length > 0) return written >= length ? 100 : Math.floor((written / length) * 100);
|
|
80
|
+
return 100;
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
export async function writeProtocolV2File(options: ProtocolV2FileWriteOptions) {
|
|
84
|
+
options.throwIfAborted?.();
|
|
85
|
+
const data = await dataToUint8Array(options.data);
|
|
86
|
+
const dataLength = data.byteLength;
|
|
87
|
+
const startOffset =
|
|
88
|
+
Number.isFinite(options.offset) && Number(options.offset) > 0 ? Number(options.offset) : 0;
|
|
89
|
+
const totalSize =
|
|
90
|
+
Number.isFinite(options.totalSize) && Number(options.totalSize) > 0
|
|
91
|
+
? Number(options.totalSize)
|
|
92
|
+
: startOffset + dataLength;
|
|
93
|
+
|
|
94
|
+
if (totalSize < startOffset + dataLength) {
|
|
95
|
+
throw ERRORS.TypedError(
|
|
96
|
+
HardwareErrorCode.RuntimeError,
|
|
97
|
+
`FilesystemFileWrite totalSize ${totalSize} is smaller than offset + data length ${
|
|
98
|
+
startOffset + dataLength
|
|
99
|
+
}`
|
|
100
|
+
);
|
|
101
|
+
}
|
|
102
|
+
|
|
103
|
+
const chunkSize = normalizeChunkSize(
|
|
104
|
+
options.chunkSize ?? options.chunkLen,
|
|
105
|
+
getProtocolV2FileChunkLimit()
|
|
106
|
+
);
|
|
107
|
+
let written = 0;
|
|
108
|
+
let chunks = 0;
|
|
109
|
+
let lastMessage: Record<string, unknown> | undefined;
|
|
110
|
+
const startTime = Date.now();
|
|
111
|
+
|
|
112
|
+
while (written < dataLength) {
|
|
113
|
+
options.throwIfAborted?.();
|
|
114
|
+
const chunk = data.slice(written, Math.min(written + chunkSize, dataLength));
|
|
115
|
+
const offset = startOffset + written;
|
|
116
|
+
const progress =
|
|
117
|
+
options.uiPercentage ??
|
|
118
|
+
getDeviceTransferProgress(offset, offset + chunk.byteLength, totalSize);
|
|
119
|
+
const response = await options.commands.typedCall(
|
|
120
|
+
'FilesystemFileWrite',
|
|
121
|
+
'FilesystemFile',
|
|
122
|
+
{
|
|
123
|
+
file: { path: options.path, offset, total_size: totalSize, data: chunk },
|
|
124
|
+
overwrite: chunks === 0 ? options.overwrite ?? false : false,
|
|
125
|
+
append: options.append ?? false,
|
|
126
|
+
ui_percentage: progress,
|
|
127
|
+
},
|
|
128
|
+
{ timeoutMs: options.timeoutMs }
|
|
129
|
+
);
|
|
130
|
+
options.throwIfAborted?.();
|
|
131
|
+
lastMessage = response.message;
|
|
132
|
+
const processedByte = Number(response.message?.processed_byte);
|
|
133
|
+
written =
|
|
134
|
+
Number.isFinite(processedByte) && processedByte > offset
|
|
135
|
+
? processedByte - startOffset
|
|
136
|
+
: written + chunk.byteLength;
|
|
137
|
+
if (written > dataLength) {
|
|
138
|
+
throw ERRORS.TypedError(
|
|
139
|
+
HardwareErrorCode.RuntimeError,
|
|
140
|
+
`FilesystemFileWrite invalid processed_byte ${processedByte}`
|
|
141
|
+
);
|
|
142
|
+
}
|
|
143
|
+
chunks += 1;
|
|
144
|
+
const elapsedMs = Date.now() - startTime;
|
|
145
|
+
const transferredBytes = Math.min(written, dataLength);
|
|
146
|
+
options.onProgress?.({
|
|
147
|
+
progress: getConfirmedProgress(startOffset + written, totalSize, written, dataLength),
|
|
148
|
+
transferredBytes,
|
|
149
|
+
totalBytes: dataLength,
|
|
150
|
+
rateBytesPerSecond:
|
|
151
|
+
elapsedMs > 0 ? Math.round((transferredBytes / elapsedMs) * 1000) : undefined,
|
|
152
|
+
elapsedMs,
|
|
153
|
+
});
|
|
154
|
+
}
|
|
155
|
+
|
|
156
|
+
return {
|
|
157
|
+
...lastMessage,
|
|
158
|
+
path: options.path,
|
|
159
|
+
offset: startOffset,
|
|
160
|
+
total_size: totalSize,
|
|
161
|
+
processed_byte: startOffset + written,
|
|
162
|
+
chunks,
|
|
163
|
+
};
|
|
164
|
+
}
|
package/src/api/index.ts
CHANGED
|
@@ -49,11 +49,16 @@ export { default as ping } from './protocol-v2/Ping';
|
|
|
49
49
|
export { default as deviceReboot } from './protocol-v2/DeviceReboot';
|
|
50
50
|
export { default as deviceInfoGet } from './protocol-v2/DeviceInfoGet';
|
|
51
51
|
export { default as deviceStatusGet } from './protocol-v2/DeviceStatusGet';
|
|
52
|
+
export { default as deviceGetOnboardingStatus } from './protocol-v2/DeviceGetOnboardingStatus';
|
|
52
53
|
export { default as deviceSessionGet } from './protocol-v2/DeviceSessionGet';
|
|
53
54
|
export { default as deviceFirmwareUpdate } from './protocol-v2/DeviceFirmwareUpdate';
|
|
54
55
|
export { default as deviceGetFirmwareUpdateStatus } from './protocol-v2/DeviceGetFirmwareUpdateStatus';
|
|
55
56
|
export { default as deviceFactoryInfoSet } from './protocol-v2/DeviceFactoryInfoSet';
|
|
56
57
|
export { default as deviceFactoryInfoGet } from './protocol-v2/DeviceFactoryInfoGet';
|
|
58
|
+
export { default as deviceSettingsGet } from './protocol-v2/DeviceSettingsGet';
|
|
59
|
+
export { default as deviceSettingsSet } from './protocol-v2/DeviceSettingsSet';
|
|
60
|
+
export { default as deviceSettingsPageShow } from './protocol-v2/DeviceSettingsPageShow';
|
|
61
|
+
export { default as deviceUploadWallpaper } from './protocol-v2/DeviceUploadWallpaper';
|
|
57
62
|
export { default as filesystemPermissionFix } from './protocol-v2/FilesystemPermissionFix';
|
|
58
63
|
export { default as filesystemFormat } from './protocol-v2/FilesystemFormat';
|
|
59
64
|
export { default as filesystemDiskControl } from './protocol-v2/FilesystemDiskControl';
|
|
@@ -66,6 +71,7 @@ export { default as dirRemove } from './DirRemove';
|
|
|
66
71
|
export { default as pathInfo } from './PathInfo';
|
|
67
72
|
export { default as filesystemFileRead } from './FileRead';
|
|
68
73
|
export { default as filesystemFileWrite } from './FileWrite';
|
|
74
|
+
export { default as uploadPortfolio } from './UploadPortfolio';
|
|
69
75
|
export { default as filesystemFileDelete } from './FileDelete';
|
|
70
76
|
export { default as filesystemDirList } from './DirList';
|
|
71
77
|
export { default as filesystemDirMake } from './DirMake';
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
import { BaseMethod } from '../BaseMethod';
|
|
2
|
+
|
|
3
|
+
export default class DeviceGetOnboardingStatus extends BaseMethod {
|
|
4
|
+
init() {
|
|
5
|
+
this.requireProtocolV2 = true;
|
|
6
|
+
this.skipForceUpdateCheck = true;
|
|
7
|
+
this.useDevicePassphraseState = false;
|
|
8
|
+
}
|
|
9
|
+
|
|
10
|
+
async run() {
|
|
11
|
+
const { message } = await this.device.commands.typedCall(
|
|
12
|
+
'DevGetOnboardingStatus',
|
|
13
|
+
'DevOnboardingStatus',
|
|
14
|
+
{}
|
|
15
|
+
);
|
|
16
|
+
return message;
|
|
17
|
+
}
|
|
18
|
+
}
|