matterbridge 3.2.8-dev-20250916-967e0b8 → 3.2.8-dev-20250918-52dc90c

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 (105) hide show
  1. package/CHANGELOG.md +12 -2
  2. package/dist/frontend.js +132 -223
  3. package/dist/frontendTypes.js +25 -0
  4. package/dist/matterbridge.js +9 -40
  5. package/dist/pluginManager.js +0 -2
  6. package/dist/shelly.js +4 -5
  7. package/dist/utils/spawn.js +4 -4
  8. package/frontend/build/assets/index.css +1 -0
  9. package/frontend/build/assets/index.js +23 -0
  10. package/frontend/build/assets/vendor_emotion.js +1 -0
  11. package/frontend/build/assets/vendor_lodash.js +1 -0
  12. package/frontend/build/assets/vendor_mdi.js +1 -0
  13. package/frontend/build/assets/vendor_mui.js +137 -0
  14. package/frontend/build/assets/vendor_node_modules.js +100 -0
  15. package/frontend/build/assets/vendor_notistack.js +5 -0
  16. package/frontend/build/assets/vendor_qrcode.js +9 -0
  17. package/frontend/build/assets/vendor_react_table.js +1 -0
  18. package/frontend/build/assets/vendor_rjsf.js +10 -0
  19. package/frontend/build/index.html +27 -1
  20. package/frontend/index.html +17 -0
  21. package/frontend/package-lock.json +5697 -17190
  22. package/frontend/package.json +60 -53
  23. package/npm-shrinkwrap.json +5 -5
  24. package/package.json +1 -1
  25. package/frontend/build/asset-manifest.json +0 -85
  26. package/frontend/build/favicon.ico +0 -0
  27. package/frontend/build/manifest.json +0 -15
  28. package/frontend/build/robots.txt +0 -3
  29. package/frontend/build/static/css/main.56c16a87.css +0 -2
  30. package/frontend/build/static/css/main.56c16a87.css.map +0 -1
  31. package/frontend/build/static/js/main.c1ca9eaf.js +0 -3
  32. package/frontend/build/static/js/main.c1ca9eaf.js.LICENSE.txt +0 -97
  33. package/frontend/build/static/js/main.c1ca9eaf.js.map +0 -1
  34. package/frontend/build/static/media/roboto-cyrillic-300-normal.44340549d94d10899346.woff +0 -0
  35. package/frontend/build/static/media/roboto-cyrillic-300-normal.89d0351bce4bc857dba6.woff2 +0 -0
  36. package/frontend/build/static/media/roboto-cyrillic-400-normal.86d5c52f4588f9f221d7.woff2 +0 -0
  37. package/frontend/build/static/media/roboto-cyrillic-400-normal.d67ac585bb6a05dbf71c.woff +0 -0
  38. package/frontend/build/static/media/roboto-cyrillic-500-normal.1fb2c6d685bfb888cfa3.woff2 +0 -0
  39. package/frontend/build/static/media/roboto-cyrillic-500-normal.36f79cc7e73a69da4438.woff +0 -0
  40. package/frontend/build/static/media/roboto-cyrillic-700-normal.e00802373a2c2db6b30d.woff +0 -0
  41. package/frontend/build/static/media/roboto-cyrillic-700-normal.fd3dfdd6cb1a9175b63d.woff2 +0 -0
  42. package/frontend/build/static/media/roboto-cyrillic-ext-300-normal.a80c0d0719b1acb8f731.woff +0 -0
  43. package/frontend/build/static/media/roboto-cyrillic-ext-300-normal.b9d87b04a9119d8d2fdf.woff2 +0 -0
  44. package/frontend/build/static/media/roboto-cyrillic-ext-400-normal.31476620b88eec076438.woff2 +0 -0
  45. package/frontend/build/static/media/roboto-cyrillic-ext-400-normal.5e3f232f89080810567d.woff +0 -0
  46. package/frontend/build/static/media/roboto-cyrillic-ext-500-normal.634ee2238bf30f362d52.woff2 +0 -0
  47. package/frontend/build/static/media/roboto-cyrillic-ext-500-normal.d6c661248da2fde17768.woff +0 -0
  48. package/frontend/build/static/media/roboto-cyrillic-ext-700-normal.361cdfd3a3f9c4bb09ca.woff2 +0 -0
  49. package/frontend/build/static/media/roboto-cyrillic-ext-700-normal.6b08bc756cd72f5af9e8.woff +0 -0
  50. package/frontend/build/static/media/roboto-greek-300-normal.8300b541aa89b8301a6f.woff +0 -0
  51. package/frontend/build/static/media/roboto-greek-300-normal.fdd1f928a606aa116a44.woff2 +0 -0
  52. package/frontend/build/static/media/roboto-greek-400-normal.98a717d5a38e77c0f657.woff2 +0 -0
  53. package/frontend/build/static/media/roboto-greek-400-normal.ecd8572d631f20ff5bd5.woff +0 -0
  54. package/frontend/build/static/media/roboto-greek-500-normal.4fe733bc436afc295c24.woff +0 -0
  55. package/frontend/build/static/media/roboto-greek-500-normal.5c8100481d4e784afbf2.woff2 +0 -0
  56. package/frontend/build/static/media/roboto-greek-700-normal.d23e03cf87ba44e5af6f.woff +0 -0
  57. package/frontend/build/static/media/roboto-greek-700-normal.d7dfd0b02cd8311e2a97.woff2 +0 -0
  58. package/frontend/build/static/media/roboto-greek-ext-300-normal.60729cafbded24073dfb.woff +0 -0
  59. package/frontend/build/static/media/roboto-greek-ext-300-normal.a88b77bb10633a8045e3.woff2 +0 -0
  60. package/frontend/build/static/media/roboto-greek-ext-400-normal.2d5875b032a1cca91eb2.woff2 +0 -0
  61. package/frontend/build/static/media/roboto-greek-ext-400-normal.a0baf7d6726d8f751a27.woff +0 -0
  62. package/frontend/build/static/media/roboto-greek-ext-500-normal.1964239c2800b6bd7e39.woff +0 -0
  63. package/frontend/build/static/media/roboto-greek-ext-500-normal.bef9c15c7164d6435aad.woff2 +0 -0
  64. package/frontend/build/static/media/roboto-greek-ext-700-normal.1aff9f4cd71608489b9a.woff +0 -0
  65. package/frontend/build/static/media/roboto-greek-ext-700-normal.eb28a447335ba6d54fcb.woff2 +0 -0
  66. package/frontend/build/static/media/roboto-latin-300-normal.cb14f8e80cc69ddbac34.woff +0 -0
  67. package/frontend/build/static/media/roboto-latin-300-normal.db56943a88e4852343ae.woff2 +0 -0
  68. package/frontend/build/static/media/roboto-latin-400-normal.50a0a61e29c19a2f05cb.woff +0 -0
  69. package/frontend/build/static/media/roboto-latin-400-normal.df1be0be92f6f19b8115.woff2 +0 -0
  70. package/frontend/build/static/media/roboto-latin-500-normal.599f66a60bdf974e578e.woff2 +0 -0
  71. package/frontend/build/static/media/roboto-latin-500-normal.c320def131b39bceabd8.woff +0 -0
  72. package/frontend/build/static/media/roboto-latin-700-normal.bcfbe8accc968a375a8e.woff +0 -0
  73. package/frontend/build/static/media/roboto-latin-700-normal.c4d6cab43bec89049809.woff2 +0 -0
  74. package/frontend/build/static/media/roboto-latin-ext-300-normal.6ddd1cfdbc5e74bcdab8.woff +0 -0
  75. package/frontend/build/static/media/roboto-latin-ext-300-normal.948c05192b1e64d931b1.woff2 +0 -0
  76. package/frontend/build/static/media/roboto-latin-ext-400-normal.0f86a30ca7e981fcfc99.woff2 +0 -0
  77. package/frontend/build/static/media/roboto-latin-ext-400-normal.2bfbba2d51a85c8702dd.woff +0 -0
  78. package/frontend/build/static/media/roboto-latin-ext-500-normal.8f02573e78730021ef49.woff2 +0 -0
  79. package/frontend/build/static/media/roboto-latin-ext-500-normal.aecaab4c4da2bf91377a.woff +0 -0
  80. package/frontend/build/static/media/roboto-latin-ext-700-normal.2d3c3ba6fe2d9c1026a5.woff +0 -0
  81. package/frontend/build/static/media/roboto-latin-ext-700-normal.8e656eff240311c6050a.woff2 +0 -0
  82. package/frontend/build/static/media/roboto-math-300-normal.90364ecfad5101ceb1a0.woff +0 -0
  83. package/frontend/build/static/media/roboto-math-300-normal.acc9c7c1d1fe3a1c7d44.woff2 +0 -0
  84. package/frontend/build/static/media/roboto-math-400-normal.3d3a272e5233c5fb1969.woff +0 -0
  85. package/frontend/build/static/media/roboto-math-400-normal.b60d9fba1e21da7497e6.woff2 +0 -0
  86. package/frontend/build/static/media/roboto-math-500-normal.41db483cb764343fca71.woff2 +0 -0
  87. package/frontend/build/static/media/roboto-math-500-normal.c3014a611cd9d8fa6252.woff +0 -0
  88. package/frontend/build/static/media/roboto-math-700-normal.a6fde3ddcb1629fd58b7.woff +0 -0
  89. package/frontend/build/static/media/roboto-math-700-normal.f6f4b54add6ab9d60a0f.woff2 +0 -0
  90. package/frontend/build/static/media/roboto-symbols-300-normal.52cdf8344b378f0c4580.woff +0 -0
  91. package/frontend/build/static/media/roboto-symbols-300-normal.616638ec44336b3da884.woff2 +0 -0
  92. package/frontend/build/static/media/roboto-symbols-400-normal.bb5b5d1459beb07bd3d5.woff2 +0 -0
  93. package/frontend/build/static/media/roboto-symbols-400-normal.f4f7e3bd8264f1a640cb.woff +0 -0
  94. package/frontend/build/static/media/roboto-symbols-500-normal.09b674875029289fd9a7.woff +0 -0
  95. package/frontend/build/static/media/roboto-symbols-500-normal.a5457b0ec984fd4cc8da.woff2 +0 -0
  96. package/frontend/build/static/media/roboto-symbols-700-normal.017e476ef02f62144169.woff +0 -0
  97. package/frontend/build/static/media/roboto-symbols-700-normal.634070e045ac99822c21.woff2 +0 -0
  98. package/frontend/build/static/media/roboto-vietnamese-300-normal.53f399e4522b647bafa7.woff +0 -0
  99. package/frontend/build/static/media/roboto-vietnamese-300-normal.6f0bf63e956c09377ef8.woff2 +0 -0
  100. package/frontend/build/static/media/roboto-vietnamese-400-normal.1cffe58e71a9109191a2.woff +0 -0
  101. package/frontend/build/static/media/roboto-vietnamese-400-normal.b1b8baa94fbcaa57d098.woff2 +0 -0
  102. package/frontend/build/static/media/roboto-vietnamese-500-normal.148734d63bd96c6e964f.woff2 +0 -0
  103. package/frontend/build/static/media/roboto-vietnamese-500-normal.72dbf2a25dd55b80b137.woff +0 -0
  104. package/frontend/build/static/media/roboto-vietnamese-700-normal.44a103f706f3ffe6a041.woff2 +0 -0
  105. package/frontend/build/static/media/roboto-vietnamese-700-normal.fa58a041a3336692af1e.woff +0 -0
