matterbridge 3.2.8-dev-20250916-da71182 → 3.2.8-dev-20250918-52dc90c
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 +12 -2
- package/dist/frontend.js +130 -199
- package/dist/frontendTypes.js +25 -0
- package/dist/matterbridge.js +3 -7
- package/dist/shelly.js +4 -5
- package/dist/utils/spawn.js +4 -4
- package/frontend/build/assets/index.css +1 -0
- package/frontend/build/assets/index.js +23 -0
- package/frontend/build/assets/vendor_emotion.js +1 -0
- package/frontend/build/assets/vendor_lodash.js +1 -0
- package/frontend/build/assets/vendor_mdi.js +1 -0
- package/frontend/build/assets/vendor_mui.js +137 -0
- package/frontend/build/assets/vendor_node_modules.js +100 -0
- package/frontend/build/assets/vendor_notistack.js +5 -0
- package/frontend/build/assets/vendor_qrcode.js +9 -0
- package/frontend/build/assets/vendor_react_table.js +1 -0
- package/frontend/build/assets/vendor_rjsf.js +10 -0
- package/frontend/build/index.html +27 -1
- package/frontend/index.html +17 -0
- package/frontend/package-lock.json +5697 -17190
- package/frontend/package.json +60 -53
- package/npm-shrinkwrap.json +5 -5
- package/package.json +1 -1
- package/frontend/build/asset-manifest.json +0 -85
- package/frontend/build/favicon.ico +0 -0
- package/frontend/build/manifest.json +0 -15
- package/frontend/build/robots.txt +0 -3
- package/frontend/build/static/css/main.56c16a87.css +0 -2
- package/frontend/build/static/css/main.56c16a87.css.map +0 -1
- package/frontend/build/static/js/main.565f820c.js +0 -3
- package/frontend/build/static/js/main.565f820c.js.LICENSE.txt +0 -97
- package/frontend/build/static/js/main.565f820c.js.map +0 -1
- package/frontend/build/static/media/roboto-cyrillic-300-normal.44340549d94d10899346.woff +0 -0
- package/frontend/build/static/media/roboto-cyrillic-300-normal.89d0351bce4bc857dba6.woff2 +0 -0
- package/frontend/build/static/media/roboto-cyrillic-400-normal.86d5c52f4588f9f221d7.woff2 +0 -0
- package/frontend/build/static/media/roboto-cyrillic-400-normal.d67ac585bb6a05dbf71c.woff +0 -0
- package/frontend/build/static/media/roboto-cyrillic-500-normal.1fb2c6d685bfb888cfa3.woff2 +0 -0
- package/frontend/build/static/media/roboto-cyrillic-500-normal.36f79cc7e73a69da4438.woff +0 -0
- package/frontend/build/static/media/roboto-cyrillic-700-normal.e00802373a2c2db6b30d.woff +0 -0
- package/frontend/build/static/media/roboto-cyrillic-700-normal.fd3dfdd6cb1a9175b63d.woff2 +0 -0
- package/frontend/build/static/media/roboto-cyrillic-ext-300-normal.a80c0d0719b1acb8f731.woff +0 -0
- package/frontend/build/static/media/roboto-cyrillic-ext-300-normal.b9d87b04a9119d8d2fdf.woff2 +0 -0
- package/frontend/build/static/media/roboto-cyrillic-ext-400-normal.31476620b88eec076438.woff2 +0 -0
- package/frontend/build/static/media/roboto-cyrillic-ext-400-normal.5e3f232f89080810567d.woff +0 -0
- package/frontend/build/static/media/roboto-cyrillic-ext-500-normal.634ee2238bf30f362d52.woff2 +0 -0
- package/frontend/build/static/media/roboto-cyrillic-ext-500-normal.d6c661248da2fde17768.woff +0 -0
- package/frontend/build/static/media/roboto-cyrillic-ext-700-normal.361cdfd3a3f9c4bb09ca.woff2 +0 -0
- package/frontend/build/static/media/roboto-cyrillic-ext-700-normal.6b08bc756cd72f5af9e8.woff +0 -0
- package/frontend/build/static/media/roboto-greek-300-normal.8300b541aa89b8301a6f.woff +0 -0
- package/frontend/build/static/media/roboto-greek-300-normal.fdd1f928a606aa116a44.woff2 +0 -0
- package/frontend/build/static/media/roboto-greek-400-normal.98a717d5a38e77c0f657.woff2 +0 -0
- package/frontend/build/static/media/roboto-greek-400-normal.ecd8572d631f20ff5bd5.woff +0 -0
- package/frontend/build/static/media/roboto-greek-500-normal.4fe733bc436afc295c24.woff +0 -0
- package/frontend/build/static/media/roboto-greek-500-normal.5c8100481d4e784afbf2.woff2 +0 -0
- package/frontend/build/static/media/roboto-greek-700-normal.d23e03cf87ba44e5af6f.woff +0 -0
- package/frontend/build/static/media/roboto-greek-700-normal.d7dfd0b02cd8311e2a97.woff2 +0 -0
- package/frontend/build/static/media/roboto-greek-ext-300-normal.60729cafbded24073dfb.woff +0 -0
- package/frontend/build/static/media/roboto-greek-ext-300-normal.a88b77bb10633a8045e3.woff2 +0 -0
- package/frontend/build/static/media/roboto-greek-ext-400-normal.2d5875b032a1cca91eb2.woff2 +0 -0
- package/frontend/build/static/media/roboto-greek-ext-400-normal.a0baf7d6726d8f751a27.woff +0 -0
- package/frontend/build/static/media/roboto-greek-ext-500-normal.1964239c2800b6bd7e39.woff +0 -0
- package/frontend/build/static/media/roboto-greek-ext-500-normal.bef9c15c7164d6435aad.woff2 +0 -0
- package/frontend/build/static/media/roboto-greek-ext-700-normal.1aff9f4cd71608489b9a.woff +0 -0
- package/frontend/build/static/media/roboto-greek-ext-700-normal.eb28a447335ba6d54fcb.woff2 +0 -0
- package/frontend/build/static/media/roboto-latin-300-normal.cb14f8e80cc69ddbac34.woff +0 -0
- package/frontend/build/static/media/roboto-latin-300-normal.db56943a88e4852343ae.woff2 +0 -0
- package/frontend/build/static/media/roboto-latin-400-normal.50a0a61e29c19a2f05cb.woff +0 -0
- package/frontend/build/static/media/roboto-latin-400-normal.df1be0be92f6f19b8115.woff2 +0 -0
- package/frontend/build/static/media/roboto-latin-500-normal.599f66a60bdf974e578e.woff2 +0 -0
- package/frontend/build/static/media/roboto-latin-500-normal.c320def131b39bceabd8.woff +0 -0
- package/frontend/build/static/media/roboto-latin-700-normal.bcfbe8accc968a375a8e.woff +0 -0
- package/frontend/build/static/media/roboto-latin-700-normal.c4d6cab43bec89049809.woff2 +0 -0
- package/frontend/build/static/media/roboto-latin-ext-300-normal.6ddd1cfdbc5e74bcdab8.woff +0 -0
- package/frontend/build/static/media/roboto-latin-ext-300-normal.948c05192b1e64d931b1.woff2 +0 -0
- package/frontend/build/static/media/roboto-latin-ext-400-normal.0f86a30ca7e981fcfc99.woff2 +0 -0
- package/frontend/build/static/media/roboto-latin-ext-400-normal.2bfbba2d51a85c8702dd.woff +0 -0
- package/frontend/build/static/media/roboto-latin-ext-500-normal.8f02573e78730021ef49.woff2 +0 -0
- package/frontend/build/static/media/roboto-latin-ext-500-normal.aecaab4c4da2bf91377a.woff +0 -0
- package/frontend/build/static/media/roboto-latin-ext-700-normal.2d3c3ba6fe2d9c1026a5.woff +0 -0
- package/frontend/build/static/media/roboto-latin-ext-700-normal.8e656eff240311c6050a.woff2 +0 -0
- package/frontend/build/static/media/roboto-math-300-normal.90364ecfad5101ceb1a0.woff +0 -0
- package/frontend/build/static/media/roboto-math-300-normal.acc9c7c1d1fe3a1c7d44.woff2 +0 -0
- package/frontend/build/static/media/roboto-math-400-normal.3d3a272e5233c5fb1969.woff +0 -0
- package/frontend/build/static/media/roboto-math-400-normal.b60d9fba1e21da7497e6.woff2 +0 -0
- package/frontend/build/static/media/roboto-math-500-normal.41db483cb764343fca71.woff2 +0 -0
- package/frontend/build/static/media/roboto-math-500-normal.c3014a611cd9d8fa6252.woff +0 -0
- package/frontend/build/static/media/roboto-math-700-normal.a6fde3ddcb1629fd58b7.woff +0 -0
- package/frontend/build/static/media/roboto-math-700-normal.f6f4b54add6ab9d60a0f.woff2 +0 -0
- package/frontend/build/static/media/roboto-symbols-300-normal.52cdf8344b378f0c4580.woff +0 -0
- package/frontend/build/static/media/roboto-symbols-300-normal.616638ec44336b3da884.woff2 +0 -0
- package/frontend/build/static/media/roboto-symbols-400-normal.bb5b5d1459beb07bd3d5.woff2 +0 -0
- package/frontend/build/static/media/roboto-symbols-400-normal.f4f7e3bd8264f1a640cb.woff +0 -0
- package/frontend/build/static/media/roboto-symbols-500-normal.09b674875029289fd9a7.woff +0 -0
- package/frontend/build/static/media/roboto-symbols-500-normal.a5457b0ec984fd4cc8da.woff2 +0 -0
- package/frontend/build/static/media/roboto-symbols-700-normal.017e476ef02f62144169.woff +0 -0
- package/frontend/build/static/media/roboto-symbols-700-normal.634070e045ac99822c21.woff2 +0 -0
- package/frontend/build/static/media/roboto-vietnamese-300-normal.53f399e4522b647bafa7.woff +0 -0
- package/frontend/build/static/media/roboto-vietnamese-300-normal.6f0bf63e956c09377ef8.woff2 +0 -0
- package/frontend/build/static/media/roboto-vietnamese-400-normal.1cffe58e71a9109191a2.woff +0 -0
- package/frontend/build/static/media/roboto-vietnamese-400-normal.b1b8baa94fbcaa57d098.woff2 +0 -0
- package/frontend/build/static/media/roboto-vietnamese-500-normal.148734d63bd96c6e964f.woff2 +0 -0
- package/frontend/build/static/media/roboto-vietnamese-500-normal.72dbf2a25dd55b80b137.woff +0 -0
- package/frontend/build/static/media/roboto-vietnamese-700-normal.44a103f706f3ffe6a041.woff2 +0 -0
- package/frontend/build/static/media/roboto-vietnamese-700-normal.fa58a041a3336692af1e.woff +0 -0
package/dist/frontend.js
CHANGED
|
@@ -16,18 +16,6 @@ import { createZip, isValidArray, isValidNumber, isValidObject, isValidString, i
|
|
|
16
16
|
import { plg } from './matterbridgeTypes.js';
|
|
17
17
|
import { capitalizeFirstLetter, getAttribute } from './matterbridgeEndpointHelpers.js';
|
|
18
18
|
import { cliEmitter, lastCpuUsage } from './cliEmitter.js';
|
|
19
|
-
export const WS_ID_LOG = 0;
|
|
20
|
-
export const WS_ID_REFRESH_NEEDED = 1;
|
|
21
|
-
export const WS_ID_RESTART_NEEDED = 2;
|
|
22
|
-
export const WS_ID_CPU_UPDATE = 3;
|
|
23
|
-
export const WS_ID_MEMORY_UPDATE = 4;
|
|
24
|
-
export const WS_ID_UPTIME_UPDATE = 5;
|
|
25
|
-
export const WS_ID_SNACKBAR = 6;
|
|
26
|
-
export const WS_ID_UPDATE_NEEDED = 7;
|
|
27
|
-
export const WS_ID_STATEUPDATE = 8;
|
|
28
|
-
export const WS_ID_CLOSE_SNACKBAR = 9;
|
|
29
|
-
export const WS_ID_SHELLY_SYS_UPDATE = 100;
|
|
30
|
-
export const WS_ID_SHELLY_MAIN_UPDATE = 101;
|
|
31
19
|
export class Frontend extends EventEmitter {
|
|
32
20
|
matterbridge;
|
|
33
21
|
log;
|
|
@@ -212,7 +200,7 @@ export class Frontend extends EventEmitter {
|
|
|
212
200
|
callbackLogLevel = "info";
|
|
213
201
|
if (this.matterbridge.matterbridgeInformation.loggerLevel === "debug" || this.matterbridge.matterbridgeInformation.matterLoggerLevel === MatterLogLevel.DEBUG)
|
|
214
202
|
callbackLogLevel = "debug";
|
|
215
|
-
AnsiLogger.setGlobalCallback(this.
|
|
203
|
+
AnsiLogger.setGlobalCallback(this.wssSendLogMessage.bind(this), callbackLogLevel);
|
|
216
204
|
this.log.debug(`WebSocketServer logger global callback set to ${callbackLogLevel}`);
|
|
217
205
|
this.log.info(`WebSocketServer client "${clientIp}" connected to Matterbridge`);
|
|
218
206
|
ws.on('message', (message) => {
|
|
@@ -590,36 +578,18 @@ export class Frontend extends EventEmitter {
|
|
|
590
578
|
}
|
|
591
579
|
if (this.httpServer) {
|
|
592
580
|
this.log.debug('Closing http server...');
|
|
593
|
-
|
|
594
|
-
|
|
595
|
-
|
|
596
|
-
this.log.error(`Error closing http server: ${error}`);
|
|
597
|
-
}
|
|
598
|
-
else {
|
|
599
|
-
this.log.debug('Http server closed successfully');
|
|
600
|
-
this.emit('server_stopped');
|
|
601
|
-
}
|
|
602
|
-
resolve();
|
|
603
|
-
});
|
|
604
|
-
}), 5000, false);
|
|
581
|
+
this.httpServer.close();
|
|
582
|
+
this.log.debug('Http server closed successfully');
|
|
583
|
+
this.emit('server_stopped');
|
|
605
584
|
this.httpServer.removeAllListeners();
|
|
606
585
|
this.httpServer = undefined;
|
|
607
586
|
this.log.debug('Frontend http server closed successfully');
|
|
608
587
|
}
|
|
609
588
|
if (this.httpsServer) {
|
|
610
589
|
this.log.debug('Closing https server...');
|
|
611
|
-
|
|
612
|
-
|
|
613
|
-
|
|
614
|
-
this.log.error(`Error closing https server: ${error}`);
|
|
615
|
-
}
|
|
616
|
-
else {
|
|
617
|
-
this.log.debug('Https server closed successfully');
|
|
618
|
-
this.emit('server_stopped');
|
|
619
|
-
}
|
|
620
|
-
resolve();
|
|
621
|
-
});
|
|
622
|
-
}), 5000, false);
|
|
590
|
+
this.httpsServer.close();
|
|
591
|
+
this.log.debug('Https server closed successfully');
|
|
592
|
+
this.emit('server_stopped');
|
|
623
593
|
this.httpsServer.removeAllListeners();
|
|
624
594
|
this.httpsServer = undefined;
|
|
625
595
|
this.log.debug('Frontend https server closed successfully');
|
|
@@ -956,46 +926,53 @@ export class Frontend extends EventEmitter {
|
|
|
956
926
|
}
|
|
957
927
|
async wsMessageHandler(client, message) {
|
|
958
928
|
let data;
|
|
929
|
+
const sendResponse = (data) => {
|
|
930
|
+
if (client.readyState === WebSocket.OPEN) {
|
|
931
|
+
const { response, ...rest } = data;
|
|
932
|
+
this.log.debug(`Sending api response broadcast message: ${debugStringify(rest)}`);
|
|
933
|
+
client.send(JSON.stringify(data));
|
|
934
|
+
}
|
|
935
|
+
};
|
|
959
936
|
try {
|
|
960
937
|
data = JSON.parse(message.toString());
|
|
961
|
-
if (!isValidNumber(data.id) || !isValidString(data.dst) || !isValidString(data.src) || !isValidString(data.method) ||
|
|
938
|
+
if (!isValidNumber(data.id) || !isValidString(data.dst) || !isValidString(data.src) || !isValidString(data.method) || data.dst !== 'Matterbridge') {
|
|
962
939
|
this.log.error(`Invalid message from websocket client: ${debugStringify(data)}`);
|
|
963
|
-
|
|
940
|
+
sendResponse({ id: data.id, method: data.method, src: 'Matterbridge', dst: data.src, error: 'Invalid message' });
|
|
964
941
|
return;
|
|
965
942
|
}
|
|
966
943
|
this.log.debug(`Received message from websocket client: ${debugStringify(data)}`);
|
|
967
944
|
if (data.method === 'ping') {
|
|
968
|
-
|
|
945
|
+
sendResponse({ id: data.id, method: data.method, src: 'Matterbridge', dst: data.src, success: true, response: 'pong' });
|
|
969
946
|
return;
|
|
970
947
|
}
|
|
971
948
|
else if (data.method === '/api/login') {
|
|
972
949
|
if (!this.matterbridge.nodeContext) {
|
|
973
950
|
this.log.error('Login nodeContext not found');
|
|
974
|
-
|
|
951
|
+
sendResponse({ id: data.id, method: data.method, src: 'Matterbridge', dst: data.src, error: 'Internal error: nodeContext not found' });
|
|
975
952
|
return;
|
|
976
953
|
}
|
|
977
954
|
const storedPassword = await this.matterbridge.nodeContext.get('password', '');
|
|
978
955
|
if (storedPassword === '' || storedPassword === data.params.password) {
|
|
979
956
|
this.log.debug('Login password valid');
|
|
980
|
-
|
|
957
|
+
sendResponse({ id: data.id, method: data.method, src: 'Matterbridge', dst: data.src, success: true });
|
|
981
958
|
return;
|
|
982
959
|
}
|
|
983
960
|
else {
|
|
984
961
|
this.log.debug('Error wrong password');
|
|
985
|
-
|
|
962
|
+
sendResponse({ id: data.id, method: data.method, src: 'Matterbridge', dst: data.src, error: 'Wrong password' });
|
|
986
963
|
return;
|
|
987
964
|
}
|
|
988
965
|
}
|
|
989
966
|
else if (data.method === '/api/install') {
|
|
990
967
|
if (!isValidString(data.params.packageName, 10) || !isValidBoolean(data.params.restart)) {
|
|
991
|
-
|
|
968
|
+
sendResponse({ id: data.id, method: data.method, src: 'Matterbridge', dst: data.src, error: 'Wrong parameter in /api/install' });
|
|
992
969
|
return;
|
|
993
970
|
}
|
|
994
971
|
this.wssSendSnackbarMessage(`Installing package ${data.params.packageName}...`, 0);
|
|
995
972
|
const { spawnCommand } = await import('./utils/spawn.js');
|
|
996
973
|
spawnCommand(this.matterbridge, 'npm', ['install', '-g', data.params.packageName, '--omit=dev', '--verbose'])
|
|
997
|
-
.then((
|
|
998
|
-
|
|
974
|
+
.then((_response) => {
|
|
975
|
+
sendResponse({ id: data.id, method: data.method, src: 'Matterbridge', dst: data.src, success: true });
|
|
999
976
|
this.wssSendCloseSnackbarMessage(`Installing package ${data.params.packageName}...`);
|
|
1000
977
|
this.wssSendSnackbarMessage(`Installed package ${data.params.packageName}`, 5, 'success');
|
|
1001
978
|
const packageName = data.params.packageName.replace(/@.*$/, '');
|
|
@@ -1040,14 +1017,14 @@ export class Frontend extends EventEmitter {
|
|
|
1040
1017
|
return;
|
|
1041
1018
|
})
|
|
1042
1019
|
.catch((error) => {
|
|
1043
|
-
|
|
1020
|
+
sendResponse({ id: data.id, method: data.method, src: 'Matterbridge', dst: data.src, error: error instanceof Error ? error.message : error });
|
|
1044
1021
|
this.wssSendCloseSnackbarMessage(`Installing package ${data.params.packageName}...`);
|
|
1045
1022
|
this.wssSendSnackbarMessage(`Package ${data.params.packageName} not installed`, 10, 'error');
|
|
1046
1023
|
});
|
|
1047
1024
|
}
|
|
1048
1025
|
else if (data.method === '/api/uninstall') {
|
|
1049
1026
|
if (!isValidString(data.params.packageName, 10)) {
|
|
1050
|
-
|
|
1027
|
+
sendResponse({ id: data.id, method: data.method, src: 'Matterbridge', dst: data.src, error: 'Wrong parameter packageName in /api/uninstall' });
|
|
1051
1028
|
return;
|
|
1052
1029
|
}
|
|
1053
1030
|
const plugin = this.matterbridge.plugins.get(data.params.packageName);
|
|
@@ -1061,14 +1038,14 @@ export class Frontend extends EventEmitter {
|
|
|
1061
1038
|
this.wssSendSnackbarMessage(`Uninstalling package ${data.params.packageName}...`, 0);
|
|
1062
1039
|
const { spawnCommand } = await import('./utils/spawn.js');
|
|
1063
1040
|
spawnCommand(this.matterbridge, 'npm', ['uninstall', '-g', data.params.packageName, '--verbose'])
|
|
1064
|
-
.then((
|
|
1065
|
-
|
|
1041
|
+
.then((_response) => {
|
|
1042
|
+
sendResponse({ id: data.id, method: data.method, src: 'Matterbridge', dst: data.src, success: true });
|
|
1066
1043
|
this.wssSendCloseSnackbarMessage(`Uninstalling package ${data.params.packageName}...`);
|
|
1067
1044
|
this.wssSendSnackbarMessage(`Uninstalled package ${data.params.packageName}`, 5, 'success');
|
|
1068
1045
|
return;
|
|
1069
1046
|
})
|
|
1070
1047
|
.catch((error) => {
|
|
1071
|
-
|
|
1048
|
+
sendResponse({ id: data.id, method: data.method, src: 'Matterbridge', dst: data.src, error: error instanceof Error ? error.message : error });
|
|
1072
1049
|
this.wssSendCloseSnackbarMessage(`Uninstalling package ${data.params.packageName}...`);
|
|
1073
1050
|
this.wssSendSnackbarMessage(`Package ${data.params.packageName} not uninstalled`, 10, 'error');
|
|
1074
1051
|
this.wssSendSnackbarMessage(`Restart required`, 0);
|
|
@@ -1076,18 +1053,18 @@ export class Frontend extends EventEmitter {
|
|
|
1076
1053
|
}
|
|
1077
1054
|
else if (data.method === '/api/addplugin') {
|
|
1078
1055
|
if (!isValidString(data.params.pluginNameOrPath, 10)) {
|
|
1079
|
-
|
|
1056
|
+
sendResponse({ id: data.id, method: data.method, src: 'Matterbridge', dst: data.src, error: 'Wrong parameter pluginNameOrPath in /api/addplugin' });
|
|
1080
1057
|
return;
|
|
1081
1058
|
}
|
|
1082
1059
|
data.params.pluginNameOrPath = data.params.pluginNameOrPath.replace(/@.*$/, '');
|
|
1083
1060
|
if (this.matterbridge.plugins.has(data.params.pluginNameOrPath)) {
|
|
1084
|
-
|
|
1061
|
+
sendResponse({ id: data.id, method: data.method, src: 'Matterbridge', dst: data.src, error: `Plugin ${data.params.pluginNameOrPath} already added` });
|
|
1085
1062
|
this.wssSendSnackbarMessage(`Plugin ${data.params.pluginNameOrPath} already added`, 10, 'warning');
|
|
1086
1063
|
return;
|
|
1087
1064
|
}
|
|
1088
1065
|
const plugin = await this.matterbridge.plugins.add(data.params.pluginNameOrPath);
|
|
1089
1066
|
if (plugin) {
|
|
1090
|
-
|
|
1067
|
+
sendResponse({ id: data.id, method: data.method, src: 'Matterbridge', dst: data.src, response: plugin.name });
|
|
1091
1068
|
this.wssSendSnackbarMessage(`Added plugin ${data.params.pluginNameOrPath}`, 5, 'success');
|
|
1092
1069
|
this.matterbridge.plugins
|
|
1093
1070
|
.load(plugin, true, 'The plugin has been added', true)
|
|
@@ -1101,13 +1078,13 @@ export class Frontend extends EventEmitter {
|
|
|
1101
1078
|
});
|
|
1102
1079
|
}
|
|
1103
1080
|
else {
|
|
1104
|
-
|
|
1081
|
+
sendResponse({ id: data.id, method: data.method, src: 'Matterbridge', dst: data.src, error: `Plugin ${data.params.pluginNameOrPath} not added` });
|
|
1105
1082
|
this.wssSendSnackbarMessage(`Plugin ${data.params.pluginNameOrPath} not added`, 10, 'error');
|
|
1106
1083
|
}
|
|
1107
1084
|
}
|
|
1108
1085
|
else if (data.method === '/api/removeplugin') {
|
|
1109
1086
|
if (!isValidString(data.params.pluginName, 10) || !this.matterbridge.plugins.has(data.params.pluginName)) {
|
|
1110
|
-
|
|
1087
|
+
sendResponse({ id: data.id, method: data.method, src: 'Matterbridge', dst: data.src, error: 'Wrong parameter pluginName in /api/removeplugin' });
|
|
1111
1088
|
return;
|
|
1112
1089
|
}
|
|
1113
1090
|
const plugin = this.matterbridge.plugins.get(data.params.pluginName);
|
|
@@ -1116,11 +1093,11 @@ export class Frontend extends EventEmitter {
|
|
|
1116
1093
|
this.wssSendSnackbarMessage(`Removed plugin ${data.params.pluginName}`, 5, 'success');
|
|
1117
1094
|
this.wssSendRefreshRequired('plugins');
|
|
1118
1095
|
this.wssSendRefreshRequired('devices');
|
|
1119
|
-
|
|
1096
|
+
sendResponse({ id: data.id, method: data.method, src: 'Matterbridge', dst: data.src, success: true });
|
|
1120
1097
|
}
|
|
1121
1098
|
else if (data.method === '/api/enableplugin') {
|
|
1122
1099
|
if (!isValidString(data.params.pluginName, 10) || !this.matterbridge.plugins.has(data.params.pluginName)) {
|
|
1123
|
-
|
|
1100
|
+
sendResponse({ id: data.id, method: data.method, src: 'Matterbridge', dst: data.src, error: 'Wrong parameter pluginName in /api/enableplugin' });
|
|
1124
1101
|
return;
|
|
1125
1102
|
}
|
|
1126
1103
|
const plugin = this.matterbridge.plugins.get(data.params.pluginName);
|
|
@@ -1146,11 +1123,11 @@ export class Frontend extends EventEmitter {
|
|
|
1146
1123
|
.catch((_error) => {
|
|
1147
1124
|
});
|
|
1148
1125
|
}
|
|
1149
|
-
|
|
1126
|
+
sendResponse({ id: data.id, method: data.method, src: 'Matterbridge', dst: data.src, success: true });
|
|
1150
1127
|
}
|
|
1151
1128
|
else if (data.method === '/api/disableplugin') {
|
|
1152
1129
|
if (!isValidString(data.params.pluginName, 10) || !this.matterbridge.plugins.has(data.params.pluginName)) {
|
|
1153
|
-
|
|
1130
|
+
sendResponse({ id: data.id, method: data.method, src: 'Matterbridge', dst: data.src, error: 'Wrong parameter pluginName in /api/disableplugin' });
|
|
1154
1131
|
return;
|
|
1155
1132
|
}
|
|
1156
1133
|
const plugin = this.matterbridge.plugins.get(data.params.pluginName);
|
|
@@ -1159,11 +1136,11 @@ export class Frontend extends EventEmitter {
|
|
|
1159
1136
|
this.wssSendSnackbarMessage(`Disabled plugin ${data.params.pluginName}`, 5, 'success');
|
|
1160
1137
|
this.wssSendRefreshRequired('plugins');
|
|
1161
1138
|
this.wssSendRefreshRequired('devices');
|
|
1162
|
-
|
|
1139
|
+
sendResponse({ id: data.id, method: data.method, src: 'Matterbridge', dst: data.src, success: true });
|
|
1163
1140
|
}
|
|
1164
1141
|
else if (data.method === '/api/restartplugin') {
|
|
1165
1142
|
if (!isValidString(data.params.pluginName, 10) || !this.matterbridge.plugins.has(data.params.pluginName)) {
|
|
1166
|
-
|
|
1143
|
+
sendResponse({ id: data.id, method: data.method, src: 'Matterbridge', dst: data.src, error: 'Wrong parameter pluginName in /api/restartplugin' });
|
|
1167
1144
|
return;
|
|
1168
1145
|
}
|
|
1169
1146
|
const plugin = this.matterbridge.plugins.get(data.params.pluginName);
|
|
@@ -1195,15 +1172,15 @@ export class Frontend extends EventEmitter {
|
|
|
1195
1172
|
this.wssSendSnackbarMessage(`Restarted plugin ${data.params.pluginName}`, 5, 'success');
|
|
1196
1173
|
this.wssSendRefreshRequired('plugins');
|
|
1197
1174
|
this.wssSendRefreshRequired('devices');
|
|
1198
|
-
|
|
1175
|
+
sendResponse({ id: data.id, method: data.method, src: 'Matterbridge', dst: data.src, success: true });
|
|
1199
1176
|
}
|
|
1200
1177
|
else if (data.method === '/api/savepluginconfig') {
|
|
1201
1178
|
if (!isValidString(data.params.pluginName, 10) || !this.matterbridge.plugins.has(data.params.pluginName)) {
|
|
1202
|
-
|
|
1179
|
+
sendResponse({ id: data.id, method: data.method, src: 'Matterbridge', dst: data.src, error: 'Wrong parameter pluginName in /api/savepluginconfig' });
|
|
1203
1180
|
return;
|
|
1204
1181
|
}
|
|
1205
1182
|
if (!isValidObject(data.params.formData, 5)) {
|
|
1206
|
-
|
|
1183
|
+
sendResponse({ id: data.id, method: data.method, src: 'Matterbridge', dst: data.src, error: 'Wrong parameter formData in /api/savepluginconfig' });
|
|
1207
1184
|
return;
|
|
1208
1185
|
}
|
|
1209
1186
|
this.log.info(`Saving config for plugin ${plg}${data.params.pluginName}${nf}...`);
|
|
@@ -1213,59 +1190,59 @@ export class Frontend extends EventEmitter {
|
|
|
1213
1190
|
this.wssSendSnackbarMessage(`Saved config for plugin ${data.params.pluginName}`);
|
|
1214
1191
|
this.wssSendRefreshRequired('pluginsRestart');
|
|
1215
1192
|
this.wssSendRestartRequired();
|
|
1216
|
-
|
|
1193
|
+
sendResponse({ id: data.id, method: data.method, src: 'Matterbridge', dst: data.src, success: true });
|
|
1217
1194
|
}
|
|
1218
1195
|
}
|
|
1219
1196
|
else if (data.method === '/api/checkupdates') {
|
|
1220
1197
|
const { checkUpdates } = await import('./update.js');
|
|
1221
1198
|
checkUpdates(this.matterbridge);
|
|
1222
|
-
|
|
1199
|
+
sendResponse({ id: data.id, method: data.method, src: 'Matterbridge', dst: data.src, success: true });
|
|
1223
1200
|
}
|
|
1224
1201
|
else if (data.method === '/api/shellysysupdate') {
|
|
1225
1202
|
const { triggerShellySysUpdate } = await import('./shelly.js');
|
|
1226
1203
|
triggerShellySysUpdate(this.matterbridge);
|
|
1227
|
-
|
|
1204
|
+
sendResponse({ id: data.id, method: data.method, src: 'Matterbridge', dst: data.src, success: true });
|
|
1228
1205
|
}
|
|
1229
1206
|
else if (data.method === '/api/shellymainupdate') {
|
|
1230
1207
|
const { triggerShellyMainUpdate } = await import('./shelly.js');
|
|
1231
1208
|
triggerShellyMainUpdate(this.matterbridge);
|
|
1232
|
-
|
|
1209
|
+
sendResponse({ id: data.id, method: data.method, src: 'Matterbridge', dst: data.src, success: true });
|
|
1233
1210
|
}
|
|
1234
1211
|
else if (data.method === '/api/shellycreatesystemlog') {
|
|
1235
1212
|
const { createShellySystemLog } = await import('./shelly.js');
|
|
1236
1213
|
createShellySystemLog(this.matterbridge);
|
|
1237
|
-
|
|
1214
|
+
sendResponse({ id: data.id, method: data.method, src: 'Matterbridge', dst: data.src, success: true });
|
|
1238
1215
|
}
|
|
1239
1216
|
else if (data.method === '/api/shellynetconfig') {
|
|
1240
1217
|
this.log.debug('/api/shellynetconfig:', data.params);
|
|
1241
1218
|
const { triggerShellyChangeIp: triggerShellyChangeNet } = await import('./shelly.js');
|
|
1242
1219
|
triggerShellyChangeNet(this.matterbridge, data.params);
|
|
1243
|
-
|
|
1220
|
+
sendResponse({ id: data.id, method: data.method, src: 'Matterbridge', dst: data.src, success: true });
|
|
1244
1221
|
}
|
|
1245
1222
|
else if (data.method === '/api/softreset') {
|
|
1246
1223
|
const { triggerShellySoftReset } = await import('./shelly.js');
|
|
1247
1224
|
triggerShellySoftReset(this.matterbridge);
|
|
1248
|
-
|
|
1225
|
+
sendResponse({ id: data.id, method: data.method, src: 'Matterbridge', dst: data.src, success: true });
|
|
1249
1226
|
}
|
|
1250
1227
|
else if (data.method === '/api/hardreset') {
|
|
1251
1228
|
const { triggerShellyHardReset } = await import('./shelly.js');
|
|
1252
1229
|
triggerShellyHardReset(this.matterbridge);
|
|
1253
|
-
|
|
1230
|
+
sendResponse({ id: data.id, method: data.method, src: 'Matterbridge', dst: data.src, success: true });
|
|
1254
1231
|
}
|
|
1255
1232
|
else if (data.method === '/api/reboot') {
|
|
1256
1233
|
const { triggerShellyReboot } = await import('./shelly.js');
|
|
1257
1234
|
triggerShellyReboot(this.matterbridge);
|
|
1258
|
-
|
|
1235
|
+
sendResponse({ id: data.id, method: data.method, src: 'Matterbridge', dst: data.src, success: true });
|
|
1259
1236
|
}
|
|
1260
1237
|
else if (data.method === '/api/restart') {
|
|
1261
1238
|
this.wssSendSnackbarMessage(`Restarting matterbridge...`, 0);
|
|
1262
1239
|
await this.matterbridge.restartProcess();
|
|
1263
|
-
|
|
1240
|
+
sendResponse({ id: data.id, method: data.method, src: 'Matterbridge', dst: data.src, success: true });
|
|
1264
1241
|
}
|
|
1265
1242
|
else if (data.method === '/api/shutdown') {
|
|
1266
1243
|
this.wssSendSnackbarMessage(`Shutting down matterbridge...`, 0);
|
|
1267
1244
|
await this.matterbridge.shutdownProcess();
|
|
1268
|
-
|
|
1245
|
+
sendResponse({ id: data.id, method: data.method, src: 'Matterbridge', dst: data.src, success: true });
|
|
1269
1246
|
}
|
|
1270
1247
|
else if (data.method === '/api/create-backup') {
|
|
1271
1248
|
this.wssSendSnackbarMessage('Creating backup...', 0);
|
|
@@ -1274,27 +1251,27 @@ export class Frontend extends EventEmitter {
|
|
|
1274
1251
|
this.log.notice(`Backup ready to be downloaded.`);
|
|
1275
1252
|
this.wssSendCloseSnackbarMessage('Creating backup...');
|
|
1276
1253
|
this.wssSendSnackbarMessage('Backup ready to be downloaded', 10);
|
|
1277
|
-
|
|
1254
|
+
sendResponse({ id: data.id, method: data.method, src: 'Matterbridge', dst: data.src, success: true });
|
|
1278
1255
|
}
|
|
1279
1256
|
else if (data.method === '/api/unregister') {
|
|
1280
1257
|
this.wssSendSnackbarMessage('Unregistering all bridged devices...', 0);
|
|
1281
1258
|
await this.matterbridge.unregisterAndShutdownProcess();
|
|
1282
1259
|
this.wssSendCloseSnackbarMessage('Unregistering all bridged devices...');
|
|
1283
|
-
|
|
1260
|
+
sendResponse({ id: data.id, method: data.method, src: 'Matterbridge', dst: data.src, success: true });
|
|
1284
1261
|
}
|
|
1285
1262
|
else if (data.method === '/api/reset') {
|
|
1286
1263
|
this.wssSendSnackbarMessage('Resetting matterbridge commissioning...', 10);
|
|
1287
1264
|
await this.matterbridge.shutdownProcessAndReset();
|
|
1288
|
-
|
|
1265
|
+
sendResponse({ id: data.id, method: data.method, src: 'Matterbridge', dst: data.src, success: true });
|
|
1289
1266
|
}
|
|
1290
1267
|
else if (data.method === '/api/factoryreset') {
|
|
1291
1268
|
this.wssSendSnackbarMessage('Factory reset of matterbridge...', 10);
|
|
1292
1269
|
await this.matterbridge.shutdownProcessAndFactoryReset();
|
|
1293
|
-
|
|
1270
|
+
sendResponse({ id: data.id, method: data.method, src: 'Matterbridge', dst: data.src, success: true });
|
|
1294
1271
|
}
|
|
1295
1272
|
else if (data.method === '/api/matter') {
|
|
1296
1273
|
if (!isValidString(data.params.id)) {
|
|
1297
|
-
|
|
1274
|
+
sendResponse({ id: data.id, method: data.method, src: 'Matterbridge', dst: data.src, error: 'Wrong parameter id in /api/matter' });
|
|
1298
1275
|
return;
|
|
1299
1276
|
}
|
|
1300
1277
|
let serverNode;
|
|
@@ -1303,129 +1280,125 @@ export class Frontend extends EventEmitter {
|
|
|
1303
1280
|
else
|
|
1304
1281
|
serverNode = this.matterbridge.getPlugins().find((p) => p.serverNode && p.serverNode.id === data.params.id)?.serverNode || this.matterbridge.getDevices().find((d) => d.serverNode && d.serverNode.id === data.params.id)?.serverNode;
|
|
1305
1282
|
if (!serverNode) {
|
|
1306
|
-
|
|
1283
|
+
sendResponse({ id: data.id, method: data.method, src: 'Matterbridge', dst: data.src, error: 'Unknown server node id in /api/matter' });
|
|
1307
1284
|
return;
|
|
1308
1285
|
}
|
|
1286
|
+
const matter = this.matterbridge.getServerNodeData(serverNode);
|
|
1309
1287
|
this.log.debug(`*Server node ${serverNode.id}: commissioned ${serverNode.state.commissioning.commissioned} upTime ${serverNode.state.generalDiagnostics.upTime}.`);
|
|
1310
1288
|
if (data.params.server) {
|
|
1311
1289
|
this.log.debug(`*Sending data for node ${data.params.id}`);
|
|
1312
|
-
this.wssSendRefreshRequired('matter', { matter: { ...
|
|
1290
|
+
this.wssSendRefreshRequired('matter', { matter: { ...matter } });
|
|
1313
1291
|
}
|
|
1314
1292
|
if (data.params.startCommission) {
|
|
1315
1293
|
await serverNode.env.get(DeviceCommissioner)?.allowBasicCommissioning();
|
|
1316
1294
|
this.matterbridge.advertisingNodes.set(serverNode.id, Date.now());
|
|
1317
1295
|
this.log.debug(`*Commissioning has been sent for node ${data.params.id}`);
|
|
1318
|
-
this.wssSendRefreshRequired('matter', { matter: { ...
|
|
1296
|
+
this.wssSendRefreshRequired('matter', { matter: { ...matter, advertising: true } });
|
|
1319
1297
|
}
|
|
1320
1298
|
if (data.params.stopCommission) {
|
|
1321
1299
|
await serverNode.env.get(DeviceCommissioner)?.endCommissioning();
|
|
1322
1300
|
this.matterbridge.advertisingNodes.delete(serverNode.id);
|
|
1323
1301
|
this.log.debug(`*Stop commissioning has been sent for node ${data.params.id}`);
|
|
1324
|
-
this.wssSendRefreshRequired('matter', { matter: { ...
|
|
1302
|
+
this.wssSendRefreshRequired('matter', { matter: { ...matter, advertising: false } });
|
|
1325
1303
|
}
|
|
1326
1304
|
if (data.params.advertise) {
|
|
1327
1305
|
await serverNode.env.get(DeviceAdvertiser)?.advertise(true);
|
|
1328
1306
|
this.log.debug(`*Advertising has been sent for node ${data.params.id}`);
|
|
1329
|
-
this.wssSendRefreshRequired('matter', { matter: { ...
|
|
1307
|
+
this.wssSendRefreshRequired('matter', { matter: { ...matter, advertising: true } });
|
|
1330
1308
|
}
|
|
1331
1309
|
if (data.params.removeFabric) {
|
|
1332
1310
|
if (serverNode.env.get(FabricManager).has(FabricIndex(data.params.removeFabric)))
|
|
1333
1311
|
await serverNode.env.get(FabricManager).removeFabric(FabricIndex(data.params.removeFabric));
|
|
1334
1312
|
this.log.debug(`*Removed fabric index ${data.params.removeFabric} for node ${data.params.id}`);
|
|
1335
|
-
this.wssSendRefreshRequired('matter', { matter: { ...
|
|
1313
|
+
this.wssSendRefreshRequired('matter', { matter: { ...matter } });
|
|
1336
1314
|
}
|
|
1337
|
-
|
|
1315
|
+
sendResponse({ id: data.id, method: data.method, src: 'Matterbridge', dst: data.src, success: true, response: matter });
|
|
1338
1316
|
}
|
|
1339
1317
|
else if (data.method === '/api/settings') {
|
|
1340
|
-
|
|
1318
|
+
sendResponse({ id: data.id, method: data.method, src: 'Matterbridge', dst: data.src, response: await this.getApiSettings() });
|
|
1341
1319
|
}
|
|
1342
1320
|
else if (data.method === '/api/plugins') {
|
|
1343
|
-
const
|
|
1344
|
-
|
|
1321
|
+
const plugins = this.getPlugins();
|
|
1322
|
+
sendResponse({ id: data.id, method: data.method, src: 'Matterbridge', dst: data.src, response: plugins });
|
|
1345
1323
|
}
|
|
1346
1324
|
else if (data.method === '/api/devices') {
|
|
1347
1325
|
const devices = await this.getDevices(isValidString(data.params.pluginName) ? data.params.pluginName : undefined);
|
|
1348
|
-
|
|
1326
|
+
sendResponse({ id: data.id, method: data.method, src: 'Matterbridge', dst: data.src, response: devices });
|
|
1349
1327
|
}
|
|
1350
1328
|
else if (data.method === '/api/clusters') {
|
|
1351
1329
|
if (!isValidString(data.params.plugin, 10)) {
|
|
1352
|
-
|
|
1330
|
+
sendResponse({ id: data.id, method: data.method, src: 'Matterbridge', dst: data.src, error: 'Wrong parameter plugin in /api/clusters' });
|
|
1353
1331
|
return;
|
|
1354
1332
|
}
|
|
1355
1333
|
if (!isValidNumber(data.params.endpoint, 1)) {
|
|
1356
|
-
|
|
1334
|
+
sendResponse({ id: data.id, method: data.method, src: 'Matterbridge', dst: data.src, error: 'Wrong parameter endpoint in /api/clusters' });
|
|
1357
1335
|
return;
|
|
1358
1336
|
}
|
|
1359
1337
|
const response = this.getClusters(data.params.plugin, data.params.endpoint);
|
|
1360
1338
|
if (response) {
|
|
1361
|
-
|
|
1339
|
+
sendResponse({
|
|
1362
1340
|
id: data.id,
|
|
1363
1341
|
method: data.method,
|
|
1364
1342
|
src: 'Matterbridge',
|
|
1365
1343
|
dst: data.src,
|
|
1366
|
-
|
|
1367
|
-
|
|
1368
|
-
serialNumber: response.serialNumber,
|
|
1369
|
-
endpoint: response.endpoint,
|
|
1370
|
-
deviceTypes: response.deviceTypes,
|
|
1371
|
-
response: response.clusters,
|
|
1372
|
-
}));
|
|
1344
|
+
response,
|
|
1345
|
+
});
|
|
1373
1346
|
}
|
|
1374
1347
|
else {
|
|
1375
|
-
|
|
1348
|
+
sendResponse({ id: data.id, method: data.method, src: 'Matterbridge', dst: data.src, error: 'Endpoint not found in /api/clusters' });
|
|
1376
1349
|
}
|
|
1377
1350
|
}
|
|
1378
|
-
else if (data.method === '/api/select
|
|
1351
|
+
else if (data.method === '/api/select/devices') {
|
|
1379
1352
|
if (!isValidString(data.params.plugin, 10)) {
|
|
1380
|
-
|
|
1353
|
+
sendResponse({ id: data.id, method: data.method, src: 'Matterbridge', dst: data.src, error: 'Wrong parameter plugin in /api/select/devices' });
|
|
1381
1354
|
return;
|
|
1382
1355
|
}
|
|
1383
1356
|
const plugin = this.matterbridge.plugins.get(data.params.plugin);
|
|
1384
1357
|
if (!plugin) {
|
|
1385
|
-
|
|
1358
|
+
sendResponse({ id: data.id, method: data.method, src: 'Matterbridge', dst: data.src, error: 'Plugin not found in /api/select/devices' });
|
|
1386
1359
|
return;
|
|
1387
1360
|
}
|
|
1388
1361
|
const selectDeviceValues = plugin.platform?.getSelectDevices().sort((keyA, keyB) => keyA.name.localeCompare(keyB.name));
|
|
1389
|
-
|
|
1362
|
+
sendResponse({ id: data.id, method: data.method, src: 'Matterbridge', dst: data.src, response: selectDeviceValues });
|
|
1390
1363
|
}
|
|
1391
1364
|
else if (data.method === '/api/select/entities') {
|
|
1392
1365
|
if (!isValidString(data.params.plugin, 10)) {
|
|
1393
|
-
|
|
1366
|
+
sendResponse({ id: data.id, method: data.method, src: 'Matterbridge', dst: data.src, error: 'Wrong parameter plugin in /api/select/entities' });
|
|
1394
1367
|
return;
|
|
1395
1368
|
}
|
|
1396
1369
|
const plugin = this.matterbridge.plugins.get(data.params.plugin);
|
|
1397
1370
|
if (!plugin) {
|
|
1398
|
-
|
|
1371
|
+
sendResponse({ id: data.id, method: data.method, src: 'Matterbridge', dst: data.src, error: 'Plugin not found in /api/select/entities' });
|
|
1399
1372
|
return;
|
|
1400
1373
|
}
|
|
1401
1374
|
const selectEntityValues = plugin.platform?.getSelectEntities().sort((keyA, keyB) => keyA.name.localeCompare(keyB.name));
|
|
1402
|
-
|
|
1375
|
+
sendResponse({ id: data.id, method: data.method, src: 'Matterbridge', dst: data.src, response: selectEntityValues });
|
|
1403
1376
|
}
|
|
1404
1377
|
else if (data.method === '/api/action') {
|
|
1405
1378
|
if (!isValidString(data.params.plugin, 5) || !isValidString(data.params.action, 1)) {
|
|
1406
|
-
|
|
1379
|
+
sendResponse({ id: data.id, method: data.method, src: 'Matterbridge', dst: data.src, error: 'Wrong parameter in /api/action' });
|
|
1407
1380
|
return;
|
|
1408
1381
|
}
|
|
1409
1382
|
const plugin = this.matterbridge.plugins.get(data.params.plugin);
|
|
1410
1383
|
if (!plugin) {
|
|
1411
|
-
|
|
1384
|
+
sendResponse({ id: data.id, method: data.method, src: 'Matterbridge', dst: data.src, error: 'Plugin not found in /api/action' });
|
|
1412
1385
|
return;
|
|
1413
1386
|
}
|
|
1414
1387
|
this.log.notice(`Action ${CYAN}${data.params.action}${nt}${data.params.value ? ' with ' + CYAN + data.params.value + nt : ''} for plugin ${CYAN}${plugin.name}${nt}`);
|
|
1415
1388
|
plugin.platform
|
|
1416
1389
|
?.onAction(data.params.action, data.params.value, data.params.id, data.params.formData)
|
|
1417
1390
|
.then(() => {
|
|
1418
|
-
|
|
1391
|
+
sendResponse({ id: data.id, method: data.method, src: 'Matterbridge', dst: data.src, success: true });
|
|
1419
1392
|
return;
|
|
1420
1393
|
})
|
|
1421
1394
|
.catch((error) => {
|
|
1422
1395
|
this.log.error(`Error in plugin ${plugin.name} action ${data.params.action}: ${error}`);
|
|
1423
|
-
|
|
1396
|
+
sendResponse({ id: data.id, method: data.method, src: 'Matterbridge', dst: data.src, error: `Error in plugin ${plugin.name} action ${data.params.action}: ${error}` });
|
|
1424
1397
|
});
|
|
1425
1398
|
}
|
|
1426
1399
|
else if (data.method === '/api/config') {
|
|
1427
1400
|
if (!isValidString(data.params.name, 5) || data.params.value === undefined) {
|
|
1428
|
-
|
|
1401
|
+
sendResponse({ id: data.id, method: data.method, src: 'Matterbridge', dst: data.src, error: 'Wrong parameter in /api/config' });
|
|
1429
1402
|
return;
|
|
1430
1403
|
}
|
|
1431
1404
|
this.log.debug(`Received /api/config name ${CYAN}${data.params.name}${db} value ${CYAN}${data.params.value}${db}`);
|
|
@@ -1433,14 +1406,14 @@ export class Frontend extends EventEmitter {
|
|
|
1433
1406
|
case 'setpassword':
|
|
1434
1407
|
if (isValidString(data.params.value)) {
|
|
1435
1408
|
await this.matterbridge.nodeContext?.set('password', data.params.value);
|
|
1436
|
-
|
|
1409
|
+
sendResponse({ id: data.id, method: data.method, src: 'Matterbridge', dst: data.src, success: true });
|
|
1437
1410
|
}
|
|
1438
1411
|
break;
|
|
1439
1412
|
case 'setbridgemode':
|
|
1440
1413
|
if (isValidString(data.params.value) && ['bridge', 'childbridge'].includes(data.params.value)) {
|
|
1441
1414
|
await this.matterbridge.nodeContext?.set('bridgeMode', data.params.value);
|
|
1442
1415
|
this.wssSendRestartRequired();
|
|
1443
|
-
|
|
1416
|
+
sendResponse({ id: data.id, method: data.method, src: 'Matterbridge', dst: data.src, success: true });
|
|
1444
1417
|
}
|
|
1445
1418
|
break;
|
|
1446
1419
|
case 'setmbloglevel':
|
|
@@ -1465,7 +1438,7 @@ export class Frontend extends EventEmitter {
|
|
|
1465
1438
|
await this.matterbridge.setLogLevel("fatal");
|
|
1466
1439
|
}
|
|
1467
1440
|
await this.matterbridge.nodeContext?.set('matterbridgeLogLevel', this.log.logLevel);
|
|
1468
|
-
|
|
1441
|
+
sendResponse({ id: data.id, method: data.method, src: 'Matterbridge', dst: data.src, success: true });
|
|
1469
1442
|
}
|
|
1470
1443
|
break;
|
|
1471
1444
|
case 'setmblogfile':
|
|
@@ -1477,7 +1450,7 @@ export class Frontend extends EventEmitter {
|
|
|
1477
1450
|
AnsiLogger.setGlobalLogfile(path.join(this.matterbridge.matterbridgeDirectory, this.matterbridge.matterbridgeLoggerFile), this.matterbridge.matterbridgeInformation.loggerLevel, true);
|
|
1478
1451
|
else
|
|
1479
1452
|
AnsiLogger.setGlobalLogfile(undefined);
|
|
1480
|
-
|
|
1453
|
+
sendResponse({ id: data.id, method: data.method, src: 'Matterbridge', dst: data.src, success: true });
|
|
1481
1454
|
}
|
|
1482
1455
|
break;
|
|
1483
1456
|
case 'setmjloglevel':
|
|
@@ -1503,7 +1476,7 @@ export class Frontend extends EventEmitter {
|
|
|
1503
1476
|
}
|
|
1504
1477
|
this.matterbridge.matterbridgeInformation.matterLoggerLevel = Logger.level;
|
|
1505
1478
|
await this.matterbridge.nodeContext?.set('matterLogLevel', Logger.level);
|
|
1506
|
-
|
|
1479
|
+
sendResponse({ id: data.id, method: data.method, src: 'Matterbridge', dst: data.src, success: true });
|
|
1507
1480
|
}
|
|
1508
1481
|
break;
|
|
1509
1482
|
case 'setmjlogfile':
|
|
@@ -1517,7 +1490,7 @@ export class Frontend extends EventEmitter {
|
|
|
1517
1490
|
else {
|
|
1518
1491
|
this.matterbridge.matterLog.logFilePath = undefined;
|
|
1519
1492
|
}
|
|
1520
|
-
|
|
1493
|
+
sendResponse({ id: data.id, method: data.method, src: 'Matterbridge', dst: data.src, success: true });
|
|
1521
1494
|
}
|
|
1522
1495
|
break;
|
|
1523
1496
|
case 'setmdnsinterface':
|
|
@@ -1527,7 +1500,7 @@ export class Frontend extends EventEmitter {
|
|
|
1527
1500
|
this.matterbridge.matterbridgeInformation.mattermdnsinterface = this.matterbridge.mdnsInterface;
|
|
1528
1501
|
await this.matterbridge.nodeContext?.set('mattermdnsinterface', data.params.value);
|
|
1529
1502
|
this.wssSendRestartRequired();
|
|
1530
|
-
|
|
1503
|
+
sendResponse({ id: data.id, method: data.method, src: 'Matterbridge', dst: data.src, success: true });
|
|
1531
1504
|
}
|
|
1532
1505
|
break;
|
|
1533
1506
|
case 'setipv4address':
|
|
@@ -1537,7 +1510,7 @@ export class Frontend extends EventEmitter {
|
|
|
1537
1510
|
this.matterbridge.matterbridgeInformation.matteripv4address = this.matterbridge.ipv4address;
|
|
1538
1511
|
await this.matterbridge.nodeContext?.set('matteripv4address', data.params.value);
|
|
1539
1512
|
this.wssSendRestartRequired();
|
|
1540
|
-
|
|
1513
|
+
sendResponse({ id: data.id, method: data.method, src: 'Matterbridge', dst: data.src, success: true });
|
|
1541
1514
|
}
|
|
1542
1515
|
break;
|
|
1543
1516
|
case 'setipv6address':
|
|
@@ -1547,7 +1520,7 @@ export class Frontend extends EventEmitter {
|
|
|
1547
1520
|
this.matterbridge.matterbridgeInformation.matteripv6address = this.matterbridge.ipv6address;
|
|
1548
1521
|
await this.matterbridge.nodeContext?.set('matteripv6address', data.params.value);
|
|
1549
1522
|
this.wssSendRestartRequired();
|
|
1550
|
-
|
|
1523
|
+
sendResponse({ id: data.id, method: data.method, src: 'Matterbridge', dst: data.src, success: true });
|
|
1551
1524
|
}
|
|
1552
1525
|
break;
|
|
1553
1526
|
case 'setmatterport':
|
|
@@ -1564,7 +1537,7 @@ export class Frontend extends EventEmitter {
|
|
|
1564
1537
|
await this.matterbridge.nodeContext?.set('matterport', 5540);
|
|
1565
1538
|
this.wssSendRestartRequired();
|
|
1566
1539
|
}
|
|
1567
|
-
|
|
1540
|
+
sendResponse({ id: data.id, method: data.method, src: 'Matterbridge', dst: data.src, success: true });
|
|
1568
1541
|
break;
|
|
1569
1542
|
case 'setmatterdiscriminator':
|
|
1570
1543
|
data.params.value = isValidString(data.params.value) ? parseInt(data.params.value) : 0;
|
|
@@ -1573,14 +1546,14 @@ export class Frontend extends EventEmitter {
|
|
|
1573
1546
|
this.matterbridge.matterbridgeInformation.matterDiscriminator = data.params.value;
|
|
1574
1547
|
await this.matterbridge.nodeContext?.set('matterdiscriminator', data.params.value);
|
|
1575
1548
|
this.wssSendRestartRequired();
|
|
1576
|
-
|
|
1549
|
+
sendResponse({ id: data.id, method: data.method, src: 'Matterbridge', dst: data.src, success: true });
|
|
1577
1550
|
}
|
|
1578
1551
|
else {
|
|
1579
1552
|
this.log.debug(`Reset matter commissioning discriminator to ${CYAN}undefined${db}`);
|
|
1580
1553
|
this.matterbridge.matterbridgeInformation.matterDiscriminator = undefined;
|
|
1581
1554
|
await this.matterbridge.nodeContext?.remove('matterdiscriminator');
|
|
1582
1555
|
this.wssSendRestartRequired();
|
|
1583
|
-
|
|
1556
|
+
sendResponse({ id: data.id, method: data.method, src: 'Matterbridge', dst: data.src, success: false });
|
|
1584
1557
|
}
|
|
1585
1558
|
break;
|
|
1586
1559
|
case 'setmatterpasscode':
|
|
@@ -1590,14 +1563,14 @@ export class Frontend extends EventEmitter {
|
|
|
1590
1563
|
this.log.debug(`Set matter commissioning passcode to ${CYAN}${data.params.value}${db}`);
|
|
1591
1564
|
await this.matterbridge.nodeContext?.set('matterpasscode', data.params.value);
|
|
1592
1565
|
this.wssSendRestartRequired();
|
|
1593
|
-
|
|
1566
|
+
sendResponse({ id: data.id, method: data.method, src: 'Matterbridge', dst: data.src, success: true });
|
|
1594
1567
|
}
|
|
1595
1568
|
else {
|
|
1596
1569
|
this.log.debug(`Reset matter commissioning passcode to ${CYAN}undefined${db}`);
|
|
1597
1570
|
this.matterbridge.matterbridgeInformation.matterPasscode = undefined;
|
|
1598
1571
|
await this.matterbridge.nodeContext?.remove('matterpasscode');
|
|
1599
1572
|
this.wssSendRestartRequired();
|
|
1600
|
-
|
|
1573
|
+
sendResponse({ id: data.id, method: data.method, src: 'Matterbridge', dst: data.src, success: false });
|
|
1601
1574
|
}
|
|
1602
1575
|
break;
|
|
1603
1576
|
case 'setvirtualmode':
|
|
@@ -1607,22 +1580,22 @@ export class Frontend extends EventEmitter {
|
|
|
1607
1580
|
await this.matterbridge.nodeContext?.set('virtualmode', data.params.value);
|
|
1608
1581
|
this.wssSendRestartRequired();
|
|
1609
1582
|
}
|
|
1610
|
-
|
|
1583
|
+
sendResponse({ id: data.id, method: data.method, src: 'Matterbridge', dst: data.src, success: true });
|
|
1611
1584
|
break;
|
|
1612
1585
|
default:
|
|
1613
1586
|
this.log.warn(`Unknown parameter ${data.params.name} in /api/config`);
|
|
1614
|
-
|
|
1587
|
+
sendResponse({ id: data.id, method: data.method, src: 'Matterbridge', dst: data.src, error: `Unknown parameter ${data.params.name} in /api/config` });
|
|
1615
1588
|
}
|
|
1616
1589
|
}
|
|
1617
1590
|
else if (data.method === '/api/command') {
|
|
1618
1591
|
if (!isValidString(data.params.command, 5)) {
|
|
1619
|
-
|
|
1592
|
+
sendResponse({ id: data.id, method: data.method, src: 'Matterbridge', dst: data.src, error: 'Wrong parameter command in /api/command' });
|
|
1620
1593
|
return;
|
|
1621
1594
|
}
|
|
1622
1595
|
if (data.params.command === 'selectdevice' && isValidString(data.params.plugin, 10) && isValidString(data.params.serial, 1) && isValidString(data.params.name, 1)) {
|
|
1623
1596
|
const plugin = this.matterbridge.plugins.get(data.params.plugin);
|
|
1624
1597
|
if (!plugin) {
|
|
1625
|
-
|
|
1598
|
+
sendResponse({ id: data.id, method: data.method, src: 'Matterbridge', dst: data.src, error: 'Plugin not found in /api/command' });
|
|
1626
1599
|
return;
|
|
1627
1600
|
}
|
|
1628
1601
|
const config = plugin.configJson;
|
|
@@ -1659,17 +1632,17 @@ export class Frontend extends EventEmitter {
|
|
|
1659
1632
|
if (!restartRequired)
|
|
1660
1633
|
this.wssSendRefreshRequired('pluginsRestart');
|
|
1661
1634
|
this.wssSendRestartRequired(false);
|
|
1662
|
-
|
|
1635
|
+
sendResponse({ id: data.id, method: data.method, src: 'Matterbridge', dst: data.src, success: true });
|
|
1663
1636
|
}
|
|
1664
1637
|
else {
|
|
1665
1638
|
this.log.error(`SelectDevice: select ${select} not supported`);
|
|
1666
|
-
|
|
1639
|
+
sendResponse({ id: data.id, method: data.method, src: 'Matterbridge', dst: data.src, error: `SelectDevice: select ${select} not supported` });
|
|
1667
1640
|
}
|
|
1668
1641
|
}
|
|
1669
1642
|
else if (data.params.command === 'unselectdevice' && isValidString(data.params.plugin, 10) && isValidString(data.params.serial, 1) && isValidString(data.params.name, 1)) {
|
|
1670
1643
|
const plugin = this.matterbridge.plugins.get(data.params.plugin);
|
|
1671
1644
|
if (!plugin) {
|
|
1672
|
-
|
|
1645
|
+
sendResponse({ id: data.id, method: data.method, src: 'Matterbridge', dst: data.src, error: 'Plugin not found in /api/command' });
|
|
1673
1646
|
return;
|
|
1674
1647
|
}
|
|
1675
1648
|
const config = plugin.configJson;
|
|
@@ -1706,24 +1679,24 @@ export class Frontend extends EventEmitter {
|
|
|
1706
1679
|
if (!restartRequired)
|
|
1707
1680
|
this.wssSendRefreshRequired('pluginsRestart');
|
|
1708
1681
|
this.wssSendRestartRequired(false);
|
|
1709
|
-
|
|
1682
|
+
sendResponse({ id: data.id, method: data.method, src: 'Matterbridge', dst: data.src, success: true });
|
|
1710
1683
|
}
|
|
1711
1684
|
else {
|
|
1712
1685
|
this.log.error(`SelectDevice: select ${select} not supported`);
|
|
1713
|
-
|
|
1686
|
+
sendResponse({ id: data.id, method: data.method, src: 'Matterbridge', dst: data.src, error: `SelectDevice: select ${select} not supported` });
|
|
1714
1687
|
}
|
|
1715
1688
|
}
|
|
1716
1689
|
}
|
|
1717
1690
|
else {
|
|
1718
1691
|
this.log.error(`Invalid method from websocket client: ${debugStringify(data)}`);
|
|
1719
|
-
|
|
1692
|
+
sendResponse({ id: data.id, method: data.method, src: 'Matterbridge', dst: data.src, error: 'Invalid method' });
|
|
1720
1693
|
}
|
|
1721
1694
|
}
|
|
1722
1695
|
catch (error) {
|
|
1723
1696
|
inspectError(this.log, `Error processing message "${message}" from websocket client`, error);
|
|
1724
1697
|
}
|
|
1725
1698
|
}
|
|
1726
|
-
|
|
1699
|
+
wssSendLogMessage(level, time, name, message) {
|
|
1727
1700
|
if (!level || !time || !name || !message)
|
|
1728
1701
|
return;
|
|
1729
1702
|
message = message.replace(/\x1B\[[0-9;]*[m|s|u|K]/g, '');
|
|
@@ -1744,19 +1717,11 @@ export class Frontend extends EventEmitter {
|
|
|
1744
1717
|
return word;
|
|
1745
1718
|
})
|
|
1746
1719
|
.join(' ');
|
|
1747
|
-
this.
|
|
1748
|
-
if (client.readyState === WebSocket.OPEN) {
|
|
1749
|
-
client.send(JSON.stringify({ id: WS_ID_LOG, src: 'Matterbridge', level, time, name, message }));
|
|
1750
|
-
}
|
|
1751
|
-
});
|
|
1720
|
+
this.wssBroadcastMessage({ id: 0, src: 'Matterbridge', dst: 'Frontend', method: 'log', params: { level, time, name, message } });
|
|
1752
1721
|
}
|
|
1753
|
-
wssSendRefreshRequired(changed = null, params
|
|
1722
|
+
wssSendRefreshRequired(changed = null, params) {
|
|
1754
1723
|
this.log.debug('Sending a refresh required message to all connected clients');
|
|
1755
|
-
this.
|
|
1756
|
-
if (client.readyState === WebSocket.OPEN) {
|
|
1757
|
-
client.send(JSON.stringify({ id: WS_ID_REFRESH_NEEDED, src: 'Matterbridge', dst: 'Frontend', method: 'refresh_required', params: { changed: changed, ...params } }));
|
|
1758
|
-
}
|
|
1759
|
-
});
|
|
1724
|
+
this.wssBroadcastMessage({ id: 1, src: 'Matterbridge', dst: 'Frontend', method: 'refresh_required', params: { changed, ...params } });
|
|
1760
1725
|
}
|
|
1761
1726
|
wssSendRestartRequired(snackbar = true, fixed = false) {
|
|
1762
1727
|
this.log.debug('Sending a restart required message to all connected clients');
|
|
@@ -1764,88 +1729,54 @@ export class Frontend extends EventEmitter {
|
|
|
1764
1729
|
this.matterbridge.matterbridgeInformation.fixedRestartRequired = fixed;
|
|
1765
1730
|
if (snackbar === true)
|
|
1766
1731
|
this.wssSendSnackbarMessage(`Restart required`, 0);
|
|
1767
|
-
this.
|
|
1768
|
-
if (client.readyState === WebSocket.OPEN) {
|
|
1769
|
-
client.send(JSON.stringify({ id: WS_ID_RESTART_NEEDED, src: 'Matterbridge', dst: 'Frontend', method: 'restart_required', params: { fixed } }));
|
|
1770
|
-
}
|
|
1771
|
-
});
|
|
1732
|
+
this.wssBroadcastMessage({ id: 2, src: 'Matterbridge', dst: 'Frontend', method: 'restart_required', params: { fixed } });
|
|
1772
1733
|
}
|
|
1773
1734
|
wssSendRestartNotRequired(snackbar = true) {
|
|
1774
1735
|
this.log.debug('Sending a restart not required message to all connected clients');
|
|
1775
1736
|
this.matterbridge.matterbridgeInformation.restartRequired = false;
|
|
1776
1737
|
if (snackbar === true)
|
|
1777
1738
|
this.wssSendCloseSnackbarMessage(`Restart required`);
|
|
1778
|
-
this.
|
|
1779
|
-
if (client.readyState === WebSocket.OPEN) {
|
|
1780
|
-
client.send(JSON.stringify({ id: WS_ID_RESTART_NEEDED, src: 'Matterbridge', dst: 'Frontend', method: 'restart_not_required', params: {} }));
|
|
1781
|
-
}
|
|
1782
|
-
});
|
|
1739
|
+
this.wssBroadcastMessage({ id: 3, src: 'Matterbridge', dst: 'Frontend', method: 'restart_not_required' });
|
|
1783
1740
|
}
|
|
1784
1741
|
wssSendUpdateRequired(devVersion = false) {
|
|
1785
1742
|
this.log.debug('Sending an update required message to all connected clients');
|
|
1786
1743
|
this.matterbridge.matterbridgeInformation.updateRequired = true;
|
|
1787
|
-
this.
|
|
1788
|
-
if (client.readyState === WebSocket.OPEN) {
|
|
1789
|
-
client.send(JSON.stringify({ id: WS_ID_UPDATE_NEEDED, src: 'Matterbridge', dst: 'Frontend', method: devVersion ? 'update_required_dev' : 'update_required', params: {} }));
|
|
1790
|
-
}
|
|
1791
|
-
});
|
|
1744
|
+
this.wssBroadcastMessage({ id: 8, src: 'Matterbridge', dst: 'Frontend', method: devVersion ? 'update_required_dev' : 'update_required' });
|
|
1792
1745
|
}
|
|
1793
1746
|
wssSendCpuUpdate(cpuUsage) {
|
|
1794
1747
|
if (hasParameter('debug'))
|
|
1795
1748
|
this.log.debug('Sending a cpu update message to all connected clients');
|
|
1796
|
-
this.
|
|
1797
|
-
if (client.readyState === WebSocket.OPEN) {
|
|
1798
|
-
client.send(JSON.stringify({ id: WS_ID_CPU_UPDATE, src: 'Matterbridge', dst: 'Frontend', method: 'cpu_update', params: { cpuUsage } }));
|
|
1799
|
-
}
|
|
1800
|
-
});
|
|
1749
|
+
this.wssBroadcastMessage({ id: 4, src: 'Matterbridge', dst: 'Frontend', method: 'cpu_update', params: { cpuUsage } });
|
|
1801
1750
|
}
|
|
1802
1751
|
wssSendMemoryUpdate(totalMemory, freeMemory, rss, heapTotal, heapUsed, external, arrayBuffers) {
|
|
1803
1752
|
if (hasParameter('debug'))
|
|
1804
1753
|
this.log.debug('Sending a memory update message to all connected clients');
|
|
1805
|
-
this.
|
|
1806
|
-
if (client.readyState === WebSocket.OPEN) {
|
|
1807
|
-
client.send(JSON.stringify({ id: WS_ID_MEMORY_UPDATE, src: 'Matterbridge', dst: 'Frontend', method: 'memory_update', params: { totalMemory, freeMemory, rss, heapTotal, heapUsed, external, arrayBuffers } }));
|
|
1808
|
-
}
|
|
1809
|
-
});
|
|
1754
|
+
this.wssBroadcastMessage({ id: 5, src: 'Matterbridge', dst: 'Frontend', method: 'memory_update', params: { totalMemory, freeMemory, rss, heapTotal, heapUsed, external, arrayBuffers } });
|
|
1810
1755
|
}
|
|
1811
1756
|
wssSendUptimeUpdate(systemUptime, processUptime) {
|
|
1812
1757
|
if (hasParameter('debug'))
|
|
1813
1758
|
this.log.debug('Sending a uptime update message to all connected clients');
|
|
1814
|
-
this.
|
|
1815
|
-
if (client.readyState === WebSocket.OPEN) {
|
|
1816
|
-
client.send(JSON.stringify({ id: WS_ID_UPTIME_UPDATE, src: 'Matterbridge', dst: 'Frontend', method: 'uptime_update', params: { systemUptime, processUptime } }));
|
|
1817
|
-
}
|
|
1818
|
-
});
|
|
1759
|
+
this.wssBroadcastMessage({ id: 6, src: 'Matterbridge', dst: 'Frontend', method: 'uptime_update', params: { systemUptime, processUptime } });
|
|
1819
1760
|
}
|
|
1820
1761
|
wssSendSnackbarMessage(message, timeout = 5, severity = 'info') {
|
|
1821
1762
|
this.log.debug('Sending a snackbar message to all connected clients');
|
|
1822
|
-
this.
|
|
1823
|
-
if (client.readyState === WebSocket.OPEN) {
|
|
1824
|
-
client.send(JSON.stringify({ id: WS_ID_SNACKBAR, src: 'Matterbridge', dst: 'Frontend', params: { message, timeout, severity } }));
|
|
1825
|
-
}
|
|
1826
|
-
});
|
|
1763
|
+
this.wssBroadcastMessage({ id: 7, src: 'Matterbridge', dst: 'Frontend', method: 'snackbar', params: { message, timeout, severity } });
|
|
1827
1764
|
}
|
|
1828
1765
|
wssSendCloseSnackbarMessage(message) {
|
|
1829
1766
|
this.log.debug('Sending a close snackbar message to all connected clients');
|
|
1830
|
-
this.
|
|
1831
|
-
if (client.readyState === WebSocket.OPEN) {
|
|
1832
|
-
client.send(JSON.stringify({ id: WS_ID_CLOSE_SNACKBAR, src: 'Matterbridge', dst: 'Frontend', params: { message } }));
|
|
1833
|
-
}
|
|
1834
|
-
});
|
|
1767
|
+
this.wssBroadcastMessage({ id: 10, src: 'Matterbridge', dst: 'Frontend', method: 'close_snackbar', params: { message } });
|
|
1835
1768
|
}
|
|
1836
1769
|
wssSendAttributeChangedMessage(plugin, serialNumber, uniqueId, cluster, attribute, value) {
|
|
1837
1770
|
this.log.debug('Sending an attribute update message to all connected clients');
|
|
1838
|
-
this.
|
|
1839
|
-
if (client.readyState === WebSocket.OPEN) {
|
|
1840
|
-
client.send(JSON.stringify({ id: WS_ID_STATEUPDATE, src: 'Matterbridge', dst: 'Frontend', method: 'state_update', params: { plugin, serialNumber, uniqueId, cluster, attribute, value } }));
|
|
1841
|
-
}
|
|
1842
|
-
});
|
|
1771
|
+
this.wssBroadcastMessage({ id: 9, src: 'Matterbridge', dst: 'Frontend', method: 'state_update', params: { plugin, serialNumber, uniqueId, cluster, attribute, value } });
|
|
1843
1772
|
}
|
|
1844
|
-
wssBroadcastMessage(
|
|
1845
|
-
|
|
1773
|
+
wssBroadcastMessage(msg) {
|
|
1774
|
+
const stringifiedMsg = JSON.stringify(msg);
|
|
1775
|
+
if (msg.id !== 0)
|
|
1776
|
+
this.log.debug(`Sending a broadcast message: ${debugStringify(msg)}`);
|
|
1846
1777
|
this.webSocketServer?.clients.forEach((client) => {
|
|
1847
1778
|
if (client.readyState === WebSocket.OPEN) {
|
|
1848
|
-
client.send(
|
|
1779
|
+
client.send(stringifiedMsg);
|
|
1849
1780
|
}
|
|
1850
1781
|
});
|
|
1851
1782
|
}
|