@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.
- package/package.json +9 -9
- package/src/MatterNode.ts +13 -12
- package/src/shell/cmd_cert.ts +34 -0
- package/src/shell/cmd_commission.ts +24 -1
- package/src/shell/cmd_config.ts +140 -0
- package/src/shell/cmd_nodes.ts +1 -3
- package/dist/esm/MatterNode.js +0 -189
- package/dist/esm/MatterNode.js.map +0 -6
- package/dist/esm/app.js +0 -167
- package/dist/esm/app.js.map +0 -6
- package/dist/esm/package.json +0 -3
- package/dist/esm/shell/Shell.js +0 -201
- package/dist/esm/shell/Shell.js.map +0 -6
- package/dist/esm/shell/cmd_cert.js +0 -134
- package/dist/esm/shell/cmd_cert.js.map +0 -6
- package/dist/esm/shell/cmd_cluster-attributes.js +0 -295
- package/dist/esm/shell/cmd_cluster-attributes.js.map +0 -6
- package/dist/esm/shell/cmd_cluster-commands.js +0 -137
- package/dist/esm/shell/cmd_cluster-commands.js.map +0 -6
- package/dist/esm/shell/cmd_cluster-events.js +0 -77
- package/dist/esm/shell/cmd_cluster-events.js.map +0 -6
- package/dist/esm/shell/cmd_commission.js +0 -269
- package/dist/esm/shell/cmd_commission.js.map +0 -6
- package/dist/esm/shell/cmd_config.js +0 -462
- package/dist/esm/shell/cmd_config.js.map +0 -6
- package/dist/esm/shell/cmd_dcl.js +0 -178
- package/dist/esm/shell/cmd_dcl.js.map +0 -6
- package/dist/esm/shell/cmd_discover.js +0 -115
- package/dist/esm/shell/cmd_discover.js.map +0 -6
- package/dist/esm/shell/cmd_identify.js +0 -46
- package/dist/esm/shell/cmd_identify.js.map +0 -6
- package/dist/esm/shell/cmd_nodes.js +0 -688
- package/dist/esm/shell/cmd_nodes.js.map +0 -6
- package/dist/esm/shell/cmd_ota.js +0 -493
- package/dist/esm/shell/cmd_ota.js.map +0 -6
- package/dist/esm/shell/cmd_session.js +0 -23
- package/dist/esm/shell/cmd_session.js.map +0 -6
- package/dist/esm/shell/cmd_subscribe.js +0 -39
- package/dist/esm/shell/cmd_subscribe.js.map +0 -6
- package/dist/esm/shell/cmd_tlv.js +0 -167
- package/dist/esm/shell/cmd_tlv.js.map +0 -6
- package/dist/esm/shell/cmd_vendor.js +0 -135
- package/dist/esm/shell/cmd_vendor.js.map +0 -6
- package/dist/esm/util/CommandlineParser.js +0 -87
- package/dist/esm/util/CommandlineParser.js.map +0 -6
- package/dist/esm/util/Json.js +0 -45
- package/dist/esm/util/Json.js.map +0 -6
- package/dist/esm/web_plumbing.js +0 -140
- 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
|