@@ -0,0 +1,25 @@
1
+ export var WsBroadcastMessageId;
2
+ (function (WsBroadcastMessageId) {
3
+ WsBroadcastMessageId[WsBroadcastMessageId["Log"] = 0] = "Log";
4
+ WsBroadcastMessageId[WsBroadcastMessageId["RefreshRequired"] = 1] = "RefreshRequired";
5
+ WsBroadcastMessageId[WsBroadcastMessageId["RestartRequired"] = 2] = "RestartRequired";
6
+ WsBroadcastMessageId[WsBroadcastMessageId["RestartNotRequired"] = 3] = "RestartNotRequired";
7
+ WsBroadcastMessageId[WsBroadcastMessageId["CpuUpdate"] = 4] = "CpuUpdate";
8
+ WsBroadcastMessageId[WsBroadcastMessageId["MemoryUpdate"] = 5] = "MemoryUpdate";
9
+ WsBroadcastMessageId[WsBroadcastMessageId["UptimeUpdate"] = 6] = "UptimeUpdate";
10
+ WsBroadcastMessageId[WsBroadcastMessageId["Snackbar"] = 7] = "Snackbar";
11
+ WsBroadcastMessageId[WsBroadcastMessageId["UpdateRequired"] = 8] = "UpdateRequired";
12
+ WsBroadcastMessageId[WsBroadcastMessageId["StateUpdate"] = 9] = "StateUpdate";
13
+ WsBroadcastMessageId[WsBroadcastMessageId["CloseSnackbar"] = 10] = "CloseSnackbar";
14
+ WsBroadcastMessageId[WsBroadcastMessageId["ShellySysUpdate"] = 100] = "ShellySysUpdate";
15
+ WsBroadcastMessageId[WsBroadcastMessageId["ShellyMainUpdate"] = 101] = "ShellyMainUpdate";
16
+ })(WsBroadcastMessageId || (WsBroadcastMessageId = {}));
17
+ export function isBroadcast(msg) {
18
+ return msg.id >= 0 && msg.id <= 101;
19
+ }
20
+ export function isApiRequest(msg) {
21
+ return msg.id > 101 && msg.src === 'Frontend' && msg.dst === 'Matterbridge' && !('success' in msg) && !('error' in msg);
22
+ }
23
+ export function isApiResponse(msg) {
24
+ return msg.id > 101 && msg.src === 'Matterbridge' && msg.dst === 'Frontend' && ('success' in msg || 'error' in msg);
25
+ }
@@ -6,7 +6,7 @@ import { inspect } from 'node:util';
6
6
  import { AnsiLogger, UNDERLINE, UNDERLINEOFF, db, debugStringify, BRIGHT, RESET, er, nf, rs, wr, RED, GREEN, zb, CYAN, nt, BLUE } from 'node-ansi-logger';
