matterbridge 2.1.2 → 2.1.3-dev.1

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 (111) hide show
  1. package/CHANGELOG.md +24 -10
  2. package/dist/cli.js +0 -26
  3. package/dist/cluster/export.js +0 -2
  4. package/dist/defaultConfigSchema.js +0 -23
  5. package/dist/deviceManager.js +1 -94
  6. package/dist/frontend.js +23 -231
  7. package/dist/index.js +0 -28
  8. package/dist/logger/export.js +0 -1
  9. package/dist/matter/behaviors.js +0 -2
  10. package/dist/matter/clusters.js +0 -2
  11. package/dist/matter/devices.js +0 -2
  12. package/dist/matter/endpoints.js +0 -2
  13. package/dist/matter/export.js +0 -2
  14. package/dist/matter/types.js +0 -2
  15. package/dist/matterbridge.js +57 -741
  16. package/dist/matterbridgeAccessoryPlatform.js +0 -33
  17. package/dist/matterbridgeBehaviors.js +1 -32
  18. package/dist/matterbridgeDeviceTypes.js +11 -112
  19. package/dist/matterbridgeDynamicPlatform.js +0 -33
  20. package/dist/matterbridgeEndpoint.js +6 -690
  21. package/dist/matterbridgeEndpointHelpers.js +0 -96
  22. package/dist/matterbridgePlatform.js +3 -111
  23. package/dist/matterbridgeTypes.js +0 -24
  24. package/dist/pluginManager.js +3 -230
  25. package/dist/storage/export.js +0 -1
  26. package/dist/utils/colorUtils.js +2 -205
  27. package/dist/utils/export.js +0 -1
  28. package/dist/utils/utils.js +7 -251
  29. package/npm-shrinkwrap.json +2 -2
  30. package/package.json +1 -2
  31. package/dist/cli.d.ts +0 -25
  32. package/dist/cli.d.ts.map +0 -1
  33. package/dist/cli.js.map +0 -1
  34. package/dist/cluster/export.d.ts +0 -2
  35. package/dist/cluster/export.d.ts.map +0 -1
  36. package/dist/cluster/export.js.map +0 -1
  37. package/dist/defaultConfigSchema.d.ts +0 -27
  38. package/dist/defaultConfigSchema.d.ts.map +0 -1
  39. package/dist/defaultConfigSchema.js.map +0 -1
  40. package/dist/deviceManager.d.ts +0 -114
  41. package/dist/deviceManager.d.ts.map +0 -1
  42. package/dist/deviceManager.js.map +0 -1
  43. package/dist/frontend.d.ts +0 -110
  44. package/dist/frontend.d.ts.map +0 -1
  45. package/dist/frontend.js.map +0 -1
  46. package/dist/index.d.ts +0 -35
  47. package/dist/index.d.ts.map +0 -1
  48. package/dist/index.js.map +0 -1
  49. package/dist/logger/export.d.ts +0 -2
  50. package/dist/logger/export.d.ts.map +0 -1
  51. package/dist/logger/export.js.map +0 -1
  52. package/dist/matter/behaviors.d.ts +0 -2
  53. package/dist/matter/behaviors.d.ts.map +0 -1
  54. package/dist/matter/behaviors.js.map +0 -1
  55. package/dist/matter/clusters.d.ts +0 -2
  56. package/dist/matter/clusters.d.ts.map +0 -1
  57. package/dist/matter/clusters.js.map +0 -1
  58. package/dist/matter/devices.d.ts +0 -2
  59. package/dist/matter/devices.d.ts.map +0 -1
  60. package/dist/matter/devices.js.map +0 -1
  61. package/dist/matter/endpoints.d.ts +0 -2
  62. package/dist/matter/endpoints.d.ts.map +0 -1
  63. package/dist/matter/endpoints.js.map +0 -1
  64. package/dist/matter/export.d.ts +0 -5
  65. package/dist/matter/export.d.ts.map +0 -1
  66. package/dist/matter/export.js.map +0 -1
  67. package/dist/matter/types.d.ts +0 -3
  68. package/dist/matter/types.d.ts.map +0 -1
  69. package/dist/matter/types.js.map +0 -1
  70. package/dist/matterbridge.d.ts +0 -409
  71. package/dist/matterbridge.d.ts.map +0 -1
  72. package/dist/matterbridge.js.map +0 -1
  73. package/dist/matterbridgeAccessoryPlatform.d.ts +0 -39
  74. package/dist/matterbridgeAccessoryPlatform.d.ts.map +0 -1
  75. package/dist/matterbridgeAccessoryPlatform.js.map +0 -1
  76. package/dist/matterbridgeBehaviors.d.ts +0 -1056
  77. package/dist/matterbridgeBehaviors.d.ts.map +0 -1
  78. package/dist/matterbridgeBehaviors.js.map +0 -1
  79. package/dist/matterbridgeDeviceTypes.d.ts +0 -177
  80. package/dist/matterbridgeDeviceTypes.d.ts.map +0 -1
  81. package/dist/matterbridgeDeviceTypes.js.map +0 -1
  82. package/dist/matterbridgeDynamicPlatform.d.ts +0 -39
  83. package/dist/matterbridgeDynamicPlatform.d.ts.map +0 -1
  84. package/dist/matterbridgeDynamicPlatform.js.map +0 -1
  85. package/dist/matterbridgeEndpoint.d.ts +0 -834
  86. package/dist/matterbridgeEndpoint.d.ts.map +0 -1
  87. package/dist/matterbridgeEndpoint.js.map +0 -1
  88. package/dist/matterbridgeEndpointHelpers.d.ts +0 -2262
  89. package/dist/matterbridgeEndpointHelpers.d.ts.map +0 -1
  90. package/dist/matterbridgeEndpointHelpers.js.map +0 -1
  91. package/dist/matterbridgePlatform.d.ts +0 -152
  92. package/dist/matterbridgePlatform.d.ts.map +0 -1
  93. package/dist/matterbridgePlatform.js.map +0 -1
  94. package/dist/matterbridgeTypes.d.ts +0 -167
  95. package/dist/matterbridgeTypes.d.ts.map +0 -1
  96. package/dist/matterbridgeTypes.js.map +0 -1
  97. package/dist/pluginManager.d.ts +0 -236
  98. package/dist/pluginManager.d.ts.map +0 -1
  99. package/dist/pluginManager.js.map +0 -1
  100. package/dist/storage/export.d.ts +0 -2
  101. package/dist/storage/export.d.ts.map +0 -1
  102. package/dist/storage/export.js.map +0 -1
  103. package/dist/utils/colorUtils.d.ts +0 -61
  104. package/dist/utils/colorUtils.d.ts.map +0 -1
  105. package/dist/utils/colorUtils.js.map +0 -1
  106. package/dist/utils/export.d.ts +0 -3
  107. package/dist/utils/export.d.ts.map +0 -1
  108. package/dist/utils/export.js.map +0 -1
  109. package/dist/utils/utils.d.ts +0 -221
  110. package/dist/utils/utils.d.ts.map +0 -1
  111. package/dist/utils/utils.js.map +0 -1
