matterbridge 2.2.0-dev.5 → 2.2.0-dev.6

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 (120) hide show
  1. package/dist/cli.js +2 -37
  2. package/dist/cluster/export.js +0 -2
  3. package/dist/defaultConfigSchema.js +0 -23
  4. package/dist/deviceManager.js +1 -94
  5. package/dist/frontend.js +22 -265
  6. package/dist/index.js +2 -29
  7. package/dist/logger/export.js +0 -1
  8. package/dist/matter/behaviors.js +0 -2
  9. package/dist/matter/clusters.js +0 -2
  10. package/dist/matter/devices.js +0 -2
  11. package/dist/matter/endpoints.js +0 -2
  12. package/dist/matter/export.js +0 -2
  13. package/dist/matter/types.js +1 -3
  14. package/dist/matterbridge.js +47 -718
  15. package/dist/matterbridgeAccessoryPlatform.js +0 -33
  16. package/dist/matterbridgeBehaviors.js +1 -32
  17. package/dist/matterbridgeDeviceTypes.js +11 -112
  18. package/dist/matterbridgeDynamicPlatform.js +0 -33
  19. package/dist/matterbridgeEndpoint.js +6 -690
  20. package/dist/matterbridgeEndpointHelpers.js +9 -118
  21. package/dist/matterbridgePlatform.js +7 -140
  22. package/dist/matterbridgeTypes.js +0 -24
  23. package/dist/pluginManager.js +3 -229
  24. package/dist/shelly.js +4 -131
  25. package/dist/storage/export.js +0 -1
  26. package/dist/update.js +0 -45
  27. package/dist/utils/colorUtils.js +2 -205
  28. package/dist/utils/copyDirectory.js +1 -37
  29. package/dist/utils/createZip.js +2 -42
  30. package/dist/utils/deepCopy.js +0 -40
  31. package/dist/utils/deepEqual.js +1 -65
  32. package/dist/utils/export.js +0 -1
  33. package/dist/utils/isvalid.js +0 -86
  34. package/dist/utils/network.js +5 -77
  35. package/dist/utils/parameter.js +0 -41
  36. package/dist/utils/wait.js +5 -48
  37. package/npm-shrinkwrap.json +2 -2
  38. package/package.json +1 -1
  39. package/dist/cli.d.ts +0 -28
  40. package/dist/cli.d.ts.map +0 -1
  41. package/dist/cli.js.map +0 -1
  42. package/dist/cluster/export.d.ts.map +0 -1
  43. package/dist/cluster/export.js.map +0 -1
  44. package/dist/defaultConfigSchema.d.ts.map +0 -1
  45. package/dist/defaultConfigSchema.js.map +0 -1
  46. package/dist/deviceManager.d.ts +0 -109
  47. package/dist/deviceManager.d.ts.map +0 -1
  48. package/dist/deviceManager.js.map +0 -1
  49. package/dist/frontend.d.ts +0 -172
  50. package/dist/frontend.d.ts.map +0 -1
  51. package/dist/frontend.js.map +0 -1
  52. package/dist/index.d.ts.map +0 -1
  53. package/dist/index.js.map +0 -1
  54. package/dist/logger/export.d.ts.map +0 -1
  55. package/dist/logger/export.js.map +0 -1
  56. package/dist/matter/behaviors.d.ts.map +0 -1
  57. package/dist/matter/behaviors.js.map +0 -1
  58. package/dist/matter/clusters.d.ts.map +0 -1
  59. package/dist/matter/clusters.js.map +0 -1
  60. package/dist/matter/devices.d.ts.map +0 -1
  61. package/dist/matter/devices.js.map +0 -1
  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.map +0 -1
  65. package/dist/matter/export.js.map +0 -1
  66. package/dist/matter/types.d.ts.map +0 -1
  67. package/dist/matter/types.js.map +0 -1
  68. package/dist/matterbridge.d.ts +0 -410
  69. package/dist/matterbridge.d.ts.map +0 -1
  70. package/dist/matterbridge.js.map +0 -1
  71. package/dist/matterbridgeAccessoryPlatform.d.ts.map +0 -1
  72. package/dist/matterbridgeAccessoryPlatform.js.map +0 -1
  73. package/dist/matterbridgeBehaviors.d.ts +0 -148
  74. package/dist/matterbridgeBehaviors.d.ts.map +0 -1
  75. package/dist/matterbridgeBehaviors.js.map +0 -1
  76. package/dist/matterbridgeDeviceTypes.d.ts.map +0 -1
  77. package/dist/matterbridgeDeviceTypes.js.map +0 -1
  78. package/dist/matterbridgeDynamicPlatform.d.ts.map +0 -1
  79. package/dist/matterbridgeDynamicPlatform.js.map +0 -1
  80. package/dist/matterbridgeEndpoint.d.ts +0 -827
  81. package/dist/matterbridgeEndpoint.d.ts.map +0 -1
  82. package/dist/matterbridgeEndpoint.js.map +0 -1
  83. package/dist/matterbridgeEndpointHelpers.d.ts +0 -123
  84. package/dist/matterbridgeEndpointHelpers.d.ts.map +0 -1
  85. package/dist/matterbridgeEndpointHelpers.js.map +0 -1
  86. package/dist/matterbridgePlatform.d.ts +0 -159
  87. package/dist/matterbridgePlatform.d.ts.map +0 -1
  88. package/dist/matterbridgePlatform.js.map +0 -1
  89. package/dist/matterbridgeTypes.d.ts.map +0 -1
  90. package/dist/matterbridgeTypes.js.map +0 -1
  91. package/dist/pluginManager.d.ts +0 -236
  92. package/dist/pluginManager.d.ts.map +0 -1
  93. package/dist/pluginManager.js.map +0 -1
  94. package/dist/shelly.d.ts.map +0 -1
  95. package/dist/shelly.js.map +0 -1
  96. package/dist/storage/export.d.ts.map +0 -1
  97. package/dist/storage/export.js.map +0 -1
  98. package/dist/update.d.ts.map +0 -1
  99. package/dist/update.js.map +0 -1
  100. package/dist/utils/colorUtils.d.ts.map +0 -1
  101. package/dist/utils/colorUtils.js.map +0 -1
  102. package/dist/utils/copyDirectory.d.ts.map +0 -1
  103. package/dist/utils/copyDirectory.js.map +0 -1
  104. package/dist/utils/createZip.d.ts.map +0 -1
  105. package/dist/utils/createZip.js.map +0 -1
  106. package/dist/utils/deepCopy.d.ts.map +0 -1
  107. package/dist/utils/deepCopy.js.map +0 -1
  108. package/dist/utils/deepEqual.d.ts.map +0 -1
  109. package/dist/utils/deepEqual.js.map +0 -1
  110. package/dist/utils/export.d.ts.map +0 -1
  111. package/dist/utils/export.js.map +0 -1
  112. package/dist/utils/isvalid.d.ts.map +0 -1
  113. package/dist/utils/isvalid.js.map +0 -1
  114. package/dist/utils/network.d.ts.map +0 -1
  115. package/dist/utils/network.js.map +0 -1
  116. package/dist/utils/parameter.d.ts.map +0 -1
  117. package/dist/utils/parameter.js.map +0 -1
  118. package/dist/utils/wait.d.ts +0 -43
  119. package/dist/utils/wait.d.ts.map +0 -1
  120. package/dist/utils/wait.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.2
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 'node:http';
27
3
  import https from 'https';
