matterbridge 2.2.1 → 2.2.2-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 +12 -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 +50 -291
- 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 +62 -731
- 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 +3 -47
- 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 +6 -6
- package/frontend/build/index.html +1 -1
- package/frontend/build/static/css/{main.cf25d33e.css → main.b9449869.css} +2 -2
- package/frontend/build/static/css/{main.cf25d33e.css.map → main.b9449869.css.map} +1 -1
- package/frontend/build/static/js/{main.025c65d2.js → main.92802eb1.js} +8 -8
- package/frontend/build/static/js/{main.025c65d2.js.map → main.92802eb1.js.map} +1 -1
- package/npm-shrinkwrap.json +7 -7
- 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 -178
- 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 -411
- 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.025c65d2.js.LICENSE.txt → main.92802eb1.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 https from 'https';
|
|
28
4
|
import express from 'express';
|
|
@@ -30,71 +6,21 @@ import WebSocket, { WebSocketServer } from 'ws';
|
|
|
30
6
|
import os from 'node:os';
|
|
31
7
|
import path from 'node:path';
|
|
32
8
|
import { promises as fs } from 'node:fs';
|
|
33
|
-
// AnsiLogger module
|
|
34
9
|
import { AnsiLogger, stringify, debugStringify, CYAN, db, er, nf, rs, UNDERLINE, UNDERLINEOFF, wr, YELLOW } from './logger/export.js';
|
|
35
|
-
// Matterbridge
|
|
36
10
|
import { createZip, deepCopy, isValidArray, isValidNumber, isValidObject, isValidString } from './utils/export.js';
|
|
37
11
|
import { plg } from './matterbridgeTypes.js';
|
|
38
12
|
import { hasParameter } from './utils/export.js';
|
|
39
13
|
import { BridgedDeviceBasicInformation } from '@matter/main/clusters';
|
|
40
|
-
/**
|
|
41
|
-
* Websocket message ID for logging.
|
|
42
|
-
* @constant {number}
|
|
43
|
-
*/
|
|
44
14
|
export const WS_ID_LOG = 0;
|
|
45
|
-
/**
|
|
46
|
-
* Websocket message ID indicating a refresh is needed.
|
|
47
|
-
* @constant {number}
|
|
48
|
-
*/
|
|
49
15
|
export const WS_ID_REFRESH_NEEDED = 1;
|
|
50
|
-
/**
|
|
51
|
-
* Websocket message ID indicating a restart is needed.
|
|
52
|
-
* @constant {number}
|
|
53
|
-
*/
|
|
54
16
|
export const WS_ID_RESTART_NEEDED = 2;
|
|
55
|
-
/**
|
|
56
|
-
* Websocket message ID indicating a cpu update.
|
|
57
|
-
* @constant {number}
|
|
58
|
-
*/
|
|
59
17
|
export const WS_ID_CPU_UPDATE = 3;
|
|
60
|
-
/**
|
|
61
|
-
* Websocket message ID indicating a memory update.
|
|
62
|
-
* @constant {number}
|
|
63
|
-
*/
|
|
64
18
|
export const WS_ID_MEMORY_UPDATE = 4;
|
|
65
|
-
/**
|
|
66
|
-
* Websocket message ID indicating an uptime update.
|
|
67
|
-
* @constant {number}
|
|
68
|
-
*/
|
|
69
19
|
export const WS_ID_UPTIME_UPDATE = 5;
|
|
70
|
-
/**
|
|
71
|
-
* Websocket message ID indicating a memory update.
|
|
72
|
-
* @constant {number}
|
|
73
|
-
*/
|
|
74
20
|
export const WS_ID_SNACKBAR = 6;
|
|
75
|
-
|
|
76
|
-
* Websocket message ID indicating a shelly system update.
|
|
77
|
-
* check:
|
|
78
|
-
* curl -k http://127.0.0.1:8101/api/updates/sys/check
|
|
79
|
-
* perform:
|
|
80
|
-
* curl -k http://127.0.0.1:8101/api/updates/sys/perform
|
|
81
|
-
* @constant {number}
|
|
82
|
-
*/
|
|
21
|
+
export const WS_ID_UPDATE_NEEDED = 7;
|
|
83
22
|
export const WS_ID_SHELLY_SYS_UPDATE = 100;
|
|
84
|
-
/**
|
|
85
|
-
* Websocket message ID indicating a shelly main update.
|
|
86
|
-
* check:
|
|
87
|
-
* curl -k http://127.0.0.1:8101/api/updates/main/check
|
|
88
|
-
* perform:
|
|
89
|
-
* curl -k http://127.0.0.1:8101/api/updates/main/perform
|
|
90
|
-
* @constant {number}
|
|
91
|
-
*/
|
|
92
23
|
export const WS_ID_SHELLY_MAIN_UPDATE = 101;
|
|
93
|
-
/**
|
|
94
|
-
* Initializes the frontend of Matterbridge.
|
|
95
|
-
*
|
|
96
|
-
* @param port The port number to run the frontend server on. Default is 8283.
|
|
97
|
-
*/
|
|
98
24
|
export class Frontend {
|
|
99
25
|
matterbridge;
|
|
100
26
|
log;
|
|
@@ -111,7 +37,7 @@ export class Frontend {
|
|
|
111
37
|
memoryTimeout;
|
|
112
38
|
constructor(matterbridge) {
|
|
113
39
|
this.matterbridge = matterbridge;
|
|
114
|
-
this.log = new AnsiLogger({ logName: 'Frontend', logTimestampFormat: 4
|
|
40
|
+
this.log = new AnsiLogger({ logName: 'Frontend', logTimestampFormat: 4, logLevel: hasParameter('debug') ? "debug" : "info" });
|
|
115
41
|
}
|
|
116
42
|
set logLevel(logLevel) {
|
|
117
43
|
this.log.logLevel = logLevel;
|
|
@@ -119,21 +45,10 @@ export class Frontend {
|
|
|
119
45
|
async start(port = 8283) {
|
|
120
46
|
this.port = port;
|
|
121
47
|
this.log.debug(`Initializing the frontend ${hasParameter('ssl') ? 'https' : 'http'} server on port ${YELLOW}${this.port}${db}`);
|
|
122
|
-
// Create the express app that serves the frontend
|
|
123
48
|
this.expressApp = express();
|
|
124
|
-
// Log all requests to the server for debugging
|
|
125
|
-
/*
|
|
126
|
-
this.expressApp.use((req, res, next) => {
|
|
127
|
-
this.log.debug(`Received request on expressApp: ${req.method} ${req.url}`);
|
|
128
|
-
next();
|
|
129
|
-
});
|
|
130
|
-
*/
|
|
131
|
-
// Serve static files from '/static' endpoint
|
|
132
49
|
this.expressApp.use(express.static(path.join(this.matterbridge.rootDirectory, 'frontend/build')));
|
|
133
50
|
if (!hasParameter('ssl')) {
|
|
134
|
-
// Create an HTTP server and attach the express app
|
|
135
51
|
this.httpServer = createServer(this.expressApp);
|
|
136
|
-
// Listen on the specified port
|
|
137
52
|
if (hasParameter('ingress')) {
|
|
138
53
|
this.httpServer.listen(this.port, '0.0.0.0', () => {
|
|
139
54
|
this.log.info(`The frontend http server is listening on ${UNDERLINE}http://0.0.0.0:${this.port}${UNDERLINEOFF}${rs}`);
|
|
@@ -147,7 +62,6 @@ export class Frontend {
|
|
|
147
62
|
this.log.info(`The frontend http server is listening on ${UNDERLINE}http://[${this.matterbridge.systemInformation.ipv6Address}]:${this.port}${UNDERLINEOFF}${rs}`);
|
|
148
63
|
});
|
|
149
64
|
}
|
|
150
|
-
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
151
65
|
this.httpServer.on('error', (error) => {
|
|
152
66
|
this.log.error(`Frontend http server error listening on ${this.port}`);
|
|
153
67
|
switch (error.code) {
|
|
@@ -163,7 +77,6 @@ export class Frontend {
|
|
|
163
77
|
});
|
|
164
78
|
}
|
|
165
79
|
else {
|
|
166
|
-
// Load the SSL certificate, the private key and optionally the CA certificate
|
|
167
80
|
let cert;
|
|
168
81
|
try {
|
|
169
82
|
cert = await fs.readFile(path.join(this.matterbridge.matterbridgeDirectory, 'certs/cert.pem'), 'utf8');
|
|
@@ -191,9 +104,7 @@ export class Frontend {
|
|
|
191
104
|
this.log.info(`CA certificate file ${path.join(this.matterbridge.matterbridgeDirectory, 'certs/ca.pem')} not loaded: ${error}`);
|
|
192
105
|
}
|
|
193
106
|
const serverOptions = { cert, key, ca };
|
|
194
|
-
// Create an HTTPS server with the SSL certificate and private key (ca is optional) and attach the express app
|
|
195
107
|
this.httpsServer = https.createServer(serverOptions, this.expressApp);
|
|
196
|
-
// Listen on the specified port
|
|
197
108
|
if (hasParameter('ingress')) {
|
|
198
109
|
this.httpsServer.listen(this.port, '0.0.0.0', () => {
|
|
199
110
|
this.log.info(`The frontend https server is listening on ${UNDERLINE}https://0.0.0.0:${this.port}${UNDERLINEOFF}${rs}`);
|
|
@@ -207,7 +118,6 @@ export class Frontend {
|
|
|
207
118
|
this.log.info(`The frontend https server is listening on ${UNDERLINE}https://[${this.matterbridge.systemInformation.ipv6Address}]:${this.port}${UNDERLINEOFF}${rs}`);
|
|
208
119
|
});
|
|
209
120
|
}
|
|
210
|
-
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
211
121
|
this.httpsServer.on('error', (error) => {
|
|
212
122
|
this.log.error(`Frontend https server error listening on ${this.port}`);
|
|
213
123
|
switch (error.code) {
|
|
@@ -224,18 +134,16 @@ export class Frontend {
|
|
|
224
134
|
}
|
|
225
135
|
if (this.initializeError)
|
|
226
136
|
return;
|
|
227
|
-
// Create a WebSocket server and attach it to the http or https server
|
|
228
137
|
const wssPort = this.port;
|
|
229
138
|
const wssHost = hasParameter('ssl') ? `wss://${this.matterbridge.systemInformation.ipv4Address}:${wssPort}` : `ws://${this.matterbridge.systemInformation.ipv4Address}:${wssPort}`;
|
|
230
139
|
this.webSocketServer = new WebSocketServer(hasParameter('ssl') ? { server: this.httpsServer } : { server: this.httpServer });
|
|
231
140
|
this.webSocketServer.on('connection', (ws, request) => {
|
|
232
141
|
const clientIp = request.socket.remoteAddress;
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
callbackLogLevel = "debug" /* LogLevel.DEBUG */;
|
|
142
|
+
let callbackLogLevel = "notice";
|
|
143
|
+
if (this.matterbridge.matterbridgeInformation.loggerLevel === "info" || this.matterbridge.matterbridgeInformation.matterLoggerLevel === MatterLogLevel.INFO)
|
|
144
|
+
callbackLogLevel = "info";
|
|
145
|
+
if (this.matterbridge.matterbridgeInformation.loggerLevel === "debug" || this.matterbridge.matterbridgeInformation.matterLoggerLevel === MatterLogLevel.DEBUG)
|
|
146
|
+
callbackLogLevel = "debug";
|
|
239
147
|
AnsiLogger.setGlobalCallback(this.wssSendMessage.bind(this), callbackLogLevel);
|
|
240
148
|
this.log.debug(`WebSocketServer logger global callback set to ${callbackLogLevel}`);
|
|
241
149
|
this.log.info(`WebSocketServer client "${clientIp}" connected to Matterbridge`);
|
|
@@ -269,7 +177,6 @@ export class Frontend {
|
|
|
269
177
|
this.webSocketServer.on('error', (ws, error) => {
|
|
270
178
|
this.log.error(`WebSocketServer error: ${error}`);
|
|
271
179
|
});
|
|
272
|
-
// Subscribe to cli events
|
|
273
180
|
const { cliEmitter } = await import('./cli.js');
|
|
274
181
|
cliEmitter.on('uptime', (systemUptime, processUptime) => {
|
|
275
182
|
this.wssSendUptimeUpdate(systemUptime, processUptime);
|
|
@@ -280,7 +187,6 @@ export class Frontend {
|
|
|
280
187
|
cliEmitter.on('cpu', (cpuUsage) => {
|
|
281
188
|
this.wssSendCpuUpdate(cpuUsage);
|
|
282
189
|
});
|
|
283
|
-
// Endpoint to validate login code
|
|
284
190
|
this.expressApp.post('/api/login', express.json(), async (req, res) => {
|
|
285
191
|
const { password } = req.body;
|
|
286
192
|
this.log.debug('The frontend sent /api/login', password);
|
|
@@ -299,27 +205,23 @@ export class Frontend {
|
|
|
299
205
|
this.log.warn('/api/login error wrong password');
|
|
300
206
|
res.json({ valid: false });
|
|
301
207
|
}
|
|
302
|
-
// eslint-disable-next-line @typescript-eslint/no-unused-vars
|
|
303
208
|
}
|
|
304
209
|
catch (error) {
|
|
305
210
|
this.log.error('/api/login error getting password');
|
|
306
211
|
res.json({ valid: false });
|
|
307
212
|
}
|
|
308
213
|
});
|
|
309
|
-
// Endpoint to provide health check
|
|
310
214
|
this.expressApp.get('/health', (req, res) => {
|
|
311
215
|
this.log.debug('Express received /health');
|
|
312
216
|
const healthStatus = {
|
|
313
|
-
status: 'ok',
|
|
314
|
-
uptime: process.uptime(),
|
|
315
|
-
timestamp: new Date().toISOString(),
|
|
217
|
+
status: 'ok',
|
|
218
|
+
uptime: process.uptime(),
|
|
219
|
+
timestamp: new Date().toISOString(),
|
|
316
220
|
};
|
|
317
221
|
res.status(200).json(healthStatus);
|
|
318
222
|
});
|
|
319
|
-
// Endpoint to provide memory usage details
|
|
320
223
|
this.expressApp.get('/memory', async (req, res) => {
|
|
321
224
|
this.log.debug('Express received /memory');
|
|
322
|
-
// Memory usage from process
|
|
323
225
|
const memoryUsageRaw = process.memoryUsage();
|
|
324
226
|
const memoryUsage = {
|
|
325
227
|
rss: this.formatMemoryUsage(memoryUsageRaw.rss),
|
|
@@ -328,13 +230,10 @@ export class Frontend {
|
|
|
328
230
|
external: this.formatMemoryUsage(memoryUsageRaw.external),
|
|
329
231
|
arrayBuffers: this.formatMemoryUsage(memoryUsageRaw.arrayBuffers),
|
|
330
232
|
};
|
|
331
|
-
// V8 heap statistics
|
|
332
233
|
const { default: v8 } = await import('node:v8');
|
|
333
234
|
const heapStatsRaw = v8.getHeapStatistics();
|
|
334
235
|
const heapSpacesRaw = v8.getHeapSpaceStatistics();
|
|
335
|
-
// Format heapStats
|
|
336
236
|
const heapStats = Object.fromEntries(Object.entries(heapStatsRaw).map(([key, value]) => [key, this.formatMemoryUsage(value)]));
|
|
337
|
-
// Format heapSpaces
|
|
338
237
|
const heapSpaces = heapSpacesRaw.map((space) => ({
|
|
339
238
|
...space,
|
|
340
239
|
space_size: this.formatMemoryUsage(space.space_size),
|
|
@@ -352,7 +251,6 @@ export class Frontend {
|
|
|
352
251
|
};
|
|
353
252
|
res.status(200).json(memoryReport);
|
|
354
253
|
});
|
|
355
|
-
// Endpoint to start advertising the server node
|
|
356
254
|
this.expressApp.get('/api/advertise', express.json(), async (req, res) => {
|
|
357
255
|
const pairingCodes = await this.matterbridge.advertiseServerNode(this.matterbridge.serverNode);
|
|
358
256
|
if (pairingCodes) {
|
|
@@ -363,22 +261,18 @@ export class Frontend {
|
|
|
363
261
|
res.status(500).json({ error: 'Failed to generate pairing codes' });
|
|
364
262
|
}
|
|
365
263
|
});
|
|
366
|
-
// Endpoint to provide settings
|
|
367
264
|
this.expressApp.get('/api/settings', express.json(), async (req, res) => {
|
|
368
265
|
this.log.debug('The frontend sent /api/settings');
|
|
369
266
|
res.json(await this.getApiSettings());
|
|
370
267
|
});
|
|
371
|
-
// Endpoint to provide plugins
|
|
372
268
|
this.expressApp.get('/api/plugins', async (req, res) => {
|
|
373
269
|
this.log.debug('The frontend sent /api/plugins');
|
|
374
270
|
res.json(this.getBaseRegisteredPlugins());
|
|
375
271
|
});
|
|
376
|
-
// Endpoint to provide devices
|
|
377
272
|
this.expressApp.get('/api/devices', (req, res) => {
|
|
378
273
|
this.log.debug('The frontend sent /api/devices');
|
|
379
274
|
const devices = [];
|
|
380
275
|
this.matterbridge.devices.forEach(async (device) => {
|
|
381
|
-
// Check if the device has the required properties
|
|
382
276
|
if (!device.plugin || !device.name || !device.deviceName || !device.serialNumber || !device.uniqueId || !device.lifecycle.isReady)
|
|
383
277
|
return;
|
|
384
278
|
const cluster = this.getClusterTextFromDevice(device);
|
|
@@ -397,7 +291,6 @@ export class Frontend {
|
|
|
397
291
|
});
|
|
398
292
|
res.json(devices);
|
|
399
293
|
});
|
|
400
|
-
// Endpoint to provide the cluster servers of the devices
|
|
401
294
|
this.expressApp.get('/api/devices_clusters/:selectedPluginName/:selectedDeviceEndpoint', (req, res) => {
|
|
402
295
|
const selectedPluginName = req.params.selectedPluginName;
|
|
403
296
|
const selectedDeviceEndpoint = parseInt(req.params.selectedDeviceEndpoint, 10);
|
|
@@ -470,7 +363,6 @@ export class Frontend {
|
|
|
470
363
|
});
|
|
471
364
|
res.json(data);
|
|
472
365
|
});
|
|
473
|
-
// Endpoint to view the log
|
|
474
366
|
this.expressApp.get('/api/view-log', async (req, res) => {
|
|
475
367
|
this.log.debug('The frontend sent /api/log');
|
|
476
368
|
try {
|
|
@@ -483,12 +375,10 @@ export class Frontend {
|
|
|
483
375
|
res.status(500).send('Error reading log file');
|
|
484
376
|
}
|
|
485
377
|
});
|
|
486
|
-
// Endpoint to download the matterbridge log
|
|
487
378
|
this.expressApp.get('/api/download-mblog', async (req, res) => {
|
|
488
379
|
this.log.debug('The frontend sent /api/download-mblog');
|
|
489
380
|
try {
|
|
490
381
|
await fs.access(path.join(this.matterbridge.matterbridgeDirectory, this.matterbridge.matterbrideLoggerFile), fs.constants.F_OK);
|
|
491
|
-
// eslint-disable-next-line @typescript-eslint/no-unused-vars
|
|
492
382
|
}
|
|
493
383
|
catch (error) {
|
|
494
384
|
fs.appendFile(path.join(this.matterbridge.matterbridgeDirectory, this.matterbridge.matterbrideLoggerFile), 'Enable the log on file in the settings to enable the file logger');
|
|
@@ -500,12 +390,10 @@ export class Frontend {
|
|
|
500
390
|
}
|
|
501
391
|
});
|
|
502
392
|
});
|
|
503
|
-
// Endpoint to download the matter log
|
|
504
393
|
this.expressApp.get('/api/download-mjlog', async (req, res) => {
|
|
505
394
|
this.log.debug('The frontend sent /api/download-mjlog');
|
|
506
395
|
try {
|
|
507
396
|
await fs.access(path.join(this.matterbridge.matterbridgeDirectory, this.matterbridge.matterLoggerFile), fs.constants.F_OK);
|
|
508
|
-
// eslint-disable-next-line @typescript-eslint/no-unused-vars
|
|
509
397
|
}
|
|
510
398
|
catch (error) {
|
|
511
399
|
fs.appendFile(path.join(this.matterbridge.matterbridgeDirectory, this.matterbridge.matterLoggerFile), 'Enable the log on file in the settings to enable the file logger');
|
|
@@ -517,12 +405,10 @@ export class Frontend {
|
|
|
517
405
|
}
|
|
518
406
|
});
|
|
519
407
|
});
|
|
520
|
-
// Endpoint to download the matter log
|
|
521
408
|
this.expressApp.get('/api/shellydownloadsystemlog', async (req, res) => {
|
|
522
409
|
this.log.debug('The frontend sent /api/shellydownloadsystemlog');
|
|
523
410
|
try {
|
|
524
411
|
await fs.access(path.join(this.matterbridge.matterbridgeDirectory, 'shelly.log'), fs.constants.F_OK);
|
|
525
|
-
// eslint-disable-next-line @typescript-eslint/no-unused-vars
|
|
526
412
|
}
|
|
527
413
|
catch (error) {
|
|
528
414
|
fs.appendFile(path.join(this.matterbridge.matterbridgeDirectory, 'shelly.log'), 'Create the Shelly system log before downloading it.');
|
|
@@ -534,7 +420,6 @@ export class Frontend {
|
|
|
534
420
|
}
|
|
535
421
|
});
|
|
536
422
|
});
|
|
537
|
-
// Endpoint to download the matter storage file
|
|
538
423
|
this.expressApp.get('/api/download-mjstorage', async (req, res) => {
|
|
539
424
|
this.log.debug('The frontend sent /api/download-mjstorage');
|
|
540
425
|
await createZip(path.join(os.tmpdir(), `matterbridge.${this.matterbridge.matterStorageName}.zip`), path.join(this.matterbridge.matterbridgeDirectory, this.matterbridge.matterStorageName));
|
|
@@ -545,7 +430,6 @@ export class Frontend {
|
|
|
545
430
|
}
|
|
546
431
|
});
|
|
547
432
|
});
|
|
548
|
-
// Endpoint to download the matterbridge storage directory
|
|
549
433
|
this.expressApp.get('/api/download-mbstorage', async (req, res) => {
|
|
550
434
|
this.log.debug('The frontend sent /api/download-mbstorage');
|
|
551
435
|
await createZip(path.join(os.tmpdir(), `matterbridge.${this.matterbridge.nodeStorageName}.zip`), path.join(this.matterbridge.matterbridgeDirectory, this.matterbridge.nodeStorageName));
|
|
@@ -556,7 +440,6 @@ export class Frontend {
|
|
|
556
440
|
}
|
|
557
441
|
});
|
|
558
442
|
});
|
|
559
|
-
// Endpoint to download the matterbridge plugin directory
|
|
560
443
|
this.expressApp.get('/api/download-pluginstorage', async (req, res) => {
|
|
561
444
|
this.log.debug('The frontend sent /api/download-pluginstorage');
|
|
562
445
|
await createZip(path.join(os.tmpdir(), `matterbridge.pluginstorage.zip`), this.matterbridge.matterbridgePluginDirectory);
|
|
@@ -567,11 +450,9 @@ export class Frontend {
|
|
|
567
450
|
}
|
|
568
451
|
});
|
|
569
452
|
});
|
|
570
|
-
// Endpoint to download the matterbridge plugin config files
|
|
571
453
|
this.expressApp.get('/api/download-pluginconfig', async (req, res) => {
|
|
572
454
|
this.log.debug('The frontend sent /api/download-pluginconfig');
|
|
573
455
|
await createZip(path.join(os.tmpdir(), `matterbridge.pluginconfig.zip`), path.relative(process.cwd(), path.join(this.matterbridge.matterbridgeDirectory, '*.config.json')));
|
|
574
|
-
// 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')));
|
|
575
456
|
res.download(path.join(os.tmpdir(), `matterbridge.pluginconfig.zip`), `matterbridge.pluginconfig.zip`, (error) => {
|
|
576
457
|
if (error) {
|
|
577
458
|
this.log.error(`Error downloading file matterbridge.pluginstorage.zip: ${error instanceof Error ? error.message : error}`);
|
|
@@ -579,7 +460,6 @@ export class Frontend {
|
|
|
579
460
|
}
|
|
580
461
|
});
|
|
581
462
|
});
|
|
582
|
-
// Endpoint to download the matterbridge plugin config files
|
|
583
463
|
this.expressApp.get('/api/download-backup', async (req, res) => {
|
|
584
464
|
this.log.debug('The frontend sent /api/download-backup');
|
|
585
465
|
res.download(path.join(os.tmpdir(), `matterbridge.backup.zip`), `matterbridge.backup.zip`, (error) => {
|
|
@@ -589,7 +469,6 @@ export class Frontend {
|
|
|
589
469
|
}
|
|
590
470
|
});
|
|
591
471
|
});
|
|
592
|
-
// Endpoint to receive commands
|
|
593
472
|
this.expressApp.post('/api/command/:command/:param', express.json(), async (req, res) => {
|
|
594
473
|
const command = req.params.command;
|
|
595
474
|
let param = req.params.param;
|
|
@@ -599,15 +478,13 @@ export class Frontend {
|
|
|
599
478
|
return;
|
|
600
479
|
}
|
|
601
480
|
this.log.debug(`Received frontend command: ${command}:${param}`);
|
|
602
|
-
// Handle the command setpassword from Settings
|
|
603
481
|
if (command === 'setpassword') {
|
|
604
|
-
const password = param.slice(1, -1);
|
|
482
|
+
const password = param.slice(1, -1);
|
|
605
483
|
this.log.debug('setpassword', param, password);
|
|
606
484
|
await this.matterbridge.nodeContext?.set('password', password);
|
|
607
485
|
res.json({ message: 'Command received' });
|
|
608
486
|
return;
|
|
609
487
|
}
|
|
610
|
-
// Handle the command setbridgemode from Settings
|
|
611
488
|
if (command === 'setbridgemode') {
|
|
612
489
|
this.log.debug(`setbridgemode: ${param}`);
|
|
613
490
|
this.wssSendRestartRequired();
|
|
@@ -615,7 +492,6 @@ export class Frontend {
|
|
|
615
492
|
res.json({ message: 'Command received' });
|
|
616
493
|
return;
|
|
617
494
|
}
|
|
618
|
-
// Handle the command backup from Settings
|
|
619
495
|
if (command === 'backup') {
|
|
620
496
|
this.log.notice(`Prepairing the backup...`);
|
|
621
497
|
await createZip(path.join(os.tmpdir(), `matterbridge.backup.zip`), path.join(this.matterbridge.matterbridgeDirectory), path.join(this.matterbridge.matterbridgePluginDirectory));
|
|
@@ -624,33 +500,31 @@ export class Frontend {
|
|
|
624
500
|
res.json({ message: 'Command received' });
|
|
625
501
|
return;
|
|
626
502
|
}
|
|
627
|
-
// Handle the command setmbloglevel from Settings
|
|
628
503
|
if (command === 'setmbloglevel') {
|
|
629
504
|
this.log.debug('Matterbridge log level:', param);
|
|
630
505
|
if (param === 'Debug') {
|
|
631
|
-
this.log.logLevel = "debug"
|
|
506
|
+
this.log.logLevel = "debug";
|
|
632
507
|
}
|
|
633
508
|
else if (param === 'Info') {
|
|
634
|
-
this.log.logLevel = "info"
|
|
509
|
+
this.log.logLevel = "info";
|
|
635
510
|
}
|
|
636
511
|
else if (param === 'Notice') {
|
|
637
|
-
this.log.logLevel = "notice"
|
|
512
|
+
this.log.logLevel = "notice";
|
|
638
513
|
}
|
|
639
514
|
else if (param === 'Warn') {
|
|
640
|
-
this.log.logLevel = "warn"
|
|
515
|
+
this.log.logLevel = "warn";
|
|
641
516
|
}
|
|
642
517
|
else if (param === 'Error') {
|
|
643
|
-
this.log.logLevel = "error"
|
|
518
|
+
this.log.logLevel = "error";
|
|
644
519
|
}
|
|
645
520
|
else if (param === 'Fatal') {
|
|
646
|
-
this.log.logLevel = "fatal"
|
|
521
|
+
this.log.logLevel = "fatal";
|
|
647
522
|
}
|
|
648
523
|
await this.matterbridge.nodeContext?.set('matterbridgeLogLevel', this.log.logLevel);
|
|
649
524
|
await this.matterbridge.setLogLevel(this.log.logLevel);
|
|
650
525
|
res.json({ message: 'Command received' });
|
|
651
526
|
return;
|
|
652
527
|
}
|
|
653
|
-
// Handle the command setmbloglevel from Settings
|
|
654
528
|
if (command === 'setmjloglevel') {
|
|
655
529
|
this.log.debug('Matter.js log level:', param);
|
|
656
530
|
if (param === 'Debug') {
|
|
@@ -675,34 +549,30 @@ export class Frontend {
|
|
|
675
549
|
res.json({ message: 'Command received' });
|
|
676
550
|
return;
|
|
677
551
|
}
|
|
678
|
-
// Handle the command setmdnsinterface from Settings
|
|
679
552
|
if (command === 'setmdnsinterface') {
|
|
680
|
-
param = param.slice(1, -1);
|
|
553
|
+
param = param.slice(1, -1);
|
|
681
554
|
this.matterbridge.matterbridgeInformation.mattermdnsinterface = param;
|
|
682
555
|
this.log.debug('Matter.js mdns interface:', param === '' ? 'All interfaces' : param);
|
|
683
556
|
await this.matterbridge.nodeContext?.set('mattermdnsinterface', param);
|
|
684
557
|
res.json({ message: 'Command received' });
|
|
685
558
|
return;
|
|
686
559
|
}
|
|
687
|
-
// Handle the command setipv4address from Settings
|
|
688
560
|
if (command === 'setipv4address') {
|
|
689
|
-
param = param.slice(1, -1);
|
|
561
|
+
param = param.slice(1, -1);
|
|
690
562
|
this.matterbridge.matterbridgeInformation.matteripv4address = param;
|
|
691
563
|
this.log.debug('Matter.js ipv4 address:', param === '' ? 'All ipv4 addresses' : param);
|
|
692
564
|
await this.matterbridge.nodeContext?.set('matteripv4address', param);
|
|
693
565
|
res.json({ message: 'Command received' });
|
|
694
566
|
return;
|
|
695
567
|
}
|
|
696
|
-
// Handle the command setipv6address from Settings
|
|
697
568
|
if (command === 'setipv6address') {
|
|
698
|
-
param = param.slice(1, -1);
|
|
569
|
+
param = param.slice(1, -1);
|
|
699
570
|
this.matterbridge.matterbridgeInformation.matteripv6address = param;
|
|
700
571
|
this.log.debug('Matter.js ipv6 address:', param === '' ? 'All ipv6 addresses' : param);
|
|
701
572
|
await this.matterbridge.nodeContext?.set('matteripv6address', param);
|
|
702
573
|
res.json({ message: 'Command received' });
|
|
703
574
|
return;
|
|
704
575
|
}
|
|
705
|
-
// Handle the command setmatterport from Settings
|
|
706
576
|
if (command === 'setmatterport') {
|
|
707
577
|
const port = Math.min(Math.max(parseInt(param), 5540), 5560);
|
|
708
578
|
this.matterbridge.matterbridgeInformation.matterPort = port;
|
|
@@ -711,7 +581,6 @@ export class Frontend {
|
|
|
711
581
|
res.json({ message: 'Command received' });
|
|
712
582
|
return;
|
|
713
583
|
}
|
|
714
|
-
// Handle the command setmatterdiscriminator from Settings
|
|
715
584
|
if (command === 'setmatterdiscriminator') {
|
|
716
585
|
const discriminator = Math.min(Math.max(parseInt(param), 1000), 4095);
|
|
717
586
|
this.matterbridge.matterbridgeInformation.matterDiscriminator = discriminator;
|
|
@@ -720,7 +589,6 @@ export class Frontend {
|
|
|
720
589
|
res.json({ message: 'Command received' });
|
|
721
590
|
return;
|
|
722
591
|
}
|
|
723
|
-
// Handle the command setmatterpasscode from Settings
|
|
724
592
|
if (command === 'setmatterpasscode') {
|
|
725
593
|
const passcode = Math.min(Math.max(parseInt(param), 10000000), 90000000);
|
|
726
594
|
this.matterbridge.matterbridgeInformation.matterPasscode = passcode;
|
|
@@ -729,20 +597,17 @@ export class Frontend {
|
|
|
729
597
|
res.json({ message: 'Command received' });
|
|
730
598
|
return;
|
|
731
599
|
}
|
|
732
|
-
// Handle the command setmbloglevel from Settings
|
|
733
600
|
if (command === 'setmblogfile') {
|
|
734
601
|
this.log.debug('Matterbridge file log:', param);
|
|
735
602
|
this.matterbridge.matterbridgeInformation.fileLogger = param === 'true';
|
|
736
603
|
await this.matterbridge.nodeContext?.set('matterbridgeFileLog', param === 'true');
|
|
737
|
-
// Create the file logger for matterbridge
|
|
738
604
|
if (param === 'true')
|
|
739
|
-
AnsiLogger.setGlobalLogfile(path.join(this.matterbridge.matterbridgeDirectory, this.matterbridge.matterbrideLoggerFile), "debug"
|
|
605
|
+
AnsiLogger.setGlobalLogfile(path.join(this.matterbridge.matterbridgeDirectory, this.matterbridge.matterbrideLoggerFile), "debug", true);
|
|
740
606
|
else
|
|
741
607
|
AnsiLogger.setGlobalLogfile(undefined);
|
|
742
608
|
res.json({ message: 'Command received' });
|
|
743
609
|
return;
|
|
744
610
|
}
|
|
745
|
-
// Handle the command setmbloglevel from Settings
|
|
746
611
|
if (command === 'setmjlogfile') {
|
|
747
612
|
this.log.debug('Matter file log:', param);
|
|
748
613
|
this.matterbridge.matterbridgeInformation.matterFileLogger = param === 'true';
|
|
@@ -769,48 +634,40 @@ export class Frontend {
|
|
|
769
634
|
res.json({ message: 'Command received' });
|
|
770
635
|
return;
|
|
771
636
|
}
|
|
772
|
-
// Handle the command unregister from Settings
|
|
773
637
|
if (command === 'unregister') {
|
|
774
638
|
await this.matterbridge.unregisterAndShutdownProcess();
|
|
775
639
|
res.json({ message: 'Command received' });
|
|
776
640
|
return;
|
|
777
641
|
}
|
|
778
|
-
// Handle the command reset from Settings
|
|
779
642
|
if (command === 'reset') {
|
|
780
643
|
await this.matterbridge.shutdownProcessAndReset();
|
|
781
644
|
res.json({ message: 'Command received' });
|
|
782
645
|
return;
|
|
783
646
|
}
|
|
784
|
-
// Handle the command factoryreset from Settings
|
|
785
647
|
if (command === 'factoryreset') {
|
|
786
648
|
await this.matterbridge.shutdownProcessAndFactoryReset();
|
|
787
649
|
res.json({ message: 'Command received' });
|
|
788
650
|
return;
|
|
789
651
|
}
|
|
790
|
-
// Handle the command shutdown from Header
|
|
791
652
|
if (command === 'shutdown') {
|
|
792
653
|
await this.matterbridge.shutdownProcess();
|
|
793
654
|
res.json({ message: 'Command received' });
|
|
794
655
|
return;
|
|
795
656
|
}
|
|
796
|
-
// Handle the command restart from Header
|
|
797
657
|
if (command === 'restart') {
|
|
798
658
|
await this.matterbridge.restartProcess();
|
|
799
659
|
res.json({ message: 'Command received' });
|
|
800
660
|
return;
|
|
801
661
|
}
|
|
802
|
-
// Handle the command update from Header
|
|
803
662
|
if (command === 'update') {
|
|
804
663
|
await this.matterbridge.updateProcess();
|
|
805
664
|
this.wssSendRestartRequired();
|
|
806
665
|
res.json({ message: 'Command received' });
|
|
807
666
|
return;
|
|
808
667
|
}
|
|
809
|
-
// Handle the command saveconfig from Home
|
|
810
668
|
if (command === 'saveconfig') {
|
|
811
669
|
param = param.replace(/\*/g, '\\');
|
|
812
670
|
this.log.info(`Saving config for plugin ${plg}${param}${nf}...`);
|
|
813
|
-
// console.log('Req.body:', JSON.stringify(req.body, null, 2));
|
|
814
671
|
if (!this.matterbridge.plugins.has(param)) {
|
|
815
672
|
this.log.warn(`Plugin ${plg}${param}${wr} not found in matterbridge`);
|
|
816
673
|
}
|
|
@@ -825,7 +682,6 @@ export class Frontend {
|
|
|
825
682
|
res.json({ message: 'Command received' });
|
|
826
683
|
return;
|
|
827
684
|
}
|
|
828
|
-
// Handle the command installplugin from Home
|
|
829
685
|
if (command === 'installplugin') {
|
|
830
686
|
param = param.replace(/\*/g, '\\');
|
|
831
687
|
this.log.info(`Installing plugin ${plg}${param}${nf}...`);
|
|
@@ -834,7 +690,6 @@ export class Frontend {
|
|
|
834
690
|
await this.matterbridge.spawnCommand('npm', ['install', '-g', param, '--omit=dev', '--verbose']);
|
|
835
691
|
this.log.info(`Plugin ${plg}${param}${nf} installed. Full restart required.`);
|
|
836
692
|
this.wssSendSnackbarMessage(`Installed package ${param}`);
|
|
837
|
-
// eslint-disable-next-line @typescript-eslint/no-unused-vars
|
|
838
693
|
}
|
|
839
694
|
catch (error) {
|
|
840
695
|
this.log.error(`Error installing plugin ${plg}${param}${er}`);
|
|
@@ -842,47 +697,40 @@ export class Frontend {
|
|
|
842
697
|
}
|
|
843
698
|
this.wssSendRestartRequired();
|
|
844
699
|
param = param.split('@')[0];
|
|
845
|
-
// Also add the plugin to matterbridge so no return!
|
|
846
700
|
if (param === 'matterbridge') {
|
|
847
|
-
// 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
|
|
848
701
|
res.json({ message: 'Command received' });
|
|
849
702
|
return;
|
|
850
703
|
}
|
|
851
704
|
}
|
|
852
|
-
// Handle the command addplugin from Home
|
|
853
705
|
if (command === 'addplugin' || command === 'installplugin') {
|
|
854
706
|
param = param.replace(/\*/g, '\\');
|
|
855
707
|
const plugin = await this.matterbridge.plugins.add(param);
|
|
856
708
|
if (plugin) {
|
|
857
709
|
this.wssSendSnackbarMessage(`Added plugin ${param}`);
|
|
858
710
|
if (this.matterbridge.bridgeMode === 'childbridge') {
|
|
859
|
-
// 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
|
|
860
|
-
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
861
711
|
this.matterbridge.createDynamicPlugin(plugin, true);
|
|
862
712
|
}
|
|
863
713
|
this.matterbridge.plugins.load(plugin, true, 'The plugin has been added', true).then(() => {
|
|
864
|
-
this.wssSendRefreshRequired();
|
|
714
|
+
this.wssSendRefreshRequired('plugins');
|
|
865
715
|
});
|
|
866
716
|
}
|
|
867
717
|
res.json({ message: 'Command received' });
|
|
868
718
|
return;
|
|
869
719
|
}
|
|
870
|
-
// Handle the command removeplugin from Home
|
|
871
720
|
if (command === 'removeplugin') {
|
|
872
721
|
if (!this.matterbridge.plugins.has(param)) {
|
|
873
722
|
this.log.warn(`Plugin ${plg}${param}${wr} not found in matterbridge`);
|
|
874
723
|
}
|
|
875
724
|
else {
|
|
876
725
|
const plugin = this.matterbridge.plugins.get(param);
|
|
877
|
-
await this.matterbridge.plugins.shutdown(plugin, 'The plugin has been removed.', true);
|
|
726
|
+
await this.matterbridge.plugins.shutdown(plugin, 'The plugin has been removed.', true);
|
|
878
727
|
await this.matterbridge.plugins.remove(param);
|
|
879
728
|
this.wssSendSnackbarMessage(`Removed plugin ${param}`);
|
|
729
|
+
this.wssSendRefreshRequired('plugins');
|
|
880
730
|
}
|
|
881
731
|
res.json({ message: 'Command received' });
|
|
882
|
-
this.wssSendRefreshRequired();
|
|
883
732
|
return;
|
|
884
733
|
}
|
|
885
|
-
// Handle the command enableplugin from Home
|
|
886
734
|
if (command === 'enableplugin') {
|
|
887
735
|
if (!this.matterbridge.plugins.has(param)) {
|
|
888
736
|
this.log.warn(`Plugin ${plg}${param}${wr} not found in matterbridge`);
|
|
@@ -901,19 +749,16 @@ export class Frontend {
|
|
|
901
749
|
await this.matterbridge.plugins.enable(param);
|
|
902
750
|
this.wssSendSnackbarMessage(`Enabled plugin ${param}`);
|
|
903
751
|
if (this.matterbridge.bridgeMode === 'childbridge' && plugin.type === 'DynamicPlatform') {
|
|
904
|
-
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
905
752
|
this.matterbridge.createDynamicPlugin(plugin, true);
|
|
906
753
|
}
|
|
907
754
|
this.matterbridge.plugins.load(plugin, true, 'The plugin has been enabled', true).then(() => {
|
|
908
|
-
this.wssSendRefreshRequired();
|
|
755
|
+
this.wssSendRefreshRequired('plugins');
|
|
909
756
|
});
|
|
910
757
|
}
|
|
911
758
|
}
|
|
912
759
|
res.json({ message: 'Command received' });
|
|
913
|
-
this.wssSendRefreshRequired();
|
|
914
760
|
return;
|
|
915
761
|
}
|
|
916
|
-
// Handle the command disableplugin from Home
|
|
917
762
|
if (command === 'disableplugin') {
|
|
918
763
|
if (!this.matterbridge.plugins.has(param)) {
|
|
919
764
|
this.log.warn(`Plugin ${plg}${param}${wr} not found in matterbridge`);
|
|
@@ -921,17 +766,16 @@ export class Frontend {
|
|
|
921
766
|
else {
|
|
922
767
|
const plugin = this.matterbridge.plugins.get(param);
|
|
923
768
|
if (plugin && plugin.enabled) {
|
|
924
|
-
await this.matterbridge.plugins.shutdown(plugin, 'The plugin has been disabled.', true);
|
|
769
|
+
await this.matterbridge.plugins.shutdown(plugin, 'The plugin has been disabled.', true);
|
|
925
770
|
await this.matterbridge.plugins.disable(param);
|
|
926
771
|
this.wssSendSnackbarMessage(`Disabled plugin ${param}`);
|
|
772
|
+
this.wssSendRefreshRequired('plugins');
|
|
927
773
|
}
|
|
928
774
|
}
|
|
929
775
|
res.json({ message: 'Command received' });
|
|
930
|
-
this.wssSendRefreshRequired();
|
|
931
776
|
return;
|
|
932
777
|
}
|
|
933
778
|
});
|
|
934
|
-
// Fallback for routing (must be the last route)
|
|
935
779
|
this.expressApp.get('*', (req, res) => {
|
|
936
780
|
this.log.debug('The frontend sent:', req.url);
|
|
937
781
|
this.log.debug('Response send file:', path.join(this.matterbridge.rootDirectory, 'frontend/build/index.html'));
|
|
@@ -940,29 +784,24 @@ export class Frontend {
|
|
|
940
784
|
this.log.debug(`Frontend initialized on port ${YELLOW}${this.port}${db} static ${UNDERLINE}${path.join(this.matterbridge.rootDirectory, 'frontend/build')}${UNDERLINEOFF}${rs}`);
|
|
941
785
|
}
|
|
942
786
|
async stop() {
|
|
943
|
-
// Close the http server
|
|
944
787
|
if (this.httpServer) {
|
|
945
788
|
this.httpServer.close();
|
|
946
789
|
this.httpServer.removeAllListeners();
|
|
947
790
|
this.httpServer = undefined;
|
|
948
791
|
this.log.debug('Frontend http server closed successfully');
|
|
949
792
|
}
|
|
950
|
-
// Close the https server
|
|
951
793
|
if (this.httpsServer) {
|
|
952
794
|
this.httpsServer.close();
|
|
953
795
|
this.httpsServer.removeAllListeners();
|
|
954
796
|
this.httpsServer = undefined;
|
|
955
797
|
this.log.debug('Frontend https server closed successfully');
|
|
956
798
|
}
|
|
957
|
-
// Remove listeners from the express app
|
|
958
799
|
if (this.expressApp) {
|
|
959
800
|
this.expressApp.removeAllListeners();
|
|
960
801
|
this.expressApp = undefined;
|
|
961
802
|
this.log.debug('Frontend app closed successfully');
|
|
962
803
|
}
|
|
963
|
-
// Close the WebSocket server
|
|
964
804
|
if (this.webSocketServer) {
|
|
965
|
-
// Close all active connections
|
|
966
805
|
this.webSocketServer.clients.forEach((client) => {
|
|
967
806
|
if (client.readyState === WebSocket.OPEN) {
|
|
968
807
|
client.close();
|
|
@@ -979,7 +818,6 @@ export class Frontend {
|
|
|
979
818
|
this.webSocketServer = undefined;
|
|
980
819
|
}
|
|
981
820
|
}
|
|
982
|
-
// Function to format bytes to KB, MB, or GB
|
|
983
821
|
formatMemoryUsage = (bytes) => {
|
|
984
822
|
if (bytes >= 1024 ** 3) {
|
|
985
823
|
return `${(bytes / 1024 ** 3).toFixed(2)} GB`;
|
|
@@ -991,7 +829,6 @@ export class Frontend {
|
|
|
991
829
|
return `${(bytes / 1024).toFixed(2)} KB`;
|
|
992
830
|
}
|
|
993
831
|
};
|
|
994
|
-
// Function to format system uptime with only the most significant unit
|
|
995
832
|
formatOsUpTime = (seconds) => {
|
|
996
833
|
if (seconds >= 86400) {
|
|
997
834
|
const days = Math.floor(seconds / 86400);
|
|
@@ -1007,13 +844,8 @@ export class Frontend {
|
|
|
1007
844
|
}
|
|
1008
845
|
return `${seconds} second${seconds !== 1 ? 's' : ''}`;
|
|
1009
846
|
};
|
|
1010
|
-
/**
|
|
1011
|
-
* Retrieves the api settings data.
|
|
1012
|
-
* @returns {Promise<object>} A promise that resolve in the api settings object.
|
|
1013
|
-
*/
|
|
1014
847
|
async getApiSettings() {
|
|
1015
848
|
const { lastCpuUsage } = await import('./cli.js');
|
|
1016
|
-
// Update the system information
|
|
1017
849
|
this.matterbridge.systemInformation.totalMemory = this.formatMemoryUsage(os.totalmem());
|
|
1018
850
|
this.matterbridge.systemInformation.freeMemory = this.formatMemoryUsage(os.freemem());
|
|
1019
851
|
this.matterbridge.systemInformation.systemUptime = this.formatOsUpTime(os.uptime());
|
|
@@ -1022,7 +854,6 @@ export class Frontend {
|
|
|
1022
854
|
this.matterbridge.systemInformation.rss = this.formatMemoryUsage(process.memoryUsage().rss);
|
|
1023
855
|
this.matterbridge.systemInformation.heapTotal = this.formatMemoryUsage(process.memoryUsage().heapTotal);
|
|
1024
856
|
this.matterbridge.systemInformation.heapUsed = this.formatMemoryUsage(process.memoryUsage().heapUsed);
|
|
1025
|
-
// Update the matterbridge information
|
|
1026
857
|
this.matterbridge.matterbridgeInformation.bridgeMode = this.matterbridge.bridgeMode;
|
|
1027
858
|
this.matterbridge.matterbridgeInformation.restartMode = this.matterbridge.restartMode;
|
|
1028
859
|
this.matterbridge.matterbridgeInformation.loggerLevel = this.matterbridge.log.logLevel;
|
|
@@ -1041,11 +872,6 @@ export class Frontend {
|
|
|
1041
872
|
this.matterbridge.matterbridgeInformation.profile = this.matterbridge.profile;
|
|
1042
873
|
return { systemInformation: this.matterbridge.systemInformation, matterbridgeInformation: this.matterbridge.matterbridgeInformation };
|
|
1043
874
|
}
|
|
1044
|
-
/**
|
|
1045
|
-
* Retrieves the reachable attribute.
|
|
1046
|
-
* @param {MatterbridgeDevice} device - The MatterbridgeDevice object.
|
|
1047
|
-
* @returns {boolean} The reachable attribute.
|
|
1048
|
-
*/
|
|
1049
875
|
getReachability(device) {
|
|
1050
876
|
if (!device.lifecycle.isReady || device.construction.status !== Lifecycle.Status.Active)
|
|
1051
877
|
return false;
|
|
@@ -1055,11 +881,6 @@ export class Frontend {
|
|
|
1055
881
|
return true;
|
|
1056
882
|
return false;
|
|
1057
883
|
}
|
|
1058
|
-
/**
|
|
1059
|
-
* Retrieves the cluster text description from a given device.
|
|
1060
|
-
* @param {MatterbridgeDevice} device - The MatterbridgeDevice object.
|
|
1061
|
-
* @returns {string} The attributes description of the cluster servers in the device.
|
|
1062
|
-
*/
|
|
1063
884
|
getClusterTextFromDevice(device) {
|
|
1064
885
|
if (!device.lifecycle.isReady || device.construction.status !== Lifecycle.Status.Active)
|
|
1065
886
|
return '';
|
|
@@ -1100,7 +921,6 @@ export class Frontend {
|
|
|
1100
921
|
};
|
|
1101
922
|
let attributes = '';
|
|
1102
923
|
device.forEachAttribute((clusterName, clusterId, attributeName, attributeId, attributeValue) => {
|
|
1103
|
-
// console.log(`${device.deviceName} => Cluster: ${clusterName}-${clusterId} Attribute: ${attributeName}-${attributeId} Value(${typeof attributeValue}): ${attributeValue}`);
|
|
1104
924
|
if (typeof attributeValue === 'undefined')
|
|
1105
925
|
return;
|
|
1106
926
|
if (clusterName === 'onOff' && attributeName === 'onOff')
|
|
@@ -1178,13 +998,8 @@ export class Frontend {
|
|
|
1178
998
|
if (clusterName === 'userLabel' && attributeName === 'labelList')
|
|
1179
999
|
attributes += `${getUserLabel(device)} `;
|
|
1180
1000
|
});
|
|
1181
|
-
// console.log(`${device.deviceName}.forEachAttribute: ${attributes}`);
|
|
1182
1001
|
return attributes.trimStart().trimEnd();
|
|
1183
1002
|
}
|
|
1184
|
-
/**
|
|
1185
|
-
* Retrieves the base registered plugins sanitized for res.json().
|
|
1186
|
-
* @returns {BaseRegisteredPlugin[]} An array of BaseRegisteredPlugin.
|
|
1187
|
-
*/
|
|
1188
1003
|
getBaseRegisteredPlugins() {
|
|
1189
1004
|
const baseRegisteredPlugins = [];
|
|
1190
1005
|
for (const plugin of this.matterbridge.plugins) {
|
|
@@ -1217,13 +1032,6 @@ export class Frontend {
|
|
|
1217
1032
|
}
|
|
1218
1033
|
return baseRegisteredPlugins;
|
|
1219
1034
|
}
|
|
1220
|
-
/**
|
|
1221
|
-
* Handles incoming websocket messages for the Matterbridge frontend.
|
|
1222
|
-
*
|
|
1223
|
-
* @param {WebSocket} client - The websocket client that sent the message.
|
|
1224
|
-
* @param {WebSocket.RawData} message - The raw data of the message received from the client.
|
|
1225
|
-
* @returns {Promise<void>} A promise that resolves when the message has been handled.
|
|
1226
|
-
*/
|
|
1227
1035
|
async wsMessageHandler(client, message) {
|
|
1228
1036
|
let data;
|
|
1229
1037
|
try {
|
|
@@ -1344,7 +1152,7 @@ export class Frontend {
|
|
|
1344
1152
|
this.matterbridge.matterbridgeInformation.matterbridgeAdvertise = true;
|
|
1345
1153
|
this.matterbridge.matterbridgeQrPairingCode = pairingCodes?.qrPairingCode;
|
|
1346
1154
|
this.matterbridge.matterbridgeManualPairingCode = pairingCodes?.manualPairingCode;
|
|
1347
|
-
this.wssSendRefreshRequired();
|
|
1155
|
+
this.wssSendRefreshRequired('matterbridgeAdvertise');
|
|
1348
1156
|
this.wssSendSnackbarMessage(`Started fabrics share`, 0);
|
|
1349
1157
|
client.send(JSON.stringify({ id: data.id, method: data.method, src: 'Matterbridge', dst: data.src, response: pairingCodes }));
|
|
1350
1158
|
return;
|
|
@@ -1352,7 +1160,7 @@ export class Frontend {
|
|
|
1352
1160
|
else if (data.method === '/api/stopadvertise') {
|
|
1353
1161
|
await this.matterbridge.stopAdvertiseServerNode(this.matterbridge.serverNode);
|
|
1354
1162
|
this.matterbridge.matterbridgeInformation.matterbridgeAdvertise = false;
|
|
1355
|
-
this.wssSendRefreshRequired();
|
|
1163
|
+
this.wssSendRefreshRequired('matterbridgeAdvertise');
|
|
1356
1164
|
this.wssSendSnackbarMessage(`Stopped fabrics share`, 0);
|
|
1357
1165
|
client.send(JSON.stringify({ id: data.id, method: data.method, src: 'Matterbridge', dst: data.src }));
|
|
1358
1166
|
return;
|
|
@@ -1369,10 +1177,8 @@ export class Frontend {
|
|
|
1369
1177
|
else if (data.method === '/api/devices') {
|
|
1370
1178
|
const devices = [];
|
|
1371
1179
|
this.matterbridge.devices.forEach(async (device) => {
|
|
1372
|
-
// Filter by pluginName if provided
|
|
1373
1180
|
if (data.params.pluginName && data.params.pluginName !== device.plugin)
|
|
1374
1181
|
return;
|
|
1375
|
-
// Check if the device has the required properties
|
|
1376
1182
|
if (!device.plugin || !device.name || !device.deviceName || !device.serialNumber || !device.uniqueId || !device.lifecycle.isReady)
|
|
1377
1183
|
return;
|
|
1378
1184
|
const cluster = this.getClusterTextFromDevice(device);
|
|
@@ -1456,7 +1262,6 @@ export class Frontend {
|
|
|
1456
1262
|
});
|
|
1457
1263
|
endpointServer.getChildEndpoints().forEach((childEndpoint) => {
|
|
1458
1264
|
deviceTypes = [];
|
|
1459
|
-
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
1460
1265
|
const name = childEndpoint.endpoint?.id;
|
|
1461
1266
|
const clusterServers = childEndpoint.getAllClusterServers();
|
|
1462
1267
|
clusterServers.forEach((clusterServer) => {
|
|
@@ -1510,7 +1315,6 @@ export class Frontend {
|
|
|
1510
1315
|
client.send(JSON.stringify({ id: data.id, method: data.method, src: 'Matterbridge', dst: data.src, error: 'Plugin not found in /api/select' }));
|
|
1511
1316
|
return;
|
|
1512
1317
|
}
|
|
1513
|
-
// const selectDeviceValues = plugin.platform?.selectDevice ? Array.from(plugin.platform.selectDevice.values()).sort((keyA, keyB) => keyA.name.localeCompare(keyB.name)) : [];
|
|
1514
1318
|
const selectDeviceValues = plugin.platform?.getSelectDevices().sort((keyA, keyB) => keyA.name.localeCompare(keyB.name));
|
|
1515
1319
|
client.send(JSON.stringify({ id: data.id, method: data.method, src: 'Matterbridge', dst: data.src, plugin: data.params.plugin, response: selectDeviceValues }));
|
|
1516
1320
|
return;
|
|
@@ -1525,7 +1329,6 @@ export class Frontend {
|
|
|
1525
1329
|
client.send(JSON.stringify({ id: data.id, method: data.method, src: 'Matterbridge', dst: data.src, error: 'Plugin not found in /api/select/entities' }));
|
|
1526
1330
|
return;
|
|
1527
1331
|
}
|
|
1528
|
-
// const selectEntityValues = plugin.platform?.selectDevice ? Array.from(plugin.platform.selectEntity.values()).sort((keyA, keyB) => keyA.name.localeCompare(keyB.name)) : [];
|
|
1529
1332
|
const selectEntityValues = plugin.platform?.getSelectEntities().sort((keyA, keyB) => keyA.name.localeCompare(keyB.name));
|
|
1530
1333
|
client.send(JSON.stringify({ id: data.id, method: data.method, src: 'Matterbridge', dst: data.src, plugin: data.params.plugin, response: selectEntityValues }));
|
|
1531
1334
|
return;
|
|
@@ -1546,13 +1349,11 @@ export class Frontend {
|
|
|
1546
1349
|
if (config.postfix) {
|
|
1547
1350
|
data.params.serial = data.params.serial.replace('-' + config.postfix, '');
|
|
1548
1351
|
}
|
|
1549
|
-
// Add the serial to the whiteList if the whiteList exists and the serial is not already in it
|
|
1550
1352
|
if (isValidArray(config.whiteList, 1)) {
|
|
1551
1353
|
if (!config.whiteList.includes(data.params.serial)) {
|
|
1552
1354
|
config.whiteList.push(data.params.serial);
|
|
1553
1355
|
}
|
|
1554
1356
|
}
|
|
1555
|
-
// Remove the serial from the blackList if the blackList exists and the serial is in it
|
|
1556
1357
|
if (isValidArray(config.blackList, 1)) {
|
|
1557
1358
|
if (config.blackList.includes(data.params.serial)) {
|
|
1558
1359
|
config.blackList = config.blackList.filter((serial) => serial !== data.params.serial);
|
|
@@ -1561,7 +1362,7 @@ export class Frontend {
|
|
|
1561
1362
|
if (plugin.platform)
|
|
1562
1363
|
plugin.platform.config = config;
|
|
1563
1364
|
await this.matterbridge.plugins.saveConfigFromPlugin(plugin);
|
|
1564
|
-
this.wssSendRestartRequired();
|
|
1365
|
+
this.wssSendRestartRequired(false);
|
|
1565
1366
|
}
|
|
1566
1367
|
}
|
|
1567
1368
|
else if (data.params.command === 'unselectdevice' && isValidString(data.params.plugin, 10) && isValidString(data.params.serial, 1)) {
|
|
@@ -1575,7 +1376,11 @@ export class Frontend {
|
|
|
1575
1376
|
if (config.postfix) {
|
|
1576
1377
|
data.params.serial = data.params.serial.replace('-' + config.postfix, '');
|
|
1577
1378
|
}
|
|
1578
|
-
|
|
1379
|
+
if (isValidArray(config.whiteList, 1)) {
|
|
1380
|
+
if (config.whiteList.includes(data.params.serial)) {
|
|
1381
|
+
config.whiteList = config.whiteList.filter((serial) => serial !== data.params.serial);
|
|
1382
|
+
}
|
|
1383
|
+
}
|
|
1579
1384
|
if (isValidArray(config.blackList)) {
|
|
1580
1385
|
if (!config.blackList.includes(data.params.serial)) {
|
|
1581
1386
|
config.blackList.push(data.params.serial);
|
|
@@ -1584,7 +1389,7 @@ export class Frontend {
|
|
|
1584
1389
|
if (plugin.platform)
|
|
1585
1390
|
plugin.platform.config = config;
|
|
1586
1391
|
await this.matterbridge.plugins.saveConfigFromPlugin(plugin);
|
|
1587
|
-
this.wssSendRestartRequired();
|
|
1392
|
+
this.wssSendRestartRequired(false);
|
|
1588
1393
|
}
|
|
1589
1394
|
}
|
|
1590
1395
|
}
|
|
@@ -1599,139 +1404,94 @@ export class Frontend {
|
|
|
1599
1404
|
return;
|
|
1600
1405
|
}
|
|
1601
1406
|
}
|
|
1602
|
-
/**
|
|
1603
|
-
* Sends a WebSocket message to all connected clients. The function is called by AnsiLogger.setGlobalCallback.
|
|
1604
|
-
*
|
|
1605
|
-
* @param {string} level - The logger level of the message: debug info notice warn error fatal...
|
|
1606
|
-
* @param {string} time - The time string of the message
|
|
1607
|
-
* @param {string} name - The logger name of the message
|
|
1608
|
-
* @param {string} message - The content of the message.
|
|
1609
|
-
*/
|
|
1610
1407
|
wssSendMessage(level, time, name, message) {
|
|
1611
1408
|
if (!level || !time || !name || !message)
|
|
1612
1409
|
return;
|
|
1613
|
-
// Remove ANSI escape codes from the message
|
|
1614
|
-
// eslint-disable-next-line no-control-regex
|
|
1615
1410
|
message = message.replace(/\x1B\[[0-9;]*[m|s|u|K]/g, '');
|
|
1616
|
-
// Remove leading asterisks from the message
|
|
1617
1411
|
message = message.replace(/^\*+/, '');
|
|
1618
|
-
// Replace all occurrences of \t and \n
|
|
1619
1412
|
message = message.replace(/[\t\n]/g, '');
|
|
1620
|
-
// Remove non-printable characters
|
|
1621
|
-
// eslint-disable-next-line no-control-regex
|
|
1622
1413
|
message = message.replace(/[\x00-\x1F\x7F]/g, '');
|
|
1623
|
-
// Replace all occurrences of \" with "
|
|
1624
1414
|
message = message.replace(/\\"/g, '"');
|
|
1625
|
-
// Define the maximum allowed length for continuous characters without a space
|
|
1626
1415
|
const maxContinuousLength = 100;
|
|
1627
1416
|
const keepStartLength = 20;
|
|
1628
1417
|
const keepEndLength = 20;
|
|
1629
|
-
// Split the message into words
|
|
1630
1418
|
message = message
|
|
1631
1419
|
.split(' ')
|
|
1632
1420
|
.map((word) => {
|
|
1633
|
-
// If the word length exceeds the max continuous length, insert spaces and truncate
|
|
1634
1421
|
if (word.length > maxContinuousLength) {
|
|
1635
1422
|
return word.slice(0, keepStartLength) + ' ... ' + word.slice(-keepEndLength);
|
|
1636
1423
|
}
|
|
1637
1424
|
return word;
|
|
1638
1425
|
})
|
|
1639
1426
|
.join(' ');
|
|
1640
|
-
// Send the message to all connected clients
|
|
1641
1427
|
this.webSocketServer?.clients.forEach((client) => {
|
|
1642
1428
|
if (client.readyState === WebSocket.OPEN) {
|
|
1643
1429
|
client.send(JSON.stringify({ id: WS_ID_LOG, src: 'Matterbridge', level, time, name, message }));
|
|
1644
1430
|
}
|
|
1645
1431
|
});
|
|
1646
1432
|
}
|
|
1647
|
-
|
|
1648
|
-
* Sends a need to refresh WebSocket message to all connected clients.
|
|
1649
|
-
*
|
|
1650
|
-
*/
|
|
1651
|
-
wssSendRefreshRequired() {
|
|
1433
|
+
wssSendRefreshRequired(changed = null) {
|
|
1652
1434
|
this.log.debug('Sending a refresh required message to all connected clients');
|
|
1653
|
-
this.matterbridge.matterbridgeInformation.refreshRequired = true;
|
|
1654
|
-
// Send the message to all connected clients
|
|
1655
1435
|
this.webSocketServer?.clients.forEach((client) => {
|
|
1656
1436
|
if (client.readyState === WebSocket.OPEN) {
|
|
1657
|
-
client.send(JSON.stringify({ id: WS_ID_REFRESH_NEEDED, src: 'Matterbridge', dst: 'Frontend', method: 'refresh_required', params: {} }));
|
|
1437
|
+
client.send(JSON.stringify({ id: WS_ID_REFRESH_NEEDED, src: 'Matterbridge', dst: 'Frontend', method: 'refresh_required', params: { changed: changed } }));
|
|
1658
1438
|
}
|
|
1659
1439
|
});
|
|
1660
1440
|
}
|
|
1661
|
-
|
|
1662
|
-
* Sends a need to restart WebSocket message to all connected clients.
|
|
1663
|
-
*
|
|
1664
|
-
*/
|
|
1665
|
-
wssSendRestartRequired() {
|
|
1441
|
+
wssSendRestartRequired(snackbar = true) {
|
|
1666
1442
|
this.log.debug('Sending a restart required message to all connected clients');
|
|
1667
1443
|
this.matterbridge.matterbridgeInformation.restartRequired = true;
|
|
1668
|
-
|
|
1669
|
-
|
|
1444
|
+
if (snackbar === true)
|
|
1445
|
+
this.wssSendSnackbarMessage(`Restart required`, 0);
|
|
1670
1446
|
this.webSocketServer?.clients.forEach((client) => {
|
|
1671
1447
|
if (client.readyState === WebSocket.OPEN) {
|
|
1672
1448
|
client.send(JSON.stringify({ id: WS_ID_RESTART_NEEDED, src: 'Matterbridge', dst: 'Frontend', method: 'restart_required', params: {} }));
|
|
1673
1449
|
}
|
|
1674
1450
|
});
|
|
1675
1451
|
}
|
|
1676
|
-
|
|
1677
|
-
|
|
1678
|
-
|
|
1679
|
-
|
|
1452
|
+
wssSendUpdateRequired() {
|
|
1453
|
+
this.log.debug('Sending an update required message to all connected clients');
|
|
1454
|
+
this.matterbridge.matterbridgeInformation.updateRequired = true;
|
|
1455
|
+
this.webSocketServer?.clients.forEach((client) => {
|
|
1456
|
+
if (client.readyState === WebSocket.OPEN) {
|
|
1457
|
+
client.send(JSON.stringify({ id: WS_ID_UPDATE_NEEDED, src: 'Matterbridge', dst: 'Frontend', method: 'update_required', params: {} }));
|
|
1458
|
+
}
|
|
1459
|
+
});
|
|
1460
|
+
}
|
|
1680
1461
|
wssSendCpuUpdate(cpuUsage) {
|
|
1681
1462
|
this.log.debug('Sending a cpu update message to all connected clients');
|
|
1682
|
-
// Send the message to all connected clients
|
|
1683
1463
|
this.webSocketServer?.clients.forEach((client) => {
|
|
1684
1464
|
if (client.readyState === WebSocket.OPEN) {
|
|
1685
1465
|
client.send(JSON.stringify({ id: WS_ID_CPU_UPDATE, src: 'Matterbridge', dst: 'Frontend', method: 'cpu_update', params: { cpuUsage } }));
|
|
1686
1466
|
}
|
|
1687
1467
|
});
|
|
1688
1468
|
}
|
|
1689
|
-
/**
|
|
1690
|
-
* Sends a cpu update message to all connected clients.
|
|
1691
|
-
*
|
|
1692
|
-
*/
|
|
1693
1469
|
wssSendMemoryUpdate(totalMemory, freeMemory, rss, heapTotal, heapUsed, external, arrayBuffers) {
|
|
1694
1470
|
this.log.debug('Sending a memory update message to all connected clients');
|
|
1695
|
-
// Send the message to all connected clients
|
|
1696
1471
|
this.webSocketServer?.clients.forEach((client) => {
|
|
1697
1472
|
if (client.readyState === WebSocket.OPEN) {
|
|
1698
1473
|
client.send(JSON.stringify({ id: WS_ID_MEMORY_UPDATE, src: 'Matterbridge', dst: 'Frontend', method: 'memory_update', params: { totalMemory, freeMemory, rss, heapTotal, heapUsed, external, arrayBuffers } }));
|
|
1699
1474
|
}
|
|
1700
1475
|
});
|
|
1701
1476
|
}
|
|
1702
|
-
/**
|
|
1703
|
-
* Sends a memory update message to all connected clients.
|
|
1704
|
-
*
|
|
1705
|
-
*/
|
|
1706
1477
|
wssSendUptimeUpdate(systemUptime, processUptime) {
|
|
1707
1478
|
this.log.debug('Sending a uptime update message to all connected clients');
|
|
1708
|
-
// Send the message to all connected clients
|
|
1709
1479
|
this.webSocketServer?.clients.forEach((client) => {
|
|
1710
1480
|
if (client.readyState === WebSocket.OPEN) {
|
|
1711
1481
|
client.send(JSON.stringify({ id: WS_ID_UPTIME_UPDATE, src: 'Matterbridge', dst: 'Frontend', method: 'uptime_update', params: { systemUptime, processUptime } }));
|
|
1712
1482
|
}
|
|
1713
1483
|
});
|
|
1714
1484
|
}
|
|
1715
|
-
/**
|
|
1716
|
-
* Sends a cpu update message to all connected clients.
|
|
1717
|
-
*
|
|
1718
|
-
*/
|
|
1719
1485
|
wssSendSnackbarMessage(message, timeout = 5) {
|
|
1720
1486
|
this.log.debug('Sending a snackbar message to all connected clients');
|
|
1721
|
-
// Send the message to all connected clients
|
|
1722
1487
|
this.webSocketServer?.clients.forEach((client) => {
|
|
1723
1488
|
if (client.readyState === WebSocket.OPEN) {
|
|
1724
1489
|
client.send(JSON.stringify({ id: WS_ID_SNACKBAR, src: 'Matterbridge', dst: 'Frontend', method: 'memory_update', params: { message, timeout } }));
|
|
1725
1490
|
}
|
|
1726
1491
|
});
|
|
1727
1492
|
}
|
|
1728
|
-
/**
|
|
1729
|
-
* Sends a message to all connected clients.
|
|
1730
|
-
*
|
|
1731
|
-
*/
|
|
1732
1493
|
wssBroadcastMessage(id, method, params) {
|
|
1733
1494
|
this.log.debug(`Sending a broadcast message id ${id} method ${method} params ${debugStringify(params ?? {})} to all connected clients`);
|
|
1734
|
-
// Send the message to all connected clients
|
|
1735
1495
|
this.webSocketServer?.clients.forEach((client) => {
|
|
1736
1496
|
if (client.readyState === WebSocket.OPEN) {
|
|
1737
1497
|
client.send(JSON.stringify({ id, src: 'Matterbridge', dst: 'Frontend', method, params }));
|
|
@@ -1739,4 +1499,3 @@ export class Frontend {
|
|
|
1739
1499
|
});
|
|
1740
1500
|
}
|
|
1741
1501
|
}
|
|
1742
|
-
//# sourceMappingURL=frontend.js.map
|