matterbridge 1.2.11 → 1.2.13

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 (35) hide show
  1. package/CHANGELOG.md +33 -1
  2. package/README.md +31 -26
  3. package/dist/BridgedDeviceBasicInformationCluster.d.ts +223 -0
  4. package/dist/BridgedDeviceBasicInformationCluster.d.ts.map +1 -0
  5. package/dist/BridgedDeviceBasicInformationCluster.js +176 -0
  6. package/dist/BridgedDeviceBasicInformationCluster.js.map +1 -0
  7. package/dist/cli.js +10 -5
  8. package/dist/cli.js.map +1 -1
  9. package/dist/index.js +4 -2
  10. package/dist/index.js.map +1 -1
  11. package/dist/matterbridge.d.ts +12 -0
  12. package/dist/matterbridge.d.ts.map +1 -1
  13. package/dist/matterbridge.js +232 -44
  14. package/dist/matterbridge.js.map +1 -1
  15. package/dist/matterbridgeAccessoryPlatform.d.ts.map +1 -1
  16. package/dist/matterbridgeAccessoryPlatform.js.map +1 -1
  17. package/dist/matterbridgeDevice.d.ts +71 -6
  18. package/dist/matterbridgeDevice.d.ts.map +1 -1
  19. package/dist/matterbridgeDevice.js +50 -2
  20. package/dist/matterbridgeDevice.js.map +1 -1
  21. package/dist/matterbridgePlatform.d.ts +1 -0
  22. package/dist/matterbridgePlatform.d.ts.map +1 -1
  23. package/dist/matterbridgePlatform.js +1 -0
  24. package/dist/matterbridgePlatform.js.map +1 -1
  25. package/frontend/build/asset-manifest.json +6 -6
  26. package/frontend/build/index.html +1 -1
  27. package/frontend/build/static/css/main.979e07d2.css +2 -0
  28. package/frontend/build/static/css/main.979e07d2.css.map +1 -0
  29. package/frontend/build/static/js/{main.60e6f24a.js → main.742e4290.js} +3 -3
  30. package/frontend/build/static/js/main.742e4290.js.map +1 -0
  31. package/package.json +2 -2
  32. package/frontend/build/static/css/main.1880392b.css +0 -2
  33. package/frontend/build/static/css/main.1880392b.css.map +0 -1
  34. package/frontend/build/static/js/main.60e6f24a.js.map +0 -1
  35. /package/frontend/build/static/js/{main.60e6f24a.js.LICENSE.txt → main.742e4290.js.LICENSE.txt} +0 -0
