matterbridge 2.1.1 → 2.1.2-dev.3

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (111) hide show
  1. package/CHANGELOG.md +17 -0
  2. package/dist/cli.js +0 -26
  3. package/dist/cluster/export.js +0 -2
  4. package/dist/defaultConfigSchema.js +0 -23
  5. package/dist/deviceManager.js +3 -29
  6. package/dist/frontend.js +51 -245
  7. package/dist/index.js +0 -28
  8. package/dist/logger/export.js +0 -1
  9. package/dist/matter/behaviors.js +0 -2
  10. package/dist/matter/clusters.js +0 -2
  11. package/dist/matter/devices.js +0 -2
  12. package/dist/matter/endpoints.js +0 -2
  13. package/dist/matter/export.js +1 -2
  14. package/dist/matter/types.js +0 -2
  15. package/dist/matterbridge.js +38 -752
  16. package/dist/matterbridgeAccessoryPlatform.js +0 -33
  17. package/dist/matterbridgeBehaviors.js +1 -32
  18. package/dist/matterbridgeDeviceTypes.js +11 -112
  19. package/dist/matterbridgeDynamicPlatform.js +0 -33
  20. package/dist/matterbridgeEndpoint.js +6 -690
  21. package/dist/matterbridgeEndpointHelpers.js +0 -96
  22. package/dist/matterbridgePlatform.js +9 -129
  23. package/dist/matterbridgeTypes.js +0 -24
  24. package/dist/pluginManager.js +5 -243
  25. package/dist/storage/export.js +0 -1
  26. package/dist/utils/colorUtils.js +2 -205
  27. package/dist/utils/export.js +0 -1
  28. package/dist/utils/utils.js +7 -251
  29. package/npm-shrinkwrap.json +2 -2
  30. package/package.json +1 -2
  31. package/dist/cli.d.ts +0 -25
  32. package/dist/cli.d.ts.map +0 -1
  33. package/dist/cli.js.map +0 -1
  34. package/dist/cluster/export.d.ts +0 -2
  35. package/dist/cluster/export.d.ts.map +0 -1
  36. package/dist/cluster/export.js.map +0 -1
  37. package/dist/defaultConfigSchema.d.ts +0 -27
  38. package/dist/defaultConfigSchema.d.ts.map +0 -1
  39. package/dist/defaultConfigSchema.js.map +0 -1
  40. package/dist/deviceManager.d.ts +0 -46
  41. package/dist/deviceManager.d.ts.map +0 -1
  42. package/dist/deviceManager.js.map +0 -1
  43. package/dist/frontend.d.ts +0 -109
  44. package/dist/frontend.d.ts.map +0 -1
  45. package/dist/frontend.js.map +0 -1
  46. package/dist/index.d.ts +0 -35
  47. package/dist/index.d.ts.map +0 -1
  48. package/dist/index.js.map +0 -1
  49. package/dist/logger/export.d.ts +0 -2
  50. package/dist/logger/export.d.ts.map +0 -1
  51. package/dist/logger/export.js.map +0 -1
  52. package/dist/matter/behaviors.d.ts +0 -2
  53. package/dist/matter/behaviors.d.ts.map +0 -1
  54. package/dist/matter/behaviors.js.map +0 -1
  55. package/dist/matter/clusters.d.ts +0 -2
  56. package/dist/matter/clusters.d.ts.map +0 -1
  57. package/dist/matter/clusters.js.map +0 -1
  58. package/dist/matter/devices.d.ts +0 -2
  59. package/dist/matter/devices.d.ts.map +0 -1
  60. package/dist/matter/devices.js.map +0 -1
  61. package/dist/matter/endpoints.d.ts +0 -2
  62. package/dist/matter/endpoints.d.ts.map +0 -1
  63. package/dist/matter/endpoints.js.map +0 -1
  64. package/dist/matter/export.d.ts +0 -4
  65. package/dist/matter/export.d.ts.map +0 -1
  66. package/dist/matter/export.js.map +0 -1
  67. package/dist/matter/types.d.ts +0 -3
  68. package/dist/matter/types.d.ts.map +0 -1
  69. package/dist/matter/types.js.map +0 -1
  70. package/dist/matterbridge.d.ts +0 -409
  71. package/dist/matterbridge.d.ts.map +0 -1
  72. package/dist/matterbridge.js.map +0 -1
  73. package/dist/matterbridgeAccessoryPlatform.d.ts +0 -39
  74. package/dist/matterbridgeAccessoryPlatform.d.ts.map +0 -1
  75. package/dist/matterbridgeAccessoryPlatform.js.map +0 -1
  76. package/dist/matterbridgeBehaviors.d.ts +0 -1056
  77. package/dist/matterbridgeBehaviors.d.ts.map +0 -1
  78. package/dist/matterbridgeBehaviors.js.map +0 -1
  79. package/dist/matterbridgeDeviceTypes.d.ts +0 -177
  80. package/dist/matterbridgeDeviceTypes.d.ts.map +0 -1
  81. package/dist/matterbridgeDeviceTypes.js.map +0 -1
  82. package/dist/matterbridgeDynamicPlatform.d.ts +0 -39
  83. package/dist/matterbridgeDynamicPlatform.d.ts.map +0 -1
  84. package/dist/matterbridgeDynamicPlatform.js.map +0 -1
  85. package/dist/matterbridgeEndpoint.d.ts +0 -834
  86. package/dist/matterbridgeEndpoint.d.ts.map +0 -1
  87. package/dist/matterbridgeEndpoint.js.map +0 -1
  88. package/dist/matterbridgeEndpointHelpers.d.ts +0 -2262
  89. package/dist/matterbridgeEndpointHelpers.d.ts.map +0 -1
  90. package/dist/matterbridgeEndpointHelpers.js.map +0 -1
  91. package/dist/matterbridgePlatform.d.ts +0 -164
  92. package/dist/matterbridgePlatform.d.ts.map +0 -1
  93. package/dist/matterbridgePlatform.js.map +0 -1
  94. package/dist/matterbridgeTypes.d.ts +0 -165
  95. package/dist/matterbridgeTypes.d.ts.map +0 -1
  96. package/dist/matterbridgeTypes.js.map +0 -1
  97. package/dist/pluginManager.d.ts +0 -238
  98. package/dist/pluginManager.d.ts.map +0 -1
  99. package/dist/pluginManager.js.map +0 -1
  100. package/dist/storage/export.d.ts +0 -2
  101. package/dist/storage/export.d.ts.map +0 -1
  102. package/dist/storage/export.js.map +0 -1
  103. package/dist/utils/colorUtils.d.ts +0 -61
  104. package/dist/utils/colorUtils.d.ts.map +0 -1
  105. package/dist/utils/colorUtils.js.map +0 -1
  106. package/dist/utils/export.d.ts +0 -3
  107. package/dist/utils/export.d.ts.map +0 -1
  108. package/dist/utils/export.js.map +0 -1
  109. package/dist/utils/utils.d.ts +0 -221
  110. package/dist/utils/utils.d.ts.map +0 -1
  111. package/dist/utils/utils.js.map +0 -1