package/dist/frontend.js CHANGED
@@ -1,28 +1,4 @@
1
- /**
2
- * This file contains the class Frontend.
3
- *
4
- * @file frontend.ts
5
- * @author Luca Liguori
6
- * @date 2025-01-13
7
- * @version 1.0.1
8
- *
9
- * Copyright 2025, 2026, 2027 Luca Liguori.
10
- *
11
- * Licensed under the Apache License, Version 2.0 (the "License");
12
- * you may not use this file except in compliance with the License.
13
- * You may obtain a copy of the License at
14
- *
15
- * http://www.apache.org/licenses/LICENSE-2.0
16
- *
17
- * Unless required by applicable law or agreed to in writing, software
18
- * distributed under the License is distributed on an "AS IS" BASIS,
19
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
20
- * See the License for the specific language governing permissions and
21
- * limitations under the License. *
22
- */
23
- // @matter
24
1
  import { EndpointServer, Logger, LogLevel as MatterLogLevel, LogFormat as MatterLogFormat } from '@matter/main';
25
- // Node modules
26
2
  import { createServer } from 'http';
27
3
  import https from 'https';
28
4
  import express from 'express';
@@ -30,32 +6,13 @@ import WebSocket, { WebSocketServer } from 'ws';
30
6
  import os from 'os';
31
7
  import path from 'path';
32
8
  import { promises as fs } from 'fs';
33
- // AnsiLogger module
34
9
  import { AnsiLogger, CYAN, db, debugStringify, er, nf, rs, stringify, UNDERLINE, UNDERLINEOFF, wr, YELLOW } from './logger/export.js';
35
- // Matterbridge
36
10
  import { createZip, getIntParameter, hasParameter, isValidNumber, isValidObject, isValidString } from './utils/utils.js';
37
11
  import { plg } from './matterbridgeTypes.js';
38
12
  import { MatterbridgeEndpoint } from './matterbridgeEndpoint.js';
39
- /**
40
- * Websocket message ID for logging.
41
- * @constant {number}
42
- */
43
13
  export const WS_ID_LOG = 0;
44
- /**
45
- * Websocket message ID indicating a refresh is needed.
46
- * @constant {number}
47
- */
48
14
  export const WS_ID_REFRESH_NEEDED = 1;
49
- /**
50
- * Websocket message ID indicating a restart is needed.
51
- * @constant {number}
52
- */
53
15
  export const WS_ID_RESTART_NEEDED = 2;
