matterbridge 2.1.4 → 2.1.5-dev.2

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 +14 -0
  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 -232
  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 +55 -761
  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 +10 -710
  21. package/dist/matterbridgeEndpointHelpers.js +29 -105
  22. package/dist/matterbridgePlatform.js +5 -121
  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 +13 -267
  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 -2264
  89. package/dist/matterbridgeEndpointHelpers.d.ts.map +0 -1
  90. package/dist/matterbridgeEndpointHelpers.js.map +0 -1
  91. package/dist/matterbridgePlatform.d.ts +0 -159
  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 -231
  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,7 +745,6 @@ 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
- // Start the memory check. This will not allow the process to exit but will log the memory usage for 5 minutes.
889
748
  if (hasParameter('memorycheck')) {
890
749
  await new Promise((resolve) => {
891
750
  this.log.debug(`***Memory check started for ${getIntParameter('memorycheck') ?? 5 * 60 * 1000} ms`);
@@ -895,29 +754,24 @@ export class Frontend {
895
754
  }, getIntParameter('memorycheck') ?? 5 * 60 * 1000);
896
755
  });
897
756
  }
898
- // Close the http server
899
757
  if (this.httpServer) {
900
758
  this.httpServer.close();
901
759
  this.httpServer.removeAllListeners();
902
760
  this.httpServer = undefined;
903
761
  this.log.debug('Frontend http server closed successfully');
904
762
  }
905
- // Close the https server
906
763
  if (this.httpsServer) {
907
764
  this.httpsServer.close();
908
765
  this.httpsServer.removeAllListeners();
909
766
  this.httpsServer = undefined;
910
767
  this.log.debug('Frontend https server closed successfully');
911
768
  }
912
- // Remove listeners from the express app
913
769
  if (this.expressApp) {
914
770
  this.expressApp.removeAllListeners();
915
771
  this.expressApp = undefined;
916
772
  this.log.debug('Frontend app closed successfully');
917
773
  }
