@matter/nodejs-shell 0.17.0-alpha.0-20260507-059f7763b → 0.17.0-alpha.0-20260508-29ff5ae9e

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.
Files changed (49) hide show
  1. package/package.json +9 -9
  2. package/src/MatterNode.ts +13 -12
  3. package/src/shell/cmd_cert.ts +34 -0
  4. package/src/shell/cmd_commission.ts +24 -1
  5. package/src/shell/cmd_config.ts +140 -0
  6. package/src/shell/cmd_nodes.ts +1 -3
  7. package/dist/esm/MatterNode.js +0 -189
  8. package/dist/esm/MatterNode.js.map +0 -6
  9. package/dist/esm/app.js +0 -167
  10. package/dist/esm/app.js.map +0 -6
  11. package/dist/esm/package.json +0 -3
  12. package/dist/esm/shell/Shell.js +0 -201
  13. package/dist/esm/shell/Shell.js.map +0 -6
  14. package/dist/esm/shell/cmd_cert.js +0 -134
  15. package/dist/esm/shell/cmd_cert.js.map +0 -6
  16. package/dist/esm/shell/cmd_cluster-attributes.js +0 -295
  17. package/dist/esm/shell/cmd_cluster-attributes.js.map +0 -6
  18. package/dist/esm/shell/cmd_cluster-commands.js +0 -137
  19. package/dist/esm/shell/cmd_cluster-commands.js.map +0 -6
  20. package/dist/esm/shell/cmd_cluster-events.js +0 -77
  21. package/dist/esm/shell/cmd_cluster-events.js.map +0 -6
  22. package/dist/esm/shell/cmd_commission.js +0 -269
  23. package/dist/esm/shell/cmd_commission.js.map +0 -6
  24. package/dist/esm/shell/cmd_config.js +0 -462
  25. package/dist/esm/shell/cmd_config.js.map +0 -6
  26. package/dist/esm/shell/cmd_dcl.js +0 -178
  27. package/dist/esm/shell/cmd_dcl.js.map +0 -6
  28. package/dist/esm/shell/cmd_discover.js +0 -115
  29. package/dist/esm/shell/cmd_discover.js.map +0 -6
  30. package/dist/esm/shell/cmd_identify.js +0 -46
  31. package/dist/esm/shell/cmd_identify.js.map +0 -6
  32. package/dist/esm/shell/cmd_nodes.js +0 -688
  33. package/dist/esm/shell/cmd_nodes.js.map +0 -6
  34. package/dist/esm/shell/cmd_ota.js +0 -493
  35. package/dist/esm/shell/cmd_ota.js.map +0 -6
  36. package/dist/esm/shell/cmd_session.js +0 -23
  37. package/dist/esm/shell/cmd_session.js.map +0 -6
  38. package/dist/esm/shell/cmd_subscribe.js +0 -39
  39. package/dist/esm/shell/cmd_subscribe.js.map +0 -6
  40. package/dist/esm/shell/cmd_tlv.js +0 -167
  41. package/dist/esm/shell/cmd_tlv.js.map +0 -6
  42. package/dist/esm/shell/cmd_vendor.js +0 -135
  43. package/dist/esm/shell/cmd_vendor.js.map +0 -6
  44. package/dist/esm/util/CommandlineParser.js +0 -87
  45. package/dist/esm/util/CommandlineParser.js.map +0 -6
  46. package/dist/esm/util/Json.js +0 -45
  47. package/dist/esm/util/Json.js.map +0 -6
  48. package/dist/esm/web_plumbing.js +0 -140
  49. package/dist/esm/web_plumbing.js.map +0 -6