28
4
  import express from 'express';
@@ -30,70 +6,19 @@ import WebSocket, { WebSocketServer } from 'ws';
30
6
  import os from 'node:os';
31
7
  import path from 'node:path';
32
8
  import { promises as fs } from 'node:fs';
33
- // AnsiLogger module
34
9
  import { AnsiLogger, stringify, debugStringify, CYAN, db, er, nf, rs, UNDERLINE, UNDERLINEOFF, wr, YELLOW } from './logger/export.js';
35
- // Matterbridge
36
10
  import { createZip, deepCopy, isValidNumber, isValidObject, isValidString } from './utils/export.js';
37
11
  import { plg } from './matterbridgeTypes.js';
38
12
  import { hasParameter } from './utils/export.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
- * Websocket message ID indicating a cpu update.
56
- * @constant {number}
57
- */
58
16
  export const WS_ID_CPU_UPDATE = 3;
59
- /**
60
- * Websocket message ID indicating a memory update.
61
- * @constant {number}
62
- */
63
17
  export const WS_ID_MEMORY_UPDATE = 4;
64
- /**
65
- * Websocket message ID indicating an uptime update.
66
- * @constant {number}
67
- */
68
18
  export const WS_ID_UPTIME_UPDATE = 5;
69
- /**
70
- * Websocket message ID indicating a memory update.
71
- * @constant {number}
72
- */
73
19
  export const WS_ID_SNACKBAR = 6;
74
- /**
75
- * Websocket message ID indicating a shelly system update.
76
- * check:
77
- * curl -k http://127.0.0.1:8101/api/updates/sys/check
78
- * perform:
79
- * curl -k http://127.0.0.1:8101/api/updates/sys/perform
80
- * @constant {number}
81
- */
82
20
  export const WS_ID_SHELLY_SYS_UPDATE = 100;
83
- /**
84
- * Websocket message ID indicating a shelly main update.
85
- * check:
86
- * curl -k http://127.0.0.1:8101/api/updates/main/check
87
- * perform:
88
- * curl -k http://127.0.0.1:8101/api/updates/main/perform
89
- * @constant {number}
90
- */
91
21
  export const WS_ID_SHELLY_MAIN_UPDATE = 101;