@@ -1,26 +1,3 @@
1
- /**
2
- * This file contains the class Matterbridge.
3
- *
4
- * @file matterbridge.ts
5
- * @author Luca Liguori
6
- * @date 2023-12-29
7
- * @version 1.5.2
8
- *
9
- * Copyright 2023, 2024, 2025 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
- // Node.js modules
24
1
  import { fileURLToPath } from 'url';
25
2
  import { promises as fs } from 'fs';
26
3
  import { exec, spawn } from 'child_process';
@@ -28,27 +5,20 @@ import EventEmitter from 'events';
28
5
  import os from 'os';
29
6
  import path from 'path';
30
7
  import { randomBytes } from 'crypto';
31
- // NodeStorage and AnsiLogger modules
32
8
  import { NodeStorageManager } from './storage/export.js';
33
9
  import { AnsiLogger, UNDERLINE, UNDERLINEOFF, YELLOW, db, debugStringify, BRIGHT, RESET, er, nf, rs, wr, RED, GREEN, zb, CYAN, nt } from './logger/export.js';
34
- // Matterbridge
35
10
  import { logInterfaces, copyDirectory, getParameter, getIntParameter, hasParameter } from './utils/utils.js';
36
11
  import { PluginManager } from './pluginManager.js';
37
12
  import { DeviceManager } from './deviceManager.js';
38
13
  import { MatterbridgeEndpoint } from './matterbridgeEndpoint.js';
39
14
  import { bridge } from './matterbridgeDeviceTypes.js';
40
15
  import { Frontend } from './frontend.js';
41
- // @matter
42
16
  import { DeviceTypeId, Endpoint as EndpointNode, Logger, LogLevel as MatterLogLevel, LogFormat as MatterLogFormat, VendorId, StorageService, Environment, ServerNode } from '@matter/main';
43
17
  import { DeviceCommissioner, FabricAction, PaseClient } from '@matter/main/protocol';
44
18
  import { AggregatorEndpoint } from '@matter/main/endpoints';
45
- // Default colors
46
19
  const plg = '\u001B[38;5;33m';
47
20
  const dev = '\u001B[38;5;79m';
48
21
  const typ = '\u001B[38;5;207m';
49
- /**
50
- * Represents the Matterbridge application.
51
- */
52
22
  export class Matterbridge extends EventEmitter {
53
23
  systemInformation = {
54
24
  interfaceName: '',
@@ -65,6 +35,8 @@ export class Matterbridge extends EventEmitter {
65
35
  totalMemory: '',
66
36
  freeMemory: '',
67
37
  systemUptime: '',
38
+ rss: '',
39
+ heap: '',
68
40
  };
69
41
  matterbridgeInformation = {
70
42
  homeDirectory: '',
@@ -83,7 +55,7 @@ export class Matterbridge extends EventEmitter {
83
55
  restartMode: '',
84
56
  readOnly: hasParameter('readonly'),
85
57
  profile: getParameter('profile'),
86
- loggerLevel: "info" /* LogLevel.INFO */,
58
+ loggerLevel: "info",
87
59
  fileLogger: false,
88
60
  matterLoggerLevel: MatterLogLevel.INFO,
89
61
  matterFileLogger: false,
@@ -118,11 +90,9 @@ export class Matterbridge extends EventEmitter {
118
90
  plugins;
119
91
  devices;
120
92
  frontend = new Frontend(this);
121
- // Matterbridge storage
122
93
  nodeStorage;
123
94
  nodeContext;
124
95
  nodeStorageName = 'storage' + (getParameter('profile') ? '.' + getParameter('profile') : '');
125
- // Cleanup
126
96
  hasCleanupStarted = false;
127
97
  initialized = false;
128
98
  execRunningCount = 0;
@@ -134,57 +104,34 @@ export class Matterbridge extends EventEmitter {
134
104
  sigtermHandler;
135
105
  exceptionHandler;
136
106
  rejectionHandler;
137
- // Matter environment
138
107
  environment = Environment.default;
139
- // Matter storage
140
108
  matterStorageName = 'matterstorage' + (getParameter('profile') ? '.' + getParameter('profile') : '');
141
109
  matterStorageService;
142
110
  matterStorageManager;
143
111
  matterbridgeContext;
144
112
  mattercontrollerContext;
145
- // Matter parameters
146
- mdnsInterface; // matter server node mdnsInterface: e.g. 'eth0' or 'wlan0' or 'WiFi'
147
- ipv4address; // matter server node listeningAddressIpv4
148
- ipv6address; // matter server node listeningAddressIpv6
149
- port; // first server node port
150
- passcode; // first server node passcode
151
- discriminator; // first server node discriminator
113
+ mdnsInterface;
114
+ ipv4address;
115
+ ipv6address;
116
+ port;
117
+ passcode;
118
+ discriminator;
152
119
  serverNode;
153
120
  aggregatorNode;
154
121
  aggregatorVendorId = VendorId(getIntParameter('vendorId') ?? 0xfff1);
155
122
  aggregatorProductId = getIntParameter('productId') ?? 0x8000;
156
123
  static instance;
157
- // We load asyncronously so is private
158
124
  constructor() {
159
125
  super();
160
126
  }
161
- /**
162
- * Retrieves the list of Matterbridge devices.
163
- * @returns {MatterbridgeEndpoint[]} An array of MatterbridgeDevice objects.
164
- */
165
127
  getDevices() {
166
128
  return this.devices.array();
167
129
  }
168
- /**
169
- * Retrieves the list of registered plugins.
170
- * @returns {RegisteredPlugin[]} An array of RegisteredPlugin objects.
171
- */
172
130
  getPlugins() {
173
131
  return this.plugins.array();
174
132
  }
175
- /** ***********************************************************************************************************************************/
176
- /** loadInstance() and cleanup() methods */
177
- /** ***********************************************************************************************************************************/
178
- /**
179
- * Loads an instance of the Matterbridge class.
180
- * If an instance already exists, return that instance.
181
- *
182
- * @param initialize - Whether to initialize the Matterbridge instance after loading.
183
- * @returns The loaded Matterbridge instance.
184
- */
185
133
  static async loadInstance(initialize = false) {
186
134
  if (!Matterbridge.instance) {
187
- // eslint-disable-next-line no-console
188
135
  if (hasParameter('debug'))
189
136
  console.log(GREEN + 'Creating a new instance of Matterbridge.', initialize ? 'Initializing...' : 'Not initializing...', rs);
190
137
  Matterbridge.instance = new Matterbridge();
@@ -193,89 +140,48 @@ export class Matterbridge extends EventEmitter {
193
140
  }
194
141
  return Matterbridge.instance;
195
142
  }
196
- /**
197
- * Call cleanup().
198
- * @deprecated This method is deprecated and is only used for jest tests.
199
- *
200
- */
201
143
  async destroyInstance() {
202
144
  await this.cleanup('destroying instance...', false);
203
- /*
204
- await waiter(
205
- 'destroying instance...',
206
- () => {
207
- return this.initialized === false && this.execRunningCount <= 0 ? true : false;
208
- },
209
- false,
210
- 60000,
211
- 100,
212
- false,
213
- );
214
- await wait(1000, 'Wait for the global node_modules and matterbridge version', false);
215
- */
216
145
  }
217
- /**
218
- * Initializes the Matterbridge application.
219
- *
220
- * @remarks
221
- * This method performs the necessary setup and initialization steps for the Matterbridge application.
222
- * It displays the help information if the 'help' parameter is provided, sets up the logger, checks the
223
- * node version, registers signal handlers, initializes storage, and parses the command line.
224
- *
225
- * @returns A Promise that resolves when the initialization is complete.
226
- */
227
146
  async initialize() {
228
- // Set the restart mode
229
147
  if (hasParameter('service'))
230
148
  this.restartMode = 'service';
231
149
  if (hasParameter('docker'))
232
150
  this.restartMode = 'docker';
233
- // Set the matterbridge directory
234
151
  this.homeDirectory = getParameter('homedir') ?? os.homedir();
235
152
  this.matterbridgeDirectory = path.join(this.homeDirectory, '.matterbridge');
236
- // Setup matter environment
237
153
  this.environment.vars.set('log.level', MatterLogLevel.INFO);
238
154
  this.environment.vars.set('log.format', MatterLogFormat.ANSI);
239
155
  this.environment.vars.set('path.root', path.join(this.matterbridgeDirectory, this.matterStorageName));
240
156
  this.environment.vars.set('runtime.signals', false);
241
157
  this.environment.vars.set('runtime.exitcode', false);
242
- // Create matterbridge logger
243
- this.log = new AnsiLogger({ logName: 'Matterbridge', logTimestampFormat: 4 /* TimestampFormat.TIME_MILLIS */, logLevel: hasParameter('debug') ? "debug" /* LogLevel.DEBUG */ : "info" /* LogLevel.INFO */ });
244
- // Register process handlers
158
+ this.log = new AnsiLogger({ logName: 'Matterbridge', logTimestampFormat: 4, logLevel: hasParameter('debug') ? "debug" : "info" });
245
159
  this.registerProcessHandlers();
246
- // Initialize nodeStorage and nodeContext
247
160
  try {
248
161
  this.log.debug(`Creating node storage manager: ${CYAN}${this.nodeStorageName}${db}`);
249
162
  this.nodeStorage = new NodeStorageManager({ dir: path.join(this.matterbridgeDirectory, this.nodeStorageName), writeQueue: false, expiredInterval: undefined, logging: false });
250
163
  this.log.debug('Creating node storage context for matterbridge');
251
164
  this.nodeContext = await this.nodeStorage.createStorage('matterbridge');
252
- // TODO: Remove this code when node-persist-manager is updated
253
- // eslint-disable-next-line @typescript-eslint/no-explicit-any
254
165
  const keys = (await this.nodeStorage?.storage.keys());
255
166
  for (const key of keys) {
256
167
  this.log.debug(`Checking node storage manager key: ${CYAN}${key}${db}`);
257
- // eslint-disable-next-line @typescript-eslint/no-explicit-any
258
168
  await this.nodeStorage?.storage.get(key);
259
169
  }
260
170
  const storages = await this.nodeStorage.getStorageNames();
261
171
  for (const storage of storages) {
262
172
  this.log.debug(`Checking storage: ${CYAN}${storage}${db}`);
263
173
  const nodeContext = await this.nodeStorage?.createStorage(storage);
264
- // TODO: Remove this code when node-persist-manager is updated
265
- // eslint-disable-next-line @typescript-eslint/no-explicit-any
266
174
  const keys = (await nodeContext?.storage.keys());
267
175
  keys.forEach(async (key) => {
268
176
  this.log.debug(`Checking key: ${CYAN}${storage}:${key}${db}`);
269
177
  await nodeContext?.get(key);
270
178
  });
271
179
  }
272
- // Creating a backup of the node storage since it is not corrupted
273
180
  this.log.debug('Creating node storage backup...');
274
181
  await copyDirectory(path.join(this.matterbridgeDirectory, this.nodeStorageName), path.join(this.matterbridgeDirectory, this.nodeStorageName + '.backup'));
275
182
  this.log.debug('Created node storage backup');
276
183
  }
277
184
  catch (error) {
278
- // Restoring the backup of the node storage since it is corrupted
279
185
  this.log.error(`Error creating node storage manager and context: ${error instanceof Error ? error.message : error}`);
280
186
  if (hasParameter('norestore')) {
281
187
  this.log.fatal(`The matterbridge node storage is corrupted. Parameter -norestore found: exiting...`);
@@ -290,51 +196,45 @@ export class Matterbridge extends EventEmitter {
290
196
  this.log.fatal('Fatal error creating node storage manager and context for matterbridge');
291
197
  throw new Error('Fatal error creating node storage manager and context for matterbridge');
292
198
  }
293
- // Set the first port to use for the commissioning server (will be incremented in childbridge mode)
294
199
  this.port = getIntParameter('port') ?? (await this.nodeContext.get('matterport', 5540)) ?? 5540;
295
- // Set the first passcode to use for the commissioning server (will be incremented in childbridge mode)
296
200
  this.passcode = getIntParameter('passcode') ?? (await this.nodeContext.get('matterpasscode')) ?? PaseClient.generateRandomPasscode();
297
- // Set the first discriminator to use for the commissioning server (will be incremented in childbridge mode)
298
201
  this.discriminator = getIntParameter('discriminator') ?? (await this.nodeContext.get('matterdiscriminator')) ?? PaseClient.generateRandomDiscriminator();
299
202
  this.log.debug(`Initializing commissioning server for Matterbridge... on port ${this.port} with passcode ${this.passcode} and discriminator ${this.discriminator}`);
300
- // Set matterbridge logger level (context: matterbridgeLogLevel)
301
203
  if (hasParameter('logger')) {
302
204
  const level = getParameter('logger');
303
205
  if (level === 'debug') {
304
- this.log.logLevel = "debug" /* LogLevel.DEBUG */;
206
+ this.log.logLevel = "debug";
305
207
  }
306
208
  else if (level === 'info') {
307
- this.log.logLevel = "info" /* LogLevel.INFO */;
209
+ this.log.logLevel = "info";
308
210
  }
309
211
  else if (level === 'notice') {
310
- this.log.logLevel = "notice" /* LogLevel.NOTICE */;
212
+ this.log.logLevel = "notice";
311
213
  }
312
214
  else if (level === 'warn') {
313
- this.log.logLevel = "warn" /* LogLevel.WARN */;
215
+ this.log.logLevel = "warn";
314
216
  }
315
217
  else if (level === 'error') {
316
- this.log.logLevel = "error" /* LogLevel.ERROR */;
218
+ this.log.logLevel = "error";
317
219
  }
318
220
  else if (level === 'fatal') {
319
- this.log.logLevel = "fatal" /* LogLevel.FATAL */;
221
+ this.log.logLevel = "fatal";
320
222
  }
321
223
  else {
322
224
  this.log.warn(`Invalid matterbridge logger level: ${level}. Using default level "info".`);
323
- this.log.logLevel = "info" /* LogLevel.INFO */;
225
+ this.log.logLevel = "info";
324
226
  }
325
227
  }
326
228
  else {
327
- this.log.logLevel = await this.nodeContext.get('matterbridgeLogLevel', "info" /* LogLevel.INFO */);
229
+ this.log.logLevel = await this.nodeContext.get('matterbridgeLogLevel', "info");
328
230
  }
329
231
  MatterbridgeEndpoint.logLevel = this.log.logLevel;
330
- // Create the file logger for matterbridge (context: matterbridgeFileLog)
331
232
  if (hasParameter('filelogger') || (await this.nodeContext.get('matterbridgeFileLog', false))) {
332
233
  AnsiLogger.setGlobalLogfile(path.join(this.matterbridgeDirectory, this.matterbrideLoggerFile), this.log.logLevel, true);
333
234
  this.matterbridgeInformation.fileLogger = true;
334
235
  }
335
236
  this.log.notice('Matterbridge is starting...');
336
237
  this.log.debug(`Matterbridge logLevel: ${this.log.logLevel} fileLoger: ${this.matterbridgeInformation.fileLogger}.`);
337
- // Set matter.js logger level, format and logger (context: matterLogLevel)
338
238
  if (hasParameter('matterlogger')) {
339
239
  const level = getParameter('matterlogger');
340
240
  if (level === 'debug') {
@@ -365,7 +265,6 @@ export class Matterbridge extends EventEmitter {
365
265
  }
366
266
  Logger.format = MatterLogFormat.ANSI;
367
267
  Logger.setLogger('default', this.createMatterLogger());
368
- // Create the file logger for matter.js (context: matterFileLog)
369
268
  if (hasParameter('matterfilelogger') || (await this.nodeContext.get('matterFileLog', false))) {
370
269
  this.matterbridgeInformation.matterFileLogger = true;
371
270
  Logger.addLogger('matterfilelogger', await this.createMatterFileLogger(path.join(this.matterbridgeDirectory, this.matterLoggerFile), true), {
@@ -374,7 +273,6 @@ export class Matterbridge extends EventEmitter {
374
273
  });
375
274
  }
376
275
  this.log.debug(`Matter logLevel: ${Logger.defaultLogLevel} fileLoger: ${this.matterbridgeInformation.matterFileLogger}.`);
377
- // Set the interface to use for matter server node mdnsInterface
378
276
  if (hasParameter('mdnsinterface')) {
379
277
  this.mdnsInterface = getParameter('mdnsinterface');
380
278
  }
@@ -383,7 +281,6 @@ export class Matterbridge extends EventEmitter {
383
281
  if (this.mdnsInterface === '')
384
282
  this.mdnsInterface = undefined;
385
283
  }
386
- // Validate mdnsInterface
387
284
  if (this.mdnsInterface) {
388
285
  const networkInterfaces = os.networkInterfaces();
389
286
  const availableInterfaces = Object.keys(networkInterfaces);
@@ -397,7 +294,6 @@ export class Matterbridge extends EventEmitter {
397
294
  }
398
295
  if (this.mdnsInterface)
399
296
  this.environment.vars.set('mdns.networkInterface', this.mdnsInterface);
400
- // Set the listeningAddressIpv4 for the matter commissioning server
401
297
  if (hasParameter('ipv4address')) {
402
298
  this.ipv4address = getParameter('ipv4address');
403
299
  }
@@ -406,7 +302,6 @@ export class Matterbridge extends EventEmitter {
406
302
  if (this.ipv4address === '')
407
303
  this.ipv4address = undefined;
408
304
  }
409
- // Set the listeningAddressIpv6 for the matter commissioning server
410
305
  if (hasParameter('ipv6address')) {
411
306
  this.ipv6address = getParameter('ipv6address');
412
307
  }
@@ -415,19 +310,14 @@ export class Matterbridge extends EventEmitter {
415
310
  if (this.ipv6address === '')
416
311
  this.ipv6address = undefined;
417
312
  }
418
- // Initialize PluginManager
419
313
  this.plugins = new PluginManager(this);
420
314
  await this.plugins.loadFromStorage();
421
315
  this.plugins.logLevel = this.log.logLevel;
422
- // Initialize DeviceManager
423
316
  this.devices = new DeviceManager(this, this.nodeContext);
424
317
  this.devices.logLevel = this.log.logLevel;
425
- // Get the plugins from node storage and create the plugins node storage contexts
426
318
  for (const plugin of this.plugins) {
427
319
  const packageJson = await this.plugins.parse(plugin);
428
320
  if (packageJson === null && !hasParameter('add') && !hasParameter('remove') && !hasParameter('enable') && !hasParameter('disable') && !hasParameter('reset') && !hasParameter('factoryreset')) {
429
- // Try to reinstall the plugin from npm (for Docker pull and external plugins)
430
- // We don't do this when the add and other parameters are set because we shut down the process after adding the plugin
431
321
  this.log.info(`Error parsing plugin ${plg}${plugin.name}${nf}. Trying to reinstall it from npm.`);
432
322
  try {
433
323
  await this.spawnCommand('npm', ['install', '-g', plugin.name, '--omit=dev', '--verbose']);
@@ -449,7 +339,6 @@ export class Matterbridge extends EventEmitter {
449
339
  await plugin.nodeContext.set('description', plugin.description);
450
340
  await plugin.nodeContext.set('author', plugin.author);
451
341
  }
452
- // Log system info and create .matterbridge directory
453
342
  await this.logNodeAndSystemInfo();
454
343
  this.log.notice(`Matterbridge version ${this.matterbridgeVersion} ` +
455
344
  `${hasParameter('bridge') || (!hasParameter('childbridge') && (await this.nodeContext?.get('bridgeMode', '')) === 'bridge') ? 'mode bridge ' : ''}` +
@@ -457,7 +346,6 @@ export class Matterbridge extends EventEmitter {
457
346
  `${hasParameter('controller') ? 'mode controller ' : ''}` +
458
347
  `${this.restartMode !== '' ? 'restart mode ' + this.restartMode + ' ' : ''}` +
459
348
  `running on ${this.systemInformation.osType} (v.${this.systemInformation.osRelease}) platform ${this.systemInformation.osPlatform} arch ${this.systemInformation.osArch}`);
460
- // Check node version and throw error
461
349
  const minNodeVersion = 18;
462
350
  const nodeVersion = process.versions.node;
463
351
  const versionMajor = parseInt(nodeVersion.split('.')[0]);
@@ -465,15 +353,9 @@ export class Matterbridge extends EventEmitter {
465
353
  this.log.error(`Node version ${versionMajor} is not supported. Please upgrade to ${minNodeVersion} or above.`);
466
354
  throw new Error(`Node version ${versionMajor} is not supported. Please upgrade to ${minNodeVersion} or above.`);
467
355
  }
468
- // Parse command line
469
356
  await this.parseCommandLine();
470
357
  this.initialized = true;
471
358
  }
472
- /**
473
- * Parses the command line arguments and performs the corresponding actions.
474
- * @private
475
- * @returns {Promise<void>} A promise that resolves when the command line arguments have been processed, or the process exits.
476
- */
477
359
  async parseCommandLine() {
478
360
  if (hasParameter('help')) {
479
361
  this.log.info(`\nUsage: matterbridge [options]\n
@@ -583,7 +465,6 @@ export class Matterbridge extends EventEmitter {
583
465
  await this.shutdownProcessAndFactoryReset();
584
466
  return;
585
467
  }
586
- // Start the matter storage and create the matterbridge context
587
468
  try {
588
469
  await this.startMatterStorage();
589
470
  }
@@ -591,12 +472,10 @@ export class Matterbridge extends EventEmitter {
591
472
  this.log.fatal(`Fatal error creating matter storage: ${error instanceof Error ? error.message : error}`);
592
473
  throw new Error(`Fatal error creating matter storage: ${error instanceof Error ? error.message : error}`);
593
474
  }
594
- // Clear the matterbridge context if the reset parameter is set
595
475
  if (hasParameter('reset') && getParameter('reset') === undefined) {
596
476
  await this.shutdownProcessAndReset();
597
477
  return;
598
478
  }
599
- // Clear matterbridge plugin context if the reset parameter is set
600
479
  if (hasParameter('reset') && getParameter('reset') !== undefined) {
601
480
  this.log.debug(`Reset plugin ${getParameter('reset')}`);
602
481
  const plugin = this.plugins.get(getParameter('reset'));
@@ -618,11 +497,9 @@ export class Matterbridge extends EventEmitter {
618
497
  this.emit('shutdown');
619
498
  return;
620
499
  }
621
- // Initialize frontend
622
500
  if (getIntParameter('frontend') !== 0 || getIntParameter('frontend') === undefined)
623
501
  await this.frontend.start(getIntParameter('frontend'));
624
502
  this.frontend.logLevel = this.log.logLevel;
625
- // Check each 60 minutes the latest versions
626
503
  this.checkUpdateInterval = setInterval(() => {
627
504
  this.getMatterbridgeLatestVersion();
628
505
  for (const plugin of this.plugins) {
@@ -630,24 +507,20 @@ export class Matterbridge extends EventEmitter {
630
507
  }
631
508
  this.frontend.wssSendRefreshRequired();
632
509
  }, 60 * 60 * 1000);
633
- // Start the matterbridge in mode test
634
510
  if (hasParameter('test')) {
635
511
  this.bridgeMode = 'bridge';
636
512
  MatterbridgeEndpoint.bridgeMode = 'bridge';
637
513
  return;
638
514
  }
639
- // Start the matterbridge in mode controller
640
515
  if (hasParameter('controller')) {
641
516
  this.bridgeMode = 'controller';
642
517
  await this.startController();
643
518
  return;
644
519
  }
645
- // Check if the bridge mode is set and start matterbridge in bridge mode if not set
646
520
  if (!hasParameter('bridge') && !hasParameter('childbridge') && (await this.nodeContext?.get('bridgeMode', '')) === '') {
647
521
  this.log.info('Setting default matterbridge start mode to bridge');
648
522
  await this.nodeContext?.set('bridgeMode', 'bridge');
649
523
  }
650
- // Start matterbridge in bridge mode
651
524
  if (hasParameter('bridge') || (!hasParameter('childbridge') && (await this.nodeContext?.get('bridgeMode', '')) === 'bridge')) {
652
525
  this.bridgeMode = 'bridge';
653
526
  MatterbridgeEndpoint.bridgeMode = 'bridge';
@@ -655,7 +528,6 @@ export class Matterbridge extends EventEmitter {
655
528
  await this.startBridge();
656
529
  return;
657
530
  }
658
- // Start matterbridge in childbridge mode
659
531
  if (hasParameter('childbridge') || (!hasParameter('bridge') && (await this.nodeContext?.get('bridgeMode', '')) === 'childbridge')) {
660
532
  this.bridgeMode = 'childbridge';
661
533
  MatterbridgeEndpoint.bridgeMode = 'childbridge';
@@ -664,28 +536,16 @@ export class Matterbridge extends EventEmitter {
664
536
  return;
665
537
  }
666
538
  }
667
- /**
668
- * Asynchronously loads and starts the registered plugins.
669
- *
670
- * This method is responsible for initializing and staarting all enabled plugins.
671
- * It ensures that each plugin is properly loaded and started before the bridge starts.
672
- *
673
- * @returns {Promise<void>} A promise that resolves when all plugins have been loaded and started.
674
- */
675
539
  async startPlugins() {
676
- // Check, load and start the plugins
677
540
  for (const plugin of this.plugins) {
678
541
  plugin.configJson = await this.plugins.loadConfig(plugin);
679
542
  plugin.schemaJson = await this.plugins.loadSchema(plugin);
680
- // Check if the plugin is available
681
543
  if (!(await this.plugins.resolve(plugin.path))) {
682
544
  this.log.error(`Plugin ${plg}${plugin.name}${er} not found or not validated. Disabling it.`);
683
545
  plugin.enabled = false;
684
546
  plugin.error = true;
685
547
  continue;
686
548
  }
687
- // Check if the plugin has a new version
688
- // this.getPluginLatestVersion(plugin); // No await do it asyncronously
689
549
  if (!plugin.enabled) {
690
550
  this.log.info(`Plugin ${plg}${plugin.name}${nf} not enabled`);
691
551
  continue;
@@ -699,26 +559,20 @@ export class Matterbridge extends EventEmitter {
699
559
  plugin.addedDevices = undefined;
700
560
  plugin.qrPairingCode = undefined;
701
561
  plugin.manualPairingCode = undefined;
702
- this.plugins.load(plugin, true, 'Matterbridge is starting'); // No await do it asyncronously
562
+ this.plugins.load(plugin, true, 'Matterbridge is starting');
703
563
  }
704
564
  this.frontend.wssSendRefreshRequired();
705
565
  }
706
- /**
707
- * Registers the process handlers for uncaughtException, unhandledRejection, SIGINT and SIGTERM.
708
- * When either of these signals are received, the cleanup method is called with an appropriate message.
709
- */
710
566
  registerProcessHandlers() {
711
567
  this.log.debug(`Registering uncaughtException and unhandledRejection handlers...`);
712
568
  process.removeAllListeners('uncaughtException');
713
569
  process.removeAllListeners('unhandledRejection');
714
570
  this.exceptionHandler = async (error) => {
715
571
  this.log.fatal('Unhandled Exception detected at:', error.stack || error, rs);
716
- // await this.cleanup('Unhandled Exception detected, cleaning up...');
717
572
  };
718
573
  process.on('uncaughtException', this.exceptionHandler);
719
574
  this.rejectionHandler = async (reason, promise) => {
720
575
  this.log.fatal('Unhandled Rejection detected at:', promise, 'reason:', reason instanceof Error ? reason.stack : reason, rs);
721
- // await this.cleanup('Unhandled Rejection detected, cleaning up...');
722
576
  };
723
577
  process.on('unhandledRejection', this.rejectionHandler);
724
578
  this.log.debug(`Registering SIGINT and SIGTERM signal handlers...`);
@@ -731,9 +585,6 @@ export class Matterbridge extends EventEmitter {
731
585
  };
732
586
  process.on('SIGTERM', this.sigtermHandler);
733
587
  }
734
- /**
735
- * Deregisters the process uncaughtException, unhandledRejection, SIGINT and SIGTERM signal handlers.
736
- */
737
588
  deregisterProcesslHandlers() {
738
589
  this.log.debug(`Deregistering uncaughtException and unhandledRejection handlers...`);
739
590
  if (this.exceptionHandler)
@@ -750,17 +601,12 @@ export class Matterbridge extends EventEmitter {
750
601
  process.off('SIGTERM', this.sigtermHandler);
751
602
  this.sigtermHandler = undefined;
752
603
  }
753
- /**
754
- * Logs the node and system information.
755
- */
756
604
  async logNodeAndSystemInfo() {
757
- // IP address information
758
605
  const networkInterfaces = os.networkInterfaces();
759
606
  this.systemInformation.interfaceName = '';
760
607
  this.systemInformation.ipv4Address = '';
761
608
  this.systemInformation.ipv6Address = '';
762
609
  for (const [interfaceName, interfaceDetails] of Object.entries(networkInterfaces)) {
763
- // this.log.debug(`Checking interface: '${interfaceName}' for '${this.mdnsInterface}'`);
764
610
  if (this.mdnsInterface && interfaceName !== this.mdnsInterface)
765
611
  continue;
766
612
  if (!interfaceDetails) {
@@ -786,22 +632,19 @@ export class Matterbridge extends EventEmitter {
786
632
  break;
787
633
  }
788
634
  }
789
- // Node information
790
635
  this.systemInformation.nodeVersion = process.versions.node;
791
636
  const versionMajor = parseInt(this.systemInformation.nodeVersion.split('.')[0]);
792
637
  const versionMinor = parseInt(this.systemInformation.nodeVersion.split('.')[1]);
793
638
  const versionPatch = parseInt(this.systemInformation.nodeVersion.split('.')[2]);
794
- // Host system information
795
639
  this.systemInformation.hostname = os.hostname();
796
640
  this.systemInformation.user = os.userInfo().username;
797
- this.systemInformation.osType = os.type(); // "Windows_NT", "Darwin", etc.
798
- this.systemInformation.osRelease = os.release(); // Kernel version
799
- this.systemInformation.osPlatform = os.platform(); // "win32", "linux", "darwin", etc.
800
- this.systemInformation.osArch = os.arch(); // "x64", "arm", etc.
801
- this.systemInformation.totalMemory = (os.totalmem() / 1024 / 1024 / 1024).toFixed(2) + ' GB'; // Convert to GB
802
- this.systemInformation.freeMemory = (os.freemem() / 1024 / 1024 / 1024).toFixed(2) + ' GB'; // Convert to GB
803
- this.systemInformation.systemUptime = (os.uptime() / 60 / 60).toFixed(2) + ' hours'; // Convert to hours
804
- // Log the system information
641
+ this.systemInformation.osType = os.type();
642
+ this.systemInformation.osRelease = os.release();
643
+ this.systemInformation.osPlatform = os.platform();
644
+ this.systemInformation.osArch = os.arch();
645
+ this.systemInformation.totalMemory = (os.totalmem() / 1024 / 1024 / 1024).toFixed(2) + ' GB';
646
+ this.systemInformation.freeMemory = (os.freemem() / 1024 / 1024 / 1024).toFixed(2) + ' GB';
647
+ this.systemInformation.systemUptime = (os.uptime() / 60 / 60).toFixed(2) + ' hours';
805
648
  this.log.debug('Host System Information:');
806
649
  this.log.debug(`- Hostname: ${this.systemInformation.hostname}`);
807
650
  this.log.debug(`- User: ${this.systemInformation.user}`);
@@ -817,19 +660,15 @@ export class Matterbridge extends EventEmitter {
817
660
  this.log.debug(`- Total Memory: ${this.systemInformation.totalMemory}`);
818
661
  this.log.debug(`- Free Memory: ${this.systemInformation.freeMemory}`);
819
662
  this.log.debug(`- System Uptime: ${this.systemInformation.systemUptime}`);
820
- // Home directory
821
663
  this.homeDirectory = getParameter('homedir') ?? os.homedir();
822
664
  this.matterbridgeInformation.homeDirectory = this.homeDirectory;
823
665
  this.log.debug(`Home Directory: ${this.homeDirectory}`);
824
- // Package root directory
825
666
  const currentFileDirectory = path.dirname(fileURLToPath(import.meta.url));
826
667
  this.rootDirectory = path.resolve(currentFileDirectory, '../');
827
668
  this.matterbridgeInformation.rootDirectory = this.rootDirectory;
828
669
  this.log.debug(`Root Directory: ${this.rootDirectory}`);
829
- // Global node_modules directory
830
670
  if (this.nodeContext)
831
671
  this.globalModulesDirectory = this.matterbridgeInformation.globalModulesDirectory = await this.nodeContext.get('globalModulesDirectory', '');
832
- // First run of Matterbridge so the node storage is empty
833
672
  if (this.globalModulesDirectory === '') {
834
673
  try {
835
674
  this.globalModulesDirectory = await this.getGlobalNodeModules();
@@ -843,20 +682,6 @@ export class Matterbridge extends EventEmitter {
843
682
  }
844
683
  else
845
684
  this.log.debug(`Global node_modules Directory: ${this.globalModulesDirectory}`);
846
- /* removed cause is too expensive for the shelly board and not really needed. Why should it change the globalModulesDirectory?
847
- else {
848
- this.getGlobalNodeModules()
849
- .then(async (globalModulesDirectory) => {
850
- this.globalModulesDirectory = globalModulesDirectory;
851
- this.matterbridgeInformation.globalModulesDirectory = this.globalModulesDirectory;
852
- this.log.debug(`Global node_modules Directory: ${this.globalModulesDirectory}`);
853
- await this.nodeContext?.set<string>('globalModulesDirectory', this.globalModulesDirectory);
854
- })
855
- .catch((error) => {
856
- this.log.error(`Error getting global node_modules directory: ${error}`);
857
- });
858
- }*/
859
- // Create the data directory .matterbridge in the home directory
860
685
  this.matterbridgeDirectory = path.join(this.homeDirectory, '.matterbridge');
861
686
  this.matterbridgeInformation.matterbridgeDirectory = this.matterbridgeDirectory;
862
687
  try {
@@ -880,7 +705,6 @@ export class Matterbridge extends EventEmitter {
880
705
  }
881
706
  }
882
707
  this.log.debug(`Matterbridge Directory: ${this.matterbridgeDirectory}`);
883
- // Create the plugin directory Matterbridge in the home directory
884
708
  this.matterbridgePluginDirectory = path.join(this.homeDirectory, 'Matterbridge');
885
709
  this.matterbridgeInformation.matterbridgePluginDirectory = this.matterbridgePluginDirectory;
886
710
  try {
@@ -904,28 +728,18 @@ export class Matterbridge extends EventEmitter {
904
728
  }
905
729
  }
906
730
  this.log.debug(`Matterbridge Plugin Directory: ${this.matterbridgePluginDirectory}`);
907
- // Matterbridge version
908
731
  const packageJson = JSON.parse(await fs.readFile(path.join(this.rootDirectory, 'package.json'), 'utf-8'));
909
732
  this.matterbridgeVersion = this.matterbridgeLatestVersion = packageJson.version;
910
733
  this.matterbridgeInformation.matterbridgeVersion = this.matterbridgeInformation.matterbridgeLatestVersion = this.matterbridgeVersion;
911
734
  this.log.debug(`Matterbridge Version: ${this.matterbridgeVersion}`);
912
- // Matterbridge latest version
913
735
  if (this.nodeContext)
914
736
  this.matterbridgeLatestVersion = await this.nodeContext.get('matterbridgeLatestVersion', this.matterbridgeVersion);
915
737
  this.log.debug(`Matterbridge Latest Version: ${this.matterbridgeLatestVersion}`);
916
- // this.getMatterbridgeLatestVersion();
917
- // Current working directory
918
738
  const currentDir = process.cwd();
919
739
  this.log.debug(`Current Working Directory: ${currentDir}`);
920
- // Command line arguments (excluding 'node' and the script name)
921
740
  const cmdArgs = process.argv.slice(2).join(' ');
922
741
  this.log.debug(`Command Line Arguments: ${cmdArgs}`);
923
742
  }
924
- /**
925
- * Retrieves the latest version of a package from the npm registry.
926
- * @param packageName - The name of the package.
927
- * @returns A Promise that resolves to the latest version of the package.
928
- */
929
743
  async getLatestVersion(packageName) {
930
744
  return new Promise((resolve, reject) => {
931
745
  this.execRunningCount++;
@@ -940,10 +754,6 @@ export class Matterbridge extends EventEmitter {
940
754
  });
941
755
  });
942
756
  }
943
- /**
944
- * Retrieves the path to the global Node.js modules directory.
945
- * @returns A promise that resolves to the path of the global Node.js modules directory.
946
- */
947
757
  async getGlobalNodeModules() {
948
758
  return new Promise((resolve, reject) => {
949
759
  this.execRunningCount++;
@@ -958,11 +768,6 @@ export class Matterbridge extends EventEmitter {
958
768
  });
959
769
  });
960
770
  }
961
- /**
962
- * Retrieves the latest version of Matterbridge and performs necessary actions based on the version comparison.
963
- * @private
964
- * @returns {Promise<void>} A promise that resolves when the latest version is retrieved and actions are performed.
965
- */
966
771
  async getMatterbridgeLatestVersion() {
967
772
  this.getLatestVersion('matterbridge')
968
773
  .then(async (matterbridgeLatestVersion) => {
@@ -979,19 +784,8 @@ export class Matterbridge extends EventEmitter {
979
784
  })
980
785
  .catch((error) => {
981
786
  this.log.error(`Error getting Matterbridge latest version: ${error.message}`);
982
- // error.stack && this.log.debug(error.stack);
983
787
  });
984
788
  }
985
- /**
986
- * Retrieves the latest version of a plugin and updates the plugin's latestVersion property.
987
- * If the plugin's version is different from the latest version, logs a warning message.
988
- * If the plugin's version is the same as the latest version, logs an info message.
989
- * If there is an error retrieving the latest version, logs an error message.
990
- *
991
- * @private
992
- * @param {RegisteredPlugin} plugin - The plugin for which to retrieve the latest version.
993
- * @returns {Promise<void>} A promise that resolves when the latest version is retrieved and actions are performed.
994
- */
995
789
  async getPluginLatestVersion(plugin) {
996
790
  this.getLatestVersion(plugin.name)
997
791
  .then(async (latestVersion) => {
@@ -1003,54 +797,40 @@ export class Matterbridge extends EventEmitter {
1003
797
  })
1004
798
  .catch((error) => {
1005
799
  this.log.error(`Error getting ${plg}${plugin.name}${er} latest version: ${error.message}`);
1006
- // error.stack && this.log.debug(error.stack);
1007
800
  });
1008
801
  }
1009
- /**
1010
- * Creates a MatterLogger function to show the matter.js log messages in AnsiLogger (for the frontend).
1011
- *
1012
- * @returns {Function} The MatterLogger function.
1013
- */
1014
802
  createMatterLogger() {
1015
- const matterLogger = new AnsiLogger({ logName: 'Matter', logTimestampFormat: 4 /* TimestampFormat.TIME_MILLIS */, logLevel: "debug" /* LogLevel.DEBUG */ });
803
+ const matterLogger = new AnsiLogger({ logName: 'Matter', logTimestampFormat: 4, logLevel: "debug" });
1016
804
  return (_level, formattedLog) => {
1017
805
  const logger = formattedLog.slice(44, 44 + 20).trim();
1018
806
  const message = formattedLog.slice(65);
1019
807
  matterLogger.logName = logger;
1020
808
  switch (_level) {
1021
809
  case MatterLogLevel.DEBUG:
1022
- matterLogger.log("debug" /* LogLevel.DEBUG */, message);
810
+ matterLogger.log("debug", message);
1023
811
  break;
1024
812
  case MatterLogLevel.INFO:
1025
- matterLogger.log("info" /* LogLevel.INFO */, message);
813
+ matterLogger.log("info", message);
1026
814
  break;
1027
815
  case MatterLogLevel.NOTICE:
1028
- matterLogger.log("notice" /* LogLevel.NOTICE */, message);
816
+ matterLogger.log("notice", message);
1029
817
  break;
1030
818
  case MatterLogLevel.WARN:
1031
- matterLogger.log("warn" /* LogLevel.WARN */, message);
819
+ matterLogger.log("warn", message);
1032
820
  break;
1033
821
  case MatterLogLevel.ERROR:
1034
- matterLogger.log("error" /* LogLevel.ERROR */, message);
822
+ matterLogger.log("error", message);
1035
823
  break;
1036
824
  case MatterLogLevel.FATAL:
1037
- matterLogger.log("fatal" /* LogLevel.FATAL */, message);
825
+ matterLogger.log("fatal", message);
1038
826
  break;
1039
827
  default:
1040
- matterLogger.log("debug" /* LogLevel.DEBUG */, message);
828
+ matterLogger.log("debug", message);
1041
829
  break;
1042
830
  }
1043
831
  };
1044
832
  }
1045
- /**
1046
- * Creates a Matter File Logger.
1047
- *
1048
- * @param {string} filePath - The path to the log file.
1049
- * @param {boolean} [unlink=false] - Whether to unlink the log file before creating a new one.
1050
- * @returns {Function} - A function that logs formatted messages to the log file.
1051
- */
1052
833
  async createMatterFileLogger(filePath, unlink = false) {
1053
- // 2024-08-21 08:55:19.488 DEBUG InteractionMessenger Sending DataReport chunk with 28 attributes and 0 events: 1004 bytes
1054
834
  let fileSize = 0;
1055
835
  if (unlink) {
1056
836
  try {
@@ -1099,21 +879,12 @@ export class Matterbridge extends EventEmitter {
1099
879
  }
1100
880
  };
1101
881
  }
1102
- /**
1103
- * Restarts the process by exiting the current instance and loading a new instance.
1104
- */
1105
882
  async restartProcess() {
1106
883
  await this.cleanup('restarting...', true);
1107
884
  }
1108
- /**
1109
- * Shut down the process by exiting the current process.
1110
- */
1111
885
  async shutdownProcess() {
1112
886
  await this.cleanup('shutting down...', false);
1113
887
  }
1114
- /**
1115
- * Update matterbridge and and shut down the process.
1116
- */
1117
888
  async updateProcess() {
1118
889
  this.log.info('Updating matterbridge...');
1119
890
  try {
@@ -1126,9 +897,6 @@ export class Matterbridge extends EventEmitter {
1126
897
  this.frontend.wssSendRestartRequired();
1127
898
  await this.cleanup('updating...', false);
1128
899
  }
1129
- /**
1130
- * Unregister all devices and shut down the process.
1131
- */
1132
900
  async unregisterAndShutdownProcess() {
1133
901
  this.log.info('Unregistering all devices and shutting down...');
1134
902
  for (const plugin of this.plugins) {
@@ -1136,9 +904,6 @@ export class Matterbridge extends EventEmitter {
1136
904
  }
1137
905
  await this.cleanup('unregistered all devices and shutting down...', false);
1138
906
  }
1139
- /**
1140
- * Reset commissioning and shut down the process.
1141
- */
1142
907
  async shutdownProcessAndReset() {
1143
908
  this.log.info('Resetting Matterbridge commissioning information...');
1144
909
  await this.matterStorageManager?.createContext('events')?.clearAll();
@@ -1150,12 +915,8 @@ export class Matterbridge extends EventEmitter {
1150
915
  this.log.info('Matter storage reset done! Remove the bridge from the controller.');
1151
916
  await this.cleanup('shutting down with reset...', false);
1152
917
  }
1153
- /**
1154
- * Factory reset and shut down the process.
1155
- */
1156
918
  async shutdownProcessAndFactoryReset() {
1157
919
  try {
1158
- // Delete old matter storage file and backup
1159
920
  const file = path.join(this.matterbridgeDirectory, 'matterbridge' + (getParameter('profile') ? '.' + getParameter('profile') : '') + '.json');
1160
921
  this.log.info(`Unlinking old matter storage file: ${file}`);
1161
922
  await fs.unlink(file);
@@ -1169,7 +930,6 @@ export class Matterbridge extends EventEmitter {
1169
930
  }
1170
931
  }
1171
932
  try {
1172
- // Delete matter node storage directory with its subdirectories and backup
1173
933
  const dir = path.join(this.matterbridgeDirectory, 'matterstorage' + (getParameter('profile') ? '.' + getParameter('profile') : ''));
1174
934
  this.log.info(`Removing matter node storage directory: ${dir}`);
1175
935
  await fs.rm(dir, { recursive: true });
@@ -1183,7 +943,6 @@ export class Matterbridge extends EventEmitter {
1183
943
  }
1184
944
  }
1185
945
  try {
1186
- // Delete node storage directory with its subdirectories and backup
1187
946
  const dir = path.join(this.matterbridgeDirectory, 'storage' + (getParameter('profile') ? '.' + getParameter('profile') : ''));
1188
947
  this.log.info(`Removing storage directory: ${dir}`);
1189
948
  await fs.rm(dir, { recursive: true });
@@ -1203,41 +962,30 @@ export class Matterbridge extends EventEmitter {
1203
962
  this.devices.clear();
1204
963
  await this.cleanup('shutting down with factory reset...', false);
1205
964
  }
1206
- /**
1207
- * Cleans up the Matterbridge instance.
1208
- * @param message - The cleanup message.
1209
- * @param restart - Indicates whether to restart the instance after cleanup. Default is `false`.
1210
- * @returns A promise that resolves when the cleanup is completed.
1211
- */
1212
965
  async cleanup(message, restart = false) {
1213
966
  if (this.initialized && !this.hasCleanupStarted) {
1214
967
  this.hasCleanupStarted = true;
1215
968
  this.log.info(message);
1216
- // Clear the start matter interval
1217
969
  if (this.startMatterInterval) {
1218
970
  clearInterval(this.startMatterInterval);
1219
971
  this.startMatterInterval = undefined;
1220
972
  this.log.debug('Start matter interval cleared');
1221
973
  }
1222
- // Clear the check update interval
1223
974
  if (this.checkUpdateInterval) {
1224
975
  clearInterval(this.checkUpdateInterval);
1225
976
  this.checkUpdateInterval = undefined;
1226
977
  this.log.debug('Check update interval cleared');
1227
978
  }
1228
- // Clear the configure timeout
1229
979
  if (this.configureTimeout) {
1230
980
  clearTimeout(this.configureTimeout);
1231
981
  this.configureTimeout = undefined;
1232
982
  this.log.debug('Matterbridge configure timeout cleared');
1233
983
  }
1234
- // Clear the reachability timeout
1235
984
  if (this.reachabilityTimeout) {
1236
985
  clearTimeout(this.reachabilityTimeout);
1237
986
  this.reachabilityTimeout = undefined;
1238
987
  this.log.debug('Matterbridge reachability timeout cleared');
1239
988
  }
1240
- // Calling the shutdown method of each plugin and clear the plugins reachability timeout
1241
989
  for (const plugin of this.plugins) {
1242
990
  if (!plugin.enabled || plugin.error)
1243
991
  continue;
@@ -1248,9 +996,7 @@ export class Matterbridge extends EventEmitter {
1248
996
  this.log.debug(`Plugin ${plg}${plugin.name}${db} reachability timeout cleared`);
1249
997
  }
1250
998
  }
1251
- // Stop the frontend
1252
999
  this.frontend.stop();
1253
- // Stopping matter server nodes
1254
1000
  this.log.notice(`Stopping matter server nodes in ${this.bridgeMode} mode...`);
1255
1001
  if (this.bridgeMode === 'bridge') {
1256
1002
  if (this.serverNode) {
@@ -1267,35 +1013,16 @@ export class Matterbridge extends EventEmitter {
1267
1013
  }
1268
1014
  }
1269
1015
  this.log.notice('Stopped matter server nodes');
1270
- // Stop matter storage
1271
1016
  await this.stopMatterStorage();
1272
- // Remove the matterfilelogger
1273
1017
  try {
1274
1018
  Logger.removeLogger('matterfilelogger');
1275
- // eslint-disable-next-line @typescript-eslint/no-unused-vars
1276
1019
  }
1277
1020
  catch (error) {
1278
- // this.log.debug(`Error removing the matterfilelogger for file ${CYAN}${path.join(this.matterbridgeDirectory, this.matterLoggerFile)}${er}: ${error instanceof Error ? error.message : error}`);
1279
1021
  }
1280
- // Serialize registeredDevices
1281
1022
  if (this.nodeStorage && this.nodeContext) {
1282
- /*
1283
- TODO: Implement serialization of registered devices in edge mode
1284
- this.log.info('Saving registered devices...');
1285
- const serializedRegisteredDevices: SerializedMatterbridgeEndpoint[] = [];
1286
- this.devices.forEach(async (device) => {
1287
- const serializedMatterbridgeDevice = MatterbridgeEndpoint.serialize(device);
1288
- // this.log.info(`- ${serializedMatterbridgeDevice.deviceName}${rs}\n`, serializedMatterbridgeDevice);
1289
- if (serializedMatterbridgeDevice) serializedRegisteredDevices.push(serializedMatterbridgeDevice);
1290
- });
1291
- await this.nodeContext.set<SerializedMatterbridgeEndpoint[]>('devices', serializedRegisteredDevices);
1292
- this.log.info(`Saved registered devices (${serializedRegisteredDevices?.length})`);
1293
- */
1294
- // Clear nodeContext and nodeStorage (they just need 1000ms to write the data to disk)
1295
1023
  this.log.debug(`Closing node storage context for ${plg}Matterbridge${db}...`);
1296
1024
  await this.nodeContext.close();
1297
1025
  this.nodeContext = undefined;
1298
- // Clear nodeContext for each plugin (they just need 1000ms to write the data to disk)
1299
1026
  for (const plugin of this.plugins) {
1300
1027
  if (plugin.nodeContext) {
1301
1028
  this.log.debug(`Closing node storage context for plugin ${plg}${plugin.name}${db}...`);
@@ -1312,13 +1039,12 @@ export class Matterbridge extends EventEmitter {
1312
1039
  }
1313
1040
  this.plugins.clear();
1314
1041
  this.devices.clear();
1315
- // Deregisters the process handlers
1316
1042
  this.deregisterProcesslHandlers();
1317
1043
  if (restart) {
1318
1044
  if (message === 'updating...') {
1319
1045
  this.log.info('Cleanup completed. Updating...');
1320
1046
  Matterbridge.instance = undefined;
1321
- this.emit('update'); // Restart the process but the update has been done before
1047
+ this.emit('update');
1322
1048
  }
1323
1049
  else if (message === 'restarting...') {
1324
1050
  this.log.info('Cleanup completed. Restarting...');
@@ -1335,14 +1061,6 @@ export class Matterbridge extends EventEmitter {
1335
1061
  this.initialized = false;
1336
1062
  }
1337
1063
  }
1338
- /**
1339
- * Creates and configures the server node for an accessory plugin for a given device.
1340
- *
1341
- * @param {RegisteredPlugin} plugin - The plugin to configure.
1342
- * @param {MatterbridgeEndpoint} device - The device to associate with the plugin.
1343
- * @param {boolean} [start=false] - Whether to start the server node after adding the device.
1344
- * @returns {Promise<void>} A promise that resolves when the server node for the accessory plugin is created and configured.
1345
- */
1346
1064
  async createAccessoryPlugin(plugin, device, start = false) {
1347
1065
  if (!plugin.locked && device.deviceName && device.vendorId && device.productId && device.vendorName && device.productName) {
1348
1066
  plugin.locked = true;
@@ -1354,13 +1072,6 @@ export class Matterbridge extends EventEmitter {
1354
1072
  await this.startServerNode(plugin.serverNode);
1355
1073
  }
1356
1074
  }
1357
- /**
1358
- * Creates and configures the server node for a dynamic plugin.
1359
- *
1360
- * @param {RegisteredPlugin} plugin - The plugin to configure.
1361
- * @param {boolean} [start=false] - Whether to start the server node after adding the aggregator node.
1362
- * @returns {Promise<void>} A promise that resolves when the server node for the dynamic plugin is created and configured.
1363
- */
1364
1075
  async createDynamicPlugin(plugin, start = false) {
1365
1076
  if (!plugin.locked) {
1366
1077
  plugin.locked = true;
@@ -1372,13 +1083,7 @@ export class Matterbridge extends EventEmitter {
1372
1083
  await this.startServerNode(plugin.serverNode);
1373
1084
  }
1374
1085
  }
1375
- /**
1376
- * Starts the Matterbridge in bridge mode.
1377
- * @private
1378
- * @returns {Promise<void>} A promise that resolves when the Matterbridge is started.
1379
- */
1380
1086
  async startBridge() {
1381
- // Plugins are configured by a timer when matter server is started and plugin.configured is set to true
1382
1087
  if (!this.matterStorageManager)
1383
1088
  throw new Error('No storage manager initialized');
1384
1089
  if (!this.matterbridgeContext)
@@ -1415,9 +1120,7 @@ export class Matterbridge extends EventEmitter {
1415
1120
  clearInterval(this.startMatterInterval);
1416
1121
  this.startMatterInterval = undefined;
1417
1122
  this.log.debug('Cleared startMatterInterval interval for Matterbridge');
1418
- // Start the Matter server node
1419
1123
  this.startServerNode(this.serverNode);
1420
- // Configure the plugins
1421
1124
  this.configureTimeout = setTimeout(async () => {
1422
1125
  for (const plugin of this.plugins) {
1423
1126
  if (!plugin.enabled || !plugin.loaded || !plugin.started || plugin.error)
@@ -1432,7 +1135,6 @@ export class Matterbridge extends EventEmitter {
1432
1135
  }
1433
1136
  this.frontend.wssSendRefreshRequired();
1434
1137
  }, 30 * 1000);
1435
- // Setting reachability to true
1436
1138
  this.reachabilityTimeout = setTimeout(() => {
1437
1139
  this.log.info(`Setting reachability to true for ${plg}Matterbridge${db}`);
1438
1140
  if (this.serverNode)
@@ -1443,14 +1145,7 @@ export class Matterbridge extends EventEmitter {
1443
1145
  }, 60 * 1000);
1444
1146
  }, 1000);
1445
1147
  }
1446
- /**
1447
- * Starts the Matterbridge in childbridge mode.
1448
- * @private
1449
- * @returns {Promise<void>} A promise that resolves when the Matterbridge is started.
1450
- */
1451
1148
  async startChildbridge() {
1452
- // Matterbridge.addBridgedDevice creates the commissionig servers and add the devices to the the commissioning server or to the aggregator
1453
- // Plugins are configured by a timer when matter server is started and plugin.configured is set to true
1454
1149
  if (!this.matterStorageManager)
1455
1150
  throw new Error('No storage manager initialized');
1456
1151
  for (const plugin of this.plugins) {
@@ -1497,13 +1192,12 @@ export class Matterbridge extends EventEmitter {
1497
1192
  clearInterval(this.startMatterInterval);
1498
1193
  this.startMatterInterval = undefined;
1499
1194
  this.log.debug('Cleared startMatterInterval interval in childbridge mode');
1500
- // Configure the plugins
1501
1195
  this.configureTimeout = setTimeout(async () => {
1502
1196
  for (const plugin of this.plugins) {
1503
1197
  if (!plugin.enabled || !plugin.loaded || !plugin.started || plugin.error)
1504
1198
  continue;
1505
1199
  try {
1506
- await this.plugins.configure(plugin); // TODO No await do it in parallel
1200
+ await this.plugins.configure(plugin);
1507
1201
  }
1508
1202
  catch (error) {
1509
1203
  plugin.error = true;
@@ -1531,9 +1225,7 @@ export class Matterbridge extends EventEmitter {
1531
1225
  this.log.error(`Node storage context not found for plugin ${plg}${plugin.name}${er}`);
1532
1226
  continue;
1533
1227
  }
1534
- // Start the Matter server node
1535
1228
  this.startServerNode(plugin.serverNode);
1536
- // Setting reachability to true
1537
1229
  plugin.reachabilityTimeout = setTimeout(() => {
1538
1230
  this.log.info(`Setting reachability to true for ${plg}${plugin.name}${db}`);
1539
1231
  if (plugin.serverNode)
@@ -1547,219 +1239,9 @@ export class Matterbridge extends EventEmitter {
1547
1239
  }
1548
1240
  }, 1000);
1549
1241
  }
1550
- /**
1551
- * Starts the Matterbridge controller.
1552
- * @private
1553
- * @returns {Promise<void>} A promise that resolves when the Matterbridge is started.
1554
- */
1555
1242
  async startController() {
1556
- /*
1557
- if (!this.storageManager) {
1558
- this.log.error('No storage manager initialized');
1559
- await this.cleanup('No storage manager initialized');
1560
- return;
1561
- }
1562
- this.log.info('Creating context: mattercontrollerContext');
1563
- this.mattercontrollerContext = this.storageManager.createContext('mattercontrollerContext');
1564
- if (!this.mattercontrollerContext) {
1565
- this.log.error('No storage context mattercontrollerContext initialized');
1566
- await this.cleanup('No storage context mattercontrollerContext initialized');
1567
- return;
1568
- }
1569
-
1570
- this.log.debug('Starting matterbridge in mode', this.bridgeMode);
1571
- this.matterServer = await this.createMatterServer(this.storageManager);
1572
- this.log.info('Creating matter commissioning controller');
1573
- this.commissioningController = new CommissioningController({
1574
- autoConnect: false,
1575
- });
1576
- this.log.info('Adding matter commissioning controller to matter server');
1577
- await this.matterServer.addCommissioningController(this.commissioningController);
1578
-
1579
- this.log.info('Starting matter server');
1580
- await this.matterServer.start();
1581
- this.log.info('Matter server started');
1582
-
1583
- if (hasParameter('pairingcode')) {
1584
- this.log.info('Pairing device with pairingcode:', getParameter('pairingcode'));
1585
- const pairingCode = getParameter('pairingcode');
1586
- const ip = this.mattercontrollerContext.has('ip') ? this.mattercontrollerContext.get<string>('ip') : undefined;
1587
- const port = this.mattercontrollerContext.has('port') ? this.mattercontrollerContext.get<number>('port') : undefined;
1588
-
1589
- let longDiscriminator, setupPin, shortDiscriminator;
1590
- if (pairingCode !== undefined) {
1591
- const pairingCodeCodec = ManualPairingCodeCodec.decode(pairingCode);
1592
- shortDiscriminator = pairingCodeCodec.shortDiscriminator;
1593
- longDiscriminator = undefined;
1594
- setupPin = pairingCodeCodec.passcode;
1595
- this.log.info(`Data extracted from pairing code: ${Logger.toJSON(pairingCodeCodec)}`);
1596
- } else {
1597
- longDiscriminator = await this.mattercontrollerContext.get('longDiscriminator', 3840);
1598
- if (longDiscriminator > 4095) throw new Error('Discriminator value must be less than 4096');
1599
- setupPin = this.mattercontrollerContext.get('pin', 20202021);
1600
- }
1601
- if ((shortDiscriminator === undefined && longDiscriminator === undefined) || setupPin === undefined) {
1602
- throw new Error('Please specify the longDiscriminator of the device to commission with -longDiscriminator or provide a valid passcode with -passcode');
1603
- }
1604
-
1605
- const commissioningOptions: ControllerCommissioningFlowOptions = {
1606
- regulatoryLocation: GeneralCommissioning.RegulatoryLocationType.IndoorOutdoor,
1607
- regulatoryCountryCode: 'XX',
1608
- };
1609
- const options = {
1610
- commissioning: commissioningOptions,
1611
- discovery: {
1612
- knownAddress: ip !== undefined && port !== undefined ? { ip, port, type: 'udp' } : undefined,
1613
- identifierData: longDiscriminator !== undefined ? { longDiscriminator } : shortDiscriminator !== undefined ? { shortDiscriminator } : {},
1614
- },
1615
- passcode: setupPin,
1616
- } as NodeCommissioningOptions;
1617
- this.log.info('Commissioning with options:', options);
1618
- const nodeId = await this.commissioningController.commissionNode(options);
1619
- this.log.info(`Commissioning successfully done with nodeId: ${nodeId}`);
1620
- this.log.info('ActiveSessionInformation:', this.commissioningController.getActiveSessionInformation());
1621
- } // (hasParameter('pairingcode'))
1622
-
1623
- if (hasParameter('unpairall')) {
1624
- this.log.info('***Commissioning controller unpairing all nodes...');
1625
- const nodeIds = this.commissioningController.getCommissionedNodes();
1626
- for (const nodeId of nodeIds) {
1627
- this.log.info('***Commissioning controller unpairing node:', nodeId);
1628
- await this.commissioningController.removeNode(nodeId);
1629
- }
1630
- return;
1631
- }
1632
-
1633
- if (hasParameter('discover')) {
1634
- // const discover = await this.commissioningController.discoverCommissionableDevices({ productId: 0x8000, deviceType: 0xfff1 });
1635
- // console.log(discover);
1636
- }
1637
-
1638
- if (!this.commissioningController.isCommissioned()) {
1639
- this.log.info('***Commissioning controller is not commissioned: use matterbridge -controller -pairingcode [pairingcode] to commission a device');
1640
- return;
1641
- }
1642
-
1643
- const nodeIds = this.commissioningController.getCommissionedNodes();
1644
- this.log.info(`***Commissioning controller is commissioned ${this.commissioningController.isCommissioned()} and has ${nodeIds.length} nodes commisioned: `);
1645
- for (const nodeId of nodeIds) {
1646
- this.log.info(`***Connecting to commissioned node: ${nodeId}`);
1647
-
1648
- const node = await this.commissioningController.connectNode(nodeId, {
1649
- autoSubscribe: false,
1650
- attributeChangedCallback: (peerNodeId, { path: { nodeId, clusterId, endpointId, attributeName }, value }) =>
1651
- this.log.info(`***Commissioning controller attributeChangedCallback ${peerNodeId}: attribute ${nodeId}/${endpointId}/${clusterId}/${attributeName} changed to ${Logger.toJSON(value)}`),
1652
- eventTriggeredCallback: (peerNodeId, { path: { nodeId, clusterId, endpointId, eventName }, events }) =>
1653
- this.log.info(`***Commissioning controller eventTriggeredCallback ${peerNodeId}: Event ${nodeId}/${endpointId}/${clusterId}/${eventName} triggered with ${Logger.toJSON(events)}`),
1654
- stateInformationCallback: (peerNodeId, info) => {
1655
- switch (info) {
1656
- case NodeStateInformation.Connected:
1657
- this.log.info(`***Commissioning controller stateInformationCallback ${peerNodeId}: Node ${nodeId} connected`);
1658
- break;
1659
- case NodeStateInformation.Disconnected:
1660
- this.log.info(`***Commissioning controller stateInformationCallback ${peerNodeId}: Node ${nodeId} disconnected`);
1661
- break;
1662
- case NodeStateInformation.Reconnecting:
1663
- this.log.info(`***Commissioning controller stateInformationCallback ${peerNodeId}: Node ${nodeId} reconnecting`);
1664
- break;
1665
- case NodeStateInformation.WaitingForDeviceDiscovery:
1666
- this.log.info(`***Commissioning controller stateInformationCallback ${peerNodeId}: Node ${nodeId} waiting for device discovery`);
1667
- break;
1668
- case NodeStateInformation.StructureChanged:
1669
- this.log.info(`***Commissioning controller stateInformationCallback ${peerNodeId}: Node ${nodeId} structure changed`);
1670
- break;
1671
- case NodeStateInformation.Decommissioned:
1672
- this.log.info(`***Commissioning controller stateInformationCallback ${peerNodeId}: Node ${nodeId} decommissioned`);
1673
- break;
1674
- default:
1675
- this.log.info(`***Commissioning controller stateInformationCallback ${peerNodeId}: Node ${nodeId} NodeStateInformation.${info}`);
1676
- break;
1677
- }
1678
- },
1679
- });
1680
-
1681
- node.logStructure();
1682
-
1683
- // Get the interaction client
1684
- this.log.info('Getting the interaction client');
1685
- const interactionClient = await node.getInteractionClient();
1686
- let cluster;
1687
- let attributes;
1688
-
1689
- // Log BasicInformationCluster
1690
- cluster = BasicInformationCluster;
1691
- attributes = await interactionClient.getMultipleAttributes({
1692
- attributes: [{ clusterId: cluster.id }],
1693
- });
1694
- if (attributes.length > 0) this.log.info(`Cluster: ${idn}${cluster.name}${rs}${nf} attributes:`);
1695
- attributes.forEach((attribute) => {
1696
- this.log.info(
1697
- `- endpoint ${or}${attribute.path.endpointId}${nf} cluster ${hk}${getClusterNameById(attribute.path.clusterId)}${nf} (${hk}0x${attribute.path.clusterId.toString(16)}${nf}) attribute ${zb}${attribute.path.attributeName}${nf} (${zb}0x${attribute.path.attributeId.toString(16)}${nf}): ${typeof attribute.value === 'object' ? stringify(attribute.value) : attribute.value}`,
1698
- );
1699
- });
1700
-
1701
- // Log PowerSourceCluster
1702
- cluster = PowerSourceCluster;
1703
- attributes = await interactionClient.getMultipleAttributes({
1704
- attributes: [{ clusterId: cluster.id }],
1705
- });
1706
- if (attributes.length > 0) this.log.info(`Cluster: ${idn}${cluster.name}${rs}${nf} attributes:`);
1707
- attributes.forEach((attribute) => {
1708
- this.log.info(
1709
- `- endpoint ${or}${attribute.path.endpointId}${nf} cluster ${hk}${getClusterNameById(attribute.path.clusterId)}${nf} (${hk}0x${attribute.path.clusterId.toString(16)}${nf}) attribute ${zb}${attribute.path.attributeName}${nf} (${zb}0x${attribute.path.attributeId.toString(16)}${nf}): ${typeof attribute.value === 'object' ? stringify(attribute.value) : attribute.value}`,
1710
- );
1711
- });
1712
-
1713
- // Log ThreadNetworkDiagnostics
1714
- cluster = ThreadNetworkDiagnosticsCluster;
1715
- attributes = await interactionClient.getMultipleAttributes({
1716
- attributes: [{ clusterId: cluster.id }],
1717
- });
1718
- if (attributes.length > 0) this.log.info(`Cluster: ${idn}${cluster.name}${rs}${nf} attributes:`);
1719
- attributes.forEach((attribute) => {
1720
- this.log.info(
1721
- `- endpoint ${or}${attribute.path.endpointId}${nf} cluster ${hk}${getClusterNameById(attribute.path.clusterId)}${nf} (${hk}0x${attribute.path.clusterId.toString(16)}${nf}) attribute ${zb}${attribute.path.attributeName}${nf} (${zb}0x${attribute.path.attributeId.toString(16)}${nf}): ${typeof attribute.value === 'object' ? stringify(attribute.value) : attribute.value}`,
1722
- );
1723
- });
1724
-
1725
- // Log SwitchCluster
1726
- cluster = SwitchCluster;
1727
- attributes = await interactionClient.getMultipleAttributes({
1728
- attributes: [{ clusterId: cluster.id }],
1729
- });
1730
- if (attributes.length > 0) this.log.info(`Cluster: ${idn}${cluster.name}${rs}${nf} attributes:`);
1731
- attributes.forEach((attribute) => {
1732
- this.log.info(
1733
- `- endpoint ${or}${attribute.path.endpointId}${nf} cluster ${hk}${getClusterNameById(attribute.path.clusterId)}${nf} (${hk}0x${attribute.path.clusterId.toString(16)}${nf}) attribute ${zb}${attribute.path.attributeName}${nf} (${zb}0x${attribute.path.attributeId.toString(16)}${nf}): ${typeof attribute.value === 'object' ? stringify(attribute.value) : attribute.value}`,
1734
- );
1735
- });
1736
-
1737
- this.log.info('Subscribing to all attributes and events');
1738
- await node.subscribeAllAttributesAndEvents({
1739
- ignoreInitialTriggers: false,
1740
- attributeChangedCallback: ({ path: { nodeId, clusterId, endpointId, attributeName }, version, value }) =>
1741
- this.log.info(
1742
- `***${db}Commissioning controller attributeChangedCallback version ${version}: attribute ${BLUE}${nodeId}${db}/${or}${endpointId}${db}/${hk}${getClusterNameById(clusterId)}${db}/${zb}${attributeName}${db} changed to ${typeof value === 'object' ? debugStringify(value ?? { none: true }) : value}`,
1743
- ),
1744
- eventTriggeredCallback: ({ path: { nodeId, clusterId, endpointId, eventName }, events }) => {
1745
- this.log.info(
1746
- `***${db}Commissioning controller eventTriggeredCallback: event ${BLUE}${nodeId}${db}/${or}${endpointId}${db}/${hk}${getClusterNameById(clusterId)}${db}/${zb}${eventName}${db} triggered with ${debugStringify(events ?? { none: true })}`,
1747
- );
1748
- },
1749
- });
1750
- this.log.info('Subscribed to all attributes and events');
1751
- }
1752
- */
1753
1243
  }
1754
- /** ***********************************************************************************************************************************/
1755
- /** Matter.js methods */
1756
- /** ***********************************************************************************************************************************/
1757
- /**
1758
- * Starts the matter storage process with name Matterbridge.
1759
- * @returns {Promise<void>} - A promise that resolves when the storage process is started.
1760
- */
1761
1244
  async startMatterStorage() {
1762
- // Setup Matter storage
1763
1245
  this.log.info(`Starting matter node storage...`);
1764
1246
  this.matterStorageService = this.environment.get(StorageService);
1765
1247
  this.log.info(`Matter node storage service created: ${this.matterStorageService.location}`);
@@ -1767,25 +1249,13 @@ export class Matterbridge extends EventEmitter {
1767
1249
  this.log.info('Matter node storage manager "Matterbridge" created');
1768
1250
  this.matterbridgeContext = await this.createServerNodeContext('Matterbridge', 'Matterbridge', bridge.code, this.aggregatorVendorId, 'Matterbridge', this.aggregatorProductId, 'Matterbridge aggregator');
1769
1251
  this.log.info('Matter node storage started');
1770
- // Backup matter storage since it is created/opened correctly
1771
1252
  await this.backupMatterStorage(path.join(this.matterbridgeDirectory, this.matterStorageName), path.join(this.matterbridgeDirectory, this.matterStorageName + '.backup'));
1772
1253
  }
1773
- /**
1774
- * Makes a backup copy of the specified matter storage directory.
1775
- *
1776
- * @param storageName - The name of the storage directory to be backed up.
1777
- * @param backupName - The name of the backup directory to be created.
1778
- * @returns {Promise<void>} A promise that resolves when the has been done.
1779
- */
1780
1254
  async backupMatterStorage(storageName, backupName) {
1781
1255
  this.log.info('Creating matter node storage backup...');
1782
1256
  await copyDirectory(storageName, backupName);
1783
1257
  this.log.info('Created matter node storage backup');
1784
1258
  }
1785
- /**
1786
- * Stops the matter storage.
1787
- * @returns {Promise<void>} A promise that resolves when the storage is stopped.
1788
- */
1789
1259
  async stopMatterStorage() {
1790
1260
  this.log.info('Closing matter node storage...');
1791
1261
  this.matterStorageManager?.close();
@@ -1794,19 +1264,6 @@ export class Matterbridge extends EventEmitter {
1794
1264
  this.matterbridgeContext = undefined;
1795
1265
  this.log.info('Matter node storage closed');
1796
1266
  }
1797
- /**
1798
- * Creates a server node storage context.
1799
- *
1800
- * @param {string} pluginName - The name of the plugin.
1801
- * @param {string} deviceName - The name of the device.
1802
- * @param {DeviceTypeId} deviceType - The device type of the device.
1803
- * @param {number} vendorId - The vendor ID.
1804
- * @param {string} vendorName - The vendor name.
1805
- * @param {number} productId - The product ID.
1806
- * @param {string} productName - The product name.
1807
- * @param {string} [serialNumber] - The serial number of the device (optional).
1808
- * @returns {Promise<StorageContext>} The storage context for the commissioning server.
1809
- */
1810
1267
  async createServerNodeContext(pluginName, deviceName, deviceType, vendorId, vendorName, productId, productName, serialNumber) {
1811
1268
  if (!this.matterStorageService)
1812
1269
  throw new Error('No storage service initialized');
@@ -1839,15 +1296,6 @@ export class Matterbridge extends EventEmitter {
1839
1296
  this.log.debug(`- hardwareVersion: ${await storageContext.get('hardwareVersion')} hardwareVersionString: ${await storageContext.get('hardwareVersionString')}`);
1840
1297
  return storageContext;
1841
1298
  }
1842
- /**
1843
- * Creates a server node.
1844
- *
1845
- * @param {StorageContext} storageContext - The storage context for the server node.
1846
- * @param {number} [port=5540] - The port number for the server node. Defaults to 5540.
1847
- * @param {number} [passcode=20242025] - The passcode for the server node. Defaults to 20242025.
1848
- * @param {number} [discriminator=3850] - The discriminator for the server node. Defaults to 3850.
1849
- * @returns {Promise<ServerNode<ServerNode.RootEndpoint>>} A promise that resolves to the created server node.
1850
- */
1851
1299
  async createServerNode(storageContext, port = 5540, passcode = 20242025, discriminator = 3850) {
1852
1300
  const storeId = await storageContext.get('storeId');
1853
1301
  this.log.notice(`Creating server node for ${storeId} on port ${port} with passcode ${passcode} and discriminator ${discriminator}...`);
@@ -1857,33 +1305,21 @@ export class Matterbridge extends EventEmitter {
1857
1305
  this.log.debug(`- uniqueId: ${await storageContext.get('uniqueId')}`);
1858
1306
  this.log.debug(`- softwareVersion: ${await storageContext.get('softwareVersion')} softwareVersionString: ${await storageContext.get('softwareVersionString')}`);
1859
1307
  this.log.debug(`- hardwareVersion: ${await storageContext.get('hardwareVersion')} hardwareVersionString: ${await storageContext.get('hardwareVersionString')}`);
1860
- /**
1861
- * Create a Matter ServerNode, which contains the Root Endpoint and all relevant data and configuration
1862
- */
1863
1308
  const serverNode = await ServerNode.create({
1864
- // Required: Give the Node a unique ID which is used to store the state of this node
1865
1309
  id: storeId,
1866
- // Provide Network relevant configuration like the port
1867
- // Optional when operating only one device on a host, Default port is 5540
1868
1310
  network: {
1869
1311
  listeningAddressIpv4: this.ipv4address,
1870
1312
  listeningAddressIpv6: this.ipv6address,
1871
1313
  port,
1872
1314
  },
1873
- // Provide Commissioning relevant settings
1874
- // Optional for development/testing purposes
1875
1315
  commissioning: {
1876
1316
  passcode,
1877
1317
  discriminator,
1878
1318
  },
1879
- // Provide Node announcement settings
1880
- // Optional: If Ommitted some development defaults are used
1881
1319
  productDescription: {
1882
1320
  name: await storageContext.get('deviceName'),
1883
1321
  deviceType: DeviceTypeId(await storageContext.get('deviceType')),
1884
1322
  },
1885
- // Provide defaults for the BasicInformation cluster on the Root endpoint
1886
- // Optional: If Omitted some development defaults are used
1887
1323
  basicInformation: {
1888
1324
  vendorId: VendorId(await storageContext.get('vendorId')),
1889
1325
  vendorName: await storageContext.get('vendorName'),
@@ -1900,13 +1336,12 @@ export class Matterbridge extends EventEmitter {
1900
1336
  },
1901
1337
  });
1902
1338
  const sanitizeFabrics = (fabrics, resetSessions = false) => {
1903
- // New type of fabric information: Record<FabricIndex, ExposedFabricInformation>
1904
1339
  const sanitizedFabrics = this.sanitizeFabricInformations(Array.from(Object.values(fabrics)));
1905
1340
  this.log.info(`Fabrics: ${debugStringify(sanitizedFabrics)}`);
1906
1341
  if (this.bridgeMode === 'bridge') {
1907
1342
  this.matterbridgeFabricInformations = sanitizedFabrics;
1908
1343
  if (resetSessions)
1909
- this.matterbridgeSessionInformations = undefined; // Changed cause Invoke Matterbridge.operationalCredentials.updateFabricLabel is sent after the session is created
1344
+ this.matterbridgeSessionInformations = undefined;
1910
1345
  this.matterbridgePaired = true;
1911
1346
  }
1912
1347
  if (this.bridgeMode === 'childbridge') {
@@ -1914,19 +1349,13 @@ export class Matterbridge extends EventEmitter {
1914
1349
  if (plugin) {
1915
1350
  plugin.fabricInformations = sanitizedFabrics;
1916
1351
  if (resetSessions)
1917
- plugin.sessionInformations = undefined; // Changed cause Invoke Matterbridge.operationalCredentials.updateFabricLabel is sent after the session is created
1352
+ plugin.sessionInformations = undefined;
1918
1353
  plugin.paired = true;
1919
1354
  }
1920
1355
  }
1921
1356
  };
1922
- /**
1923
- * This event is triggered when the device is initially commissioned successfully.
1924
- * This means: It is added to the first fabric.
1925
- */
1926
1357
  serverNode.lifecycle.commissioned.on(() => this.log.notice(`Server node for ${storeId} was initially commissioned successfully!`));
1927
- /** This event is triggered when all fabrics are removed from the device, usually it also does a factory reset then. */
1928
1358
  serverNode.lifecycle.decommissioned.on(() => this.log.notice(`Server node for ${storeId} was fully decommissioned successfully!`));
1929
- /** This event is triggered when the device went online. This means that it is discoverable in the network. */
1930
1359
  serverNode.lifecycle.online.on(async () => {
1931
1360
  this.log.notice(`Server node for ${storeId} is online`);
1932
1361
  if (!serverNode.lifecycle.isCommissioned) {
@@ -1972,7 +1401,6 @@ export class Matterbridge extends EventEmitter {
1972
1401
  }
1973
1402
  this.frontend.wssSendRefreshRequired();
1974
1403
  });
1975
- /** This event is triggered when the device went offline. it is not longer discoverable or connectable in the network. */
1976
1404
  serverNode.lifecycle.offline.on(() => {
1977
1405
  this.log.notice(`Server node for ${storeId} is offline`);
1978
1406
  if (this.bridgeMode === 'bridge') {
@@ -1994,10 +1422,6 @@ export class Matterbridge extends EventEmitter {
1994
1422
  }
1995
1423
  this.frontend.wssSendRefreshRequired();
1996
1424
  });
1997
- /**
1998
- * This event is triggered when a fabric is added, removed or updated on the device. Use this if more granular
1999
- * information is needed.
2000
- */
2001
1425
  serverNode.events.commissioning.fabricsChanged.on((fabricIndex, fabricAction) => {
2002
1426
  let action = '';
2003
1427
  switch (fabricAction) {
@@ -2031,24 +1455,16 @@ export class Matterbridge extends EventEmitter {
2031
1455
  }
2032
1456
  }
2033
1457
  };
2034
- /**
2035
- * This event is triggered when an operative new session was opened by a Controller.
2036
- * It is not triggered for the initial commissioning process, just afterwards for real connections.
2037
- */
2038
1458
  serverNode.events.sessions.opened.on((session) => {
2039
1459
  this.log.notice(`Session opened on server node for ${storeId}: ${debugStringify(session)}`);
2040
1460
  sanitizeSessions(Object.values(serverNode.state.sessions.sessions));
2041
1461
  this.frontend.wssSendRefreshRequired();
2042
1462
  });
2043
- /**
2044
- * This event is triggered when an operative session is closed by a Controller or because the Device goes offline.
2045
- */
2046
1463
  serverNode.events.sessions.closed.on((session) => {
2047
1464
  this.log.notice(`Session closed on server node for ${storeId}: ${debugStringify(session)}`);
2048
1465
  sanitizeSessions(Object.values(serverNode.state.sessions.sessions));
2049
1466
  this.frontend.wssSendRefreshRequired();
2050
1467
  });
2051
- /** This event is triggered when a subscription gets added or removed on an operative session. */
2052
1468
  serverNode.events.sessions.subscriptionsChanged.on((session) => {
2053
1469
  this.log.notice(`Session subscriptions changed on server node for ${storeId}: ${debugStringify(session)}`);
2054
1470
  sanitizeSessions(Object.values(serverNode.state.sessions.sessions));
@@ -2057,39 +1473,19 @@ export class Matterbridge extends EventEmitter {
2057
1473
  this.log.info(`Created server node for ${storeId}`);
2058
1474
  return serverNode;
2059
1475
  }
2060
- /**
2061
- * Starts the specified server node.
2062
- *
2063
- * @param {ServerNode} [matterServerNode] - The server node to start.
2064
- * @returns {Promise<void>} A promise that resolves when the server node has started.
2065
- */
2066
1476
  async startServerNode(matterServerNode) {
2067
1477
  if (!matterServerNode)
2068
1478
  return;
2069
1479
  this.log.notice(`Starting ${matterServerNode.id} server node`);
2070
1480
  await matterServerNode.start();
2071
1481
  }
2072
- /**
2073
- * Stops the specified server node.
2074
- *
2075
- * @param {ServerNode} matterServerNode - The server node to stop.
2076
- * @returns {Promise<void>} A promise that resolves when the server node has stopped.
2077
- */
2078
1482
  async stopServerNode(matterServerNode) {
2079
1483
  if (!matterServerNode)
2080
1484
  return;
2081
1485
  this.log.notice(`Closing ${matterServerNode.id} server node`);
2082
1486
  await matterServerNode.close();
2083
1487
  this.log.info(`Closed ${matterServerNode.id} server node`);
2084
- // await matterServerNode.env.get(MdnsService)[Symbol.asyncDispose]();
2085
- // this.log.info(`Closed ${matterServerNode.id} MdnsService`);
2086
1488
  }
2087
- /**
2088
- * Advertises the specified server node if it is commissioned.
2089
- *
2090
- * @param {ServerNode} [matterServerNode] - The server node to advertise.
2091
- * @returns {Promise<{ qrPairingCode: string, manualPairingCode: string } | undefined>} A promise that resolves to the pairing codes if the server node is advertised, or undefined if not.
2092
- */
2093
1489
  async advertiseServerNode(matterServerNode) {
2094
1490
  if (matterServerNode && matterServerNode.lifecycle.isCommissioned) {
2095
1491
  await matterServerNode.env.get(DeviceCommissioner)?.allowBasicCommissioning();
@@ -2099,32 +1495,17 @@ export class Matterbridge extends EventEmitter {
2099
1495
  }
2100
1496
  return undefined;
2101
1497
  }
2102
- /**
2103
- * Creates an aggregator node with the specified storage context.
2104
- *
2105
- * @param {StorageContext} storageContext - The storage context for the aggregator node.
2106
- * @returns {Promise<EndpointNode<AggregatorEndpoint>>} A promise that resolves to the created aggregator node.
2107
- */
2108
1498
  async createAggregatorNode(storageContext) {
2109
1499
  this.log.notice(`Creating ${await storageContext.get('storeId')} aggregator `);
2110
1500
  const aggregatorNode = new EndpointNode(AggregatorEndpoint, { id: `${await storageContext.get('storeId')}` });
2111
1501
  return aggregatorNode;
2112
1502
  }
2113
- /**
2114
- * Adds a MatterbridgeEndpoint to the specified plugin.
2115
- *
2116
- * @param {string} pluginName - The name of the plugin.
2117
- * @param {MatterbridgeEndpoint} device - The device to add as a bridged endpoint.
2118
- * @returns {Promise<void>} A promise that resolves when the bridged endpoint has been added.
2119
- */
2120
1503
  async addBridgedEndpoint(pluginName, device) {
2121
- // Check if the plugin is registered
2122
1504
  const plugin = this.plugins.get(pluginName);
2123
1505
  if (!plugin) {
2124
1506
  this.log.error(`Error adding bridged endpoint ${dev}${device.deviceName}${er} (${zb}${device.id}${er}) plugin ${plg}${pluginName}${er} not found`);
2125
1507
  return;
2126
1508
  }
2127
- // Register and add the device to the matterbridge aggregator node
2128
1509
  if (this.bridgeMode === 'bridge') {
2129
1510
  this.log.debug(`Adding bridged endpoint ${plg}${pluginName}${db}:${dev}${device.deviceName}${db} to Matterbridge aggregator node`);
2130
1511
  if (!this.aggregatorNode)
@@ -2147,26 +1528,16 @@ export class Matterbridge extends EventEmitter {
2147
1528
  plugin.registeredDevices++;
2148
1529
  if (plugin.addedDevices !== undefined)
2149
1530
  plugin.addedDevices++;
2150
- // Add the device to the DeviceManager
2151
1531
  this.devices.set(device);
2152
1532
  this.log.info(`Added and registered bridged endpoint (${plugin.registeredDevices}/${plugin.addedDevices}) ${dev}${device.deviceName}${nf} (${dev}${device.id}${nf}) for plugin ${plg}${pluginName}${nf}`);
2153
1533
  }
2154
- /**
2155
- * Removes a MatterbridgeEndpoint from the specified plugin.
2156
- *
2157
- * @param {string} pluginName - The name of the plugin.
2158
- * @param {MatterbridgeEndpoint} device - The device to remove as a bridged endpoint.
2159
- * @returns {Promise<void>} A promise that resolves when the bridged endpoint has been removed.
2160
- */
2161
1534
  async removeBridgedEndpoint(pluginName, device) {
2162
1535
  this.log.debug(`Removing bridged endpoint ${plg}${pluginName}${db}:${dev}${device.deviceName}${db} (${zb}${device.name}${db}) for plugin ${plg}${pluginName}${db}`);
2163
- // Check if the plugin is registered
2164
1536
  const plugin = this.plugins.get(pluginName);
2165
1537
  if (!plugin) {
2166
1538
  this.log.error(`Error removing bridged endpoint ${dev}${device.deviceName}${er} (${zb}${device.name}${er}) for plugin ${plg}${pluginName}${er}: plugin not found`);
2167
1539
  return;
2168
1540
  }
2169
- // Register and add the device to the matterbridge aggregator node
2170
1541
  if (this.bridgeMode === 'bridge') {
2171
1542
  if (!this.aggregatorNode) {
2172
1543
  this.log.error(`Error removing bridged endpoint ${dev}${device.deviceName}${er} (${zb}${device.name}${er}) for plugin ${plg}${pluginName}${er}: aggregator node not found`);
@@ -2181,7 +1552,6 @@ export class Matterbridge extends EventEmitter {
2181
1552
  }
2182
1553
  else if (this.bridgeMode === 'childbridge') {
2183
1554
  if (plugin.type === 'AccessoryPlatform') {
2184
- // Nothing to do here since the server node has no aggregator node but only the device itself
2185
1555
  }
2186
1556
  else if (plugin.type === 'DynamicPlatform') {
2187
1557
  if (!plugin.aggregatorNode) {
@@ -2195,7 +1565,6 @@ export class Matterbridge extends EventEmitter {
2195
1565
  plugin.registeredDevices--;
2196
1566
  if (plugin.addedDevices !== undefined)
2197
1567
  plugin.addedDevices--;
2198
- // Close the server node TODO check if this is correct
2199
1568
  if (plugin.registeredDevices === 0 && plugin.addedDevices === 0) {
2200
1569
  if (plugin.serverNode) {
2201
1570
  await this.stopServerNode(plugin.serverNode);
@@ -2206,27 +1575,14 @@ export class Matterbridge extends EventEmitter {
2206
1575
  }
2207
1576
  }
2208
1577
  }
2209
- // Remove the device from the DeviceManager
2210
1578
  this.devices.remove(device);
2211
1579
  }
2212
- /**
2213
- * Removes all bridged endpoints from the specified plugin.
2214
- *
2215
- * @param {string} pluginName - The name of the plugin.
2216
- * @returns {Promise<void>} A promise that resolves when all bridged endpoints have been removed.
2217
- */
2218
1580
  async removeAllBridgedEndpoints(pluginName) {
2219
1581
  this.log.debug(`Removing all bridged endpoints for plugin ${plg}${pluginName}${db}`);
2220
1582
  for (const device of this.devices.array().filter((device) => device.plugin === pluginName)) {
2221
1583
  await this.removeBridgedEndpoint(pluginName, device);
2222
1584
  }
2223
1585
  }
2224
- /**
2225
- * Sanitizes the fabric information by converting bigint properties to strings because `res.json` doesn't support bigint.
2226
- *
2227
- * @param {ExposedFabricInformation[]} fabricInfo - The array of exposed fabric information objects.
2228
- * @returns {SanitizedExposedFabricInformation[]} An array of sanitized exposed fabric information objects.
2229
- */
2230
1586
  sanitizeFabricInformations(fabricInfo) {
2231
1587
  return fabricInfo.map((info) => {
2232
1588
  return {
@@ -2240,12 +1596,6 @@ export class Matterbridge extends EventEmitter {
2240
1596
  };
2241
1597
  });
2242
1598
  }
2243
- /**
2244
- * Sanitizes the session information by converting bigint properties to strings because `res.json` doesn't support bigint.
2245
- *
2246
- * @param {SessionInformation[]} sessionInfo - The array of session information objects.
2247
- * @returns {SanitizedSessionInformation[]} An array of sanitized session information objects.
2248
- */
2249
1599
  sanitizeSessionInformation(sessionInfo) {
2250
1600
  return sessionInfo
2251
1601
  .filter((session) => session.isPeerActive)
@@ -2273,51 +1623,11 @@ export class Matterbridge extends EventEmitter {
2273
1623
  };
2274
1624
  });
2275
1625
  }
2276
- /**
2277
- * Sets the reachability of a matter server node and trigger ReachableChanged event.
2278
- *
2279
- * @param {ServerNode<ServerNode.RootEndpoint>} serverNode - The commissioning server to set the reachability for.
2280
- * @param {boolean} reachable - The new reachability status.
2281
- */
2282
- // eslint-disable-next-line @typescript-eslint/no-unused-vars
2283
1626
  setServerNodeReachability(serverNode, reachable) {
2284
- /*
2285
- const basicInformationCluster = commissioningServer?.getRootClusterServer(BasicInformationCluster);
2286
- if (basicInformationCluster && basicInformationCluster.attributes.reachable !== undefined) basicInformationCluster.setReachableAttribute(reachable);
2287
- if (basicInformationCluster && basicInformationCluster.triggerReachableChangedEvent) basicInformationCluster.triggerReachableChangedEvent({ reachableNewValue: reachable });
2288
- */
2289
1627
  }
2290
- /**
2291
- * Sets the reachability of the specified matter aggregator and its bridged devices and trigger.
2292
- * @param {EndpointNode<AggregatorEndpoint>} aggregatorNode - The matter aggregator to set the reachability for.
2293
- * @param {boolean} reachable - A boolean indicating the reachability status to set.
2294
- */
2295
- // eslint-disable-next-line @typescript-eslint/no-unused-vars
2296
1628
  setAggregatorReachability(aggregatorNode, reachable) {
2297
- /*
2298
- const basicInformationCluster = matterAggregator.getClusterServer(BasicInformationCluster);
2299
- if (basicInformationCluster && basicInformationCluster.attributes.reachable !== undefined) basicInformationCluster.setReachableAttribute(reachable);
2300
- if (basicInformationCluster && basicInformationCluster.triggerReachableChangedEvent) basicInformationCluster.triggerReachableChangedEvent({ reachableNewValue: reachable });
2301
- matterAggregator.getBridgedDevices().forEach((device) => {
2302
- this.log.debug(`Setting reachability to true for bridged device: ${dev}${device.name}${nf}`);
2303
- device.getClusterServer(BridgedDeviceBasicInformationCluster)?.setReachableAttribute(reachable);
2304
- device.getClusterServer(BridgedDeviceBasicInformationCluster)?.triggerReachableChangedEvent({ reachableNewValue: reachable });
2305
- });
2306
- */
2307
1629
  }
2308
- /**
2309
- * Sets the reachability of a device and trigger.
2310
- *
2311
- * @param {MatterbridgeEndpoint} device - The device to set the reachability for.
2312
- * @param {boolean} reachable - The new reachability status of the device.
2313
- */
2314
- // eslint-disable-next-line @typescript-eslint/no-unused-vars
2315
1630
  setDeviceReachability(device, reachable) {
2316
- /*
2317
- const basicInformationCluster = device.getClusterServer(BasicInformationCluster);
2318
- if (basicInformationCluster && basicInformationCluster.attributes.reachable !== undefined) basicInformationCluster.setReachableAttribute(reachable);
2319
- if (basicInformationCluster && basicInformationCluster.triggerReachableChangedEvent) basicInformationCluster.triggerReachableChangedEvent({ reachableNewValue: reachable });
2320
- */
2321
1631
  }
2322
1632
  getVendorIdName = (vendorId) => {
2323
1633
  if (!vendorId)
@@ -2360,36 +1670,13 @@ export class Matterbridge extends EventEmitter {
2360
1670
  }
2361
1671
  return vendorName;
2362
1672
  };
2363
- /**
2364
- * Spawns a child process with the given command and arguments.
2365
- * @param {string} command - The command to execute.
2366
- * @param {string[]} args - The arguments to pass to the command (default: []).
2367
- * @returns {Promise<boolean>} A promise that resolves when the child process exits successfully, or rejects if there is an error.
2368
- */
2369
1673
  async spawnCommand(command, args = []) {
2370
- /*
2371
- npm > npm.cmd on windows
2372
- cmd.exe ['dir'] on windows
2373
- await this.spawnCommand('npm', ['install', '-g', 'matterbridge']);
2374
- process.on('unhandledRejection', (reason, promise) => {
2375
- this.log.error('Unhandled Rejection at:', promise, 'reason:', reason);
2376
- });
2377
-
2378
- spawn - [14:27:21.125] [Matterbridge:spawn]: changed 38 packages in 4s
2379
- spawn - [14:27:21.125] [Matterbridge:spawn]: 10 packages are looking for funding run `npm fund` for details
2380
- debug - [14:27:21.131] [Matterbridge]: Child process exited with code 0 and signal null
2381
- debug - [14:27:21.131] [Matterbridge]: Child process stdio streams have closed with code 0
2382
- */
2383
1674
  const cmdLine = command + ' ' + args.join(' ');
2384
1675
  if (process.platform === 'win32' && command === 'npm') {
2385
- // Must be spawn('cmd.exe', ['/c', 'npm -g install <package>']);
2386
1676
  const argstring = 'npm ' + args.join(' ');
2387
1677
  args.splice(0, args.length, '/c', argstring);
2388
1678
  command = 'cmd.exe';
2389
1679
  }
2390
- // Decide when using sudo on linux
2391
- // When you need sudo: Spawn stderr: npm error Error: EACCES: permission denied
2392
- // When you don't need sudo: Failed to start child process "npm install -g matterbridge-eve-door": spawn sudo ENOENT
2393
1680
  if (hasParameter('sudo') || (process.platform === 'linux' && command === 'npm' && !hasParameter('docker') && !hasParameter('nosudo'))) {
2394
1681
  args.unshift(command);
2395
1682
  command = 'sudo';
@@ -2448,4 +1735,3 @@ export class Matterbridge extends EventEmitter {
2448
1735
  });
2449
1736
  }
2450
1737
  }
2451
- //# sourceMappingURL=matterbridge.js.map