@matterbridge/core 3.9.2-dev-20260620-9802e5b → 3.9.2-dev-20260620-2b9580a

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.
package/dist/backend.d.ts CHANGED
@@ -29,9 +29,9 @@ export declare class Backend extends EventEmitter<BackendEvents> {
29
29
  private broadcastMsgHandler;
30
30
  start(port?: number): Promise<void>;
31
31
  stop(): Promise<void>;
32
- getApiSettings(): ApiSettings;
33
- getApiPlugins(): ApiPlugin[];
34
- getApiDevices(_pluginName?: string): ApiDevice[];
32
+ getApiSettings(): Promise<ApiSettings>;
33
+ getApiPlugins(): Promise<ApiPlugin[]>;
34
+ getApiDevices(pluginName?: string): Promise<ApiDevice[]>;
35
35
  generateDiagnostic(): Promise<void>;
36
36
  }
37
37
  export {};
package/dist/backend.js CHANGED
@@ -292,13 +292,16 @@ export class Backend extends EventEmitter {
292
292
  this.backendExpress = undefined;
293
293
  this.log.debug('Backend stopped');
294
294
  }
295
- getApiSettings() {
296
- return {};
295
+ async getApiSettings() {
296
+ const response = await this.server.fetch({ type: 'matterbridge_apisettings', src: 'frontend', dst: 'matterbridge', params: undefined });
297
+ return response.result.data;
297
298
  }
298
- getApiPlugins() {
299
- return [];
299
+ async getApiPlugins() {
300
+ const response = await this.server.fetch({ type: 'plugins_apipluginarray', src: 'frontend', dst: 'plugins', params: undefined });
301
+ return response.result.plugins;
300
302
  }
301
- getApiDevices(_pluginName) {
303
+ async getApiDevices(pluginName) {
304
+ const _response = await this.server.fetch({ type: 'devices_basearray', src: 'frontend', dst: 'devices', params: { pluginName } });
302
305
  return [];
303
306
  }
304
307
  async generateDiagnostic() { }
@@ -131,23 +131,23 @@ export class BackendExpress {
131
131
  };
132
132
  res.status(200).json(memoryReport);
133
133
  });
134
- this.expressApp.get('/api/settings', (req, res) => {
134
+ this.expressApp.get('/api/settings', async (req, res) => {
135
135
  this.log.debug('The frontend sent /api/settings');
136
136
  if (!this.validateReq(req, res))
137
137
  return;
138
- res.json(this.backend.getApiSettings());
138
+ res.json(await this.backend.getApiSettings());
139
139
  });
140
- this.expressApp.get('/api/plugins', (req, res) => {
140
+ this.expressApp.get('/api/plugins', async (req, res) => {
141
141
  this.log.debug('The frontend sent /api/plugins');
142
142
  if (!this.validateReq(req, res))
143
143
  return;
144
- res.json(this.backend.getApiPlugins());
144
+ res.json(await this.backend.getApiPlugins());
145
145
  });
146
- this.expressApp.get('/api/devices', (req, res) => {
146
+ this.expressApp.get('/api/devices', async (req, res) => {
147
147
  this.log.debug('The frontend sent /api/devices');
148
148
  if (!this.validateReq(req, res))
149
149
  return;
150
- res.json(this.backend.getApiDevices());
150
+ res.json(await this.backend.getApiDevices());
151
151
  });
152
152
  this.expressApp.get('/api/view-mblog', async (req, res) => {
153
153
  this.log.debug('The frontend sent /api/view-mblog');
@@ -25,7 +25,8 @@ export declare class BackendWsServer {
25
25
  }): void;
26
26
  wssSendRestartRequired(snackbar?: boolean, fixed?: boolean): void;
27
27
  wssSendRestartNotRequired(snackbar?: boolean): void;
28
- wssSendUpdateRequired(devVersion?: boolean): void;
28
+ wssSendUpdateRequired(version: string, devVersion?: boolean): void;
29
+ wssSendPluginUpdateRequired(plugin: string, version: string, devVersion?: boolean): void;
29
30
  wssSendCpuUpdate(cpuUsage: number, processCpuUsage: number): void;
30
31
  wssSendMemoryUpdate(totalMemory: string, freeMemory: string, rss: string, heapTotal: string, heapUsed: string, external: string, arrayBuffers: string): void;
31
32
  wssSendUptimeUpdate(systemUptime: string, processUptime: string): void;
@@ -232,12 +232,19 @@ export class BackendWsServer {
232
232
  this.wssSendCloseSnackbarMessage(`Restart required`);
233
233
  this.wssBroadcastMessage({ id: 0, src: 'Matterbridge', dst: 'Frontend', method: 'restart_not_required', success: true });
234
234
  }
235
- wssSendUpdateRequired(devVersion = false) {
235
+ wssSendUpdateRequired(version, devVersion = false) {
236
236
  if (!this.hasActiveClients())
237
237
  return;
238
238
  if (this.verbose)
239
239
  this.log.debug('Sending an update required message to all connected clients');
240
- this.wssBroadcastMessage({ id: 0, src: 'Matterbridge', dst: 'Frontend', method: 'update_required', success: true, response: { devVersion } });
240
+ this.wssBroadcastMessage({ id: 0, src: 'Matterbridge', dst: 'Frontend', method: 'update_required', success: true, response: { version, devVersion } });
241
+ }
242
+ wssSendPluginUpdateRequired(plugin, version, devVersion = false) {
243
+ if (!this.hasActiveClients())
244
+ return;
245
+ if (this.verbose)
246
+ this.log.debug('Sending a plugin update required message to all connected clients');
247
+ this.wssBroadcastMessage({ id: 0, src: 'Matterbridge', dst: 'Frontend', method: 'plugin_update_required', success: true, response: { plugin, version, devVersion } });
241
248
  }
242
249
  wssSendCpuUpdate(cpuUsage, processCpuUsage) {
243
250
  if (!this.hasActiveClients())
@@ -57,7 +57,8 @@ export declare class Frontend extends EventEmitter<FrontendEvents> {
57
57
  }): void;
58
58
  wssSendRestartRequired(snackbar?: boolean, fixed?: boolean): void;
59
59
  wssSendRestartNotRequired(snackbar?: boolean): void;
60
- wssSendUpdateRequired(devVersion?: boolean): void;
60
+ wssSendUpdateRequired(version: string, devVersion?: boolean): void;
61
+ wssSendPluginUpdateRequired(plugin: string, version: string, devVersion?: boolean): void;
61
62
  wssSendCpuUpdate(cpuUsage: number, processCpuUsage: number): void;
62
63
  wssSendMemoryUpdate(totalMemory: string, freeMemory: string, rss: string, heapTotal: string, heapUsed: string, external: string, arrayBuffers: string): void;
63
64
  wssSendUptimeUpdate(systemUptime: string, processUptime: string): void;
package/dist/frontend.js CHANGED
@@ -93,7 +93,11 @@ export class Frontend extends EventEmitter {
93
93
  this.server.respond({ ...msg, result: { success: true } });
94
94
  break;
95
95
  case 'frontend_updaterequired':
96
- this.wssSendUpdateRequired(msg.params.devVersion);
96
+ this.wssSendUpdateRequired(msg.params.version, msg.params.devVersion);
97
+ this.server.respond({ ...msg, result: { success: true } });
98
+ break;
99
+ case 'frontend_pluginupdaterequired':
100
+ this.wssSendPluginUpdateRequired(msg.params.plugin, msg.params.version, msg.params.devVersion);
97
101
  this.server.respond({ ...msg, result: { success: true } });
98
102
  break;
99
103
  case 'frontend_snackbarmessage':
@@ -2113,12 +2117,18 @@ export class Frontend extends EventEmitter {
2113
2117
  this.wssSendCloseSnackbarMessage(`Restart required`);
2114
2118
  this.wssBroadcastMessage({ id: 0, src: 'Matterbridge', dst: 'Frontend', method: 'restart_not_required', success: true });
2115
2119
  }
2116
- wssSendUpdateRequired(devVersion = false) {
2120
+ wssSendUpdateRequired(version, devVersion = false) {
2117
2121
  if (!this.listening || this.webSocketServer?.clients.size === 0)
2118
2122
  return;
2119
2123
  this.log.debug('Sending an update required message to all connected clients');
2120
2124
  this.updateRequired = true;
2121
- this.wssBroadcastMessage({ id: 0, src: 'Matterbridge', dst: 'Frontend', method: 'update_required', success: true, response: { devVersion } });
2125
+ this.wssBroadcastMessage({ id: 0, src: 'Matterbridge', dst: 'Frontend', method: 'update_required', success: true, response: { version, devVersion } });
2126
+ }
2127
+ wssSendPluginUpdateRequired(plugin, version, devVersion = false) {
2128
+ if (!this.listening || this.webSocketServer?.clients.size === 0)
2129
+ return;
2130
+ this.log.debug('Sending a plugin update required message to all connected clients');
2131
+ this.wssBroadcastMessage({ id: 0, src: 'Matterbridge', dst: 'Frontend', method: 'plugin_update_required', success: true, response: { plugin, version, devVersion } });
2122
2132
  }
2123
2133
  wssSendCpuUpdate(cpuUsage, processCpuUsage) {
2124
2134
  if (!this.listening || this.webSocketServer?.clients.size === 0)
@@ -5,7 +5,7 @@ import { Endpoint, ServerNode } from '@matter/node';
5
5
  import { AggregatorEndpoint } from '@matter/node/endpoints/aggregator';
6
6
  import { type DeviceCertification } from '@matter/protocol';
7
7
  import { DeviceTypeId, VendorId } from '@matter/types/datatype';
8
- import type { ApiMatter, MaybePromise, PlatformMatterbridge, SharedMatterbridge, SystemInformation } from '@matterbridge/types';
8
+ import type { ApiMatter, ApiSettings, MaybePromise, PlatformMatterbridge, SharedMatterbridge, SystemInformation } from '@matterbridge/types';
9
9
  import { AnsiLogger, LogLevel } from 'node-ansi-logger';
10
10
  import { type NodeStorage, NodeStorageManager } from 'node-persist-manager';
11
11
  import { DeviceManager } from './deviceManager.js';
@@ -116,6 +116,7 @@ export declare class Matterbridge extends EventEmitter<MatterbridgeEvents> {
116
116
  destroy(): void;
117
117
  getPlatformMatterbridge(): PlatformMatterbridge;
118
118
  getSharedMatterbridge(): SharedMatterbridge;
119
+ getApiSettings(): ApiSettings;
119
120
  private msgHandler;
120
121
  static loadInstance(initialize?: boolean): Promise<Matterbridge>;
121
122
  private initialize;
@@ -17,7 +17,7 @@ import { dev, MATTER_LOGGER_FILE, MATTER_STORAGE_DIR, MATTERBRIDGE_LOGGER_FILE,
17
17
  import { getIntParameter, getParameter, hasAnyParameter, hasParameter } from '@matterbridge/utils/cli';
18
18
  import { copyDirectory } from '@matterbridge/utils/copy-dir';
19
19
  import { createDirectory } from '@matterbridge/utils/create-dir';
20
- import { inspectError, logError } from '@matterbridge/utils/error';
20
+ import { getErrorMessage, inspectError, logError } from '@matterbridge/utils/error';
21
21
  import { formatBytes, formatPercent, formatUptime } from '@matterbridge/utils/format';
22
22
  import { logModuleLoaded } from '@matterbridge/utils/loader';
23
23
  import { excludedInterfaceNamePattern } from '@matterbridge/utils/network';
@@ -209,6 +209,48 @@ export class Matterbridge extends EventEmitter {
209
209
  passcode: this.passcode,
210
210
  };
211
211
  }
212
+ getApiSettings() {
213
+ return {
214
+ systemInformation: { ...this.systemInformation },
215
+ matterbridgeInformation: {
216
+ rootDirectory: this.rootDirectory,
217
+ homeDirectory: this.homeDirectory,
218
+ matterbridgeDirectory: this.matterbridgeDirectory,
219
+ matterbridgePluginDirectory: this.matterbridgePluginDirectory,
220
+ matterbridgeCertDirectory: this.matterbridgeCertDirectory,
221
+ globalModulesDirectory: this.globalModulesDirectory,
222
+ matterbridgeVersion: this.matterbridgeVersion,
223
+ matterbridgeLatestVersion: this.matterbridgeLatestVersion,
224
+ matterbridgeDevVersion: this.matterbridgeDevVersion,
225
+ frontendVersion: this.frontendVersion,
226
+ dockerDev: this.dockerDev,
227
+ dockerVersion: this.dockerVersion,
228
+ dockerLatestVersion: this.dockerLatestVersion,
229
+ dockerDevVersion: this.dockerDevVersion,
230
+ bridgeMode: this.bridgeMode,
231
+ restartMode: this.restartMode,
232
+ virtualMode: this.virtualMode,
233
+ profile: this.profile,
234
+ readOnly: hasParameter('readonly'),
235
+ shellyBoard: false,
236
+ shellySysUpdate: false,
237
+ shellyMainUpdate: false,
238
+ loggerLevel: this.logLevel,
239
+ fileLogger: this.fileLogger,
240
+ matterLoggerLevel: this.matterLogLevel,
241
+ matterFileLogger: this.matterFileLogger,
242
+ matterMdnsInterface: this.mdnsInterface,
243
+ matterIpv4Address: this.ipv4Address,
244
+ matterIpv6Address: this.ipv6Address,
245
+ matterPort: this.port ?? 5540,
246
+ matterDiscriminator: this.discriminator,
247
+ matterPasscode: this.passcode,
248
+ restartRequired: false,
249
+ fixedRestartRequired: false,
250
+ updateRequired: false,
251
+ },
252
+ };
253
+ }
212
254
  async msgHandler(msg) {
213
255
  if (this.server.isWorkerRequest(msg) && (msg.dst === 'all' || msg.dst === 'matterbridge')) {
214
256
  if (this.verbose)
@@ -249,6 +291,9 @@ export class Matterbridge extends EventEmitter {
249
291
  case 'matterbridge_shared':
250
292
  this.server.respond({ ...msg, result: { data: this.getSharedMatterbridge(), success: true } });
251
293
  break;
294
+ case 'matterbridge_apisettings':
295
+ this.server.respond({ ...msg, result: { data: this.getApiSettings(), success: true } });
296
+ break;
252
297
  case 'matterbridge_start_plugin_server':
253
298
  {
254
299
  const plugin = this.plugins.get(msg.params.pluginName);
@@ -440,7 +485,7 @@ export class Matterbridge extends EventEmitter {
440
485
  }
441
486
  }
442
487
  catch (error) {
443
- this.log.debug(`Pairing file ${CYAN}${pairingFilePath}${db} not found: ${error instanceof Error ? error.message : error}`);
488
+ this.log.debug(`Pairing file ${CYAN}${pairingFilePath}${db} not found: ${getErrorMessage(error)}`);
444
489
  }
445
490
  await this.nodeContext.set('matterport', this.port);
446
491
  await this.nodeContext.set('matterpasscode', this.passcode);
@@ -549,14 +594,14 @@ export class Matterbridge extends EventEmitter {
549
594
  this.mdnsInterface = undefined;
550
595
  }
551
596
  if (this.mdnsInterface) {
552
- if (!availableInterfaceNames.includes(this.mdnsInterface)) {
597
+ if (availableInterfaceNames.includes(this.mdnsInterface)) {
598
+ this.log.info(`Using mdnsinterface ${CYAN}${this.mdnsInterface}${nf} for the Matter MdnsBroadcaster.`);
599
+ }
600
+ else {
553
601
  this.log.error(`Invalid mdnsinterface: ${this.mdnsInterface}. Available interfaces are: ${availableInterfaceNames.join(', ')}. Using all available interfaces.`);
554
602
  this.mdnsInterface = undefined;
555
603
  await this.nodeContext.remove('mattermdnsinterface');
556
604
  }
557
- else {
558
- this.log.info(`Using mdnsinterface ${CYAN}${this.mdnsInterface}${nf} for the Matter MdnsBroadcaster.`);
559
- }
560
605
  }
561
606
  if (this.mdnsInterface)
562
607
  this.environment.vars.set('mdns.networkInterface', this.mdnsInterface);
@@ -683,12 +728,12 @@ export class Matterbridge extends EventEmitter {
683
728
  await plugin.nodeContext.set('author', plugin.author);
684
729
  }
685
730
  await this.logNodeAndSystemInfo();
686
- this.log.notice(`Matterbridge version ${this.matterbridgeVersion} ` +
687
- `${hasParameter('bridge') || (!hasParameter('childbridge') && (await this.nodeContext?.get('bridgeMode', '')) === 'bridge') ? 'mode bridge ' : ''}` +
688
- `${hasParameter('childbridge') || (!hasParameter('bridge') && (await this.nodeContext?.get('bridgeMode', '')) === 'childbridge') ? 'mode childbridge ' : ''}` +
689
- `${hasParameter('controller') ? 'mode controller ' : ''}` +
690
- `${this.restartMode !== '' ? 'restart mode ' + this.restartMode + ' ' : ''}` +
691
- `running on ${this.systemInformation.osType} (v.${this.systemInformation.osRelease}) platform ${this.systemInformation.osPlatform} arch ${this.systemInformation.osArch}`);
731
+ this.log.notice('Matterbridge version ' + this.matterbridgeVersion + ' ' +
732
+ (hasParameter('bridge') || (!hasParameter('childbridge') && (await this.nodeContext?.get('bridgeMode', '')) === 'bridge') ? 'mode bridge ' : '') +
733
+ (hasParameter('childbridge') || (!hasParameter('bridge') && (await this.nodeContext?.get('bridgeMode', '')) === 'childbridge') ? 'mode childbridge ' : '') +
734
+ (hasParameter('controller') ? 'mode controller ' : '') +
735
+ (this.restartMode === '' ? '' : 'restart mode ' + this.restartMode + ' ') +
736
+ 'running on ' + this.systemInformation.osType + ' (v.' + this.systemInformation.osRelease + ') platform ' + this.systemInformation.osPlatform + ' arch ' + this.systemInformation.osArch);
692
737
  const minNodeVersion = 20;
693
738
  const nodeVersion = process.versions.node;
694
739
  const [versionMajor] = nodeVersion.split('.').map(Number);
@@ -705,13 +750,13 @@ export class Matterbridge extends EventEmitter {
705
750
  this.log.info(`│ Registered plugins (${this.plugins.length})`);
706
751
  let index = 0;
707
752
  for (const plugin of this.plugins) {
708
- if (index !== this.plugins.length - 1) {
709
- this.log.info(`├─┬─ plugin ${plg}${plugin.name}${nf}: "${plg}${BRIGHT}${plugin.description}${RESET}${nf}" type: ${typ}${plugin.type}${nf} version: ${plg}${plugin.version}${nf} ${plugin.enabled ? GREEN : RED}enabled${nf}`);
710
- this.log.info(`│ └─ entry ${UNDERLINE}${db}${plugin.path}${UNDERLINEOFF}${db}`);
753
+ if (index === this.plugins.length - 1) {
754
+ this.log.info(`└─┬─ plugin ${plg}${plugin.name}${nf}: "${plg}${BRIGHT}${plugin.description}${RESET}${nf}" type: ${typ}${plugin.type}${nf} version: ${plg}${plugin.version}${nf} ${plugin.enabled ? GREEN : RED}${plugin.enabled ? 'enabled' : 'disabled'}${nf}`);
755
+ this.log.info(` └─ entry ${UNDERLINE}${db}${plugin.path}${UNDERLINEOFF}${db}`);
711
756
  }
712
757
  else {
713
- this.log.info(`└─┬─ plugin ${plg}${plugin.name}${nf}: "${plg}${BRIGHT}${plugin.description}${RESET}${nf}" type: ${typ}${plugin.type}${nf} version: ${plg}${plugin.version}${nf} ${plugin.enabled ? GREEN : RED}disabled${nf}`);
714
- this.log.info(` └─ entry ${UNDERLINE}${db}${plugin.path}${UNDERLINEOFF}${db}`);
758
+ this.log.info(`├─┬─ plugin ${plg}${plugin.name}${nf}: "${plg}${BRIGHT}${plugin.description}${RESET}${nf}" type: ${typ}${plugin.type}${nf} version: ${plg}${plugin.version}${nf} ${plugin.enabled ? GREEN : RED}${plugin.enabled ? 'enabled' : 'disabled'}${nf}`);
759
+ this.log.info(`│ └─ entry ${UNDERLINE}${db}${plugin.path}${UNDERLINEOFF}${db}`);
715
760
  }
716
761
  index++;
717
762
  }
@@ -741,27 +786,31 @@ export class Matterbridge extends EventEmitter {
741
786
  this.shutdown = true;
742
787
  return;
743
788
  }
744
- if (getParameter('add')) {
745
- this.log.debug(`Adding plugin ${getParameter('add')}`);
746
- await this.plugins.add(getParameter('add'));
789
+ const addPlugin = getParameter('add');
790
+ if (addPlugin) {
791
+ this.log.debug(`Adding plugin ${addPlugin}`);
792
+ await this.plugins.add(addPlugin);
747
793
  this.shutdown = true;
748
794
  return;
749
795
  }
750
- if (getParameter('remove')) {
751
- this.log.debug(`Removing plugin ${getParameter('remove')}`);
752
- await this.plugins.remove(getParameter('remove'));
796
+ const removePlugin = getParameter('remove');
797
+ if (removePlugin) {
798
+ this.log.debug(`Removing plugin ${removePlugin}`);
799
+ await this.plugins.remove(removePlugin);
753
800
  this.shutdown = true;
754
801
  return;
755
802
  }
756
- if (getParameter('enable')) {
757
- this.log.debug(`Enabling plugin ${getParameter('enable')}`);
758
- await this.plugins.enable(getParameter('enable'));
803
+ const enablePlugin = getParameter('enable');
804
+ if (enablePlugin) {
805
+ this.log.debug(`Enabling plugin ${enablePlugin}`);
806
+ await this.plugins.enable(enablePlugin);
759
807
  this.shutdown = true;
760
808
  return;
761
809
  }
762
- if (getParameter('disable')) {
763
- this.log.debug(`Disabling plugin ${getParameter('disable')}`);
764
- await this.plugins.disable(getParameter('disable'));
810
+ const disablePlugin = getParameter('disable');
811
+ if (disablePlugin) {
812
+ this.log.debug(`Disabling plugin ${disablePlugin}`);
813
+ await this.plugins.disable(disablePlugin);
765
814
  this.shutdown = true;
766
815
  return;
767
816
  }
@@ -783,8 +832,8 @@ export class Matterbridge extends EventEmitter {
783
832
  }
784
833
  }
785
834
  catch (error) {
786
- this.log.fatal(`Fatal error creating matter storage: ${error instanceof Error ? error.message : error}`);
787
- throw new Error(`Fatal error creating matter storage: ${error instanceof Error ? error.message : error}`, { cause: error });
835
+ this.log.fatal(`Fatal error creating matter storage: ${getErrorMessage(error)}`);
836
+ throw new Error(`Fatal error creating matter storage: ${getErrorMessage(error)}`, { cause: error });
788
837
  }
789
838
  if (hasParameter('reset') && getParameter('reset') === undefined) {
790
839
  this.initialized = true;
@@ -792,15 +841,13 @@ export class Matterbridge extends EventEmitter {
792
841
  this.shutdown = true;
793
842
  return;
794
843
  }
795
- if (hasParameter('reset') && getParameter('reset') !== undefined) {
796
- this.log.debug(`Reset plugin ${getParameter('reset')}`);
797
- const plugin = this.plugins.get(getParameter('reset'));
844
+ const resetPlugin = getParameter('reset');
845
+ if (hasParameter('reset') && resetPlugin !== undefined) {
846
+ this.log.debug(`Reset plugin ${resetPlugin}`);
847
+ const plugin = this.plugins.get(resetPlugin);
798
848
  if (plugin) {
799
849
  const matterStorageManager = await this.matterStorageService?.open(plugin.name);
800
- if (!matterStorageManager) {
801
- this.log.error(`Plugin ${plg}${plugin.name}${er} storageManager not found`);
802
- }
803
- else {
850
+ if (matterStorageManager) {
804
851
  await matterStorageManager.createContext('events')?.clearAll();
805
852
  await matterStorageManager.createContext('fabrics')?.clearAll();
806
853
  await matterStorageManager.createContext('root')?.clearAll();
@@ -808,6 +855,9 @@ export class Matterbridge extends EventEmitter {
808
855
  await matterStorageManager.createContext('persist')?.clearAll();
809
856
  this.log.notice(`Reset commissioning for plugin ${plg}${plugin.name}${nt} done! Remove the device from the controller.`);
810
857
  }
858
+ else {
859
+ this.log.error(`Plugin ${plg}${plugin.name}${er} storageManager not found`);
860
+ }
811
861
  }
812
862
  else {
813
863
  this.log.warn(`Plugin ${plg}${getParameter('reset')}${wr} not registerd in matterbridge`);
@@ -845,13 +895,13 @@ export class Matterbridge extends EventEmitter {
845
895
  }
846
896
  if (hasParameter('delay') && os.uptime() <= 60 * 5) {
847
897
  const { wait } = await import('@matterbridge/utils/wait');
848
- const delay = getIntParameter('delay') || 120;
898
+ const delay = getIntParameter('delay') ?? 120;
849
899
  this.log.warn('Delay switch found with system uptime less then 5 minutes. Waiting for ' + delay + ' seconds before starting matterbridge...');
850
900
  await wait(delay * 1000, 'Race condition delay', true);
851
901
  }
852
902
  if (hasParameter('fixed_delay')) {
853
903
  const { wait } = await import('@matterbridge/utils/wait');
854
- const delay = getIntParameter('fixed_delay') || 120;
904
+ const delay = getIntParameter('fixed_delay') ?? 120;
855
905
  this.log.warn('Fixed delay switch found. Waiting for ' + delay + ' seconds before starting matterbridge...');
856
906
  await wait(delay * 1000, 'Fixed race condition delay', true);
857
907
  }
@@ -899,25 +949,29 @@ export class Matterbridge extends EventEmitter {
899
949
  this.log.debug(`Registering uncaughtException and unhandledRejection handlers...`);
900
950
  process.removeAllListeners('uncaughtException');
901
951
  process.removeAllListeners('unhandledRejection');
902
- this.exceptionHandler = async (error) => {
903
- const errorMessage = error instanceof Error ? error.message : error;
952
+ this.exceptionHandler = (error) => {
953
+ const errorMessage = getErrorMessage(error);
904
954
  const errorInspect = inspect(error, { depth: 10 });
905
- this.log.error(`Unhandled Exception detected: ${errorMessage}\nstack: ${errorInspect}}`);
955
+ this.log.error(`Unhandled Exception detected: ${errorMessage}\nstack: ${errorInspect}`);
906
956
  };
907
957
  process.on('uncaughtException', this.exceptionHandler);
908
- this.rejectionHandler = async (reason, promise) => {
909
- const errorMessage = reason instanceof Error ? reason.message : reason;
958
+ this.rejectionHandler = (reason, _promise) => {
959
+ const errorMessage = getErrorMessage(reason);
910
960
  const errorInspect = inspect(reason, { depth: 10 });
911
- this.log.error(`Unhandled Rejection detected: ${promise}\nreason: ${errorMessage}\nstack: ${errorInspect}`);
961
+ this.log.error(`Unhandled Rejection detected: ${errorMessage}\nstack: ${errorInspect}`);
912
962
  };
913
963
  process.on('unhandledRejection', this.rejectionHandler);
914
964
  this.log.debug(`Registering SIGINT and SIGTERM signal handlers...`);
915
- this.sigintHandler = async () => {
916
- await this.cleanup('SIGINT received, cleaning up...');
965
+ this.sigintHandler = () => {
966
+ this.cleanup('SIGINT received, cleaning up...').catch((error) => {
967
+ this.log.error(`Error cleaning up on SIGINT: ${getErrorMessage(error)}`);
968
+ });
917
969
  };
918
970
  process.on('SIGINT', this.sigintHandler);
919
- this.sigtermHandler = async () => {
920
- await this.cleanup('SIGTERM received, cleaning up...');
971
+ this.sigtermHandler = () => {
972
+ this.cleanup('SIGTERM received, cleaning up...').catch((error) => {
973
+ this.log.error(`Error cleaning up on SIGTERM: ${getErrorMessage(error)}`);
974
+ });
921
975
  };
922
976
  process.on('SIGTERM', this.sigtermHandler);
923
977
  }
@@ -1401,74 +1455,78 @@ export class Matterbridge extends EventEmitter {
1401
1455
  this.log.debug('Starting start matter interval in bridge mode...');
1402
1456
  this.frontend.wssSendSnackbarMessage(`The bridge is starting...`, 0, 'info');
1403
1457
  let failCount = 0;
1404
- this.startMatterInterval = setInterval(async () => {
1405
- if (failCount && failCount % 10 === 0) {
1406
- this.frontend.wssSendSnackbarMessage(`The bridge is still starting...`, 10, 'info');
1407
- this.frontend.wssSendRefreshRequired('plugins');
1408
- }
1409
- for (const plugin of this.plugins) {
1410
- if (!plugin.enabled)
1411
- continue;
1412
- if (plugin.error) {
1413
- clearInterval(this.startMatterInterval);
1414
- this.startMatterInterval = undefined;
1415
- this.log.debug('Cleared startMatterInterval interval for Matterbridge for plugin in error state');
1416
- this.log.error(`The plugin ${plg}${plugin.name}${er} is in error state.`);
1417
- this.log.error('The bridge will not start until the problem is solved to prevent the controllers from deleting all registered devices.');
1418
- this.log.error('If you want to start the bridge disable the plugin in error state and restart.');
1419
- this.frontend.wssSendSnackbarMessage(`The plugin ${plugin.name} is in error state. Check the logs.`, 0, 'error');
1420
- this.frontend.wssSendSnackbarMessage(`The bridge is offline. Startup halted due to plugin errors.`, 0, 'error');
1458
+ this.startMatterInterval = setInterval(() => {
1459
+ void (async () => {
1460
+ if (failCount && failCount % 10 === 0) {
1461
+ this.frontend.wssSendSnackbarMessage(`The bridge is still starting...`, 10, 'info');
1421
1462
  this.frontend.wssSendRefreshRequired('plugins');
1422
- this.frontend.wssSendCloseSnackbarMessage(`The bridge is starting...`);
1423
- return;
1424
- }
1425
- if (!plugin.loaded || !plugin.started) {
1426
- this.log.debug(`Waiting (failSafeCount=${failCount}/${this.failCountLimit}) in startMatterInterval interval for plugin ${plg}${plugin.name}${db} loaded: ${plugin.loaded} started: ${plugin.started}...`);
1427
- failCount++;
1428
- if (failCount > this.failCountLimit) {
1429
- this.log.error(`Error waiting for plugin ${plg}${plugin.name}${er} to load and start. Plugin is in error state.`);
1430
- plugin.error = true;
1431
- }
1432
- return;
1433
- }
1434
- }
1435
- clearInterval(this.startMatterInterval);
1436
- this.startMatterInterval = undefined;
1437
- this.log.debug('Cleared startMatterInterval interval in bridge mode');
1438
- fireAndForget(this.startServerNode(this.serverNode), this.log, 'Start server node');
1439
- for (const device of this.devices.array()) {
1440
- if (device.mode === 'server' && device.serverNode) {
1441
- this.log.debug(`Starting server node for device ${dev}${device.deviceName}${db} in server mode...`);
1442
- fireAndForget(this.startServerNode(device.serverNode), this.log, `Start server node for device ${device.deviceName}`);
1443
1463
  }
1444
- }
1445
- this.configureTimeout = setTimeout(async () => {
1446
- for (const plugin of this.plugins.array()) {
1447
- if (!plugin.enabled || !plugin.loaded || !plugin.started || plugin.error)
1464
+ for (const plugin of this.plugins) {
1465
+ if (!plugin.enabled)
1448
1466
  continue;
1449
- try {
1450
- if ((await this.plugins.configure(plugin)) === undefined) {
1451
- if (plugin.configured !== true)
1452
- this.frontend.wssSendSnackbarMessage(`The plugin ${plugin.name} failed to configure. Check the logs.`, 0, 'error');
1467
+ if (plugin.error) {
1468
+ clearInterval(this.startMatterInterval);
1469
+ this.startMatterInterval = undefined;
1470
+ this.log.debug('Cleared startMatterInterval interval for Matterbridge for plugin in error state');
1471
+ this.log.error(`The plugin ${plg}${plugin.name}${er} is in error state.`);
1472
+ this.log.error('The bridge will not start until the problem is solved to prevent the controllers from deleting all registered devices.');
1473
+ this.log.error('If you want to start the bridge disable the plugin in error state and restart.');
1474
+ this.frontend.wssSendSnackbarMessage(`The plugin ${plugin.name} is in error state. Check the logs.`, 0, 'error');
1475
+ this.frontend.wssSendSnackbarMessage(`The bridge is offline. Startup halted due to plugin errors.`, 0, 'error');
1476
+ this.frontend.wssSendRefreshRequired('plugins');
1477
+ this.frontend.wssSendCloseSnackbarMessage(`The bridge is starting...`);
1478
+ return;
1479
+ }
1480
+ if (!plugin.loaded || !plugin.started) {
1481
+ this.log.debug(`Waiting (failSafeCount=${failCount}/${this.failCountLimit}) in startMatterInterval interval for plugin ${plg}${plugin.name}${db} loaded: ${plugin.loaded} started: ${plugin.started}...`);
1482
+ failCount++;
1483
+ if (failCount > this.failCountLimit) {
1484
+ this.log.error(`Error waiting for plugin ${plg}${plugin.name}${er} to load and start. Plugin is in error state.`);
1485
+ plugin.error = true;
1453
1486
  }
1487
+ return;
1454
1488
  }
1455
- catch (error) {
1456
- plugin.error = true;
1457
- this.log.error(`Error configuring plugin ${plg}${plugin.name}${er}`, error);
1489
+ }
1490
+ clearInterval(this.startMatterInterval);
1491
+ this.startMatterInterval = undefined;
1492
+ this.log.debug('Cleared startMatterInterval interval in bridge mode');
1493
+ fireAndForget(this.startServerNode(this.serverNode), this.log, 'Start server node');
1494
+ for (const device of this.devices.array()) {
1495
+ if (device.mode === 'server' && device.serverNode) {
1496
+ this.log.debug(`Starting server node for device ${dev}${device.deviceName}${db} in server mode...`);
1497
+ fireAndForget(this.startServerNode(device.serverNode), this.log, `Start server node for device ${device.deviceName}`);
1458
1498
  }
1459
1499
  }
1500
+ this.configureTimeout = setTimeout(() => {
1501
+ void (async () => {
1502
+ for (const plugin of this.plugins.array()) {
1503
+ if (!plugin.enabled || !plugin.loaded || !plugin.started || plugin.error)
1504
+ continue;
1505
+ try {
1506
+ if ((await this.plugins.configure(plugin)) === undefined) {
1507
+ if (plugin.configured !== true)
1508
+ this.frontend.wssSendSnackbarMessage(`The plugin ${plugin.name} failed to configure. Check the logs.`, 0, 'error');
1509
+ }
1510
+ }
1511
+ catch (error) {
1512
+ plugin.error = true;
1513
+ this.log.error(`Error configuring plugin ${plg}${plugin.name}${er}`, error);
1514
+ }
1515
+ }
1516
+ this.frontend.wssSendRefreshRequired('plugins');
1517
+ })();
1518
+ }, 30 * 1000).unref();
1519
+ this.reachabilityTimeout = setTimeout(() => {
1520
+ this.log.info(`Setting reachability to true for ${plg}Matterbridge${db}`);
1521
+ if (this.aggregatorNode)
1522
+ fireAndForget(this.setAggregatorReachability(this.aggregatorNode, true), this.log, `Set aggregator node reachability for Matterbridge`);
1523
+ }, 60 * 1000).unref();
1524
+ this.emit('bridge_started');
1525
+ this.log.notice('Matterbridge bridge started successfully');
1526
+ this.frontend.wssSendRefreshRequired('settings');
1460
1527
  this.frontend.wssSendRefreshRequired('plugins');
1461
- }, 30 * 1000).unref();
1462
- this.reachabilityTimeout = setTimeout(() => {
1463
- this.log.info(`Setting reachability to true for ${plg}Matterbridge${db}`);
1464
- if (this.aggregatorNode)
1465
- fireAndForget(this.setAggregatorReachability(this.aggregatorNode, true), this.log, `Set aggregator node reachability for Matterbridge`);
1466
- }, 60 * 1000).unref();
1467
- this.emit('bridge_started');
1468
- this.log.notice('Matterbridge bridge started successfully');
1469
- this.frontend.wssSendRefreshRequired('settings');
1470
- this.frontend.wssSendRefreshRequired('plugins');
1471
- this.frontend.wssSendCloseSnackbarMessage(`The bridge is starting...`);
1528
+ this.frontend.wssSendCloseSnackbarMessage(`The bridge is starting...`);
1529
+ })();
1472
1530
  }, Number(process.env['MATTERBRIDGE_START_MATTER_INTERVAL_MS']) || this.startMatterIntervalMs);
1473
1531
  }
1474
1532
  async startChildbridge(delay = 1000) {
@@ -1486,100 +1544,104 @@ export class Matterbridge extends EventEmitter {
1486
1544
  this.log.debug('Starting start matter interval in childbridge mode...');
1487
1545
  this.frontend.wssSendSnackbarMessage(`The bridge is starting...`, 0, 'info');
1488
1546
  let failCount = 0;
1489
- this.startMatterInterval = setInterval(async () => {
1490
- if (failCount && failCount % 10 === 0) {
1491
- this.frontend.wssSendSnackbarMessage(`The bridge is still starting...`, 10, 'info');
1492
- this.frontend.wssSendRefreshRequired('plugins');
1493
- }
1494
- let allStarted = true;
1495
- for (const plugin of this.plugins.array()) {
1496
- if (!plugin.enabled)
1497
- continue;
1498
- if (plugin.error) {
1499
- clearInterval(this.startMatterInterval);
1500
- this.startMatterInterval = undefined;
1501
- this.log.debug('Cleared startMatterInterval interval for a plugin in error state');
1502
- this.log.error(`The plugin ${plg}${plugin.name}${er} is in error state.`);
1503
- this.log.error('The bridge will not start until the problem is solved to prevent the controllers from deleting all registered devices.');
1504
- this.log.error('If you want to start the bridge disable the plugin in error state and restart.');
1505
- this.frontend.wssSendSnackbarMessage(`The plugin ${plugin.name} is in error state. Check the logs.`, 0, 'error');
1506
- this.frontend.wssSendSnackbarMessage(`The bridge is offline. Startup halted due to plugin errors.`, 0, 'error');
1547
+ this.startMatterInterval = setInterval(() => {
1548
+ void (async () => {
1549
+ if (failCount && failCount % 10 === 0) {
1550
+ this.frontend.wssSendSnackbarMessage(`The bridge is still starting...`, 10, 'info');
1507
1551
  this.frontend.wssSendRefreshRequired('plugins');
1508
- this.frontend.wssSendCloseSnackbarMessage(`The bridge is starting...`);
1509
- return;
1510
1552
  }
1511
- this.log.debug(`Checking plugin ${plg}${plugin.name}${db} to start matter in childbridge mode...`);
1512
- if (!plugin.loaded || !plugin.started) {
1513
- allStarted = false;
1514
- this.log.debug(`Waiting (failSafeCount=${failCount}/${this.failCountLimit}) for plugin ${plg}${plugin.name}${db} to load (${plugin.loaded}) and start (${plugin.started}) ...`);
1515
- failCount++;
1516
- if (failCount > this.failCountLimit) {
1517
- this.log.error(`Error waiting for plugin ${plg}${plugin.name}${er} to load and start. Plugin is in error state.`);
1518
- plugin.error = true;
1553
+ let allStarted = true;
1554
+ for (const plugin of this.plugins.array()) {
1555
+ if (!plugin.enabled)
1556
+ continue;
1557
+ if (plugin.error) {
1558
+ clearInterval(this.startMatterInterval);
1559
+ this.startMatterInterval = undefined;
1560
+ this.log.debug('Cleared startMatterInterval interval for a plugin in error state');
1561
+ this.log.error(`The plugin ${plg}${plugin.name}${er} is in error state.`);
1562
+ this.log.error('The bridge will not start until the problem is solved to prevent the controllers from deleting all registered devices.');
1563
+ this.log.error('If you want to start the bridge disable the plugin in error state and restart.');
1564
+ this.frontend.wssSendSnackbarMessage(`The plugin ${plugin.name} is in error state. Check the logs.`, 0, 'error');
1565
+ this.frontend.wssSendSnackbarMessage(`The bridge is offline. Startup halted due to plugin errors.`, 0, 'error');
1566
+ this.frontend.wssSendRefreshRequired('plugins');
1567
+ this.frontend.wssSendCloseSnackbarMessage(`The bridge is starting...`);
1568
+ return;
1569
+ }
1570
+ this.log.debug(`Checking plugin ${plg}${plugin.name}${db} to start matter in childbridge mode...`);
1571
+ if (!plugin.loaded || !plugin.started) {
1572
+ allStarted = false;
1573
+ this.log.debug(`Waiting (failSafeCount=${failCount}/${this.failCountLimit}) for plugin ${plg}${plugin.name}${db} to load (${plugin.loaded}) and start (${plugin.started}) ...`);
1574
+ failCount++;
1575
+ if (failCount > this.failCountLimit) {
1576
+ this.log.error(`Error waiting for plugin ${plg}${plugin.name}${er} to load and start. Plugin is in error state.`);
1577
+ plugin.error = true;
1578
+ }
1519
1579
  }
1520
1580
  }
1521
- }
1522
- if (!allStarted)
1523
- return;
1524
- clearInterval(this.startMatterInterval);
1525
- this.startMatterInterval = undefined;
1526
- if (delay > 0)
1527
- await wait(Number(process.env['MATTERBRIDGE_PAUSE_MATTER_INTERVAL_MS']) || delay);
1528
- this.log.debug('Cleared startMatterInterval interval in childbridge mode');
1529
- this.configureTimeout = setTimeout(async () => {
1581
+ if (!allStarted)
1582
+ return;
1583
+ clearInterval(this.startMatterInterval);
1584
+ this.startMatterInterval = undefined;
1585
+ if (delay > 0)
1586
+ await wait(Number(process.env['MATTERBRIDGE_PAUSE_MATTER_INTERVAL_MS']) || delay);
1587
+ this.log.debug('Cleared startMatterInterval interval in childbridge mode');
1588
+ this.configureTimeout = setTimeout(() => {
1589
+ void (async () => {
1590
+ for (const plugin of this.plugins.array()) {
1591
+ if (!plugin.enabled || !plugin.loaded || !plugin.started || plugin.error)
1592
+ continue;
1593
+ try {
1594
+ if ((await this.plugins.configure(plugin)) === undefined) {
1595
+ if (plugin.configured !== true)
1596
+ this.frontend.wssSendSnackbarMessage(`The plugin ${plugin.name} failed to configure. Check the logs.`, 0, 'error');
1597
+ }
1598
+ }
1599
+ catch (error) {
1600
+ plugin.error = true;
1601
+ this.log.error(`Error configuring plugin ${plg}${plugin.name}${er}`, error);
1602
+ }
1603
+ }
1604
+ this.frontend.wssSendRefreshRequired('plugins');
1605
+ })();
1606
+ }, 30 * 1000).unref();
1530
1607
  for (const plugin of this.plugins.array()) {
1531
- if (!plugin.enabled || !plugin.loaded || !plugin.started || plugin.error)
1608
+ if (!plugin.enabled || plugin.error)
1609
+ continue;
1610
+ if (plugin.type !== 'DynamicPlatform' && (!plugin.registeredDevices || plugin.registeredDevices === 0)) {
1611
+ this.log.error(`Plugin ${plg}${plugin.name}${er} didn't register any devices to Matterbridge. Verify the plugin configuration.`);
1532
1612
  continue;
1533
- try {
1534
- if ((await this.plugins.configure(plugin)) === undefined) {
1535
- if (plugin.configured !== true)
1536
- this.frontend.wssSendSnackbarMessage(`The plugin ${plugin.name} failed to configure. Check the logs.`, 0, 'error');
1537
- }
1538
1613
  }
1539
- catch (error) {
1540
- plugin.error = true;
1541
- this.log.error(`Error configuring plugin ${plg}${plugin.name}${er}`, error);
1614
+ if (!plugin.serverNode) {
1615
+ this.log.error(`Server node not found for plugin ${plg}${plugin.name}${er}`);
1616
+ continue;
1542
1617
  }
1618
+ if (!plugin.storageContext) {
1619
+ this.log.error(`Storage context not found for plugin ${plg}${plugin.name}${er}`);
1620
+ continue;
1621
+ }
1622
+ if (!plugin.nodeContext) {
1623
+ this.log.error(`Node storage context not found for plugin ${plg}${plugin.name}${er}`);
1624
+ continue;
1625
+ }
1626
+ fireAndForget(this.startServerNode(plugin.serverNode), this.log, `Start server node for plugin ${plugin.name}`);
1627
+ plugin.reachabilityTimeout = setTimeout(() => {
1628
+ this.log.info(`Setting reachability to true for ${plg}${plugin.name}${nf}`);
1629
+ if (plugin.type === 'DynamicPlatform' && plugin.aggregatorNode)
1630
+ fireAndForget(this.setAggregatorReachability(plugin.aggregatorNode, true), this.log, `Set aggregator node reachability for plugin ${plugin.name}`);
1631
+ }, 60 * 1000).unref();
1543
1632
  }
1544
- this.frontend.wssSendRefreshRequired('plugins');
1545
- }, 30 * 1000).unref();
1546
- for (const plugin of this.plugins.array()) {
1547
- if (!plugin.enabled || plugin.error)
1548
- continue;
1549
- if (plugin.type !== 'DynamicPlatform' && (!plugin.registeredDevices || plugin.registeredDevices === 0)) {
1550
- this.log.error(`Plugin ${plg}${plugin.name}${er} didn't register any devices to Matterbridge. Verify the plugin configuration.`);
1551
- continue;
1552
- }
1553
- if (!plugin.serverNode) {
1554
- this.log.error(`Server node not found for plugin ${plg}${plugin.name}${er}`);
1555
- continue;
1556
- }
1557
- if (!plugin.storageContext) {
1558
- this.log.error(`Storage context not found for plugin ${plg}${plugin.name}${er}`);
1559
- continue;
1560
- }
1561
- if (!plugin.nodeContext) {
1562
- this.log.error(`Node storage context not found for plugin ${plg}${plugin.name}${er}`);
1563
- continue;
1564
- }
1565
- fireAndForget(this.startServerNode(plugin.serverNode), this.log, `Start server node for plugin ${plugin.name}`);
1566
- plugin.reachabilityTimeout = setTimeout(() => {
1567
- this.log.info(`Setting reachability to true for ${plg}${plugin.name}${nf}`);
1568
- if (plugin.type === 'DynamicPlatform' && plugin.aggregatorNode)
1569
- fireAndForget(this.setAggregatorReachability(plugin.aggregatorNode, true), this.log, `Set aggregator node reachability for plugin ${plugin.name}`);
1570
- }, 60 * 1000).unref();
1571
- }
1572
- for (const device of this.devices.array()) {
1573
- if (device.mode === 'server' && device.serverNode) {
1574
- this.log.debug(`Starting server node for device ${dev}${device.deviceName}${db} in server mode...`);
1575
- fireAndForget(this.startServerNode(device.serverNode), this.log, `Start server node for device ${device.deviceName}`);
1633
+ for (const device of this.devices.array()) {
1634
+ if (device.mode === 'server' && device.serverNode) {
1635
+ this.log.debug(`Starting server node for device ${dev}${device.deviceName}${db} in server mode...`);
1636
+ fireAndForget(this.startServerNode(device.serverNode), this.log, `Start server node for device ${device.deviceName}`);
1637
+ }
1576
1638
  }
1577
- }
1578
- this.emit('childbridge_started');
1579
- this.log.notice('Matterbridge childbridge started successfully');
1580
- this.frontend.wssSendRefreshRequired('settings');
1581
- this.frontend.wssSendRefreshRequired('plugins');
1582
- this.frontend.wssSendCloseSnackbarMessage(`The bridge is starting...`);
1639
+ this.emit('childbridge_started');
1640
+ this.log.notice('Matterbridge childbridge started successfully');
1641
+ this.frontend.wssSendRefreshRequired('settings');
1642
+ this.frontend.wssSendRefreshRequired('plugins');
1643
+ this.frontend.wssSendCloseSnackbarMessage(`The bridge is starting...`);
1644
+ })();
1583
1645
  }, Number(process.env['MATTERBRIDGE_START_MATTER_INTERVAL_MS']) || this.startMatterIntervalMs);
1584
1646
  }
1585
1647
  async startController() {
@@ -1732,9 +1794,13 @@ export class Matterbridge extends EventEmitter {
1732
1794
  this.frontend.wssSendSnackbarMessage(`${storeId} is offline`, 5, 'warning');
1733
1795
  this.frontend.wssSendSnackbarMessage(`Server node for ${storeId} fully decommissioned successfully!`, 5, 'success');
1734
1796
  });
1735
- serverNode.lifecycle.online.on(async () => {
1797
+ serverNode.lifecycle.online.on(() => {
1736
1798
  this.log.notice(`Server node for ${storeId} is online`);
1737
- if (!serverNode.lifecycle.isCommissioned) {
1799
+ if (serverNode.lifecycle.isCommissioned) {
1800
+ this.log.notice(`Server node for ${storeId} is already commissioned.`);
1801
+ this.advertisingNodes.delete(storeId);
1802
+ }
1803
+ else {
1738
1804
  this.log.notice(`Server node for ${storeId} is not commissioned. Pair to commission.`);
1739
1805
  this.advertisingNodes.set(storeId, Date.now());
1740
1806
  const { qrPairingCode, manualPairingCode } = serverNode.state.commissioning.pairingCodes;
@@ -1742,10 +1808,6 @@ export class Matterbridge extends EventEmitter {
1742
1808
  this.log.notice(`QR Code URL: https://project-chip.github.io/connectedhomeip/qrcode.html?data=${qrPairingCode}`);
1743
1809
  this.log.notice(`Manual pairing code ${CYAN}${manualPairingCode}${nt} discriminator ${CYAN}${discriminator}${nt} short discriminator ${CYAN}${pairingData.shortDiscriminator}${nt} passcode ${CYAN}${passcode}${nt}`);
1744
1810
  }
1745
- else {
1746
- this.log.notice(`Server node for ${storeId} is already commissioned.`);
1747
- this.advertisingNodes.delete(storeId);
1748
- }
1749
1811
  this.frontend.wssSendRefreshRequired('matter', { matter: { ...this.getServerNodeData(serverNode) } });
1750
1812
  this.frontend.wssSendSnackbarMessage(`${storeId} is online`, 5, 'success');
1751
1813
  this.emit('online', storeId);
@@ -1790,7 +1852,7 @@ export class Matterbridge extends EventEmitter {
1790
1852
  return serverNode;
1791
1853
  }
1792
1854
  getServerNodeData(serverNode) {
1793
- const advertiseTime = this.advertisingNodes.get(serverNode.id) || 0;
1855
+ const advertiseTime = this.advertisingNodes.get(serverNode.id) ?? 0;
1794
1856
  return {
1795
1857
  id: serverNode.id,
1796
1858
  online: serverNode.lifecycle.isOnline,
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@matterbridge/core",
3
- "version": "3.9.2-dev-20260620-9802e5b",
3
+ "version": "3.9.2-dev-20260620-2b9580a",
4
4
  "description": "Matterbridge core library",
5
5
  "author": "https://github.com/Luligu",
6
6
  "homepage": "https://matterbridge.io/",
@@ -130,16 +130,16 @@
130
130
  ],
131
131
  "dependencies": {
132
132
  "@matter/main": "0.17.3",
133
- "@matterbridge/dgram": "3.9.2-dev-20260620-9802e5b",
134
- "@matterbridge/thread": "3.9.2-dev-20260620-9802e5b",
135
- "@matterbridge/types": "3.9.2-dev-20260620-9802e5b",
136
- "@matterbridge/utils": "3.9.2-dev-20260620-9802e5b",
133
+ "@matterbridge/dgram": "3.9.2-dev-20260620-2b9580a",
134
+ "@matterbridge/thread": "3.9.2-dev-20260620-2b9580a",
135
+ "@matterbridge/types": "3.9.2-dev-20260620-2b9580a",
136
+ "@matterbridge/utils": "3.9.2-dev-20260620-2b9580a",
137
137
  "escape-html": "1.0.3",
138
138
  "express": "5.2.1",
139
139
  "express-rate-limit": "8.5.2",
140
140
  "multer": "2.2.0",
141
- "node-ansi-logger": "3.3.0-dev-20260617-6ebcff7",
142
- "node-persist-manager": "2.1.0-dev-20260617-3224082",
141
+ "node-ansi-logger": "3.3.0",
142
+ "node-persist-manager": "2.1.0",
143
143
  "ws": "8.21.0"
144
144
  }
145
145
  }