@matter/nodejs-shell 0.16.0-alpha.0-20251112-dba1973d5 → 0.16.0-alpha.0-20251125-16883ca92
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/README.md +210 -5
- package/dist/cjs/MatterNode.js +18 -0
- package/dist/cjs/MatterNode.js.map +1 -1
- package/dist/cjs/shell/Shell.js +8 -0
- package/dist/cjs/shell/Shell.js.map +2 -2
- package/dist/cjs/shell/cmd_cert.js +154 -0
- package/dist/cjs/shell/cmd_cert.js.map +6 -0
- package/dist/cjs/shell/cmd_config.js +62 -1
- package/dist/cjs/shell/cmd_config.js.map +1 -1
- package/dist/cjs/shell/cmd_dcl.js +198 -0
- package/dist/cjs/shell/cmd_dcl.js.map +6 -0
- package/dist/cjs/shell/cmd_nodes.js +160 -0
- package/dist/cjs/shell/cmd_nodes.js.map +1 -1
- package/dist/cjs/shell/cmd_ota.js +449 -0
- package/dist/cjs/shell/cmd_ota.js.map +6 -0
- package/dist/cjs/shell/cmd_vendor.js +118 -0
- package/dist/cjs/shell/cmd_vendor.js.map +6 -0
- package/package.json +10 -10
- package/src/MatterNode.ts +30 -1
- package/src/shell/Shell.ts +8 -0
- package/src/shell/cmd_cert.ts +156 -0
- package/src/shell/cmd_config.ts +80 -1
- package/src/shell/cmd_dcl.ts +221 -0
- package/src/shell/cmd_nodes.ts +192 -1
- package/src/shell/cmd_ota.ts +550 -0
- package/src/shell/cmd_vendor.ts +108 -0
package/src/MatterNode.ts
CHANGED
|
@@ -6,6 +6,7 @@
|
|
|
6
6
|
|
|
7
7
|
// Include this first to auto-register Crypto, Network and Time Node.js implementations
|
|
8
8
|
import { Environment, Logger, StorageContext, StorageService } from "#general";
|
|
9
|
+
import { DclCertificateService, DclOtaUpdateService, DclVendorInfoService } from "#protocol";
|
|
9
10
|
import { NodeId } from "#types";
|
|
10
11
|
import { CommissioningController, ControllerStore } from "@project-chip/matter.js";
|
|
11
12
|
import { CommissioningControllerNodeOptions, Endpoint, PairedNode } from "@project-chip/matter.js/device";
|
|
@@ -16,11 +17,12 @@ const logger = Logger.get("Node");
|
|
|
16
17
|
export class MatterNode {
|
|
17
18
|
#storageLocation?: string;
|
|
18
19
|
#storageContext?: StorageContext;
|
|
19
|
-
readonly #environment
|
|
20
|
+
readonly #environment: Environment;
|
|
20
21
|
commissioningController?: CommissioningController;
|
|
21
22
|
#started = false;
|
|
22
23
|
readonly #nodeNum: number;
|
|
23
24
|
readonly #netInterface?: string;
|
|
25
|
+
#dclFetchTestCertificates = false;
|
|
24
26
|
|
|
25
27
|
constructor(nodeNum: number, netInterface?: string) {
|
|
26
28
|
this.#environment = Environment.default;
|
|
@@ -33,6 +35,30 @@ export class MatterNode {
|
|
|
33
35
|
return this.#storageLocation;
|
|
34
36
|
}
|
|
35
37
|
|
|
38
|
+
get environment() {
|
|
39
|
+
return this.#environment;
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
get otaService() {
|
|
43
|
+
return this.environment.has(DclOtaUpdateService)
|
|
44
|
+
? this.environment.get(DclOtaUpdateService)
|
|
45
|
+
: new DclOtaUpdateService(this.environment); // Will add itself on initial instantiation
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
get certificateService() {
|
|
49
|
+
if (this.environment.has(DclCertificateService)) {
|
|
50
|
+
return this.environment.get(DclCertificateService);
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
return new DclCertificateService(this.environment, { fetchTestCertificates: this.#dclFetchTestCertificates });
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
get vendorInfoService() {
|
|
57
|
+
return this.environment.has(DclVendorInfoService)
|
|
58
|
+
? this.environment.get(DclVendorInfoService)
|
|
59
|
+
: new DclVendorInfoService(this.environment); // Will add itself on initial instantiation
|
|
60
|
+
}
|
|
61
|
+
|
|
36
62
|
async initialize(resetStorage: boolean) {
|
|
37
63
|
/**
|
|
38
64
|
* Initialize the storage system.
|
|
@@ -63,6 +89,9 @@ export class MatterNode {
|
|
|
63
89
|
}
|
|
64
90
|
this.#storageContext = controllerStore.storage.createContext("Node");
|
|
65
91
|
|
|
92
|
+
// Read DCL test certificates setting
|
|
93
|
+
this.#dclFetchTestCertificates = await this.#storageContext.get<boolean>("DclFetchTestCertificates", false);
|
|
94
|
+
|
|
66
95
|
const storageService = this.commissioningController.env.get(StorageService);
|
|
67
96
|
const baseLocation = storageService.location;
|
|
68
97
|
if (baseLocation !== undefined) {
|
package/src/shell/Shell.ts
CHANGED
|
@@ -13,17 +13,21 @@ import yargs from "yargs/yargs";
|
|
|
13
13
|
import { MatterNode } from "../MatterNode.js";
|
|
14
14
|
import { exit } from "../app";
|
|
15
15
|
import { commandlineParser } from "../util/CommandlineParser.js";
|
|
16
|
+
import cmdCert from "./cmd_cert.js";
|
|
16
17
|
import cmdAttributes from "./cmd_cluster-attributes";
|
|
17
18
|
import cmdCommands from "./cmd_cluster-commands";
|
|
18
19
|
import cmdEvents from "./cmd_cluster-events";
|
|
19
20
|
import cmdCommission from "./cmd_commission.js";
|
|
20
21
|
import cmdConfig from "./cmd_config.js";
|
|
22
|
+
import cmdDcl from "./cmd_dcl.js";
|
|
21
23
|
import cmdDiscover from "./cmd_discover.js";
|
|
22
24
|
import cmdIdentify from "./cmd_identify.js";
|
|
23
25
|
import cmdNodes from "./cmd_nodes.js";
|
|
26
|
+
import cmdOta from "./cmd_ota.js";
|
|
24
27
|
import cmdSession from "./cmd_session.js";
|
|
25
28
|
import cmdSubscribe from "./cmd_subscribe.js";
|
|
26
29
|
import cmdTlv from "./cmd_tlv";
|
|
30
|
+
import cmdVendor from "./cmd_vendor.js";
|
|
27
31
|
|
|
28
32
|
const MAX_HISTORY_SIZE = 1000;
|
|
29
33
|
|
|
@@ -148,7 +152,11 @@ export class Shell {
|
|
|
148
152
|
cmdAttributes(this.theNode),
|
|
149
153
|
cmdEvents(this.theNode),
|
|
150
154
|
cmdCommands(this.theNode),
|
|
155
|
+
cmdOta(this.theNode),
|
|
156
|
+
cmdCert(this.theNode),
|
|
157
|
+
cmdVendor(this.theNode),
|
|
151
158
|
cmdTlv(),
|
|
159
|
+
cmdDcl(),
|
|
152
160
|
exitCommand(),
|
|
153
161
|
])
|
|
154
162
|
.command({
|
|
@@ -0,0 +1,156 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @license
|
|
3
|
+
* Copyright 2022-2025 Matter.js Authors
|
|
4
|
+
* SPDX-License-Identifier: Apache-2.0
|
|
5
|
+
*/
|
|
6
|
+
|
|
7
|
+
import { Diagnostic } from "#general";
|
|
8
|
+
import type { Argv } from "yargs";
|
|
9
|
+
import { MatterNode } from "../MatterNode.js";
|
|
10
|
+
|
|
11
|
+
export default function commands(theNode: MatterNode) {
|
|
12
|
+
return {
|
|
13
|
+
command: "cert",
|
|
14
|
+
describe: "Certificate management operations",
|
|
15
|
+
builder: (yargs: Argv) =>
|
|
16
|
+
yargs
|
|
17
|
+
.command(
|
|
18
|
+
["*", "list [vendor-id]"],
|
|
19
|
+
"List all stored certificates",
|
|
20
|
+
yargs => {
|
|
21
|
+
return yargs.positional("vendor-id", {
|
|
22
|
+
describe: "Filter by vendor ID (hex format like 0xFFF1 or decimal)",
|
|
23
|
+
type: "string",
|
|
24
|
+
});
|
|
25
|
+
},
|
|
26
|
+
async argv => {
|
|
27
|
+
const { vendorId: vendorIdStr } = argv;
|
|
28
|
+
|
|
29
|
+
await theNode.start();
|
|
30
|
+
let certificates = theNode.certificateService.certificates;
|
|
31
|
+
|
|
32
|
+
// Filter by vendor ID if provided
|
|
33
|
+
if (vendorIdStr) {
|
|
34
|
+
let vendorId: number;
|
|
35
|
+
if (vendorIdStr.startsWith("0x")) {
|
|
36
|
+
const hexStr = vendorIdStr.replace(/^0x/i, "");
|
|
37
|
+
vendorId = parseInt(hexStr, 16);
|
|
38
|
+
} else {
|
|
39
|
+
vendorId = parseInt(vendorIdStr, 10);
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
if (!isFinite(vendorId)) {
|
|
43
|
+
console.error(`Error: Invalid vendor ID "${vendorIdStr}"`);
|
|
44
|
+
return;
|
|
45
|
+
}
|
|
46
|
+
certificates = certificates.filter(cert => cert.vid === vendorId);
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
if (certificates.length === 0) {
|
|
50
|
+
console.log(
|
|
51
|
+
vendorIdStr
|
|
52
|
+
? `No certificates found for vendor ID ${vendorIdStr}.`
|
|
53
|
+
: "No certificates found in storage.",
|
|
54
|
+
);
|
|
55
|
+
return;
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
console.log(`\nFound ${certificates.length} certificate(s):\n`);
|
|
59
|
+
|
|
60
|
+
certificates.forEach(cert => {
|
|
61
|
+
console.log(`Subject Key ID: ${cert.subjectKeyId}`);
|
|
62
|
+
console.log(` Subject: ${cert.subjectAsText || cert.subject || "N/A"}`);
|
|
63
|
+
console.log("");
|
|
64
|
+
});
|
|
65
|
+
},
|
|
66
|
+
)
|
|
67
|
+
.command(
|
|
68
|
+
"details <subject-key-id>",
|
|
69
|
+
"Display detailed information about a certificate",
|
|
70
|
+
yargs => {
|
|
71
|
+
return yargs.positional("subject-key-id", {
|
|
72
|
+
describe: "Subject Key ID of the certificate",
|
|
73
|
+
type: "string",
|
|
74
|
+
demandOption: true,
|
|
75
|
+
});
|
|
76
|
+
},
|
|
77
|
+
async argv => {
|
|
78
|
+
const { subjectKeyId } = argv;
|
|
79
|
+
|
|
80
|
+
await theNode.start();
|
|
81
|
+
const cert = theNode.certificateService.getCertificate(subjectKeyId);
|
|
82
|
+
if (!cert) {
|
|
83
|
+
console.error(`Certificate with subject key ID ${subjectKeyId} not found`);
|
|
84
|
+
return;
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
console.log("\nCertificate Details:");
|
|
88
|
+
console.log(Diagnostic.json(cert));
|
|
89
|
+
},
|
|
90
|
+
)
|
|
91
|
+
.command(
|
|
92
|
+
"as-pem <subject-key-id>",
|
|
93
|
+
"Get certificate in PEM format",
|
|
94
|
+
yargs => {
|
|
95
|
+
return yargs.positional("subject-key-id", {
|
|
96
|
+
describe: "Subject Key ID of the certificate",
|
|
97
|
+
type: "string",
|
|
98
|
+
demandOption: true,
|
|
99
|
+
});
|
|
100
|
+
},
|
|
101
|
+
async argv => {
|
|
102
|
+
const { subjectKeyId } = argv;
|
|
103
|
+
// Normalize subject key ID by removing colons
|
|
104
|
+
const normalizedId = subjectKeyId.replace(/:/g, "").toUpperCase();
|
|
105
|
+
|
|
106
|
+
await theNode.start();
|
|
107
|
+
const pemCert = await theNode.certificateService.getCertificateAsPem(normalizedId);
|
|
108
|
+
console.log(pemCert);
|
|
109
|
+
},
|
|
110
|
+
)
|
|
111
|
+
.command(
|
|
112
|
+
"delete <subject-key-id>",
|
|
113
|
+
"Deletes a certificate from the storage",
|
|
114
|
+
yargs => {
|
|
115
|
+
return yargs.positional("subject-key-id", {
|
|
116
|
+
describe: "Subject Key ID of the certificate to delete",
|
|
117
|
+
type: "string",
|
|
118
|
+
demandOption: true,
|
|
119
|
+
});
|
|
120
|
+
},
|
|
121
|
+
async argv => {
|
|
122
|
+
const { subjectKeyId } = argv;
|
|
123
|
+
// Normalize subject key ID by removing colons
|
|
124
|
+
const normalizedId = subjectKeyId.replace(/:/g, "").toUpperCase();
|
|
125
|
+
|
|
126
|
+
await theNode.start();
|
|
127
|
+
await theNode.certificateService.deleteCertificate(normalizedId);
|
|
128
|
+
console.log(`Certificate ${subjectKeyId} deleted successfully`);
|
|
129
|
+
},
|
|
130
|
+
)
|
|
131
|
+
.command(
|
|
132
|
+
"update",
|
|
133
|
+
"Update certificates from DCL",
|
|
134
|
+
yargs =>
|
|
135
|
+
yargs.option("force", {
|
|
136
|
+
describe: "Force re-download and overwrite existing certificates",
|
|
137
|
+
type: "boolean",
|
|
138
|
+
default: false,
|
|
139
|
+
}),
|
|
140
|
+
async argv => {
|
|
141
|
+
const { force } = argv;
|
|
142
|
+
await theNode.start();
|
|
143
|
+
|
|
144
|
+
console.log(`Updating certificates from DCL${force ? " (force mode)" : ""}...`);
|
|
145
|
+
await theNode.certificateService.update(force);
|
|
146
|
+
console.log("Certificate update completed successfully");
|
|
147
|
+
|
|
148
|
+
const count = theNode.certificateService.certificates.length;
|
|
149
|
+
console.log(`Total certificates in storage: ${count}`);
|
|
150
|
+
},
|
|
151
|
+
),
|
|
152
|
+
handler: async (argv: any) => {
|
|
153
|
+
argv.unhandled = true;
|
|
154
|
+
},
|
|
155
|
+
};
|
|
156
|
+
}
|
package/src/shell/cmd_config.ts
CHANGED
|
@@ -5,6 +5,7 @@
|
|
|
5
5
|
*/
|
|
6
6
|
|
|
7
7
|
import { Logger } from "#general";
|
|
8
|
+
import { DclCertificateService } from "@matter/protocol";
|
|
8
9
|
import { Argv } from "yargs";
|
|
9
10
|
import { MatterNode } from "../MatterNode";
|
|
10
11
|
import { setLogLevel } from "../app";
|
|
@@ -220,7 +221,42 @@ export default function commands(theNode: MatterNode) {
|
|
|
220
221
|
},
|
|
221
222
|
argv => doThreadCredentials(theNode, { action: "set", ...argv }),
|
|
222
223
|
);
|
|
223
|
-
})
|
|
224
|
+
})
|
|
225
|
+
|
|
226
|
+
// DCL Test Certificates
|
|
227
|
+
.command(
|
|
228
|
+
"dcl-test-certificates",
|
|
229
|
+
"Manage DCL test certificate fetching (production only vs. include test)",
|
|
230
|
+
yargs => {
|
|
231
|
+
return yargs
|
|
232
|
+
.command(
|
|
233
|
+
"* [action]",
|
|
234
|
+
"get/delete DCL test certificate setting",
|
|
235
|
+
yargs => {
|
|
236
|
+
return yargs.positional("action", {
|
|
237
|
+
describe: "get/delete",
|
|
238
|
+
choices: ["get", "delete"] as const,
|
|
239
|
+
default: "get",
|
|
240
|
+
type: "string",
|
|
241
|
+
});
|
|
242
|
+
},
|
|
243
|
+
async argv => doDclTestCertificates(theNode, argv),
|
|
244
|
+
)
|
|
245
|
+
.command(
|
|
246
|
+
"set <value>",
|
|
247
|
+
"Enable or disable test certificate fetching from DCL",
|
|
248
|
+
yargs => {
|
|
249
|
+
return yargs.positional("value", {
|
|
250
|
+
describe: "Enable test certificates (true/false)",
|
|
251
|
+
type: "string",
|
|
252
|
+
choices: ["true", "false"] as const,
|
|
253
|
+
demandOption: true,
|
|
254
|
+
});
|
|
255
|
+
},
|
|
256
|
+
async argv => doDclTestCertificates(theNode, { action: "set", ...argv }),
|
|
257
|
+
);
|
|
258
|
+
},
|
|
259
|
+
),
|
|
224
260
|
handler: async (argv: any) => {
|
|
225
261
|
argv.unhandled = true;
|
|
226
262
|
},
|
|
@@ -424,3 +460,46 @@ async function doThreadCredentials(
|
|
|
424
460
|
break;
|
|
425
461
|
}
|
|
426
462
|
}
|
|
463
|
+
|
|
464
|
+
async function doDclTestCertificates(
|
|
465
|
+
theNode: MatterNode,
|
|
466
|
+
args: {
|
|
467
|
+
action: string;
|
|
468
|
+
value?: string;
|
|
469
|
+
},
|
|
470
|
+
) {
|
|
471
|
+
const { action, value } = args;
|
|
472
|
+
switch (action) {
|
|
473
|
+
case "get":
|
|
474
|
+
const enabled = await theNode.Store.get<boolean>("DclFetchTestCertificates", false);
|
|
475
|
+
console.log(
|
|
476
|
+
`DCL test certificates: ${enabled ? "enabled (production + test + GitHub)" : "disabled (production only)"}`,
|
|
477
|
+
);
|
|
478
|
+
break;
|
|
479
|
+
case "set":
|
|
480
|
+
if (value === undefined) {
|
|
481
|
+
console.log(`Cannot change DCL test certificates setting: New value not provided`);
|
|
482
|
+
return;
|
|
483
|
+
}
|
|
484
|
+
const newValue = value === "true";
|
|
485
|
+
await theNode.Store.set("DclFetchTestCertificates", newValue);
|
|
486
|
+
|
|
487
|
+
// Close existing certificate service so it gets re-initialized with new setting
|
|
488
|
+
await theNode.environment.close(DclCertificateService);
|
|
489
|
+
|
|
490
|
+
console.log(
|
|
491
|
+
`DCL test certificates: ${newValue ? "enabled (production + test + GitHub)" : "disabled (production only)"}. Please restart the shell for the changes to take effect.`,
|
|
492
|
+
);
|
|
493
|
+
break;
|
|
494
|
+
case "delete":
|
|
495
|
+
await theNode.Store.delete("DclFetchTestCertificates");
|
|
496
|
+
|
|
497
|
+
// Close existing certificate service so it gets re-initialized with new setting
|
|
498
|
+
await theNode.environment.close(DclCertificateService);
|
|
499
|
+
|
|
500
|
+
console.log(
|
|
501
|
+
`DCL test certificates setting reset to default (disabled). Please restart the shell for the changes to take effect.`,
|
|
502
|
+
);
|
|
503
|
+
break;
|
|
504
|
+
}
|
|
505
|
+
}
|
|
@@ -0,0 +1,221 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @license
|
|
3
|
+
* Copyright 2022-2025 Matter.js Authors
|
|
4
|
+
* SPDX-License-Identifier: Apache-2.0
|
|
5
|
+
*/
|
|
6
|
+
|
|
7
|
+
import { Diagnostic } from "#general";
|
|
8
|
+
import { DclClient } from "@matter/protocol";
|
|
9
|
+
import type { Argv } from "yargs";
|
|
10
|
+
|
|
11
|
+
/**
|
|
12
|
+
* Parse a VID or PID from string (supports decimal or hex with 0x prefix)
|
|
13
|
+
*/
|
|
14
|
+
function parseVidPid(value: string, fieldName: string): number {
|
|
15
|
+
const num = value.startsWith("0x") ? parseInt(value, 16) : parseInt(value, 10);
|
|
16
|
+
if (isNaN(num) || num < 0 || num > 0xffff) {
|
|
17
|
+
throw new Error(`${fieldName} must be a valid 16-bit number`);
|
|
18
|
+
}
|
|
19
|
+
return num;
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
/**
|
|
23
|
+
* Get DCL environment description
|
|
24
|
+
*/
|
|
25
|
+
function getDclEnv(isTest: boolean): string {
|
|
26
|
+
return isTest ? "test" : "production";
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
/**
|
|
30
|
+
* Create yargs positional argument configuration for VID
|
|
31
|
+
*/
|
|
32
|
+
function vidPositional() {
|
|
33
|
+
return {
|
|
34
|
+
describe: "Vendor ID (decimal or hex with 0x prefix)",
|
|
35
|
+
type: "string" as const,
|
|
36
|
+
demandOption: true,
|
|
37
|
+
coerce: (value: string) => parseVidPid(value, "VID"),
|
|
38
|
+
};
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
/**
|
|
42
|
+
* Create yargs positional argument configuration for PID
|
|
43
|
+
*/
|
|
44
|
+
function pidPositional() {
|
|
45
|
+
return {
|
|
46
|
+
describe: "Product ID (decimal or hex with 0x prefix)",
|
|
47
|
+
type: "string" as const,
|
|
48
|
+
demandOption: true,
|
|
49
|
+
coerce: (value: string) => parseVidPid(value, "PID"),
|
|
50
|
+
};
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
/**
|
|
54
|
+
* DCL (Distributed Compliance Ledger) query commands
|
|
55
|
+
*
|
|
56
|
+
* These commands allow querying the CSA DCL for Matter compliance information,
|
|
57
|
+
* including root certificates, device models, and firmware versions.
|
|
58
|
+
*/
|
|
59
|
+
export default function commands() {
|
|
60
|
+
return {
|
|
61
|
+
command: "dcl",
|
|
62
|
+
describe: "Query the CSA Distributed Compliance Ledger (DCL) for Matter compliance information",
|
|
63
|
+
builder: (yargs: Argv) =>
|
|
64
|
+
yargs
|
|
65
|
+
.option("test", {
|
|
66
|
+
alias: "t",
|
|
67
|
+
describe: "Use test DCL network instead of production",
|
|
68
|
+
type: "boolean",
|
|
69
|
+
default: false,
|
|
70
|
+
global: true,
|
|
71
|
+
})
|
|
72
|
+
.command(
|
|
73
|
+
"fetch-root-certificates",
|
|
74
|
+
"Fetch list of all approved Product Attestation Authority (PAA) root certificates",
|
|
75
|
+
yargs => yargs,
|
|
76
|
+
async argv => {
|
|
77
|
+
const { test } = argv;
|
|
78
|
+
const client = new DclClient(!test);
|
|
79
|
+
|
|
80
|
+
try {
|
|
81
|
+
console.log(`Fetching root certificate list from ${getDclEnv(test)} DCL...`);
|
|
82
|
+
const certificates = await client.fetchRootCertificateList();
|
|
83
|
+
console.log(`Found ${certificates.length} root certificates:`);
|
|
84
|
+
console.log(JSON.stringify(certificates, null, 2));
|
|
85
|
+
} catch (error) {
|
|
86
|
+
console.error("Error fetching root certificates:", error);
|
|
87
|
+
}
|
|
88
|
+
},
|
|
89
|
+
)
|
|
90
|
+
.command(
|
|
91
|
+
"fetch-root-certificate <subject> <subjectKeyId>",
|
|
92
|
+
"Fetch detailed information for a specific root certificate",
|
|
93
|
+
yargs => {
|
|
94
|
+
return yargs
|
|
95
|
+
.positional("subject", {
|
|
96
|
+
describe: "Certificate subject (DN)",
|
|
97
|
+
type: "string",
|
|
98
|
+
demandOption: true,
|
|
99
|
+
})
|
|
100
|
+
.positional("subjectKeyId", {
|
|
101
|
+
describe: "Subject key identifier",
|
|
102
|
+
type: "string",
|
|
103
|
+
demandOption: true,
|
|
104
|
+
});
|
|
105
|
+
},
|
|
106
|
+
async argv => {
|
|
107
|
+
const { subject, subjectKeyId, test } = argv;
|
|
108
|
+
const client = new DclClient(!test);
|
|
109
|
+
|
|
110
|
+
try {
|
|
111
|
+
console.log(`Fetching certificate details from ${getDclEnv(test)} DCL...`);
|
|
112
|
+
console.log(`Subject: ${subject}`);
|
|
113
|
+
console.log(`Subject Key ID: ${subjectKeyId}`);
|
|
114
|
+
|
|
115
|
+
const certificate = await client.fetchRootCertificateBySubject({
|
|
116
|
+
subject,
|
|
117
|
+
subjectKeyId,
|
|
118
|
+
});
|
|
119
|
+
console.log("Certificate details:");
|
|
120
|
+
console.log(JSON.stringify(certificate, null, 2));
|
|
121
|
+
} catch (error) {
|
|
122
|
+
console.error("Error fetching certificate:", error);
|
|
123
|
+
}
|
|
124
|
+
},
|
|
125
|
+
)
|
|
126
|
+
.command(
|
|
127
|
+
"fetch-model <vid> <pid>",
|
|
128
|
+
"Fetch device model information by Vendor ID and Product ID",
|
|
129
|
+
yargs => {
|
|
130
|
+
return yargs.positional("vid", vidPositional()).positional("pid", pidPositional());
|
|
131
|
+
},
|
|
132
|
+
async argv => {
|
|
133
|
+
const { vid, pid, test } = argv;
|
|
134
|
+
if (vid === undefined || pid === undefined) {
|
|
135
|
+
throw new Error("VID and PID are required");
|
|
136
|
+
}
|
|
137
|
+
const client = new DclClient(!test);
|
|
138
|
+
|
|
139
|
+
try {
|
|
140
|
+
console.log(`Fetching model information from ${getDclEnv(test)} DCL...`);
|
|
141
|
+
console.log(`VID: ${Diagnostic.hex(vid, 4)}`);
|
|
142
|
+
console.log(`PID: ${Diagnostic.hex(pid, 4)}`);
|
|
143
|
+
|
|
144
|
+
const model = await client.fetchModelByVidPid(vid, pid);
|
|
145
|
+
console.log("Device model information:");
|
|
146
|
+
console.log(JSON.stringify(model, null, 2));
|
|
147
|
+
} catch (error) {
|
|
148
|
+
console.error("Error fetching model:", error);
|
|
149
|
+
}
|
|
150
|
+
},
|
|
151
|
+
)
|
|
152
|
+
.command(
|
|
153
|
+
"fetch-model-versions <vid> <pid>",
|
|
154
|
+
"Fetch available software versions for a device model",
|
|
155
|
+
yargs => {
|
|
156
|
+
return yargs.positional("vid", vidPositional()).positional("pid", pidPositional());
|
|
157
|
+
},
|
|
158
|
+
async argv => {
|
|
159
|
+
const { vid, pid, test } = argv;
|
|
160
|
+
if (vid === undefined || pid === undefined) {
|
|
161
|
+
throw new Error("VID and PID are required");
|
|
162
|
+
}
|
|
163
|
+
const client = new DclClient(!test);
|
|
164
|
+
|
|
165
|
+
try {
|
|
166
|
+
console.log(`Fetching available versions from ${getDclEnv(test)} DCL...`);
|
|
167
|
+
console.log(`VID: ${Diagnostic.hex(vid, 4)}`);
|
|
168
|
+
console.log(`PID: ${Diagnostic.hex(pid, 4)}`);
|
|
169
|
+
|
|
170
|
+
const versions = await client.fetchModelVersionsByVidPid(vid, pid);
|
|
171
|
+
console.log(`Found ${versions.length} software version(s):`);
|
|
172
|
+
console.log(JSON.stringify(versions, null, 2));
|
|
173
|
+
} catch (error) {
|
|
174
|
+
console.error("Error fetching versions:", error);
|
|
175
|
+
}
|
|
176
|
+
},
|
|
177
|
+
)
|
|
178
|
+
.command(
|
|
179
|
+
"fetch-model-version <vid> <pid> <softwareVersion>",
|
|
180
|
+
"Fetch detailed information for a specific software version",
|
|
181
|
+
yargs => {
|
|
182
|
+
return yargs
|
|
183
|
+
.positional("vid", vidPositional())
|
|
184
|
+
.positional("pid", pidPositional())
|
|
185
|
+
.positional("softwareVersion", {
|
|
186
|
+
describe: "Software version number",
|
|
187
|
+
type: "number",
|
|
188
|
+
demandOption: true,
|
|
189
|
+
});
|
|
190
|
+
},
|
|
191
|
+
async argv => {
|
|
192
|
+
const { vid, pid, softwareVersion, test } = argv;
|
|
193
|
+
if (vid === undefined || pid === undefined || softwareVersion === undefined) {
|
|
194
|
+
throw new Error("VID, PID, and software version are required");
|
|
195
|
+
}
|
|
196
|
+
const client = new DclClient(!test);
|
|
197
|
+
|
|
198
|
+
try {
|
|
199
|
+
console.log(`Fetching version details from ${getDclEnv(test)} DCL...`);
|
|
200
|
+
console.log(`VID: ${Diagnostic.hex(vid, 4)}`);
|
|
201
|
+
console.log(`PID: ${Diagnostic.hex(pid, 4)}`);
|
|
202
|
+
console.log(`Software Version: ${softwareVersion}`);
|
|
203
|
+
|
|
204
|
+
const versionInfo = await client.fetchModelVersionByVidPidSoftwareVersion(
|
|
205
|
+
vid,
|
|
206
|
+
pid,
|
|
207
|
+
softwareVersion,
|
|
208
|
+
);
|
|
209
|
+
console.log("Software version information:");
|
|
210
|
+
console.log(JSON.stringify(versionInfo, null, 2));
|
|
211
|
+
} catch (error) {
|
|
212
|
+
console.error("Error fetching version details:", error);
|
|
213
|
+
}
|
|
214
|
+
},
|
|
215
|
+
)
|
|
216
|
+
.demandCommand(1, "You must specify a DCL query command"),
|
|
217
|
+
handler: async (argv: any) => {
|
|
218
|
+
argv.unhandled = true;
|
|
219
|
+
},
|
|
220
|
+
};
|
|
221
|
+
}
|