@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 +3 -3
- package/dist/backend.js +8 -5
- package/dist/backendExpress.js +6 -6
- package/dist/backendWsServer.d.ts +2 -1
- package/dist/backendWsServer.js +9 -2
- package/dist/frontend.d.ts +2 -1
- package/dist/frontend.js +13 -3
- package/dist/matterbridge.d.ts +2 -1
- package/dist/matterbridge.js +263 -201
- package/package.json +7 -7
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(
|
|
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
|
-
|
|
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
|
-
|
|
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(
|
|
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() { }
|
package/dist/backendExpress.js
CHANGED
|
@@ -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;
|
package/dist/backendWsServer.js
CHANGED
|
@@ -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())
|
package/dist/frontend.d.ts
CHANGED
|
@@ -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)
|
package/dist/matterbridge.d.ts
CHANGED
|
@@ -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;
|
package/dist/matterbridge.js
CHANGED
|
@@ -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
|
|
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 (
|
|
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(
|
|
687
|
-
|
|
688
|
-
|
|
689
|
-
|
|
690
|
-
|
|
691
|
-
|
|
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
|
|
709
|
-
this.log.info(
|
|
710
|
-
this.log.info(
|
|
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(
|
|
714
|
-
this.log.info(
|
|
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
|
-
|
|
745
|
-
|
|
746
|
-
|
|
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
|
-
|
|
751
|
-
|
|
752
|
-
|
|
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
|
-
|
|
757
|
-
|
|
758
|
-
|
|
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
|
-
|
|
763
|
-
|
|
764
|
-
|
|
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
|
|
787
|
-
throw new Error(`Fatal error creating matter storage: ${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
|
-
|
|
796
|
-
|
|
797
|
-
|
|
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 (
|
|
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')
|
|
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')
|
|
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 =
|
|
903
|
-
const errorMessage = 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 =
|
|
909
|
-
const errorMessage = 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: ${
|
|
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 =
|
|
916
|
-
|
|
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 =
|
|
920
|
-
|
|
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(
|
|
1405
|
-
|
|
1406
|
-
|
|
1407
|
-
|
|
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
|
-
|
|
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
|
-
|
|
1450
|
-
|
|
1451
|
-
|
|
1452
|
-
|
|
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
|
-
|
|
1456
|
-
|
|
1457
|
-
|
|
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
|
-
|
|
1462
|
-
|
|
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(
|
|
1490
|
-
|
|
1491
|
-
|
|
1492
|
-
|
|
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
|
-
|
|
1512
|
-
|
|
1513
|
-
|
|
1514
|
-
|
|
1515
|
-
|
|
1516
|
-
|
|
1517
|
-
this.
|
|
1518
|
-
plugin
|
|
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
|
-
|
|
1523
|
-
|
|
1524
|
-
|
|
1525
|
-
|
|
1526
|
-
|
|
1527
|
-
|
|
1528
|
-
|
|
1529
|
-
|
|
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 ||
|
|
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
|
-
|
|
1540
|
-
|
|
1541
|
-
|
|
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.
|
|
1545
|
-
|
|
1546
|
-
|
|
1547
|
-
|
|
1548
|
-
|
|
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
|
-
|
|
1579
|
-
|
|
1580
|
-
|
|
1581
|
-
|
|
1582
|
-
|
|
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(
|
|
1797
|
+
serverNode.lifecycle.online.on(() => {
|
|
1736
1798
|
this.log.notice(`Server node for ${storeId} is online`);
|
|
1737
|
-
if (
|
|
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)
|
|
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-
|
|
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-
|
|
134
|
-
"@matterbridge/thread": "3.9.2-dev-20260620-
|
|
135
|
-
"@matterbridge/types": "3.9.2-dev-20260620-
|
|
136
|
-
"@matterbridge/utils": "3.9.2-dev-20260620-
|
|
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
|
|
142
|
-
"node-persist-manager": "2.1.0
|
|
141
|
+
"node-ansi-logger": "3.3.0",
|
|
142
|
+
"node-persist-manager": "2.1.0",
|
|
143
143
|
"ws": "8.21.0"
|
|
144
144
|
}
|
|
145
145
|
}
|