@@ -1,688 +0,0 @@
1
- /**
2
- * @license
3
- * Copyright 2022-2026 Matter.js Authors
4
- * SPDX-License-Identifier: Apache-2.0
5
- */
6
- import { capitalize, ChannelType, decamelize, Diagnostic, ServerAddress } from "@matter/general";
7
- import { NetworkClient, SoftwareUpdateManager } from "@matter/node";
8
- import { PeerAddress, PeerSet } from "@matter/protocol";
9
- import { FabricIndex, NodeId } from "@matter/types";
10
- import { NodeStateInformation } from "@project-chip/matter.js/device";
11
- function createDiagnosticCallbacks() {
12
- return {
13
- attributeChangedCallback: (peerNodeId, { path: { nodeId, clusterId, endpointId, attributeName }, value }) => console.log(
14
- `attributeChangedCallback ${peerNodeId}: Attribute ${nodeId}/${endpointId}/${clusterId}/${attributeName} changed to ${Diagnostic.json(
15
- value
16
- )}`
17
- ),
18
- eventTriggeredCallback: (peerNodeId, { path: { nodeId, clusterId, endpointId, eventName }, events }) => console.log(
19
- `eventTriggeredCallback ${peerNodeId}: Event ${nodeId}/${endpointId}/${clusterId}/${eventName} triggered with ${Diagnostic.json(
20
- events
21
- )}`
22
- ),
23
- stateInformationCallback: (peerNodeId, info) => {
24
- switch (info) {
25
- case NodeStateInformation.Connected:
26
- console.log(`stateInformationCallback Node ${peerNodeId} connected`);
27
- break;
28
- case NodeStateInformation.Disconnected:
29
- console.log(`stateInformationCallback Node ${peerNodeId} disconnected`);
30
- break;
31
- case NodeStateInformation.Reconnecting:
32
- console.log(`stateInformationCallback Node ${peerNodeId} reconnecting`);
33
- break;
34
- case NodeStateInformation.WaitingForDeviceDiscovery:
35
- console.log(
36
- `stateInformationCallback Node ${peerNodeId} waiting that device gets discovered again`
37
- );
38
- break;
39
- case NodeStateInformation.StructureChanged:
40
- console.log(`stateInformationCallback Node ${peerNodeId} structure changed`);
41
- break;
42
- case NodeStateInformation.Decommissioned:
43
- console.log(`stateInformationCallback Node ${peerNodeId} decommissioned`);
44
- break;
45
- }
46
- }
47
- };
48
- }
49
- function commands(theNode) {
50
- return {
51
- command: ["nodes", "node"],
52
- describe: "Manage nodes",
53
- builder: (yargs) => yargs.command(
54
- ["*", "list [status]"],
55
- "List all commissioned nodes",
56
- (yargs2) => {
57
- return yargs2.positional("status", {
58
- describe: "status",
59
- options: ["commissioned", "connected"],
60
- default: "commissioned",
61
- type: "string"
62
- });
63
- },
64
- async (argv) => {
65
- const { status } = argv;
66
- await theNode.start();
67
- if (theNode.commissioningController === void 0) {
68
- throw new Error("CommissioningController not initialized");
69
- }
70
- switch (status) {
71
- case "commissioned": {
72
- const details = theNode.commissioningController.getCommissionedNodesDetails();
73
- details.map((detail) => ({
74
- ...detail,
75
- nodeId: detail.nodeId.toString()
76
- })).forEach((detail) => {
77
- console.log(detail);
78
- });
79
- break;
80
- }
81
- case "connected": {
82
- const nodeIds = theNode.commissioningController.getCommissionedNodes().filter((nodeId) => !!theNode.commissioningController?.getPairedNode(nodeId));
83
- console.log(nodeIds.map((nodeId) => nodeId.toString()));
84
- break;
85
- }
86
- }
87
- }
88
- ).command(
89
- "log [node-id]",
90
- "Log the Structure of one node",
91
- (yargs2) => {
92
- return yargs2.positional("node-id", {
93
- describe: "node id to log - if omitted the first node is logged.",
94
- default: void 0,
95
- type: "string"
96
- });
97
- },
98
- async (argv) => {
99
- const { nodeId } = argv;
100
- const node = (await theNode.connectAndGetNodes(nodeId))[0];
101
- console.log("Logging structure of Node ", node.nodeId.toString());
102
- node.logStructure();
103
- }
104
- ).command(
105
- "descriptor <node-id>",
106
- "Show peer descriptor and transport details for a node",
107
- (yargs2) => {
108
- return yargs2.positional("node-id", {
109
- describe: "node id",
110
- type: "string",
111
- demandOption: true
112
- });
113
- },
114
- async (argv) => {
115
- const { nodeId: nodeIdStr } = argv;
116
- await theNode.start();
117
- if (theNode.commissioningController === void 0) {
118
- throw new Error("CommissioningController not initialized");
119
- }
120
- const nodeId = NodeId(BigInt(nodeIdStr));
121
- const peerAddress = theNode.commissioningController.fabric.addressOf(nodeId);
122
- const peerSet = theNode.node.env.get(PeerSet);
123
- const peer = peerSet.for(peerAddress);
124
- if (!peer) {
125
- console.log(`Peer ${nodeIdStr} not found`);
126
- return;
127
- }
128
- const desc = peer.descriptor;
129
- console.log(`
130
- Peer Descriptor for node ${nodeIdStr}:`);
131
- console.log(` Address: ${desc.address}`);
132
- console.log(
133
- ` Operational Address: ${desc.operationalAddress ? ServerAddress.urlFor(desc.operationalAddress) : "(unknown)"}`
134
- );
135
- console.log(
136
- ` Transport Preference: ${peer.transportPreference === ChannelType.TCP ? "TCP" : "UDP (default)"}`
137
- );
138
- if (desc.discoveryData) {
139
- const dd = desc.discoveryData;
140
- console.log(` Discovery Data:`);
141
- if (dd.DN) console.log(` Device Name: ${dd.DN}`);
142
- if (dd.VP) console.log(` Vendor/Prod: ${dd.VP}`);
143
- if (dd.DT !== void 0) console.log(` Device Type: ${dd.DT}`);
144
- if (dd.T !== void 0) {
145
- const tcpClient = !!(dd.T & 2);
146
- const tcpServer = !!(dd.T & 4);
147
- console.log(` TCP Support: T=${dd.T} (client=${tcpClient}, server=${tcpServer})`);
148
- } else {
149
- console.log(` TCP Support: not advertised`);
150
- }
151
- if (dd.SII) console.log(` Idle Interval: ${dd.SII}ms`);
152
- if (dd.SAI) console.log(` Active Interval: ${dd.SAI}ms`);
153
- }
154
- if (desc.sessionParameters) {
155
- const sp = desc.sessionParameters;
156
- console.log(` Session Parameters:`);
157
- console.log(` Supported Transports: ${Diagnostic.json(sp.supportedTransports)}`);
158
- if (sp.maxTcpMessageSize !== void 0) {
159
- console.log(` Max TCP Message Size: ${sp.maxTcpMessageSize}`);
160
- }
161
- }
162
- const sessions = [...peer.sessions];
163
- if (sessions.length) {
164
- console.log(` Active Sessions: ${sessions.length}`);
165
- for (const session of sessions) {
166
- console.log(` ${session.via} (${session.channel.transportChannel.type})`);
167
- }
168
- } else {
169
- console.log(` Active Sessions: none`);
170
- }
171
- console.log();
172
- }
173
- ).command(
174
- "connect [node-id] [min-subscription-interval] [max-subscription-interval]",
175
- "Connects to one or all commissioned nodes",
176
- (yargs2) => {
177
- return yargs2.positional("node-id", {
178
- describe: "node id to connect. Use 'all' to connect to all nodes.",
179
- default: "all",
180
- type: "string",
181
- demandOption: true
182
- }).positional("min-subscription-interval", {
183
- describe: "Minimum subscription interval in seconds. If set then the node is subscribed to all attributes and events.",
184
- type: "number"
185
- }).positional("max-subscription-interval", {
186
- describe: "Maximum subscription interval in seconds. If minimum interval is set and this not it will be determined automatically.",
187
- type: "number"
188
- });
189
- },
190
- async (argv) => {
191
- const { nodeId: nodeIdStr, maxSubscriptionInterval, minSubscriptionInterval } = argv;
192
- await theNode.start();
193
- if (theNode.commissioningController === void 0) {
194
- throw new Error("CommissioningController not initialized");
195
- }
196
- let nodeIds = theNode.commissioningController.getCommissionedNodes();
197
- if (nodeIdStr !== "all") {
198
- const cmdNodeId = NodeId(BigInt(nodeIdStr));
199
- nodeIds = nodeIds.filter((nodeId) => nodeId === cmdNodeId);
200
- if (!nodeIds.length) {
201
- throw new Error(`Node ${nodeIdStr} not commissioned`);
202
- }
203
- }
204
- const autoSubscribe = minSubscriptionInterval !== void 0;
205
- for (const nodeIdToProcess of nodeIds) {
206
- const node = await theNode.commissioningController.getNode(nodeIdToProcess);
207
- node.connect({
208
- autoSubscribe,
209
- subscribeMinIntervalFloorSeconds: autoSubscribe ? minSubscriptionInterval : void 0,
210
- subscribeMaxIntervalCeilingSeconds: autoSubscribe ? maxSubscriptionInterval : void 0,
211
- ...createDiagnosticCallbacks()
212
- });
213
- }
214
- }
215
- ).command(
216
- "disconnect [node-id]",
217
- "Disconnects from one or all nodes",
218
- (yargs2) => {
219
- return yargs2.positional("node-id", {
220
- describe: "node id to disconnect. Use 'all' to disconnect from all nodes.",
221
- default: "all",
222
- type: "string"
223
- });
224
- },
225
- async (argv) => {
226
- const { nodeId: nodeIdStr } = argv;
227
- if (theNode.commissioningController === void 0) {
228
- console.log("Controller not initialized, nothing to disconnect.");
229
- return;
230
- }
231
- let nodeIds = theNode.commissioningController.getCommissionedNodes();
232
- if (nodeIdStr !== "all") {
233
- const cmdNodeId = NodeId(BigInt(nodeIdStr));
234
- nodeIds = nodeIds.filter((nodeId) => nodeId === cmdNodeId);
235
- if (!nodeIds.length) {
236
- throw new Error(`Node ${nodeIdStr} not commissioned`);
237
- }
238
- }
239
- for (const nodeIdToProcess of nodeIds) {
240
- const node = theNode.commissioningController.getPairedNode(nodeIdToProcess);
241
- if (node === void 0) {
242
- console.log(`Node ${nodeIdToProcess} not connected`);
243
- continue;
244
- }
245
- await node.disconnect();
246
- }
247
- }
248
- ).command(
249
- "status [node-ids]",
250
- "Logs the connection status for all or specified nodes",
251
- (yargs2) => {
252
- return yargs2.positional("node-ids", {
253
- describe: "node ids to connect (comma separated list allowed). Use 'all' to log status for all nodes.",
254
- default: "all",
255
- type: "string"
256
- });
257
- },
258
- async (argv) => {
259
- const { nodeIds: nodeIdStr } = argv;
260
- await theNode.start();
261
- if (theNode.commissioningController === void 0) {
262
- throw new Error("CommissioningController not initialized");
263
- }
264
- let nodeIds = theNode.commissioningController.getCommissionedNodes();
265
- if (nodeIdStr !== "all") {
266
- const nodeIdList = nodeIdStr.split(",").map((nodeId) => NodeId(BigInt(nodeId)));
267
- nodeIds = nodeIds.filter((nodeId) => nodeIdList.includes(nodeId));
268
- if (!nodeIds.length) {
269
- throw new Error(`Node ${nodeIdStr} not commissioned`);
270
- }
271
- }
272
- const nodeDetails = theNode.commissioningController.getCommissionedNodesDetails();
273
- for (const nodeIdToProcess of nodeIds) {
274
- const node = theNode.commissioningController.getPairedNode(nodeIdToProcess);
275
- if (node === void 0) {
276
- const details = nodeDetails.find((nd) => nd.nodeId === nodeIdToProcess);
277
- console.log(
278
- `Node ${nodeIdToProcess}: Not initialized${details?.deviceData?.basicInformation !== void 0 ? ` (${details.deviceData.basicInformation.vendorName} ${details.deviceData.basicInformation.productName})` : ""}`
279
- );
280
- } else {
281
- const basicInfo = node.basicInformation;
282
- console.log(
283
- `Node ${nodeIdToProcess}: Node Status: ${capitalize(decamelize(NodeStateInformation[node.connectionState], " "))}${basicInfo !== void 0 ? ` (${basicInfo.vendorName} ${basicInfo.productName})` : ""}`
284
- );
285
- }
286
- }
287
- }
288
- ).command(
289
- "tcp <node-id> <preference>",
290
- "Set TCP transport preference for a node",
291
- (yargs2) => {
292
- return yargs2.positional("node-id", {
293
- describe: "node id",
294
- type: "string",
295
- demandOption: true
296
- }).positional("preference", {
297
- describe: "tcp preference: on/off (on = prefer TCP, off = prefer UDP)",
298
- choices: ["on", "off"],
299
- demandOption: true,
300
- type: "string"
301
- });
302
- },
303
- async (argv) => {
304
- const { nodeId: nodeIdStr, preference } = argv;
305
- await theNode.start();
306
- if (theNode.commissioningController === void 0) {
307
- throw new Error("CommissioningController not initialized");
308
- }
309
- const nodeId = NodeId(BigInt(nodeIdStr));
310
- const node = await theNode.commissioningController.getNode(nodeId);
311
- const pref = preference === "on" ? "tcp" : "udp";
312
- await node.node.setStateOf(NetworkClient, { transportPreference: pref });
313
- const peer = theNode.node.env.get(PeerSet).for(theNode.commissioningController.fabric.addressOf(nodeId));
314
- if (peer) {
315
- peer.transportPreference = pref === "tcp" ? ChannelType.TCP : void 0;
316
- }
317
- console.log(
318
- `Transport preference for node ${nodeIdStr} set to ${pref.toUpperCase()}. Reconnect to the node to take effect.`
319
- );
320
- }
321
- ).command(
322
- "add [node-id]",
323
- "Adds a node without commissioning and connects to it (means need to exist in the fabric and commissioned otherwise)",
324
- (yargs2) => {
325
- return yargs2.positional("node-id", {
326
- describe: "node id to connect.",
327
- default: "all",
328
- type: "string",
329
- demandOption: true
330
- }).positional("min-subscription-interval", {
331
- describe: "Minimum subscription interval in seconds. If set then the node is subscribed to all attributes and events.",
332
- type: "number"
333
- }).positional("max-subscription-interval", {
334
- describe: "Maximum subscription interval in seconds. If minimum interval is set and this not it will be determined automatically.",
335
- type: "number"
336
- });
337
- },
338
- async (argv) => {
339
- const { nodeId: nodeIdStr, maxSubscriptionInterval, minSubscriptionInterval } = argv;
340
- await theNode.start();
341
- if (theNode.commissioningController === void 0) {
342
- throw new Error("CommissioningController not initialized");
343
- }
344
- let nodeIds = theNode.commissioningController.getCommissionedNodes();
345
- const cmdNodeId = NodeId(BigInt(nodeIdStr));
346
- nodeIds = nodeIds.filter((nodeId) => nodeId === cmdNodeId);
347
- if (nodeIds.length) {
348
- throw new Error(`Node ${nodeIdStr} already known`);
349
- }
350
- await theNode.commissioningController.node.peers.forAddress(
351
- theNode.commissioningController.fabric.addressOf(cmdNodeId)
352
- );
353
- const autoSubscribe = minSubscriptionInterval !== void 0;
354
- const node = await theNode.commissioningController.getNode(cmdNodeId);
355
- node.connect({
356
- autoSubscribe,
357
- subscribeMinIntervalFloorSeconds: autoSubscribe ? minSubscriptionInterval : void 0,
358
- subscribeMaxIntervalCeilingSeconds: autoSubscribe ? maxSubscriptionInterval : void 0,
359
- ...createDiagnosticCallbacks()
360
- });
361
- }
362
- ).command(
363
- "ota",
364
- "OTA update operations for nodes",
365
- (yargs2) => yargs2.command(
366
- "known [node-id]",
367
- "List which OTA updates are known to be available for commissioned nodes. Only nodes that are connected and subscribed are considered.",
368
- (yargs3) => {
369
- return yargs3.positional("node-id", {
370
- describe: "Node ID to check for updates",
371
- type: "string",
372
- default: void 0
373
- }).option("local", {
374
- describe: "include local update files",
375
- type: "boolean",
376
- default: false
377
- });
378
- },
379
- async (argv) => {
380
- const { nodeId: nodeIdStr, local } = argv;
381
- await theNode.start();
382
- if (theNode.commissioningController === void 0) {
383
- throw new Error("CommissioningController not initialized");
384
- }
385
- let peerToCheck = void 0;
386
- if (nodeIdStr !== void 0) {
387
- const nodeId = NodeId(BigInt(nodeIdStr));
388
- peerToCheck = (await theNode.commissioningController.getNode(nodeId))?.node;
389
- }
390
- const updatesAvailable = await theNode.commissioningController.otaProvider.act(
391
- (agent) => agent.get(SoftwareUpdateManager).queryUpdates({ peerToCheck, includeStoredUpdates: local })
392
- );
393
- if (updatesAvailable.length) {
394
- console.log(`OTA updates available for ${updatesAvailable.length} nodes:`);
395
- for (const { peerAddress, info } of updatesAvailable) {
396
- console.log(
397
- peerAddress.toString(),
398
- `: new Version: ${info.softwareVersion} (${info.softwareVersionString})`
399
- );
400
- }
401
- } else {
402
- console.log("No OTA updates available.");
403
- }
404
- }
405
- ).command(
406
- "check <node-id>",
407
- "Check for OTA updates for a commissioned node",
408
- (yargs3) => {
409
- return yargs3.positional("node-id", {
410
- describe: "Node ID to check for updates",
411
- type: "string",
412
- demandOption: true
413
- }).option("mode", {
414
- describe: "DCL mode (prod or test)",
415
- type: "string",
416
- choices: ["prod", "test", "both"],
417
- default: "prod"
418
- }).option("local", {
419
- describe: "include local update files",
420
- type: "boolean",
421
- default: false
422
- });
423
- },
424
- async (argv) => {
425
- const { nodeId: nodeIdStr, mode, local } = argv;
426
- const isProduction = mode === "prod" ? true : mode === "test" ? false : void 0;
427
- await theNode.start();
428
- if (theNode.commissioningController === void 0) {
429
- throw new Error("CommissioningController not initialized");
430
- }
431
- const nodeId = NodeId(BigInt(nodeIdStr));
432
- const nodeDetails = theNode.commissioningController.getCommissionedNodesDetails().find((nd) => nd.nodeId === nodeId);
433
- const basicInfo = nodeDetails?.deviceData?.basicInformation;
434
- if (!basicInfo) {
435
- throw new Error(`Node ${nodeIdStr} has no basic information available`);
436
- }
437
- if (basicInfo.vendorId === void 0 || basicInfo.productId === void 0 || basicInfo.softwareVersion === void 0) {
438
- throw new Error(
439
- `Node ${nodeIdStr} is missing required basic information for OTA check`
440
- );
441
- }
442
- console.log(`Checking for OTA updates for node ${nodeIdStr}...`);
443
- console.log(
444
- ` Vendor ID: ${Diagnostic.hex(basicInfo.vendorId, 4).toUpperCase()}`
445
- );
446
- console.log(
447
- ` Product ID: ${Diagnostic.hex(basicInfo.productId, 4).toUpperCase()}`
448
- );
449
- console.log(
450
- ` Current Software Version: ${basicInfo.softwareVersion} (${basicInfo.softwareVersionString})`
451
- );
452
- console.log(` DCL Mode: ${mode}
453
- `);
454
- const updateInfo = await (await theNode.otaService()).checkForUpdate({
455
- vendorId: basicInfo.vendorId,
456
- productId: basicInfo.productId,
457
- currentSoftwareVersion: basicInfo.softwareVersion,
458
- includeStoredUpdates: local,
459
- isProduction
460
- });
461
- if (updateInfo) {
462
- console.log("\u2713 Update available!");
463
- console.log(
464
- ` New Version: ${updateInfo.softwareVersion} (${updateInfo.softwareVersionString})`
465
- );
466
- console.log(` OTA URL: ${updateInfo.otaUrl}`);
467
- if (updateInfo.otaFileSize) {
468
- const sizeKB = Number(updateInfo.otaFileSize) / 1024;
469
- console.log(` File Size: ${sizeKB.toFixed(2)} KB`);
470
- }
471
- if (updateInfo.releaseNotesUrl) {
472
- console.log(` Release Notes: ${updateInfo.releaseNotesUrl}`);
473
- }
474
- console.log(
475
- `
476
- Run "nodes ota download ${nodeIdStr}${mode === "test" ? " --mode test" : ""}" to download this update.`
477
- );
478
- } else {
479
- console.log("\u2713 No updates available. Device is up to date.");
480
- }
481
- }
482
- ).command(
483
- "download <node-id>",
484
- "Download OTA update for a commissioned node",
485
- (yargs3) => {
486
- return yargs3.positional("node-id", {
487
- describe: "Node ID to download update for",
488
- type: "string",
489
- demandOption: true
490
- }).option("mode", {
491
- describe: "DCL mode (prod or test)",
492
- type: "string",
493
- choices: ["prod", "test", "both"],
494
- default: "prod"
495
- }).option("force", {
496
- describe: "Force download even if update is already stored locally",
497
- type: "boolean",
498
- default: false
499
- }).option("local", {
500
- describe: "include local update files",
501
- type: "boolean",
502
- default: false
503
- });
504
- },
505
- async (argv) => {
506
- const { nodeId: nodeIdStr, mode, force, local } = argv;
507
- const isProduction = mode === "prod" ? true : mode === "test" ? false : void 0;
508
- const forceDownload = force === true;
509
- await theNode.start();
510
- if (theNode.commissioningController === void 0) {
511
- throw new Error("CommissioningController not initialized");
512
- }
513
- const nodeId = NodeId(BigInt(nodeIdStr));
514
- const nodeDetails = theNode.commissioningController.getCommissionedNodesDetails().find((nd) => nd.nodeId === nodeId);
515
- const basicInfo = nodeDetails?.deviceData?.basicInformation;
516
- if (!basicInfo) {
517
- throw new Error(`Node ${nodeIdStr} has no basic information available`);
518
- }
519
- if (basicInfo.vendorId === void 0 || basicInfo.productId === void 0 || basicInfo.softwareVersion === void 0) {
520
- throw new Error(
521
- `Node ${nodeIdStr} is missing required basic information for OTA check`
522
- );
523
- }
524
- console.log(`Checking for OTA updates for node ${nodeIdStr}...`);
525
- console.log(
526
- ` Vendor ID: ${Diagnostic.hex(basicInfo.vendorId, 4).toUpperCase()}`
527
- );
528
- console.log(
529
- ` Product ID: ${Diagnostic.hex(basicInfo.productId, 4).toUpperCase()}`
530
- );
531
- console.log(
532
- ` Current Software Version: ${basicInfo.softwareVersion} (${basicInfo.softwareVersionString})`
533
- );
534
- console.log(` DCL Mode: ${mode}
535
- `);
536
- const updateInfo = await (await theNode.otaService()).checkForUpdate({
537
- vendorId: basicInfo.vendorId,
538
- productId: basicInfo.productId,
539
- currentSoftwareVersion: basicInfo.softwareVersion,
540
- includeStoredUpdates: local,
541
- isProduction
542
- });
543
- if (!updateInfo) {
544
- console.log("No updates available. Device is up to date.");
545
- return;
546
- }
547
- console.log("Update found:");
548
- console.log(
549
- ` New Version: ${updateInfo.softwareVersion} (${updateInfo.softwareVersionString})`
550
- );
551
- console.log(` OTA URL: ${updateInfo.otaUrl}`);
552
- console.log(` Source: ${updateInfo.source}`);
553
- if (updateInfo.otaFileSize) {
554
- const sizeKB = Number(updateInfo.otaFileSize) / 1024;
555
- console.log(` File Size: ${sizeKB.toFixed(2)} KB`);
556
- }
557
- console.log("\nDownloading update...");
558
- const fd = await (await theNode.otaService()).downloadUpdate(updateInfo, forceDownload);
559
- console.log(`\u2713 Update downloaded and stored successfully: ${fd.text}`);
560
- console.log(
561
- `
562
- You can now apply this update to the device using your device's OTA mechanism.`
563
- );
564
- }
565
- ).command(
566
- "apply <node-id>",
567
- "Apply OTA update for a commissioned node",
568
- (yargs3) => {
569
- return yargs3.positional("node-id", {
570
- describe: "Node ID to download update for",
571
- type: "string",
572
- demandOption: true
573
- }).option("mode", {
574
- describe: "DCL mode (prod or test)",
575
- type: "string",
576
- choices: ["prod", "test", "both"],
577
- default: "prod"
578
- }).option("force", {
579
- describe: "Force download even if update is already stored locally",
580
- type: "boolean",
581
- default: false
582
- }).option("local", {
583
- describe: "Apply update from local file",
584
- type: "boolean",
585
- default: false
586
- });
587
- },
588
- async (argv) => {
589
- const { nodeId: nodeIdStr, mode, force, local } = argv;
590
- const isProduction = mode === "prod" ? true : mode === "test" ? false : void 0;
591
- const forceDownload = force === true;
592
- await theNode.start();
593
- if (theNode.commissioningController === void 0) {
594
- throw new Error("CommissioningController not initialized");
595
- }
596
- const nodeId = NodeId(BigInt(nodeIdStr));
597
- const nodeDetails = theNode.commissioningController.getCommissionedNodesDetails().find((nd) => nd.nodeId === nodeId);
598
- const basicInfo = nodeDetails?.deviceData?.basicInformation;
599
- if (!basicInfo) {
600
- throw new Error(`Node ${nodeIdStr} has no basic information available`);
601
- }
602
- if (basicInfo.vendorId === void 0 || basicInfo.productId === void 0 || basicInfo.softwareVersion === void 0) {
603
- throw new Error(
604
- `Node ${nodeIdStr} is missing required basic information for OTA check`
605
- );
606
- }
607
- console.log(`Checking for OTA updates for node ${nodeIdStr}...`);
608
- console.log(
609
- ` Vendor ID: ${Diagnostic.hex(basicInfo.vendorId, 4).toUpperCase()}`
610
- );
611
- console.log(
612
- ` Product ID: ${Diagnostic.hex(basicInfo.productId, 4).toUpperCase()}`
613
- );
614
- console.log(
615
- ` Current Software Version: ${basicInfo.softwareVersion} (${basicInfo.softwareVersionString})`
616
- );
617
- console.log(` DCL Mode: ${mode}
618
- `);
619
- const localUpdates = await (await theNode.otaService()).find({
620
- vendorId: basicInfo.vendorId,
621
- productId: basicInfo.productId,
622
- currentVersion: basicInfo.softwareVersion
623
- });
624
- if (local && !localUpdates.length) {
625
- console.log("No applicable updates available in local storage.");
626
- return;
627
- }
628
- const updateInfo = await (await theNode.otaService()).checkForUpdate({
629
- vendorId: basicInfo.vendorId,
630
- productId: basicInfo.productId,
631
- currentSoftwareVersion: basicInfo.softwareVersion,
632
- includeStoredUpdates: local,
633
- isProduction
634
- });
635
- let updateVersion;
636
- if (!updateInfo && !local) {
637
- console.log("No updates available in DCL. Device is up to date.");
638
- return;
639
- } else if (updateInfo) {
640
- console.log("Update found:");
641
- console.log(
642
- ` New Version: ${updateInfo.softwareVersion} (${updateInfo.softwareVersionString})`
643
- );
644
- console.log(` OTA URL: ${updateInfo.otaUrl}`);
645
- if (updateInfo.otaFileSize) {
646
- const sizeKB = Number(updateInfo.otaFileSize) / 1024;
647
- console.log(` File Size: ${sizeKB.toFixed(2)} KB`);
648
- }
649
- console.log("\nDownloading update...");
650
- const fd = await (await theNode.otaService()).downloadUpdate(updateInfo, forceDownload);
651
- updateVersion = updateInfo.softwareVersion;
652
- console.log(
653
- `\u2713 Update to version ${updateVersion} (${updateInfo.softwareVersionString}) downloaded and stored successfully: ${fd.text}`
654
- );
655
- } else {
656
- updateVersion = localUpdates[0].softwareVersion;
657
- console.log(
658
- `Update to version ${updateVersion} (${localUpdates[0].softwareVersionString}) found in local storage: ${localUpdates[0].filename}`
659
- );
660
- }
661
- const node = theNode.commissioningController.getPairedNode(nodeId);
662
- if (node === void 0) {
663
- throw new Error(`Node ${nodeIdStr} not connected`);
664
- }
665
- await theNode.commissioningController.otaProvider.act((agent) => {
666
- return agent.get(SoftwareUpdateManager).forceUpdate(
667
- PeerAddress({ nodeId, fabricIndex: FabricIndex(1) }),
668
- basicInfo.vendorId,
669
- basicInfo.productId,
670
- updateVersion
671
- );
672
- });
673
- }
674
- ).demandCommand(1, "Please specify an OTA subcommand"),
675
- async (argv) => {
676
- argv.unhandled = true;
677
- }
678
- ),
679
- handler: async (argv) => {
680
- argv.unhandled = true;
681
- }
682
- };
683
- }
684
- export {
685
- createDiagnosticCallbacks,
686
- commands as default
687
- };
688
- //# sourceMappingURL=cmd_nodes.js.map