92
- /**
93
- * Initializes the frontend of Matterbridge.
94
- *
95
- * @param port The port number to run the frontend server on. Default is 8283.
96
- */
97
22
  export class Frontend {
98
23
  matterbridge;
99
24
  log;
@@ -110,7 +35,7 @@ export class Frontend {
110
35
  memoryTimeout;
111
36
  constructor(matterbridge) {
112
37
  this.matterbridge = matterbridge;
113
- this.log = new AnsiLogger({ logName: 'Frontend', logTimestampFormat: 4 /* TimestampFormat.TIME_MILLIS */, logLevel: hasParameter('debug') ? "debug" /* LogLevel.DEBUG */ : "info" /* LogLevel.INFO */ });
38
+ this.log = new AnsiLogger({ logName: 'Frontend', logTimestampFormat: 4, logLevel: hasParameter('debug') ? "debug" : "info" });
114
39
  }
115
40
  set logLevel(logLevel) {
116
41
  this.log.logLevel = logLevel;
@@ -118,21 +43,10 @@ export class Frontend {
118
43
  async start(port = 8283) {
119
44
  this.port = port;
120
45
  this.log.debug(`Initializing the frontend ${hasParameter('ssl') ? 'https' : 'http'} server on port ${YELLOW}${this.port}${db}`);
121
- // Create the express app that serves the frontend
122
46
  this.expressApp = express();
123
- // Log all requests to the server for debugging
124
- /*
125
- this.expressApp.use((req, res, next) => {
126
- this.log.debug(`Received request on expressApp: ${req.method} ${req.url}`);
127
- next();
128
- });
129
- */
130
- // Serve static files from '/static' endpoint
131
47
  this.expressApp.use(express.static(path.join(this.matterbridge.rootDirectory, 'frontend/build')));
132
48
  if (!hasParameter('ssl')) {
133
- // Create an HTTP server and attach the express app
134
49
  this.httpServer = createServer(this.expressApp);
135
- // Listen on the specified port
136
50
  if (hasParameter('ingress')) {
137
51
  this.httpServer.listen(this.port, '0.0.0.0', () => {
138
52
  this.log.info(`The frontend http server is listening on ${UNDERLINE}http://0.0.0.0:${this.port}${UNDERLINEOFF}${rs}`);
@@ -146,7 +60,6 @@ export class Frontend {
146
60
  this.log.info(`The frontend http server is listening on ${UNDERLINE}http://[${this.matterbridge.systemInformation.ipv6Address}]:${this.port}${UNDERLINEOFF}${rs}`);
147
61
  });
148
62
  }
149
- // eslint-disable-next-line @typescript-eslint/no-explicit-any
150
63
  this.httpServer.on('error', (error) => {
151
64
  this.log.error(`Frontend http server error listening on ${this.port}`);
152
65
  switch (error.code) {
@@ -162,7 +75,6 @@ export class Frontend {
162
75
  });
163
76
  }
164
77
  else {
165
- // Load the SSL certificate, the private key and optionally the CA certificate
166
78
  let cert;
167
79
  try {
168
80
  cert = await fs.readFile(path.join(this.matterbridge.matterbridgeDirectory, 'certs/cert.pem'), 'utf8');
@@ -190,9 +102,7 @@ export class Frontend {
190
102
  this.log.info(`CA certificate file ${path.join(this.matterbridge.matterbridgeDirectory, 'certs/ca.pem')} not loaded: ${error}`);
191
103
  }
192
104
  const serverOptions = { cert, key, ca };
193
- // Create an HTTPS server with the SSL certificate and private key (ca is optional) and attach the express app
194
105
  this.httpsServer = https.createServer(serverOptions, this.expressApp);
195
- // Listen on the specified port
196
106
  if (hasParameter('ingress')) {
197
107
  this.httpsServer.listen(this.port, '0.0.0.0', () => {
198
108
  this.log.info(`The frontend https server is listening on ${UNDERLINE}https://0.0.0.0:${this.port}${UNDERLINEOFF}${rs}`);
@@ -206,7 +116,6 @@ export class Frontend {
206
116
  this.log.info(`The frontend https server is listening on ${UNDERLINE}https://[${this.matterbridge.systemInformation.ipv6Address}]:${this.port}${UNDERLINEOFF}${rs}`);
207
117
  });
208
118
  }
209
- // eslint-disable-next-line @typescript-eslint/no-explicit-any
210
119
  this.httpsServer.on('error', (error) => {
211
120
  this.log.error(`Frontend https server error listening on ${this.port}`);
212
121
  switch (error.code) {
@@ -223,18 +132,16 @@ export class Frontend {
223
132
  }
224
133
  if (this.initializeError)
225
134
  return;
226
- // Create a WebSocket server and attach it to the http or https server
227
135
  const wssPort = this.port;
228
136
  const wssHost = hasParameter('ssl') ? `wss://${this.matterbridge.systemInformation.ipv4Address}:${wssPort}` : `ws://${this.matterbridge.systemInformation.ipv4Address}:${wssPort}`;
229
137
  this.webSocketServer = new WebSocketServer(hasParameter('ssl') ? { server: this.httpsServer } : { server: this.httpServer });
230
138
  this.webSocketServer.on('connection', (ws, request) => {
231
139
  const clientIp = request.socket.remoteAddress;
232
- // Set the global logger callback for the WebSocketServer
233
- let callbackLogLevel = "notice" /* LogLevel.NOTICE */;
234
- if (this.matterbridge.matterbridgeInformation.loggerLevel === "info" /* LogLevel.INFO */ || this.matterbridge.matterbridgeInformation.matterLoggerLevel === MatterLogLevel.INFO)
235
- callbackLogLevel = "info" /* LogLevel.INFO */;
236
- if (this.matterbridge.matterbridgeInformation.loggerLevel === "debug" /* LogLevel.DEBUG */ || this.matterbridge.matterbridgeInformation.matterLoggerLevel === MatterLogLevel.DEBUG)
237
- callbackLogLevel = "debug" /* LogLevel.DEBUG */;
140
+ let callbackLogLevel = "notice";
141
+ if (this.matterbridge.matterbridgeInformation.loggerLevel === "info" || this.matterbridge.matterbridgeInformation.matterLoggerLevel === MatterLogLevel.INFO)
142
+ callbackLogLevel = "info";
143
+ if (this.matterbridge.matterbridgeInformation.loggerLevel === "debug" || this.matterbridge.matterbridgeInformation.matterLoggerLevel === MatterLogLevel.DEBUG)
144
+ callbackLogLevel = "debug";
238
145
  AnsiLogger.setGlobalCallback(this.wssSendMessage.bind(this), callbackLogLevel);
239
146
  this.log.debug(`WebSocketServer logger global callback set to ${callbackLogLevel}`);
240
147
  this.log.info(`WebSocketServer client "${clientIp}" connected to Matterbridge`);
@@ -268,7 +175,6 @@ export class Frontend {
268
175
  this.webSocketServer.on('error', (ws, error) => {
269
176
  this.log.error(`WebSocketServer error: ${error}`);
270
177
  });
271
- // Subscribe to cli events
272
178
  const { cliEmitter } = await import('./cli.js');
273
179
  cliEmitter.on('uptime', (systemUptime, processUptime) => {
274
180
  this.wssSendUptimeUpdate(systemUptime, processUptime);
@@ -279,7 +185,6 @@ export class Frontend {
279
185
  cliEmitter.on('cpu', (cpuUsage) => {
280
186
  this.wssSendCpuUpdate(cpuUsage);
281
187
  });
282
- // Endpoint to validate login code
283
188
  this.expressApp.post('/api/login', express.json(), async (req, res) => {
284
189
  const { password } = req.body;
285
190
  this.log.debug('The frontend sent /api/login', password);
@@ -298,27 +203,23 @@ export class Frontend {
298
203
  this.log.warn('/api/login error wrong password');
299
204
  res.json({ valid: false });
300
205
  }
301
- // eslint-disable-next-line @typescript-eslint/no-unused-vars
302
206
  }
303
207
  catch (error) {
304
208
  this.log.error('/api/login error getting password');
305
209
  res.json({ valid: false });
306
210
  }
307
211
  });
308
- // Endpoint to provide health check
309
212
  this.expressApp.get('/health', (req, res) => {
310
213
  this.log.debug('Express received /health');
311
214
  const healthStatus = {
312
- status: 'ok', // Indicate service is healthy
313
- uptime: process.uptime(), // Server uptime in seconds
314
- timestamp: new Date().toISOString(), // Current timestamp
215
+ status: 'ok',
216
+ uptime: process.uptime(),
217
+ timestamp: new Date().toISOString(),
315
218
  };
316
219
  res.status(200).json(healthStatus);
317
220
  });
318
- // Endpoint to provide memory usage details
319
221
  this.expressApp.get('/memory', async (req, res) => {
320
222
  this.log.debug('Express received /memory');
321
- // Memory usage from process
322
223
  const memoryUsageRaw = process.memoryUsage();
323
224
  const memoryUsage = {
324
225
  rss: this.formatMemoryUsage(memoryUsageRaw.rss),
@@ -327,13 +228,10 @@ export class Frontend {
327
228
  external: this.formatMemoryUsage(memoryUsageRaw.external),
328
229
  arrayBuffers: this.formatMemoryUsage(memoryUsageRaw.arrayBuffers),
329
230
  };
330
- // V8 heap statistics
331
231
  const { default: v8 } = await import('node:v8');
332
232
  const heapStatsRaw = v8.getHeapStatistics();
333
233
  const heapSpacesRaw = v8.getHeapSpaceStatistics();
334
- // Format heapStats
335
234
  const heapStats = Object.fromEntries(Object.entries(heapStatsRaw).map(([key, value]) => [key, this.formatMemoryUsage(value)]));
336
- // Format heapSpaces
337
235
  const heapSpaces = heapSpacesRaw.map((space) => ({
338
236
  ...space,
339
237
  space_size: this.formatMemoryUsage(space.space_size),
@@ -351,7 +249,6 @@ export class Frontend {
351
249
  };
352
250
  res.status(200).json(memoryReport);
353
251
  });
354
- // Endpoint to start advertising the server node
355
252
  this.expressApp.get('/api/advertise', express.json(), async (req, res) => {
356
253
  const pairingCodes = await this.matterbridge.advertiseServerNode(this.matterbridge.serverNode);
357
254
  if (pairingCodes) {
@@ -362,22 +259,18 @@ export class Frontend {
362
259
  res.status(500).json({ error: 'Failed to generate pairing codes' });
363
260
  }
364
261
  });
365
- // Endpoint to provide settings
366
262
  this.expressApp.get('/api/settings', express.json(), async (req, res) => {
367
263
  this.log.debug('The frontend sent /api/settings');
368
264
  res.json(await this.getApiSettings());
369
265
  });
370
- // Endpoint to provide plugins
371
266
  this.expressApp.get('/api/plugins', async (req, res) => {
372
267
  this.log.debug('The frontend sent /api/plugins');
373
268
  res.json(this.getBaseRegisteredPlugins());
374
269
  });
375
- // Endpoint to provide devices
376
270
  this.expressApp.get('/api/devices', (req, res) => {
377
271
  this.log.debug('The frontend sent /api/devices');
378
272
  const devices = [];
379
273
  this.matterbridge.devices.forEach(async (device) => {
380
- // Check if the device has the required properties
381
274
  if (!device.plugin || !device.name || !device.deviceName || !device.serialNumber || !device.uniqueId || !device.lifecycle.isReady)
382
275
  return;
383
276
  const cluster = this.getClusterTextFromDevice(device);
@@ -395,7 +288,6 @@ export class Frontend {
395
288
  });
396
289
  res.json(devices);
397
290
  });
398
- // Endpoint to provide the cluster servers of the devices
399
291
  this.expressApp.get('/api/devices_clusters/:selectedPluginName/:selectedDeviceEndpoint', (req, res) => {
400
292
  const selectedPluginName = req.params.selectedPluginName;
401
293
  const selectedDeviceEndpoint = parseInt(req.params.selectedDeviceEndpoint, 10);
@@ -468,7 +360,6 @@ export class Frontend {
468
360
  });
469
361
  res.json(data);
470
362
  });
471
- // Endpoint to view the log
472
363
  this.expressApp.get('/api/view-log', async (req, res) => {
473
364
  this.log.debug('The frontend sent /api/log');
474
365
  try {
@@ -481,12 +372,10 @@ export class Frontend {
481
372
  res.status(500).send('Error reading log file');
482
373
  }
483
374
  });
484
- // Endpoint to download the matterbridge log
485
375
  this.expressApp.get('/api/download-mblog', async (req, res) => {
486
376
  this.log.debug('The frontend sent /api/download-mblog');
487
377
  try {
488
378
  await fs.access(path.join(this.matterbridge.matterbridgeDirectory, this.matterbridge.matterbrideLoggerFile), fs.constants.F_OK);
489
- // eslint-disable-next-line @typescript-eslint/no-unused-vars
490
379
  }
491
380
  catch (error) {
492
381
  fs.appendFile(path.join(this.matterbridge.matterbridgeDirectory, this.matterbridge.matterbrideLoggerFile), 'Enable the log on file in the settings to enable the file logger');
@@ -498,12 +387,10 @@ export class Frontend {
498
387
  }
499
388
  });
500
389
  });
501
- // Endpoint to download the matter log
502
390
  this.expressApp.get('/api/download-mjlog', async (req, res) => {
503
391
  this.log.debug('The frontend sent /api/download-mjlog');
504
392
  try {
505
393
  await fs.access(path.join(this.matterbridge.matterbridgeDirectory, this.matterbridge.matterLoggerFile), fs.constants.F_OK);
506
- // eslint-disable-next-line @typescript-eslint/no-unused-vars
507
394
  }
508
395
  catch (error) {
509
396
  fs.appendFile(path.join(this.matterbridge.matterbridgeDirectory, this.matterbridge.matterLoggerFile), 'Enable the log on file in the settings to enable the file logger');
@@ -515,7 +402,6 @@ export class Frontend {
515
402
  }
516
403
  });
517
404
  });
518
- // Endpoint to download the matter storage file
519
405
  this.expressApp.get('/api/download-mjstorage', async (req, res) => {
520
406
  this.log.debug('The frontend sent /api/download-mjstorage');
521
407
  await createZip(path.join(os.tmpdir(), `matterbridge.${this.matterbridge.matterStorageName}.zip`), path.join(this.matterbridge.matterbridgeDirectory, this.matterbridge.matterStorageName));
@@ -526,7 +412,6 @@ export class Frontend {
526
412
  }
527
413
  });
528
414
  });
529
- // Endpoint to download the matterbridge storage directory
530
415
  this.expressApp.get('/api/download-mbstorage', async (req, res) => {
531
416
  this.log.debug('The frontend sent /api/download-mbstorage');
532
417
  await createZip(path.join(os.tmpdir(), `matterbridge.${this.matterbridge.nodeStorageName}.zip`), path.join(this.matterbridge.matterbridgeDirectory, this.matterbridge.nodeStorageName));
@@ -537,7 +422,6 @@ export class Frontend {
537
422
  }
538
423
  });
539
424
  });
540
- // Endpoint to download the matterbridge plugin directory
541
425
  this.expressApp.get('/api/download-pluginstorage', async (req, res) => {
542
426
  this.log.debug('The frontend sent /api/download-pluginstorage');
543
427
  await createZip(path.join(os.tmpdir(), `matterbridge.pluginstorage.zip`), this.matterbridge.matterbridgePluginDirectory);
@@ -548,11 +432,9 @@ export class Frontend {
548
432
  }
549
433
  });
550
434
  });
551
- // Endpoint to download the matterbridge plugin config files
552
435
  this.expressApp.get('/api/download-pluginconfig', async (req, res) => {
553
436
  this.log.debug('The frontend sent /api/download-pluginconfig');
554
437
  await createZip(path.join(os.tmpdir(), `matterbridge.pluginconfig.zip`), path.relative(process.cwd(), path.join(this.matterbridge.matterbridgeDirectory, '*.config.json')));
555
- // 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')));
556
438
  res.download(path.join(os.tmpdir(), `matterbridge.pluginconfig.zip`), `matterbridge.pluginconfig.zip`, (error) => {
557
439
  if (error) {
558
440
  this.log.error(`Error downloading file matterbridge.pluginstorage.zip: ${error instanceof Error ? error.message : error}`);
@@ -560,7 +442,6 @@ export class Frontend {
560
442
  }
561
443
  });
562
444
  });
563
- // Endpoint to download the matterbridge plugin config files
564
445
  this.expressApp.get('/api/download-backup', async (req, res) => {
565
446
  this.log.debug('The frontend sent /api/download-backup');
566
447
  res.download(path.join(os.tmpdir(), `matterbridge.backup.zip`), `matterbridge.backup.zip`, (error) => {
@@ -570,7 +451,6 @@ export class Frontend {
570
451
  }
571
452
  });
572
453
  });
573
- // Endpoint to receive commands
574
454
  this.expressApp.post('/api/command/:command/:param', express.json(), async (req, res) => {
575
455
  const command = req.params.command;
576
456
  let param = req.params.param;
@@ -580,15 +460,13 @@ export class Frontend {
580
460
  return;
581
461
  }
582
462
  this.log.debug(`Received frontend command: ${command}:${param}`);
583
- // Handle the command setpassword from Settings
584
463
  if (command === 'setpassword') {
585
- const password = param.slice(1, -1); // Remove the first and last characters
464
+ const password = param.slice(1, -1);
586
465
  this.log.debug('setpassword', param, password);
587
466
  await this.matterbridge.nodeContext?.set('password', password);
588
467
  res.json({ message: 'Command received' });
589
468
  return;
590
469
  }
591
- // Handle the command setbridgemode from Settings
592
470
  if (command === 'setbridgemode') {
593
471
  this.log.debug(`setbridgemode: ${param}`);
594
472
  this.wssSendRestartRequired();
@@ -596,7 +474,6 @@ export class Frontend {
596
474
  res.json({ message: 'Command received' });
597
475
  return;
598
476
  }
599
- // Handle the command backup from Settings
600
477
  if (command === 'backup') {
601
478
  this.log.notice(`Prepairing the backup...`);
602
479
  await createZip(path.join(os.tmpdir(), `matterbridge.backup.zip`), path.join(this.matterbridge.matterbridgeDirectory), path.join(this.matterbridge.matterbridgePluginDirectory));
@@ -605,33 +482,31 @@ export class Frontend {
605
482
  res.json({ message: 'Command received' });
606
483
  return;
607
484
  }
608
- // Handle the command setmbloglevel from Settings
609
485
  if (command === 'setmbloglevel') {
610
486
  this.log.debug('Matterbridge log level:', param);
611
487
  if (param === 'Debug') {
612
- this.log.logLevel = "debug" /* LogLevel.DEBUG */;
488
+ this.log.logLevel = "debug";
613
489
  }
614
490
  else if (param === 'Info') {
615
- this.log.logLevel = "info" /* LogLevel.INFO */;
491
+ this.log.logLevel = "info";
616
492
  }
617
493
  else if (param === 'Notice') {
618
- this.log.logLevel = "notice" /* LogLevel.NOTICE */;
494
+ this.log.logLevel = "notice";
619
495
  }
620
496
  else if (param === 'Warn') {
621
- this.log.logLevel = "warn" /* LogLevel.WARN */;
497
+ this.log.logLevel = "warn";
622
498
  }
623
499
  else if (param === 'Error') {
624
- this.log.logLevel = "error" /* LogLevel.ERROR */;
500
+ this.log.logLevel = "error";
625
501
  }
626
502
  else if (param === 'Fatal') {
627
- this.log.logLevel = "fatal" /* LogLevel.FATAL */;
503
+ this.log.logLevel = "fatal";
628
504
  }
629
505
  await this.matterbridge.nodeContext?.set('matterbridgeLogLevel', this.log.logLevel);
630
506
  await this.matterbridge.setLogLevel(this.log.logLevel);
631
507
  res.json({ message: 'Command received' });
632
508
  return;
633
509
  }
634
- // Handle the command setmbloglevel from Settings
635
510
  if (command === 'setmjloglevel') {
636
511
  this.log.debug('Matter.js log level:', param);
637
512
  if (param === 'Debug') {
@@ -656,34 +531,30 @@ export class Frontend {
656
531
  res.json({ message: 'Command received' });
657
532
  return;
658
533
  }
659
- // Handle the command setmdnsinterface from Settings
660
534
  if (command === 'setmdnsinterface') {
661
- param = param.slice(1, -1); // Remove the first and last characters *mdns*
535
+ param = param.slice(1, -1);
662
536
  this.matterbridge.matterbridgeInformation.mattermdnsinterface = param;
663
537
  this.log.debug('Matter.js mdns interface:', param === '' ? 'All interfaces' : param);
664
538
  await this.matterbridge.nodeContext?.set('mattermdnsinterface', param);
665
539
  res.json({ message: 'Command received' });
666
540
  return;
667
541
  }
668
- // Handle the command setipv4address from Settings
669
542
  if (command === 'setipv4address') {
670
- param = param.slice(1, -1); // Remove the first and last characters *ip*
543
+ param = param.slice(1, -1);
671
544
  this.matterbridge.matterbridgeInformation.matteripv4address = param;
672
545
  this.log.debug('Matter.js ipv4 address:', param === '' ? 'All ipv4 addresses' : param);
673
546
  await this.matterbridge.nodeContext?.set('matteripv4address', param);
674
547
  res.json({ message: 'Command received' });
675
548
  return;
676
549
  }
677
- // Handle the command setipv6address from Settings
678
550
  if (command === 'setipv6address') {
679
- param = param.slice(1, -1); // Remove the first and last characters *ip*
551
+ param = param.slice(1, -1);
680
552
  this.matterbridge.matterbridgeInformation.matteripv6address = param;
681
553
  this.log.debug('Matter.js ipv6 address:', param === '' ? 'All ipv6 addresses' : param);
682
554
  await this.matterbridge.nodeContext?.set('matteripv6address', param);
683
555
  res.json({ message: 'Command received' });
684
556
  return;
685
557
  }
686
- // Handle the command setmatterport from Settings
687
558
  if (command === 'setmatterport') {
688
559
  const port = Math.min(Math.max(parseInt(param), 5540), 5560);
689
560
  this.matterbridge.matterbridgeInformation.matterPort = port;
@@ -692,7 +563,6 @@ export class Frontend {
692
563
  res.json({ message: 'Command received' });
693
564
  return;
694
565
  }
695
- // Handle the command setmatterdiscriminator from Settings
696
566
  if (command === 'setmatterdiscriminator') {
697
567
  const discriminator = Math.min(Math.max(parseInt(param), 1000), 4095);
698
568
  this.matterbridge.matterbridgeInformation.matterDiscriminator = discriminator;
@@ -701,7 +571,6 @@ export class Frontend {
701
571
  res.json({ message: 'Command received' });
702
572
  return;
703
573
  }
704
- // Handle the command setmatterpasscode from Settings
705
574
  if (command === 'setmatterpasscode') {
706
575
  const passcode = Math.min(Math.max(parseInt(param), 10000000), 90000000);
707
576
  this.matterbridge.matterbridgeInformation.matterPasscode = passcode;
@@ -710,20 +579,17 @@ export class Frontend {
710
579
  res.json({ message: 'Command received' });
711
580
  return;
712
581
  }
713
- // Handle the command setmbloglevel from Settings
714
582
  if (command === 'setmblogfile') {
715
583
  this.log.debug('Matterbridge file log:', param);
716
584
  this.matterbridge.matterbridgeInformation.fileLogger = param === 'true';
717
585
  await this.matterbridge.nodeContext?.set('matterbridgeFileLog', param === 'true');
718
- // Create the file logger for matterbridge
719
586
  if (param === 'true')
720
- AnsiLogger.setGlobalLogfile(path.join(this.matterbridge.matterbridgeDirectory, this.matterbridge.matterbrideLoggerFile), "debug" /* LogLevel.DEBUG */, true);
587
+ AnsiLogger.setGlobalLogfile(path.join(this.matterbridge.matterbridgeDirectory, this.matterbridge.matterbrideLoggerFile), "debug", true);
721
588
  else
722
589
  AnsiLogger.setGlobalLogfile(undefined);
723
590
  res.json({ message: 'Command received' });
724
591
  return;
725
592
  }
726
- // Handle the command setmbloglevel from Settings
727
593
  if (command === 'setmjlogfile') {
728
594
  this.log.debug('Matter file log:', param);
729
595
  this.matterbridge.matterbridgeInformation.matterFileLogger = param === 'true';
@@ -750,48 +616,40 @@ export class Frontend {
750
616
  res.json({ message: 'Command received' });
751
617
  return;
752
618
  }
753
- // Handle the command unregister from Settings
754
619
  if (command === 'unregister') {
755
620
  await this.matterbridge.unregisterAndShutdownProcess();
756
621
  res.json({ message: 'Command received' });
757
622
  return;
758
623
  }
759
- // Handle the command reset from Settings
760
624
  if (command === 'reset') {
761
625
  await this.matterbridge.shutdownProcessAndReset();
762
626
  res.json({ message: 'Command received' });
763
627
  return;
764
628
  }
765
- // Handle the command factoryreset from Settings
766
629
  if (command === 'factoryreset') {
767
630
  await this.matterbridge.shutdownProcessAndFactoryReset();
768
631
  res.json({ message: 'Command received' });
769
632
  return;
770
633
  }
771
- // Handle the command shutdown from Header
772
634
  if (command === 'shutdown') {
773
635
  await this.matterbridge.shutdownProcess();
774
636
  res.json({ message: 'Command received' });
775
637
  return;
776
638
  }
777
- // Handle the command restart from Header
778
639
  if (command === 'restart') {
779
640
  await this.matterbridge.restartProcess();
780
641
  res.json({ message: 'Command received' });
781
642
  return;
782
643
  }
783
- // Handle the command update from Header
784
644
  if (command === 'update') {
785
645
  await this.matterbridge.updateProcess();
786
646
  this.wssSendRestartRequired();
787
647
  res.json({ message: 'Command received' });
788
648
  return;
789
649
  }
790
- // Handle the command saveconfig from Home
791
650
  if (command === 'saveconfig') {
792
651
  param = param.replace(/\*/g, '\\');
793
652
  this.log.info(`Saving config for plugin ${plg}${param}${nf}...`);
794
- // console.log('Req.body:', JSON.stringify(req.body, null, 2));
795
653
  if (!this.matterbridge.plugins.has(param)) {
796
654
  this.log.warn(`Plugin ${plg}${param}${wr} not found in matterbridge`);
797
655
  }
@@ -806,7 +664,6 @@ export class Frontend {
806
664
  res.json({ message: 'Command received' });
807
665
  return;
808
666
  }
809
- // Handle the command installplugin from Home
810
667
  if (command === 'installplugin') {
811
668
  param = param.replace(/\*/g, '\\');
812
669
  this.log.info(`Installing plugin ${plg}${param}${nf}...`);
@@ -815,7 +672,6 @@ export class Frontend {
815
672
  await this.matterbridge.spawnCommand('npm', ['install', '-g', param, '--omit=dev', '--verbose']);
816
673
  this.log.info(`Plugin ${plg}${param}${nf} installed. Full restart required.`);
817
674
  this.wssSendSnackbarMessage(`Installed package ${param}`);
818
- // eslint-disable-next-line @typescript-eslint/no-unused-vars
819
675
  }
820
676
  catch (error) {
821
677
  this.log.error(`Error installing plugin ${plg}${param}${er}`);
@@ -824,21 +680,16 @@ export class Frontend {
824
680
  this.wssSendSnackbarMessage(`Restart required`, 0);
825
681
  this.wssSendRestartRequired();
826
682
  param = param.split('@')[0];
827
- // Also add the plugin to matterbridge so no return!
828
683
  if (param === 'matterbridge') {
829
- // 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
830
684
  res.json({ message: 'Command received' });
831
685
  return;
832
686
  }
833
687
  }
834
- // Handle the command addplugin from Home
835
688
  if (command === 'addplugin' || command === 'installplugin') {
836
689
  param = param.replace(/\*/g, '\\');
837
690
  const plugin = await this.matterbridge.plugins.add(param);
838
691
  if (plugin) {
839
692
  if (this.matterbridge.bridgeMode === 'childbridge') {
840
- // 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
841
- // eslint-disable-next-line @typescript-eslint/no-explicit-any
842
693
  this.matterbridge.createDynamicPlugin(plugin, true);
843
694
  }
844
695
  this.matterbridge.plugins.load(plugin, true, 'The plugin has been added', true).then(() => {
@@ -848,21 +699,19 @@ export class Frontend {
848
699
  res.json({ message: 'Command received' });
849
700
  return;
850
701
  }
851
- // Handle the command removeplugin from Home
852
702
  if (command === 'removeplugin') {
853
703
  if (!this.matterbridge.plugins.has(param)) {
854
704
  this.log.warn(`Plugin ${plg}${param}${wr} not found in matterbridge`);
855
705
  }
856
706
  else {
857
707
  const plugin = this.matterbridge.plugins.get(param);
858
- await this.matterbridge.plugins.shutdown(plugin, 'The plugin has been removed.', true); // This will also close the server node in childbridge mode
708
+ await this.matterbridge.plugins.shutdown(plugin, 'The plugin has been removed.', true);
859
709
  await this.matterbridge.plugins.remove(param);
860
710
  }
861
711
  res.json({ message: 'Command received' });
862
712
  this.wssSendRefreshRequired();
863
713
  return;
864
714
  }
865
- // Handle the command enableplugin from Home
866
715
  if (command === 'enableplugin') {
867
716
  if (!this.matterbridge.plugins.has(param)) {
868
717
  this.log.warn(`Plugin ${plg}${param}${wr} not found in matterbridge`);
@@ -880,7 +729,6 @@ export class Frontend {
880
729
  plugin.addedDevices = undefined;
881
730
  await this.matterbridge.plugins.enable(param);
882
731
  if (this.matterbridge.bridgeMode === 'childbridge' && plugin.type === 'DynamicPlatform') {
883
- // eslint-disable-next-line @typescript-eslint/no-explicit-any
884
732
  this.matterbridge.createDynamicPlugin(plugin, true);
885
733
  }
886
734
  this.matterbridge.plugins.load(plugin, true, 'The plugin has been enabled', true).then(() => {
@@ -892,7 +740,6 @@ export class Frontend {
892
740
  this.wssSendRefreshRequired();
893
741
  return;
894
742
  }
895
- // Handle the command disableplugin from Home
896
743
  if (command === 'disableplugin') {
897
744
  if (!this.matterbridge.plugins.has(param)) {
898
745
  this.log.warn(`Plugin ${plg}${param}${wr} not found in matterbridge`);
@@ -900,7 +747,7 @@ export class Frontend {
900
747
  else {
901
748
  const plugin = this.matterbridge.plugins.get(param);
902
749
  if (plugin && plugin.enabled) {
903
- await this.matterbridge.plugins.shutdown(plugin, 'The plugin has been disabled.', true); // This will also close the server node in childbridge mode
750
+ await this.matterbridge.plugins.shutdown(plugin, 'The plugin has been disabled.', true);
904
751
  await this.matterbridge.plugins.disable(param);
905
752
  }
906
753
  }
@@ -909,7 +756,6 @@ export class Frontend {
909
756
  return;
910
757
  }
911
758
  });
912
- // Fallback for routing (must be the last route)
913
759
  this.expressApp.get('*', (req, res) => {
914
760
  this.log.debug('The frontend sent:', req.url);
915
761
  this.log.debug('Response send file:', path.join(this.matterbridge.rootDirectory, 'frontend/build/index.html'));
@@ -918,29 +764,24 @@ export class Frontend {
918
764
  this.log.debug(`Frontend initialized on port ${YELLOW}${this.port}${db} static ${UNDERLINE}${path.join(this.matterbridge.rootDirectory, 'frontend/build')}${UNDERLINEOFF}${rs}`);
919
765
  }
920
766
  async stop() {
921
- // Close the http server
922
767
  if (this.httpServer) {
923
768
  this.httpServer.close();
924
769
  this.httpServer.removeAllListeners();
925
770
  this.httpServer = undefined;
926
771
  this.log.debug('Frontend http server closed successfully');
927
772
  }
928
- // Close the https server
929
773
  if (this.httpsServer) {
930
774
  this.httpsServer.close();
931
775
  this.httpsServer.removeAllListeners();
932
776
  this.httpsServer = undefined;
933
777
  this.log.debug('Frontend https server closed successfully');
934
778
  }
935
- // Remove listeners from the express app
936
779
  if (this.expressApp) {
937
780
  this.expressApp.removeAllListeners();
938
781
  this.expressApp = undefined;
939
782
  this.log.debug('Frontend app closed successfully');
940
783
  }
941
- // Close the WebSocket server
942
784
  if (this.webSocketServer) {
943
- // Close all active connections
944
785
  this.webSocketServer.clients.forEach((client) => {
945
786
  if (client.readyState === WebSocket.OPEN) {
946
787
  client.close();
@@ -957,7 +798,6 @@ export class Frontend {
957
798
  this.webSocketServer = undefined;
958
799
  }
959
800
  }
960
- // Function to format bytes to KB, MB, or GB
961
801
  formatMemoryUsage = (bytes) => {
962
802
  if (bytes >= 1024 ** 3) {
963
803
  return `${(bytes / 1024 ** 3).toFixed(2)} GB`;
@@ -969,7 +809,6 @@ export class Frontend {
969
809
  return `${(bytes / 1024).toFixed(2)} KB`;
970
810
  }
971
811
  };
972
- // Function to format system uptime with only the most significant unit
973
812
  formatOsUpTime = (seconds) => {
974
813
  if (seconds >= 86400) {
975
814
  const days = Math.floor(seconds / 86400);
@@ -985,13 +824,8 @@ export class Frontend {
985
824
  }
986
825
  return `${seconds} second${seconds !== 1 ? 's' : ''}`;
987
826
  };
988
- /**
989
- * Retrieves the api settings data.
990
- * @returns {Promise<object>} A promise that resolve in the api settings object.
991
- */
992
827
  async getApiSettings() {
993
828
  const { lastCpuUsage } = await import('./cli.js');
994
- // Update the system information
995
829
  this.matterbridge.systemInformation.totalMemory = this.formatMemoryUsage(os.totalmem());
996
830
  this.matterbridge.systemInformation.freeMemory = this.formatMemoryUsage(os.freemem());
997
831
  this.matterbridge.systemInformation.systemUptime = this.formatOsUpTime(os.uptime());
@@ -1000,7 +834,6 @@ export class Frontend {
1000
834
  this.matterbridge.systemInformation.rss = this.formatMemoryUsage(process.memoryUsage().rss);
1001
835
  this.matterbridge.systemInformation.heapTotal = this.formatMemoryUsage(process.memoryUsage().heapTotal);
1002
836
  this.matterbridge.systemInformation.heapUsed = this.formatMemoryUsage(process.memoryUsage().heapUsed);
1003
- // Update the matterbridge information
1004
837
  this.matterbridge.matterbridgeInformation.bridgeMode = this.matterbridge.bridgeMode;
1005
838
  this.matterbridge.matterbridgeInformation.restartMode = this.matterbridge.restartMode;
1006
839
  this.matterbridge.matterbridgeInformation.loggerLevel = this.matterbridge.log.logLevel;
@@ -1019,11 +852,6 @@ export class Frontend {
1019
852
  this.matterbridge.matterbridgeInformation.profile = this.matterbridge.profile;
1020
853
  return { systemInformation: this.matterbridge.systemInformation, matterbridgeInformation: this.matterbridge.matterbridgeInformation };
1021
854
  }
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
855
  getClusterTextFromDevice(device) {
1028
856
  const getAttribute = (device, cluster, attribute) => {
1029
857
  let value = undefined;
@@ -1062,7 +890,6 @@ export class Frontend {
1062
890
  };
1063
891
  let attributes = '';
1064
892
  device.forEachAttribute((clusterName, clusterId, attributeName, attributeId, attributeValue) => {
1065
- // console.log(`${device.deviceName} => Cluster: ${clusterName}-${clusterId} Attribute: ${attributeName}-${attributeId} Value(${typeof attributeValue}): ${attributeValue}`);
1066
893
  if (typeof attributeValue === 'undefined')
1067
894
  return;
1068
895
  if (clusterName === 'onOff' && attributeName === 'onOff')
@@ -1140,13 +967,8 @@ export class Frontend {
1140
967
  if (clusterName === 'userLabel' && attributeName === 'labelList')
1141
968
  attributes += `${getUserLabel(device)} `;
1142
969
  });
1143
- // console.log(`${device.deviceName}.forEachAttribute: ${attributes}`);
1144
970
  return attributes.trimStart().trimEnd();
1145
971
  }
1146
- /**
1147
- * Retrieves the base registered plugins sanitized for res.json().
1148
- * @returns {BaseRegisteredPlugin[]} An array of BaseRegisteredPlugin.
1149
- */
1150
972
  getBaseRegisteredPlugins() {
1151
973
  const baseRegisteredPlugins = [];
1152
974
  for (const plugin of this.matterbridge.plugins) {
@@ -1177,13 +999,6 @@ export class Frontend {
1177
999
  }
1178
1000
  return baseRegisteredPlugins;
1179
1001
  }
1180
- /**
1181
- * Handles incoming websocket messages for the Matterbridge frontend.
1182
- *
1183
- * @param {WebSocket} client - The websocket client that sent the message.
1184
- * @param {WebSocket.RawData} message - The raw data of the message received from the client.
1185
- * @returns {Promise<void>} A promise that resolves when the message has been handled.
1186
- */
1187
1002
  async wsMessageHandler(client, message) {
1188
1003
  let data;
1189
1004
  try {
@@ -1324,10 +1139,8 @@ export class Frontend {
1324
1139
  else if (data.method === '/api/devices') {
1325
1140
  const devices = [];
1326
1141
  this.matterbridge.devices.forEach(async (device) => {
1327
- // Filter by pluginName if provided
1328
1142
  if (data.params.pluginName && data.params.pluginName !== device.plugin)
1329
1143
  return;
1330
- // Check if the device has the required properties
1331
1144
  if (!device.plugin || !device.name || !device.deviceName || !device.serialNumber || !device.uniqueId || !device.lifecycle.isReady)
1332
1145
  return;
1333
1146
  const cluster = this.getClusterTextFromDevice(device);
@@ -1410,7 +1223,6 @@ export class Frontend {
1410
1223
  });
1411
1224
  endpointServer.getChildEndpoints().forEach((childEndpoint) => {
1412
1225
  deviceTypes = [];
1413
- // eslint-disable-next-line @typescript-eslint/no-explicit-any
1414
1226
  const name = childEndpoint.endpoint?.id;
1415
1227
  const clusterServers = childEndpoint.getAllClusterServers();
1416
1228
  clusterServers.forEach((clusterServer) => {
@@ -1493,139 +1305,85 @@ export class Frontend {
1493
1305
  return;
1494
1306
  }
1495
1307
  }
1496
- /**
1497
- * Sends a WebSocket message to all connected clients. The function is called by AnsiLogger.setGlobalCallback.
1498
- *
1499
- * @param {string} level - The logger level of the message: debug info notice warn error fatal...
1500
- * @param {string} time - The time string of the message
1501
- * @param {string} name - The logger name of the message
1502
- * @param {string} message - The content of the message.
1503
- */
1504
1308
  wssSendMessage(level, time, name, message) {
1505
1309
  if (!level || !time || !name || !message)
1506
1310
  return;
1507
- // Remove ANSI escape codes from the message
1508
- // eslint-disable-next-line no-control-regex
1509
1311
  message = message.replace(/\x1B\[[0-9;]*[m|s|u|K]/g, '');
1510
- // Remove leading asterisks from the message
1511
1312
  message = message.replace(/^\*+/, '');
1512
- // Replace all occurrences of \t and \n
1513
1313
  message = message.replace(/[\t\n]/g, '');
1514
- // Remove non-printable characters
1515
- // eslint-disable-next-line no-control-regex
1516
1314
  message = message.replace(/[\x00-\x1F\x7F]/g, '');
1517
- // Replace all occurrences of \" with "
1518
1315
  message = message.replace(/\\"/g, '"');
1519
- // Define the maximum allowed length for continuous characters without a space
1520
1316
  const maxContinuousLength = 100;
1521
1317
  const keepStartLength = 20;
1522
1318
  const keepEndLength = 20;
1523
- // Split the message into words
1524
1319
  message = message
1525
1320
  .split(' ')
1526
1321
  .map((word) => {
1527
- // If the word length exceeds the max continuous length, insert spaces and truncate
1528
1322
  if (word.length > maxContinuousLength) {
1529
1323
  return word.slice(0, keepStartLength) + ' ... ' + word.slice(-keepEndLength);
1530
1324
  }
1531
1325
  return word;
1532
1326
  })
1533
1327
  .join(' ');
1534
- // Send the message to all connected clients
1535
1328
  this.webSocketServer?.clients.forEach((client) => {
1536
1329
  if (client.readyState === WebSocket.OPEN) {
1537
1330
  client.send(JSON.stringify({ id: WS_ID_LOG, src: 'Matterbridge', level, time, name, message }));
1538
1331
  }
1539
1332
  });
1540
1333
  }
1541
- /**
1542
- * Sends a need to refresh WebSocket message to all connected clients.
1543
- *
1544
- */
1545
1334
  wssSendRefreshRequired() {
1546
1335
  this.log.debug('Sending a refresh required message to all connected clients');
1547
1336
  this.matterbridge.matterbridgeInformation.refreshRequired = true;
1548
- // Send the message to all connected clients
1549
1337
  this.webSocketServer?.clients.forEach((client) => {
1550
1338
  if (client.readyState === WebSocket.OPEN) {
1551
1339
  client.send(JSON.stringify({ id: WS_ID_REFRESH_NEEDED, src: 'Matterbridge', dst: 'Frontend', method: 'refresh_required', params: {} }));
1552
1340
  }
1553
1341
  });
1554
1342
  }
1555
- /**
1556
- * Sends a need to restart WebSocket message to all connected clients.
1557
- *
1558
- */
1559
1343
  wssSendRestartRequired() {
1560
1344
  this.log.debug('Sending a restart required message to all connected clients');
1561
1345
  this.matterbridge.matterbridgeInformation.restartRequired = true;
1562
1346
  this.wssSendSnackbarMessage(`Restart required`, 0);
1563
- // Send the message to all connected clients
1564
1347
  this.webSocketServer?.clients.forEach((client) => {
1565
1348
  if (client.readyState === WebSocket.OPEN) {
1566
1349
  client.send(JSON.stringify({ id: WS_ID_RESTART_NEEDED, src: 'Matterbridge', dst: 'Frontend', method: 'restart_required', params: {} }));
1567
1350
  }
1568
1351
  });
1569
1352
  }
1570
- /**
1571
- * Sends a memory update message to all connected clients.
1572
- *
1573
- */
1574
1353
  wssSendCpuUpdate(cpuUsage) {
1575
1354
  this.log.debug('Sending a cpu update message to all connected clients');
1576
- // Send the message to all connected clients
1577
1355
  this.webSocketServer?.clients.forEach((client) => {
1578
1356
  if (client.readyState === WebSocket.OPEN) {
1579
1357
  client.send(JSON.stringify({ id: WS_ID_CPU_UPDATE, src: 'Matterbridge', dst: 'Frontend', method: 'cpu_update', params: { cpuUsage } }));
1580
1358
  }
1581
1359
  });
1582
1360
  }
1583
- /**
1584
- * Sends a cpu update message to all connected clients.
1585
- *
1586
- */
1587
1361
  wssSendMemoryUpdate(totalMemory, freeMemory, rss, heapTotal, heapUsed, external, arrayBuffers) {
1588
1362
  this.log.debug('Sending a memory update message to all connected clients');
1589
- // Send the message to all connected clients
1590
1363
  this.webSocketServer?.clients.forEach((client) => {
1591
1364
  if (client.readyState === WebSocket.OPEN) {
1592
1365
  client.send(JSON.stringify({ id: WS_ID_MEMORY_UPDATE, src: 'Matterbridge', dst: 'Frontend', method: 'memory_update', params: { totalMemory, freeMemory, rss, heapTotal, heapUsed, external, arrayBuffers } }));
1593
1366
  }
1594
1367
  });
1595
1368
  }
1596
- /**
1597
- * Sends a memory update message to all connected clients.
1598
- *
1599
- */
1600
1369
  wssSendUptimeUpdate(systemUptime, processUptime) {
1601
1370
  this.log.debug('Sending a uptime update message to all connected clients');
1602
- // Send the message to all connected clients
1603
1371
  this.webSocketServer?.clients.forEach((client) => {
1604
1372
  if (client.readyState === WebSocket.OPEN) {
1605
1373
  client.send(JSON.stringify({ id: WS_ID_UPTIME_UPDATE, src: 'Matterbridge', dst: 'Frontend', method: 'uptime_update', params: { systemUptime, processUptime } }));
1606
1374
  }
1607
1375
  });
1608
1376
  }
1609
- /**
1610
- * Sends a cpu update message to all connected clients.
1611
- *
1612
- */
1613
1377
  wssSendSnackbarMessage(message, timeout = 5) {
1614
1378
  this.log.debug('Sending a snackbar message to all connected clients');
1615
- // Send the message to all connected clients
1616
1379
  this.webSocketServer?.clients.forEach((client) => {
1617
1380
  if (client.readyState === WebSocket.OPEN) {
1618
1381
  client.send(JSON.stringify({ id: WS_ID_SNACKBAR, src: 'Matterbridge', dst: 'Frontend', method: 'memory_update', params: { message, timeout } }));
1619
1382
  }
1620
1383
  });
1621
1384
  }
1622
- /**
1623
- * Sends a message to all connected clients.
1624
- *
1625
- */
1626
1385
  wssBroadcastMessage(id, method, params) {
1627
1386
  this.log.debug(`Sending a broadcast message id ${id} method ${method} params ${debugStringify(params ?? {})} to all connected clients`);
1628
- // Send the message to all connected clients
1629
1387
  this.webSocketServer?.clients.forEach((client) => {
1630
1388
  if (client.readyState === WebSocket.OPEN) {
1631
1389
  client.send(JSON.stringify({ id, src: 'Matterbridge', dst: 'Frontend', method, params }));
@@ -1633,4 +1391,3 @@ export class Frontend {
1633
1391
  });
1634
1392
  }
1635
1393
  }
1636
- //# sourceMappingURL=frontend.js.map