918
- // Close the WebSocket server
919
774
  if (this.webSocketServer) {
920
- // Close all active connections
921
775
  this.webSocketServer.clients.forEach((client) => {
922
776
  if (client.readyState === WebSocket.OPEN) {
923
777
  client.close();
@@ -933,12 +787,10 @@ export class Frontend {
933
787
  });
934
788
  this.webSocketServer = undefined;
935
789
  }
936
- // Stop the memory dump interval
937
790
  if (hasParameter('memorydump')) {
938
791
  this.stopCpuMemoryDump();
939
792
  }
940
793
  }
941
- // Function to format bytes to KB or MB
942
794
  formatMemoryUsage = (bytes) => {
943
795
  const kb = bytes / 1024;
944
796
  const mb = kb / 1024;
@@ -950,10 +802,9 @@ export class Frontend {
950
802
  const interval = () => {
951
803
  const currCpus = os.cpus();
952
804
  if (currCpus.length !== this.prevCpus.length) {
953
- this.prevCpus = currCpus; // Reset the previous cpus if the number of cpu has changed
805
+ this.prevCpus = currCpus;
954
806
  }
955
807
  let totalIdle = 0, totalTick = 0;
956
- // Get the cpu usage
957
808
  this.prevCpus.forEach((prevCpu, i) => {
958
809
  const currCpu = currCpus[i];
959
810
  const idleDiff = currCpu.times.idle - prevCpu.times.idle;
@@ -963,7 +814,6 @@ export class Frontend {
963
814
  });
964
815
  const cpuUsage = (100 - (totalIdle / totalTick) * 100).toFixed(2);
965
816
  this.prevCpus = currCpus;
966
- // Get the memory usage
967
817
  const memoryUsageRaw = process.memoryUsage();
968
818
  this.memoryData.push({ ...memoryUsageRaw, cpu: cpuUsage });
969
819
  const memoryUsage = {
@@ -996,21 +846,14 @@ export class Frontend {
996
846
  external: this.formatMemoryUsage(memory.external),
997
847
  arrayBuffers: this.formatMemoryUsage(memory.arrayBuffers),
998
848
  };
999
- // eslint-disable-next-line no-console
1000
849
  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}`);
1001
850
  }
1002
851
  this.memoryData = [];
1003
852
  this.prevCpus = [];
1004
853
  }
1005
- /**
1006
- * Retrieves the api settings data.
1007
- * @returns {Promise<object>} A promise that resolve in the api settings object.
1008
- */
1009
854
  async getApiSettings() {
1010
- // Update the system information
1011
855
  this.matterbridge.systemInformation.rss = this.formatMemoryUsage(process.memoryUsage().rss);
1012
856
  this.matterbridge.systemInformation.heap = this.formatMemoryUsage(process.memoryUsage().heapUsed) + ' / ' + this.formatMemoryUsage(process.memoryUsage().heapTotal);
1013
- // Update the matterbridge information
1014
857
  this.matterbridge.matterbridgeInformation.bridgeMode = this.matterbridge.bridgeMode;
1015
858
  this.matterbridge.matterbridgeInformation.restartMode = this.matterbridge.restartMode;
1016
859
  this.matterbridge.matterbridgeInformation.loggerLevel = this.matterbridge.log.logLevel;
@@ -1029,11 +872,6 @@ export class Frontend {
1029
872
  this.matterbridge.matterbridgeInformation.profile = this.matterbridge.profile;
1030
873
  return { systemInformation: this.matterbridge.systemInformation, matterbridgeInformation: this.matterbridge.matterbridgeInformation };
1031
874
  }
1032
- /**
1033
- * Retrieves the cluster text description from a given device.
1034
- * @param {MatterbridgeDevice} device - The MatterbridgeDevice object.
1035
- * @returns {string} The attributes description of the cluster servers in the device.
1036
- */
1037
875
  getClusterTextFromDevice(device) {
1038
876
  const getAttribute = (device, cluster, attribute) => {
1039
877
  let value = undefined;
@@ -1072,7 +910,6 @@ export class Frontend {
1072
910
  };
1073
911
  let attributes = '';
1074
912
  device.forEachAttribute((clusterName, clusterId, attributeName, attributeId, attributeValue) => {
1075
- // console.log(`${device.deviceName} => Cluster: ${clusterName}-${clusterId} Attribute: ${attributeName}-${attributeId} Value(${typeof attributeValue}): ${attributeValue}`);
1076
913
  if (typeof attributeValue === 'undefined')
1077
914
  return;
1078
915
  if (clusterName === 'onOff' && attributeName === 'onOff')
@@ -1150,13 +987,8 @@ export class Frontend {
1150
987
  if (clusterName === 'userLabel' && attributeName === 'labelList')
1151
988
  attributes += `${getUserLabel(device)} `;
1152
989
  });
1153
- // console.log(`${device.deviceName}.forEachAttribute: ${attributes}`);
1154
990
  return attributes.trimStart().trimEnd();
1155
991
  }
1156
- /**
1157
- * Retrieves the base registered plugins sanitized for res.json().
1158
- * @returns {BaseRegisteredPlugin[]} An array of BaseRegisteredPlugin.
1159
- */
1160
992
  getBaseRegisteredPlugins() {
1161
993
  const baseRegisteredPlugins = [];
1162
994
  for (const plugin of this.matterbridge.plugins) {
@@ -1187,14 +1019,6 @@ export class Frontend {
1187
1019
  }
1188
1020
  return baseRegisteredPlugins;
1189
1021
  }
1190
- /**
1191
- * Handles incoming websocket messages for the Matterbridge.
1192
- *
1193
- * @param {Matterbridge} this - The Matterbridge instance.
1194
- * @param {WebSocket} client - The websocket client that sent the message.
1195
- * @param {WebSocket.RawData} message - The raw data of the message received from the client.
1196
- * @returns {Promise<void>} A promise that resolves when the message has been handled.
1197
- */
1198
1022
  async wsMessageHandler(client, message) {
1199
1023
  let data;
1200
1024
  try {
@@ -1282,10 +1106,8 @@ export class Frontend {
1282
1106
  else if (data.method === '/api/devices') {
1283
1107
  const devices = [];
1284
1108
  this.matterbridge.devices.forEach(async (device) => {
1285
- // Filter by pluginName if provided
1286
1109
  if (data.params.pluginName && data.params.pluginName !== device.plugin)
1287
1110
  return;
1288
- // Check if the device has the required properties
1289
1111
  if (!device.plugin || !device.name || !device.deviceName || !device.serialNumber || !device.uniqueId)
1290
1112
  return;
1291
1113
  const cluster = this.getClusterTextFromDevice(device);
@@ -1368,7 +1190,6 @@ export class Frontend {
1368
1190
  });
1369
1191
  endpointServer.getChildEndpoints().forEach((childEndpoint) => {
1370
1192
  deviceTypes = [];
1371
- // eslint-disable-next-line @typescript-eslint/no-explicit-any
1372
1193
  const name = childEndpoint.endpoint?.id;
1373
1194
  const clusterServers = childEndpoint.getAllClusterServers();
1374
1195
  clusterServers.forEach((clusterServer) => {
@@ -1451,73 +1272,44 @@ export class Frontend {
1451
1272
  return;
1452
1273
  }
1453
1274
  }
1454
- /**
1455
- * Sends a WebSocket message to all connected clients. The function is called by AnsiLogger.setGlobalCallback.
1456
- *
1457
- * @param {string} level - The logger level of the message: debug info notice warn error fatal...
1458
- * @param {string} time - The time string of the message
1459
- * @param {string} name - The logger name of the message
1460
- * @param {string} message - The content of the message.
1461
- */
1462
1275
  wssSendMessage(level, time, name, message) {
1463
1276
  if (!level || !time || !name || !message)
1464
1277
  return;
1465
- // Remove ANSI escape codes from the message
1466
- // eslint-disable-next-line no-control-regex
1467
1278
  message = message.replace(/\x1B\[[0-9;]*[m|s|u|K]/g, '');
1468
- // Remove leading asterisks from the message
1469
1279
  message = message.replace(/^\*+/, '');
1470
- // Replace all occurrences of \t and \n
1471
1280
  message = message.replace(/[\t\n]/g, '');
1472
- // Remove non-printable characters
1473
- // eslint-disable-next-line no-control-regex
1474
1281
  message = message.replace(/[\x00-\x1F\x7F]/g, '');
1475
- // Replace all occurrences of \" with "
1476
1282
  message = message.replace(/\\"/g, '"');
1477
- // Define the maximum allowed length for continuous characters without a space
1478
1283
  const maxContinuousLength = 100;
1479
1284
  const keepStartLength = 20;
1480
1285
  const keepEndLength = 20;
1481
- // Split the message into words
1482
1286
  message = message
1483
1287
  .split(' ')
1484
1288
  .map((word) => {
1485
- // If the word length exceeds the max continuous length, insert spaces and truncate
1486
1289
  if (word.length > maxContinuousLength) {
1487
1290
  return word.slice(0, keepStartLength) + ' ... ' + word.slice(-keepEndLength);
1488
1291
  }
1489
1292
  return word;
1490
1293
  })
1491
1294
  .join(' ');
1492
- // Send the message to all connected clients
1493
1295
  this.webSocketServer?.clients.forEach((client) => {
1494
1296
  if (client.readyState === WebSocket.OPEN) {
1495
1297
  client.send(JSON.stringify({ id: WS_ID_LOG, src: 'Matterbridge', level, time, name, message }));
1496
1298
  }
1497
1299
  });
1498
1300
  }
1499
- /**
1500
- * Sends a need to refresh WebSocket message to all connected clients.
1501
- *
1502
- */
1503
1301
  wssSendRefreshRequired() {
1504
1302
  this.log.debug('Sending a refresh required message to all connected clients');
1505
1303
  this.matterbridge.matterbridgeInformation.refreshRequired = true;
1506
- // Send the message to all connected clients
1507
1304
  this.webSocketServer?.clients.forEach((client) => {
1508
1305
  if (client.readyState === WebSocket.OPEN) {
1509
1306
  client.send(JSON.stringify({ id: WS_ID_REFRESH_NEEDED, src: 'Matterbridge', dst: 'Frontend', method: 'refresh_required', params: {} }));
1510
1307
  }
1511
1308
  });
1512
1309
  }
1513
- /**
1514
- * Sends a need to restart WebSocket message to all connected clients.
1515
- *
1516
- */
1517
1310
  wssSendRestartRequired() {
1518
1311
  this.log.debug('Sending a restart required message to all connected clients');
1519
1312
  this.matterbridge.matterbridgeInformation.restartRequired = true;
1520
- // Send the message to all connected clients
1521
1313
  this.webSocketServer?.clients.forEach((client) => {
1522
1314
  if (client.readyState === WebSocket.OPEN) {
1523
1315
  client.send(JSON.stringify({ id: WS_ID_RESTART_NEEDED, src: 'Matterbridge', dst: 'Frontend', method: 'restart_required', params: {} }));
@@ -1525,4 +1317,3 @@ export class Frontend {
1525
1317
  });
1526
1318
  }
1527
1319
  }
1528
- //# sourceMappingURL=frontend.js.map