@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.
@@ -5,7 +5,7 @@
5
5
  */
6
6
 
7
7
  import { capitalize, decamelize, Diagnostic } from "#general";
8
- import { NodeId } from "#types";
8
+ import { NodeId, VendorId } from "#types";
9
9
  import { CommissioningControllerNodeOptions, NodeStateInformation } from "@project-chip/matter.js/device";
10
10
  import type { Argv } from "yargs";
11
11
  import { MatterNode } from "../MatterNode";
@@ -240,6 +240,197 @@ export default function commands(theNode: MatterNode) {
240
240
  }
241
241
  }
242
242
  },
243
+ )
244
+ .command(
245
+ "ota",
246
+ "OTA update operations for nodes",
247
+ yargs =>
248
+ yargs
249
+ .command(
250
+ "check <node-id>",
251
+ "Check for OTA updates for a commissioned node",
252
+ yargs => {
253
+ return yargs
254
+ .positional("node-id", {
255
+ describe: "Node ID to check for updates",
256
+ type: "string",
257
+ demandOption: true,
258
+ })
259
+ .option("mode", {
260
+ describe: "DCL mode (prod or test)",
261
+ type: "string",
262
+ choices: ["prod", "test"],
263
+ default: "prod",
264
+ });
265
+ },
266
+ async argv => {
267
+ const { nodeId: nodeIdStr, mode } = argv;
268
+ const isProduction = mode === "prod";
269
+
270
+ await theNode.start();
271
+ if (theNode.commissioningController === undefined) {
272
+ throw new Error("CommissioningController not initialized");
273
+ }
274
+
275
+ const nodeId = NodeId(BigInt(nodeIdStr));
276
+ const nodeDetails = theNode.commissioningController
277
+ .getCommissionedNodesDetails()
278
+ .find(nd => nd.nodeId === nodeId);
279
+ const basicInfo = nodeDetails?.deviceData?.basicInformation;
280
+ if (!basicInfo) {
281
+ throw new Error(`Node ${nodeIdStr} has no basic information available`);
282
+ }
283
+ if (
284
+ basicInfo.vendorId === undefined ||
285
+ basicInfo.productId === undefined ||
286
+ basicInfo.softwareVersion === undefined
287
+ ) {
288
+ throw new Error(
289
+ `Node ${nodeIdStr} is missing required basic information for OTA check`,
290
+ );
291
+ }
292
+
293
+ console.log(`Checking for OTA updates for node ${nodeIdStr}...`);
294
+ console.log(
295
+ ` Vendor ID: ${Diagnostic.hex(basicInfo.vendorId as VendorId, 4).toUpperCase()}`,
296
+ );
297
+ console.log(
298
+ ` Product ID: ${Diagnostic.hex(basicInfo.productId as number, 4).toUpperCase()}`,
299
+ );
300
+ console.log(
301
+ ` Current Software Version: ${basicInfo.softwareVersion} (${basicInfo.softwareVersionString})`,
302
+ );
303
+ console.log(` DCL Mode: ${isProduction ? "production" : "test"}\n`);
304
+
305
+ const updateInfo = await theNode.otaService.checkForUpdate(
306
+ basicInfo.vendorId as VendorId,
307
+ basicInfo.productId as number,
308
+ basicInfo.softwareVersion as number,
309
+ isProduction,
310
+ );
311
+
312
+ if (updateInfo) {
313
+ console.log("✓ Update available!");
314
+ console.log(
315
+ ` New Version: ${updateInfo.softwareVersion} (${updateInfo.softwareVersionString})`,
316
+ );
317
+ console.log(` OTA URL: ${updateInfo.otaUrl}`);
318
+ if (updateInfo.otaFileSize) {
319
+ const sizeKB = Number(updateInfo.otaFileSize) / 1024;
320
+ console.log(` File Size: ${sizeKB.toFixed(2)} KB`);
321
+ }
322
+ if (updateInfo.releaseNotesUrl) {
323
+ console.log(` Release Notes: ${updateInfo.releaseNotesUrl}`);
324
+ }
325
+ console.log(
326
+ `\nRun "nodes ota download ${nodeIdStr}${mode === "test" ? " --mode test" : ""}" to download this update.`,
327
+ );
328
+ } else {
329
+ console.log("✓ No updates available. Device is up to date.");
330
+ }
331
+ },
332
+ )
333
+ .command(
334
+ "download <node-id>",
335
+ "Download OTA update for a commissioned node",
336
+ yargs => {
337
+ return yargs
338
+ .positional("node-id", {
339
+ describe: "Node ID to download update for",
340
+ type: "string",
341
+ demandOption: true,
342
+ })
343
+ .option("mode", {
344
+ describe: "DCL mode (prod or test)",
345
+ type: "string",
346
+ choices: ["prod", "test"],
347
+ default: "prod",
348
+ })
349
+ .option("force", {
350
+ describe: "Force download even if update is already stored locally",
351
+ type: "boolean",
352
+ default: false,
353
+ });
354
+ },
355
+ async argv => {
356
+ const { nodeId: nodeIdStr, mode, force } = argv;
357
+ const isProduction = mode === "prod";
358
+ const forceDownload = force === true;
359
+
360
+ await theNode.start();
361
+ if (theNode.commissioningController === undefined) {
362
+ throw new Error("CommissioningController not initialized");
363
+ }
364
+
365
+ const nodeId = NodeId(BigInt(nodeIdStr));
366
+ const nodeDetails = theNode.commissioningController
367
+ .getCommissionedNodesDetails()
368
+ .find(nd => nd.nodeId === nodeId);
369
+ const basicInfo = nodeDetails?.deviceData?.basicInformation;
370
+ if (!basicInfo) {
371
+ throw new Error(`Node ${nodeIdStr} has no basic information available`);
372
+ }
373
+ if (
374
+ basicInfo.vendorId === undefined ||
375
+ basicInfo.productId === undefined ||
376
+ basicInfo.softwareVersion === undefined
377
+ ) {
378
+ throw new Error(
379
+ `Node ${nodeIdStr} is missing required basic information for OTA check`,
380
+ );
381
+ }
382
+
383
+ console.log(`Checking for OTA updates for node ${nodeIdStr}...`);
384
+ console.log(
385
+ ` Vendor ID: ${Diagnostic.hex(basicInfo.vendorId as VendorId, 4).toUpperCase()}`,
386
+ );
387
+ console.log(
388
+ ` Product ID: ${Diagnostic.hex(basicInfo.productId as number, 4).toUpperCase()}`,
389
+ );
390
+ console.log(
391
+ ` Current Software Version: ${basicInfo.softwareVersion} (${basicInfo.softwareVersionString})`,
392
+ );
393
+ console.log(` DCL Mode: ${isProduction ? "production" : "test"}\n`);
394
+
395
+ const updateInfo = await theNode.otaService.checkForUpdate(
396
+ basicInfo.vendorId as VendorId,
397
+ basicInfo.productId as number,
398
+ basicInfo.softwareVersion as number,
399
+ isProduction,
400
+ );
401
+
402
+ if (!updateInfo) {
403
+ console.log("No updates available. Device is up to date.");
404
+ return;
405
+ }
406
+
407
+ console.log("Update found:");
408
+ console.log(
409
+ ` New Version: ${updateInfo.softwareVersion} (${updateInfo.softwareVersionString})`,
410
+ );
411
+ console.log(` OTA URL: ${updateInfo.otaUrl}`);
412
+ if (updateInfo.otaFileSize) {
413
+ const sizeKB = Number(updateInfo.otaFileSize) / 1024;
414
+ console.log(` File Size: ${sizeKB.toFixed(2)} KB`);
415
+ }
416
+
417
+ console.log("\nDownloading update...");
418
+ const fd = await theNode.otaService.downloadUpdate(
419
+ updateInfo,
420
+ isProduction,
421
+ forceDownload,
422
+ );
423
+
424
+ console.log(`✓ Update downloaded and stored successfully: ${fd.text}`);
425
+ console.log(
426
+ `\nYou can now apply this update to the device using your device's OTA mechanism.`,
427
+ );
428
+ },
429
+ )
430
+ .demandCommand(1, "Please specify an OTA subcommand"),
431
+ async (argv: any) => {
432
+ argv.unhandled = true;
433
+ },
243
434
  ),
244
435
  handler: async (argv: any) => {
245
436
  argv.unhandled = true;