matterbridge 2.2.2 → 2.2.4-dev.1
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 +29 -0
- package/dist/cli.js +2 -37
- package/dist/cluster/export.js +0 -2
- package/dist/defaultConfigSchema.js +0 -23
- package/dist/deviceManager.js +1 -94
- package/dist/frontend.js +31 -306
- package/dist/index.js +1 -28
- package/dist/logger/export.js +0 -1
- package/dist/matter/behaviors.js +0 -2
- package/dist/matter/clusters.js +0 -2
- package/dist/matter/devices.js +0 -2
- package/dist/matter/endpoints.js +0 -2
- package/dist/matter/export.js +0 -2
- package/dist/matter/types.js +0 -2
- package/dist/matterbridge.js +69 -727
- package/dist/matterbridgeAccessoryPlatform.js +0 -33
- package/dist/matterbridgeBehaviors.js +1 -32
- package/dist/matterbridgeDeviceTypes.js +11 -112
- package/dist/matterbridgeDynamicPlatform.js +0 -33
- package/dist/matterbridgeEndpoint.js +6 -690
- package/dist/matterbridgeEndpointHelpers.js +9 -118
- package/dist/matterbridgePlatform.js +7 -185
- package/dist/matterbridgeTypes.js +0 -24
- package/dist/pluginManager.js +3 -229
- package/dist/shelly.js +6 -121
- package/dist/storage/export.js +0 -1
- package/dist/update.js +0 -45
- package/dist/utils/colorUtils.js +2 -205
- package/dist/utils/copyDirectory.js +1 -37
- package/dist/utils/createZip.js +2 -42
- package/dist/utils/deepCopy.js +0 -40
- package/dist/utils/deepEqual.js +1 -65
- package/dist/utils/export.js +0 -1
- package/dist/utils/isvalid.js +0 -86
- package/dist/utils/network.js +5 -77
- package/dist/utils/parameter.js +0 -41
- package/dist/utils/wait.js +5 -48
- package/frontend/build/asset-manifest.json +3 -3
- package/frontend/build/index.html +1 -1
- package/frontend/build/static/js/{main.6bd178dd.js → main.819c0908.js} +4 -4
- package/frontend/build/static/js/{main.6bd178dd.js.map → main.819c0908.js.map} +1 -1
- package/npm-shrinkwrap.json +2 -2
- package/package.json +1 -2
- package/dist/cli.d.ts +0 -29
- package/dist/cli.d.ts.map +0 -1
- package/dist/cli.js.map +0 -1
- package/dist/cluster/export.d.ts +0 -2
- package/dist/cluster/export.d.ts.map +0 -1
- package/dist/cluster/export.js.map +0 -1
- package/dist/defaultConfigSchema.d.ts +0 -27
- package/dist/defaultConfigSchema.d.ts.map +0 -1
- package/dist/defaultConfigSchema.js.map +0 -1
- package/dist/deviceManager.d.ts +0 -114
- package/dist/deviceManager.d.ts.map +0 -1
- package/dist/deviceManager.js.map +0 -1
- package/dist/frontend.d.ts +0 -201
- package/dist/frontend.d.ts.map +0 -1
- package/dist/frontend.js.map +0 -1
- package/dist/index.d.ts +0 -35
- package/dist/index.d.ts.map +0 -1
- package/dist/index.js.map +0 -1
- package/dist/logger/export.d.ts +0 -2
- package/dist/logger/export.d.ts.map +0 -1
- package/dist/logger/export.js.map +0 -1
- package/dist/matter/behaviors.d.ts +0 -2
- package/dist/matter/behaviors.d.ts.map +0 -1
- package/dist/matter/behaviors.js.map +0 -1
- package/dist/matter/clusters.d.ts +0 -2
- package/dist/matter/clusters.d.ts.map +0 -1
- package/dist/matter/clusters.js.map +0 -1
- package/dist/matter/devices.d.ts +0 -2
- package/dist/matter/devices.d.ts.map +0 -1
- package/dist/matter/devices.js.map +0 -1
- package/dist/matter/endpoints.d.ts +0 -2
- package/dist/matter/endpoints.d.ts.map +0 -1
- package/dist/matter/endpoints.js.map +0 -1
- package/dist/matter/export.d.ts +0 -5
- package/dist/matter/export.d.ts.map +0 -1
- package/dist/matter/export.js.map +0 -1
- package/dist/matter/types.d.ts +0 -3
- package/dist/matter/types.d.ts.map +0 -1
- package/dist/matter/types.js.map +0 -1
- package/dist/matterbridge.d.ts +0 -412
- package/dist/matterbridge.d.ts.map +0 -1
- package/dist/matterbridge.js.map +0 -1
- package/dist/matterbridgeAccessoryPlatform.d.ts +0 -39
- package/dist/matterbridgeAccessoryPlatform.d.ts.map +0 -1
- package/dist/matterbridgeAccessoryPlatform.js.map +0 -1
- package/dist/matterbridgeBehaviors.d.ts +0 -1056
- package/dist/matterbridgeBehaviors.d.ts.map +0 -1
- package/dist/matterbridgeBehaviors.js.map +0 -1
- package/dist/matterbridgeDeviceTypes.d.ts +0 -177
- package/dist/matterbridgeDeviceTypes.d.ts.map +0 -1
- package/dist/matterbridgeDeviceTypes.js.map +0 -1
- package/dist/matterbridgeDynamicPlatform.d.ts +0 -39
- package/dist/matterbridgeDynamicPlatform.d.ts.map +0 -1
- package/dist/matterbridgeDynamicPlatform.js.map +0 -1
- package/dist/matterbridgeEndpoint.d.ts +0 -835
- package/dist/matterbridgeEndpoint.d.ts.map +0 -1
- package/dist/matterbridgeEndpoint.js.map +0 -1
- package/dist/matterbridgeEndpointHelpers.d.ts +0 -2275
- package/dist/matterbridgeEndpointHelpers.d.ts.map +0 -1
- package/dist/matterbridgeEndpointHelpers.js.map +0 -1
- package/dist/matterbridgePlatform.d.ts +0 -251
- package/dist/matterbridgePlatform.d.ts.map +0 -1
- package/dist/matterbridgePlatform.js.map +0 -1
- package/dist/matterbridgeTypes.d.ts +0 -177
- package/dist/matterbridgeTypes.d.ts.map +0 -1
- package/dist/matterbridgeTypes.js.map +0 -1
- package/dist/pluginManager.d.ts +0 -236
- package/dist/pluginManager.d.ts.map +0 -1
- package/dist/pluginManager.js.map +0 -1
- package/dist/shelly.d.ts +0 -77
- package/dist/shelly.d.ts.map +0 -1
- package/dist/shelly.js.map +0 -1
- package/dist/storage/export.d.ts +0 -2
- package/dist/storage/export.d.ts.map +0 -1
- package/dist/storage/export.js.map +0 -1
- package/dist/update.d.ts +0 -32
- package/dist/update.d.ts.map +0 -1
- package/dist/update.js.map +0 -1
- package/dist/utils/colorUtils.d.ts +0 -61
- package/dist/utils/colorUtils.d.ts.map +0 -1
- package/dist/utils/colorUtils.js.map +0 -1
- package/dist/utils/copyDirectory.d.ts +0 -32
- package/dist/utils/copyDirectory.d.ts.map +0 -1
- package/dist/utils/copyDirectory.js.map +0 -1
- package/dist/utils/createZip.d.ts +0 -38
- package/dist/utils/createZip.d.ts.map +0 -1
- package/dist/utils/createZip.js.map +0 -1
- package/dist/utils/deepCopy.d.ts +0 -31
- package/dist/utils/deepCopy.d.ts.map +0 -1
- package/dist/utils/deepCopy.js.map +0 -1
- package/dist/utils/deepEqual.d.ts +0 -53
- package/dist/utils/deepEqual.d.ts.map +0 -1
- package/dist/utils/deepEqual.js.map +0 -1
- package/dist/utils/export.d.ts +0 -10
- package/dist/utils/export.d.ts.map +0 -1
- package/dist/utils/export.js.map +0 -1
- package/dist/utils/isvalid.d.ts +0 -87
- package/dist/utils/isvalid.d.ts.map +0 -1
- package/dist/utils/isvalid.js.map +0 -1
- package/dist/utils/network.d.ts +0 -70
- package/dist/utils/network.d.ts.map +0 -1
- package/dist/utils/network.js.map +0 -1
- package/dist/utils/parameter.d.ts +0 -44
- package/dist/utils/parameter.d.ts.map +0 -1
- package/dist/utils/parameter.js.map +0 -1
- package/dist/utils/wait.d.ts +0 -43
- package/dist/utils/wait.d.ts.map +0 -1
- package/dist/utils/wait.js.map +0 -1
- /package/frontend/build/static/js/{main.6bd178dd.js.LICENSE.txt → main.819c0908.js.LICENSE.txt} +0 -0
package/dist/frontend.js
CHANGED
|
@@ -1,28 +1,4 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* This file contains the class Frontend.
|
|
3
|
-
*
|
|
4
|
-
* @file frontend.ts
|
|
5
|
-
* @author Luca Liguori
|
|
6
|
-
* @date 2025-01-13
|
|
7
|
-
* @version 1.0.2
|
|
8
|
-
*
|
|
9
|
-
* Copyright 2025, 2026, 2027 Luca Liguori.
|
|
10
|
-
*
|
|
11
|
-
* Licensed under the Apache License, Version 2.0 (the "License");
|
|
12
|
-
* you may not use this file except in compliance with the License.
|
|
13
|
-
* You may obtain a copy of the License at
|
|
14
|
-
*
|
|
15
|
-
* http://www.apache.org/licenses/LICENSE-2.0
|
|
16
|
-
*
|
|
17
|
-
* Unless required by applicable law or agreed to in writing, software
|
|
18
|
-
* distributed under the License is distributed on an "AS IS" BASIS,
|
|
19
|
-
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
20
|
-
* See the License for the specific language governing permissions and
|
|
21
|
-
* limitations under the License. *
|
|
22
|
-
*/
|
|
23
|
-
// @matter
|
|
24
1
|
import { EndpointServer, Logger, LogLevel as MatterLogLevel, LogFormat as MatterLogFormat, Lifecycle } from '@matter/main';
|
|
25
|
-
// Node modules
|
|
26
2
|
import { createServer } from 'node:http';
|
|
27
3
|
import os from 'node:os';
|
|
28
4
|
import path from 'node:path';
|
|
@@ -31,70 +7,21 @@ import https from 'https';
|
|
|
31
7
|
import express from 'express';
|
|
32
8
|
import WebSocket, { WebSocketServer } from 'ws';
|
|
33
9
|
import multer from 'multer';
|
|
34
|
-
// AnsiLogger module
|
|
35
10
|
import { AnsiLogger, stringify, debugStringify, CYAN, db, er, nf, rs, UNDERLINE, UNDERLINEOFF, wr, YELLOW } from './logger/export.js';
|
|
36
|
-
// Matterbridge
|
|
37
11
|
import { createZip, deepCopy, isValidArray, isValidNumber, isValidObject, isValidString } from './utils/export.js';
|
|
38
12
|
import { plg } from './matterbridgeTypes.js';
|
|
39
13
|
import { hasParameter } from './utils/export.js';
|
|
40
14
|
import { BridgedDeviceBasicInformation } from '@matter/main/clusters';
|
|
41
|
-
/**
|
|
42
|
-
* Websocket message ID for logging.
|
|
43
|
-
* @constant {number}
|
|
44
|
-
*/
|
|
45
15
|
export const WS_ID_LOG = 0;
|
|
46
|
-
/**
|
|
47
|
-
* Websocket message ID indicating a refresh is needed.
|
|
48
|
-
* @constant {number}
|
|
49
|
-
*/
|
|
50
16
|
export const WS_ID_REFRESH_NEEDED = 1;
|
|
51
|
-
/**
|
|
52
|
-
* Websocket message ID indicating a restart is needed.
|
|
53
|
-
* @constant {number}
|
|
54
|
-
*/
|
|
55
17
|
export const WS_ID_RESTART_NEEDED = 2;
|
|
56
|
-
/**
|
|
57
|
-
* Websocket message ID indicating a cpu update.
|
|
58
|
-
* @constant {number}
|
|
59
|
-
*/
|
|
60
18
|
export const WS_ID_CPU_UPDATE = 3;
|
|
61
|
-
/**
|
|
62
|
-
* Websocket message ID indicating a memory update.
|
|
63
|
-
* @constant {number}
|
|
64
|
-
*/
|
|
65
19
|
export const WS_ID_MEMORY_UPDATE = 4;
|
|
66
|
-
/**
|
|
67
|
-
* Websocket message ID indicating an uptime update.
|
|
68
|
-
* @constant {number}
|
|
69
|
-
*/
|
|
70
20
|
export const WS_ID_UPTIME_UPDATE = 5;
|
|
71
|
-
/**
|
|
72
|
-
* Websocket message ID indicating a memory update.
|
|
73
|
-
* @constant {number}
|
|
74
|
-
*/
|
|
75
21
|
export const WS_ID_SNACKBAR = 6;
|
|
76
|
-
/**
|
|
77
|
-
* Websocket message ID indicating a memory update.
|
|
78
|
-
* @constant {number}
|
|
79
|
-
*/
|
|
80
22
|
export const WS_ID_UPDATE_NEEDED = 7;
|
|
81
|
-
|
|
82
|
-
* Websocket message ID indicating a shelly system update.
|
|
83
|
-
* check:
|
|
84
|
-
* curl -k http://127.0.0.1:8101/api/updates/sys/check
|
|
85
|
-
* perform:
|
|
86
|
-
* curl -k http://127.0.0.1:8101/api/updates/sys/perform
|
|
87
|
-
* @constant {number}
|
|
88
|
-
*/
|
|
23
|
+
export const WS_ID_STATEUPDATE = 8;
|
|
89
24
|
export const WS_ID_SHELLY_SYS_UPDATE = 100;
|
|
90
|
-
/**
|
|
91
|
-
* Websocket message ID indicating a shelly main update.
|
|
92
|
-
* check:
|
|
93
|
-
* curl -k http://127.0.0.1:8101/api/updates/main/check
|
|
94
|
-
* perform:
|
|
95
|
-
* curl -k http://127.0.0.1:8101/api/updates/main/perform
|
|
96
|
-
* @constant {number}
|
|
97
|
-
*/
|
|
98
25
|
export const WS_ID_SHELLY_MAIN_UPDATE = 101;
|
|
99
26
|
export class Frontend {
|
|
100
27
|
matterbridge;
|
|
@@ -112,7 +39,7 @@ export class Frontend {
|
|
|
112
39
|
memoryTimeout;
|
|
113
40
|
constructor(matterbridge) {
|
|
114
41
|
this.matterbridge = matterbridge;
|
|
115
|
-
this.log = new AnsiLogger({ logName: 'Frontend', logTimestampFormat: 4
|
|
42
|
+
this.log = new AnsiLogger({ logName: 'Frontend', logTimestampFormat: 4, logLevel: hasParameter('debug') ? "debug" : "info" });
|
|
116
43
|
}
|
|
117
44
|
set logLevel(logLevel) {
|
|
118
45
|
this.log.logLevel = logLevel;
|
|
@@ -120,25 +47,13 @@ export class Frontend {
|
|
|
120
47
|
async start(port = 8283) {
|
|
121
48
|
this.port = port;
|
|
122
49
|
this.log.debug(`Initializing the frontend ${hasParameter('ssl') ? 'https' : 'http'} server on port ${YELLOW}${this.port}${db}`);
|
|
123
|
-
// Initialize multer with the upload directory
|
|
124
50
|
const uploadDir = path.join(this.matterbridge.matterbridgeDirectory, 'uploads');
|
|
125
51
|
await fs.mkdir(uploadDir, { recursive: true });
|
|
126
52
|
const upload = multer({ dest: uploadDir });
|
|
127
|
-
// Create the express app that serves the frontend
|
|
128
53
|
this.expressApp = express();
|
|
129
|
-
// Log all requests to the server for debugging
|
|
130
|
-
/*
|
|
131
|
-
this.expressApp.use((req, res, next) => {
|
|
132
|
-
this.log.debug(`Received request on expressApp: ${req.method} ${req.url}`);
|
|
133
|
-
next();
|
|
134
|
-
});
|
|
135
|
-
*/
|
|
136
|
-
// Serve static files from '/static' endpoint
|
|
137
54
|
this.expressApp.use(express.static(path.join(this.matterbridge.rootDirectory, 'frontend/build')));
|
|
138
55
|
if (!hasParameter('ssl')) {
|
|
139
|
-
// Create an HTTP server and attach the express app
|
|
140
56
|
this.httpServer = createServer(this.expressApp);
|
|
141
|
-
// Listen on the specified port
|
|
142
57
|
if (hasParameter('ingress')) {
|
|
143
58
|
this.httpServer.listen(this.port, '0.0.0.0', () => {
|
|
144
59
|
this.log.info(`The frontend http server is listening on ${UNDERLINE}http://0.0.0.0:${this.port}${UNDERLINEOFF}${rs}`);
|
|
@@ -152,7 +67,6 @@ export class Frontend {
|
|
|
152
67
|
this.log.info(`The frontend http server is listening on ${UNDERLINE}http://[${this.matterbridge.systemInformation.ipv6Address}]:${this.port}${UNDERLINEOFF}${rs}`);
|
|
153
68
|
});
|
|
154
69
|
}
|
|
155
|
-
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
156
70
|
this.httpServer.on('error', (error) => {
|
|
157
71
|
this.log.error(`Frontend http server error listening on ${this.port}`);
|
|
158
72
|
switch (error.code) {
|
|
@@ -168,7 +82,6 @@ export class Frontend {
|
|
|
168
82
|
});
|
|
169
83
|
}
|
|
170
84
|
else {
|
|
171
|
-
// Load the SSL certificate, the private key and optionally the CA certificate
|
|
172
85
|
let cert;
|
|
173
86
|
try {
|
|
174
87
|
cert = await fs.readFile(path.join(this.matterbridge.matterbridgeDirectory, 'certs/cert.pem'), 'utf8');
|
|
@@ -196,9 +109,7 @@ export class Frontend {
|
|
|
196
109
|
this.log.info(`CA certificate file ${path.join(this.matterbridge.matterbridgeDirectory, 'certs/ca.pem')} not loaded: ${error}`);
|
|
197
110
|
}
|
|
198
111
|
const serverOptions = { cert, key, ca };
|
|
199
|
-
// Create an HTTPS server with the SSL certificate and private key (ca is optional) and attach the express app
|
|
200
112
|
this.httpsServer = https.createServer(serverOptions, this.expressApp);
|
|
201
|
-
// Listen on the specified port
|
|
202
113
|
if (hasParameter('ingress')) {
|
|
203
114
|
this.httpsServer.listen(this.port, '0.0.0.0', () => {
|
|
204
115
|
this.log.info(`The frontend https server is listening on ${UNDERLINE}https://0.0.0.0:${this.port}${UNDERLINEOFF}${rs}`);
|
|
@@ -212,7 +123,6 @@ export class Frontend {
|
|
|
212
123
|
this.log.info(`The frontend https server is listening on ${UNDERLINE}https://[${this.matterbridge.systemInformation.ipv6Address}]:${this.port}${UNDERLINEOFF}${rs}`);
|
|
213
124
|
});
|
|
214
125
|
}
|
|
215
|
-
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
216
126
|
this.httpsServer.on('error', (error) => {
|
|
217
127
|
this.log.error(`Frontend https server error listening on ${this.port}`);
|
|
218
128
|
switch (error.code) {
|
|
@@ -229,18 +139,16 @@ export class Frontend {
|
|
|
229
139
|
}
|
|
230
140
|
if (this.initializeError)
|
|
231
141
|
return;
|
|
232
|
-
// Create a WebSocket server and attach it to the http or https server
|
|
233
142
|
const wssPort = this.port;
|
|
234
143
|
const wssHost = hasParameter('ssl') ? `wss://${this.matterbridge.systemInformation.ipv4Address}:${wssPort}` : `ws://${this.matterbridge.systemInformation.ipv4Address}:${wssPort}`;
|
|
235
144
|
this.webSocketServer = new WebSocketServer(hasParameter('ssl') ? { server: this.httpsServer } : { server: this.httpServer });
|
|
236
145
|
this.webSocketServer.on('connection', (ws, request) => {
|
|
237
146
|
const clientIp = request.socket.remoteAddress;
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
callbackLogLevel = "debug" /* LogLevel.DEBUG */;
|
|
147
|
+
let callbackLogLevel = "notice";
|
|
148
|
+
if (this.matterbridge.matterbridgeInformation.loggerLevel === "info" || this.matterbridge.matterbridgeInformation.matterLoggerLevel === MatterLogLevel.INFO)
|
|
149
|
+
callbackLogLevel = "info";
|
|
150
|
+
if (this.matterbridge.matterbridgeInformation.loggerLevel === "debug" || this.matterbridge.matterbridgeInformation.matterLoggerLevel === MatterLogLevel.DEBUG)
|
|
151
|
+
callbackLogLevel = "debug";
|
|
244
152
|
AnsiLogger.setGlobalCallback(this.wssSendMessage.bind(this), callbackLogLevel);
|
|
245
153
|
this.log.debug(`WebSocketServer logger global callback set to ${callbackLogLevel}`);
|
|
246
154
|
this.log.info(`WebSocketServer client "${clientIp}" connected to Matterbridge`);
|
|
@@ -274,7 +182,6 @@ export class Frontend {
|
|
|
274
182
|
this.webSocketServer.on('error', (ws, error) => {
|
|
275
183
|
this.log.error(`WebSocketServer error: ${error}`);
|
|
276
184
|
});
|
|
277
|
-
// Subscribe to cli events
|
|
278
185
|
const { cliEmitter } = await import('./cli.js');
|
|
279
186
|
cliEmitter.on('uptime', (systemUptime, processUptime) => {
|
|
280
187
|
this.wssSendUptimeUpdate(systemUptime, processUptime);
|
|
@@ -285,7 +192,6 @@ export class Frontend {
|
|
|
285
192
|
cliEmitter.on('cpu', (cpuUsage) => {
|
|
286
193
|
this.wssSendCpuUpdate(cpuUsage);
|
|
287
194
|
});
|
|
288
|
-
// Endpoint to validate login code
|
|
289
195
|
this.expressApp.post('/api/login', express.json(), async (req, res) => {
|
|
290
196
|
const { password } = req.body;
|
|
291
197
|
this.log.debug('The frontend sent /api/login', password);
|
|
@@ -304,27 +210,23 @@ export class Frontend {
|
|
|
304
210
|
this.log.warn('/api/login error wrong password');
|
|
305
211
|
res.json({ valid: false });
|
|
306
212
|
}
|
|
307
|
-
// eslint-disable-next-line @typescript-eslint/no-unused-vars
|
|
308
213
|
}
|
|
309
214
|
catch (error) {
|
|
310
215
|
this.log.error('/api/login error getting password');
|
|
311
216
|
res.json({ valid: false });
|
|
312
217
|
}
|
|
313
218
|
});
|
|
314
|
-
// Endpoint to provide health check
|
|
315
219
|
this.expressApp.get('/health', (req, res) => {
|
|
316
220
|
this.log.debug('Express received /health');
|
|
317
221
|
const healthStatus = {
|
|
318
|
-
status: 'ok',
|
|
319
|
-
uptime: process.uptime(),
|
|
320
|
-
timestamp: new Date().toISOString(),
|
|
222
|
+
status: 'ok',
|
|
223
|
+
uptime: process.uptime(),
|
|
224
|
+
timestamp: new Date().toISOString(),
|
|
321
225
|
};
|
|
322
226
|
res.status(200).json(healthStatus);
|
|
323
227
|
});
|
|
324
|
-
// Endpoint to provide memory usage details
|
|
325
228
|
this.expressApp.get('/memory', async (req, res) => {
|
|
326
229
|
this.log.debug('Express received /memory');
|
|
327
|
-
// Memory usage from process
|
|
328
230
|
const memoryUsageRaw = process.memoryUsage();
|
|
329
231
|
const memoryUsage = {
|
|
330
232
|
rss: this.formatMemoryUsage(memoryUsageRaw.rss),
|
|
@@ -333,13 +235,10 @@ export class Frontend {
|
|
|
333
235
|
external: this.formatMemoryUsage(memoryUsageRaw.external),
|
|
334
236
|
arrayBuffers: this.formatMemoryUsage(memoryUsageRaw.arrayBuffers),
|
|
335
237
|
};
|
|
336
|
-
// V8 heap statistics
|
|
337
238
|
const { default: v8 } = await import('node:v8');
|
|
338
239
|
const heapStatsRaw = v8.getHeapStatistics();
|
|
339
240
|
const heapSpacesRaw = v8.getHeapSpaceStatistics();
|
|
340
|
-
// Format heapStats
|
|
341
241
|
const heapStats = Object.fromEntries(Object.entries(heapStatsRaw).map(([key, value]) => [key, this.formatMemoryUsage(value)]));
|
|
342
|
-
// Format heapSpaces
|
|
343
242
|
const heapSpaces = heapSpacesRaw.map((space) => ({
|
|
344
243
|
...space,
|
|
345
244
|
space_size: this.formatMemoryUsage(space.space_size),
|
|
@@ -357,7 +256,6 @@ export class Frontend {
|
|
|
357
256
|
};
|
|
358
257
|
res.status(200).json(memoryReport);
|
|
359
258
|
});
|
|
360
|
-
// Endpoint to start advertising the server node
|
|
361
259
|
this.expressApp.get('/api/advertise', express.json(), async (req, res) => {
|
|
362
260
|
const pairingCodes = await this.matterbridge.advertiseServerNode(this.matterbridge.serverNode);
|
|
363
261
|
if (pairingCodes) {
|
|
@@ -368,22 +266,18 @@ export class Frontend {
|
|
|
368
266
|
res.status(500).json({ error: 'Failed to generate pairing codes' });
|
|
369
267
|
}
|
|
370
268
|
});
|
|
371
|
-
// Endpoint to provide settings
|
|
372
269
|
this.expressApp.get('/api/settings', express.json(), async (req, res) => {
|
|
373
270
|
this.log.debug('The frontend sent /api/settings');
|
|
374
271
|
res.json(await this.getApiSettings());
|
|
375
272
|
});
|
|
376
|
-
// Endpoint to provide plugins
|
|
377
273
|
this.expressApp.get('/api/plugins', async (req, res) => {
|
|
378
274
|
this.log.debug('The frontend sent /api/plugins');
|
|
379
275
|
res.json(this.getBaseRegisteredPlugins());
|
|
380
276
|
});
|
|
381
|
-
// Endpoint to provide devices
|
|
382
277
|
this.expressApp.get('/api/devices', (req, res) => {
|
|
383
278
|
this.log.debug('The frontend sent /api/devices');
|
|
384
279
|
const devices = [];
|
|
385
280
|
this.matterbridge.devices.forEach(async (device) => {
|
|
386
|
-
// Check if the device has the required properties
|
|
387
281
|
if (!device.plugin || !device.name || !device.deviceName || !device.serialNumber || !device.uniqueId || !device.lifecycle.isReady)
|
|
388
282
|
return;
|
|
389
283
|
const cluster = this.getClusterTextFromDevice(device);
|
|
@@ -402,7 +296,6 @@ export class Frontend {
|
|
|
402
296
|
});
|
|
403
297
|
res.json(devices);
|
|
404
298
|
});
|
|
405
|
-
// Endpoint to provide the cluster servers of the devices
|
|
406
299
|
this.expressApp.get('/api/devices_clusters/:selectedPluginName/:selectedDeviceEndpoint', (req, res) => {
|
|
407
300
|
const selectedPluginName = req.params.selectedPluginName;
|
|
408
301
|
const selectedDeviceEndpoint = parseInt(req.params.selectedDeviceEndpoint, 10);
|
|
@@ -475,7 +368,6 @@ export class Frontend {
|
|
|
475
368
|
});
|
|
476
369
|
res.json(data);
|
|
477
370
|
});
|
|
478
|
-
// Endpoint to view the log
|
|
479
371
|
this.expressApp.get('/api/view-log', async (req, res) => {
|
|
480
372
|
this.log.debug('The frontend sent /api/log');
|
|
481
373
|
try {
|
|
@@ -488,12 +380,10 @@ export class Frontend {
|
|
|
488
380
|
res.status(500).send('Error reading log file');
|
|
489
381
|
}
|
|
490
382
|
});
|
|
491
|
-
// Endpoint to download the matterbridge log
|
|
492
383
|
this.expressApp.get('/api/download-mblog', async (req, res) => {
|
|
493
384
|
this.log.debug('The frontend sent /api/download-mblog');
|
|
494
385
|
try {
|
|
495
386
|
await fs.access(path.join(this.matterbridge.matterbridgeDirectory, this.matterbridge.matterbrideLoggerFile), fs.constants.F_OK);
|
|
496
|
-
// eslint-disable-next-line @typescript-eslint/no-unused-vars
|
|
497
387
|
}
|
|
498
388
|
catch (error) {
|
|
499
389
|
fs.appendFile(path.join(this.matterbridge.matterbridgeDirectory, this.matterbridge.matterbrideLoggerFile), 'Enable the log on file in the settings to enable the file logger');
|
|
@@ -505,12 +395,10 @@ export class Frontend {
|
|
|
505
395
|
}
|
|
506
396
|
});
|
|
507
397
|
});
|
|
508
|
-
// Endpoint to download the matter log
|
|
509
398
|
this.expressApp.get('/api/download-mjlog', async (req, res) => {
|
|
510
399
|
this.log.debug('The frontend sent /api/download-mjlog');
|
|
511
400
|
try {
|
|
512
401
|
await fs.access(path.join(this.matterbridge.matterbridgeDirectory, this.matterbridge.matterLoggerFile), fs.constants.F_OK);
|
|
513
|
-
// eslint-disable-next-line @typescript-eslint/no-unused-vars
|
|
514
402
|
}
|
|
515
403
|
catch (error) {
|
|
516
404
|
fs.appendFile(path.join(this.matterbridge.matterbridgeDirectory, this.matterbridge.matterLoggerFile), 'Enable the log on file in the settings to enable the file logger');
|
|
@@ -522,12 +410,10 @@ export class Frontend {
|
|
|
522
410
|
}
|
|
523
411
|
});
|
|
524
412
|
});
|
|
525
|
-
// Endpoint to download the matter log
|
|
526
413
|
this.expressApp.get('/api/shellydownloadsystemlog', async (req, res) => {
|
|
527
414
|
this.log.debug('The frontend sent /api/shellydownloadsystemlog');
|
|
528
415
|
try {
|
|
529
416
|
await fs.access(path.join(this.matterbridge.matterbridgeDirectory, 'shelly.log'), fs.constants.F_OK);
|
|
530
|
-
// eslint-disable-next-line @typescript-eslint/no-unused-vars
|
|
531
417
|
}
|
|
532
418
|
catch (error) {
|
|
533
419
|
fs.appendFile(path.join(this.matterbridge.matterbridgeDirectory, 'shelly.log'), 'Create the Shelly system log before downloading it.');
|
|
@@ -539,7 +425,6 @@ export class Frontend {
|
|
|
539
425
|
}
|
|
540
426
|
});
|
|
541
427
|
});
|
|
542
|
-
// Endpoint to download the matter storage file
|
|
543
428
|
this.expressApp.get('/api/download-mjstorage', async (req, res) => {
|
|
544
429
|
this.log.debug('The frontend sent /api/download-mjstorage');
|
|
545
430
|
await createZip(path.join(os.tmpdir(), `matterbridge.${this.matterbridge.matterStorageName}.zip`), path.join(this.matterbridge.matterbridgeDirectory, this.matterbridge.matterStorageName));
|
|
@@ -550,7 +435,6 @@ export class Frontend {
|
|
|
550
435
|
}
|
|
551
436
|
});
|
|
552
437
|
});
|
|
553
|
-
// Endpoint to download the matterbridge storage directory
|
|
554
438
|
this.expressApp.get('/api/download-mbstorage', async (req, res) => {
|
|
555
439
|
this.log.debug('The frontend sent /api/download-mbstorage');
|
|
556
440
|
await createZip(path.join(os.tmpdir(), `matterbridge.${this.matterbridge.nodeStorageName}.zip`), path.join(this.matterbridge.matterbridgeDirectory, this.matterbridge.nodeStorageName));
|
|
@@ -561,7 +445,6 @@ export class Frontend {
|
|
|
561
445
|
}
|
|
562
446
|
});
|
|
563
447
|
});
|
|
564
|
-
// Endpoint to download the matterbridge plugin directory
|
|
565
448
|
this.expressApp.get('/api/download-pluginstorage', async (req, res) => {
|
|
566
449
|
this.log.debug('The frontend sent /api/download-pluginstorage');
|
|
567
450
|
await createZip(path.join(os.tmpdir(), `matterbridge.pluginstorage.zip`), this.matterbridge.matterbridgePluginDirectory);
|
|
@@ -572,11 +455,9 @@ export class Frontend {
|
|
|
572
455
|
}
|
|
573
456
|
});
|
|
574
457
|
});
|
|
575
|
-
// Endpoint to download the matterbridge plugin config files
|
|
576
458
|
this.expressApp.get('/api/download-pluginconfig', async (req, res) => {
|
|
577
459
|
this.log.debug('The frontend sent /api/download-pluginconfig');
|
|
578
460
|
await createZip(path.join(os.tmpdir(), `matterbridge.pluginconfig.zip`), path.relative(process.cwd(), path.join(this.matterbridge.matterbridgeDirectory, '*.config.json')));
|
|
579
|
-
// await createZip(path.join(os.tmpdir(), `matterbridge.pluginconfig.zip`), path.relative(process.cwd(), path.join(this.matterbridge.matterbridgeDirectory, 'certs', '*.*')), path.relative(process.cwd(), path.join(this.matterbridge.matterbridgeDirectory, '*.config.json')));
|
|
580
461
|
res.download(path.join(os.tmpdir(), `matterbridge.pluginconfig.zip`), `matterbridge.pluginconfig.zip`, (error) => {
|
|
581
462
|
if (error) {
|
|
582
463
|
this.log.error(`Error downloading file matterbridge.pluginstorage.zip: ${error instanceof Error ? error.message : error}`);
|
|
@@ -584,7 +465,6 @@ export class Frontend {
|
|
|
584
465
|
}
|
|
585
466
|
});
|
|
586
467
|
});
|
|
587
|
-
// Endpoint to download the matterbridge plugin config files
|
|
588
468
|
this.expressApp.get('/api/download-backup', async (req, res) => {
|
|
589
469
|
this.log.debug('The frontend sent /api/download-backup');
|
|
590
470
|
res.download(path.join(os.tmpdir(), `matterbridge.backup.zip`), `matterbridge.backup.zip`, (error) => {
|
|
@@ -594,7 +474,6 @@ export class Frontend {
|
|
|
594
474
|
}
|
|
595
475
|
});
|
|
596
476
|
});
|
|
597
|
-
// Endpoint to receive commands
|
|
598
477
|
this.expressApp.post('/api/command/:command/:param', express.json(), async (req, res) => {
|
|
599
478
|
const command = req.params.command;
|
|
600
479
|
let param = req.params.param;
|
|
@@ -604,15 +483,13 @@ export class Frontend {
|
|
|
604
483
|
return;
|
|
605
484
|
}
|
|
606
485
|
this.log.debug(`Received frontend command: ${command}:${param}`);
|
|
607
|
-
// Handle the command setpassword from Settings
|
|
608
486
|
if (command === 'setpassword') {
|
|
609
|
-
const password = param.slice(1, -1);
|
|
487
|
+
const password = param.slice(1, -1);
|
|
610
488
|
this.log.debug('setpassword', param, password);
|
|
611
489
|
await this.matterbridge.nodeContext?.set('password', password);
|
|
612
490
|
res.json({ message: 'Command received' });
|
|
613
491
|
return;
|
|
614
492
|
}
|
|
615
|
-
// Handle the command setbridgemode from Settings
|
|
616
493
|
if (command === 'setbridgemode') {
|
|
617
494
|
this.log.debug(`setbridgemode: ${param}`);
|
|
618
495
|
this.wssSendRestartRequired();
|
|
@@ -620,7 +497,6 @@ export class Frontend {
|
|
|
620
497
|
res.json({ message: 'Command received' });
|
|
621
498
|
return;
|
|
622
499
|
}
|
|
623
|
-
// Handle the command backup from Settings
|
|
624
500
|
if (command === 'backup') {
|
|
625
501
|
this.log.notice(`Prepairing the backup...`);
|
|
626
502
|
await createZip(path.join(os.tmpdir(), `matterbridge.backup.zip`), path.join(this.matterbridge.matterbridgeDirectory), path.join(this.matterbridge.matterbridgePluginDirectory));
|
|
@@ -629,33 +505,31 @@ export class Frontend {
|
|
|
629
505
|
res.json({ message: 'Command received' });
|
|
630
506
|
return;
|
|
631
507
|
}
|
|
632
|
-
// Handle the command setmbloglevel from Settings
|
|
633
508
|
if (command === 'setmbloglevel') {
|
|
634
509
|
this.log.debug('Matterbridge log level:', param);
|
|
635
510
|
if (param === 'Debug') {
|
|
636
|
-
this.log.logLevel = "debug"
|
|
511
|
+
this.log.logLevel = "debug";
|
|
637
512
|
}
|
|
638
513
|
else if (param === 'Info') {
|
|
639
|
-
this.log.logLevel = "info"
|
|
514
|
+
this.log.logLevel = "info";
|
|
640
515
|
}
|
|
641
516
|
else if (param === 'Notice') {
|
|
642
|
-
this.log.logLevel = "notice"
|
|
517
|
+
this.log.logLevel = "notice";
|
|
643
518
|
}
|
|
644
519
|
else if (param === 'Warn') {
|
|
645
|
-
this.log.logLevel = "warn"
|
|
520
|
+
this.log.logLevel = "warn";
|
|
646
521
|
}
|
|
647
522
|
else if (param === 'Error') {
|
|
648
|
-
this.log.logLevel = "error"
|
|
523
|
+
this.log.logLevel = "error";
|
|
649
524
|
}
|
|
650
525
|
else if (param === 'Fatal') {
|
|
651
|
-
this.log.logLevel = "fatal"
|
|
526
|
+
this.log.logLevel = "fatal";
|
|
652
527
|
}
|
|
653
528
|
await this.matterbridge.nodeContext?.set('matterbridgeLogLevel', this.log.logLevel);
|
|
654
529
|
await this.matterbridge.setLogLevel(this.log.logLevel);
|
|
655
530
|
res.json({ message: 'Command received' });
|
|
656
531
|
return;
|
|
657
532
|
}
|
|
658
|
-
// Handle the command setmbloglevel from Settings
|
|
659
533
|
if (command === 'setmjloglevel') {
|
|
660
534
|
this.log.debug('Matter.js log level:', param);
|
|
661
535
|
if (param === 'Debug') {
|
|
@@ -680,34 +554,30 @@ export class Frontend {
|
|
|
680
554
|
res.json({ message: 'Command received' });
|
|
681
555
|
return;
|
|
682
556
|
}
|
|
683
|
-
// Handle the command setmdnsinterface from Settings
|
|
684
557
|
if (command === 'setmdnsinterface') {
|
|
685
|
-
param = param.slice(1, -1);
|
|
558
|
+
param = param.slice(1, -1);
|
|
686
559
|
this.matterbridge.matterbridgeInformation.mattermdnsinterface = param;
|
|
687
560
|
this.log.debug('Matter.js mdns interface:', param === '' ? 'All interfaces' : param);
|
|
688
561
|
await this.matterbridge.nodeContext?.set('mattermdnsinterface', param);
|
|
689
562
|
res.json({ message: 'Command received' });
|
|
690
563
|
return;
|
|
691
564
|
}
|
|
692
|
-
// Handle the command setipv4address from Settings
|
|
693
565
|
if (command === 'setipv4address') {
|
|
694
|
-
param = param.slice(1, -1);
|
|
566
|
+
param = param.slice(1, -1);
|
|
695
567
|
this.matterbridge.matterbridgeInformation.matteripv4address = param;
|
|
696
568
|
this.log.debug('Matter.js ipv4 address:', param === '' ? 'All ipv4 addresses' : param);
|
|
697
569
|
await this.matterbridge.nodeContext?.set('matteripv4address', param);
|
|
698
570
|
res.json({ message: 'Command received' });
|
|
699
571
|
return;
|
|
700
572
|
}
|
|
701
|
-
// Handle the command setipv6address from Settings
|
|
702
573
|
if (command === 'setipv6address') {
|
|
703
|
-
param = param.slice(1, -1);
|
|
574
|
+
param = param.slice(1, -1);
|
|
704
575
|
this.matterbridge.matterbridgeInformation.matteripv6address = param;
|
|
705
576
|
this.log.debug('Matter.js ipv6 address:', param === '' ? 'All ipv6 addresses' : param);
|
|
706
577
|
await this.matterbridge.nodeContext?.set('matteripv6address', param);
|
|
707
578
|
res.json({ message: 'Command received' });
|
|
708
579
|
return;
|
|
709
580
|
}
|
|
710
|
-
// Handle the command setmatterport from Settings
|
|
711
581
|
if (command === 'setmatterport') {
|
|
712
582
|
const port = Math.min(Math.max(parseInt(param), 5540), 5560);
|
|
713
583
|
this.matterbridge.matterbridgeInformation.matterPort = port;
|
|
@@ -716,7 +586,6 @@ export class Frontend {
|
|
|
716
586
|
res.json({ message: 'Command received' });
|
|
717
587
|
return;
|
|
718
588
|
}
|
|
719
|
-
// Handle the command setmatterdiscriminator from Settings
|
|
720
589
|
if (command === 'setmatterdiscriminator') {
|
|
721
590
|
const discriminator = Math.min(Math.max(parseInt(param), 1000), 4095);
|
|
722
591
|
this.matterbridge.matterbridgeInformation.matterDiscriminator = discriminator;
|
|
@@ -725,7 +594,6 @@ export class Frontend {
|
|
|
725
594
|
res.json({ message: 'Command received' });
|
|
726
595
|
return;
|
|
727
596
|
}
|
|
728
|
-
// Handle the command setmatterpasscode from Settings
|
|
729
597
|
if (command === 'setmatterpasscode') {
|
|
730
598
|
const passcode = Math.min(Math.max(parseInt(param), 10000000), 90000000);
|
|
731
599
|
this.matterbridge.matterbridgeInformation.matterPasscode = passcode;
|
|
@@ -734,20 +602,17 @@ export class Frontend {
|
|
|
734
602
|
res.json({ message: 'Command received' });
|
|
735
603
|
return;
|
|
736
604
|
}
|
|
737
|
-
// Handle the command setmbloglevel from Settings
|
|
738
605
|
if (command === 'setmblogfile') {
|
|
739
606
|
this.log.debug('Matterbridge file log:', param);
|
|
740
607
|
this.matterbridge.matterbridgeInformation.fileLogger = param === 'true';
|
|
741
608
|
await this.matterbridge.nodeContext?.set('matterbridgeFileLog', param === 'true');
|
|
742
|
-
// Create the file logger for matterbridge
|
|
743
609
|
if (param === 'true')
|
|
744
|
-
AnsiLogger.setGlobalLogfile(path.join(this.matterbridge.matterbridgeDirectory, this.matterbridge.matterbrideLoggerFile), "debug"
|
|
610
|
+
AnsiLogger.setGlobalLogfile(path.join(this.matterbridge.matterbridgeDirectory, this.matterbridge.matterbrideLoggerFile), "debug", true);
|
|
745
611
|
else
|
|
746
612
|
AnsiLogger.setGlobalLogfile(undefined);
|
|
747
613
|
res.json({ message: 'Command received' });
|
|
748
614
|
return;
|
|
749
615
|
}
|
|
750
|
-
// Handle the command setmbloglevel from Settings
|
|
751
616
|
if (command === 'setmjlogfile') {
|
|
752
617
|
this.log.debug('Matter file log:', param);
|
|
753
618
|
this.matterbridge.matterbridgeInformation.matterFileLogger = param === 'true';
|
|
@@ -774,48 +639,40 @@ export class Frontend {
|
|
|
774
639
|
res.json({ message: 'Command received' });
|
|
775
640
|
return;
|
|
776
641
|
}
|
|
777
|
-
// Handle the command unregister from Settings
|
|
778
642
|
if (command === 'unregister') {
|
|
779
643
|
await this.matterbridge.unregisterAndShutdownProcess();
|
|
780
644
|
res.json({ message: 'Command received' });
|
|
781
645
|
return;
|
|
782
646
|
}
|
|
783
|
-
// Handle the command reset from Settings
|
|
784
647
|
if (command === 'reset') {
|
|
785
648
|
await this.matterbridge.shutdownProcessAndReset();
|
|
786
649
|
res.json({ message: 'Command received' });
|
|
787
650
|
return;
|
|
788
651
|
}
|
|
789
|
-
// Handle the command factoryreset from Settings
|
|
790
652
|
if (command === 'factoryreset') {
|
|
791
653
|
await this.matterbridge.shutdownProcessAndFactoryReset();
|
|
792
654
|
res.json({ message: 'Command received' });
|
|
793
655
|
return;
|
|
794
656
|
}
|
|
795
|
-
// Handle the command shutdown from Header
|
|
796
657
|
if (command === 'shutdown') {
|
|
797
658
|
await this.matterbridge.shutdownProcess();
|
|
798
659
|
res.json({ message: 'Command received' });
|
|
799
660
|
return;
|
|
800
661
|
}
|
|
801
|
-
// Handle the command restart from Header
|
|
802
662
|
if (command === 'restart') {
|
|
803
663
|
await this.matterbridge.restartProcess();
|
|
804
664
|
res.json({ message: 'Command received' });
|
|
805
665
|
return;
|
|
806
666
|
}
|
|
807
|
-
// Handle the command update from Header
|
|
808
667
|
if (command === 'update') {
|
|
809
668
|
await this.matterbridge.updateProcess();
|
|
810
669
|
this.wssSendRestartRequired();
|
|
811
670
|
res.json({ message: 'Command received' });
|
|
812
671
|
return;
|
|
813
672
|
}
|
|
814
|
-
// Handle the command saveconfig from Home
|
|
815
673
|
if (command === 'saveconfig') {
|
|
816
674
|
param = param.replace(/\*/g, '\\');
|
|
817
675
|
this.log.info(`Saving config for plugin ${plg}${param}${nf}...`);
|
|
818
|
-
// console.log('Req.body:', JSON.stringify(req.body, null, 2));
|
|
819
676
|
if (!this.matterbridge.plugins.has(param)) {
|
|
820
677
|
this.log.warn(`Plugin ${plg}${param}${wr} not found in matterbridge`);
|
|
821
678
|
}
|
|
@@ -830,7 +687,6 @@ export class Frontend {
|
|
|
830
687
|
res.json({ message: 'Command received' });
|
|
831
688
|
return;
|
|
832
689
|
}
|
|
833
|
-
// Handle the command installplugin from Home
|
|
834
690
|
if (command === 'installplugin') {
|
|
835
691
|
param = param.replace(/\*/g, '\\');
|
|
836
692
|
this.log.info(`Installing plugin ${plg}${param}${nf}...`);
|
|
@@ -839,7 +695,6 @@ export class Frontend {
|
|
|
839
695
|
await this.matterbridge.spawnCommand('npm', ['install', '-g', param, '--omit=dev', '--verbose']);
|
|
840
696
|
this.log.info(`Plugin ${plg}${param}${nf} installed. Full restart required.`);
|
|
841
697
|
this.wssSendSnackbarMessage(`Installed package ${param}`);
|
|
842
|
-
// eslint-disable-next-line @typescript-eslint/no-unused-vars
|
|
843
698
|
}
|
|
844
699
|
catch (error) {
|
|
845
700
|
this.log.error(`Error installing plugin ${plg}${param}${er}`);
|
|
@@ -847,22 +702,17 @@ export class Frontend {
|
|
|
847
702
|
}
|
|
848
703
|
this.wssSendRestartRequired();
|
|
849
704
|
param = param.split('@')[0];
|
|
850
|
-
// Also add the plugin to matterbridge so no return!
|
|
851
705
|
if (param === 'matterbridge') {
|
|
852
|
-
// If we used the command installplugin to install a dev or a specific version of matterbridge we don't want to add it to matterbridge
|
|
853
706
|
res.json({ message: 'Command received' });
|
|
854
707
|
return;
|
|
855
708
|
}
|
|
856
709
|
}
|
|
857
|
-
// Handle the command addplugin from Home
|
|
858
710
|
if (command === 'addplugin' || command === 'installplugin') {
|
|
859
711
|
param = param.replace(/\*/g, '\\');
|
|
860
712
|
const plugin = await this.matterbridge.plugins.add(param);
|
|
861
713
|
if (plugin) {
|
|
862
714
|
this.wssSendSnackbarMessage(`Added plugin ${param}`);
|
|
863
715
|
if (this.matterbridge.bridgeMode === 'childbridge') {
|
|
864
|
-
// We don't know now if the plugin is a dynamic platform or an accessory platform so we create the server node and the aggregator node
|
|
865
|
-
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
866
716
|
this.matterbridge.createDynamicPlugin(plugin, true);
|
|
867
717
|
}
|
|
868
718
|
this.matterbridge.plugins.load(plugin, true, 'The plugin has been added', true).then(() => {
|
|
@@ -872,14 +722,13 @@ export class Frontend {
|
|
|
872
722
|
res.json({ message: 'Command received' });
|
|
873
723
|
return;
|
|
874
724
|
}
|
|
875
|
-
// Handle the command removeplugin from Home
|
|
876
725
|
if (command === 'removeplugin') {
|
|
877
726
|
if (!this.matterbridge.plugins.has(param)) {
|
|
878
727
|
this.log.warn(`Plugin ${plg}${param}${wr} not found in matterbridge`);
|
|
879
728
|
}
|
|
880
729
|
else {
|
|
881
730
|
const plugin = this.matterbridge.plugins.get(param);
|
|
882
|
-
await this.matterbridge.plugins.shutdown(plugin, 'The plugin has been removed.', true);
|
|
731
|
+
await this.matterbridge.plugins.shutdown(plugin, 'The plugin has been removed.', true);
|
|
883
732
|
await this.matterbridge.plugins.remove(param);
|
|
884
733
|
this.wssSendSnackbarMessage(`Removed plugin ${param}`);
|
|
885
734
|
this.wssSendRefreshRequired('plugins');
|
|
@@ -887,7 +736,6 @@ export class Frontend {
|
|
|
887
736
|
res.json({ message: 'Command received' });
|
|
888
737
|
return;
|
|
889
738
|
}
|
|
890
|
-
// Handle the command enableplugin from Home
|
|
891
739
|
if (command === 'enableplugin') {
|
|
892
740
|
if (!this.matterbridge.plugins.has(param)) {
|
|
893
741
|
this.log.warn(`Plugin ${plg}${param}${wr} not found in matterbridge`);
|
|
@@ -906,7 +754,6 @@ export class Frontend {
|
|
|
906
754
|
await this.matterbridge.plugins.enable(param);
|
|
907
755
|
this.wssSendSnackbarMessage(`Enabled plugin ${param}`);
|
|
908
756
|
if (this.matterbridge.bridgeMode === 'childbridge' && plugin.type === 'DynamicPlatform') {
|
|
909
|
-
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
910
757
|
this.matterbridge.createDynamicPlugin(plugin, true);
|
|
911
758
|
}
|
|
912
759
|
this.matterbridge.plugins.load(plugin, true, 'The plugin has been enabled', true).then(() => {
|
|
@@ -917,7 +764,6 @@ export class Frontend {
|
|
|
917
764
|
res.json({ message: 'Command received' });
|
|
918
765
|
return;
|
|
919
766
|
}
|
|
920
|
-
// Handle the command disableplugin from Home
|
|
921
767
|
if (command === 'disableplugin') {
|
|
922
768
|
if (!this.matterbridge.plugins.has(param)) {
|
|
923
769
|
this.log.warn(`Plugin ${plg}${param}${wr} not found in matterbridge`);
|
|
@@ -925,7 +771,7 @@ export class Frontend {
|
|
|
925
771
|
else {
|
|
926
772
|
const plugin = this.matterbridge.plugins.get(param);
|
|
927
773
|
if (plugin && plugin.enabled) {
|
|
928
|
-
await this.matterbridge.plugins.shutdown(plugin, 'The plugin has been disabled.', true);
|
|
774
|
+
await this.matterbridge.plugins.shutdown(plugin, 'The plugin has been disabled.', true);
|
|
929
775
|
await this.matterbridge.plugins.disable(param);
|
|
930
776
|
this.wssSendSnackbarMessage(`Disabled plugin ${param}`);
|
|
931
777
|
this.wssSendRefreshRequired('plugins');
|
|
@@ -943,13 +789,10 @@ export class Frontend {
|
|
|
943
789
|
res.status(400).send('Invalid request: file and filename are required');
|
|
944
790
|
return;
|
|
945
791
|
}
|
|
946
|
-
// Define the path where the plugin file will be saved
|
|
947
792
|
const filePath = path.join(this.matterbridge.matterbridgeDirectory, 'uploads', filename);
|
|
948
793
|
try {
|
|
949
|
-
// Move the uploaded file to the specified path
|
|
950
794
|
await fs.rename(file.path, filePath);
|
|
951
795
|
this.log.info(`File ${plg}${filename}${nf} uploaded successfully`);
|
|
952
|
-
// Install the plugin package
|
|
953
796
|
if (filename.endsWith('.tgz')) {
|
|
954
797
|
await this.matterbridge.spawnCommand('npm', ['install', '-g', filePath, '--omit=dev', '--verbose']);
|
|
955
798
|
this.log.info(`Plugin package ${plg}${filename}${nf} installed successfully. Full restart required.`);
|
|
@@ -965,7 +808,6 @@ export class Frontend {
|
|
|
965
808
|
res.status(500).send(`Error uploading or installing plugin package ${filename}`);
|
|
966
809
|
}
|
|
967
810
|
});
|
|
968
|
-
// Fallback for routing (must be the last route)
|
|
969
811
|
this.expressApp.get('*', (req, res) => {
|
|
970
812
|
this.log.debug('The frontend sent:', req.url);
|
|
971
813
|
this.log.debug('Response send file:', path.join(this.matterbridge.rootDirectory, 'frontend/build/index.html'));
|
|
@@ -974,31 +816,24 @@ export class Frontend {
|
|
|
974
816
|
this.log.debug(`Frontend initialized on port ${YELLOW}${this.port}${db} static ${UNDERLINE}${path.join(this.matterbridge.rootDirectory, 'frontend/build')}${UNDERLINEOFF}${rs}`);
|
|
975
817
|
}
|
|
976
818
|
async stop() {
|
|
977
|
-
// Remove all listeners from the cliEmitter
|
|
978
|
-
// cliEmitter.removeAllListeners();
|
|
979
|
-
// Close the http server
|
|
980
819
|
if (this.httpServer) {
|
|
981
820
|
this.httpServer.close();
|
|
982
821
|
this.httpServer.removeAllListeners();
|
|
983
822
|
this.httpServer = undefined;
|
|
984
823
|
this.log.debug('Frontend http server closed successfully');
|
|
985
824
|
}
|
|
986
|
-
// Close the https server
|
|
987
825
|
if (this.httpsServer) {
|
|
988
826
|
this.httpsServer.close();
|
|
989
827
|
this.httpsServer.removeAllListeners();
|
|
990
828
|
this.httpsServer = undefined;
|
|
991
829
|
this.log.debug('Frontend https server closed successfully');
|
|
992
830
|
}
|
|
993
|
-
// Remove listeners from the express app
|
|
994
831
|
if (this.expressApp) {
|
|
995
832
|
this.expressApp.removeAllListeners();
|
|
996
833
|
this.expressApp = undefined;
|
|
997
834
|
this.log.debug('Frontend app closed successfully');
|
|
998
835
|
}
|
|
999
|
-
// Close the WebSocket server
|
|
1000
836
|
if (this.webSocketServer) {
|
|
1001
|
-
// Close all active connections
|
|
1002
837
|
this.webSocketServer.clients.forEach((client) => {
|
|
1003
838
|
if (client.readyState === WebSocket.OPEN) {
|
|
1004
839
|
client.close();
|
|
@@ -1015,7 +850,6 @@ export class Frontend {
|
|
|
1015
850
|
this.webSocketServer = undefined;
|
|
1016
851
|
}
|
|
1017
852
|
}
|
|
1018
|
-
// Function to format bytes to KB, MB, or GB
|
|
1019
853
|
formatMemoryUsage = (bytes) => {
|
|
1020
854
|
if (bytes >= 1024 ** 3) {
|
|
1021
855
|
return `${(bytes / 1024 ** 3).toFixed(2)} GB`;
|
|
@@ -1027,7 +861,6 @@ export class Frontend {
|
|
|
1027
861
|
return `${(bytes / 1024).toFixed(2)} KB`;
|
|
1028
862
|
}
|
|
1029
863
|
};
|
|
1030
|
-
// Function to format system uptime with only the most significant unit
|
|
1031
864
|
formatOsUpTime = (seconds) => {
|
|
1032
865
|
if (seconds >= 86400) {
|
|
1033
866
|
const days = Math.floor(seconds / 86400);
|
|
@@ -1043,13 +876,8 @@ export class Frontend {
|
|
|
1043
876
|
}
|
|
1044
877
|
return `${seconds} second${seconds !== 1 ? 's' : ''}`;
|
|
1045
878
|
};
|
|
1046
|
-
/**
|
|
1047
|
-
* Retrieves the api settings data.
|
|
1048
|
-
* @returns {Promise<object>} A promise that resolve in the api settings object.
|
|
1049
|
-
*/
|
|
1050
879
|
async getApiSettings() {
|
|
1051
880
|
const { lastCpuUsage } = await import('./cli.js');
|
|
1052
|
-
// Update the system information
|
|
1053
881
|
this.matterbridge.systemInformation.totalMemory = this.formatMemoryUsage(os.totalmem());
|
|
1054
882
|
this.matterbridge.systemInformation.freeMemory = this.formatMemoryUsage(os.freemem());
|
|
1055
883
|
this.matterbridge.systemInformation.systemUptime = this.formatOsUpTime(os.uptime());
|
|
@@ -1058,7 +886,6 @@ export class Frontend {
|
|
|
1058
886
|
this.matterbridge.systemInformation.rss = this.formatMemoryUsage(process.memoryUsage().rss);
|
|
1059
887
|
this.matterbridge.systemInformation.heapTotal = this.formatMemoryUsage(process.memoryUsage().heapTotal);
|
|
1060
888
|
this.matterbridge.systemInformation.heapUsed = this.formatMemoryUsage(process.memoryUsage().heapUsed);
|
|
1061
|
-
// Update the matterbridge information
|
|
1062
889
|
this.matterbridge.matterbridgeInformation.bridgeMode = this.matterbridge.bridgeMode;
|
|
1063
890
|
this.matterbridge.matterbridgeInformation.restartMode = this.matterbridge.restartMode;
|
|
1064
891
|
this.matterbridge.matterbridgeInformation.loggerLevel = this.matterbridge.log.logLevel;
|
|
@@ -1077,11 +904,6 @@ export class Frontend {
|
|
|
1077
904
|
this.matterbridge.matterbridgeInformation.profile = this.matterbridge.profile;
|
|
1078
905
|
return { systemInformation: this.matterbridge.systemInformation, matterbridgeInformation: this.matterbridge.matterbridgeInformation };
|
|
1079
906
|
}
|
|
1080
|
-
/**
|
|
1081
|
-
* Retrieves the reachable attribute.
|
|
1082
|
-
* @param {MatterbridgeDevice} device - The MatterbridgeDevice object.
|
|
1083
|
-
* @returns {boolean} The reachable attribute.
|
|
1084
|
-
*/
|
|
1085
907
|
getReachability(device) {
|
|
1086
908
|
if (!device.lifecycle.isReady || device.construction.status !== Lifecycle.Status.Active)
|
|
1087
909
|
return false;
|
|
@@ -1091,11 +913,6 @@ export class Frontend {
|
|
|
1091
913
|
return true;
|
|
1092
914
|
return false;
|
|
1093
915
|
}
|
|
1094
|
-
/**
|
|
1095
|
-
* Retrieves the cluster text description from a given device.
|
|
1096
|
-
* @param {MatterbridgeDevice} device - The MatterbridgeDevice object.
|
|
1097
|
-
* @returns {string} The attributes description of the cluster servers in the device.
|
|
1098
|
-
*/
|
|
1099
916
|
getClusterTextFromDevice(device) {
|
|
1100
917
|
if (!device.lifecycle.isReady || device.construction.status !== Lifecycle.Status.Active)
|
|
1101
918
|
return '';
|
|
@@ -1136,7 +953,6 @@ export class Frontend {
|
|
|
1136
953
|
};
|
|
1137
954
|
let attributes = '';
|
|
1138
955
|
device.forEachAttribute((clusterName, clusterId, attributeName, attributeId, attributeValue) => {
|
|
1139
|
-
// console.log(`${device.deviceName} => Cluster: ${clusterName}-${clusterId} Attribute: ${attributeName}-${attributeId} Value(${typeof attributeValue}): ${attributeValue}`);
|
|
1140
956
|
if (typeof attributeValue === 'undefined')
|
|
1141
957
|
return;
|
|
1142
958
|
if (clusterName === 'onOff' && attributeName === 'onOff')
|
|
@@ -1214,13 +1030,8 @@ export class Frontend {
|
|
|
1214
1030
|
if (clusterName === 'userLabel' && attributeName === 'labelList')
|
|
1215
1031
|
attributes += `${getUserLabel(device)} `;
|
|
1216
1032
|
});
|
|
1217
|
-
// console.log(`${device.deviceName}.forEachAttribute: ${attributes}`);
|
|
1218
1033
|
return attributes.trimStart().trimEnd();
|
|
1219
1034
|
}
|
|
1220
|
-
/**
|
|
1221
|
-
* Retrieves the base registered plugins sanitized for res.json().
|
|
1222
|
-
* @returns {BaseRegisteredPlugin[]} An array of BaseRegisteredPlugin.
|
|
1223
|
-
*/
|
|
1224
1035
|
getBaseRegisteredPlugins() {
|
|
1225
1036
|
const baseRegisteredPlugins = [];
|
|
1226
1037
|
for (const plugin of this.matterbridge.plugins) {
|
|
@@ -1253,13 +1064,6 @@ export class Frontend {
|
|
|
1253
1064
|
}
|
|
1254
1065
|
return baseRegisteredPlugins;
|
|
1255
1066
|
}
|
|
1256
|
-
/**
|
|
1257
|
-
* Handles incoming websocket messages for the Matterbridge frontend.
|
|
1258
|
-
*
|
|
1259
|
-
* @param {WebSocket} client - The websocket client that sent the message.
|
|
1260
|
-
* @param {WebSocket.RawData} message - The raw data of the message received from the client.
|
|
1261
|
-
* @returns {Promise<void>} A promise that resolves when the message has been handled.
|
|
1262
|
-
*/
|
|
1263
1067
|
async wsMessageHandler(client, message) {
|
|
1264
1068
|
let data;
|
|
1265
1069
|
try {
|
|
@@ -1405,10 +1209,8 @@ export class Frontend {
|
|
|
1405
1209
|
else if (data.method === '/api/devices') {
|
|
1406
1210
|
const devices = [];
|
|
1407
1211
|
this.matterbridge.devices.forEach(async (device) => {
|
|
1408
|
-
// Filter by pluginName if provided
|
|
1409
1212
|
if (data.params.pluginName && data.params.pluginName !== device.plugin)
|
|
1410
1213
|
return;
|
|
1411
|
-
// Check if the device has the required properties
|
|
1412
1214
|
if (!device.plugin || !device.name || !device.deviceName || !device.serialNumber || !device.uniqueId || !device.lifecycle.isReady)
|
|
1413
1215
|
return;
|
|
1414
1216
|
const cluster = this.getClusterTextFromDevice(device);
|
|
@@ -1492,7 +1294,6 @@ export class Frontend {
|
|
|
1492
1294
|
});
|
|
1493
1295
|
endpointServer.getChildEndpoints().forEach((childEndpoint) => {
|
|
1494
1296
|
deviceTypes = [];
|
|
1495
|
-
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
1496
1297
|
const name = childEndpoint.endpoint?.id;
|
|
1497
1298
|
const clusterServers = childEndpoint.getAllClusterServers();
|
|
1498
1299
|
clusterServers.forEach((clusterServer) => {
|
|
@@ -1546,7 +1347,6 @@ export class Frontend {
|
|
|
1546
1347
|
client.send(JSON.stringify({ id: data.id, method: data.method, src: 'Matterbridge', dst: data.src, error: 'Plugin not found in /api/select' }));
|
|
1547
1348
|
return;
|
|
1548
1349
|
}
|
|
1549
|
-
// const selectDeviceValues = plugin.platform?.selectDevice ? Array.from(plugin.platform.selectDevice.values()).sort((keyA, keyB) => keyA.name.localeCompare(keyB.name)) : [];
|
|
1550
1350
|
const selectDeviceValues = plugin.platform?.getSelectDevices().sort((keyA, keyB) => keyA.name.localeCompare(keyB.name));
|
|
1551
1351
|
client.send(JSON.stringify({ id: data.id, method: data.method, src: 'Matterbridge', dst: data.src, plugin: data.params.plugin, response: selectDeviceValues }));
|
|
1552
1352
|
return;
|
|
@@ -1561,7 +1361,6 @@ export class Frontend {
|
|
|
1561
1361
|
client.send(JSON.stringify({ id: data.id, method: data.method, src: 'Matterbridge', dst: data.src, error: 'Plugin not found in /api/select/entities' }));
|
|
1562
1362
|
return;
|
|
1563
1363
|
}
|
|
1564
|
-
// const selectEntityValues = plugin.platform?.selectDevice ? Array.from(plugin.platform.selectEntity.values()).sort((keyA, keyB) => keyA.name.localeCompare(keyB.name)) : [];
|
|
1565
1364
|
const selectEntityValues = plugin.platform?.getSelectEntities().sort((keyA, keyB) => keyA.name.localeCompare(keyB.name));
|
|
1566
1365
|
client.send(JSON.stringify({ id: data.id, method: data.method, src: 'Matterbridge', dst: data.src, plugin: data.params.plugin, response: selectEntityValues }));
|
|
1567
1366
|
return;
|
|
@@ -1582,13 +1381,11 @@ export class Frontend {
|
|
|
1582
1381
|
if (config.postfix) {
|
|
1583
1382
|
data.params.serial = data.params.serial.replace('-' + config.postfix, '');
|
|
1584
1383
|
}
|
|
1585
|
-
// Add the serial to the whiteList if the whiteList exists and the serial is not already in it
|
|
1586
1384
|
if (isValidArray(config.whiteList, 1)) {
|
|
1587
1385
|
if (!config.whiteList.includes(data.params.serial)) {
|
|
1588
1386
|
config.whiteList.push(data.params.serial);
|
|
1589
1387
|
}
|
|
1590
1388
|
}
|
|
1591
|
-
// Remove the serial from the blackList if the blackList exists and the serial is in it
|
|
1592
1389
|
if (isValidArray(config.blackList, 1)) {
|
|
1593
1390
|
if (config.blackList.includes(data.params.serial)) {
|
|
1594
1391
|
config.blackList = config.blackList.filter((serial) => serial !== data.params.serial);
|
|
@@ -1611,13 +1408,11 @@ export class Frontend {
|
|
|
1611
1408
|
if (config.postfix) {
|
|
1612
1409
|
data.params.serial = data.params.serial.replace('-' + config.postfix, '');
|
|
1613
1410
|
}
|
|
1614
|
-
// Remove the serial from the whiteList if the whiteList exists and the serial is in it
|
|
1615
1411
|
if (isValidArray(config.whiteList, 1)) {
|
|
1616
1412
|
if (config.whiteList.includes(data.params.serial)) {
|
|
1617
1413
|
config.whiteList = config.whiteList.filter((serial) => serial !== data.params.serial);
|
|
1618
1414
|
}
|
|
1619
1415
|
}
|
|
1620
|
-
// Add the serial to the blackList
|
|
1621
1416
|
if (isValidArray(config.blackList)) {
|
|
1622
1417
|
if (!config.blackList.includes(data.params.serial)) {
|
|
1623
1418
|
config.blackList.push(data.params.serial);
|
|
@@ -1641,171 +1436,102 @@ export class Frontend {
|
|
|
1641
1436
|
return;
|
|
1642
1437
|
}
|
|
1643
1438
|
}
|
|
1644
|
-
/**
|
|
1645
|
-
* Sends a WebSocket message to all connected clients. The function is called by AnsiLogger.setGlobalCallback.
|
|
1646
|
-
*
|
|
1647
|
-
* @param {string} level - The logger level of the message: debug info notice warn error fatal...
|
|
1648
|
-
* @param {string} time - The time string of the message
|
|
1649
|
-
* @param {string} name - The logger name of the message
|
|
1650
|
-
* @param {string} message - The content of the message.
|
|
1651
|
-
*/
|
|
1652
1439
|
wssSendMessage(level, time, name, message) {
|
|
1653
1440
|
if (!level || !time || !name || !message)
|
|
1654
1441
|
return;
|
|
1655
|
-
// Remove ANSI escape codes from the message
|
|
1656
|
-
// eslint-disable-next-line no-control-regex
|
|
1657
1442
|
message = message.replace(/\x1B\[[0-9;]*[m|s|u|K]/g, '');
|
|
1658
|
-
// Remove leading asterisks from the message
|
|
1659
1443
|
message = message.replace(/^\*+/, '');
|
|
1660
|
-
// Replace all occurrences of \t and \n
|
|
1661
1444
|
message = message.replace(/[\t\n]/g, '');
|
|
1662
|
-
// Remove non-printable characters
|
|
1663
|
-
// eslint-disable-next-line no-control-regex
|
|
1664
1445
|
message = message.replace(/[\x00-\x1F\x7F]/g, '');
|
|
1665
|
-
// Replace all occurrences of \" with "
|
|
1666
1446
|
message = message.replace(/\\"/g, '"');
|
|
1667
|
-
// Define the maximum allowed length for continuous characters without a space
|
|
1668
1447
|
const maxContinuousLength = 100;
|
|
1669
1448
|
const keepStartLength = 20;
|
|
1670
1449
|
const keepEndLength = 20;
|
|
1671
|
-
// Split the message into words
|
|
1672
1450
|
message = message
|
|
1673
1451
|
.split(' ')
|
|
1674
1452
|
.map((word) => {
|
|
1675
|
-
// If the word length exceeds the max continuous length, insert spaces and truncate
|
|
1676
1453
|
if (word.length > maxContinuousLength) {
|
|
1677
1454
|
return word.slice(0, keepStartLength) + ' ... ' + word.slice(-keepEndLength);
|
|
1678
1455
|
}
|
|
1679
1456
|
return word;
|
|
1680
1457
|
})
|
|
1681
1458
|
.join(' ');
|
|
1682
|
-
// Send the message to all connected clients
|
|
1683
1459
|
this.webSocketServer?.clients.forEach((client) => {
|
|
1684
1460
|
if (client.readyState === WebSocket.OPEN) {
|
|
1685
1461
|
client.send(JSON.stringify({ id: WS_ID_LOG, src: 'Matterbridge', level, time, name, message }));
|
|
1686
1462
|
}
|
|
1687
1463
|
});
|
|
1688
1464
|
}
|
|
1689
|
-
/**
|
|
1690
|
-
* Sends a need to refresh WebSocket message to all connected clients.
|
|
1691
|
-
*
|
|
1692
|
-
* @param {string} changed - The changed value. If null, the whole page will be refreshed.
|
|
1693
|
-
* possible values:
|
|
1694
|
-
* - 'matterbridgeLatestVersion'
|
|
1695
|
-
* - 'matterbridgeAdvertise'
|
|
1696
|
-
* - 'online'
|
|
1697
|
-
* - 'offline'
|
|
1698
|
-
* - 'reachability'
|
|
1699
|
-
* - 'settings'
|
|
1700
|
-
* - 'plugins'
|
|
1701
|
-
* - 'devices'
|
|
1702
|
-
* - 'fabrics'
|
|
1703
|
-
* - 'sessions'
|
|
1704
|
-
*/
|
|
1705
1465
|
wssSendRefreshRequired(changed = null) {
|
|
1706
1466
|
this.log.debug('Sending a refresh required message to all connected clients');
|
|
1707
|
-
// Send the message to all connected clients
|
|
1708
1467
|
this.webSocketServer?.clients.forEach((client) => {
|
|
1709
1468
|
if (client.readyState === WebSocket.OPEN) {
|
|
1710
1469
|
client.send(JSON.stringify({ id: WS_ID_REFRESH_NEEDED, src: 'Matterbridge', dst: 'Frontend', method: 'refresh_required', params: { changed: changed } }));
|
|
1711
1470
|
}
|
|
1712
1471
|
});
|
|
1713
1472
|
}
|
|
1714
|
-
/**
|
|
1715
|
-
* Sends a need to restart WebSocket message to all connected clients.
|
|
1716
|
-
*
|
|
1717
|
-
*/
|
|
1718
1473
|
wssSendRestartRequired(snackbar = true) {
|
|
1719
1474
|
this.log.debug('Sending a restart required message to all connected clients');
|
|
1720
1475
|
this.matterbridge.matterbridgeInformation.restartRequired = true;
|
|
1721
1476
|
if (snackbar === true)
|
|
1722
1477
|
this.wssSendSnackbarMessage(`Restart required`, 0);
|
|
1723
|
-
// Send the message to all connected clients
|
|
1724
1478
|
this.webSocketServer?.clients.forEach((client) => {
|
|
1725
1479
|
if (client.readyState === WebSocket.OPEN) {
|
|
1726
1480
|
client.send(JSON.stringify({ id: WS_ID_RESTART_NEEDED, src: 'Matterbridge', dst: 'Frontend', method: 'restart_required', params: {} }));
|
|
1727
1481
|
}
|
|
1728
1482
|
});
|
|
1729
1483
|
}
|
|
1730
|
-
/**
|
|
1731
|
-
* Sends a need to update WebSocket message to all connected clients.
|
|
1732
|
-
*
|
|
1733
|
-
*/
|
|
1734
1484
|
wssSendUpdateRequired() {
|
|
1735
1485
|
this.log.debug('Sending an update required message to all connected clients');
|
|
1736
1486
|
this.matterbridge.matterbridgeInformation.updateRequired = true;
|
|
1737
|
-
// Send the message to all connected clients
|
|
1738
1487
|
this.webSocketServer?.clients.forEach((client) => {
|
|
1739
1488
|
if (client.readyState === WebSocket.OPEN) {
|
|
1740
1489
|
client.send(JSON.stringify({ id: WS_ID_UPDATE_NEEDED, src: 'Matterbridge', dst: 'Frontend', method: 'update_required', params: {} }));
|
|
1741
1490
|
}
|
|
1742
1491
|
});
|
|
1743
1492
|
}
|
|
1744
|
-
/**
|
|
1745
|
-
* Sends a memory update message to all connected clients.
|
|
1746
|
-
*
|
|
1747
|
-
*/
|
|
1748
1493
|
wssSendCpuUpdate(cpuUsage) {
|
|
1749
1494
|
this.log.debug('Sending a cpu update message to all connected clients');
|
|
1750
|
-
// Send the message to all connected clients
|
|
1751
1495
|
this.webSocketServer?.clients.forEach((client) => {
|
|
1752
1496
|
if (client.readyState === WebSocket.OPEN) {
|
|
1753
1497
|
client.send(JSON.stringify({ id: WS_ID_CPU_UPDATE, src: 'Matterbridge', dst: 'Frontend', method: 'cpu_update', params: { cpuUsage } }));
|
|
1754
1498
|
}
|
|
1755
1499
|
});
|
|
1756
1500
|
}
|
|
1757
|
-
/**
|
|
1758
|
-
* Sends a cpu update message to all connected clients.
|
|
1759
|
-
*
|
|
1760
|
-
*/
|
|
1761
1501
|
wssSendMemoryUpdate(totalMemory, freeMemory, rss, heapTotal, heapUsed, external, arrayBuffers) {
|
|
1762
1502
|
this.log.debug('Sending a memory update message to all connected clients');
|
|
1763
|
-
// Send the message to all connected clients
|
|
1764
1503
|
this.webSocketServer?.clients.forEach((client) => {
|
|
1765
1504
|
if (client.readyState === WebSocket.OPEN) {
|
|
1766
1505
|
client.send(JSON.stringify({ id: WS_ID_MEMORY_UPDATE, src: 'Matterbridge', dst: 'Frontend', method: 'memory_update', params: { totalMemory, freeMemory, rss, heapTotal, heapUsed, external, arrayBuffers } }));
|
|
1767
1506
|
}
|
|
1768
1507
|
});
|
|
1769
1508
|
}
|
|
1770
|
-
/**
|
|
1771
|
-
* Sends a memory update message to all connected clients.
|
|
1772
|
-
*
|
|
1773
|
-
*/
|
|
1774
1509
|
wssSendUptimeUpdate(systemUptime, processUptime) {
|
|
1775
1510
|
this.log.debug('Sending a uptime update message to all connected clients');
|
|
1776
|
-
// Send the message to all connected clients
|
|
1777
1511
|
this.webSocketServer?.clients.forEach((client) => {
|
|
1778
1512
|
if (client.readyState === WebSocket.OPEN) {
|
|
1779
1513
|
client.send(JSON.stringify({ id: WS_ID_UPTIME_UPDATE, src: 'Matterbridge', dst: 'Frontend', method: 'uptime_update', params: { systemUptime, processUptime } }));
|
|
1780
1514
|
}
|
|
1781
1515
|
});
|
|
1782
1516
|
}
|
|
1783
|
-
/**
|
|
1784
|
-
* Sends a cpu update message to all connected clients.
|
|
1785
|
-
* @param {string} message - The message to send.
|
|
1786
|
-
* @param {number} timeout - The timeout in seconds for the snackbar message.
|
|
1787
|
-
* @param {'info' | 'warning' | 'error' | 'success'} severity - The severity of the snackbar message (default info).
|
|
1788
|
-
*
|
|
1789
|
-
*/
|
|
1790
1517
|
wssSendSnackbarMessage(message, timeout = 5, severity = 'info') {
|
|
1791
1518
|
this.log.debug('Sending a snackbar message to all connected clients');
|
|
1792
|
-
// Send the message to all connected clients
|
|
1793
1519
|
this.webSocketServer?.clients.forEach((client) => {
|
|
1794
1520
|
if (client.readyState === WebSocket.OPEN) {
|
|
1795
1521
|
client.send(JSON.stringify({ id: WS_ID_SNACKBAR, src: 'Matterbridge', dst: 'Frontend', method: 'memory_update', params: { message, timeout, severity } }));
|
|
1796
1522
|
}
|
|
1797
1523
|
});
|
|
1798
1524
|
}
|
|
1799
|
-
|
|
1800
|
-
|
|
1801
|
-
|
|
1802
|
-
|
|
1803
|
-
|
|
1804
|
-
|
|
1805
|
-
|
|
1525
|
+
wssSendAttributeChangedMessage(plugin, serialNumber, uniqueId, cluster, attribute, value) {
|
|
1526
|
+
this.log.debug('Sending an attribute update message to all connected clients');
|
|
1527
|
+
this.webSocketServer?.clients.forEach((client) => {
|
|
1528
|
+
if (client.readyState === WebSocket.OPEN) {
|
|
1529
|
+
client.send(JSON.stringify({ id: WS_ID_STATEUPDATE, src: 'Matterbridge', dst: 'Frontend', method: 'state_update', params: { plugin, serialNumber, uniqueId, cluster, attribute, value } }));
|
|
1530
|
+
}
|
|
1531
|
+
});
|
|
1532
|
+
}
|
|
1806
1533
|
wssBroadcastMessage(id, method, params) {
|
|
1807
1534
|
this.log.debug(`Sending a broadcast message id ${id} method ${method} params ${debugStringify(params ?? {})} to all connected clients`);
|
|
1808
|
-
// Send the message to all connected clients
|
|
1809
1535
|
this.webSocketServer?.clients.forEach((client) => {
|
|
1810
1536
|
if (client.readyState === WebSocket.OPEN) {
|
|
1811
1537
|
client.send(JSON.stringify({ id, src: 'Matterbridge', dst: 'Frontend', method, params }));
|
|
@@ -1813,4 +1539,3 @@ export class Frontend {
|
|
|
1813
1539
|
});
|
|
1814
1540
|
}
|
|
1815
1541
|
}
|
|
1816
|
-
//# sourceMappingURL=frontend.js.map
|