7
7
  import { NodeStorageManager } from 'node-persist-manager';
8
8
  import { DeviceTypeId, Endpoint, Logger, LogLevel as MatterLogLevel, LogFormat as MatterLogFormat, VendorId, StorageService, Environment, ServerNode, UINT32_MAX, UINT16_MAX, Crypto, } from '@matter/main';
9
- import { DeviceCommissioner, FabricAction, MdnsService, PaseClient } from '@matter/main/protocol';
9
+ import { FabricAction, MdnsService, PaseClient } from '@matter/main/protocol';
10
10
  import { AggregatorEndpoint } from '@matter/main/endpoints';
11
11
  import { BasicInformationServer } from '@matter/main/behaviors/basic-information';
12
12
  import { BridgedDeviceBasicInformationServer } from '@matter/main/behaviors/bridged-device-basic-information';
@@ -173,7 +173,7 @@ export class Matterbridge extends EventEmitter {
173
173
  callbackLogLevel = "info";
174
174
  if (this.matterbridgeInformation.loggerLevel === "debug" || this.matterbridgeInformation.matterLoggerLevel === MatterLogLevel.DEBUG)
175
175
  callbackLogLevel = "debug";
176
- AnsiLogger.setGlobalCallback(this.frontend.wssSendMessage.bind(this.frontend), callbackLogLevel);
176
+ AnsiLogger.setGlobalCallback(this.frontend.wssSendLogMessage.bind(this.frontend), callbackLogLevel);
177
177
  this.log.debug(`WebSocketServer logger global callback set to ${callbackLogLevel}`);
178
178
  }