@@ -1 +1 @@
1
- {"version":3,"file":"matterbridge.d.ts","sourceRoot":"","sources":["../src/matterbridge.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;GAqBG;;AAEH,OAAO,EAAE,kBAAkB,EAAgC,MAAM,yBAAyB,CAAC;AAS3F,OAAO,YAAY,MAAM,QAAQ,CAAC;AA2ClC,MAAM,MAAM,mBAAmB,GAAG,MAAM,GAAG,MAAM,GAAG,OAAO,GAAG,MAAM,GAAG,MAAM,GAAG,SAAS,GAAG,IAAI,CAAC;AAEjG,MAAM,MAAM,cAAc,GAAG;IAC3B,CAAC,GAAG,EAAE,MAAM,GAAG,mBAAmB,CAAC;CACpC,CAAC;AA0CF,UAAU,iBAAiB;IACzB,WAAW,EAAE,MAAM,CAAC;IACpB,WAAW,EAAE,MAAM,CAAC;IACpB,WAAW,EAAE,MAAM,CAAC;IACpB,QAAQ,EAAE,MAAM,CAAC;IACjB,IAAI,EAAE,MAAM,CAAC;IACb,MAAM,EAAE,MAAM,CAAC;IACf,SAAS,EAAE,MAAM,CAAC;IAClB,UAAU,EAAE,MAAM,CAAC;IACnB,MAAM,EAAE,MAAM,CAAC;IACf,WAAW,EAAE,MAAM,CAAC;IACpB,UAAU,EAAE,MAAM,CAAC;IACnB,YAAY,EAAE,MAAM,CAAC;CACtB;AAGD,UAAU,uBAAuB;IAC/B,aAAa,EAAE,MAAM,CAAC;IACtB,aAAa,EAAE,MAAM,CAAC;IACtB,qBAAqB,EAAE,MAAM,CAAC;IAC9B,2BAA2B,EAAE,MAAM,CAAC;IACpC,sBAAsB,EAAE,MAAM,CAAC;IAC/B,mBAAmB,EAAE,MAAM,CAAC;IAC5B,yBAAyB,EAAE,MAAM,CAAC;IAClC,UAAU,EAAE,MAAM,CAAC;IACnB,WAAW,EAAE,MAAM,CAAC;IACpB,YAAY,EAAE,OAAO,CAAC;CACvB;AAMD;;GAEG;AACH,qBAAa,YAAa,SAAQ,YAAY;IACrC,iBAAiB,EAAE,iBAAiB,CAazC;IAEK,uBAAuB,EAAE,uBAAuB,CAWrD;IAEK,aAAa,EAAE,MAAM,CAAM;IAC3B,aAAa,EAAE,MAAM,CAAM;IAC3B,qBAAqB,EAAE,MAAM,CAAM;IACnC,2BAA2B,EAAE,MAAM,CAAM;IACzC,sBAAsB,EAAE,MAAM,CAAM;IACpC,mBAAmB,EAAE,MAAM,CAAM;IACjC,yBAAyB,EAAE,MAAM,CAAM;IAEvC,UAAU,EAAE,QAAQ,GAAG,aAAa,GAAG,YAAY,GAAG,EAAE,CAAM;IAC9D,WAAW,EAAE,SAAS,GAAG,QAAQ,GAAG,EAAE,CAAM;IAC5C,YAAY,UAAS;IAE5B,OAAO,CAAC,IAAI,CAAQ;IACpB,OAAO,CAAC,GAAG,CAAc;IACzB,OAAO,CAAC,iBAAiB,CAAS;IAClC,OAAO,CAAC,iBAAiB,CAA0B;IACnD,OAAO,CAAC,iBAAiB,CAA0B;IACnD,OAAO,CAAC,WAAW,CAAiC;IACpD,OAAO,CAAC,WAAW,CAA0B;IAC7C,OAAO,CAAC,UAAU,CAA8B;IAChD,OAAO,CAAC,aAAa,CAAqB;IAC1C,OAAO,CAAC,eAAe,CAA8B;IAErD,OAAO,CAAC,cAAc,CAA6B;IACnD,OAAO,CAAC,mBAAmB,CAA6B;IACxD,OAAO,CAAC,uBAAuB,CAA6B;IAE5D,OAAO,CAAC,YAAY,CAA2B;IAC/C,OAAO,CAAC,gBAAgB,CAAyB;IACjD,OAAO,CAAC,mBAAmB,CAAkC;IAC7D,OAAO,CAAC,uBAAuB,CAAsC;IAErE,OAAO,CAAC,MAAM,CAAC,QAAQ,CAA2B;IAElD,OAAO;IAKP;;;;;;OAMG;WACU,YAAY,CAAC,UAAU,UAAQ;IAU5C;;;;OAIG;IACU,cAAc,CAAC,QAAQ,EAAE,MAAM,EAAE,YAAY,EAAE,OAAO,EAAE,gBAAgB,EAAE,MAAM,EAAE,IAAI,SAAO,GAAG,OAAO,CAAC,OAAO,CAAC;IAuE7H;;;;OAIG;IACU,aAAa;IAanB,uBAAuB,IAAI,OAAO;IAKzC;;;;;;;;;OASG;IACU,UAAU;IAwFvB;;;;OAIG;YACW,gBAAgB;IA2I9B;;;;OAIG;YACW,iBAAiB;IAoC/B;;;;;OAKG;YACW,kBAAkB;IAgFhC;;;OAGG;YACW,sBAAsB;IAUpC;;OAEG;YACW,aAAa;IAK3B;;OAEG;YACW,cAAc;IAK5B;;OAEG;YACW,eAAe;IAK7B;;;;;OAKG;YACW,OAAO;IAqJrB;;;;;OAKG;IACG,SAAS,CAAC,UAAU,EAAE,MAAM,EAAE,MAAM,EAAE,kBAAkB,GAAG,OAAO,CAAC,IAAI,CAAC;IA+B9E;;;;;OAKG;IACG,gBAAgB,CAAC,UAAU,EAAE,MAAM,EAAE,MAAM,EAAE,kBAAkB,GAAG,OAAO,CAAC,IAAI,CAAC;IA+BrF;;;;;OAKG;IACG,mBAAmB,CAAC,UAAU,EAAE,MAAM,EAAE,MAAM,EAAE,kBAAkB,GAAG,OAAO,CAAC,IAAI,CAAC;IA2DxF;;;;;OAKG;IACG,uBAAuB,CAAC,UAAU,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;IAiBhE;;;;;OAKG;YACW,YAAY;IA0B1B;;;;;OAKG;YACW,iBAAiB;IAkB/B;;;OAGG;YACW,WAAW;YASX,qBAAqB;IA8FnC;;;;;;;;OAQG;YACW,gBAAgB;IAgC9B;;;;;OAKG;YACW,gBAAgB;IAe9B;;;;;;OAMG;YACW,SAAS;IAYvB;;;;;;;OAOG;YACW,WAAW;IA+BzB;;;;;OAKG;YACW,eAAe;IA8B7B;;;;;;;OAOG;YACW,UAAU;IAwDxB;;;;OAIG;YACW,qBAAqB;IA2KnC;;;;;;;;OAQG;YACW,iBAAiB;IAoK/B;;;OAGG;YACW,iBAAiB;IAW/B;;;;;;OAMG;YACW,gCAAgC;IAwB9C;;;;;;;;;;;;;;;;;OAiBG;YACW,gCAAgC;IA0C9C;;;;;;;OAOG;YACW,uBAAuB;IAgCrC;;;;;OAKG;IACH,OAAO,CAAC,UAAU;IASlB;;;;;OAKG;IACH,OAAO,CAAC,kCAAkC;IAM1C;;;;OAIG;IACH,OAAO,CAAC,yBAAyB;IAWjC;;;;;OAKG;IACH,OAAO,CAAC,qBAAqB;IAM7B;;;;;;OAMG;YACW,wBAAwB;IA4ItC;;;;OAIG;IACH,OAAO,CAAC,kBAAkB;IAO1B;;;;OAIG;YACW,sBAAsB;IAuCpC;;OAEG;YACW,UAAU;IAcxB;;;;OAIG;YACW,gBAAgB;IAY9B;;;OAGG;YACW,oBAAoB;IAYlC;;OAEG;YACW,oBAAoB;IA2JlC;;;;OAIG;IACH,OAAO,CAAC,wBAAwB;IAqBhC;;;OAGG;IACH,OAAO,CAAC,wBAAwB;IAkBhC;;;;;OAKG;YACW,YAAY;IA0E1B;;;;;;OAMG;IACH,OAAO,CAAC,cAAc;IActB;;;;OAIG;IACG,kBAAkB,CAAC,IAAI,GAAE,MAAa,GAAG,OAAO,CAAC,IAAI,CAAC;IAkY5D;;;;OAIG;IACH,OAAO,CAAC,wBAAwB;CAyBjC"}
1
+ {"version":3,"file":"matterbridge.d.ts","sourceRoot":"","sources":["../src/matterbridge.ts"],"names":[],"mappings":"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"}
@@ -32,10 +32,9 @@ import express from 'express';
32
32
  import os from 'os';
33
33
  import path from 'path';
34
34
  import WebSocket, { WebSocketServer } from 'ws';
35
+ import { BridgedDeviceBasicInformation, BridgedDeviceBasicInformationCluster } from './BridgedDeviceBasicInformationCluster.js';
35
36
  import { CommissioningController, CommissioningServer, MatterServer } from '@project-chip/matter-node.js';
36
- import { BasicInformationCluster, BooleanStateCluster,
37
- // eslint-disable-next-line @typescript-eslint/no-unused-vars
38
- BridgedDeviceBasicInformation, BridgedDeviceBasicInformationCluster, ClusterServer, GeneralCommissioning, PowerSourceCluster, ThreadNetworkDiagnosticsCluster, getClusterNameById, } from '@project-chip/matter-node.js/cluster';
37
+ import { BasicInformationCluster, BooleanStateCluster, ClusterServer, FixedLabelCluster, GeneralCommissioning, GeneralDiagnostics, GeneralDiagnosticsCluster, PowerSourceCluster, ThreadNetworkDiagnosticsCluster, getClusterNameById, } from '@project-chip/matter-node.js/cluster';
39
38
  import { DeviceTypeId, VendorId } from '@project-chip/matter-node.js/datatype';
40
39
  import { Aggregator, DeviceTypes, NodeStateInformation } from '@project-chip/matter-node.js/device';
41
40
  import { Format, Level, Logger } from '@project-chip/matter-node.js/log';
@@ -190,7 +189,7 @@ export class Matterbridge extends EventEmitter {
190
189
  await this.showCommissioningQRCode(this.commissioningServer, this.matterbridgeContext, this.nodeContext, 'Matterbridge');
191
190
  // Set reachability to true and trigger event after 60 seconds
192
191
  setTimeout(() => {
193
- this.log.info(`*Setting reachability to true for ${plg}Matterbridge${db}`);
192
+ this.log.info(`Setting reachability to true for ${plg}Matterbridge${db}`);
194
193
  if (this.commissioningServer)
195
194
  this.setCommissioningServerReachability(this.commissioningServer, true);
196
195
  if (this.matterAggregator)
@@ -367,7 +366,7 @@ export class Matterbridge extends EventEmitter {
367
366
  // Delete matter storage file
368
367
  await fs.unlink(path.join(this.matterbridgeDirectory, 'matterbridge.json'));
369
368
  // Delete node storage directory with its subdirectories
370
- await fs.rmdir(path.join(this.matterbridgeDirectory, 'storage'), { recursive: true });
369
+ await fs.rm(path.join(this.matterbridgeDirectory, 'storage'), { recursive: true });
371
370
  this.log.info('Factory reset done! Remove all paired devices from the controllers.');
372
371
  this.emit('shutdown');
373
372
  process.exit(0);
@@ -611,6 +610,31 @@ export class Matterbridge extends EventEmitter {
611
610
  await this.cleanup('shutting down...', false);
612
611
  this.hasCleanupStarted = false;
613
612
  }
613
+ /**
614
+ * Shut down the process and reset.
615
+ */
616
+ async unregisterAndShutdownProcess() {
617
+ this.log.info('Unregistering all devices and shutting down...');
618
+ for (const plugin of this.registeredPlugins.filter((plugin) => plugin.enabled && !plugin.error)) {
619
+ await this.removeAllBridgedDevices(plugin.name);
620
+ }
621
+ await this.cleanup('unregistered all devices and shutting down...', false);
622
+ this.hasCleanupStarted = false;
623
+ }
624
+ /**
625
+ * Shut down the process and reset.
626
+ */
627
+ async shutdownProcessAndReset() {
628
+ await this.cleanup('shutting down with reset...', false);
629
+ this.hasCleanupStarted = false;
630
+ }
631
+ /**
632
+ * Shut down the process and factory reset.
633
+ */
634
+ async shutdownProcessAndFactoryReset() {
635
+ await this.cleanup('shutting down with factory reset...', false);
636
+ this.hasCleanupStarted = false;
637
+ }
614
638
  /**
615
639
  * Cleans up the Matterbridge instance.
616
640
  * @param message - The cleanup message.
@@ -628,11 +652,11 @@ export class Matterbridge extends EventEmitter {
628
652
  for (const plugin of this.registeredPlugins) {
629
653
  if (!plugin.enabled || plugin.error)
630
654
  continue;
631
- this.log.info(`*Shutting down plugin ${plg}${plugin.name}${nf}`);
655
+ this.log.info(`Shutting down plugin ${plg}${plugin.name}${nf}`);
632
656
  if (plugin.platform) {
633
657
  try {
634
658
  await plugin.platform.onShutdown('Matterbridge is closing: ' + message);
635
- await this.savePluginConfig(plugin);
659
+ // await this.savePluginConfig(plugin);
636
660
  }
637
661
  catch (error) {
638
662
  this.log.error(`Plugin ${plg}${plugin.name}${er} shutting down error: ${error}`);
@@ -710,7 +734,7 @@ export class Matterbridge extends EventEmitter {
710
734
  });
711
735
  this.webSocketServer = undefined;
712
736
  }
713
- /*const cleanupTimeout1 =*/ setTimeout(async () => {
737
+ setTimeout(async () => {
714
738
  // Closing matter
715
739
  await this.stopMatter();
716
740
  // Closing storage
@@ -740,7 +764,7 @@ export class Matterbridge extends EventEmitter {
740
764
  this.registeredPlugins = [];
741
765
  this.registeredDevices = [];
742
766
  this.log.info('Waiting for matter to deliver last messages...');
743
- /*const cleanupTimeout2 =*/ setTimeout(async () => {
767
+ setTimeout(async () => {
744
768
  if (restart) {
745
769
  if (message === 'updating...') {
746
770
  this.log.info('Cleanup completed. Updating...');
@@ -754,14 +778,27 @@ export class Matterbridge extends EventEmitter {
754
778
  }
755
779
  }
756
780
  else {
781
+ if (message === 'shutting down with reset...') {
782
+ // Delete matter storage file
783
+ this.log.info('Resetting Matterbridge commissioning information...');
784
+ await fs.unlink(path.join(this.matterbridgeDirectory, 'matterbridge.json'));
785
+ this.log.info('Reset done! Remove all paired devices from the controllers.');
786
+ }
787
+ if (message === 'shutting down with factory reset...') {
788
+ // Delete matter storage file
789
+ this.log.info('Resetting Matterbridge commissioning information...');
790
+ await fs.unlink(path.join(this.matterbridgeDirectory, 'matterbridge.json'));
791
+ // Delete node storage directory with its subdirectories
792
+ this.log.info('Resetting Matterbridge storage...');
793
+ await fs.rm(path.join(this.matterbridgeDirectory, 'storage'), { recursive: true });
794
+ this.log.info('Factory reset done! Remove all paired devices from the controllers.');
795
+ }
757
796
  this.log.info('Cleanup completed. Shutting down...');
758
797
  Matterbridge.instance = undefined;
759
798
  this.emit('shutdown');
760
799
  }
761
800
  }, 2 * 1000);
762
- //cleanupTimeout2.unref();
763
801
  }, 3 * 1000);
764
- //cleanupTimeout1.unref();
765
802
  }
766
803
  }
767
804
  /**
@@ -911,7 +948,7 @@ export class Matterbridge extends EventEmitter {
911
948
  async removeAllBridgedDevices(pluginName) {
912
949
  const plugin = this.findPlugin(pluginName);
913
950
  if (this.bridgeMode === 'childbridge' && plugin?.type === 'AccessoryPlatform') {
914
- this.log.info(`Removing devices for plugin ${plg}${pluginName}${nf}: AccessoryPlatform not supported in childbridge mode`);
951
+ this.log.info(`Removing devices for plugin ${plg}${pluginName}${nf} type AccessoryPlatform is not supported in childbridge mode`);
915
952
  return;
916
953
  }
917
954
  const devicesToRemove = [];
@@ -1230,6 +1267,7 @@ export class Matterbridge extends EventEmitter {
1230
1267
  .then(() => {
1231
1268
  plugin.configured = true;
1232
1269
  this.log.info(`Configured plugin ${plg}${plugin.name}${db} type ${typ}${plugin.type}${db}`);
1270
+ this.savePluginConfig(plugin);
1233
1271
  return Promise.resolve();
1234
1272
  })
1235
1273
  .catch((err) => {
@@ -1261,7 +1299,7 @@ export class Matterbridge extends EventEmitter {
1261
1299
  this.log.error(`Plugin ${plg}${plugin.name}${er} already loaded`);
1262
1300
  return Promise.resolve(plugin.platform);
1263
1301
  }
1264
- this.log.info(`Loading plugin ${plg}${plugin.name}${db} type ${typ}${plugin.type}${db}`);
1302
+ this.log.info(`Loading plugin ${plg}${plugin.name}${nf} type ${typ}${plugin.type}${nf}`);
1265
1303
  try {
1266
1304
  // Load the package.json of the plugin
1267
1305
  const packageJson = JSON.parse(await fs.readFile(plugin.path, 'utf8'));
@@ -1280,6 +1318,7 @@ export class Matterbridge extends EventEmitter {
1280
1318
  const platform = pluginInstance.default(this, log, config);
1281
1319
  platform.name = packageJson.name;
1282
1320
  platform.config = config;
1321
+ platform.version = packageJson.version;
1283
1322
  plugin.name = packageJson.name;
1284
1323
  plugin.description = packageJson.description;
1285
1324
  plugin.version = packageJson.version;
@@ -1290,7 +1329,19 @@ export class Matterbridge extends EventEmitter {
1290
1329
  plugin.registeredDevices = 0;
1291
1330
  plugin.addedDevices = 0;
1292
1331
  await this.nodeContext?.set('plugins', this.getBaseRegisteredPlugins());
1293
- this.log.info(`Loaded plugin ${plg}${plugin.name}${db} type ${typ}${platform.type}${db} (entrypoint ${UNDERLINE}${pluginEntry}${UNDERLINEOFF})`);
1332
+ this.getLatestVersion(plugin.name)
1333
+ .then(async (latestVersion) => {
1334
+ plugin.latestVersion = latestVersion;
1335
+ await this.nodeContext?.set('plugins', this.getBaseRegisteredPlugins());
1336
+ if (plugin.version !== latestVersion)
1337
+ this.log.warn(`The plugin ${plg}${plugin.name}${wr} is out of date. Current version: ${plugin.version}, Latest version: ${latestVersion}`);
1338
+ else
1339
+ this.log.info(`The plugin ${plg}${plugin.name}${nf} is up to date. Current version: ${plugin.version}, Latest version: ${latestVersion}`);
1340
+ })
1341
+ .catch((error) => {
1342
+ this.log.error(`Error getting ${plugin.name} latest version: ${error}`);
1343
+ });
1344
+ this.log.info(`Loaded plugin ${plg}${plugin.name}${nf} type ${typ}${platform.type} ${db}(entrypoint ${UNDERLINE}${pluginEntry}${UNDERLINEOFF})`);
1294
1345
  if (start)
1295
1346
  this.startPlugin(plugin, message); // No await do it asyncronously
1296
1347
  return Promise.resolve(platform);
@@ -1532,9 +1583,10 @@ export class Matterbridge extends EventEmitter {
1532
1583
  await this.startMatterServer();
1533
1584
  this.log.info('Matter server started');
1534
1585
  await this.showCommissioningQRCode(this.commissioningServer, this.matterbridgeContext, this.nodeContext, 'Matterbridge');
1586
+ // logEndpoint(this.commissioningServer.getRootEndpoint());
1535
1587
  //if (hasParameter('advertise')) await this.commissioningServer.advertise();
1536
1588
  setTimeout(() => {
1537
- this.log.info(`*Setting reachability to true for ${plg}Matterbridge${db}`);
1589
+ this.log.info(`Setting reachability to true for ${plg}Matterbridge${db}`);
1538
1590
  if (this.commissioningServer)
1539
1591
  this.setCommissioningServerReachability(this.commissioningServer, true);
1540
1592
  if (this.matterAggregator)
@@ -1637,7 +1689,7 @@ export class Matterbridge extends EventEmitter {
1637
1689
  }
1638
1690
  await this.showCommissioningQRCode(plugin.commissioningServer, plugin.storageContext, plugin.nodeContext, plugin.name);
1639
1691
  // Setting reachability to true
1640
- this.log.info(`*Setting reachability to true for ${plg}${plugin.name}${db}`);
1692
+ this.log.info(`Setting reachability to true for ${plg}${plugin.name}${db}`);
1641
1693
  if (plugin.commissioningServer)
1642
1694
  this.setCommissioningServerReachability(plugin.commissioningServer, true);
1643
1695
  if (plugin.type === 'AccessoryPlatform' && plugin.device)
@@ -1737,14 +1789,14 @@ export class Matterbridge extends EventEmitter {
1737
1789
  if (!commissioningServer || !storageContext || !pluginName)
1738
1790
  return;
1739
1791
  if (!commissioningServer.isCommissioned()) {
1740
- this.log.info(`***The commissioning server on port ${commissioningServer.getPort()} for ${plg}${pluginName}${nf} is not commissioned. Pair it scanning the QR code ...`);
1741
1792
  const { qrPairingCode, manualPairingCode } = commissioningServer.getPairingCode();
1742
1793
  await storageContext.set('qrPairingCode', qrPairingCode);
1743
1794
  await storageContext.set('manualPairingCode', manualPairingCode);
1744
1795
  await nodeContext.set('qrPairingCode', qrPairingCode);
1745
1796
  await nodeContext.set('manualPairingCode', manualPairingCode);
1746
1797
  const QrCode = new QrCodeSchema();
1747
- this.log.info(`Pairing code:\n\n${QrCode.encode(qrPairingCode)}\n${plg}${pluginName}${nf}\n\nqrPairingCode: ${qrPairingCode}\n\nManual pairing code: ${manualPairingCode}\n`);
1798
+ this.log.info(`***The commissioning server on port ${commissioningServer.getPort()} for ${plg}${pluginName}${nf} is not commissioned. Pair it scanning the QR code:\n\n` +
1799
+ `${QrCode.encode(qrPairingCode)}\n${plg}${pluginName}${nf}\n\nqrPairingCode: ${qrPairingCode}\n\nManual pairing code: ${manualPairingCode}\n`);
1748
1800
  if (pluginName !== 'Matterbridge') {
1749
1801
  const plugin = this.findPlugin(pluginName);
1750
1802
  if (plugin) {
@@ -1756,7 +1808,7 @@ export class Matterbridge extends EventEmitter {
1756
1808
  await this.nodeContext?.set('plugins', this.getBaseRegisteredPlugins());
1757
1809
  }
1758
1810
  else {
1759
- this.log.info(`***The commissioning server on port ${commissioningServer.getPort()} for ${plg}${pluginName}${nf} is already commissioned . Waiting for controllers to connect ...`);
1811
+ this.log.info(`*The commissioning server on port ${commissioningServer.getPort()} for ${plg}${pluginName}${nf} is already commissioned . Waiting for controllers to connect ...`);
1760
1812
  if (pluginName !== 'Matterbridge') {
1761
1813
  const plugin = this.findPlugin(pluginName);
1762
1814
  if (plugin) {
@@ -1805,7 +1857,7 @@ export class Matterbridge extends EventEmitter {
1805
1857
  if (basicInformationCluster && basicInformationCluster.triggerReachableChangedEvent)
1806
1858
  basicInformationCluster.triggerReachableChangedEvent({ reachableNewValue: reachable });
1807
1859
  matterAggregator.getBridgedDevices().forEach((device) => {
1808
- this.log.debug(`*Setting reachability to true for bridged device: ${dev}${device.name}${nf}`);
1860
+ this.log.debug(`Setting reachability to true for bridged device: ${dev}${device.name}${nf}`);
1809
1861
  device.getClusterServer(BridgedDeviceBasicInformationCluster)?.setReachableAttribute(reachable);
1810
1862
  device.getClusterServer(BridgedDeviceBasicInformationCluster)?.triggerReachableChangedEvent({ reachableNewValue: reachable });
1811
1863
  });
@@ -1831,6 +1883,38 @@ export class Matterbridge extends EventEmitter {
1831
1883
  * @returns {CommissioningServer} The created commissioning server.
1832
1884
  */
1833
1885
  async createCommisioningServer(context, pluginName) {
1886
+ const getVendorIdName = (vendorId) => {
1887
+ if (!vendorId)
1888
+ return '';
1889
+ let vendorName = '';
1890
+ switch (vendorId) {
1891
+ case 4937:
1892
+ vendorName = '(AppleHome)';
1893
+ break;
1894
+ case 4996:
1895
+ vendorName = '(AppleKeyChain)';
1896
+ break;
1897
+ case 4362:
1898
+ vendorName = '(SmartThings)';
1899
+ break;
1900
+ case 4939:
1901
+ vendorName = '(HomeAssistant)';
1902
+ break;
1903
+ case 24582:
1904
+ vendorName = '(GoogleHome)';
1905
+ break;
1906
+ case 4701:
1907
+ vendorName = '(Tuya)';
1908
+ break;
1909
+ case 4742:
1910
+ vendorName = '(eWeLink)';
1911
+ break;
1912
+ default:
1913
+ vendorName = '(unknown)';
1914
+ break;
1915
+ }
1916
+ return vendorName;
1917
+ };
1834
1918
  this.log.debug(`Creating matter commissioning server for plugin ${plg}${pluginName}${db}`);
1835
1919
  const deviceName = await context.get('deviceName');
1836
1920
  const deviceType = await context.get('deviceType');
@@ -1873,16 +1957,9 @@ export class Matterbridge extends EventEmitter {
1873
1957
  const info = commissioningServer.getActiveSessionInformation(fabricIndex);
1874
1958
  let connected = false;
1875
1959
  info.forEach((session) => {
1876
- this.log.info(`***Active session changed on fabric ${fabricIndex} ${session.fabric?.rootVendorId}/${session.fabric?.label} for ${plg}${pluginName}${nf}`, debugStringify(session));
1960
+ this.log.info(`*Active session changed on fabric ${fabricIndex} ${session.fabric?.rootVendorId}${getVendorIdName(session.fabric?.rootVendorId)}/${session.fabric?.label} for ${plg}${pluginName}${nf}`, debugStringify(session));
1877
1961
  if (session.isPeerActive === true && session.secure === true && session.numberOfActiveSubscriptions >= 1) {
1878
- let controllerName = '';
1879
- if (session.fabric?.rootVendorId === 4937)
1880
- controllerName = 'AppleHome';
1881
- if (session.fabric?.rootVendorId === 4362)
1882
- controllerName = 'SmartThings';
1883
- if (session.fabric?.rootVendorId === 4939)
1884
- controllerName = 'HomeAssistant';
1885
- this.log.info(`***Controller ${session.fabric?.rootVendorId}${controllerName !== '' ? '(' + controllerName + ')' : ''}/${session.fabric?.label} connected to ${plg}${pluginName}${nf} on session ${session.name}`);
1962
+ this.log.info(`*Controller ${session.fabric?.rootVendorId}${getVendorIdName(session.fabric?.rootVendorId)}/${session.fabric?.label} connected to ${plg}${pluginName}${nf} on session ${session.name}`);
1886
1963
  connected = true;
1887
1964
  }
1888
1965
  });
@@ -1938,15 +2015,15 @@ export class Matterbridge extends EventEmitter {
1938
2015
  }
1939
2016
  Logger.defaultLogLevel = this.debugEnabled ? Level.DEBUG : Level.INFO;
1940
2017
  }
1941
- //logEndpoint(commissioningServer.getRootEndpoint());
2018
+ // logEndpoint(commissioningServer.getRootEndpoint());
1942
2019
  }, 2000);
1943
2020
  }
1944
2021
  },
1945
2022
  commissioningChangedCallback: async (fabricIndex) => {
1946
2023
  const info = commissioningServer.getCommissionedFabricInformation(fabricIndex);
1947
- this.log.debug(`***Commissioning changed on fabric ${fabricIndex} for ${plg}${pluginName}${nf}`, debugStringify(info));
2024
+ this.log.debug(`*Commissioning changed on fabric ${fabricIndex} for ${plg}${pluginName}${nf}`, debugStringify(info));
1948
2025
  if (info.length === 0) {
1949
- this.log.warn(`***Commissioning removed from fabric ${fabricIndex} for ${plg}${pluginName}${wr}. Resetting the commissioning server ...`);
2026
+ this.log.warn(`*Commissioning removed from fabric ${fabricIndex} for ${plg}${pluginName}${wr}. Resetting the commissioning server ...`);
1950
2027
  await commissioningServer.factoryReset();
1951
2028
  if (pluginName === 'Matterbridge') {
1952
2029
  await this.matterbridgeContext?.clearAll();
@@ -1961,10 +2038,27 @@ export class Matterbridge extends EventEmitter {
1961
2038
  }
1962
2039
  }
1963
2040
  }
1964
- this.log.warn(`***Restart to activate the pairing for ${plg}${pluginName}${wr}`);
2041
+ this.log.warn(`*Restart to activate the pairing for ${plg}${pluginName}${wr}`);
1965
2042
  }
1966
2043
  },
1967
2044
  });
2045
+ const gdcCluster = commissioningServer.getRootClusterServer(GeneralDiagnosticsCluster);
2046
+ if (gdcCluster) {
2047
+ gdcCluster.setNetworkInterfacesAttribute([
2048
+ {
2049
+ name: 'eth0',
2050
+ isOperational: true,
2051
+ offPremiseServicesReachableIPv4: null,
2052
+ offPremiseServicesReachableIPv6: null,
2053
+ hardwareAddress: Uint8Array.fromString('00000000'),
2054
+ iPv4Addresses: [Uint8Array.fromString('0000')],
2055
+ iPv6Addresses: [Uint8Array.fromString('0000000000000000')],
2056
+ type: GeneralDiagnostics.InterfaceType.Ethernet,
2057
+ },
2058
+ ]);
2059
+ }
2060
+ else
2061
+ this.log.warn(`*GeneralDiagnosticsCluster not found for ${plg}${pluginName}${wr}`);
1968
2062
  commissioningServer.addCommandHandler('testEventTrigger', async ({ request: { enableKey, eventTrigger } }) => this.log.info(`testEventTrigger called on GeneralDiagnostic cluster: ${enableKey} ${eventTrigger}`));
1969
2063
  return commissioningServer;
1970
2064
  }
@@ -1991,7 +2085,7 @@ export class Matterbridge extends EventEmitter {
1991
2085
  const matterAggregator = new Aggregator();
1992
2086
  matterAggregator.addClusterServer(ClusterServer(BasicInformationCluster, {
1993
2087
  dataModelRevision: 1,
1994
- location: 'XX',
2088
+ location: 'FR',
1995
2089
  vendorId: VendorId(0xfff1),
1996
2090
  vendorName: 'Matterbridge',
1997
2091
  productId: 0x8000,
@@ -2228,6 +2322,7 @@ export class Matterbridge extends EventEmitter {
2228
2322
  type: plugin.type,
2229
2323
  name: plugin.name,
2230
2324
  version: plugin.version,
2325
+ latestVersion: plugin.latestVersion,
2231
2326
  description: plugin.description,
2232
2327
  author: plugin.author,
2233
2328
  enabled: plugin.enabled,
@@ -2522,6 +2617,7 @@ export class Matterbridge extends EventEmitter {
2522
2617
  //console.log(error);
2523
2618
  }
2524
2619
  data.push({
2620
+ endpoint: registeredDevice.device.number ? registeredDevice.device.number.toString() : '...',
2525
2621
  clusterName: clusterServer.name,
2526
2622
  clusterId: '0x' + clusterServer.id.toString(16).padStart(2, '0'),
2527
2623
  attributeName: key,
@@ -2530,6 +2626,37 @@ export class Matterbridge extends EventEmitter {
2530
2626
  });
2531
2627
  });
2532
2628
  });
2629
+ registeredDevice.device.getChildEndpoints().forEach((childEndpoint) => {
2630
+ const name = registeredDevice.device.getChildEndpointName(childEndpoint);
2631
+ const clusterServers = childEndpoint.getAllClusterServers();
2632
+ clusterServers.forEach((clusterServer) => {
2633
+ Object.entries(clusterServer.attributes).forEach(([key, value]) => {
2634
+ if (clusterServer.name === 'EveHistory')
2635
+ return;
2636
+ //this.log.debug(`***--clusterServer: ${clusterServer.name}(${clusterServer.id}) attribute:${key}(${value.id}) ${value.isFixed} ${value.isWritable} ${value.isWritable}`);
2637
+ let attributeValue;
2638
+ try {
2639
+ if (typeof value.getLocal() === 'object')
2640
+ attributeValue = stringify(value.getLocal());
2641
+ else
2642
+ attributeValue = value.getLocal().toString();
2643
+ }
2644
+ catch (error) {
2645
+ attributeValue = 'Unavailable';
2646
+ this.log.debug(`GetLocal error ${error} in clusterServer: ${clusterServer.name}(${clusterServer.id}) attribute: ${key}(${value.id})`);
2647
+ //console.log(error);
2648
+ }
2649
+ data.push({
2650
+ endpoint: (childEndpoint.number ? childEndpoint.number.toString() : '...') + (name ? ' (' + name + ')' : ''),
2651
+ clusterName: clusterServer.name,
2652
+ clusterId: '0x' + clusterServer.id.toString(16).padStart(2, '0'),
2653
+ attributeName: key,
2654
+ attributeId: '0x' + value.id.toString(16).padStart(2, '0'),
2655
+ attributeValue,
2656
+ });
2657
+ });
2658
+ });
2659
+ });
2533
2660
  }
2534
2661
  });
2535
2662
  res.json(data);
@@ -2567,17 +2694,34 @@ export class Matterbridge extends EventEmitter {
2567
2694
  this.debugEnabled = false;
2568
2695
  Logger.defaultLogLevel = Level.WARN;
2569
2696
  }
2697
+ else if (param === 'Error') {
2698
+ this.log.setLogDebug(false);
2699
+ this.debugEnabled = false;
2700
+ Logger.defaultLogLevel = Level.ERROR;
2701
+ }
2570
2702
  this.registeredPlugins.forEach((plugin) => {
2571
2703
  plugin.platform?.log.setLogDebug(this.debugEnabled);
2572
2704
  });
2573
2705
  }
