matterbridge 3.2.9-dev-20250924-2e9594f → 3.2.9-dev-20250926-85736bb
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/CHANGELOG.md +1 -0
- package/dist/frontend.js +10 -3
- package/dist/matterbridge.js +17 -10
- package/dist/utils/spawn.js +4 -1
- package/frontend/build/assets/index.js +5 -1
- package/frontend/build/assets/vendor_mui.js +1 -1
- package/npm-shrinkwrap.json +2 -2
- package/package.json +1 -1
package/CHANGELOG.md
CHANGED
|
@@ -22,6 +22,7 @@ If you like this project and find it useful, please consider giving it a star on
|
|
|
22
22
|
- [frontend]: Optimized WebSocker message handlers. Now, the handler targets the component.
|
|
23
23
|
- [frontend]: Removed dangerouslySetInnerHTML from log rendering.
|
|
24
24
|
- [frontend]: Added push update to Icon view and table view cluster panel.
|
|
25
|
+
- [frontend]: Added install progress dialog when installing or uploading packages.
|
|
25
26
|
- [endpoint]: Added occupancy feature to all Thermostat cluster helpers. When provided (either false or true) it will create a Thermostat with occupancy feature.
|
|
26
27
|
- [endpoint]: Added outdoorTemperature to all Thermostat cluster helpers. Default is undefined (it will be ignored).
|
|
27
28
|
|
package/dist/frontend.js
CHANGED
|
@@ -21,6 +21,7 @@ export class Frontend extends EventEmitter {
|
|
|
21
21
|
matterbridge;
|
|
22
22
|
log;
|
|
23
23
|
port = 8283;
|
|
24
|
+
listening = false;
|
|
24
25
|
expressApp;
|
|
25
26
|
httpServer;
|
|
26
27
|
httpsServer;
|
|
@@ -63,6 +64,7 @@ export class Frontend extends EventEmitter {
|
|
|
63
64
|
if (hasParameter('ingress')) {
|
|
64
65
|
this.httpServer.listen(this.port, '0.0.0.0', () => {
|
|
65
66
|
this.log.info(`The frontend http server is listening on ${UNDERLINE}http://0.0.0.0:${this.port}${UNDERLINEOFF}${rs}`);
|
|
67
|
+
this.listening = true;
|
|
66
68
|
this.emit('server_listening', 'http', this.port, '0.0.0.0');
|
|
67
69
|
});
|
|
68
70
|
}
|
|
@@ -72,6 +74,7 @@ export class Frontend extends EventEmitter {
|
|
|
72
74
|
this.log.info(`The frontend http server is listening on ${UNDERLINE}http://${this.matterbridge.systemInformation.ipv4Address}:${this.port}${UNDERLINEOFF}${rs}`);
|
|
73
75
|
if (this.matterbridge.systemInformation.ipv6Address !== '')
|
|
74
76
|
this.log.info(`The frontend http server is listening on ${UNDERLINE}http://[${this.matterbridge.systemInformation.ipv6Address}]:${this.port}${UNDERLINEOFF}${rs}`);
|
|
77
|
+
this.listening = true;
|
|
75
78
|
this.emit('server_listening', 'http', this.port);
|
|
76
79
|
});
|
|
77
80
|
}
|
|
@@ -164,6 +167,7 @@ export class Frontend extends EventEmitter {
|
|
|
164
167
|
if (hasParameter('ingress')) {
|
|
165
168
|
this.httpsServer.listen(this.port, '0.0.0.0', () => {
|
|
166
169
|
this.log.info(`The frontend https server is listening on ${UNDERLINE}https://0.0.0.0:${this.port}${UNDERLINEOFF}${rs}`);
|
|
170
|
+
this.listening = true;
|
|
167
171
|
this.emit('server_listening', 'https', this.port, '0.0.0.0');
|
|
168
172
|
});
|
|
169
173
|
}
|
|
@@ -173,6 +177,7 @@ export class Frontend extends EventEmitter {
|
|
|
173
177
|
this.log.info(`The frontend https server is listening on ${UNDERLINE}https://${this.matterbridge.systemInformation.ipv4Address}:${this.port}${UNDERLINEOFF}${rs}`);
|
|
174
178
|
if (this.matterbridge.systemInformation.ipv6Address !== '')
|
|
175
179
|
this.log.info(`The frontend https server is listening on ${UNDERLINE}https://[${this.matterbridge.systemInformation.ipv6Address}]:${this.port}${UNDERLINEOFF}${rs}`);
|
|
180
|
+
this.listening = true;
|
|
176
181
|
this.emit('server_listening', 'https', this.port);
|
|
177
182
|
});
|
|
178
183
|
}
|
|
@@ -525,7 +530,7 @@ export class Frontend extends EventEmitter {
|
|
|
525
530
|
this.log.info(`File ${plg}${filename}${nf} uploaded successfully`);
|
|
526
531
|
if (filename.endsWith('.tgz')) {
|
|
527
532
|
const { spawnCommand } = await import('./utils/spawn.js');
|
|
528
|
-
await spawnCommand(this.matterbridge, 'npm', ['install', '-g', filePath, '--omit=dev', '--verbose']);
|
|
533
|
+
await spawnCommand(this.matterbridge, 'npm', ['install', '-g', filePath, '--omit=dev', '--verbose'], filename);
|
|
529
534
|
this.log.info(`Plugin package ${plg}${filename}${nf} installed successfully. Full restart required.`);
|
|
530
535
|
this.wssSendCloseSnackbarMessage(`Installing package ${filename}. Please wait...`);
|
|
531
536
|
this.wssSendSnackbarMessage(`Installed package ${filename}`, 10, 'success');
|
|
@@ -581,6 +586,7 @@ export class Frontend extends EventEmitter {
|
|
|
581
586
|
this.log.debug('Closing http server...');
|
|
582
587
|
this.httpServer.close();
|
|
583
588
|
this.log.debug('Http server closed successfully');
|
|
589
|
+
this.listening = false;
|
|
584
590
|
this.emit('server_stopped');
|
|
585
591
|
this.httpServer.removeAllListeners();
|
|
586
592
|
this.httpServer = undefined;
|
|
@@ -590,6 +596,7 @@ export class Frontend extends EventEmitter {
|
|
|
590
596
|
this.log.debug('Closing https server...');
|
|
591
597
|
this.httpsServer.close();
|
|
592
598
|
this.log.debug('Https server closed successfully');
|
|
599
|
+
this.listening = false;
|
|
593
600
|
this.emit('server_stopped');
|
|
594
601
|
this.httpsServer.removeAllListeners();
|
|
595
602
|
this.httpsServer = undefined;
|
|
@@ -969,7 +976,7 @@ export class Frontend extends EventEmitter {
|
|
|
969
976
|
}
|
|
970
977
|
this.wssSendSnackbarMessage(`Installing package ${data.params.packageName}...`, 0);
|
|
971
978
|
const { spawnCommand } = await import('./utils/spawn.js');
|
|
972
|
-
spawnCommand(this.matterbridge, 'npm', ['install', '-g', data.params.packageName, '--omit=dev', '--verbose'])
|
|
979
|
+
spawnCommand(this.matterbridge, 'npm', ['install', '-g', data.params.packageName, '--omit=dev', '--verbose'], data.params.packageName)
|
|
973
980
|
.then((_response) => {
|
|
974
981
|
sendResponse({ id: localData.id, method: localData.method, src: 'Matterbridge', dst: data.src, success: true });
|
|
975
982
|
this.wssSendCloseSnackbarMessage(`Installing package ${localData.params.packageName}...`);
|
|
@@ -1037,7 +1044,7 @@ export class Frontend extends EventEmitter {
|
|
|
1037
1044
|
}
|
|
1038
1045
|
this.wssSendSnackbarMessage(`Uninstalling package ${data.params.packageName}...`, 0);
|
|
1039
1046
|
const { spawnCommand } = await import('./utils/spawn.js');
|
|
1040
|
-
spawnCommand(this.matterbridge, 'npm', ['uninstall', '-g', data.params.packageName, '--verbose'])
|
|
1047
|
+
spawnCommand(this.matterbridge, 'npm', ['uninstall', '-g', data.params.packageName, '--verbose'], data.params.packageName)
|
|
1041
1048
|
.then((_response) => {
|
|
1042
1049
|
sendResponse({ id: localData.id, method: localData.method, src: 'Matterbridge', dst: data.src, success: true });
|
|
1043
1050
|
this.wssSendCloseSnackbarMessage(`Uninstalling package ${localData.params.packageName}...`);
|
package/dist/matterbridge.js
CHANGED
|
@@ -507,7 +507,7 @@ export class Matterbridge extends EventEmitter {
|
|
|
507
507
|
this.log.info(`Error parsing plugin ${plg}${plugin.name}${nf}. Trying to reinstall it from npm.`);
|
|
508
508
|
try {
|
|
509
509
|
const { spawnCommand } = await import('./utils/spawn.js');
|
|
510
|
-
await spawnCommand(this, 'npm', ['install', '-g', plugin.name, '--omit=dev', '--verbose']);
|
|
510
|
+
await spawnCommand(this, 'npm', ['install', '-g', plugin.name, '--omit=dev', '--verbose'], plugin.name);
|
|
511
511
|
this.log.info(`Plugin ${plg}${plugin.name}${nf} reinstalled.`);
|
|
512
512
|
plugin.error = false;
|
|
513
513
|
}
|
|
@@ -654,6 +654,8 @@ export class Matterbridge extends EventEmitter {
|
|
|
654
654
|
this.shutdown = true;
|
|
655
655
|
return;
|
|
656
656
|
}
|
|
657
|
+
if (getIntParameter('frontend') !== 0 || getIntParameter('frontend') === undefined)
|
|
658
|
+
await this.frontend.start(getIntParameter('frontend'));
|
|
657
659
|
try {
|
|
658
660
|
await this.startMatterStorage();
|
|
659
661
|
if (this.aggregatorSerialNumber && this.aggregatorUniqueId && this.matterStorageService) {
|
|
@@ -699,8 +701,6 @@ export class Matterbridge extends EventEmitter {
|
|
|
699
701
|
this.shutdown = true;
|
|
700
702
|
return;
|
|
701
703
|
}
|
|
702
|
-
if (getIntParameter('frontend') !== 0 || getIntParameter('frontend') === undefined)
|
|
703
|
-
await this.frontend.start(getIntParameter('frontend'));
|
|
704
704
|
clearTimeout(this.checkUpdateTimeout);
|
|
705
705
|
this.checkUpdateTimeout = setTimeout(async () => {
|
|
706
706
|
const { checkUpdates } = await import('./update.js');
|
|
@@ -737,7 +737,7 @@ export class Matterbridge extends EventEmitter {
|
|
|
737
737
|
return;
|
|
738
738
|
}
|
|
739
739
|
}
|
|
740
|
-
async startPlugins() {
|
|
740
|
+
async startPlugins(wait = false, start = true) {
|
|
741
741
|
for (const plugin of this.plugins) {
|
|
742
742
|
plugin.configJson = await this.plugins.loadConfig(plugin);
|
|
743
743
|
plugin.schemaJson = await this.plugins.loadSchema(plugin);
|
|
@@ -757,7 +757,10 @@ export class Matterbridge extends EventEmitter {
|
|
|
757
757
|
plugin.started = false;
|
|
758
758
|
plugin.configured = false;
|
|
759
759
|
plugin.registeredDevices = undefined;
|
|
760
|
-
|
|
760
|
+
if (wait)
|
|
761
|
+
await this.plugins.load(plugin, start, 'Matterbridge is starting');
|
|
762
|
+
else
|
|
763
|
+
this.plugins.load(plugin, start, 'Matterbridge is starting');
|
|
761
764
|
}
|
|
762
765
|
this.frontend.wssSendRefreshRequired('plugins');
|
|
763
766
|
}
|
|
@@ -949,7 +952,7 @@ export class Matterbridge extends EventEmitter {
|
|
|
949
952
|
this.log.info('Updating matterbridge...');
|
|
950
953
|
try {
|
|
951
954
|
const { spawnCommand } = await import('./utils/spawn.js');
|
|
952
|
-
await spawnCommand(this, 'npm', ['install', '-g', 'matterbridge', '--omit=dev', '--verbose']);
|
|
955
|
+
await spawnCommand(this, 'npm', ['install', '-g', 'matterbridge', '--omit=dev', '--verbose'], 'matterbridge');
|
|
953
956
|
this.log.info('Matterbridge has been updated. Full restart required.');
|
|
954
957
|
}
|
|
955
958
|
catch (error) {
|
|
@@ -1252,7 +1255,14 @@ export class Matterbridge extends EventEmitter {
|
|
|
1252
1255
|
async startChildbridge(delay = 1000) {
|
|
1253
1256
|
if (!this.matterStorageManager)
|
|
1254
1257
|
throw new Error('No storage manager initialized');
|
|
1255
|
-
|
|
1258
|
+
this.log.debug('Loading all plugins in childbridge mode...');
|
|
1259
|
+
await this.startPlugins(true, false);
|
|
1260
|
+
this.log.debug('Creating server nodes for DynamicPlatform plugins and starting all plugins in childbridge mode...');
|
|
1261
|
+
for (const plugin of this.plugins.array().filter((p) => p.enabled && !p.error)) {
|
|
1262
|
+
if (plugin.type === 'DynamicPlatform')
|
|
1263
|
+
await this.createDynamicPlugin(plugin);
|
|
1264
|
+
this.plugins.start(plugin, 'Matterbridge is starting');
|
|
1265
|
+
}
|
|
1256
1266
|
this.log.debug('Starting start matter interval in childbridge mode...');
|
|
1257
1267
|
let failCount = 0;
|
|
1258
1268
|
this.startMatterInterval = setInterval(async () => {
|
|
@@ -1280,9 +1290,6 @@ export class Matterbridge extends EventEmitter {
|
|
|
1280
1290
|
plugin.error = true;
|
|
1281
1291
|
}
|
|
1282
1292
|
}
|
|
1283
|
-
if (plugin.type === 'DynamicPlatform' && !plugin.locked) {
|
|
1284
|
-
await this.createDynamicPlugin(plugin);
|
|
1285
|
-
}
|
|
1286
1293
|
}
|
|
1287
1294
|
if (!allStarted)
|
|
1288
1295
|
return;
|
package/dist/utils/spawn.js
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { hasParameter } from './commandLine.js';
|
|
2
|
-
export async function spawnCommand(matterbridge, command, args) {
|
|
2
|
+
export async function spawnCommand(matterbridge, command, args, packageName) {
|
|
3
3
|
const { spawn } = await import('node:child_process');
|
|
4
4
|
const cmdLine = command + ' ' + args.join(' ');
|
|
5
5
|
if (process.platform === 'win32' && command === 'npm') {
|
|
@@ -13,6 +13,7 @@ export async function spawnCommand(matterbridge, command, args) {
|
|
|
13
13
|
}
|
|
14
14
|
matterbridge.log.debug(`Spawn command ${command} with ${args.join(' ')}`);
|
|
15
15
|
return new Promise((resolve, reject) => {
|
|
16
|
+
matterbridge.frontend.wssSendLogMessage('spawn', matterbridge.log.now(), 'Matterbridge:spawn-init', packageName || `unknown-package`);
|
|
16
17
|
const childProcess = spawn(command, args, {
|
|
17
18
|
stdio: ['inherit', 'pipe', 'pipe'],
|
|
18
19
|
});
|
|
@@ -22,6 +23,7 @@ export async function spawnCommand(matterbridge, command, args) {
|
|
|
22
23
|
});
|
|
23
24
|
childProcess.on('close', (code, signal) => {
|
|
24
25
|
matterbridge.frontend.wssSendLogMessage('spawn', matterbridge.log.now(), 'Matterbridge:spawn', `child process closed with code ${code} and signal ${signal}`);
|
|
26
|
+
matterbridge.frontend.wssSendLogMessage('spawn', matterbridge.log.now(), 'Matterbridge:spawn-exit', 'Child process closed');
|
|
25
27
|
if (code === 0) {
|
|
26
28
|
if (cmdLine.startsWith('npm install -g'))
|
|
27
29
|
matterbridge.log.notice(`Package ${cmdLine.replace('npm install -g ', '').replace('--verbose', '').replace('--omit=dev', '')} installed correctly`);
|
|
@@ -35,6 +37,7 @@ export async function spawnCommand(matterbridge, command, args) {
|
|
|
35
37
|
});
|
|
36
38
|
childProcess.on('exit', (code, signal) => {
|
|
37
39
|
matterbridge.frontend.wssSendLogMessage('spawn', matterbridge.log.now(), 'Matterbridge:spawn', `child process exited with code ${code} and signal ${signal}`);
|
|
40
|
+
matterbridge.frontend.wssSendLogMessage('spawn', matterbridge.log.now(), 'Matterbridge:spawn-exit', 'Child process exited');
|
|
38
41
|
if (code === 0) {
|
|
39
42
|
matterbridge.log.debug(`Child process "${cmdLine}" exited with code ${code} and signal ${signal}`);
|
|
40
43
|
resolve(true);
|