179
179
  static async loadInstance(initialize = false) {
@@ -768,7 +768,6 @@ export class Matterbridge extends EventEmitter {
768
768
  plugin.started = false;
769
769
  plugin.configured = false;
770
770
  plugin.registeredDevices = undefined;
771
- plugin.addedDevices = undefined;
772
771
  this.plugins.load(plugin, true, 'Matterbridge is starting');
773
772
  }
774
773
  this.frontend.wssSendRefreshRequired('plugins');
@@ -976,10 +975,8 @@ export class Matterbridge extends EventEmitter {
976
975
  if (plugin.error || !plugin.enabled)
977
976
  continue;
978
977
  const registeredDevices = plugin.registeredDevices;
979
- const addedDevices = plugin.addedDevices;
980
978
  await this.plugins.shutdown(plugin, 'unregistering all devices and shutting down...', false, true);
981
979
  plugin.registeredDevices = registeredDevices;
982
- plugin.addedDevices = addedDevices;
983
980
  await this.removeAllBridgedEndpoints(plugin.name, 100);
984
981
  }
985
982
  this.log.debug('Waiting for the MessageExchange to finish...');
@@ -1085,12 +1082,6 @@ export class Matterbridge extends EventEmitter {
1085
1082
  }
1086
1083
  await this.stopMatterStorage();
1087
1084
  await this.frontend.stop();
1088
- try {
1089
- Logger.removeLogger('matterfilelogger');
1090
- }
1091
- catch (error) {
1092
- this.log.debug(`Error removing the matterfilelogger for file ${CYAN}${path.join(this.matterbridgeDirectory, this.matterLoggerFile)}${db}: ${error instanceof Error ? error.message : String(error)}`);
1093
- }
1094
1085
  if (this.nodeStorage && this.nodeContext) {
1095
1086
  this.log.debug(`Closing node storage context for ${plg}Matterbridge${db}...`);
1096
1087
  await this.nodeContext.close();
@@ -1182,7 +1173,6 @@ export class Matterbridge extends EventEmitter {
1182
1173
  plugin.device = device;
1183
1174
  plugin.storageContext = await this.createServerNodeContext(plugin.name, device.deviceName, DeviceTypeId(device.deviceType), device.vendorId, device.vendorName, device.productId, device.productName);
1184
1175
  plugin.serverNode = await this.createServerNode(plugin.storageContext, this.port ? this.port++ : undefined, this.passcode ? this.passcode++ : undefined, this.discriminator ? this.discriminator++ : undefined);
1185
- plugin.serialNumber = await plugin.storageContext.get('serialNumber', '');
1186
1176
  this.log.debug(`Adding ${plg}${plugin.name}${db}:${dev}${device.deviceName}${db} to ${plg}${plugin.name}${db} server node`);
1187
1177
  await plugin.serverNode.add(device);
1188
1178
  }
@@ -1193,7 +1183,6 @@ export class Matterbridge extends EventEmitter {
1193
1183
  plugin.storageContext = await this.createServerNodeContext(plugin.name, 'Matterbridge', this.aggregatorDeviceType, this.aggregatorVendorId, this.aggregatorVendorName, this.aggregatorProductId, plugin.description);
1194
1184
  plugin.serverNode = await this.createServerNode(plugin.storageContext, this.port ? this.port++ : undefined, this.passcode ? this.passcode++ : undefined, this.discriminator ? this.discriminator++ : undefined);
1195
1185
  plugin.aggregatorNode = await this.createAggregatorNode(plugin.storageContext);
1196
- plugin.serialNumber = await plugin.storageContext.get('serialNumber', '');
1197
1186
  await plugin.serverNode.add(plugin.aggregatorNode);
1198
1187
  }
1199
1188
  }
@@ -1332,8 +1321,8 @@ export class Matterbridge extends EventEmitter {
1332
1321
  for (const plugin of this.plugins.array()) {
1333
1322
  if (!plugin.enabled || plugin.error)
1334
1323
  continue;
1335
- if (plugin.type !== 'DynamicPlatform' && (!plugin.addedDevices || plugin.addedDevices === 0)) {
1336
- this.log.error(`Plugin ${plg}${plugin.name}${er} didn't add any devices to Matterbridge. Verify the plugin configuration.`);
1324
+ if (plugin.type !== 'DynamicPlatform' && (!plugin.registeredDevices || plugin.registeredDevices === 0)) {
1325
+ this.log.error(`Plugin ${plg}${plugin.name}${er} didn't register any devices to Matterbridge. Verify the plugin configuration.`);
1337
1326
  continue;
1338
1327
  }
1339
1328
  if (!plugin.serverNode) {
@@ -1607,22 +1596,6 @@ export class Matterbridge extends EventEmitter {
1607
1596
  this.log.error(`Failed to close ${matterServerNode.id} server node: ${error instanceof Error ? error.message : error}`);
1608
1597
  }
1609
1598
  }
1610
- async advertiseServerNode(matterServerNode) {
1611
- if (matterServerNode) {
1612
- await matterServerNode.env.get(DeviceCommissioner)?.allowBasicCommissioning();
1613
- const { qrPairingCode, manualPairingCode } = matterServerNode.state.commissioning.pairingCodes;
1614
- this.advertisingNodes.set(matterServerNode.id, Date.now());
1615
- this.log.notice(`Started advertising for ${matterServerNode.id} with the following pairing codes: qrPairingCode ${qrPairingCode}, manualPairingCode ${manualPairingCode}`);
1616
- return { qrPairingCode, manualPairingCode };
1617
- }
1618
- }
1619
- async stopAdvertiseServerNode(matterServerNode) {
1620
- if (matterServerNode && matterServerNode.lifecycle.isOnline) {
1621
- await matterServerNode.env.get(DeviceCommissioner)?.endCommissioning();
1622
- this.advertisingNodes.delete(matterServerNode.id);
1623
- this.log.notice(`Stopped advertising for ${matterServerNode.id}`);
1624
- }
1625
- }
1626
1599
  async createAggregatorNode(storageContext) {
1627
1600
  this.log.notice(`Creating ${await storageContext.get('storeId')} aggregator...`);
1628
1601
  const aggregatorNode = new Endpoint(AggregatorEndpoint, { id: `${await storageContext.get('storeId')}` });
@@ -1729,11 +1702,9 @@ export class Matterbridge extends EventEmitter {
1729
1702
  }
1730
1703
  if (plugin.registeredDevices !== undefined)
1731
1704
  plugin.registeredDevices++;
1732
- if (plugin.addedDevices !== undefined)
1733
- plugin.addedDevices++;
1734
1705
  this.devices.set(device);
1735
1706
  await this.subscribeAttributeChanged(plugin, device);
1736
- this.log.info(`Added and registered bridged endpoint (${plugin.registeredDevices}/${plugin.addedDevices}) ${dev}${device.deviceName}${nf} (${dev}${device.id}${nf}) for plugin ${plg}${pluginName}${nf}`);
1707
+ this.log.info(`Added and registered bridged endpoint (${plugin.registeredDevices}) ${dev}${device.deviceName}${nf} (${dev}${device.id}${nf}) for plugin ${plg}${pluginName}${nf}`);
1737
1708
  }
1738
1709
  async removeBridgedEndpoint(pluginName, device) {
1739
1710
  this.log.debug(`Removing bridged endpoint ${plg}${pluginName}${db}:${dev}${device.deviceName}${db} (${zb}${device.name}${db}) for plugin ${plg}${pluginName}${db}`);
@@ -1748,11 +1719,9 @@ export class Matterbridge extends EventEmitter {
1748
1719
  return;
1749
1720
  }
1750
1721
  await device.delete();
1751
- this.log.info(`Removed bridged endpoint(${plugin.registeredDevices}/${plugin.addedDevices}) ${dev}${device.deviceName}${nf} (${zb}${device.name}${nf}) for plugin ${plg}${pluginName}${nf}`);
1722
+ this.log.info(`Removed bridged endpoint(${plugin.registeredDevices}) ${dev}${device.deviceName}${nf} (${zb}${device.name}${nf}) for plugin ${plg}${pluginName}${nf}`);
1752
1723
  if (plugin.registeredDevices !== undefined)
1753
1724
  plugin.registeredDevices--;
1754
- if (plugin.addedDevices !== undefined)
1755
- plugin.addedDevices--;
1756
1725
  }
1757
1726
  else if (this.bridgeMode === 'childbridge') {
1758
1727
  if (plugin.type === 'AccessoryPlatform') {
@@ -1764,11 +1733,9 @@ export class Matterbridge extends EventEmitter {
1764
1733
  }
1765
1734
  await device.delete();
1766
1735
  }
1767
- this.log.info(`Removed bridged endpoint(${plugin.registeredDevices}/${plugin.addedDevices}) ${dev}${device.deviceName}${nf} (${zb}${device.name}${nf}) for plugin ${plg}${pluginName}${nf}`);
1736
+ this.log.info(`Removed bridged endpoint(${plugin.registeredDevices}) ${dev}${device.deviceName}${nf} (${zb}${device.name}${nf}) for plugin ${plg}${pluginName}${nf}`);
1768
1737
  if (plugin.registeredDevices !== undefined)
1769
1738
  plugin.registeredDevices--;
1770
- if (plugin.addedDevices !== undefined)
1771
- plugin.addedDevices--;
1772
1739
  }
1773
1740
  this.devices.remove(device);
1774
1741
  }
@@ -1783,6 +1750,8 @@ export class Matterbridge extends EventEmitter {
1783
1750
  await wait(2000);
1784
1751
  }
1785
1752
  async subscribeAttributeChanged(plugin, device) {
1753
+ if (!plugin || !device || !device.plugin || !device.serialNumber || !device.uniqueId)
1754
+ return;
1786
1755
  this.log.info(`Subscribing attributes for endpoint ${dev}${device.deviceName}${nf} (${dev}${device.id}${nf}) plugin ${plg}${plugin.name}${nf}`);
1787
1756
  if (this.bridgeMode === 'childbridge' && plugin.type === 'AccessoryPlatform' && plugin.serverNode) {
1788
1757
  plugin.serverNode.eventsOf(BasicInformationServer).reachable$Changed?.on((reachable) => {
@@ -484,7 +484,6 @@ export class PluginManager extends EventEmitter {
484
484
  plugin.platform = platform;
485
485
  plugin.loaded = true;
486
486
  plugin.registeredDevices = 0;
487
- plugin.addedDevices = 0;
488
487
  await this.saveToStorage();
489
488
  this.log.notice(`Loaded plugin ${plg}${plugin.name}${nt} type ${typ}${platform.type}${nt} (entrypoint ${UNDERLINE}${pluginEntry}${UNDERLINEOFF})`);
490
489
  this.emit('loaded', plugin.name);
@@ -599,7 +598,6 @@ export class PluginManager extends EventEmitter {
599
598
  await this.matterbridge.removeAllBridgedEndpoints(plugin.name);
600
599
  }
601
600
  plugin.registeredDevices = undefined;
602
- plugin.addedDevices = undefined;
603
601
  this.log.notice(`Shutdown of plugin ${plg}${plugin.name}${nt} completed`);
604
602
  this.emit('shutdown', plugin.name);
605
603
  return plugin;
package/dist/shelly.js CHANGED
@@ -1,5 +1,4 @@
1
1
  import { debugStringify } from 'node-ansi-logger';
2
- import { WS_ID_SHELLY_MAIN_UPDATE, WS_ID_SHELLY_SYS_UPDATE } from './frontend.js';
3
2
  let verifyIntervalSecs = 15;
4
3
  let verifyTimeoutSecs = 600;
5
4
  export function setVerifyIntervalSecs(seconds) {
@@ -14,7 +13,7 @@ export async function getShellySysUpdate(matterbridge) {
14
13
  if (updates.length === 0)
15
14
  return;
16
15
  matterbridge.matterbridgeInformation.shellySysUpdate = true;
17
- matterbridge.frontend.wssBroadcastMessage(WS_ID_SHELLY_SYS_UPDATE, 'shelly-sys-update', { available: true });
16
+ matterbridge.frontend.wssBroadcastMessage({ id: 100, src: 'Matterbridge', dst: 'Frontend', method: 'shelly_sys_update', params: { available: true } });
18
17
  for (const { name } of updates) {
19
18
  if (!name)
20
19
  continue;
@@ -32,7 +31,7 @@ export async function triggerShellySysUpdate(matterbridge) {
32
31
  matterbridge.log.notice('Installing Shelly system update...');
33
32
  matterbridge.matterbridgeInformation.shellySysUpdate = false;
34
33
  matterbridge.frontend.wssSendSnackbarMessage('Installing Shelly system update...', 15);
35
- matterbridge.frontend.wssBroadcastMessage(WS_ID_SHELLY_SYS_UPDATE, 'shelly-sys-update', { available: false });
34
+ matterbridge.frontend.wssBroadcastMessage({ id: 100, src: 'Matterbridge', dst: 'Frontend', method: 'shelly_sys_update', params: { available: false } });
36
35
  await verifyShellyUpdate(matterbridge, '/api/updates/sys/status', 'Shelly system update');
37
36
  }
38
37
  catch (err) {
@@ -45,7 +44,7 @@ export async function getShellyMainUpdate(matterbridge) {
45
44
  if (updates.length === 0)
46
45
  return;
47
46
  matterbridge.matterbridgeInformation.shellyMainUpdate = true;
48
- matterbridge.frontend.wssBroadcastMessage(WS_ID_SHELLY_MAIN_UPDATE, 'shelly-main-update', { available: true });
47
+ matterbridge.frontend.wssBroadcastMessage({ id: 101, src: 'Matterbridge', dst: 'Frontend', method: 'shelly_main_update', params: { available: true } });
49
48
  for (const { name } of updates) {
50
49
  if (!name)
51
50
  continue;
@@ -63,7 +62,7 @@ export async function triggerShellyMainUpdate(matterbridge) {
63
62
  matterbridge.log.notice('Installing Shelly software update...');
64
63
  matterbridge.matterbridgeInformation.shellyMainUpdate = false;
65
64
  matterbridge.frontend.wssSendSnackbarMessage('Installing Shelly software update...', 15);
66
- matterbridge.frontend.wssBroadcastMessage(WS_ID_SHELLY_MAIN_UPDATE, 'shelly-main-update', { available: false });
65
+ matterbridge.frontend.wssBroadcastMessage({ id: 101, src: 'Matterbridge', dst: 'Frontend', method: 'shelly_main_update', params: { available: false } });
67
66
  await verifyShellyUpdate(matterbridge, '/api/updates/main/status', 'Shelly software update');
68
67
  }
69
68
  catch (err) {
@@ -21,7 +21,7 @@ export async function spawnCommand(matterbridge, command, args) {
21
21
  reject(err);
22
22
  });
23
23
  childProcess.on('close', (code, signal) => {
24
- matterbridge.frontend.wssSendMessage('spawn', matterbridge.log.now(), 'Matterbridge:spawn', `child process closed with code ${code} and signal ${signal}`);
24
+ matterbridge.frontend.wssSendLogMessage('spawn', matterbridge.log.now(), 'Matterbridge:spawn', `child process closed with code ${code} and signal ${signal}`);
25
25
  if (code === 0) {
26
26
  if (cmdLine.startsWith('npm install -g'))
27
27
  matterbridge.log.notice(`Package ${cmdLine.replace('npm install -g ', '').replace('--verbose', '').replace('--omit=dev', '')} installed correctly`);
@@ -34,7 +34,7 @@ export async function spawnCommand(matterbridge, command, args) {
34
34
  }
35
35
  });
36
36
  childProcess.on('exit', (code, signal) => {
37
- matterbridge.frontend.wssSendMessage('spawn', matterbridge.log.now(), 'Matterbridge:spawn', `child process exited with code ${code} and signal ${signal}`);
37
+ matterbridge.frontend.wssSendLogMessage('spawn', matterbridge.log.now(), 'Matterbridge:spawn', `child process exited with code ${code} and signal ${signal}`);
38
38
  if (code === 0) {
39
39
  matterbridge.log.debug(`Child process "${cmdLine}" exited with code ${code} and signal ${signal}`);
40
40
  resolve(true);
@@ -52,14 +52,14 @@ export async function spawnCommand(matterbridge, command, args) {
52
52
  childProcess.stdout.on('data', (data) => {
53
53
  const message = data.toString().trim();
54
54
  matterbridge.log.debug(`Spawn output (stdout): ${message}`);
55
- matterbridge.frontend.wssSendMessage('spawn', matterbridge.log.now(), 'Matterbridge:spawn', message);
55
+ matterbridge.frontend.wssSendLogMessage('spawn', matterbridge.log.now(), 'Matterbridge:spawn', message);
56
56
  });
57
57
  }
58
58
  if (childProcess.stderr) {
59
59
  childProcess.stderr.on('data', (data) => {
60
60
  const message = data.toString().trim();
61
61
  matterbridge.log.debug(`Spawn verbose (stderr): ${message}`);
62
- matterbridge.frontend.wssSendMessage('spawn', matterbridge.log.now(), 'Matterbridge:spawn', message);
62
+ matterbridge.frontend.wssSendLogMessage('spawn', matterbridge.log.now(), 'Matterbridge:spawn', message);
63
63
  });
64
64
  }
65
65
  });
@@ -0,0 +1 @@
1
+ body{font-family:Roboto,sans-serif}[frontend-theme=classic]{--main-bg-color: #c4c2c2;--main-text-color: black;--main-grey-color: #616161;--main-light-color: #959595;--main-icon-color: #4d4d4d;--main-log-color: var(--main-text-color);--main-button-color: #ffffff;--main-button-bg-color: var(--primary-color);--main-menu-color: #26292d;--main-menu-bg-color: #e2e2e2;--main-menu-hover-color: #959595;--main-label-color: var(--main-grey-color);--primary-color: #009a00;--secondary-color: #92771f;--header-bg-color: var(--primary-color);--header-text-color: white;--footer-bg-color: var(--div-bg-color);--footer-text-color: var(--div-text-color);--ttip-bg-color: #555;--ttip-text-color: #fff;--table-border-color: #ddd;--table-text-color: black;--table-even-bg-color: #bdbdbd;--table-odd-bg-color: var(--div-bg-color);--table-hover-bg-color: #5f8c9e;--table-selected-bg-color: #5f8c9e;--div-bg-color: #adadad;--div-text-color: black;--div-shadow-color: #888;--div-border-color: rgb(139, 139, 139);--div-border-radius: 0px;--div-title-bg-color: var(--div-bg-color);--div-title-text-color: black;background-color:var(--main-bg-color);color:var(--main-text-color);font-family:Roboto,Helvetica,Arial,sans-serif}[frontend-theme=dark]{--main-bg-color: #26292d;--main-text-color: #ffffff;--main-grey-color: #616161;--main-light-color: #959595;--main-icon-color: var(--main-light-color);--main-log-color: var(--main-light-color);--main-button-color: #ffffff;--main-button-bg-color: var(--primary-color);--main-menu-color: var(--main-light-color);--main-menu-bg-color: var(--main-bg-color);--main-menu-hover-color: var(--div-bg-color);--main-label-color: var(--main-grey-color);--primary-color: #1976d2;--secondary-color: #a58827;--header-bg-color: var(--div-bg-color);--header-text-color: var(--primary-color);--footer-bg-color: var(--div-bg-color);--footer-text-color: var(--div-text-color);--ttip-bg-color: #555;--ttip-text-color: #fff;--table-border-color: var(--div-bg-color);--table-text-color: var(--main-light-color);--table-even-bg-color: var(--div-bg-color);--table-odd-bg-color: var(--div-bg-color);--table-hover-bg-color: var(--main-bg-color);--table-selected-bg-color: var(--main-bg-color);--div-bg-color: #1b1d21;--div-text-color: var(--main-light-color);--div-shadow-color: #34373d;--div-border-color: #1b1d21;--div-border-radius: 5px;--div-title-bg-color: #1b1d21;--div-title-text-color: var(--primary-color);background-color:var(--main-bg-color);color:var(--main-text-color);font-family:Roboto,Helvetica,Arial,sans-serif}[frontend-theme=light]{--main-bg-color: #f0f0f0;--main-text-color: #212121;--main-grey-color: #616161;--main-light-color: #363636;--main-icon-color: #7a7a7a;--main-log-color: var(--main-light-color);--main-button-color: #ffffff;--main-button-bg-color: var(--primary-color);--main-menu-color: var(--main-text-color);--main-menu-bg-color: var(--div-bg-color);--main-menu-hover-color: #85c0d8;--main-label-color: var(--main-grey-color);--primary-color: #2196f3;--secondary-color: #a58827;--header-bg-color: var(--div-bg-color);--header-text-color: var(--div-text-color);--footer-bg-color: var(--div-bg-color);--footer-text-color: var(--div-text-color);--ttip-bg-color: #555;--ttip-text-color: #fff;--table-border-color: var(--div-bg-color);--table-text-color: var(--main-light-color);--table-even-bg-color: var(--div-bg-color);--table-odd-bg-color: var(--div-bg-color);--table-hover-bg-color: #85c0d8;--table-selected-bg-color: #85c0d8;--div-bg-color: #ffffff;--div-text-color: #212121;--div-shadow-color: #bfbfbf;--div-border-color: var(--div-bg-color);--div-border-radius: 5px;--div-title-bg-color: var(--div-bg-color);--div-title-text-color: var(--div-text-color);background-color:var(--main-bg-color);color:var(--main-text-color);font-family:Roboto,Helvetica,Arial,sans-serif}::-webkit-scrollbar{width:10px}::-webkit-scrollbar-thumb{background:var(--primary-color);border-radius:5px}::-webkit-scrollbar-thumb:hover{background:var(--primary-color);border-radius:5px}::-webkit-scrollbar-track{background:"inherit"}html{scrollbar-color:var(--primary-color) var(--div-bg-color);scrollbar-width:thin}.thin-scroll{scrollbar-width:thin;scrollbar-color:var(--primary-color) var(--div-bg-color)}.thin-scroll::-webkit-scrollbar{width:5px;height:5px}.thin-scroll::-webkit-scrollbar-thumb{background:var(--primary-color);border-radius:5px}.tooltip-container{position:relative;display:inline-block;z-index:10}.tooltip-text{visibility:hidden;background-color:var(--ttip-bg-color);color:var(--ttip-text-color);text-align:center;padding:5px;border-radius:6px;position:absolute;z-index:10;bottom:calc(100% + 10px);left:50%;margin-left:-60px;opacity:0;transition:opacity .3s;font-size:12px}.tooltip-container:hover{cursor:pointer;z-index:10}.tooltip-container:hover .tooltip-text{visibility:visible;opacity:1;z-index:10}.status-enabled{background-color:green;color:#fff;padding:.2rem;border-radius:.25rem;text-align:center;font-size:12px;cursor:pointer;box-shadow:2px 2px 2px #0003}.status-disabled{background-color:red;color:#fff;padding:.2rem;border-radius:.25rem;text-align:center;font-size:12px;cursor:pointer;box-shadow:2px 2px 2px #0003}.status-information{background-color:#9e9e9e;color:#fff;padding:2px 10px;border-radius:.25rem;text-align:center;font-size:12px;cursor:pointer;box-shadow:2px 2px 2px #0003}.status-warning{background-color:#e9db18;color:#000;padding:2px 10px;border-radius:.25rem;text-align:center;font-size:12px;cursor:pointer;box-shadow:2px 2px 2px #0003}.status-sponsor{background-color:#b6409c;color:#fff;padding:2px 10px;border-radius:.25rem;text-align:center;font-size:12px;cursor:pointer;box-shadow:2px 2px 2px #0003}.status-blue{background-color:#5f8c9e;color:#fff;padding:.2rem;border-radius:.25rem;text-align:center;font-size:12px;cursor:pointer;box-shadow:2px 2px 2px #0003}.header{display:flex;flex-direction:row;align-items:center;justify-content:space-between;gap:20px;margin:0;padding:0;height:40px}.sub-header{flex:0 0 auto;display:flex;flex-direction:row;align-items:center;gap:20px;margin:0;padding:0;height:40px}nav{display:flex;align-items:center}.nav-link{margin:0 10px;font-size:20px;text-decoration:none;color:var(--main-icon-color);transition:color .3s ease}.nav-link:hover{color:var(--primary-color)}table{border-collapse:collapse;width:100%;table-layout:auto}thead{position:sticky;top:0;border:1px solid var(--table-border-color);z-index:10}thead th{border:1px solid var(--table-border-color);padding:5px 10px;color:var(--header-text-color);background:var(--header-bg-color);text-align:left;z-index:10}tbody td{border:1px solid var(--table-border-color);margin:0;padding:5px 10px;text-align:left;font-size:14px}tbody tr:hover{color:var(--table-text-color);background-color:var(--table-hover-bg-color)}.table-content-even{color:var(--table-text-color);background-color:var(--table-even-bg-color)}.table-content-odd{color:var(--table-text-color);background-color:var(--table-odd-bg-color)}.table-content-selected{color:var(--table-text-color);background-color:var(--table-selected-bg-color)}h3{margin:0}.MbfScreen{display:flex;flex-direction:column;width:calc(100vw - 40px);height:calc(100vh - 40px);gap:20px;margin:0;padding:20px;background-color:var(--main-bg-color)}.MbfPageDiv{display:flex;flex-direction:column;height:calc(100% - 60px);width:100%;margin:0;padding:0;gap:20px}.MbfWindowDiv{display:flex;flex-direction:column;box-shadow:5px 5px 10px var(--div-shadow-color);border:1px solid var(--table-border-color);border-radius:var(--div-border-radius);box-sizing:border-box;background-color:var(--div-bg-color)}.MbfWindowDivTable{display:flex;flex-direction:column;flex:1 1 auto;margin:-1px;padding:0;gap:0;overflow:auto;display:block}.MbfWindowHeaderFooterIcons{display:flex;flex-direction:row;margin:0;padding:0 10px;gap:10px}.MbfWindowHeader{display:flex;flex-direction:row;align-items:center;width:100%;border-bottom:1px solid var(--table-border-color);color:var(--header-text-color);background-color:var(--header-bg-color);margin:0;padding:0;box-sizing:border-box}.MbfWindowHeaderText{color:var(--header-text-color);font-weight:700;margin:0;padding:5px 10px}.MbfWindowFooter{display:flex;flex-direction:row;align-items:center;justify-content:center;color:var(--footer-text-color);background-color:var(--footer-bg-color);margin:0;padding:0}.MbfWindowFooterText{color:var(--footer-text-color);background-color:var(--footer-bg-color);font-weight:700;text-align:center;margin:0;padding:5px 10px}.MbfWindowBody{display:flex;flex:1 1 auto;margin:0;padding:10px;gap:10px}.MbfWindowBodyColumn{display:flex;flex-direction:column;flex:1 1 auto;width:100%;margin:0;padding:10px 0;gap:0px;overflow:auto}.MbfWindowBodyRow{display:flex;flex-direction:row;flex:1 1 auto;height:100%;margin:0;padding:0 10px;gap:0px;overflow:auto}.configSubmitButton{display:flex;flex-direction:row;justify-content:center;width:auto;margin:20px}.configSubmitButton button{width:auto}@media (max-width: 1300px){.MbfScreen{width:1300px;height:1024px}.xxxheader{flex-direction:column;align-items:start;justify-content:start}.xxxsub-header{align-items:start;justify-content:start}}body{margin:0;font-family:-apple-system,BlinkMacSystemFont,Segoe UI,Roboto,Oxygen,Ubuntu,Cantarell,Fira Sans,Droid Sans,Helvetica Neue,sans-serif;-webkit-font-smoothing:antialiased;-moz-osx-font-smoothing:grayscale}code{font-family:source-code-pro,Menlo,Monaco,Consolas,Courier New,monospace}