54
- /**
55
- * Initializes the frontend of Matterbridge.
56
- *
57
- * @param port The port number to run the frontend server on. Default is 8283.
58
- */
59
16
  export class Frontend {
60
17
  matterbridge;
61
18
  log;
@@ -71,7 +28,7 @@ export class Frontend {
71
28
  memoryTimeout;
72
29
  constructor(matterbridge) {
73
30
  this.matterbridge = matterbridge;
74
- this.log = new AnsiLogger({ logName: 'Frontend', logTimestampFormat: 4 /* TimestampFormat.TIME_MILLIS */, logLevel: hasParameter('debug') ? "debug" /* LogLevel.DEBUG */ : "info" /* LogLevel.INFO */ });
31
+ this.log = new AnsiLogger({ logName: 'Frontend', logTimestampFormat: 4, logLevel: hasParameter('debug') ? "debug" : "info" });
75
32
  }
76
33
  set logLevel(logLevel) {
77
34
  this.log.logLevel = logLevel;
@@ -79,21 +36,10 @@ export class Frontend {
79
36
  async start(port = 8283) {
80
37
  this.port = port;
81
38
  this.log.debug(`Initializing the frontend ${hasParameter('ssl') ? 'https' : 'http'} server on port ${YELLOW}${this.port}${db}`);
82
- // Create the express app that serves the frontend
83
39
  this.expressApp = express();
84
- // Log all requests to the server for debugging
85
- /*
86
- this.expressApp.use((req, res, next) => {
87
- this.log.debug(`Received request on expressApp: ${req.method} ${req.url}`);
88
- next();
89
- });
90
- */
91
- // Serve static files from '/static' endpoint
92
40
  this.expressApp.use(express.static(path.join(this.matterbridge.rootDirectory, 'frontend/build')));
93
41
  if (!hasParameter('ssl')) {
94
- // Create an HTTP server and attach the express app
95
42
  this.httpServer = createServer(this.expressApp);
96
- // Listen on the specified port
97
43
  if (hasParameter('ingress')) {
98
44
  this.httpServer.listen(this.port, '0.0.0.0', () => {
99
45
  this.log.info(`The frontend http server is listening on ${UNDERLINE}http://0.0.0.0:${this.port}${UNDERLINEOFF}${rs}`);
@@ -107,7 +53,6 @@ export class Frontend {
107
53
  this.log.info(`The frontend http server is listening on ${UNDERLINE}http://[${this.matterbridge.systemInformation.ipv6Address}]:${this.port}${UNDERLINEOFF}${rs}`);
108
54
  });
109
55
  }
110
- // eslint-disable-next-line @typescript-eslint/no-explicit-any
111
56
  this.httpServer.on('error', (error) => {
112
57
  this.log.error(`Frontend http server error listening on ${this.port}`);
113
58
  switch (error.code) {
@@ -123,7 +68,6 @@ export class Frontend {
123
68
  });
124
69
  }
125
70
  else {
126
- // Load the SSL certificate, the private key and optionally the CA certificate
127
71
  let cert;
128
72
  try {
129
73
  cert = await fs.readFile(path.join(this.matterbridge.matterbridgeDirectory, 'certs/cert.pem'), 'utf8');
@@ -151,9 +95,7 @@ export class Frontend {
151
95
  this.log.info(`CA certificate file ${path.join(this.matterbridge.matterbridgeDirectory, 'certs/ca.pem')} not loaded: ${error}`);
152
96
  }
153
97
  const serverOptions = { cert, key, ca };
154
- // Create an HTTPS server with the SSL certificate and private key (ca is optional) and attach the express app
155
98
  this.httpsServer = https.createServer(serverOptions, this.expressApp);
156
- // Listen on the specified port
157
99
  if (hasParameter('ingress')) {
158
100
  this.httpsServer.listen(this.port, '0.0.0.0', () => {
159
101
  this.log.info(`The frontend https server is listening on ${UNDERLINE}https://0.0.0.0:${this.port}${UNDERLINEOFF}${rs}`);
@@ -167,7 +109,6 @@ export class Frontend {
167
109
  this.log.info(`The frontend https server is listening on ${UNDERLINE}https://[${this.matterbridge.systemInformation.ipv6Address}]:${this.port}${UNDERLINEOFF}${rs}`);
168
110
  });
169
111
  }
170
- // eslint-disable-next-line @typescript-eslint/no-explicit-any
171
112
  this.httpsServer.on('error', (error) => {
172
113
  this.log.error(`Frontend https server error listening on ${this.port}`);
173
114
  switch (error.code) {
@@ -184,13 +125,12 @@ export class Frontend {
184
125
  }
185
126
  if (this.initializeError)
186
127
  return;
187
- // Createe a WebSocket server and attach it to the http or https server
188
128
  const wssPort = this.port;
189
129
  const wssHost = hasParameter('ssl') ? `wss://${this.matterbridge.systemInformation.ipv4Address}:${wssPort}` : `ws://${this.matterbridge.systemInformation.ipv4Address}:${wssPort}`;
190
130
  this.webSocketServer = new WebSocketServer(hasParameter('ssl') ? { server: this.httpsServer } : { server: this.httpServer });
191
131
  this.webSocketServer.on('connection', (ws, request) => {
192
132
  const clientIp = request.socket.remoteAddress;
193
- AnsiLogger.setGlobalCallback(this.wssSendMessage.bind(this), "debug" /* LogLevel.DEBUG */);
133
+ AnsiLogger.setGlobalCallback(this.wssSendMessage.bind(this), "debug");
194
134
  this.log.info(`WebSocketServer client "${clientIp}" connected to Matterbridge`);
195
135
  ws.on('message', (message) => {
196
136
  this.wsMessageHandler(ws, message);
@@ -222,11 +162,9 @@ export class Frontend {
222
162
  this.webSocketServer.on('error', (ws, error) => {
223
163
  this.log.error(`WebSocketServer error: ${error}`);
224
164
  });
225
- // Start the memory dump interval
226
165
  if (hasParameter('memorydump')) {
227
166
  this.startCpuMemoryDump();
228
167
  }
229
- // Endpoint to validate login code
230
168
  this.expressApp.post('/api/login', express.json(), async (req, res) => {
231
169
  const { password } = req.body;
232
170
  this.log.debug('The frontend sent /api/login', password);
@@ -245,27 +183,23 @@ export class Frontend {
245
183
  this.log.warn('/api/login error wrong password');
246
184
  res.json({ valid: false });
247
185
  }
248
- // eslint-disable-next-line @typescript-eslint/no-unused-vars
249
186
  }
250
187
  catch (error) {
251
188
  this.log.error('/api/login error getting password');
252
189
  res.json({ valid: false });
253
190
  }
254
191
  });
255
- // Endpoint to provide health check
256
192
  this.expressApp.get('/health', (req, res) => {
257
193
  this.log.debug('Express received /health');
258
194
  const healthStatus = {
259
- status: 'ok', // Indicate service is healthy
260
- uptime: process.uptime(), // Server uptime in seconds
261
- timestamp: new Date().toISOString(), // Current timestamp
195
+ status: 'ok',
196
+ uptime: process.uptime(),
197
+ timestamp: new Date().toISOString(),
262
198
  };
263
199
  res.status(200).json(healthStatus);
264
200
  });
265
- // Endpoint to provide memory usage details
266
201
  this.expressApp.get('/memory', async (req, res) => {
267
202
  this.log.debug('Express received /memory');
268
- // Memory usage from process
269
203
  const memoryUsageRaw = process.memoryUsage();
270
204
  const memoryUsage = {
271
205
  rss: this.formatMemoryUsage(memoryUsageRaw.rss),
@@ -274,13 +208,10 @@ export class Frontend {
274
208
  external: this.formatMemoryUsage(memoryUsageRaw.external),
275
209
  arrayBuffers: this.formatMemoryUsage(memoryUsageRaw.arrayBuffers),
276
210
  };
277
- // V8 heap statistics
278
211
  const { default: v8 } = await import('node:v8');
279
212
  const heapStatsRaw = v8.getHeapStatistics();
280
213
  const heapSpacesRaw = v8.getHeapSpaceStatistics();
281
- // Format heapStats
282
214
  const heapStats = Object.fromEntries(Object.entries(heapStatsRaw).map(([key, value]) => [key, this.formatMemoryUsage(value)]));
283
- // Format heapSpaces
284
215
  const heapSpaces = heapSpacesRaw.map((space) => ({
285
216
  ...space,
286
217
  space_size: this.formatMemoryUsage(space.space_size),
@@ -290,23 +221,6 @@ export class Frontend {
290
221
  }));
291
222
  const { default: module } = await import('module');
292
223
  const loadedModules = module._cache ? Object.keys(module._cache).sort() : [];
293
- /*
294
- if (req.query.heapdump === 'true') {
295
- const { default: heapdump } = await import('heapdump');
296
- const filename = `heapdump-${Date.now()}.heapsnapshot`;
297
-
298
- heapdump.writeSnapshot(filename, (err, dumpFilename) => {
299
- if (err) {
300
- this.log.error(`Heap dump error: ${err.message}`);
301
- return res.status(500).json({ error: 'Heap dump failed', details: err.message });
302
- }
303
-
304
- this.log.info(`Heap dump written to ${dumpFilename}`);
305
- return res.status(200).json({ ...memoryReport, heapdump: dumpFilename });
306
- });
307
- return; // Exit early since heapdump response is handled inside callback
308
- }
309
- */
310
224
  const memoryReport = {
311
225
  memoryUsage,
312
226
  heapStats,
@@ -315,7 +229,6 @@ export class Frontend {
315
229
  };
316
230
  res.status(200).json(memoryReport);
317
231
  });
318
- // Endpoint to start advertising the server node
319
232
  this.expressApp.get('/api/advertise', express.json(), async (req, res) => {
320
233
  const pairingCodes = await this.matterbridge.advertiseServerNode(this.matterbridge.serverNode);
321
234
  if (pairingCodes) {
@@ -326,24 +239,19 @@ export class Frontend {
326
239
  res.status(500).json({ error: 'Failed to generate pairing codes' });
327
240
  }
328
241
  });
329
- // Endpoint to provide settings
330
242
  this.expressApp.get('/api/settings', express.json(), async (req, res) => {
331
243
  this.log.debug('The frontend sent /api/settings');
332
244
  res.json(await this.getApiSettings());
333
245
  });
334
- // Endpoint to provide plugins
335
246
  this.expressApp.get('/api/plugins', async (req, res) => {
336
247
  this.log.debug('The frontend sent /api/plugins');
337
248
  const response = this.getBaseRegisteredPlugins();
338
- // this.log.debug('Response:', debugStringify(response));
339
249
  res.json(response);
340
250
  });
341
- // Endpoint to provide devices
342
251
  this.expressApp.get('/api/devices', (req, res) => {
343
252
  this.log.debug('The frontend sent /api/devices');
344
253
  const devices = [];
345
254
  this.matterbridge.devices.forEach(async (device) => {
346
- // Check if the device has the required properties
347
255
  if (!device.plugin || !device.name || !device.deviceName || !device.serialNumber || !device.uniqueId)
348
256
  return;
349
257
  const cluster = this.getClusterTextFromDevice(device);
@@ -359,10 +267,8 @@ export class Frontend {
359
267
  cluster: cluster,
360
268
  });
361
269
  });
362
- // this.log.debug('Response:', debugStringify(data));
363
270
  res.json(devices);
364
271
  });
365
- // Endpoint to provide the cluster servers of the devices
366
272
  this.expressApp.get('/api/devices_clusters/:selectedPluginName/:selectedDeviceEndpoint', (req, res) => {
367
273
  const selectedPluginName = req.params.selectedPluginName;
368
274
  const selectedDeviceEndpoint = parseInt(req.params.selectedDeviceEndpoint, 10);
@@ -435,7 +341,6 @@ export class Frontend {
435
341
  });
436
342
  res.json(data);
437
343
  });
438
- // Endpoint to view the log
439
344
  this.expressApp.get('/api/view-log', async (req, res) => {
440
345
  this.log.debug('The frontend sent /api/log');
441
346
  try {
@@ -448,12 +353,10 @@ export class Frontend {
448
353
  res.status(500).send('Error reading log file');
449
354
  }
450
355
  });
451
- // Endpoint to download the matterbridge log
452
356
  this.expressApp.get('/api/download-mblog', async (req, res) => {
453
357
  this.log.debug('The frontend sent /api/download-mblog');
454
358
  try {
455
359
  await fs.access(path.join(this.matterbridge.matterbridgeDirectory, this.matterbridge.matterbrideLoggerFile), fs.constants.F_OK);
456
- // eslint-disable-next-line @typescript-eslint/no-unused-vars
457
360
  }
458
361
  catch (error) {
459
362
  fs.appendFile(path.join(this.matterbridge.matterbridgeDirectory, this.matterbridge.matterbrideLoggerFile), 'Enable the log on file in the settings to enable the file logger');
@@ -465,12 +368,10 @@ export class Frontend {
465
368
  }
466
369
  });
467
370
  });
468
- // Endpoint to download the matter log
469
371
  this.expressApp.get('/api/download-mjlog', async (req, res) => {
470
372
  this.log.debug('The frontend sent /api/download-mjlog');
471
373
  try {
472
374
  await fs.access(path.join(this.matterbridge.matterbridgeDirectory, this.matterbridge.matterLoggerFile), fs.constants.F_OK);
473
- // eslint-disable-next-line @typescript-eslint/no-unused-vars
474
375
  }
475
376
  catch (error) {
476
377
  fs.appendFile(path.join(this.matterbridge.matterbridgeDirectory, this.matterbridge.matterLoggerFile), 'Enable the log on file in the settings to enable the file logger');
@@ -482,7 +383,6 @@ export class Frontend {
482
383
  }
483
384
  });
484
385
  });
485
- // Endpoint to download the matter storage file
486
386
  this.expressApp.get('/api/download-mjstorage', async (req, res) => {
487
387
  this.log.debug('The frontend sent /api/download-mjstorage');
488
388
  await createZip(path.join(os.tmpdir(), `matterbridge.${this.matterbridge.matterStorageName}.zip`), path.join(this.matterbridge.matterbridgeDirectory, this.matterbridge.matterStorageName));
@@ -493,7 +393,6 @@ export class Frontend {
493
393
  }
494
394
  });
495
395
  });
496
- // Endpoint to download the matterbridge storage directory
497
396
  this.expressApp.get('/api/download-mbstorage', async (req, res) => {
498
397
  this.log.debug('The frontend sent /api/download-mbstorage');
499
398
  await createZip(path.join(os.tmpdir(), `matterbridge.${this.matterbridge.nodeStorageName}.zip`), path.join(this.matterbridge.matterbridgeDirectory, this.matterbridge.nodeStorageName));
@@ -504,7 +403,6 @@ export class Frontend {
504
403
  }
505
404
  });
506
405
  });
507
- // Endpoint to download the matterbridge plugin directory
508
406
  this.expressApp.get('/api/download-pluginstorage', async (req, res) => {
509
407
  this.log.debug('The frontend sent /api/download-pluginstorage');
510
408
  await createZip(path.join(os.tmpdir(), `matterbridge.pluginstorage.zip`), this.matterbridge.matterbridgePluginDirectory);
@@ -515,11 +413,9 @@ export class Frontend {
515
413
  }
516
414
  });
517
415
  });
518
- // Endpoint to download the matterbridge plugin config files
519
416
  this.expressApp.get('/api/download-pluginconfig', async (req, res) => {
520
417
  this.log.debug('The frontend sent /api/download-pluginconfig');
521
418
  await createZip(path.join(os.tmpdir(), `matterbridge.pluginconfig.zip`), path.relative(process.cwd(), path.join(this.matterbridge.matterbridgeDirectory, '*.config.json')));
522
- // await createZip(path.join(os.tmpdir(), `matterbridge.pluginconfig.zip`), path.relative(process.cwd(), path.join(this.matterbridge.matterbridgeDirectory, 'certs', '*.*')), path.relative(process.cwd(), path.join(this.matterbridge.matterbridgeDirectory, '*.config.json')));
523
419
  res.download(path.join(os.tmpdir(), `matterbridge.pluginconfig.zip`), `matterbridge.pluginconfig.zip`, (error) => {
524
420
  if (error) {
525
421
  this.log.error(`Error downloading file matterbridge.pluginstorage.zip: ${error instanceof Error ? error.message : error}`);
@@ -527,7 +423,6 @@ export class Frontend {
527
423
  }
528
424
  });
529
425
  });
530
- // Endpoint to download the matterbridge plugin config files
531
426
  this.expressApp.get('/api/download-backup', async (req, res) => {
532
427
  this.log.debug('The frontend sent /api/download-backup');
533
428
  res.download(path.join(os.tmpdir(), `matterbridge.backup.zip`), `matterbridge.backup.zip`, (error) => {
@@ -537,7 +432,6 @@ export class Frontend {
537
432
  }
538
433
  });
539
434
  });
540
- // Endpoint to receive commands
541
435
  this.expressApp.post('/api/command/:command/:param', express.json(), async (req, res) => {
542
436
  const command = req.params.command;
543
437
  let param = req.params.param;
@@ -547,15 +441,13 @@ export class Frontend {
547
441
  return;
548
442
  }
549
443
  this.log.debug(`Received frontend command: ${command}:${param}`);
550
- // Handle the command setpassword from Settings
551
444
  if (command === 'setpassword') {
552
- const password = param.slice(1, -1); // Remove the first and last characters
445
+ const password = param.slice(1, -1);
553
446
  this.log.debug('setpassword', param, password);
554
447
  await this.matterbridge.nodeContext?.set('password', password);
555
448
  res.json({ message: 'Command received' });
556
449
  return;
557
450
  }
558
- // Handle the command setbridgemode from Settings
559
451
  if (command === 'setbridgemode') {
560
452
  this.log.debug(`setbridgemode: ${param}`);
561
453
  this.wssSendRestartRequired();
@@ -563,7 +455,6 @@ export class Frontend {
563
455
  res.json({ message: 'Command received' });
564
456
  return;
565
457
  }
566
- // Handle the command backup from Settings
567
458
  if (command === 'backup') {
568
459
  this.log.notice(`Prepairing the backup...`);
569
460
  await createZip(path.join(os.tmpdir(), `matterbridge.backup.zip`), path.join(this.matterbridge.matterbridgeDirectory), path.join(this.matterbridge.matterbridgePluginDirectory));
@@ -571,26 +462,25 @@ export class Frontend {
571
462
  res.json({ message: 'Command received' });
572
463
  return;
573
464
  }
574
- // Handle the command setmbloglevel from Settings
575
465
  if (command === 'setmbloglevel') {
576
466
  this.log.debug('Matterbridge log level:', param);
577
467
  if (param === 'Debug') {
578
- this.log.logLevel = "debug" /* LogLevel.DEBUG */;
468
+ this.log.logLevel = "debug";
579
469
  }
580
470
  else if (param === 'Info') {
581
- this.log.logLevel = "info" /* LogLevel.INFO */;
471
+ this.log.logLevel = "info";
582
472
  }
583
473
  else if (param === 'Notice') {
584
- this.log.logLevel = "notice" /* LogLevel.NOTICE */;
474
+ this.log.logLevel = "notice";
585
475
  }
586
476
  else if (param === 'Warn') {
587
- this.log.logLevel = "warn" /* LogLevel.WARN */;
477
+ this.log.logLevel = "warn";
588
478
  }
589
479
  else if (param === 'Error') {
590
- this.log.logLevel = "error" /* LogLevel.ERROR */;
480
+ this.log.logLevel = "error";
591
481
  }
592
482
  else if (param === 'Fatal') {
593
- this.log.logLevel = "fatal" /* LogLevel.FATAL */;
483
+ this.log.logLevel = "fatal";
594
484
  }
595
485
  await this.matterbridge.nodeContext?.set('matterbridgeLogLevel', this.log.logLevel);
596
486
  this.matterbridge.log.logLevel = this.log.logLevel;
@@ -600,13 +490,12 @@ export class Frontend {
600
490
  for (const plugin of this.matterbridge.plugins) {
601
491
  if (!plugin.platform || !plugin.platform.config)
602
492
  continue;
603
- plugin.platform.log.logLevel = plugin.platform.config.debug ? "debug" /* LogLevel.DEBUG */ : this.log.logLevel;
604
- await plugin.platform.onChangeLoggerLevel(plugin.platform.config.debug ? "debug" /* LogLevel.DEBUG */ : this.log.logLevel);
493
+ plugin.platform.log.logLevel = plugin.platform.config.debug ? "debug" : this.log.logLevel;
494
+ await plugin.platform.onChangeLoggerLevel(plugin.platform.config.debug ? "debug" : this.log.logLevel);
605
495
  }
606
496
  res.json({ message: 'Command received' });
607
497
  return;
608
498
  }
609
- // Handle the command setmbloglevel from Settings
610
499
  if (command === 'setmjloglevel') {
611
500
  this.log.debug('Matter.js log level:', param);
612
501
  if (param === 'Debug') {
@@ -631,34 +520,30 @@ export class Frontend {
631
520
  res.json({ message: 'Command received' });
632
521
  return;
633
522
  }
634
- // Handle the command setmdnsinterface from Settings
635
523
  if (command === 'setmdnsinterface') {
636
- param = param.slice(1, -1); // Remove the first and last characters *mdns*
524
+ param = param.slice(1, -1);
637
525
  this.matterbridge.matterbridgeInformation.mattermdnsinterface = param;
638
526
  this.log.debug('Matter.js mdns interface:', param === '' ? 'All interfaces' : param);
639
527
  await this.matterbridge.nodeContext?.set('mattermdnsinterface', param);
640
528
  res.json({ message: 'Command received' });
641
529
  return;
642
530
  }
643
- // Handle the command setipv4address from Settings
644
531
  if (command === 'setipv4address') {
645
- param = param.slice(1, -1); // Remove the first and last characters *ip*
532
+ param = param.slice(1, -1);
646
533
  this.matterbridge.matterbridgeInformation.matteripv4address = param;
647
534
  this.log.debug('Matter.js ipv4 address:', param === '' ? 'All ipv4 addresses' : param);
648
535
  await this.matterbridge.nodeContext?.set('matteripv4address', param);
649
536
  res.json({ message: 'Command received' });
650
537
  return;
651
538
  }
652
- // Handle the command setipv6address from Settings
653
539
  if (command === 'setipv6address') {
654
- param = param.slice(1, -1); // Remove the first and last characters *ip*
540
+ param = param.slice(1, -1);
655
541
  this.matterbridge.matterbridgeInformation.matteripv6address = param;
656
542
  this.log.debug('Matter.js ipv6 address:', param === '' ? 'All ipv6 addresses' : param);
657
543
  await this.matterbridge.nodeContext?.set('matteripv6address', param);
658
544
  res.json({ message: 'Command received' });
659
545
  return;
660
546
  }
661
- // Handle the command setmatterport from Settings
662
547
  if (command === 'setmatterport') {
663
548
  const port = Math.min(Math.max(parseInt(param), 5540), 5560);
664
549
  this.matterbridge.matterbridgeInformation.matterPort = port;
@@ -667,7 +552,6 @@ export class Frontend {
667
552
  res.json({ message: 'Command received' });
668
553
  return;
669
554
  }
670
- // Handle the command setmatterdiscriminator from Settings
671
555
  if (command === 'setmatterdiscriminator') {
672
556
  const discriminator = Math.min(Math.max(parseInt(param), 1000), 4095);
673
557
  this.matterbridge.matterbridgeInformation.matterDiscriminator = discriminator;
@@ -676,7 +560,6 @@ export class Frontend {
676
560
  res.json({ message: 'Command received' });
677
561
  return;
678
562
  }
679
- // Handle the command setmatterpasscode from Settings
680
563
  if (command === 'setmatterpasscode') {
681
564
  const passcode = Math.min(Math.max(parseInt(param), 10000000), 90000000);
682
565
  this.matterbridge.matterbridgeInformation.matterPasscode = passcode;
@@ -685,20 +568,17 @@ export class Frontend {
685
568
  res.json({ message: 'Command received' });
686
569
  return;
687
570
  }
688
- // Handle the command setmbloglevel from Settings
689
571
  if (command === 'setmblogfile') {
690
572
  this.log.debug('Matterbridge file log:', param);
691
573
  this.matterbridge.matterbridgeInformation.fileLogger = param === 'true';
692
574
  await this.matterbridge.nodeContext?.set('matterbridgeFileLog', param === 'true');
693
- // Create the file logger for matterbridge
694
575
  if (param === 'true')
695
- AnsiLogger.setGlobalLogfile(path.join(this.matterbridge.matterbridgeDirectory, this.matterbridge.matterbrideLoggerFile), "debug" /* LogLevel.DEBUG */, true);
576
+ AnsiLogger.setGlobalLogfile(path.join(this.matterbridge.matterbridgeDirectory, this.matterbridge.matterbrideLoggerFile), "debug", true);
696
577
  else
697
578
  AnsiLogger.setGlobalLogfile(undefined);
698
579
  res.json({ message: 'Command received' });
699
580
  return;
700
581
  }
701
- // Handle the command setmbloglevel from Settings
702
582
  if (command === 'setmjlogfile') {
703
583
  this.log.debug('Matter file log:', param);
704
584
  this.matterbridge.matterbridgeInformation.matterFileLogger = param === 'true';
@@ -725,48 +605,40 @@ export class Frontend {
725
605
  res.json({ message: 'Command received' });
726
606
  return;
727
607
  }
728
- // Handle the command unregister from Settings
729
608
  if (command === 'unregister') {
730
609
  await this.matterbridge.unregisterAndShutdownProcess();
731
610
  res.json({ message: 'Command received' });
732
611
  return;
733
612
  }
734
- // Handle the command reset from Settings
735
613
  if (command === 'reset') {
736
614
  await this.matterbridge.shutdownProcessAndReset();
737
615
  res.json({ message: 'Command received' });
738
616
  return;
739
617
  }
740
- // Handle the command factoryreset from Settings
741
618
  if (command === 'factoryreset') {
742
619
  await this.matterbridge.shutdownProcessAndFactoryReset();
743
620
  res.json({ message: 'Command received' });
744
621
  return;
745
622
  }
746
- // Handle the command shutdown from Header
747
623
  if (command === 'shutdown') {
748
624
  await this.matterbridge.shutdownProcess();
749
625
  res.json({ message: 'Command received' });
750
626
  return;
751
627
  }
752
- // Handle the command restart from Header
753
628
  if (command === 'restart') {
754
629
  await this.matterbridge.restartProcess();
755
630
  res.json({ message: 'Command received' });
756
631
  return;
757
632
  }
758
- // Handle the command update from Header
759
633
  if (command === 'update') {
760
634
  await this.matterbridge.updateProcess();
761
635
  this.wssSendRestartRequired();
762
636
  res.json({ message: 'Command received' });
763
637
  return;
764
638
  }
765
- // Handle the command saveconfig from Home
766
639
  if (command === 'saveconfig') {
767
640
  param = param.replace(/\*/g, '\\');
768
641
  this.log.info(`Saving config for plugin ${plg}${param}${nf}...`);
769
- // console.log('Req.body:', JSON.stringify(req.body, null, 2));
770
642
  if (!this.matterbridge.plugins.has(param)) {
771
643
  this.log.warn(`Plugin ${plg}${param}${wr} not found in matterbridge`);
772
644
  }
@@ -780,58 +652,49 @@ export class Frontend {
780
652
  res.json({ message: 'Command received' });
781
653
  return;
782
654
  }
783
- // Handle the command installplugin from Home
784
655
  if (command === 'installplugin') {
785
656
  param = param.replace(/\*/g, '\\');
786
657
  this.log.info(`Installing plugin ${plg}${param}${nf}...`);
787
658
  try {
788
659
  await this.matterbridge.spawnCommand('npm', ['install', '-g', param, '--omit=dev', '--verbose']);
789
660
  this.log.info(`Plugin ${plg}${param}${nf} installed. Full restart required.`);
790
- // eslint-disable-next-line @typescript-eslint/no-unused-vars
791
661
  }
792
662
  catch (error) {
793
663
  this.log.error(`Error installing plugin ${plg}${param}${er}`);
794
664
  }
795
665
  this.wssSendRestartRequired();
796
666
  param = param.split('@')[0];
797
- // Also add the plugin to matterbridge so no return!
798
667
  if (param === 'matterbridge') {
799
- // If we used the command installplugin to install a dev or a specific version of matterbridge we don't want to add it to matterbridge
800
668
  res.json({ message: 'Command received' });
801
669
  return;
802
670
  }
803
671
  }
804
- // Handle the command addplugin from Home
805
672
  if (command === 'addplugin' || command === 'installplugin') {
806
673
  param = param.replace(/\*/g, '\\');
807
674
  const plugin = await this.matterbridge.plugins.add(param);
808
675
  if (plugin) {
809
676
  if (this.matterbridge.bridgeMode === 'childbridge') {
810
- // We don't know now if the plugin is a dynamic platform or an accessory platform so we create the server node and the aggregator node
811
- // eslint-disable-next-line @typescript-eslint/no-explicit-any
812
677
  this.matterbridge.createDynamicPlugin(plugin, true);
813
678
  }
814
- this.matterbridge.plugins.load(plugin, true, 'The plugin has been added', true); // No await do it in the background
679
+ this.matterbridge.plugins.load(plugin, true, 'The plugin has been added', true);
815
680
  }
816
681
  res.json({ message: 'Command received' });
817
682
  this.wssSendRefreshRequired();
818
683
  return;
819
684
  }
820
- // Handle the command removeplugin from Home
821
685
  if (command === 'removeplugin') {
822
686
  if (!this.matterbridge.plugins.has(param)) {
823
687
  this.log.warn(`Plugin ${plg}${param}${wr} not found in matterbridge`);
824
688
  }
825
689
  else {
826
690
  const plugin = this.matterbridge.plugins.get(param);
827
- await this.matterbridge.plugins.shutdown(plugin, 'The plugin has been removed.', true); // This will also close the server node in childbridge mode
691
+ await this.matterbridge.plugins.shutdown(plugin, 'The plugin has been removed.', true);
828
692
  await this.matterbridge.plugins.remove(param);
829
693
  }
830
694
  res.json({ message: 'Command received' });
831
695
  this.wssSendRefreshRequired();
832
696
  return;
833
697
  }
834
- // Handle the command enableplugin from Home
835
698
  if (command === 'enableplugin') {
836
699
  if (!this.matterbridge.plugins.has(param)) {
837
700
  this.log.warn(`Plugin ${plg}${param}${wr} not found in matterbridge`);
@@ -849,17 +712,15 @@ export class Frontend {
849
712
  plugin.addedDevices = undefined;
850
713
  await this.matterbridge.plugins.enable(param);
851
714
  if (this.matterbridge.bridgeMode === 'childbridge' && plugin.type === 'DynamicPlatform') {
852
- // eslint-disable-next-line @typescript-eslint/no-explicit-any
853
715
  this.matterbridge.createDynamicPlugin(plugin, true);
854
716
  }
855
- this.matterbridge.plugins.load(plugin, true, 'The plugin has been enabled', true); // No await do it in the background since the server node is already started
717
+ this.matterbridge.plugins.load(plugin, true, 'The plugin has been enabled', true);
856
718
  }
857
719
  }
858
720
  res.json({ message: 'Command received' });
859
721
  this.wssSendRefreshRequired();
860
722
  return;
861
723
  }
862
- // Handle the command disableplugin from Home
863
724
  if (command === 'disableplugin') {
864
725
  if (!this.matterbridge.plugins.has(param)) {
865
726
  this.log.warn(`Plugin ${plg}${param}${wr} not found in matterbridge`);
@@ -867,7 +728,7 @@ export class Frontend {
867
728
  else {
868
729
  const plugin = this.matterbridge.plugins.get(param);
869
730
  if (plugin && plugin.enabled) {
870
- await this.matterbridge.plugins.shutdown(plugin, 'The plugin has been disabled.', true); // This will also close the server node in childbridge mode
731
+ await this.matterbridge.plugins.shutdown(plugin, 'The plugin has been disabled.', true);
871
732
  await this.matterbridge.plugins.disable(param);
872
733
  }
873
734
  }
@@ -876,7 +737,6 @@ export class Frontend {
876
737
  return;
877
738
  }
878
739
  });
879
- // Fallback for routing (must be the last route)
880
740
  this.expressApp.get('*', (req, res) => {
881
741
  this.log.debug('The frontend sent:', req.url);
882
742
  this.log.debug('Response send file:', path.join(this.matterbridge.rootDirectory, 'frontend/build/index.html'));
@@ -885,29 +745,24 @@ export class Frontend {
885
745
  this.log.debug(`Frontend initialized on port ${YELLOW}${this.port}${db} static ${UNDERLINE}${path.join(this.matterbridge.rootDirectory, 'frontend/build')}${UNDERLINEOFF}${rs}`);
886
746
  }
887
747
  async stop() {
888
- // Close the http server
889
748
  if (this.httpServer) {
890
749
  this.httpServer.close();
891
750
  this.httpServer.removeAllListeners();
892
751
  this.httpServer = undefined;
893
752
  this.log.debug('Frontend http server closed successfully');
894
753
  }
895
- // Close the https server
896
754
  if (this.httpsServer) {
897
755
  this.httpsServer.close();
898
756
  this.httpsServer.removeAllListeners();
899
757
  this.httpsServer = undefined;
900
758
  this.log.debug('Frontend https server closed successfully');
901
759
  }
902
- // Remove listeners from the express app
903
760
  if (this.expressApp) {
904
761
  this.expressApp.removeAllListeners();
905
762
  this.expressApp = undefined;
906
763
  this.log.debug('Frontend app closed successfully');
907
764
  }
908
- // Close the WebSocket server
909
765
  if (this.webSocketServer) {
910
- // Close all active connections
911
766
  this.webSocketServer.clients.forEach((client) => {
912
767
  if (client.readyState === WebSocket.OPEN) {
913
768
  client.close();
@@ -923,12 +778,10 @@ export class Frontend {
923
778
  });
924
779
  this.webSocketServer = undefined;
925
780
  }
926
- // Stop the memory dump interval
927
781
  if (hasParameter('memorydump')) {
928
782
  this.stopCpuMemoryDump();
929
783
  }
930
784
  }
931
- // Function to format bytes to KB or MB
932
785
  formatMemoryUsage = (bytes) => {
933
786
  const kb = bytes / 1024;
934
787
  const mb = kb / 1024;
@@ -940,10 +793,9 @@ export class Frontend {
940
793
  const interval = () => {
941
794
  const currCpus = os.cpus();
942
795
  if (currCpus.length !== this.prevCpus.length) {
943
- this.prevCpus = currCpus; // Reset the previous cpus if the number of cpu has changed
796
+ this.prevCpus = currCpus;
944
797
  }
945
798
  let totalIdle = 0, totalTick = 0;
946
- // Get the cpu usage
947
799
  this.prevCpus.forEach((prevCpu, i) => {
948
800
  const currCpu = currCpus[i];
949
801
  const idleDiff = currCpu.times.idle - prevCpu.times.idle;
@@ -953,7 +805,6 @@ export class Frontend {
953
805
  });
954
806
  const cpuUsage = (100 - (totalIdle / totalTick) * 100).toFixed(2);
955
807
  this.prevCpus = currCpus;
956
- // Get the memory usage
957
808
  const memoryUsageRaw = process.memoryUsage();
958
809
  this.memoryData.push({ ...memoryUsageRaw, cpu: cpuUsage });
959
810
  const memoryUsage = {
@@ -986,21 +837,14 @@ export class Frontend {
986
837
  external: this.formatMemoryUsage(memory.external),
987
838
  arrayBuffers: this.formatMemoryUsage(memory.arrayBuffers),
988
839
  };
989
- // eslint-disable-next-line no-console
990
840
  console.log(`${YELLOW}Cpu usage${db} ${CYAN}${memory.cpu.padStart(6, ' ')} %${db} - ${YELLOW}Memory usage${db} rss ${CYAN}${memoryUsage.rss}${db} heapTotal ${CYAN}${memoryUsage.heapTotal}${db} heapUsed ${CYAN}${memoryUsage.heapUsed}${db} external ${memoryUsage.external} arrayBuffers ${memoryUsage.arrayBuffers}${rs}`);
991
841
  }
992
842
  this.memoryData = [];
993
843
  this.prevCpus = [];
994
844
  }
995
- /**
996
- * Retrieves the api settings data.
997
- * @returns {Promise<object>} A promise that resolve in the api settings object.
998
- */
999
845
  async getApiSettings() {
1000
- // Update the system information
1001
846
  this.matterbridge.systemInformation.rss = this.formatMemoryUsage(process.memoryUsage().rss);
1002
847
  this.matterbridge.systemInformation.heap = this.formatMemoryUsage(process.memoryUsage().heapUsed) + ' / ' + this.formatMemoryUsage(process.memoryUsage().heapTotal);
1003
- // Update the matterbridge information
1004
848
  this.matterbridge.matterbridgeInformation.bridgeMode = this.matterbridge.bridgeMode;
1005
849
  this.matterbridge.matterbridgeInformation.restartMode = this.matterbridge.restartMode;
1006
850
  this.matterbridge.matterbridgeInformation.loggerLevel = this.matterbridge.log.logLevel;
@@ -1019,11 +863,6 @@ export class Frontend {
1019
863
  this.matterbridge.matterbridgeInformation.profile = this.matterbridge.profile;
1020
864
  return { systemInformation: this.matterbridge.systemInformation, matterbridgeInformation: this.matterbridge.matterbridgeInformation };
1021
865
  }
1022
- /**
1023
- * Retrieves the cluster text description from a given device.
1024
- * @param {MatterbridgeDevice} device - The MatterbridgeDevice object.
1025
- * @returns {string} The attributes description of the cluster servers in the device.
1026
- */
1027
866
  getClusterTextFromDevice(device) {
1028
867
  const getAttribute = (device, cluster, attribute) => {
1029
868
  let value = undefined;
@@ -1062,7 +901,6 @@ export class Frontend {
1062
901
  };
1063
902
  let attributes = '';
1064
903
  device.forEachAttribute((clusterName, clusterId, attributeName, attributeId, attributeValue) => {
1065
- // console.log(`${device.deviceName} => Cluster: ${clusterName}-${clusterId} Attribute: ${attributeName}-${attributeId} Value(${typeof attributeValue}): ${attributeValue}`);
1066
904
  if (typeof attributeValue === 'undefined')
1067
905
  return;
1068
906
  if (clusterName === 'onOff' && attributeName === 'onOff')
@@ -1140,13 +978,8 @@ export class Frontend {
1140
978
  if (clusterName === 'userLabel' && attributeName === 'labelList')
1141
979
  attributes += `${getUserLabel(device)} `;
1142
980
  });
1143
- // console.log(`${device.deviceName}.forEachAttribute: ${attributes}`);
1144
981
  return attributes.trimStart().trimEnd();
1145
982
  }
1146
- /**
1147
- * Retrieves the base registered plugins sanitized for res.json().
1148
- * @returns {BaseRegisteredPlugin[]} An array of BaseRegisteredPlugin.
1149
- */
1150
983
  getBaseRegisteredPlugins() {
1151
984
  const baseRegisteredPlugins = [];
1152
985
  for (const plugin of this.matterbridge.plugins) {
@@ -1177,14 +1010,6 @@ export class Frontend {
1177
1010
  }
1178
1011
  return baseRegisteredPlugins;
1179
1012
  }
1180
- /**
1181
- * Handles incoming websocket messages for the Matterbridge.
1182
- *
1183
- * @param {Matterbridge} this - The Matterbridge instance.
1184
- * @param {WebSocket} client - The websocket client that sent the message.
1185
- * @param {WebSocket.RawData} message - The raw data of the message received from the client.
1186
- * @returns {Promise<void>} A promise that resolves when the message has been handled.
1187
- */
1188
1013
  async wsMessageHandler(client, message) {
1189
1014
  let data;
1190
1015
  try {
@@ -1272,10 +1097,8 @@ export class Frontend {
1272
1097
  else if (data.method === '/api/devices') {
1273
1098
  const devices = [];
1274
1099
  this.matterbridge.devices.forEach(async (device) => {
1275
- // Filter by pluginName if provided
1276
1100
  if (data.params.pluginName && data.params.pluginName !== device.plugin)
1277
1101
  return;
1278
- // Check if the device has the required properties
1279
1102
  if (!device.plugin || !device.name || !device.deviceName || !device.serialNumber || !device.uniqueId)
1280
1103
  return;
1281
1104
  const cluster = this.getClusterTextFromDevice(device);
@@ -1358,7 +1181,6 @@ export class Frontend {
1358
1181
  });
1359
1182
  endpointServer.getChildEndpoints().forEach((childEndpoint) => {
1360
1183
  deviceTypes = [];
1361
- // eslint-disable-next-line @typescript-eslint/no-explicit-any
1362
1184
  const name = childEndpoint.endpoint?.id;
1363
1185
  const clusterServers = childEndpoint.getAllClusterServers();
1364
1186
  clusterServers.forEach((clusterServer) => {
@@ -1441,73 +1263,44 @@ export class Frontend {
1441
1263
  return;
1442
1264
  }
1443
1265
  }
1444
- /**
1445
- * Sends a WebSocket message to all connected clients. The function is called by AnsiLogger.setGlobalCallback.
1446
- *
1447
- * @param {string} level - The logger level of the message: debug info notice warn error fatal...
1448
- * @param {string} time - The time string of the message
1449
- * @param {string} name - The logger name of the message
1450
- * @param {string} message - The content of the message.
1451
- */
1452
1266
  wssSendMessage(level, time, name, message) {
1453
1267
  if (!level || !time || !name || !message)
1454
1268
  return;
1455
- // Remove ANSI escape codes from the message
1456
- // eslint-disable-next-line no-control-regex
1457
1269
  message = message.replace(/\x1B\[[0-9;]*[m|s|u|K]/g, '');
1458
- // Remove leading asterisks from the message
1459
1270
  message = message.replace(/^\*+/, '');
1460
- // Replace all occurrences of \t and \n
1461
1271
  message = message.replace(/[\t\n]/g, '');
1462
- // Remove non-printable characters
1463
- // eslint-disable-next-line no-control-regex
1464
1272
  message = message.replace(/[\x00-\x1F\x7F]/g, '');
1465
- // Replace all occurrences of \" with "
1466
1273
  message = message.replace(/\\"/g, '"');
1467
- // Define the maximum allowed length for continuous characters without a space
1468
1274
  const maxContinuousLength = 100;
1469
1275
  const keepStartLength = 20;
1470
1276
  const keepEndLength = 20;
1471
- // Split the message into words
1472
1277
  message = message
1473
1278
  .split(' ')
1474
1279
  .map((word) => {
1475
- // If the word length exceeds the max continuous length, insert spaces and truncate
1476
1280
  if (word.length > maxContinuousLength) {
1477
1281
  return word.slice(0, keepStartLength) + ' ... ' + word.slice(-keepEndLength);
1478
1282
  }
1479
1283
  return word;
1480
1284
  })
1481
1285
  .join(' ');
1482
- // Send the message to all connected clients
1483
1286
  this.webSocketServer?.clients.forEach((client) => {
1484
1287
  if (client.readyState === WebSocket.OPEN) {
1485
1288
  client.send(JSON.stringify({ id: WS_ID_LOG, src: 'Matterbridge', level, time, name, message }));
1486
1289
  }
1487
1290
  });
1488
1291
  }
1489
- /**
1490
- * Sends a need to refresh WebSocket message to all connected clients.
1491
- *
1492
- */
1493
1292
  wssSendRefreshRequired() {
1494
1293
  this.log.debug('Sending a refresh required message to all connected clients');
1495
1294
  this.matterbridge.matterbridgeInformation.refreshRequired = true;
1496
- // Send the message to all connected clients
1497
1295
  this.webSocketServer?.clients.forEach((client) => {
1498
1296
  if (client.readyState === WebSocket.OPEN) {
1499
1297
  client.send(JSON.stringify({ id: WS_ID_REFRESH_NEEDED, src: 'Matterbridge', dst: 'Frontend', method: 'refresh_required', params: {} }));
1500
1298
  }
1501
1299
  });
1502
1300
  }
1503
- /**
1504
- * Sends a need to restart WebSocket message to all connected clients.
1505
- *
1506
- */
1507
1301
  wssSendRestartRequired() {
1508
1302
  this.log.debug('Sending a restart required message to all connected clients');
1509
1303
  this.matterbridge.matterbridgeInformation.restartRequired = true;
1510
- // Send the message to all connected clients
1511
1304
  this.webSocketServer?.clients.forEach((client) => {
1512
1305
  if (client.readyState === WebSocket.OPEN) {
1513
1306
  client.send(JSON.stringify({ id: WS_ID_RESTART_NEEDED, src: 'Matterbridge', dst: 'Frontend', method: 'restart_required', params: {} }));
@@ -1515,4 +1308,3 @@ export class Frontend {
1515
1308
  });
1516
1309
  }
1517
1310
  }
1518
- //# sourceMappingURL=frontend.js.map