2574
- // Handle the command shutdown from Header
2706
+ // Handle the command reset from Settings
2707
+ if (command === 'unregister') {
2708
+ await this.unregisterAndShutdownProcess();
2709
+ }
2710
+ // Handle the command reset from Settings
2711
+ if (command === 'reset') {
2712
+ this.shutdownProcessAndReset(); // No await do it asyncronously
2713
+ }
2714
+ // Handle the command factoryreset from Settings
2715
+ if (command === 'factoryreset') {
2716
+ this.shutdownProcessAndFactoryReset(); // No await do it asyncronously
2717
+ }
2718
+ // Handle the command restart from Header
2575
2719
  if (command === 'shutdown') {
2576
- this.shutdownProcess();
2720
+ this.shutdownProcess(); // No await do it asyncronously
2577
2721
  }
2578
2722
  // Handle the command restart from Header
2579
2723
  if (command === 'restart') {
2580
- this.restartProcess();
2724
+ this.restartProcess(); // No await do it asyncronously
2581
2725
  }
2582
2726
  // Handle the command update from Header
2583
2727
  if (command === 'update') {
@@ -2608,7 +2752,7 @@ export class Matterbridge extends EventEmitter {
2608
2752
  }
2609
2753
  }
2610
2754
  // Handle the command addplugin from Home
