matterbridge 2.0.0 → 2.1.0-dev.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (97) hide show
  1. package/CHANGELOG.md +21 -1
  2. package/README.md +1 -1
  3. package/dist/cli.js +0 -26
  4. package/dist/cluster/export.js +0 -2
  5. package/dist/defaultConfigSchema.js +0 -23
  6. package/dist/deviceManager.js +1 -26
  7. package/dist/frontend.js +57 -242
  8. package/dist/index.js +1 -30
  9. package/dist/logger/export.js +0 -1
  10. package/dist/matter/export.js +0 -7
  11. package/dist/matterbridge.js +77 -702
  12. package/dist/matterbridgeAccessoryPlatform.js +0 -33
  13. package/dist/matterbridgeBehaviors.js +33 -38
  14. package/dist/matterbridgeDeviceTypes.js +11 -112
  15. package/dist/matterbridgeDynamicPlatform.js +0 -33
  16. package/dist/matterbridgeEndpoint.js +970 -2524
  17. package/dist/matterbridgePlatform.js +3 -123
  18. package/dist/matterbridgeTypes.js +0 -25
  19. package/dist/pluginManager.js +3 -240
  20. package/dist/storage/export.js +0 -1
  21. package/dist/utils/colorUtils.js +2 -205
  22. package/dist/utils/export.js +0 -1
  23. package/dist/utils/utils.js +7 -251
  24. package/frontend/build/asset-manifest.json +3 -3
  25. package/frontend/build/index.html +1 -1
  26. package/frontend/build/static/js/{main.6df4ebe4.js → main.26dbf9b9.js} +3 -3
  27. package/frontend/build/static/js/{main.6df4ebe4.js.map → main.26dbf9b9.js.map} +1 -1
  28. package/npm-shrinkwrap.json +83 -68
  29. package/package.json +2 -4
  30. package/dist/cli.d.ts +0 -25
  31. package/dist/cli.d.ts.map +0 -1
  32. package/dist/cli.js.map +0 -1
  33. package/dist/cluster/export.d.ts +0 -2
  34. package/dist/cluster/export.d.ts.map +0 -1
  35. package/dist/cluster/export.js.map +0 -1
  36. package/dist/defaultConfigSchema.d.ts +0 -27
  37. package/dist/defaultConfigSchema.d.ts.map +0 -1
  38. package/dist/defaultConfigSchema.js.map +0 -1
  39. package/dist/deviceManager.d.ts +0 -46
  40. package/dist/deviceManager.d.ts.map +0 -1
  41. package/dist/deviceManager.js.map +0 -1
  42. package/dist/frontend.d.ts +0 -98
  43. package/dist/frontend.d.ts.map +0 -1
  44. package/dist/frontend.js.map +0 -1
  45. package/dist/index.d.ts +0 -34
  46. package/dist/index.d.ts.map +0 -1
  47. package/dist/index.js.map +0 -1
  48. package/dist/logger/export.d.ts +0 -2
  49. package/dist/logger/export.d.ts.map +0 -1
  50. package/dist/logger/export.js.map +0 -1
  51. package/dist/matter/export.d.ts +0 -10
  52. package/dist/matter/export.d.ts.map +0 -1
  53. package/dist/matter/export.js.map +0 -1
  54. package/dist/matterbridge.d.ts +0 -356
  55. package/dist/matterbridge.d.ts.map +0 -1
  56. package/dist/matterbridge.js.map +0 -1
  57. package/dist/matterbridgeAccessoryPlatform.d.ts +0 -39
  58. package/dist/matterbridgeAccessoryPlatform.d.ts.map +0 -1
  59. package/dist/matterbridgeAccessoryPlatform.js.map +0 -1
  60. package/dist/matterbridgeBehaviors.d.ts +0 -963
  61. package/dist/matterbridgeBehaviors.d.ts.map +0 -1
  62. package/dist/matterbridgeBehaviors.js.map +0 -1
  63. package/dist/matterbridgeDeviceTypes.d.ts +0 -177
  64. package/dist/matterbridgeDeviceTypes.d.ts.map +0 -1
  65. package/dist/matterbridgeDeviceTypes.js.map +0 -1
  66. package/dist/matterbridgeDynamicPlatform.d.ts +0 -39
  67. package/dist/matterbridgeDynamicPlatform.d.ts.map +0 -1
  68. package/dist/matterbridgeDynamicPlatform.js.map +0 -1
  69. package/dist/matterbridgeEndpoint.d.ts +0 -10254
  70. package/dist/matterbridgeEndpoint.d.ts.map +0 -1
  71. package/dist/matterbridgeEndpoint.js.map +0 -1
  72. package/dist/matterbridgeEndpointDefault.d.ts +0 -2
  73. package/dist/matterbridgeEndpointDefault.d.ts.map +0 -1
  74. package/dist/matterbridgeEndpointDefault.js +0 -159
  75. package/dist/matterbridgeEndpointDefault.js.map +0 -1
  76. package/dist/matterbridgePlatform.d.ts +0 -164
  77. package/dist/matterbridgePlatform.d.ts.map +0 -1
  78. package/dist/matterbridgePlatform.js.map +0 -1
  79. package/dist/matterbridgeTypes.d.ts +0 -167
  80. package/dist/matterbridgeTypes.d.ts.map +0 -1
  81. package/dist/matterbridgeTypes.js.map +0 -1
  82. package/dist/pluginManager.d.ts +0 -238
  83. package/dist/pluginManager.d.ts.map +0 -1
  84. package/dist/pluginManager.js.map +0 -1
  85. package/dist/storage/export.d.ts +0 -2
  86. package/dist/storage/export.d.ts.map +0 -1
  87. package/dist/storage/export.js.map +0 -1
  88. package/dist/utils/colorUtils.d.ts +0 -61
  89. package/dist/utils/colorUtils.d.ts.map +0 -1
  90. package/dist/utils/colorUtils.js.map +0 -1
  91. package/dist/utils/export.d.ts +0 -3
  92. package/dist/utils/export.d.ts.map +0 -1
  93. package/dist/utils/export.js.map +0 -1
  94. package/dist/utils/utils.d.ts +0 -221
  95. package/dist/utils/utils.d.ts.map +0 -1
  96. package/dist/utils/utils.js.map +0 -1
  97. /package/frontend/build/static/js/{main.6df4ebe4.js.LICENSE.txt → main.26dbf9b9.js.LICENSE.txt} +0 -0
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.0
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, 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;
@@ -67,26 +24,15 @@ export class Frontend {
67
24
  webSocketServer;
68
25
  constructor(matterbridge) {
69
26
  this.matterbridge = matterbridge;
70
- this.log = new AnsiLogger({ logName: 'Frontend', logTimestampFormat: 4 /* TimestampFormat.TIME_MILLIS */, logLevel: hasParameter('debug') ? "debug" /* LogLevel.DEBUG */ : "info" /* LogLevel.INFO */ });
27
+ this.log = new AnsiLogger({ logName: 'Frontend', logTimestampFormat: 4, logLevel: hasParameter('debug') ? "debug" : "info" });
71
28
  }
72
29
  async start(port = 8283) {
73
30
  this.port = port;
74
31
  this.log.debug(`Initializing the frontend ${hasParameter('ssl') ? 'https' : 'http'} server on port ${YELLOW}${this.port}${db}`);
75
- // Create the express app that serves the frontend
76
32
  this.expressApp = express();
77
- // Log all requests to the server for debugging
78
- /*
79
- this.expressApp.use((req, res, next) => {
80
- this.log.debug(`Received request on expressApp: ${req.method} ${req.url}`);
81
- next();
82
- });
83
- */
84
- // Serve static files from '/static' endpoint
85
33
  this.expressApp.use(express.static(path.join(this.matterbridge.rootDirectory, 'frontend/build')));
86
34
  if (!hasParameter('ssl')) {
87
- // Create an HTTP server and attach the express app
88
35
  this.httpServer = createServer(this.expressApp);
89
- // Listen on the specified port
90
36
  if (hasParameter('ingress')) {
91
37
  this.httpServer.listen(this.port, '0.0.0.0', () => {
92
38
  this.log.info(`The frontend http server is listening on ${UNDERLINE}http://0.0.0.0:${this.port}${UNDERLINEOFF}${rs}`);
@@ -100,7 +46,6 @@ export class Frontend {
100
46
  this.log.info(`The frontend http server is listening on ${UNDERLINE}http://[${this.matterbridge.systemInformation.ipv6Address}]:${this.port}${UNDERLINEOFF}${rs}`);
101
47
  });
102
48
  }
103
- // eslint-disable-next-line @typescript-eslint/no-explicit-any
104
49
  this.httpServer.on('error', (error) => {
105
50
  this.log.error(`Frontend http server error listening on ${this.port}`);
106
51
  switch (error.code) {
@@ -116,7 +61,6 @@ export class Frontend {
116
61
  });
117
62
  }
118
63
  else {
119
- // Load the SSL certificate, the private key and optionally the CA certificate
120
64
  let cert;
121
65
  try {
122
66
  cert = await fs.readFile(path.join(this.matterbridge.matterbridgeDirectory, 'certs/cert.pem'), 'utf8');
@@ -144,9 +88,7 @@ export class Frontend {
144
88
  this.log.info(`CA certificate file ${path.join(this.matterbridge.matterbridgeDirectory, 'certs/ca.pem')} not loaded: ${error}`);
145
89
  }
146
90
  const serverOptions = { cert, key, ca };
147
- // Create an HTTPS server with the SSL certificate and private key (ca is optional) and attach the express app
148
91
  this.httpsServer = https.createServer(serverOptions, this.expressApp);
149
- // Listen on the specified port
150
92
  if (hasParameter('ingress')) {
151
93
  this.httpsServer.listen(this.port, '0.0.0.0', () => {
152
94
  this.log.info(`The frontend https server is listening on ${UNDERLINE}https://0.0.0.0:${this.port}${UNDERLINEOFF}${rs}`);
@@ -160,7 +102,6 @@ export class Frontend {
160
102
  this.log.info(`The frontend https server is listening on ${UNDERLINE}https://[${this.matterbridge.systemInformation.ipv6Address}]:${this.port}${UNDERLINEOFF}${rs}`);
161
103
  });
162
104
  }
163
- // eslint-disable-next-line @typescript-eslint/no-explicit-any
164
105
  this.httpsServer.on('error', (error) => {
165
106
  this.log.error(`Frontend https server error listening on ${this.port}`);
166
107
  switch (error.code) {
@@ -177,13 +118,12 @@ export class Frontend {
177
118
  }
178
119
  if (this.initializeError)
179
120
  return;
180
- // Createe a WebSocket server and attach it to the http or https server
181
121
  const wssPort = this.port;
182
122
  const wssHost = hasParameter('ssl') ? `wss://${this.matterbridge.systemInformation.ipv4Address}:${wssPort}` : `ws://${this.matterbridge.systemInformation.ipv4Address}:${wssPort}`;
183
123
  this.webSocketServer = new WebSocketServer(hasParameter('ssl') ? { server: this.httpsServer } : { server: this.httpServer });
184
124
  this.webSocketServer.on('connection', (ws, request) => {
185
125
  const clientIp = request.socket.remoteAddress;
186
- AnsiLogger.setGlobalCallback(this.wssSendMessage.bind(this), "debug" /* LogLevel.DEBUG */);
126
+ AnsiLogger.setGlobalCallback(this.wssSendMessage.bind(this), "debug");
187
127
  this.log.info(`WebSocketServer client "${clientIp}" connected to Matterbridge`);
188
128
  ws.on('message', (message) => {
189
129
  this.wsMessageHandler(ws, message);
@@ -215,7 +155,6 @@ export class Frontend {
215
155
  this.webSocketServer.on('error', (ws, error) => {
216
156
  this.log.error(`WebSocketServer error: ${error}`);
217
157
  });
218
- // Endpoint to validate login code
219
158
  this.expressApp.post('/api/login', express.json(), async (req, res) => {
220
159
  const { password } = req.body;
221
160
  this.log.debug('The frontend sent /api/login', password);
@@ -234,33 +173,28 @@ export class Frontend {
234
173
  this.log.warn('/api/login error wrong password');
235
174
  res.json({ valid: false });
236
175
  }
237
- // eslint-disable-next-line @typescript-eslint/no-unused-vars
238
176
  }
239
177
  catch (error) {
240
178
  this.log.error('/api/login error getting password');
241
179
  res.json({ valid: false });
242
180
  }
243
181
  });
244
- // Endpoint to provide health check
245
182
  this.expressApp.get('/health', (req, res) => {
246
183
  this.log.debug('Express received /health');
247
184
  const healthStatus = {
248
- status: 'ok', // Indicate service is healthy
249
- uptime: process.uptime(), // Server uptime in seconds
250
- timestamp: new Date().toISOString(), // Current timestamp
185
+ status: 'ok',
186
+ uptime: process.uptime(),
187
+ timestamp: new Date().toISOString(),
251
188
  };
252
189
  res.status(200).json(healthStatus);
253
190
  });
254
- // Endpoint to provide memory usage details
255
191
  this.expressApp.get('/memory', async (req, res) => {
256
192
  this.log.debug('Express received /memory');
257
- // Function to format bytes to KB or MB
258
193
  const formatMemoryUsage = (bytes) => {
259
194
  const kb = bytes / 1024;
260
195
  const mb = kb / 1024;
261
196
  return mb >= 1 ? `${mb.toFixed(2)} MB` : `${kb.toFixed(2)} KB`;
262
197
  };
263
- // Memory usage from process
264
198
  const memoryUsageRaw = process.memoryUsage();
265
199
  const memoryUsage = {
266
200
  rss: formatMemoryUsage(memoryUsageRaw.rss),
@@ -269,13 +203,10 @@ export class Frontend {
269
203
  external: formatMemoryUsage(memoryUsageRaw.external),
270
204
  arrayBuffers: formatMemoryUsage(memoryUsageRaw.arrayBuffers),
271
205
  };
272
- // V8 heap statistics
273
206
  const { default: v8 } = await import('node:v8');
274
207
  const heapStatsRaw = v8.getHeapStatistics();
275
208
  const heapSpacesRaw = v8.getHeapSpaceStatistics();
276
- // Format heapStats
277
209
  const heapStats = Object.fromEntries(Object.entries(heapStatsRaw).map(([key, value]) => [key, formatMemoryUsage(value)]));
278
- // Format heapSpaces
279
210
  const heapSpaces = heapSpacesRaw.map((space) => ({
280
211
  ...space,
281
212
  space_size: formatMemoryUsage(space.space_size),
@@ -293,42 +224,23 @@ export class Frontend {
293
224
  };
294
225
  res.status(200).json(memoryReport);
295
226
  });
296
- // Endpoint to provide settings
227
+ this.expressApp.get('/api/advertise', express.json(), async (req, res) => {
228
+ const pairingCodes = await this.matterbridge.advertiseServerNode(this.matterbridge.serverNode);
229
+ res.json(pairingCodes);
230
+ });
297
231
  this.expressApp.get('/api/settings', express.json(), async (req, res) => {
298
232
  this.log.debug('The frontend sent /api/settings');
299
- this.matterbridge.matterbridgeInformation.bridgeMode = this.matterbridge.bridgeMode;
300
- this.matterbridge.matterbridgeInformation.restartMode = this.matterbridge.restartMode;
301
- this.matterbridge.matterbridgeInformation.loggerLevel = this.log.logLevel;
302
- this.matterbridge.matterbridgeInformation.matterLoggerLevel = Logger.defaultLogLevel;
303
- this.matterbridge.matterbridgeInformation.mattermdnsinterface = (await this.matterbridge.nodeContext?.get('mattermdnsinterface', '')) || '';
304
- this.matterbridge.matterbridgeInformation.matteripv4address = (await this.matterbridge.nodeContext?.get('matteripv4address', '')) || '';
305
- this.matterbridge.matterbridgeInformation.matteripv6address = (await this.matterbridge.nodeContext?.get('matteripv6address', '')) || '';
306
- this.matterbridge.matterbridgeInformation.matterPort = (await this.matterbridge.nodeContext?.get('matterport', 5540)) ?? 5540;
307
- this.matterbridge.matterbridgeInformation.matterDiscriminator = await this.matterbridge.nodeContext?.get('matterdiscriminator');
308
- this.matterbridge.matterbridgeInformation.matterPasscode = await this.matterbridge.nodeContext?.get('matterpasscode');
309
- this.matterbridge.matterbridgeInformation.matterbridgePaired = this.matterbridge.matterbridgePaired;
310
- this.matterbridge.matterbridgeInformation.matterbridgeQrPairingCode = this.matterbridge.matterbridgeQrPairingCode;
311
- this.matterbridge.matterbridgeInformation.matterbridgeManualPairingCode = this.matterbridge.matterbridgeManualPairingCode;
312
- this.matterbridge.matterbridgeInformation.matterbridgeFabricInformations = this.matterbridge.matterbridgeFabricInformations;
313
- this.matterbridge.matterbridgeInformation.matterbridgeSessionInformations = Array.from(this.matterbridge.matterbridgeSessionInformations.values());
314
- this.matterbridge.matterbridgeInformation.profile = this.matterbridge.profile;
315
- const response = { systemInformation: this.matterbridge.systemInformation, matterbridgeInformation: this.matterbridge.matterbridgeInformation };
316
- // this.log.debug('Response:', debugStringify(response));
317
- res.json(response);
233
+ res.json(await this.getApiSettings());
318
234
  });
319
- // Endpoint to provide plugins
320
235
  this.expressApp.get('/api/plugins', async (req, res) => {
321
236
  this.log.debug('The frontend sent /api/plugins');
322
- const response = await this.getBaseRegisteredPlugins();
323
- // this.log.debug('Response:', debugStringify(response));
237
+ const response = this.getBaseRegisteredPlugins();
324
238
  res.json(response);
325
239
  });
326
- // Endpoint to provide devices
327
240
  this.expressApp.get('/api/devices', (req, res) => {
328
241
  this.log.debug('The frontend sent /api/devices');
329
242
  const devices = [];
330
243
  this.matterbridge.devices.forEach(async (device) => {
331
- // Check if the device has the required properties
332
244
  if (!device.plugin || !device.name || !device.deviceName || !device.serialNumber || !device.uniqueId)
333
245
  return;
334
246
  const cluster = this.getClusterTextFromDevice(device);
@@ -344,10 +256,8 @@ export class Frontend {
344
256
  cluster: cluster,
345
257
  });
346
258
  });
347
- // this.log.debug('Response:', debugStringify(data));
348
259
  res.json(devices);
349
260
  });
350
- // Endpoint to provide the cluster servers of the devices
351
261
  this.expressApp.get('/api/devices_clusters/:selectedPluginName/:selectedDeviceEndpoint', (req, res) => {
352
262
  const selectedPluginName = req.params.selectedPluginName;
353
263
  const selectedDeviceEndpoint = parseInt(req.params.selectedDeviceEndpoint, 10);
@@ -420,7 +330,6 @@ export class Frontend {
420
330
  });
421
331
  res.json(data);
422
332
  });
423
- // Endpoint to view the log
424
333
  this.expressApp.get('/api/view-log', async (req, res) => {
425
334
  this.log.debug('The frontend sent /api/log');
426
335
  try {
@@ -433,12 +342,10 @@ export class Frontend {
433
342
  res.status(500).send('Error reading log file');
434
343
  }
435
344
  });
436
- // Endpoint to download the matterbridge log
437
345
  this.expressApp.get('/api/download-mblog', async (req, res) => {
438
346
  this.log.debug('The frontend sent /api/download-mblog');
439
347
  try {
440
348
  await fs.access(path.join(this.matterbridge.matterbridgeDirectory, this.matterbridge.matterbrideLoggerFile), fs.constants.F_OK);
441
- // eslint-disable-next-line @typescript-eslint/no-unused-vars
442
349
  }
443
350
  catch (error) {
444
351
  fs.appendFile(path.join(this.matterbridge.matterbridgeDirectory, this.matterbridge.matterbrideLoggerFile), 'Enable the log on file in the settings to enable the file logger');
@@ -450,12 +357,10 @@ export class Frontend {
450
357
  }
451
358
  });
452
359
  });
453
- // Endpoint to download the matter log
454
360
  this.expressApp.get('/api/download-mjlog', async (req, res) => {
455
361
  this.log.debug('The frontend sent /api/download-mjlog');
456
362
  try {
457
363
  await fs.access(path.join(this.matterbridge.matterbridgeDirectory, this.matterbridge.matterLoggerFile), fs.constants.F_OK);
458
- // eslint-disable-next-line @typescript-eslint/no-unused-vars
459
364
  }
460
365
  catch (error) {
461
366
  fs.appendFile(path.join(this.matterbridge.matterbridgeDirectory, this.matterbridge.matterLoggerFile), 'Enable the log on file in the settings to enable the file logger');
@@ -467,7 +372,6 @@ export class Frontend {
467
372
  }
468
373
  });
469
374
  });
470
- // Endpoint to download the matter storage file
471
375
  this.expressApp.get('/api/download-mjstorage', async (req, res) => {
472
376
  this.log.debug('The frontend sent /api/download-mjstorage');
473
377
  await createZip(path.join(os.tmpdir(), `matterbridge.${this.matterbridge.matterStorageName}.zip`), path.join(this.matterbridge.matterbridgeDirectory, this.matterbridge.matterStorageName));
@@ -478,7 +382,6 @@ export class Frontend {
478
382
  }
479
383
  });
480
384
  });
481
- // Endpoint to download the matterbridge storage directory
482
385
  this.expressApp.get('/api/download-mbstorage', async (req, res) => {
483
386
  this.log.debug('The frontend sent /api/download-mbstorage');
484
387
  await createZip(path.join(os.tmpdir(), `matterbridge.${this.matterbridge.nodeStorageName}.zip`), path.join(this.matterbridge.matterbridgeDirectory, this.matterbridge.nodeStorageName));
@@ -489,7 +392,6 @@ export class Frontend {
489
392
  }
490
393
  });
491
394
  });
492
- // Endpoint to download the matterbridge plugin directory
493
395
  this.expressApp.get('/api/download-pluginstorage', async (req, res) => {
494
396
  this.log.debug('The frontend sent /api/download-pluginstorage');
495
397
  await createZip(path.join(os.tmpdir(), `matterbridge.pluginstorage.zip`), this.matterbridge.matterbridgePluginDirectory);
@@ -500,11 +402,9 @@ export class Frontend {
500
402
  }
501
403
  });
502
404
  });
503
- // Endpoint to download the matterbridge plugin config files
504
405
  this.expressApp.get('/api/download-pluginconfig', async (req, res) => {
505
406
  this.log.debug('The frontend sent /api/download-pluginconfig');
506
407
  await createZip(path.join(os.tmpdir(), `matterbridge.pluginconfig.zip`), path.relative(process.cwd(), path.join(this.matterbridge.matterbridgeDirectory, '*.config.json')));
507
- // 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')));
508
408
  res.download(path.join(os.tmpdir(), `matterbridge.pluginconfig.zip`), `matterbridge.pluginconfig.zip`, (error) => {
509
409
  if (error) {
510
410
  this.log.error(`Error downloading file matterbridge.pluginstorage.zip: ${error instanceof Error ? error.message : error}`);
@@ -512,7 +412,6 @@ export class Frontend {
512
412
  }
513
413
  });
514
414
  });
515
- // Endpoint to download the matterbridge plugin config files
516
415
  this.expressApp.get('/api/download-backup', async (req, res) => {
517
416
  this.log.debug('The frontend sent /api/download-backup');
518
417
  res.download(path.join(os.tmpdir(), `matterbridge.backup.zip`), `matterbridge.backup.zip`, (error) => {
@@ -522,7 +421,6 @@ export class Frontend {
522
421
  }
523
422
  });
524
423
  });
525
- // Endpoint to receive commands
526
424
  this.expressApp.post('/api/command/:command/:param', express.json(), async (req, res) => {
527
425
  const command = req.params.command;
528
426
  let param = req.params.param;
@@ -532,15 +430,13 @@ export class Frontend {
532
430
  return;
533
431
  }
534
432
  this.log.debug(`Received frontend command: ${command}:${param}`);
535
- // Handle the command setpassword from Settings
536
433
  if (command === 'setpassword') {
537
- const password = param.slice(1, -1); // Remove the first and last characters
434
+ const password = param.slice(1, -1);
538
435
  this.log.debug('setpassword', param, password);
539
436
  await this.matterbridge.nodeContext?.set('password', password);
540
437
  res.json({ message: 'Command received' });
541
438
  return;
542
439
  }
543
- // Handle the command setbridgemode from Settings
544
440
  if (command === 'setbridgemode') {
545
441
  this.log.debug(`setbridgemode: ${param}`);
546
442
  this.wssSendRestartRequired();
@@ -548,7 +444,6 @@ export class Frontend {
548
444
  res.json({ message: 'Command received' });
549
445
  return;
550
446
  }
551
- // Handle the command backup from Settings
552
447
  if (command === 'backup') {
553
448
  this.log.notice(`Prepairing the backup...`);
554
449
  await createZip(path.join(os.tmpdir(), `matterbridge.backup.zip`), path.join(this.matterbridge.matterbridgeDirectory), path.join(this.matterbridge.matterbridgePluginDirectory));
@@ -556,26 +451,25 @@ export class Frontend {
556
451
  res.json({ message: 'Command received' });
557
452
  return;
558
453
  }
559
- // Handle the command setmbloglevel from Settings
560
454
  if (command === 'setmbloglevel') {
561
455
  this.log.debug('Matterbridge log level:', param);
562
456
  if (param === 'Debug') {
563
- this.log.logLevel = "debug" /* LogLevel.DEBUG */;
457
+ this.log.logLevel = "debug";
564
458
  }
565
459
  else if (param === 'Info') {
566
- this.log.logLevel = "info" /* LogLevel.INFO */;
460
+ this.log.logLevel = "info";
567
461
  }
568
462
  else if (param === 'Notice') {
569
- this.log.logLevel = "notice" /* LogLevel.NOTICE */;
463
+ this.log.logLevel = "notice";
570
464
  }
571
465
  else if (param === 'Warn') {
572
- this.log.logLevel = "warn" /* LogLevel.WARN */;
466
+ this.log.logLevel = "warn";
573
467
  }
574
468
  else if (param === 'Error') {
575
- this.log.logLevel = "error" /* LogLevel.ERROR */;
469
+ this.log.logLevel = "error";
576
470
  }
577
471
  else if (param === 'Fatal') {
578
- this.log.logLevel = "fatal" /* LogLevel.FATAL */;
472
+ this.log.logLevel = "fatal";
579
473
  }
580
474
  await this.matterbridge.nodeContext?.set('matterbridgeLogLevel', this.log.logLevel);
581
475
  MatterbridgeEndpoint.logLevel = this.log.logLevel;
@@ -583,13 +477,12 @@ export class Frontend {
583
477
  for (const plugin of this.matterbridge.plugins) {
584
478
  if (!plugin.platform || !plugin.platform.config)
585
479
  continue;
586
- plugin.platform.log.logLevel = plugin.platform.config.debug ? "debug" /* LogLevel.DEBUG */ : this.log.logLevel;
587
- await plugin.platform.onChangeLoggerLevel(plugin.platform.config.debug ? "debug" /* LogLevel.DEBUG */ : this.log.logLevel);
480
+ plugin.platform.log.logLevel = plugin.platform.config.debug ? "debug" : this.log.logLevel;
481
+ await plugin.platform.onChangeLoggerLevel(plugin.platform.config.debug ? "debug" : this.log.logLevel);
588
482
  }
589
483
  res.json({ message: 'Command received' });
590
484
  return;
591
485
  }
592
- // Handle the command setmbloglevel from Settings
593
486
  if (command === 'setmjloglevel') {
594
487
  this.log.debug('Matter.js log level:', param);
595
488
  if (param === 'Debug') {
@@ -614,34 +507,30 @@ export class Frontend {
614
507
  res.json({ message: 'Command received' });
615
508
  return;
616
509
  }
617
- // Handle the command setmdnsinterface from Settings
618
510
  if (command === 'setmdnsinterface') {
619
- param = param.slice(1, -1); // Remove the first and last characters *mdns*
511
+ param = param.slice(1, -1);
620
512
  this.matterbridge.matterbridgeInformation.mattermdnsinterface = param;
621
513
  this.log.debug('Matter.js mdns interface:', param === '' ? 'All interfaces' : param);
622
514
  await this.matterbridge.nodeContext?.set('mattermdnsinterface', param);
623
515
  res.json({ message: 'Command received' });
624
516
  return;
625
517
  }
626
- // Handle the command setipv4address from Settings
627
518
  if (command === 'setipv4address') {
628
- param = param.slice(1, -1); // Remove the first and last characters *ip*
519
+ param = param.slice(1, -1);
629
520
  this.matterbridge.matterbridgeInformation.matteripv4address = param;
630
521
  this.log.debug('Matter.js ipv4 address:', param === '' ? 'All ipv4 addresses' : param);
631
522
  await this.matterbridge.nodeContext?.set('matteripv4address', param);
632
523
  res.json({ message: 'Command received' });
633
524
  return;
634
525
  }
635
- // Handle the command setipv6address from Settings
636
526
  if (command === 'setipv6address') {
637
- param = param.slice(1, -1); // Remove the first and last characters *ip*
527
+ param = param.slice(1, -1);
638
528
  this.matterbridge.matterbridgeInformation.matteripv6address = param;
639
529
  this.log.debug('Matter.js ipv6 address:', param === '' ? 'All ipv6 addresses' : param);
640
530
  await this.matterbridge.nodeContext?.set('matteripv6address', param);
641
531
  res.json({ message: 'Command received' });
642
532
  return;
643
533
  }
644
- // Handle the command setmatterport from Settings
645
534
  if (command === 'setmatterport') {
646
535
  const port = Math.min(Math.max(parseInt(param), 5540), 5560);
647
536
  this.matterbridge.matterbridgeInformation.matterPort = port;
@@ -650,7 +539,6 @@ export class Frontend {
650
539
  res.json({ message: 'Command received' });
651
540
  return;
652
541
  }
653
- // Handle the command setmatterdiscriminator from Settings
654
542
  if (command === 'setmatterdiscriminator') {
655
543
  const discriminator = Math.min(Math.max(parseInt(param), 1000), 4095);
656
544
  this.matterbridge.matterbridgeInformation.matterDiscriminator = discriminator;
@@ -659,7 +547,6 @@ export class Frontend {
659
547
  res.json({ message: 'Command received' });
660
548
  return;
661
549
  }
662
- // Handle the command setmatterpasscode from Settings
663
550
  if (command === 'setmatterpasscode') {
664
551
  const passcode = Math.min(Math.max(parseInt(param), 10000000), 90000000);
665
552
  this.matterbridge.matterbridgeInformation.matterPasscode = passcode;
@@ -668,20 +555,17 @@ export class Frontend {
668
555
  res.json({ message: 'Command received' });
669
556
  return;
670
557
  }
671
- // Handle the command setmbloglevel from Settings
672
558
  if (command === 'setmblogfile') {
673
559
  this.log.debug('Matterbridge file log:', param);
674
560
  this.matterbridge.matterbridgeInformation.fileLogger = param === 'true';
675
561
  await this.matterbridge.nodeContext?.set('matterbridgeFileLog', param === 'true');
676
- // Create the file logger for matterbridge
677
562
  if (param === 'true')
678
- AnsiLogger.setGlobalLogfile(path.join(this.matterbridge.matterbridgeDirectory, this.matterbridge.matterbrideLoggerFile), "debug" /* LogLevel.DEBUG */, true);
563
+ AnsiLogger.setGlobalLogfile(path.join(this.matterbridge.matterbridgeDirectory, this.matterbridge.matterbrideLoggerFile), "debug", true);
679
564
  else
680
565
  AnsiLogger.setGlobalLogfile(undefined);
681
566
  res.json({ message: 'Command received' });
682
567
  return;
683
568
  }
684
- // Handle the command setmbloglevel from Settings
685
569
  if (command === 'setmjlogfile') {
686
570
  this.log.debug('Matter file log:', param);
687
571
  this.matterbridge.matterbridgeInformation.matterFileLogger = param === 'true';
@@ -708,43 +592,36 @@ export class Frontend {
708
592
  res.json({ message: 'Command received' });
709
593
  return;
710
594
  }
711
- // Handle the command unregister from Settings
712
595
  if (command === 'unregister') {
713
596
  await this.matterbridge.unregisterAndShutdownProcess();
714
597
  res.json({ message: 'Command received' });
715
598
  return;
716
599
  }
717
- // Handle the command reset from Settings
718
600
  if (command === 'reset') {
719
601
  await this.matterbridge.shutdownProcessAndReset();
720
602
  res.json({ message: 'Command received' });
721
603
  return;
722
604
  }
723
- // Handle the command factoryreset from Settings
724
605
  if (command === 'factoryreset') {
725
606
  await this.matterbridge.shutdownProcessAndFactoryReset();
726
607
  res.json({ message: 'Command received' });
727
608
  return;
728
609
  }
729
- // Handle the command shutdown from Header
730
610
  if (command === 'shutdown') {
731
611
  await this.matterbridge.shutdownProcess();
732
612
  res.json({ message: 'Command received' });
733
613
  return;
734
614
  }
735
- // Handle the command restart from Header
736
615
  if (command === 'restart') {
737
616
  await this.matterbridge.restartProcess();
738
617
  res.json({ message: 'Command received' });
739
618
  return;
740
619
  }
741
- // Handle the command update from Header
742
620
  if (command === 'update') {
743
621
  this.log.info('Updating matterbridge...');
744
622
  try {
745
623
  await this.matterbridge.spawnCommand('npm', ['install', '-g', 'matterbridge', '--omit=dev', '--verbose']);
746
624
  this.log.info('Matterbridge has been updated. Full restart required.');
747
- // eslint-disable-next-line @typescript-eslint/no-unused-vars
748
625
  }
749
626
  catch (error) {
750
627
  this.log.error('Error updating matterbridge');
@@ -754,11 +631,9 @@ export class Frontend {
754
631
  res.json({ message: 'Command received' });
755
632
  return;
756
633
  }
757
- // Handle the command saveconfig from Home
758
634
  if (command === 'saveconfig') {
759
635
  param = param.replace(/\*/g, '\\');
760
636
  this.log.info(`Saving config for plugin ${plg}${param}${nf}...`);
761
- // console.log('Req.body:', JSON.stringify(req.body, null, 2));
762
637
  if (!this.matterbridge.plugins.has(param)) {
763
638
  this.log.warn(`Plugin ${plg}${param}${wr} not found in matterbridge`);
764
639
  }
@@ -772,58 +647,49 @@ export class Frontend {
772
647
  res.json({ message: 'Command received' });
773
648
  return;
774
649
  }
775
- // Handle the command installplugin from Home
776
650
  if (command === 'installplugin') {
777
651
  param = param.replace(/\*/g, '\\');
778
652
  this.log.info(`Installing plugin ${plg}${param}${nf}...`);
779
653
  try {
780
654
  await this.matterbridge.spawnCommand('npm', ['install', '-g', param, '--omit=dev', '--verbose']);
781
655
  this.log.info(`Plugin ${plg}${param}${nf} installed. Full restart required.`);
782
- // eslint-disable-next-line @typescript-eslint/no-unused-vars
783
656
  }
784
657
  catch (error) {
785
658
  this.log.error(`Error installing plugin ${plg}${param}${er}`);
786
659
  }
787
660
  this.wssSendRestartRequired();
788
661
  param = param.split('@')[0];
789
- // Also add the plugin to matterbridge so no return!
790
662
  if (param === 'matterbridge') {
791
- // 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
792
663
  res.json({ message: 'Command received' });
793
664
  return;
794
665
  }
795
666
  }
796
- // Handle the command addplugin from Home
797
667
  if (command === 'addplugin' || command === 'installplugin') {
798
668
  param = param.replace(/\*/g, '\\');
799
669
  const plugin = await this.matterbridge.plugins.add(param);
800
670
  if (plugin) {
801
671
  if (this.matterbridge.bridgeMode === 'childbridge') {
802
- // 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
803
- // eslint-disable-next-line @typescript-eslint/no-explicit-any
804
672
  this.matterbridge.createDynamicPlugin(plugin, true);
805
673
  }
806
- this.matterbridge.plugins.load(plugin, true, 'The plugin has been added', true); // No await do it in the background
674
+ this.matterbridge.plugins.load(plugin, true, 'The plugin has been added', true);
807
675
  }
808
676
  res.json({ message: 'Command received' });
809
677
  this.wssSendRefreshRequired();
810
678
  return;
811
679
  }
812
- // Handle the command removeplugin from Home
813
680
  if (command === 'removeplugin') {
814
681
  if (!this.matterbridge.plugins.has(param)) {
815
682
  this.log.warn(`Plugin ${plg}${param}${wr} not found in matterbridge`);
816
683
  }
817
684
  else {
818
685
  const plugin = this.matterbridge.plugins.get(param);
819
- await this.matterbridge.plugins.shutdown(plugin, 'The plugin has been removed.', true); // This will also close the server node in childbridge mode
686
+ await this.matterbridge.plugins.shutdown(plugin, 'The plugin has been removed.', true);
820
687
  await this.matterbridge.plugins.remove(param);
821
688
  }
822
689
  res.json({ message: 'Command received' });
823
690
  this.wssSendRefreshRequired();
824
691
  return;
825
692
  }
826
- // Handle the command enableplugin from Home
827
693
  if (command === 'enableplugin') {
828
694
  if (!this.matterbridge.plugins.has(param)) {
829
695
  this.log.warn(`Plugin ${plg}${param}${wr} not found in matterbridge`);
@@ -841,17 +707,15 @@ export class Frontend {
841
707
  plugin.addedDevices = undefined;
842
708
  await this.matterbridge.plugins.enable(param);
843
709
  if (this.matterbridge.bridgeMode === 'childbridge' && plugin.type === 'DynamicPlatform') {
844
- // eslint-disable-next-line @typescript-eslint/no-explicit-any
845
710
  this.matterbridge.createDynamicPlugin(plugin, true);
846
711
  }
847
- 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
712
+ this.matterbridge.plugins.load(plugin, true, 'The plugin has been enabled', true);
848
713
  }
849
714
  }
850
715
  res.json({ message: 'Command received' });
851
716
  this.wssSendRefreshRequired();
852
717
  return;
853
718
  }
854
- // Handle the command disableplugin from Home
855
719
  if (command === 'disableplugin') {
856
720
  if (!this.matterbridge.plugins.has(param)) {
857
721
  this.log.warn(`Plugin ${plg}${param}${wr} not found in matterbridge`);
@@ -859,7 +723,7 @@ export class Frontend {
859
723
  else {
860
724
  const plugin = this.matterbridge.plugins.get(param);
861
725
  if (plugin && plugin.enabled) {
862
- await this.matterbridge.plugins.shutdown(plugin, 'The plugin has been disabled.', true); // This will also close the server node in childbridge mode
726
+ await this.matterbridge.plugins.shutdown(plugin, 'The plugin has been disabled.', true);
863
727
  await this.matterbridge.plugins.disable(param);
864
728
  }
865
729
  }
@@ -868,7 +732,6 @@ export class Frontend {
868
732
  return;
869
733
  }
870
734
  });
871
- // Fallback for routing (must be the last route)
872
735
  this.expressApp.get('*', (req, res) => {
873
736
  this.log.debug('The frontend sent:', req.url);
874
737
  this.log.debug('Response send file:', path.join(this.matterbridge.rootDirectory, 'frontend/build/index.html'));
@@ -877,29 +740,24 @@ export class Frontend {
877
740
  this.log.debug(`Frontend initialized on port ${YELLOW}${this.port}${db} static ${UNDERLINE}${path.join(this.matterbridge.rootDirectory, 'frontend/build')}${UNDERLINEOFF}${rs}`);
878
741
  }
879
742
  async stop() {
880
- // Close the http server
881
743
  if (this.httpServer) {
882
744
  this.httpServer.close();
883
745
  this.httpServer.removeAllListeners();
884
746
  this.httpServer = undefined;
885
747
  this.log.debug('Frontend http server closed successfully');
886
748
  }
887
- // Close the https server
888
749
  if (this.httpsServer) {
889
750
  this.httpsServer.close();
890
751
  this.httpsServer.removeAllListeners();
891
752
  this.httpsServer = undefined;
892
753
  this.log.debug('Frontend https server closed successfully');
893
754
  }
894
- // Remove listeners from the express app
895
755
  if (this.expressApp) {
896
756
  this.expressApp.removeAllListeners();
897
757
  this.expressApp = undefined;
898
758
  this.log.debug('Frontend app closed successfully');
899
759
  }
900
- // Close the WebSocket server
901
760
  if (this.webSocketServer) {
902
- // Close all active connections
903
761
  this.webSocketServer.clients.forEach((client) => {
904
762
  if (client.readyState === WebSocket.OPEN) {
905
763
  client.close();
@@ -916,11 +774,25 @@ export class Frontend {
916
774
  this.webSocketServer = undefined;
917
775
  }
918
776
  }
919
- /**
920
- * Retrieves the cluster text description from a given device.
921
- * @param {MatterbridgeDevice} device - The MatterbridgeDevice object.
922
- * @returns {string} The attributes description of the cluster servers in the device.
923
- */
777
+ async getApiSettings() {
778
+ this.matterbridge.matterbridgeInformation.bridgeMode = this.matterbridge.bridgeMode;
779
+ this.matterbridge.matterbridgeInformation.restartMode = this.matterbridge.restartMode;
780
+ this.matterbridge.matterbridgeInformation.loggerLevel = this.log.logLevel;
781
+ this.matterbridge.matterbridgeInformation.matterLoggerLevel = Logger.defaultLogLevel;
782
+ this.matterbridge.matterbridgeInformation.mattermdnsinterface = this.matterbridge.mdnsInterface;
783
+ this.matterbridge.matterbridgeInformation.matteripv4address = this.matterbridge.ipv4address;
784
+ this.matterbridge.matterbridgeInformation.matteripv6address = this.matterbridge.ipv6address;
785
+ this.matterbridge.matterbridgeInformation.matterPort = (await this.matterbridge.nodeContext?.get('matterport', 5540)) ?? 5540;
786
+ this.matterbridge.matterbridgeInformation.matterDiscriminator = await this.matterbridge.nodeContext?.get('matterdiscriminator');
787
+ this.matterbridge.matterbridgeInformation.matterPasscode = await this.matterbridge.nodeContext?.get('matterpasscode');
788
+ this.matterbridge.matterbridgeInformation.matterbridgePaired = this.matterbridge.matterbridgePaired;
789
+ this.matterbridge.matterbridgeInformation.matterbridgeQrPairingCode = this.matterbridge.matterbridgeQrPairingCode;
790
+ this.matterbridge.matterbridgeInformation.matterbridgeManualPairingCode = this.matterbridge.matterbridgeManualPairingCode;
791
+ this.matterbridge.matterbridgeInformation.matterbridgeFabricInformations = this.matterbridge.matterbridgeFabricInformations;
792
+ this.matterbridge.matterbridgeInformation.matterbridgeSessionInformations = this.matterbridge.matterbridgeSessionInformations;
793
+ this.matterbridge.matterbridgeInformation.profile = this.matterbridge.profile;
794
+ return { systemInformation: this.matterbridge.systemInformation, matterbridgeInformation: this.matterbridge.matterbridgeInformation };
795
+ }
924
796
  getClusterTextFromDevice(device) {
925
797
  const getAttribute = (device, cluster, attribute) => {
926
798
  let value = undefined;
@@ -958,10 +830,10 @@ export class Frontend {
958
830
  return '';
959
831
  };
960
832
  let attributes = '';
961
- // eslint-disable-next-line @typescript-eslint/no-explicit-any
962
833
  Object.entries(device.state).forEach(([clusterName, clusterAttributes]) => {
963
834
  Object.entries(clusterAttributes).forEach(([attributeName, attributeValue]) => {
964
- // console.log(`Cluster: ${clusterName} Attribute: ${attributeName} Value: ${attributeValue}`);
835
+ if (typeof attributeValue === 'undefined')
836
+ return;
965
837
  if (clusterName === 'onOff' && attributeName === 'onOff')
966
838
  attributes += `OnOff: ${attributeValue} `;
967
839
  if (clusterName === 'switch' && attributeName === 'currentPosition')
@@ -1032,11 +904,7 @@ export class Frontend {
1032
904
  });
1033
905
  return attributes.trimStart().trimEnd();
1034
906
  }
1035
- /**
1036
- * Retrieves the base registered plugins sanitized for res.json().
1037
- * @returns {BaseRegisteredPlugin[]} A promise that resolves to an array of BaseRegisteredPlugin objects.
1038
- */
1039
- async getBaseRegisteredPlugins() {
907
+ getBaseRegisteredPlugins() {
1040
908
  const baseRegisteredPlugins = [];
1041
909
  for (const plugin of this.matterbridge.plugins) {
1042
910
  baseRegisteredPlugins.push({
@@ -1066,14 +934,6 @@ export class Frontend {
1066
934
  }
1067
935
  return baseRegisteredPlugins;
1068
936
  }
1069
- /**
1070
- * Handles incoming websocket messages for the Matterbridge.
1071
- *
1072
- * @param {Matterbridge} this - The Matterbridge instance.
1073
- * @param {WebSocket} client - The websocket client that sent the message.
1074
- * @param {WebSocket.RawData} message - The raw data of the message received from the client.
1075
- * @returns {Promise<void>} A promise that resolves when the message has been handled.
1076
- */
1077
937
  async wsMessageHandler(client, message) {
1078
938
  let data;
1079
939
  try {
@@ -1144,39 +1004,25 @@ export class Frontend {
1144
1004
  await this.matterbridge.shutdownProcess();
1145
1005
  return;
1146
1006
  }
1007
+ else if (data.method === '/api/advertise') {
1008
+ const pairingCodes = await this.matterbridge.advertiseServerNode(this.matterbridge.serverNode);
1009
+ client.send(JSON.stringify({ id: data.id, method: data.method, src: 'Matterbridge', dst: data.src, response: pairingCodes }));
1010
+ return;
1011
+ }
1147
1012
  else if (data.method === '/api/settings') {
1148
- this.matterbridge.matterbridgeInformation.bridgeMode = this.matterbridge.bridgeMode;
1149
- this.matterbridge.matterbridgeInformation.restartMode = this.matterbridge.restartMode;
1150
- this.matterbridge.matterbridgeInformation.loggerLevel = this.log.logLevel;
1151
- this.matterbridge.matterbridgeInformation.matterLoggerLevel = Logger.defaultLogLevel;
1152
- this.matterbridge.matterbridgeInformation.mattermdnsinterface = (await this.matterbridge.nodeContext?.get('mattermdnsinterface', '')) || '';
1153
- this.matterbridge.matterbridgeInformation.matteripv4address = (await this.matterbridge.nodeContext?.get('matteripv4address', '')) || '';
1154
- this.matterbridge.matterbridgeInformation.matteripv6address = (await this.matterbridge.nodeContext?.get('matteripv6address', '')) || '';
1155
- this.matterbridge.matterbridgeInformation.matterPort = (await this.matterbridge.nodeContext?.get('matterport', 5540)) ?? 5540;
1156
- this.matterbridge.matterbridgeInformation.matterDiscriminator = await this.matterbridge.nodeContext?.get('matterdiscriminator');
1157
- this.matterbridge.matterbridgeInformation.matterPasscode = await this.matterbridge.nodeContext?.get('matterpasscode');
1158
- this.matterbridge.matterbridgeInformation.matterbridgePaired = this.matterbridge.matterbridgePaired;
1159
- this.matterbridge.matterbridgeInformation.matterbridgeQrPairingCode = this.matterbridge.matterbridgeQrPairingCode;
1160
- this.matterbridge.matterbridgeInformation.matterbridgeManualPairingCode = this.matterbridge.matterbridgeManualPairingCode;
1161
- this.matterbridge.matterbridgeInformation.matterbridgeFabricInformations = this.matterbridge.matterbridgeFabricInformations;
1162
- this.matterbridge.matterbridgeInformation.matterbridgeSessionInformations = Array.from(this.matterbridge.matterbridgeSessionInformations.values());
1163
- this.matterbridge.matterbridgeInformation.profile = this.matterbridge.profile;
1164
- const response = { systemInformation: this.matterbridge.systemInformation, matterbridgeInformation: this.matterbridge.matterbridgeInformation };
1165
- client.send(JSON.stringify({ id: data.id, method: data.method, src: 'Matterbridge', dst: data.src, response }));
1013
+ client.send(JSON.stringify({ id: data.id, method: data.method, src: 'Matterbridge', dst: data.src, response: await this.getApiSettings() }));
1166
1014
  return;
1167
1015
  }
1168
1016
  else if (data.method === '/api/plugins') {
1169
- const response = await this.getBaseRegisteredPlugins();
1017
+ const response = this.getBaseRegisteredPlugins();
1170
1018
  client.send(JSON.stringify({ id: data.id, method: data.method, src: 'Matterbridge', dst: data.src, response }));
1171
1019
  return;
1172
1020
  }
1173
1021
  else if (data.method === '/api/devices') {
1174
1022
  const devices = [];
1175
1023
  this.matterbridge.devices.forEach(async (device) => {
1176
- // Filter by pluginName if provided
1177
1024
  if (data.params.pluginName && data.params.pluginName !== device.plugin)
1178
1025
  return;
1179
- // Check if the device has the required properties
1180
1026
  if (!device.plugin || !device.name || !device.deviceName || !device.serialNumber || !device.uniqueId)
1181
1027
  return;
1182
1028
  const cluster = this.getClusterTextFromDevice(device);
@@ -1256,7 +1102,6 @@ export class Frontend {
1256
1102
  });
1257
1103
  endpointServer.getChildEndpoints().forEach((childEndpoint) => {
1258
1104
  deviceTypes = [];
1259
- // eslint-disable-next-line @typescript-eslint/no-explicit-any
1260
1105
  const name = childEndpoint.endpoint?.id;
1261
1106
  const clusterServers = childEndpoint.getAllClusterServers();
1262
1107
  clusterServers.forEach((clusterServer) => {
@@ -1339,73 +1184,44 @@ export class Frontend {
1339
1184
  return;
1340
1185
  }
1341
1186
  }
1342
- /**
1343
- * Sends a WebSocket message to all connected clients. The function is called by AnsiLogger.setGlobalCallback.
1344
- *
1345
- * @param {string} level - The logger level of the message: debug info notice warn error fatal...
1346
- * @param {string} time - The time string of the message
1347
- * @param {string} name - The logger name of the message
1348
- * @param {string} message - The content of the message.
1349
- */
1350
1187
  wssSendMessage(level, time, name, message) {
1351
1188
  if (!level || !time || !name || !message)
1352
1189
  return;
1353
- // Remove ANSI escape codes from the message
1354
- // eslint-disable-next-line no-control-regex
1355
1190
  message = message.replace(/\x1B\[[0-9;]*[m|s|u|K]/g, '');
1356
- // Remove leading asterisks from the message
1357
1191
  message = message.replace(/^\*+/, '');
1358
- // Replace all occurrences of \t and \n
1359
1192
  message = message.replace(/[\t\n]/g, '');
1360
- // Remove non-printable characters
1361
- // eslint-disable-next-line no-control-regex
1362
1193
  message = message.replace(/[\x00-\x1F\x7F]/g, '');
1363
- // Replace all occurrences of \" with "
1364
1194
  message = message.replace(/\\"/g, '"');
1365
- // Define the maximum allowed length for continuous characters without a space
1366
1195
  const maxContinuousLength = 100;
1367
1196
  const keepStartLength = 20;
1368
1197
  const keepEndLength = 20;
1369
- // Split the message into words
1370
1198
  message = message
1371
1199
  .split(' ')
1372
1200
  .map((word) => {
1373
- // If the word length exceeds the max continuous length, insert spaces and truncate
1374
1201
  if (word.length > maxContinuousLength) {
1375
1202
  return word.slice(0, keepStartLength) + ' ... ' + word.slice(-keepEndLength);
1376
1203
  }
1377
1204
  return word;
1378
1205
  })
1379
1206
  .join(' ');
1380
- // Send the message to all connected clients
1381
1207
  this.webSocketServer?.clients.forEach((client) => {
1382
1208
  if (client.readyState === WebSocket.OPEN) {
1383
1209
  client.send(JSON.stringify({ id: WS_ID_LOG, src: 'Matterbridge', level, time, name, message }));
1384
1210
  }
1385
1211
  });
1386
1212
  }
1387
- /**
1388
- * Sends a need to refresh WebSocket message to all connected clients.
1389
- *
1390
- */
1391
1213
  wssSendRefreshRequired() {
1392
1214
  this.log.debug('Sending a refresh required message to all connected clients');
1393
1215
  this.matterbridge.matterbridgeInformation.refreshRequired = true;
1394
- // Send the message to all connected clients
1395
1216
  this.webSocketServer?.clients.forEach((client) => {
1396
1217
  if (client.readyState === WebSocket.OPEN) {
1397
1218
  client.send(JSON.stringify({ id: WS_ID_REFRESH_NEEDED, src: 'Matterbridge', dst: 'Frontend', method: 'refresh_required', params: {} }));
1398
1219
  }
1399
1220
  });
1400
1221
  }
1401
- /**
1402
- * Sends a need to restart WebSocket message to all connected clients.
1403
- *
1404
- */
1405
1222
  wssSendRestartRequired() {
1406
1223
  this.log.debug('Sending a restart required message to all connected clients');
1407
1224
  this.matterbridge.matterbridgeInformation.restartRequired = true;
1408
- // Send the message to all connected clients
1409
1225
  this.webSocketServer?.clients.forEach((client) => {
1410
1226
  if (client.readyState === WebSocket.OPEN) {
1411
1227
  client.send(JSON.stringify({ id: WS_ID_RESTART_NEEDED, src: 'Matterbridge', dst: 'Frontend', method: 'restart_required', params: {} }));
@@ -1413,4 +1229,3 @@ export class Frontend {
1413
1229
  });
1414
1230
  }
1415
1231
  }
1416
- //# sourceMappingURL=frontend.js.map