2611
- if (command === 'addplugin') {
2755
+ if (command === 'addplugin' || command === 'installplugin') {
2612
2756
  param = param.replace(/\*/g, '\\');
2613
2757
  if (this.registeredPlugins.find((plugin) => plugin.name === param)) {
2614
2758
  this.log.warn(`Plugin ${plg}${param}${wr} already added to matterbridge`);
@@ -2647,7 +2791,7 @@ export class Matterbridge extends EventEmitter {
2647
2791
  if (index !== -1) {
2648
2792
  if (this.registeredPlugins[index].platform) {
2649
2793
  await this.registeredPlugins[index].platform?.onShutdown('The plugin has been removed.');
2650
- await this.savePluginConfig(this.registeredPlugins[index]);
2794
+ // await this.savePluginConfig(this.registeredPlugins[index]);
2651
2795
  }
2652
2796
  this.registeredPlugins.splice(index, 1);
2653
2797
  await this.nodeContext?.set('plugins', this.getBaseRegisteredPlugins());
@@ -2665,10 +2809,13 @@ export class Matterbridge extends EventEmitter {
2665
2809
  const plugin = plugins.find((plugin) => plugin.name === param);
2666
2810
  if (plugin) {
2667
2811
  plugin.enabled = true;
2812
+ plugin.error = undefined;
2668
2813
  plugin.loaded = undefined;
2669
2814
  plugin.started = undefined;
2670
2815
  plugin.configured = undefined;
2671
2816
  plugin.connected = undefined;
2817
+ plugin.platform = undefined;
2818
+ plugin.registeredDevices = undefined;
2672
2819
  await this.nodeContext?.set('plugins', plugins);
2673
2820
  this.log.info(`Enabled plugin ${plg}${param}${nf}`);
2674
2821
  }
@@ -2679,7 +2826,6 @@ export class Matterbridge extends EventEmitter {
2679
2826
  pluginToEnable.platform = await this.loadPlugin(pluginToEnable);
2680
2827
  if (pluginToEnable.platform) {
2681
2828
  await this.startPlugin(pluginToEnable, 'The plugin has been enabled', true);
2682
- pluginToEnable.enabled = false;
2683
2829
  }
2684
2830
  else {
2685
2831
  pluginToEnable.enabled = false;
@@ -2695,24 +2841,29 @@ export class Matterbridge extends EventEmitter {
2695
2841
  if (pluginToDisable) {
2696
2842
  if (pluginToDisable.platform) {
2697
2843
  await pluginToDisable.platform.onShutdown('The plugin has been removed.');
2698
- await this.savePluginConfig(pluginToDisable);
2844
+ // await this.savePluginConfig(pluginToDisable);
2699
2845
  }
2700
2846
  pluginToDisable.enabled = false;
2847
+ pluginToDisable.error = undefined;
2701
2848
  pluginToDisable.loaded = undefined;
2702
2849
  pluginToDisable.started = undefined;
2703
2850
  pluginToDisable.configured = undefined;
2704
2851
  pluginToDisable.connected = undefined;
2705
2852
  pluginToDisable.platform = undefined;
2853
+ pluginToDisable.registeredDevices = undefined;
2706
2854
  const plugins = await this.nodeContext?.get('plugins');
2707
2855
  if (!plugins)
2708
2856
  return;
2709
2857
  const plugin = plugins.find((plugin) => plugin.name === param);
2710
2858
  if (plugin) {
2711
2859
  plugin.enabled = false;
2860
+ plugin.error = undefined;
2712
2861
  plugin.loaded = undefined;
2713
2862
  plugin.started = undefined;
2714
2863
  plugin.configured = undefined;
2715
2864
  plugin.connected = undefined;
2865
+ plugin.platform = undefined;
2866
+ plugin.registeredDevices = undefined;
2716
2867
  await this.nodeContext?.set('plugins', plugins);
2717
2868
  this.log.info(`Disabled plugin ${plg}${param}${nf}`);
2718
2869
  }
@@ -2728,7 +2879,7 @@ export class Matterbridge extends EventEmitter {
2728
2879
  if (!useHttps) {
2729
2880
  // Listen on HTTP
2730
2881
  this.expressServer = this.expressApp.listen(port, () => {
2731
- this.log.info(`The frontend is running on ${UNDERLINE}http://localhost:${port}${UNDERLINEOFF}${rs}`);
2882
+ this.log.info(`The frontend is listening on ${UNDERLINE}http://${this.systemInformation.ipv4Address}:${port}${UNDERLINEOFF}${rs}`);
2732
2883
  });
2733
2884
  }
2734
2885
  else {
@@ -2742,7 +2893,7 @@ export class Matterbridge extends EventEmitter {
2742
2893
  // Specify the port to listen on, for example 443 for default HTTPS
2743
2894
  const PORT = 443;
2744
2895
  httpsServer.listen(PORT, () => {
2745
- this.log.info(`The frontend is running on ${UNDERLINE}https://localhost:${PORT}${UNDERLINEOFF}${rs}`);
2896
+ this.log.info(`The frontend is listening on ${UNDERLINE}https://${this.systemInformation.ipv4Address}:${PORT}${UNDERLINEOFF}${rs}`);
2746
2897
  });
2747
2898
  }
2748
2899
  this.log.debug(`Frontend initialized on port ${YELLOW}${port}${db} static ${UNDERLINE}${path.join(this.rootDirectory, 'frontend/build')}${UNDERLINEOFF}${rs}`);
@@ -2753,6 +2904,16 @@ export class Matterbridge extends EventEmitter {
2753
2904
  * @returns The attributes of the cluster servers in the device.
2754
2905
  */
2755
2906
  getClusterTextFromDevice(device) {
2907
+ const stringifyFixedLabel = (endpoint) => {
2908
+ const labelList = endpoint.getClusterServer(FixedLabelCluster)?.getLabelListAttribute();
2909
+ if (!labelList)
2910
+ return;
2911
+ const composed = labelList.find((entry) => entry.label === 'composed');
2912
+ if (composed)
2913
+ return 'Composed: ' + composed.value;
2914
+ else
2915
+ return ''; //'FixedLabel: ' + labelList.map((entry) => entry.label + ': ' + entry.value).join(' ');
2916
+ };
2756
2917
  let attributes = '';
2757
2918
  //this.log.debug(`getClusterTextFromDevice: ${device.name}`);
2758
2919
  const clusterServers = device.getAllClusterServers();
@@ -2789,7 +2950,9 @@ export class Matterbridge extends EventEmitter {
2789
2950
  if (clusterServer.name === 'PressureMeasurement')
2790
2951
  attributes += `Pressure: ${clusterServer.getMeasuredValueAttribute()} `;
2791
2952
  if (clusterServer.name === 'FlowMeasurement')
2792
- attributes += `Pressure: ${clusterServer.getMeasuredValueAttribute()} `;
2953
+ attributes += `Flow: ${clusterServer.getMeasuredValueAttribute()} `;
2954
+ if (clusterServer.name === 'FixedLabel')
2955
+ attributes += `${stringifyFixedLabel(device)} `;
2793
2956
  });
2794
2957
  return attributes;
2795
2958
  }
@@ -2819,6 +2982,31 @@ function restartProcess() {
2819
2982
  process.exit();
2820
2983
  }
2821
2984
 
2985
+ import React from 'react';
2986
+ import Form from "@rjsf/core";
2987
+
2988
+ const schema = {
2989
+ title: "Todo",
2990
+ type: "object",
2991
+ required: ["title"],
2992
+ properties: {
2993
+ title: {type: "string", title: "Title", default: "A new task"},
2994
+ done: {type: "boolean", title: "Done?", default: false}
2995
+ }
2996
+ };
2997
+
2998
+ const log = (type) => console.log.bind(console, type);
2999
+
3000
+ function Todo() {
3001
+ return (
3002
+ <Form schema={schema}
3003
+ onChange={log("changed")}
3004
+ onSubmit={log("submitted")}
3005
+ onError={log("errors")} />
3006
+ );
3007
+ }
3008
+
3009
+ export default Todo;
2822
3010
 
2823
3011
  /*
2824
3012
  How frontend was created