matterbridge 1.7.0 → 1.7.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 +52 -9
- package/README-EDGE.md +4 -6
- package/README-SERVICE.md +2 -2
- package/dist/cli.js +0 -26
- package/dist/cluster/export.js +0 -2
- package/dist/defaultConfigSchema.js +0 -23
- package/dist/deviceManager.js +1 -26
- package/dist/index.js +0 -30
- package/dist/logger/export.js +0 -1
- package/dist/matter/export.js +0 -4
- package/dist/matterbridge.js +61 -707
- package/dist/matterbridgeAccessoryPlatform.js +0 -33
- package/dist/matterbridgeBehaviors.js +1 -29
- package/dist/matterbridgeDevice.js +9 -996
- package/dist/matterbridgeDeviceTypes.js +11 -82
- package/dist/matterbridgeDynamicPlatform.js +0 -33
- package/dist/matterbridgeEdge.js +0 -530
- package/dist/matterbridgeEndpoint.js +14 -1121
- package/dist/matterbridgePlatform.js +8 -112
- package/dist/matterbridgeTypes.js +0 -24
- package/dist/matterbridgeWebsocket.js +60 -49
- package/dist/pluginManager.js +3 -238
- package/dist/storage/export.js +0 -1
- package/dist/utils/colorUtils.js +2 -205
- package/dist/utils/export.js +0 -1
- package/dist/utils/utils.js +7 -252
- package/frontend/build/asset-manifest.json +6 -6
- package/frontend/build/index.html +1 -1
- package/frontend/build/static/css/{main.f1fce054.css → main.b1a621ee.css} +2 -2
- package/frontend/build/static/css/main.b1a621ee.css.map +1 -0
- package/frontend/build/static/js/{main.5caad8c7.js → main.0cc31fc9.js} +10 -10
- package/frontend/build/static/js/main.0cc31fc9.js.map +1 -0
- package/npm-shrinkwrap.json +8 -8
- package/package.json +1 -2
- package/dist/cli.d.ts +0 -25
- 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 -46
- package/dist/deviceManager.d.ts.map +0 -1
- package/dist/deviceManager.js.map +0 -1
- package/dist/index.d.ts +0 -40
- 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/export.d.ts +0 -11
- package/dist/matter/export.d.ts.map +0 -1
- package/dist/matter/export.js.map +0 -1
- package/dist/matterbridge.d.ts +0 -483
- 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 -942
- package/dist/matterbridgeBehaviors.d.ts.map +0 -1
- package/dist/matterbridgeBehaviors.js.map +0 -1
- package/dist/matterbridgeDevice.d.ts +0 -7077
- package/dist/matterbridgeDevice.d.ts.map +0 -1
- package/dist/matterbridgeDevice.js.map +0 -1
- package/dist/matterbridgeDeviceTypes.d.ts +0 -109
- 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/matterbridgeEdge.d.ts +0 -91
- package/dist/matterbridgeEdge.d.ts.map +0 -1
- package/dist/matterbridgeEdge.js.map +0 -1
- package/dist/matterbridgeEndpoint.d.ts +0 -10151
- package/dist/matterbridgeEndpoint.d.ts.map +0 -1
- package/dist/matterbridgeEndpoint.js.map +0 -1
- package/dist/matterbridgePlatform.d.ts +0 -140
- package/dist/matterbridgePlatform.d.ts.map +0 -1
- package/dist/matterbridgePlatform.js.map +0 -1
- package/dist/matterbridgeTypes.d.ts +0 -169
- package/dist/matterbridgeTypes.d.ts.map +0 -1
- package/dist/matterbridgeTypes.js.map +0 -1
- package/dist/matterbridgeWebsocket.d.ts +0 -49
- package/dist/matterbridgeWebsocket.d.ts.map +0 -1
- package/dist/matterbridgeWebsocket.js.map +0 -1
- package/dist/pluginManager.d.ts +0 -238
- package/dist/pluginManager.d.ts.map +0 -1
- package/dist/pluginManager.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/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/export.d.ts +0 -3
- package/dist/utils/export.d.ts.map +0 -1
- package/dist/utils/export.js.map +0 -1
- package/dist/utils/utils.d.ts +0 -221
- package/dist/utils/utils.d.ts.map +0 -1
- package/dist/utils/utils.js.map +0 -1
- package/frontend/build/static/css/main.f1fce054.css.map +0 -1
- package/frontend/build/static/js/main.5caad8c7.js.map +0 -1
- /package/frontend/build/static/js/{main.5caad8c7.js.LICENSE.txt → main.0cc31fc9.js.LICENSE.txt} +0 -0
package/dist/matterbridge.js
CHANGED
|
@@ -1,26 +1,3 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* This file contains the class Matterbridge.
|
|
3
|
-
*
|
|
4
|
-
* @file matterbridge.ts
|
|
5
|
-
* @author Luca Liguori
|
|
6
|
-
* @date 2023-12-29
|
|
7
|
-
* @version 1.5.2
|
|
8
|
-
*
|
|
9
|
-
* Copyright 2023, 2024, 2025 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
|
-
// Node.js modules
|
|
24
1
|
import { fileURLToPath } from 'url';
|
|
25
2
|
import { promises as fs } from 'fs';
|
|
26
3
|
import { exec, spawn } from 'child_process';
|
|
@@ -29,36 +6,27 @@ import EventEmitter from 'events';
|
|
|
29
6
|
import os from 'os';
|
|
30
7
|
import path from 'path';
|
|
31
8
|
import { randomBytes } from 'crypto';
|
|
32
|
-
// Package modules
|
|
33
9
|
import https from 'https';
|
|
34
10
|
import express from 'express';
|
|
35
11
|
import WebSocket, { WebSocketServer } from 'ws';
|
|
36
|
-
// NodeStorage and AnsiLogger modules
|
|
37
12
|
import { NodeStorageManager } from 'node-persist-manager';
|
|
38
13
|
import { AnsiLogger, UNDERLINE, UNDERLINEOFF, YELLOW, db, debugStringify, stringify, BRIGHT, RESET, er, nf, rs, wr, RED, GREEN, zb, CYAN, nt, idn, or, hk, BLUE } from 'node-ansi-logger';
|
|
39
|
-
// Matterbridge
|
|
40
14
|
import { MatterbridgeDevice } from './matterbridgeDevice.js';
|
|
41
15
|
import { WS_ID_LOG, WS_ID_REFRESH_NEEDED, WS_ID_RESTART_NEEDED, wsMessageHandler } from './matterbridgeWebsocket.js';
|
|
42
16
|
import { logInterfaces, wait, waiter, createZip, copyDirectory, getParameter, getIntParameter, hasParameter } from './utils/utils.js';
|
|
43
17
|
import { PluginManager } from './pluginManager.js';
|
|
44
18
|
import { DeviceManager } from './deviceManager.js';
|
|
45
19
|
import { MatterbridgeEndpoint } from './matterbridgeEndpoint.js';
|
|
46
|
-
// @matter
|
|
47
20
|
import { DeviceTypeId, Logger, LogLevel as MatterLogLevel, LogFormat as MatterLogFormat, VendorId, StorageManager, EndpointServer, StorageService, Environment } from '@matter/main';
|
|
48
21
|
import { BasicInformationCluster, BridgedDeviceBasicInformation, BridgedDeviceBasicInformationCluster, FixedLabelCluster, GeneralCommissioning, PowerSourceCluster, SwitchCluster, ThreadNetworkDiagnosticsCluster, UserLabelCluster, } from '@matter/main/clusters';
|
|
49
22
|
import { getClusterNameById, ManualPairingCodeCodec, QrCodeSchema } from '@matter/main/types';
|
|
50
23
|
import { StorageBackendDisk, StorageBackendJsonFile } from '@matter/nodejs';
|
|
51
|
-
// @project-chip
|
|
52
24
|
import { CommissioningController, CommissioningServer, MatterServer } from '@project-chip/matter.js';
|
|
53
25
|
import { Aggregator, DeviceTypes, NodeStateInformation } from '@project-chip/matter.js/device';
|
|
54
26
|
import { aggregator } from './matterbridgeDeviceTypes.js';
|
|
55
|
-
// Default colors
|
|
56
27
|
const plg = '\u001B[38;5;33m';
|
|
57
28
|
const dev = '\u001B[38;5;79m';
|
|
58
29
|
const typ = '\u001B[38;5;207m';
|
|
59
|
-
/**
|
|
60
|
-
* Represents the Matterbridge application.
|
|
61
|
-
*/
|
|
62
30
|
export class Matterbridge extends EventEmitter {
|
|
63
31
|
systemInformation = {
|
|
64
32
|
interfaceName: '',
|
|
@@ -95,7 +63,7 @@ export class Matterbridge extends EventEmitter {
|
|
|
95
63
|
edge: hasParameter('edge'),
|
|
96
64
|
readOnly: hasParameter('readonly'),
|
|
97
65
|
profile: getParameter('profile'),
|
|
98
|
-
loggerLevel: "info"
|
|
66
|
+
loggerLevel: "info",
|
|
99
67
|
fileLogger: false,
|
|
100
68
|
matterLoggerLevel: MatterLogLevel.INFO,
|
|
101
69
|
matterFileLogger: false,
|
|
@@ -134,7 +102,6 @@ export class Matterbridge extends EventEmitter {
|
|
|
134
102
|
nodeContext;
|
|
135
103
|
matterStorageName = 'matterbridge' + (getParameter('profile') ? '.' + getParameter('profile') : '') + '.json';
|
|
136
104
|
nodeStorageName = 'storage' + (getParameter('profile') ? '.' + getParameter('profile') : '');
|
|
137
|
-
// Cleanup
|
|
138
105
|
hasCleanupStarted = false;
|
|
139
106
|
initialized = false;
|
|
140
107
|
execRunningCount = 0;
|
|
@@ -146,18 +113,16 @@ export class Matterbridge extends EventEmitter {
|
|
|
146
113
|
sigtermHandler;
|
|
147
114
|
exceptionHandler;
|
|
148
115
|
rejectionHandler;
|
|
149
|
-
// Frontend
|
|
150
116
|
expressApp;
|
|
151
117
|
httpServer;
|
|
152
118
|
httpsServer;
|
|
153
119
|
webSocketServer;
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
discriminator; // first commissioning server discriminator
|
|
120
|
+
mdnsInterface;
|
|
121
|
+
ipv4address;
|
|
122
|
+
ipv6address;
|
|
123
|
+
port = 5540;
|
|
124
|
+
passcode;
|
|
125
|
+
discriminator;
|
|
161
126
|
storageManager;
|
|
162
127
|
matterbridgeContext;
|
|
163
128
|
mattercontrollerContext;
|
|
@@ -168,40 +133,19 @@ export class Matterbridge extends EventEmitter {
|
|
|
168
133
|
aggregatorVendorId = VendorId(getIntParameter('vendorId') ?? 0xfff1);
|
|
169
134
|
aggregatorProductId = getIntParameter('productId') ?? 0x8000;
|
|
170
135
|
static instance;
|
|
171
|
-
// We load asyncronously so is private
|
|
172
136
|
constructor() {
|
|
173
137
|
super();
|
|
174
|
-
// Bind the handler to the instance
|
|
175
138
|
this.matterbridgeMessageHandler = wsMessageHandler.bind(this);
|
|
176
139
|
}
|
|
177
|
-
/**
|
|
178
|
-
* Retrieves the list of Matterbridge devices.
|
|
179
|
-
* @returns {MatterbridgeDevice[]} An array of MatterbridgeDevice objects.
|
|
180
|
-
*/
|
|
181
140
|
getDevices() {
|
|
182
141
|
return this.devices.array();
|
|
183
142
|
}
|
|
184
|
-
/**
|
|
185
|
-
* Retrieves the list of registered plugins.
|
|
186
|
-
* @returns {RegisteredPlugin[]} An array of RegisteredPlugin objects.
|
|
187
|
-
*/
|
|
188
143
|
getPlugins() {
|
|
189
144
|
return this.plugins.array();
|
|
190
145
|
}
|
|
191
146
|
matterbridgeMessageHandler;
|
|
192
|
-
/** ***********************************************************************************************************************************/
|
|
193
|
-
/** loadInstance() and cleanup() methods */
|
|
194
|
-
/** ***********************************************************************************************************************************/
|
|
195
|
-
/**
|
|
196
|
-
* Loads an instance of the Matterbridge class.
|
|
197
|
-
* If an instance already exists, return that instance.
|
|
198
|
-
*
|
|
199
|
-
* @param initialize - Whether to initialize the Matterbridge instance after loading.
|
|
200
|
-
* @returns The loaded Matterbridge instance.
|
|
201
|
-
*/
|
|
202
147
|
static async loadInstance(initialize = false) {
|
|
203
148
|
if (!Matterbridge.instance) {
|
|
204
|
-
// eslint-disable-next-line no-console
|
|
205
149
|
if (hasParameter('debug'))
|
|
206
150
|
console.log(GREEN + 'Creating a new instance of Matterbridge.', initialize ? 'Initializing...' : 'Not initializing...', rs);
|
|
207
151
|
Matterbridge.instance = new Matterbridge();
|
|
@@ -210,11 +154,6 @@ export class Matterbridge extends EventEmitter {
|
|
|
210
154
|
}
|
|
211
155
|
return Matterbridge.instance;
|
|
212
156
|
}
|
|
213
|
-
/**
|
|
214
|
-
* Call cleanup().
|
|
215
|
-
* @deprecated This method is deprecated and is only used for jest tests.
|
|
216
|
-
*
|
|
217
|
-
*/
|
|
218
157
|
async destroyInstance() {
|
|
219
158
|
await this.cleanup('destroying instance...', false);
|
|
220
159
|
await waiter('destroying instance...', () => {
|
|
@@ -222,60 +161,39 @@ export class Matterbridge extends EventEmitter {
|
|
|
222
161
|
}, false, 60000, 100, false);
|
|
223
162
|
await wait(1000, 'Wait for the global node_modules and matterbridge version', false);
|
|
224
163
|
}
|
|
225
|
-
/**
|
|
226
|
-
* Initializes the Matterbridge application.
|
|
227
|
-
*
|
|
228
|
-
* @remarks
|
|
229
|
-
* This method performs the necessary setup and initialization steps for the Matterbridge application.
|
|
230
|
-
* It displays the help information if the 'help' parameter is provided, sets up the logger, checks the
|
|
231
|
-
* node version, registers signal handlers, initializes storage, and parses the command line.
|
|
232
|
-
*
|
|
233
|
-
* @returns A Promise that resolves when the initialization is complete.
|
|
234
|
-
*/
|
|
235
164
|
async initialize() {
|
|
236
|
-
// Set the restart mode
|
|
237
165
|
if (hasParameter('service'))
|
|
238
166
|
this.restartMode = 'service';
|
|
239
167
|
if (hasParameter('docker'))
|
|
240
168
|
this.restartMode = 'docker';
|
|
241
|
-
// Set the matterbridge directory
|
|
242
169
|
this.homeDirectory = getParameter('homedir') ?? os.homedir();
|
|
243
170
|
this.matterbridgeDirectory = path.join(this.homeDirectory, '.matterbridge');
|
|
244
|
-
|
|
245
|
-
this.log = new AnsiLogger({ logName: 'Matterbridge', logTimestampFormat: 4 /* TimestampFormat.TIME_MILLIS */, logLevel: hasParameter('debug') ? "debug" /* LogLevel.DEBUG */ : "info" /* LogLevel.INFO */ });
|
|
246
|
-
// Initialize nodeStorage and nodeContext
|
|
171
|
+
this.log = new AnsiLogger({ logName: 'Matterbridge', logTimestampFormat: 4, logLevel: hasParameter('debug') ? "debug" : "info" });
|
|
247
172
|
try {
|
|
248
173
|
this.log.debug(`Creating node storage manager: ${CYAN}${this.nodeStorageName}${db}`);
|
|
249
174
|
this.nodeStorage = new NodeStorageManager({ dir: path.join(this.matterbridgeDirectory, this.nodeStorageName), writeQueue: false, expiredInterval: undefined, logging: false });
|
|
250
175
|
this.log.debug('Creating node storage context for matterbridge');
|
|
251
176
|
this.nodeContext = await this.nodeStorage.createStorage('matterbridge');
|
|
252
|
-
// TODO: Remove this code when node-persist-manager is updated
|
|
253
|
-
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
254
177
|
const keys = (await this.nodeStorage?.storage.keys());
|
|
255
178
|
for (const key of keys) {
|
|
256
179
|
this.log.debug(`Checking node storage manager key: ${CYAN}${key}${db}`);
|
|
257
|
-
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
258
180
|
await this.nodeStorage?.storage.get(key);
|
|
259
181
|
}
|
|
260
182
|
const storages = await this.nodeStorage.getStorageNames();
|
|
261
183
|
for (const storage of storages) {
|
|
262
184
|
this.log.debug(`Checking storage: ${CYAN}${storage}${db}`);
|
|
263
185
|
const nodeContext = await this.nodeStorage?.createStorage(storage);
|
|
264
|
-
// TODO: Remove this code when node-persist-manager is updated
|
|
265
|
-
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
266
186
|
const keys = (await nodeContext?.storage.keys());
|
|
267
187
|
keys.forEach(async (key) => {
|
|
268
188
|
this.log.debug(`Checking key: ${CYAN}${storage}:${key}${db}`);
|
|
269
189
|
await nodeContext?.get(key);
|
|
270
190
|
});
|
|
271
191
|
}
|
|
272
|
-
// Creating a backup of the node storage since it is not corrupted
|
|
273
192
|
this.log.debug('Creating node storage backup...');
|
|
274
193
|
await copyDirectory(path.join(this.matterbridgeDirectory, this.nodeStorageName), path.join(this.matterbridgeDirectory, this.nodeStorageName + '.backup'));
|
|
275
194
|
this.log.debug('Created node storage backup');
|
|
276
195
|
}
|
|
277
196
|
catch (error) {
|
|
278
|
-
// Restoring the backup of the node storage since it is corrupted
|
|
279
197
|
this.log.error(`Error creating node storage manager and context: ${error instanceof Error ? error.message : error}`);
|
|
280
198
|
if (hasParameter('norestore')) {
|
|
281
199
|
this.log.fatal(`The matterbridge node storage is corrupted. Parameter -norestore found: exiting...`);
|
|
@@ -290,51 +208,45 @@ export class Matterbridge extends EventEmitter {
|
|
|
290
208
|
this.log.fatal('Fatal error creating node storage manager and context for matterbridge');
|
|
291
209
|
throw new Error('Fatal error creating node storage manager and context for matterbridge');
|
|
292
210
|
}
|
|
293
|
-
// Set the first port to use for the commissioning server (will be incremented in childbridge mode)
|
|
294
211
|
this.port = getIntParameter('port') ?? (await this.nodeContext.get('matterport', 5540)) ?? 5540;
|
|
295
|
-
// Set the first passcode to use for the commissioning server (will be incremented in childbridge mode)
|
|
296
212
|
this.passcode = this.passcode ?? getIntParameter('passcode') ?? (await this.nodeContext.get('matterpasscode'));
|
|
297
|
-
// Set the first discriminator to use for the commissioning server (will be incremented in childbridge mode)
|
|
298
213
|
this.discriminator = this.discriminator ?? getIntParameter('discriminator') ?? (await this.nodeContext.get('matterdiscriminator'));
|
|
299
214
|
this.log.debug(`Initializing commissioning server for Matterbridge... on port ${this.port} with passcode ${this.passcode} and discriminator ${this.discriminator}`);
|
|
300
|
-
// Set matterbridge logger level (context: matterbridgeLogLevel)
|
|
301
215
|
if (hasParameter('logger')) {
|
|
302
216
|
const level = getParameter('logger');
|
|
303
217
|
if (level === 'debug') {
|
|
304
|
-
this.log.logLevel = "debug"
|
|
218
|
+
this.log.logLevel = "debug";
|
|
305
219
|
}
|
|
306
220
|
else if (level === 'info') {
|
|
307
|
-
this.log.logLevel = "info"
|
|
221
|
+
this.log.logLevel = "info";
|
|
308
222
|
}
|
|
309
223
|
else if (level === 'notice') {
|
|
310
|
-
this.log.logLevel = "notice"
|
|
224
|
+
this.log.logLevel = "notice";
|
|
311
225
|
}
|
|
312
226
|
else if (level === 'warn') {
|
|
313
|
-
this.log.logLevel = "warn"
|
|
227
|
+
this.log.logLevel = "warn";
|
|
314
228
|
}
|
|
315
229
|
else if (level === 'error') {
|
|
316
|
-
this.log.logLevel = "error"
|
|
230
|
+
this.log.logLevel = "error";
|
|
317
231
|
}
|
|
318
232
|
else if (level === 'fatal') {
|
|
319
|
-
this.log.logLevel = "fatal"
|
|
233
|
+
this.log.logLevel = "fatal";
|
|
320
234
|
}
|
|
321
235
|
else {
|
|
322
236
|
this.log.warn(`Invalid matterbridge logger level: ${level}. Using default level "info".`);
|
|
323
|
-
this.log.logLevel = "info"
|
|
237
|
+
this.log.logLevel = "info";
|
|
324
238
|
}
|
|
325
239
|
}
|
|
326
240
|
else {
|
|
327
|
-
this.log.logLevel = await this.nodeContext.get('matterbridgeLogLevel', "info"
|
|
241
|
+
this.log.logLevel = await this.nodeContext.get('matterbridgeLogLevel', "info");
|
|
328
242
|
}
|
|
329
243
|
MatterbridgeDevice.logLevel = this.log.logLevel;
|
|
330
|
-
// Create the file logger for matterbridge (context: matterbridgeFileLog)
|
|
331
244
|
if (hasParameter('filelogger') || (await this.nodeContext.get('matterbridgeFileLog', false))) {
|
|
332
245
|
AnsiLogger.setGlobalLogfile(path.join(this.matterbridgeDirectory, this.matterbrideLoggerFile), this.log.logLevel, true);
|
|
333
246
|
this.matterbridgeInformation.fileLogger = true;
|
|
334
247
|
}
|
|
335
248
|
this.log.notice('Matterbridge is starting...');
|
|
336
249
|
this.log.debug(`Matterbridge logLevel: ${this.log.logLevel} fileLoger: ${this.matterbridgeInformation.fileLogger}.`);
|
|
337
|
-
// Set matter.js logger level, format and logger (context: matterLogLevel)
|
|
338
250
|
if (hasParameter('matterlogger')) {
|
|
339
251
|
const level = getParameter('matterlogger');
|
|
340
252
|
if (level === 'debug') {
|
|
@@ -365,7 +277,6 @@ export class Matterbridge extends EventEmitter {
|
|
|
365
277
|
}
|
|
366
278
|
Logger.format = MatterLogFormat.ANSI;
|
|
367
279
|
Logger.setLogger('default', this.createMatterLogger());
|
|
368
|
-
// Create the file logger for matter.js (context: matterFileLog)
|
|
369
280
|
if (hasParameter('matterfilelogger') || (await this.nodeContext.get('matterFileLog', false))) {
|
|
370
281
|
this.matterbridgeInformation.matterFileLogger = true;
|
|
371
282
|
Logger.addLogger('matterfilelogger', await this.createMatterFileLogger(path.join(this.matterbridgeDirectory, this.matterLoggerFile), true), {
|
|
@@ -374,7 +285,6 @@ export class Matterbridge extends EventEmitter {
|
|
|
374
285
|
});
|
|
375
286
|
}
|
|
376
287
|
this.log.debug(`Matter logLevel: ${Logger.defaultLogLevel} fileLoger: ${this.matterbridgeInformation.matterFileLogger}.`);
|
|
377
|
-
// Set the interface to use for the matter server mdnsInterface
|
|
378
288
|
if (hasParameter('mdnsinterface')) {
|
|
379
289
|
this.mdnsInterface = getParameter('mdnsinterface');
|
|
380
290
|
}
|
|
@@ -383,7 +293,6 @@ export class Matterbridge extends EventEmitter {
|
|
|
383
293
|
if (this.mdnsInterface === '')
|
|
384
294
|
this.mdnsInterface = undefined;
|
|
385
295
|
}
|
|
386
|
-
// Set the listeningAddressIpv4 for the matter commissioning server
|
|
387
296
|
if (hasParameter('ipv4address')) {
|
|
388
297
|
this.ipv4address = getParameter('ipv4address');
|
|
389
298
|
}
|
|
@@ -392,7 +301,6 @@ export class Matterbridge extends EventEmitter {
|
|
|
392
301
|
if (this.ipv4address === '')
|
|
393
302
|
this.ipv4address = undefined;
|
|
394
303
|
}
|
|
395
|
-
// Set the listeningAddressIpv6 for the matter commissioning server
|
|
396
304
|
if (hasParameter('ipv6address')) {
|
|
397
305
|
this.ipv6address = getParameter('ipv6address');
|
|
398
306
|
}
|
|
@@ -401,23 +309,17 @@ export class Matterbridge extends EventEmitter {
|
|
|
401
309
|
if (this.ipv6address === '')
|
|
402
310
|
this.ipv6address = undefined;
|
|
403
311
|
}
|
|
404
|
-
// Initialize PluginManager
|
|
405
312
|
this.plugins = new PluginManager(this);
|
|
406
313
|
await this.plugins.loadFromStorage();
|
|
407
|
-
// Initialize DeviceManager
|
|
408
314
|
this.devices = new DeviceManager(this, this.nodeContext);
|
|
409
|
-
// Get the plugins from node storage and create the plugins node storage contexts
|
|
410
315
|
for (const plugin of this.plugins) {
|
|
411
316
|
const packageJson = await this.plugins.parse(plugin);
|
|
412
317
|
if (packageJson === null && !hasParameter('add')) {
|
|
413
|
-
// Try to reinstall the plugin from npm (for Docker pull and external plugins)
|
|
414
|
-
// We don't do this when the add parameter is set because we shut down the process after adding the plugin
|
|
415
318
|
this.log.info(`Error parsing plugin ${plg}${plugin.name}${nf}. Trying to reinstall it from npm.`);
|
|
416
319
|
try {
|
|
417
320
|
await this.spawnCommand('npm', ['install', '-g', plugin.name, '--omit=dev', '--verbose']);
|
|
418
321
|
this.log.info(`Plugin ${plg}${plugin.name}${nf} reinstalled.`);
|
|
419
322
|
plugin.error = false;
|
|
420
|
-
// eslint-disable-next-line @typescript-eslint/no-unused-vars
|
|
421
323
|
}
|
|
422
324
|
catch (error) {
|
|
423
325
|
plugin.error = true;
|
|
@@ -434,7 +336,6 @@ export class Matterbridge extends EventEmitter {
|
|
|
434
336
|
await plugin.nodeContext.set('description', plugin.description);
|
|
435
337
|
await plugin.nodeContext.set('author', plugin.author);
|
|
436
338
|
}
|
|
437
|
-
// Log system info and create .matterbridge directory
|
|
438
339
|
await this.logNodeAndSystemInfo();
|
|
439
340
|
this.log.notice(`Matterbridge version ${this.matterbridgeVersion} ` +
|
|
440
341
|
`${hasParameter('bridge') || (!hasParameter('childbridge') && (await this.nodeContext?.get('bridgeMode', '')) === 'bridge') ? 'mode bridge ' : ''}` +
|
|
@@ -442,7 +343,6 @@ export class Matterbridge extends EventEmitter {
|
|
|
442
343
|
`${hasParameter('controller') ? 'mode controller ' : ''}` +
|
|
443
344
|
`${this.restartMode !== '' ? 'restart mode ' + this.restartMode + ' ' : ''}` +
|
|
444
345
|
`running on ${this.systemInformation.osType} (v.${this.systemInformation.osRelease}) platform ${this.systemInformation.osPlatform} arch ${this.systemInformation.osArch}`);
|
|
445
|
-
// Check node version and throw error
|
|
446
346
|
const minNodeVersion = 18;
|
|
447
347
|
const nodeVersion = process.versions.node;
|
|
448
348
|
const versionMajor = parseInt(nodeVersion.split('.')[0]);
|
|
@@ -450,17 +350,10 @@ export class Matterbridge extends EventEmitter {
|
|
|
450
350
|
this.log.error(`Node version ${versionMajor} is not supported. Please upgrade to ${minNodeVersion} or above.`);
|
|
451
351
|
throw new Error(`Node version ${versionMajor} is not supported. Please upgrade to ${minNodeVersion} or above.`);
|
|
452
352
|
}
|
|
453
|
-
// Register process handlers
|
|
454
353
|
this.registerProcessHandlers();
|
|
455
|
-
// Parse command line
|
|
456
354
|
await this.parseCommandLine();
|
|
457
355
|
this.initialized = true;
|
|
458
356
|
}
|
|
459
|
-
/**
|
|
460
|
-
* Parses the command line arguments and performs the corresponding actions.
|
|
461
|
-
* @private
|
|
462
|
-
* @returns {Promise<void>} A promise that resolves when the command line arguments have been processed, or the process exits.
|
|
463
|
-
*/
|
|
464
357
|
async parseCommandLine() {
|
|
465
358
|
if (hasParameter('help')) {
|
|
466
359
|
this.log.info(`\nUsage: matterbridge [options]\n
|
|
@@ -568,7 +461,6 @@ export class Matterbridge extends EventEmitter {
|
|
|
568
461
|
}
|
|
569
462
|
if (hasParameter('factoryreset')) {
|
|
570
463
|
try {
|
|
571
|
-
// Delete old matter storage file
|
|
572
464
|
const file = path.join(this.matterbridgeDirectory, 'matterbridge' + (getParameter('profile') ? '.' + getParameter('profile') : '') + '.json');
|
|
573
465
|
this.log.info(`Unlinking old matter storage file: ${file}`);
|
|
574
466
|
await fs.unlink(file);
|
|
@@ -579,7 +471,6 @@ export class Matterbridge extends EventEmitter {
|
|
|
579
471
|
}
|
|
580
472
|
}
|
|
581
473
|
try {
|
|
582
|
-
// Delete matter node storage directory with its subdirectories
|
|
583
474
|
const dir = path.join(this.matterbridgeDirectory, 'matterstorage' + (getParameter('profile') ? '.' + getParameter('profile') : ''));
|
|
584
475
|
this.log.info(`Removing matter node storage directory: ${dir}`);
|
|
585
476
|
await fs.rm(dir, { recursive: true });
|
|
@@ -590,7 +481,6 @@ export class Matterbridge extends EventEmitter {
|
|
|
590
481
|
}
|
|
591
482
|
}
|
|
592
483
|
try {
|
|
593
|
-
// Delete node storage directory with its subdirectories
|
|
594
484
|
const dir = path.join(this.matterbridgeDirectory, 'storage' + (getParameter('profile') ? '.' + getParameter('profile') : ''));
|
|
595
485
|
this.log.info(`Removing storage directory: ${dir}`);
|
|
596
486
|
await fs.rm(dir, { recursive: true });
|
|
@@ -608,7 +498,6 @@ export class Matterbridge extends EventEmitter {
|
|
|
608
498
|
this.emit('shutdown');
|
|
609
499
|
return;
|
|
610
500
|
}
|
|
611
|
-
// Start the matter storage and create the matterbridge context
|
|
612
501
|
try {
|
|
613
502
|
await this.startMatterStorage('json', path.join(this.matterbridgeDirectory, this.matterStorageName));
|
|
614
503
|
}
|
|
@@ -616,7 +505,6 @@ export class Matterbridge extends EventEmitter {
|
|
|
616
505
|
this.log.fatal(`Fatal error creating matter storage: ${error instanceof Error ? error.message : error}`);
|
|
617
506
|
throw new Error(`Fatal error creating matter storage: ${error instanceof Error ? error.message : error}`);
|
|
618
507
|
}
|
|
619
|
-
// Clear the matterbridge context if the reset parameter is set
|
|
620
508
|
if (!this.edge && hasParameter('reset') && getParameter('reset') === undefined) {
|
|
621
509
|
this.log.info('Resetting Matterbridge commissioning information...');
|
|
622
510
|
await this.matterbridgeContext?.clearAll();
|
|
@@ -625,7 +513,6 @@ export class Matterbridge extends EventEmitter {
|
|
|
625
513
|
this.emit('shutdown');
|
|
626
514
|
return;
|
|
627
515
|
}
|
|
628
|
-
// Clear matterbridge plugin context if the reset parameter is set
|
|
629
516
|
if (!this.edge && hasParameter('reset') && getParameter('reset') !== undefined) {
|
|
630
517
|
this.log.debug(`Reset plugin ${getParameter('reset')}`);
|
|
631
518
|
const plugin = this.plugins.get(getParameter('reset'));
|
|
@@ -645,34 +532,28 @@ export class Matterbridge extends EventEmitter {
|
|
|
645
532
|
this.emit('shutdown');
|
|
646
533
|
return;
|
|
647
534
|
}
|
|
648
|
-
// Initialize frontend
|
|
649
535
|
if (getIntParameter('frontend') !== 0 || getIntParameter('frontend') === undefined)
|
|
650
536
|
await this.initializeFrontend(getIntParameter('frontend'));
|
|
651
|
-
// Check each 60 minutes the latest versions
|
|
652
537
|
this.checkUpdateInterval = setInterval(() => {
|
|
653
538
|
this.getMatterbridgeLatestVersion();
|
|
654
539
|
for (const plugin of this.plugins) {
|
|
655
540
|
this.getPluginLatestVersion(plugin);
|
|
656
541
|
}
|
|
657
542
|
}, 60 * 60 * 1000);
|
|
658
|
-
// Start the matterbridge in mode test
|
|
659
543
|
if (hasParameter('test')) {
|
|
660
544
|
this.bridgeMode = 'bridge';
|
|
661
545
|
MatterbridgeDevice.bridgeMode = 'bridge';
|
|
662
546
|
return;
|
|
663
547
|
}
|
|
664
|
-
// Start the matterbridge in mode controller
|
|
665
548
|
if (hasParameter('controller')) {
|
|
666
549
|
this.bridgeMode = 'controller';
|
|
667
550
|
await this.startController();
|
|
668
551
|
return;
|
|
669
552
|
}
|
|
670
|
-
// Check if the bridge mode is set and start matterbridge in bridge mode if not set
|
|
671
553
|
if (!hasParameter('bridge') && !hasParameter('childbridge') && (await this.nodeContext?.get('bridgeMode', '')) === '') {
|
|
672
554
|
this.log.info('Setting default matterbridge start mode to bridge');
|
|
673
555
|
await this.nodeContext?.set('bridgeMode', 'bridge');
|
|
674
556
|
}
|
|
675
|
-
// Start matterbridge in bridge mode
|
|
676
557
|
if (hasParameter('bridge') || (!hasParameter('childbridge') && (await this.nodeContext?.get('bridgeMode', '')) === 'bridge')) {
|
|
677
558
|
this.bridgeMode = 'bridge';
|
|
678
559
|
MatterbridgeDevice.bridgeMode = 'bridge';
|
|
@@ -681,7 +562,6 @@ export class Matterbridge extends EventEmitter {
|
|
|
681
562
|
await this.startBridge();
|
|
682
563
|
return;
|
|
683
564
|
}
|
|
684
|
-
// Start matterbridge in childbridge mode
|
|
685
565
|
if (hasParameter('childbridge') || (!hasParameter('bridge') && (await this.nodeContext?.get('bridgeMode', '')) === 'childbridge')) {
|
|
686
566
|
this.bridgeMode = 'childbridge';
|
|
687
567
|
MatterbridgeDevice.bridgeMode = 'childbridge';
|
|
@@ -691,28 +571,17 @@ export class Matterbridge extends EventEmitter {
|
|
|
691
571
|
return;
|
|
692
572
|
}
|
|
693
573
|
}
|
|
694
|
-
/**
|
|
695
|
-
* Asynchronously loads and starts the registered plugins.
|
|
696
|
-
*
|
|
697
|
-
* This method is responsible for initializing and staarting all enabled plugins.
|
|
698
|
-
* It ensures that each plugin is properly loaded and started before the ridge starts.
|
|
699
|
-
*
|
|
700
|
-
* @returns {Promise<void>} A promise that resolves when all plugins have been loaded and started.
|
|
701
|
-
*/
|
|
702
574
|
async startPlugins() {
|
|
703
|
-
// Check, load and start the plugins
|
|
704
575
|
for (const plugin of this.plugins) {
|
|
705
576
|
plugin.configJson = await this.plugins.loadConfig(plugin);
|
|
706
577
|
plugin.schemaJson = await this.plugins.loadSchema(plugin);
|
|
707
|
-
// Check if the plugin is available
|
|
708
578
|
if (!(await this.plugins.resolve(plugin.path))) {
|
|
709
579
|
this.log.error(`Plugin ${plg}${plugin.name}${er} not found or not validated. Disabling it.`);
|
|
710
580
|
plugin.enabled = false;
|
|
711
581
|
plugin.error = true;
|
|
712
582
|
continue;
|
|
713
583
|
}
|
|
714
|
-
|
|
715
|
-
this.getPluginLatestVersion(plugin); // No await do it asyncronously
|
|
584
|
+
this.getPluginLatestVersion(plugin);
|
|
716
585
|
if (!plugin.enabled) {
|
|
717
586
|
this.log.info(`Plugin ${plg}${plugin.name}${nf} not enabled`);
|
|
718
587
|
continue;
|
|
@@ -727,26 +596,20 @@ export class Matterbridge extends EventEmitter {
|
|
|
727
596
|
plugin.addedDevices = undefined;
|
|
728
597
|
plugin.qrPairingCode = undefined;
|
|
729
598
|
plugin.manualPairingCode = undefined;
|
|
730
|
-
this.plugins.load(plugin, true, 'Matterbridge is starting');
|
|
599
|
+
this.plugins.load(plugin, true, 'Matterbridge is starting');
|
|
731
600
|
}
|
|
732
601
|
this.wssSendRefreshRequired();
|
|
733
602
|
}
|
|
734
|
-
/**
|
|
735
|
-
* Registers the process handlers for uncaughtException, unhandledRejection, SIGINT and SIGTERM.
|
|
736
|
-
* When either of these signals are received, the cleanup method is called with an appropriate message.
|
|
737
|
-
*/
|
|
738
603
|
registerProcessHandlers() {
|
|
739
604
|
this.log.debug(`Registering uncaughtException and unhandledRejection handlers...`);
|
|
740
605
|
process.removeAllListeners('uncaughtException');
|
|
741
606
|
process.removeAllListeners('unhandledRejection');
|
|
742
607
|
this.exceptionHandler = async (error) => {
|
|
743
608
|
this.log.fatal('Unhandled Exception detected at:', error.stack || error, rs);
|
|
744
|
-
// await this.cleanup('Unhandled Exception detected, cleaning up...');
|
|
745
609
|
};
|
|
746
610
|
process.on('uncaughtException', this.exceptionHandler);
|
|
747
611
|
this.rejectionHandler = async (reason, promise) => {
|
|
748
612
|
this.log.fatal('Unhandled Rejection detected at:', promise, 'reason:', reason instanceof Error ? reason.stack : reason, rs);
|
|
749
|
-
// await this.cleanup('Unhandled Rejection detected, cleaning up...');
|
|
750
613
|
};
|
|
751
614
|
process.on('unhandledRejection', this.rejectionHandler);
|
|
752
615
|
this.log.debug(`Registering SIGINT and SIGTERM signal handlers...`);
|
|
@@ -759,9 +622,6 @@ export class Matterbridge extends EventEmitter {
|
|
|
759
622
|
};
|
|
760
623
|
process.on('SIGTERM', this.sigtermHandler);
|
|
761
624
|
}
|
|
762
|
-
/**
|
|
763
|
-
* Deregisters the process uncaughtException, unhandledRejection, SIGINT and SIGTERM signal handlers.
|
|
764
|
-
*/
|
|
765
625
|
deregisterProcesslHandlers() {
|
|
766
626
|
this.log.debug(`Deregistering uncaughtException and unhandledRejection handlers...`);
|
|
767
627
|
if (this.exceptionHandler)
|
|
@@ -778,11 +638,7 @@ export class Matterbridge extends EventEmitter {
|
|
|
778
638
|
process.off('SIGTERM', this.sigtermHandler);
|
|
779
639
|
this.sigtermHandler = undefined;
|
|
780
640
|
}
|
|
781
|
-
/**
|
|
782
|
-
* Logs the node and system information.
|
|
783
|
-
*/
|
|
784
641
|
async logNodeAndSystemInfo() {
|
|
785
|
-
// IP address information
|
|
786
642
|
const networkInterfaces = os.networkInterfaces();
|
|
787
643
|
this.systemInformation.ipv4Address = '';
|
|
788
644
|
this.systemInformation.ipv6Address = '';
|
|
@@ -802,7 +658,7 @@ export class Matterbridge extends EventEmitter {
|
|
|
802
658
|
this.systemInformation.macAddress = detail.mac;
|
|
803
659
|
}
|
|
804
660
|
}
|
|
805
|
-
if (this.systemInformation.ipv4Address !== ''
|
|
661
|
+
if (this.systemInformation.ipv4Address !== '') {
|
|
806
662
|
this.log.debug(`Using interface: '${this.systemInformation.interfaceName}'`);
|
|
807
663
|
this.log.debug(`- with MAC address: '${this.systemInformation.macAddress}'`);
|
|
808
664
|
this.log.debug(`- with IPv4 address: '${this.systemInformation.ipv4Address}'`);
|
|
@@ -810,22 +666,19 @@ export class Matterbridge extends EventEmitter {
|
|
|
810
666
|
break;
|
|
811
667
|
}
|
|
812
668
|
}
|
|
813
|
-
// Node information
|
|
814
669
|
this.systemInformation.nodeVersion = process.versions.node;
|
|
815
670
|
const versionMajor = parseInt(this.systemInformation.nodeVersion.split('.')[0]);
|
|
816
671
|
const versionMinor = parseInt(this.systemInformation.nodeVersion.split('.')[1]);
|
|
817
672
|
const versionPatch = parseInt(this.systemInformation.nodeVersion.split('.')[2]);
|
|
818
|
-
// Host system information
|
|
819
673
|
this.systemInformation.hostname = os.hostname();
|
|
820
674
|
this.systemInformation.user = os.userInfo().username;
|
|
821
|
-
this.systemInformation.osType = os.type();
|
|
822
|
-
this.systemInformation.osRelease = os.release();
|
|
823
|
-
this.systemInformation.osPlatform = os.platform();
|
|
824
|
-
this.systemInformation.osArch = os.arch();
|
|
825
|
-
this.systemInformation.totalMemory = (os.totalmem() / 1024 / 1024 / 1024).toFixed(2) + ' GB';
|
|
826
|
-
this.systemInformation.freeMemory = (os.freemem() / 1024 / 1024 / 1024).toFixed(2) + ' GB';
|
|
827
|
-
this.systemInformation.systemUptime = (os.uptime() / 60 / 60).toFixed(2) + ' hours';
|
|
828
|
-
// Log the system information
|
|
675
|
+
this.systemInformation.osType = os.type();
|
|
676
|
+
this.systemInformation.osRelease = os.release();
|
|
677
|
+
this.systemInformation.osPlatform = os.platform();
|
|
678
|
+
this.systemInformation.osArch = os.arch();
|
|
679
|
+
this.systemInformation.totalMemory = (os.totalmem() / 1024 / 1024 / 1024).toFixed(2) + ' GB';
|
|
680
|
+
this.systemInformation.freeMemory = (os.freemem() / 1024 / 1024 / 1024).toFixed(2) + ' GB';
|
|
681
|
+
this.systemInformation.systemUptime = (os.uptime() / 60 / 60).toFixed(2) + ' hours';
|
|
829
682
|
this.log.debug('Host System Information:');
|
|
830
683
|
this.log.debug(`- Hostname: ${this.systemInformation.hostname}`);
|
|
831
684
|
this.log.debug(`- User: ${this.systemInformation.user}`);
|
|
@@ -841,19 +694,15 @@ export class Matterbridge extends EventEmitter {
|
|
|
841
694
|
this.log.debug(`- Total Memory: ${this.systemInformation.totalMemory}`);
|
|
842
695
|
this.log.debug(`- Free Memory: ${this.systemInformation.freeMemory}`);
|
|
843
696
|
this.log.debug(`- System Uptime: ${this.systemInformation.systemUptime}`);
|
|
844
|
-
// Home directory
|
|
845
697
|
this.homeDirectory = getParameter('homedir') ?? os.homedir();
|
|
846
698
|
this.matterbridgeInformation.homeDirectory = this.homeDirectory;
|
|
847
699
|
this.log.debug(`Home Directory: ${this.homeDirectory}`);
|
|
848
|
-
// Package root directory
|
|
849
700
|
const currentFileDirectory = path.dirname(fileURLToPath(import.meta.url));
|
|
850
701
|
this.rootDirectory = path.resolve(currentFileDirectory, '../');
|
|
851
702
|
this.matterbridgeInformation.rootDirectory = this.rootDirectory;
|
|
852
703
|
this.log.debug(`Root Directory: ${this.rootDirectory}`);
|
|
853
|
-
// Global node_modules directory
|
|
854
704
|
if (this.nodeContext)
|
|
855
705
|
this.globalModulesDirectory = await this.nodeContext.get('globalModulesDirectory', '');
|
|
856
|
-
// First run of Matterbridge so the node storage is empty
|
|
857
706
|
if (this.globalModulesDirectory === '') {
|
|
858
707
|
try {
|
|
859
708
|
this.globalModulesDirectory = await this.getGlobalNodeModules();
|
|
@@ -877,7 +726,6 @@ export class Matterbridge extends EventEmitter {
|
|
|
877
726
|
this.log.error(`Error getting global node_modules directory: ${error}`);
|
|
878
727
|
});
|
|
879
728
|
}
|
|
880
|
-
// Create the data directory .matterbridge in the home directory
|
|
881
729
|
this.matterbridgeDirectory = path.join(this.homeDirectory, '.matterbridge');
|
|
882
730
|
this.matterbridgeInformation.matterbridgeDirectory = this.matterbridgeDirectory;
|
|
883
731
|
try {
|
|
@@ -901,7 +749,6 @@ export class Matterbridge extends EventEmitter {
|
|
|
901
749
|
}
|
|
902
750
|
}
|
|
903
751
|
this.log.debug(`Matterbridge Directory: ${this.matterbridgeDirectory}`);
|
|
904
|
-
// Create the plugin directory Matterbridge in the home directory
|
|
905
752
|
this.matterbridgePluginDirectory = path.join(this.homeDirectory, 'Matterbridge');
|
|
906
753
|
this.matterbridgeInformation.matterbridgePluginDirectory = this.matterbridgePluginDirectory;
|
|
907
754
|
try {
|
|
@@ -925,28 +772,19 @@ export class Matterbridge extends EventEmitter {
|
|
|
925
772
|
}
|
|
926
773
|
}
|
|
927
774
|
this.log.debug(`Matterbridge Plugin Directory: ${this.matterbridgePluginDirectory}`);
|
|
928
|
-
// Matterbridge version
|
|
929
775
|
const packageJson = JSON.parse(await fs.readFile(path.join(this.rootDirectory, 'package.json'), 'utf-8'));
|
|
930
776
|
this.matterbridgeVersion = packageJson.version;
|
|
931
777
|
this.matterbridgeInformation.matterbridgeVersion = this.matterbridgeVersion;
|
|
932
778
|
this.log.debug(`Matterbridge Version: ${this.matterbridgeVersion}`);
|
|
933
|
-
// Matterbridge latest version
|
|
934
779
|
if (this.nodeContext)
|
|
935
780
|
this.matterbridgeLatestVersion = await this.nodeContext.get('matterbridgeLatestVersion', '');
|
|
936
781
|
this.log.debug(`Matterbridge Latest Version: ${this.matterbridgeLatestVersion}`);
|
|
937
782
|
this.getMatterbridgeLatestVersion();
|
|
938
|
-
// Current working directory
|
|
939
783
|
const currentDir = process.cwd();
|
|
940
784
|
this.log.debug(`Current Working Directory: ${currentDir}`);
|
|
941
|
-
// Command line arguments (excluding 'node' and the script name)
|
|
942
785
|
const cmdArgs = process.argv.slice(2).join(' ');
|
|
943
786
|
this.log.debug(`Command Line Arguments: ${cmdArgs}`);
|
|
944
787
|
}
|
|
945
|
-
/**
|
|
946
|
-
* Retrieves the latest version of a package from the npm registry.
|
|
947
|
-
* @param packageName - The name of the package.
|
|
948
|
-
* @returns A Promise that resolves to the latest version of the package.
|
|
949
|
-
*/
|
|
950
788
|
async getLatestVersion(packageName) {
|
|
951
789
|
return new Promise((resolve, reject) => {
|
|
952
790
|
this.execRunningCount++;
|
|
@@ -961,10 +799,6 @@ export class Matterbridge extends EventEmitter {
|
|
|
961
799
|
});
|
|
962
800
|
});
|
|
963
801
|
}
|
|
964
|
-
/**
|
|
965
|
-
* Retrieves the path to the global Node.js modules directory.
|
|
966
|
-
* @returns A promise that resolves to the path of the global Node.js modules directory.
|
|
967
|
-
*/
|
|
968
802
|
async getGlobalNodeModules() {
|
|
969
803
|
return new Promise((resolve, reject) => {
|
|
970
804
|
this.execRunningCount++;
|
|
@@ -979,11 +813,6 @@ export class Matterbridge extends EventEmitter {
|
|
|
979
813
|
});
|
|
980
814
|
});
|
|
981
815
|
}
|
|
982
|
-
/**
|
|
983
|
-
* Retrieves the latest version of Matterbridge and performs necessary actions based on the version comparison.
|
|
984
|
-
* @private
|
|
985
|
-
* @returns {Promise<void>} A promise that resolves when the latest version is retrieved and actions are performed.
|
|
986
|
-
*/
|
|
987
816
|
async getMatterbridgeLatestVersion() {
|
|
988
817
|
this.getLatestVersion('matterbridge')
|
|
989
818
|
.then(async (matterbridgeLatestVersion) => {
|
|
@@ -1000,19 +829,8 @@ export class Matterbridge extends EventEmitter {
|
|
|
1000
829
|
})
|
|
1001
830
|
.catch((error) => {
|
|
1002
831
|
this.log.error(`Error getting Matterbridge latest version: ${error.message}`);
|
|
1003
|
-
// error.stack && this.log.debug(error.stack);
|
|
1004
832
|
});
|
|
1005
833
|
}
|
|
1006
|
-
/**
|
|
1007
|
-
* Retrieves the latest version of a plugin and updates the plugin's latestVersion property.
|
|
1008
|
-
* If the plugin's version is different from the latest version, logs a warning message.
|
|
1009
|
-
* If the plugin's version is the same as the latest version, logs an info message.
|
|
1010
|
-
* If there is an error retrieving the latest version, logs an error message.
|
|
1011
|
-
*
|
|
1012
|
-
* @private
|
|
1013
|
-
* @param {RegisteredPlugin} plugin - The plugin for which to retrieve the latest version.
|
|
1014
|
-
* @returns {Promise<void>} A promise that resolves when the latest version is retrieved and actions are performed.
|
|
1015
|
-
*/
|
|
1016
834
|
async getPluginLatestVersion(plugin) {
|
|
1017
835
|
this.getLatestVersion(plugin.name)
|
|
1018
836
|
.then(async (latestVersion) => {
|
|
@@ -1024,54 +842,40 @@ export class Matterbridge extends EventEmitter {
|
|
|
1024
842
|
})
|
|
1025
843
|
.catch((error) => {
|
|
1026
844
|
this.log.error(`Error getting ${plg}${plugin.name}${er} latest version: ${error.message}`);
|
|
1027
|
-
// error.stack && this.log.debug(error.stack);
|
|
1028
845
|
});
|
|
1029
846
|
}
|
|
1030
|
-
/**
|
|
1031
|
-
* Creates a MatterLogger function to show the matter.js log messages in AnsiLogger (for the frontend).
|
|
1032
|
-
*
|
|
1033
|
-
* @returns {Function} The MatterLogger function.
|
|
1034
|
-
*/
|
|
1035
847
|
createMatterLogger() {
|
|
1036
|
-
const matterLogger = new AnsiLogger({ logName: 'Matter', logTimestampFormat: 4
|
|
848
|
+
const matterLogger = new AnsiLogger({ logName: 'Matter', logTimestampFormat: 4, logLevel: "debug" });
|
|
1037
849
|
return (_level, formattedLog) => {
|
|
1038
850
|
const logger = formattedLog.slice(44, 44 + 20).trim();
|
|
1039
851
|
const message = formattedLog.slice(65);
|
|
1040
852
|
matterLogger.logName = logger;
|
|
1041
853
|
switch (_level) {
|
|
1042
854
|
case MatterLogLevel.DEBUG:
|
|
1043
|
-
matterLogger.log("debug"
|
|
855
|
+
matterLogger.log("debug", message);
|
|
1044
856
|
break;
|
|
1045
857
|
case MatterLogLevel.INFO:
|
|
1046
|
-
matterLogger.log("info"
|
|
858
|
+
matterLogger.log("info", message);
|
|
1047
859
|
break;
|
|
1048
860
|
case MatterLogLevel.NOTICE:
|
|
1049
|
-
matterLogger.log("notice"
|
|
861
|
+
matterLogger.log("notice", message);
|
|
1050
862
|
break;
|
|
1051
863
|
case MatterLogLevel.WARN:
|
|
1052
|
-
matterLogger.log("warn"
|
|
864
|
+
matterLogger.log("warn", message);
|
|
1053
865
|
break;
|
|
1054
866
|
case MatterLogLevel.ERROR:
|
|
1055
|
-
matterLogger.log("error"
|
|
867
|
+
matterLogger.log("error", message);
|
|
1056
868
|
break;
|
|
1057
869
|
case MatterLogLevel.FATAL:
|
|
1058
|
-
matterLogger.log("fatal"
|
|
870
|
+
matterLogger.log("fatal", message);
|
|
1059
871
|
break;
|
|
1060
872
|
default:
|
|
1061
|
-
matterLogger.log("debug"
|
|
873
|
+
matterLogger.log("debug", message);
|
|
1062
874
|
break;
|
|
1063
875
|
}
|
|
1064
876
|
};
|
|
1065
877
|
}
|
|
1066
|
-
/**
|
|
1067
|
-
* Creates a Matter File Logger.
|
|
1068
|
-
*
|
|
1069
|
-
* @param {string} filePath - The path to the log file.
|
|
1070
|
-
* @param {boolean} [unlink=false] - Whether to unlink the log file before creating a new one.
|
|
1071
|
-
* @returns {Function} - A function that logs formatted messages to the log file.
|
|
1072
|
-
*/
|
|
1073
878
|
async createMatterFileLogger(filePath, unlink = false) {
|
|
1074
|
-
// 2024-08-21 08:55:19.488 DEBUG InteractionMessenger Sending DataReport chunk with 28 attributes and 0 events: 1004 bytes
|
|
1075
879
|
let fileSize = 0;
|
|
1076
880
|
if (unlink) {
|
|
1077
881
|
try {
|
|
@@ -1120,30 +924,18 @@ export class Matterbridge extends EventEmitter {
|
|
|
1120
924
|
}
|
|
1121
925
|
};
|
|
1122
926
|
}
|
|
1123
|
-
/**
|
|
1124
|
-
* Update matterbridge and cleanup.
|
|
1125
|
-
*/
|
|
1126
927
|
async updateProcess() {
|
|
1127
928
|
await this.cleanup('updating...', false);
|
|
1128
929
|
}
|
|
1129
|
-
/**
|
|
1130
|
-
* Restarts the process by spawning a new process and exiting the current process.
|
|
1131
|
-
*/
|
|
1132
930
|
async restartProcess() {
|
|
1133
931
|
await this.cleanup('restarting...', true);
|
|
1134
932
|
}
|
|
1135
|
-
/**
|
|
1136
|
-
* Shut down the process by exiting the current process.
|
|
1137
|
-
*/
|
|
1138
933
|
async shutdownProcess() {
|
|
1139
934
|
await this.cleanup('shutting down...', false);
|
|
1140
935
|
}
|
|
1141
|
-
/**
|
|
1142
|
-
* Shut down the process and reset.
|
|
1143
|
-
*/
|
|
1144
936
|
async unregisterAndShutdownProcess() {
|
|
1145
937
|
this.log.info('Unregistering all devices and shutting down...');
|
|
1146
|
-
for (const plugin of this.plugins
|
|
938
|
+
for (const plugin of this.plugins) {
|
|
1147
939
|
if (this.edge)
|
|
1148
940
|
await this.removeAllBridgedEndpoints(plugin.name);
|
|
1149
941
|
else
|
|
@@ -1151,55 +943,37 @@ export class Matterbridge extends EventEmitter {
|
|
|
1151
943
|
}
|
|
1152
944
|
await this.cleanup('unregistered all devices and shutting down...', false);
|
|
1153
945
|
}
|
|
1154
|
-
/**
|
|
1155
|
-
* Shut down the process and reset.
|
|
1156
|
-
*/
|
|
1157
946
|
async shutdownProcessAndReset() {
|
|
1158
947
|
await this.cleanup('shutting down with reset...', false);
|
|
1159
948
|
}
|
|
1160
|
-
/**
|
|
1161
|
-
* Shut down the process and factory reset.
|
|
1162
|
-
*/
|
|
1163
949
|
async shutdownProcessAndFactoryReset() {
|
|
1164
950
|
await this.cleanup('shutting down with factory reset...', false);
|
|
1165
951
|
}
|
|
1166
|
-
/**
|
|
1167
|
-
* Cleans up the Matterbridge instance.
|
|
1168
|
-
* @param message - The cleanup message.
|
|
1169
|
-
* @param restart - Indicates whether to restart the instance after cleanup. Default is `false`.
|
|
1170
|
-
* @returns A promise that resolves when the cleanup is completed.
|
|
1171
|
-
*/
|
|
1172
952
|
async cleanup(message, restart = false) {
|
|
1173
953
|
if (this.initialized && !this.hasCleanupStarted) {
|
|
1174
954
|
this.hasCleanupStarted = true;
|
|
1175
955
|
this.log.info(message);
|
|
1176
|
-
// Deregisters the process handlers
|
|
1177
956
|
this.deregisterProcesslHandlers();
|
|
1178
|
-
// Clear the start matter interval
|
|
1179
957
|
if (this.startMatterInterval) {
|
|
1180
958
|
clearInterval(this.startMatterInterval);
|
|
1181
959
|
this.startMatterInterval = undefined;
|
|
1182
960
|
this.log.debug('Start matter interval cleared');
|
|
1183
961
|
}
|
|
1184
|
-
// Clear the check update interval
|
|
1185
962
|
if (this.checkUpdateInterval) {
|
|
1186
963
|
clearInterval(this.checkUpdateInterval);
|
|
1187
964
|
this.checkUpdateInterval = undefined;
|
|
1188
965
|
this.log.debug('Check update interval cleared');
|
|
1189
966
|
}
|
|
1190
|
-
// Clear the configure timeout
|
|
1191
967
|
if (this.configureTimeout) {
|
|
1192
968
|
clearTimeout(this.configureTimeout);
|
|
1193
969
|
this.configureTimeout = undefined;
|
|
1194
970
|
this.log.debug('Matterbridge configure timeout cleared');
|
|
1195
971
|
}
|
|
1196
|
-
// Clear the reachability timeout
|
|
1197
972
|
if (this.reachabilityTimeout) {
|
|
1198
973
|
clearTimeout(this.reachabilityTimeout);
|
|
1199
974
|
this.reachabilityTimeout = undefined;
|
|
1200
975
|
this.log.debug('Matterbridge reachability timeout cleared');
|
|
1201
976
|
}
|
|
1202
|
-
// Calling the shutdown method of each plugin and clear the reachability timeout
|
|
1203
977
|
for (const plugin of this.plugins) {
|
|
1204
978
|
if (!plugin.enabled || plugin.error)
|
|
1205
979
|
continue;
|
|
@@ -1210,7 +984,6 @@ export class Matterbridge extends EventEmitter {
|
|
|
1210
984
|
this.log.debug(`Plugin ${plg}${plugin.name}${db} reachability timeout cleared`);
|
|
1211
985
|
}
|
|
1212
986
|
}
|
|
1213
|
-
// Convert the matter storage to the new format
|
|
1214
987
|
if (!hasParameter('nostorageconversion') && this.edge === false && this.matterbridgeContext && ['updating...', 'restarting...', 'shutting down...'].includes(message)) {
|
|
1215
988
|
if (this.bridgeMode === 'bridge') {
|
|
1216
989
|
await this.convertStorage(this.matterbridgeContext, 'Matterbridge');
|
|
@@ -1223,29 +996,24 @@ export class Matterbridge extends EventEmitter {
|
|
|
1223
996
|
}
|
|
1224
997
|
}
|
|
1225
998
|
}
|
|
1226
|
-
// Close the http server
|
|
1227
999
|
if (this.httpServer) {
|
|
1228
1000
|
this.httpServer.close();
|
|
1229
1001
|
this.httpServer.removeAllListeners();
|
|
1230
1002
|
this.httpServer = undefined;
|
|
1231
1003
|
this.log.debug('Frontend http server closed successfully');
|
|
1232
1004
|
}
|
|
1233
|
-
// Close the https server
|
|
1234
1005
|
if (this.httpsServer) {
|
|
1235
1006
|
this.httpsServer.close();
|
|
1236
1007
|
this.httpsServer.removeAllListeners();
|
|
1237
1008
|
this.httpsServer = undefined;
|
|
1238
1009
|
this.log.debug('Frontend https server closed successfully');
|
|
1239
1010
|
}
|
|
1240
|
-
// Remove listeners from the express app
|
|
1241
1011
|
if (this.expressApp) {
|
|
1242
1012
|
this.expressApp.removeAllListeners();
|
|
1243
1013
|
this.expressApp = undefined;
|
|
1244
1014
|
this.log.debug('Frontend app closed successfully');
|
|
1245
1015
|
}
|
|
1246
|
-
// Close the WebSocket server
|
|
1247
1016
|
if (this.webSocketServer) {
|
|
1248
|
-
// Close all active connections
|
|
1249
1017
|
this.webSocketServer.clients.forEach((client) => {
|
|
1250
1018
|
if (client.readyState === WebSocket.OPEN) {
|
|
1251
1019
|
client.close();
|
|
@@ -1261,35 +1029,26 @@ export class Matterbridge extends EventEmitter {
|
|
|
1261
1029
|
});
|
|
1262
1030
|
this.webSocketServer = undefined;
|
|
1263
1031
|
}
|
|
1264
|
-
// Closing matter
|
|
1265
1032
|
await this.stopMatterServer();
|
|
1266
|
-
// Closing matter storage
|
|
1267
1033
|
await this.stopMatterStorage();
|
|
1268
|
-
// Remove the matterfilelogger
|
|
1269
1034
|
try {
|
|
1270
1035
|
Logger.removeLogger('matterfilelogger');
|
|
1271
|
-
// eslint-disable-next-line @typescript-eslint/no-unused-vars
|
|
1272
1036
|
}
|
|
1273
1037
|
catch (error) {
|
|
1274
|
-
// this.log.debug(`Error removing the matterfilelogger for file ${CYAN}${path.join(this.matterbridgeDirectory, this.matterLoggerFile)}${er}: ${error instanceof Error ? error.message : error}`);
|
|
1275
1038
|
}
|
|
1276
|
-
// Serialize registeredDevices
|
|
1277
1039
|
if (this.nodeStorage && this.nodeContext) {
|
|
1278
1040
|
this.log.info('Saving registered devices...');
|
|
1279
1041
|
const serializedRegisteredDevices = [];
|
|
1280
1042
|
this.devices.forEach(async (device) => {
|
|
1281
1043
|
const serializedMatterbridgeDevice = device.serialize();
|
|
1282
|
-
// this.log.info(`- ${serializedMatterbridgeDevice.deviceName}${rs}\n`, serializedMatterbridgeDevice);
|
|
1283
1044
|
if (serializedMatterbridgeDevice)
|
|
1284
1045
|
serializedRegisteredDevices.push(serializedMatterbridgeDevice);
|
|
1285
1046
|
});
|
|
1286
1047
|
await this.nodeContext.set('devices', serializedRegisteredDevices);
|
|
1287
1048
|
this.log.info(`Saved registered devices (${serializedRegisteredDevices?.length})`);
|
|
1288
|
-
// Clear nodeContext and nodeStorage (they just need 1000ms to write the data to disk)
|
|
1289
1049
|
this.log.debug(`Closing node storage context for ${plg}Matterbridge${db}...`);
|
|
1290
1050
|
await this.nodeContext.close();
|
|
1291
1051
|
this.nodeContext = undefined;
|
|
1292
|
-
// Clear nodeContext for each plugin (they just need 1000ms to write the data to disk)
|
|
1293
1052
|
for (const plugin of this.plugins) {
|
|
1294
1053
|
if (plugin.nodeContext) {
|
|
1295
1054
|
this.log.debug(`Closing node storage context for plugin ${plg}${plugin.name}${db}...`);
|
|
@@ -1321,7 +1080,6 @@ export class Matterbridge extends EventEmitter {
|
|
|
1321
1080
|
else {
|
|
1322
1081
|
if (message === 'shutting down with reset...' || message === 'shutting down with factory reset...') {
|
|
1323
1082
|
try {
|
|
1324
|
-
// Delete old matter storage file
|
|
1325
1083
|
const file = path.join(this.matterbridgeDirectory, 'matterbridge' + (getParameter('profile') ? '.' + getParameter('profile') : '') + '.json');
|
|
1326
1084
|
this.log.info(`Unlinking old matter storage file: ${file}`);
|
|
1327
1085
|
await fs.unlink(file);
|
|
@@ -1330,7 +1088,6 @@ export class Matterbridge extends EventEmitter {
|
|
|
1330
1088
|
this.log.debug(`Error resetting old matter storage file: ${error}`);
|
|
1331
1089
|
}
|
|
1332
1090
|
try {
|
|
1333
|
-
// Delete matter node storage directory with its subdirectories
|
|
1334
1091
|
const dir = path.join(this.matterbridgeDirectory, 'matterstorage' + (getParameter('profile') ? '.' + getParameter('profile') : ''));
|
|
1335
1092
|
this.log.info(`Removing matter node storage directory: ${dir}`);
|
|
1336
1093
|
await fs.rm(dir, { recursive: true });
|
|
@@ -1342,7 +1099,6 @@ export class Matterbridge extends EventEmitter {
|
|
|
1342
1099
|
}
|
|
1343
1100
|
if (message === 'shutting down with factory reset...') {
|
|
1344
1101
|
try {
|
|
1345
|
-
// Delete node storage directory with its subdirectories
|
|
1346
1102
|
this.log.info('Resetting Matterbridge storage...');
|
|
1347
1103
|
await fs.rm(path.join(this.matterbridgeDirectory, this.nodeStorageName), { recursive: true });
|
|
1348
1104
|
}
|
|
@@ -1359,33 +1115,19 @@ export class Matterbridge extends EventEmitter {
|
|
|
1359
1115
|
this.initialized = false;
|
|
1360
1116
|
}
|
|
1361
1117
|
}
|
|
1362
|
-
// eslint-disable-next-line @typescript-eslint/no-unused-vars
|
|
1363
1118
|
async addBridgedEndpoint(pluginName, device) {
|
|
1364
|
-
// Nothing to do here
|
|
1365
1119
|
}
|
|
1366
|
-
// eslint-disable-next-line @typescript-eslint/no-unused-vars
|
|
1367
1120
|
async removeBridgedEndpoint(pluginName, device) {
|
|
1368
|
-
// Nothing to do here
|
|
1369
1121
|
}
|
|
1370
|
-
// eslint-disable-next-line @typescript-eslint/no-unused-vars
|
|
1371
1122
|
async removeAllBridgedEndpoints(pluginName) {
|
|
1372
|
-
// Nothing to do here
|
|
1373
1123
|
}
|
|
1374
|
-
/**
|
|
1375
|
-
* Adds a bridged device to the Matterbridge.
|
|
1376
|
-
* @param pluginName - The name of the plugin.
|
|
1377
|
-
* @param device - The bridged device to add.
|
|
1378
|
-
* @returns {Promise<void>} - A promise that resolves when the device is added.
|
|
1379
|
-
*/
|
|
1380
1124
|
async addBridgedDevice(pluginName, device) {
|
|
1381
1125
|
this.log.debug(`Adding bridged device ${dev}${device.deviceName}${db} (${zb}${device.name}${db}) for plugin ${plg}${pluginName}${db}`);
|
|
1382
|
-
// Check if the plugin is registered
|
|
1383
1126
|
const plugin = this.plugins.get(pluginName);
|
|
1384
1127
|
if (!plugin) {
|
|
1385
1128
|
this.log.error(`Error adding bridged device ${dev}${device.deviceName}${er} (${zb}${device.name}${er}) plugin ${plg}${pluginName}${er} not found`);
|
|
1386
1129
|
return;
|
|
1387
1130
|
}
|
|
1388
|
-
// Register and add the device to matterbridge aggregator in bridge mode
|
|
1389
1131
|
if (this.bridgeMode === 'bridge') {
|
|
1390
1132
|
if (!this.matterAggregator) {
|
|
1391
1133
|
this.log.error(`Adding bridged device ${dev}${device.deviceName}${er} (${zb}${device.name}${er}) for plugin ${plg}${pluginName}${er} error: matterAggregator not found`);
|
|
@@ -1393,11 +1135,8 @@ export class Matterbridge extends EventEmitter {
|
|
|
1393
1135
|
}
|
|
1394
1136
|
this.matterAggregator.addBridgedDevice(device);
|
|
1395
1137
|
}
|
|
1396
|
-
// The first time create the commissioning server and the aggregator for DynamicPlatform
|
|
1397
|
-
// Register and add the device in childbridge mode
|
|
1398
1138
|
if (this.bridgeMode === 'childbridge') {
|
|
1399
1139
|
if (plugin.type === 'AccessoryPlatform') {
|
|
1400
|
-
// Check if the plugin is locked with the commissioning server
|
|
1401
1140
|
if (!plugin.locked) {
|
|
1402
1141
|
plugin.locked = true;
|
|
1403
1142
|
plugin.storageContext = await this.importCommissioningServerContext(plugin.name, device);
|
|
@@ -1411,7 +1150,6 @@ export class Matterbridge extends EventEmitter {
|
|
|
1411
1150
|
}
|
|
1412
1151
|
}
|
|
1413
1152
|
if (plugin.type === 'DynamicPlatform') {
|
|
1414
|
-
// Check if the plugin is locked with the commissioning server and the aggregator
|
|
1415
1153
|
if (!plugin.locked) {
|
|
1416
1154
|
plugin.locked = true;
|
|
1417
1155
|
this.log.debug(`Creating commissioning server context for ${plg}${plugin.name}${db}`);
|
|
@@ -1432,25 +1170,16 @@ export class Matterbridge extends EventEmitter {
|
|
|
1432
1170
|
plugin.registeredDevices++;
|
|
1433
1171
|
if (plugin.addedDevices !== undefined)
|
|
1434
1172
|
plugin.addedDevices++;
|
|
1435
|
-
// Add the device to the DeviceManager
|
|
1436
1173
|
this.devices.set(device);
|
|
1437
1174
|
this.log.info(`Added and registered bridged device (${plugin.registeredDevices}/${plugin.addedDevices}) ${dev}${device.deviceName}${nf} (${dev}${device.name}${nf}) for plugin ${plg}${pluginName}${nf}`);
|
|
1438
1175
|
}
|
|
1439
|
-
/**
|
|
1440
|
-
* Removes a bridged device from the Matterbridge.
|
|
1441
|
-
* @param pluginName - The name of the plugin.
|
|
1442
|
-
* @param device - The device to be removed.
|
|
1443
|
-
* @returns A Promise that resolves when the device is successfully removed.
|
|
1444
|
-
*/
|
|
1445
1176
|
async removeBridgedDevice(pluginName, device) {
|
|
1446
1177
|
this.log.debug(`Removing bridged device ${dev}${device.deviceName}${db} (${zb}${device.name}${db}) for plugin ${plg}${pluginName}${db}`);
|
|
1447
|
-
// Check if the plugin is registered
|
|
1448
1178
|
const plugin = this.plugins.get(pluginName);
|
|
1449
1179
|
if (!plugin) {
|
|
1450
1180
|
this.log.error(`Error removing bridged device ${dev}${device.deviceName}${er} (${zb}${device.name}${er}) for plugin ${plg}${pluginName}${er}: plugin not found`);
|
|
1451
1181
|
return;
|
|
1452
1182
|
}
|
|
1453
|
-
// Remove the device from matterbridge aggregator in bridge mode
|
|
1454
1183
|
if (this.bridgeMode === 'bridge') {
|
|
1455
1184
|
if (!this.matterAggregator) {
|
|
1456
1185
|
this.log.error(`Error removing bridged device ${dev}${device.deviceName}${er} (${zb}${device.name}${er}) for plugin ${plg}${pluginName}${er}: matterAggregator not found`);
|
|
@@ -1460,8 +1189,6 @@ export class Matterbridge extends EventEmitter {
|
|
|
1460
1189
|
device.setBridgedDeviceReachability(false);
|
|
1461
1190
|
device.getClusterServerById(BridgedDeviceBasicInformation.Cluster.id)?.triggerReachableChangedEvent({ reachableNewValue: false });
|
|
1462
1191
|
}
|
|
1463
|
-
// device.getClusterServerById(BridgedDeviceBasicInformation.Cluster.id)?.triggerShutDownEvent({});
|
|
1464
|
-
// device.getClusterServerById(BridgedDeviceBasicInformation.Cluster.id)?.triggerLeaveEvent({});
|
|
1465
1192
|
this.matterAggregator?.removeBridgedDevice(device);
|
|
1466
1193
|
this.log.info(`Removed bridged device(${plugin.registeredDevices}/${plugin.addedDevices}) ${dev}${device.deviceName}${nf} (${zb}${device.name}${nf}) for plugin ${plg}${pluginName}${nf}`);
|
|
1467
1194
|
if (plugin.registeredDevices !== undefined)
|
|
@@ -1469,7 +1196,6 @@ export class Matterbridge extends EventEmitter {
|
|
|
1469
1196
|
if (plugin.addedDevices !== undefined)
|
|
1470
1197
|
plugin.addedDevices--;
|
|
1471
1198
|
}
|
|
1472
|
-
// Remove the device in childbridge mode
|
|
1473
1199
|
if (this.bridgeMode === 'childbridge') {
|
|
1474
1200
|
if (plugin.type === 'AccessoryPlatform') {
|
|
1475
1201
|
if (!plugin.commissioningServer) {
|
|
@@ -1493,22 +1219,14 @@ export class Matterbridge extends EventEmitter {
|
|
|
1493
1219
|
plugin.registeredDevices--;
|
|
1494
1220
|
if (plugin.addedDevices !== undefined)
|
|
1495
1221
|
plugin.addedDevices--;
|
|
1496
|
-
// Remove the commissioning server
|
|
1497
1222
|
if (plugin.registeredDevices === 0 && plugin.addedDevices === 0 && plugin.commissioningServer) {
|
|
1498
1223
|
this.matterServer?.removeCommissioningServer(plugin.commissioningServer);
|
|
1499
1224
|
plugin.commissioningServer = undefined;
|
|
1500
1225
|
this.log.info(`Removed commissioning server for plugin ${plg}${pluginName}${nf}`);
|
|
1501
1226
|
}
|
|
1502
1227
|
}
|
|
1503
|
-
// Remove the device from the DeviceManager
|
|
1504
1228
|
this.devices.remove(device);
|
|
1505
1229
|
}
|
|
1506
|
-
/**
|
|
1507
|
-
* Removes all bridged devices associated with a specific plugin.
|
|
1508
|
-
*
|
|
1509
|
-
* @param pluginName - The name of the plugin.
|
|
1510
|
-
* @returns A promise that resolves when all devices have been removed.
|
|
1511
|
-
*/
|
|
1512
1230
|
async removeAllBridgedDevices(pluginName) {
|
|
1513
1231
|
this.log.debug(`Removing all bridged devices for plugin ${plg}${pluginName}${db}`);
|
|
1514
1232
|
this.devices.forEach(async (device) => {
|
|
@@ -1517,13 +1235,7 @@ export class Matterbridge extends EventEmitter {
|
|
|
1517
1235
|
}
|
|
1518
1236
|
});
|
|
1519
1237
|
}
|
|
1520
|
-
/**
|
|
1521
|
-
* Starts the Matterbridge in bridge mode.
|
|
1522
|
-
* @private
|
|
1523
|
-
* @returns {Promise<void>} A promise that resolves when the Matterbridge is started.
|
|
1524
|
-
*/
|
|
1525
1238
|
async startBridge() {
|
|
1526
|
-
// Plugins are configured by a timer when matter server is started and plugin.configured is set to true
|
|
1527
1239
|
if (!this.storageManager)
|
|
1528
1240
|
throw new Error('No storage manager initialized');
|
|
1529
1241
|
if (!this.matterbridgeContext)
|
|
@@ -1542,7 +1254,6 @@ export class Matterbridge extends EventEmitter {
|
|
|
1542
1254
|
let failCount = 0;
|
|
1543
1255
|
this.startMatterInterval = setInterval(async () => {
|
|
1544
1256
|
for (const plugin of this.plugins) {
|
|
1545
|
-
// new code to not start the bridge if one plugin is in error cause the controllers will delete the devices loosing all the configuration
|
|
1546
1257
|
if (!plugin.enabled)
|
|
1547
1258
|
continue;
|
|
1548
1259
|
if (plugin.error) {
|
|
@@ -1567,18 +1278,15 @@ export class Matterbridge extends EventEmitter {
|
|
|
1567
1278
|
clearInterval(this.startMatterInterval);
|
|
1568
1279
|
this.startMatterInterval = undefined;
|
|
1569
1280
|
this.log.debug('Cleared startMatterInterval interval for Matterbridge');
|
|
1570
|
-
// Start the Matter server
|
|
1571
1281
|
await this.startMatterServer();
|
|
1572
1282
|
this.log.notice('Matter server started');
|
|
1573
|
-
// Show the QR code for commissioning or log the already commissioned message
|
|
1574
1283
|
await this.showCommissioningQRCode(this.commissioningServer, this.matterbridgeContext, this.nodeContext, 'Matterbridge');
|
|
1575
|
-
// Configure the plugins
|
|
1576
1284
|
this.configureTimeout = setTimeout(async () => {
|
|
1577
1285
|
for (const plugin of this.plugins) {
|
|
1578
1286
|
if (!plugin.enabled || !plugin.loaded || !plugin.started || plugin.error)
|
|
1579
1287
|
continue;
|
|
1580
1288
|
try {
|
|
1581
|
-
await this.plugins.configure(plugin);
|
|
1289
|
+
await this.plugins.configure(plugin);
|
|
1582
1290
|
}
|
|
1583
1291
|
catch (error) {
|
|
1584
1292
|
plugin.error = true;
|
|
@@ -1587,7 +1295,6 @@ export class Matterbridge extends EventEmitter {
|
|
|
1587
1295
|
}
|
|
1588
1296
|
this.wssSendRefreshRequired();
|
|
1589
1297
|
}, 30 * 1000);
|
|
1590
|
-
// Setting reachability to true
|
|
1591
1298
|
this.reachabilityTimeout = setTimeout(() => {
|
|
1592
1299
|
this.log.info(`Setting reachability to true for ${plg}Matterbridge${db}`);
|
|
1593
1300
|
if (this.commissioningServer)
|
|
@@ -1597,14 +1304,7 @@ export class Matterbridge extends EventEmitter {
|
|
|
1597
1304
|
}, 60 * 1000);
|
|
1598
1305
|
}, 1000);
|
|
1599
1306
|
}
|
|
1600
|
-
/**
|
|
1601
|
-
* Starts the Matterbridge in childbridge mode.
|
|
1602
|
-
* @private
|
|
1603
|
-
* @returns {Promise<void>} A promise that resolves when the Matterbridge is started.
|
|
1604
|
-
*/
|
|
1605
1307
|
async startChildbridge() {
|
|
1606
|
-
// Matterbridge.addBridgedDevice creates the commissionig servers and add the devices to the the commissioning server or to the aggregator
|
|
1607
|
-
// Plugins are configured by a timer when matter server is started and plugin.configured is set to true
|
|
1608
1308
|
if (!this.storageManager)
|
|
1609
1309
|
throw new Error('No storage manager initialized');
|
|
1610
1310
|
this.matterServer = await this.createMatterServer(this.storageManager);
|
|
@@ -1614,7 +1314,6 @@ export class Matterbridge extends EventEmitter {
|
|
|
1614
1314
|
this.startMatterInterval = setInterval(async () => {
|
|
1615
1315
|
let allStarted = true;
|
|
1616
1316
|
for (const plugin of this.plugins) {
|
|
1617
|
-
// Prevents to start the bridge if one plugin is in error cause the controllers will delete the devices loosing all the configuration
|
|
1618
1317
|
if (!plugin.enabled)
|
|
1619
1318
|
continue;
|
|
1620
1319
|
if (plugin.error) {
|
|
@@ -1642,16 +1341,14 @@ export class Matterbridge extends EventEmitter {
|
|
|
1642
1341
|
clearInterval(this.startMatterInterval);
|
|
1643
1342
|
this.startMatterInterval = undefined;
|
|
1644
1343
|
this.log.debug('Cleared startMatterInterval interval in childbridge mode');
|
|
1645
|
-
// Start the Matter server
|
|
1646
1344
|
await this.startMatterServer();
|
|
1647
1345
|
this.log.notice('Matter server started');
|
|
1648
|
-
// Configure the plugins
|
|
1649
1346
|
this.configureTimeout = setTimeout(async () => {
|
|
1650
1347
|
for (const plugin of this.plugins) {
|
|
1651
1348
|
if (!plugin.enabled || !plugin.loaded || !plugin.started || plugin.error)
|
|
1652
1349
|
continue;
|
|
1653
1350
|
try {
|
|
1654
|
-
await this.plugins.configure(plugin);
|
|
1351
|
+
await this.plugins.configure(plugin);
|
|
1655
1352
|
}
|
|
1656
1353
|
catch (error) {
|
|
1657
1354
|
plugin.error = true;
|
|
@@ -1680,7 +1377,6 @@ export class Matterbridge extends EventEmitter {
|
|
|
1680
1377
|
continue;
|
|
1681
1378
|
}
|
|
1682
1379
|
await this.showCommissioningQRCode(plugin.commissioningServer, plugin.storageContext, plugin.nodeContext, plugin.name);
|
|
1683
|
-
// Setting reachability to true
|
|
1684
1380
|
plugin.reachabilityTimeout = setTimeout(() => {
|
|
1685
1381
|
this.log.info(`Setting reachability to true for ${plg}${plugin.name}${db}`);
|
|
1686
1382
|
if (plugin.commissioningServer)
|
|
@@ -1693,11 +1389,6 @@ export class Matterbridge extends EventEmitter {
|
|
|
1693
1389
|
}
|
|
1694
1390
|
}, 1000);
|
|
1695
1391
|
}
|
|
1696
|
-
/**
|
|
1697
|
-
* Starts the Matterbridge controller.
|
|
1698
|
-
* @private
|
|
1699
|
-
* @returns {Promise<void>} A promise that resolves when the Matterbridge is started.
|
|
1700
|
-
*/
|
|
1701
1392
|
async startController() {
|
|
1702
1393
|
if (!this.storageManager) {
|
|
1703
1394
|
this.log.error('No storage manager initialized');
|
|
@@ -1760,7 +1451,7 @@ export class Matterbridge extends EventEmitter {
|
|
|
1760
1451
|
const nodeId = await this.commissioningController.commissionNode(options);
|
|
1761
1452
|
this.log.info(`Commissioning successfully done with nodeId: ${nodeId}`);
|
|
1762
1453
|
this.log.info('ActiveSessionInformation:', this.commissioningController.getActiveSessionInformation());
|
|
1763
|
-
}
|
|
1454
|
+
}
|
|
1764
1455
|
if (hasParameter('unpairall')) {
|
|
1765
1456
|
this.log.info('***Commissioning controller unpairing all nodes...');
|
|
1766
1457
|
const nodeIds = this.commissioningController.getCommissionedNodes();
|
|
@@ -1771,8 +1462,6 @@ export class Matterbridge extends EventEmitter {
|
|
|
1771
1462
|
return;
|
|
1772
1463
|
}
|
|
1773
1464
|
if (hasParameter('discover')) {
|
|
1774
|
-
// const discover = await this.commissioningController.discoverCommissionableDevices({ productId: 0x8000, deviceType: 0xfff1 });
|
|
1775
|
-
// console.log(discover);
|
|
1776
1465
|
}
|
|
1777
1466
|
if (!this.commissioningController.isCommissioned()) {
|
|
1778
1467
|
this.log.info('***Commissioning controller is not commissioned: use matterbridge -controller -pairingcode [pairingcode] to commission a device');
|
|
@@ -1813,12 +1502,10 @@ export class Matterbridge extends EventEmitter {
|
|
|
1813
1502
|
},
|
|
1814
1503
|
});
|
|
1815
1504
|
node.logStructure();
|
|
1816
|
-
// Get the interaction client
|
|
1817
1505
|
this.log.info('Getting the interaction client');
|
|
1818
1506
|
const interactionClient = await node.getInteractionClient();
|
|
1819
1507
|
let cluster;
|
|
1820
1508
|
let attributes;
|
|
1821
|
-
// Log BasicInformationCluster
|
|
1822
1509
|
cluster = BasicInformationCluster;
|
|
1823
1510
|
attributes = await interactionClient.getMultipleAttributes({
|
|
1824
1511
|
attributes: [{ clusterId: cluster.id }],
|
|
@@ -1828,7 +1515,6 @@ export class Matterbridge extends EventEmitter {
|
|
|
1828
1515
|
attributes.forEach((attribute) => {
|
|
1829
1516
|
this.log.info(`- endpoint ${or}${attribute.path.endpointId}${nf} cluster ${hk}${getClusterNameById(attribute.path.clusterId)}${nf} (${hk}0x${attribute.path.clusterId.toString(16)}${nf}) attribute ${zb}${attribute.path.attributeName}${nf} (${zb}0x${attribute.path.attributeId.toString(16)}${nf}): ${typeof attribute.value === 'object' ? stringify(attribute.value) : attribute.value}`);
|
|
1830
1517
|
});
|
|
1831
|
-
// Log PowerSourceCluster
|
|
1832
1518
|
cluster = PowerSourceCluster;
|
|
1833
1519
|
attributes = await interactionClient.getMultipleAttributes({
|
|
1834
1520
|
attributes: [{ clusterId: cluster.id }],
|
|
@@ -1838,7 +1524,6 @@ export class Matterbridge extends EventEmitter {
|
|
|
1838
1524
|
attributes.forEach((attribute) => {
|
|
1839
1525
|
this.log.info(`- endpoint ${or}${attribute.path.endpointId}${nf} cluster ${hk}${getClusterNameById(attribute.path.clusterId)}${nf} (${hk}0x${attribute.path.clusterId.toString(16)}${nf}) attribute ${zb}${attribute.path.attributeName}${nf} (${zb}0x${attribute.path.attributeId.toString(16)}${nf}): ${typeof attribute.value === 'object' ? stringify(attribute.value) : attribute.value}`);
|
|
1840
1526
|
});
|
|
1841
|
-
// Log ThreadNetworkDiagnostics
|
|
1842
1527
|
cluster = ThreadNetworkDiagnosticsCluster;
|
|
1843
1528
|
attributes = await interactionClient.getMultipleAttributes({
|
|
1844
1529
|
attributes: [{ clusterId: cluster.id }],
|
|
@@ -1848,7 +1533,6 @@ export class Matterbridge extends EventEmitter {
|
|
|
1848
1533
|
attributes.forEach((attribute) => {
|
|
1849
1534
|
this.log.info(`- endpoint ${or}${attribute.path.endpointId}${nf} cluster ${hk}${getClusterNameById(attribute.path.clusterId)}${nf} (${hk}0x${attribute.path.clusterId.toString(16)}${nf}) attribute ${zb}${attribute.path.attributeName}${nf} (${zb}0x${attribute.path.attributeId.toString(16)}${nf}): ${typeof attribute.value === 'object' ? stringify(attribute.value) : attribute.value}`);
|
|
1850
1535
|
});
|
|
1851
|
-
// Log SwitchCluster
|
|
1852
1536
|
cluster = SwitchCluster;
|
|
1853
1537
|
attributes = await interactionClient.getMultipleAttributes({
|
|
1854
1538
|
attributes: [{ clusterId: cluster.id }],
|
|
@@ -1869,15 +1553,6 @@ export class Matterbridge extends EventEmitter {
|
|
|
1869
1553
|
this.log.info('Subscribed to all attributes and events');
|
|
1870
1554
|
}
|
|
1871
1555
|
}
|
|
1872
|
-
/** ***********************************************************************************************************************************/
|
|
1873
|
-
/** Matter.js methods */
|
|
1874
|
-
/** ***********************************************************************************************************************************/
|
|
1875
|
-
/**
|
|
1876
|
-
* Starts the matter storage process based on the specified storage type and name.
|
|
1877
|
-
* @param {string} storageType - The type of storage to start (e.g., 'disk', 'json').
|
|
1878
|
-
* @param {string} storageName - The name of the storage file.
|
|
1879
|
-
* @returns {Promise<void>} - A promise that resolves when the storage process is started.
|
|
1880
|
-
*/
|
|
1881
1556
|
async startMatterStorage(storageType, storageName) {
|
|
1882
1557
|
this.log.debug(`Starting matter ${storageType} storage ${CYAN}${storageName}${db}`);
|
|
1883
1558
|
if (storageType === 'disk') {
|
|
@@ -1926,12 +1601,6 @@ export class Matterbridge extends EventEmitter {
|
|
|
1926
1601
|
await this.matterbridgeContext.set('passcode', this.passcode);
|
|
1927
1602
|
await this.matterbridgeContext.set('discriminator', this.discriminator);
|
|
1928
1603
|
}
|
|
1929
|
-
/**
|
|
1930
|
-
* Convert the old API matter storage to the new API format.
|
|
1931
|
-
* @param {StorageContext} context - The context of Matterbridge or of the plugin.
|
|
1932
|
-
* @param {string} pluginName - The name of the plugin or Matterbridge.
|
|
1933
|
-
* @returns {Promise<void>} - A promise that resolves when the storage process is started.
|
|
1934
|
-
*/
|
|
1935
1604
|
async convertStorage(context, pluginName) {
|
|
1936
1605
|
if (this.edge !== false)
|
|
1937
1606
|
return;
|
|
@@ -1946,19 +1615,13 @@ export class Matterbridge extends EventEmitter {
|
|
|
1946
1615
|
else {
|
|
1947
1616
|
this.log.notice(`Converting matter node storage to Matterbridge edge for ${plg}${pluginName}${nt}...`);
|
|
1948
1617
|
}
|
|
1949
|
-
// Read FabricManager from the old storage and get FabricManager.fabrics and FabricManager.nextFabricIndex
|
|
1950
1618
|
const fabricManagerContext = context.createContext('FabricManager');
|
|
1951
1619
|
const fabrics = (await fabricManagerContext.get('fabrics', []));
|
|
1952
1620
|
const nextFabricIndex = await fabricManagerContext.get('nextFabricIndex', 0);
|
|
1953
|
-
// Read EventHandler from the old storage
|
|
1954
1621
|
const eventHandlerContext = context.createContext('EventHandler');
|
|
1955
|
-
// Read SessionManager from the old storage
|
|
1956
1622
|
const sessionManagerContext = context.createContext('SessionManager');
|
|
1957
|
-
// Read EndpointStructure from the old storage
|
|
1958
1623
|
const endpointStructureContext = context.createContext('EndpointStructure');
|
|
1959
|
-
// Read generalCommissioning from the old storage
|
|
1960
1624
|
const generalCommissioningContext = context.createContext('Cluster-0-48');
|
|
1961
|
-
// Read basicInformation from the old storage
|
|
1962
1625
|
const basicInformationContext = context.createContext('Cluster-0-40');
|
|
1963
1626
|
const fabricInfo = {};
|
|
1964
1627
|
const fabricInfoArray = [];
|
|
@@ -2012,13 +1675,8 @@ export class Matterbridge extends EventEmitter {
|
|
|
2012
1675
|
await nodeStorage.createContext('root').createContext('commissioning').set('fabrics', fabricInfo);
|
|
2013
1676
|
await nodeStorage.createContext('root').createContext('operationalCredentials').set('commissionedFabrics', fabricInfoArray.length);
|
|
2014
1677
|
await nodeStorage.createContext('root').createContext('operationalCredentials').set('fabrics', fabricInfoArray);
|
|
2015
|
-
// operationalCredentials.nocs ==>> [{noc: fabric.operationalCert, icac: null, fabricIndex: fabric.fabricIndex }]
|
|
2016
1678
|
await nodeStorage.createContext('root').createContext('operationalCredentials').set('nocs', nocArray);
|
|
2017
|
-
// operationalCredentials.trustedRootCertificates ==>> ["{\"__object__\":\"Uint8Array\",\"__value__\":\"" + fabric.rootCert + "\"}"]
|
|
2018
1679
|
await nodeStorage.createContext('root').createContext('operationalCredentials').set('trustedRootCertificates', trcArray);
|
|
2019
|
-
// ACL updated, updating ACL manager { fabricIndex: 3, privilege: 5, authMode: 2, subjects: [ 18446744060825763897 ], targets: null }
|
|
2020
|
-
// From fabric.rootNodeId if fabric.scopedClusterData.get(0x1f).get('acl') is empty
|
|
2021
|
-
// [{"fabricIndex":3,"privilege":5,"authMode":2,"subjects":["{\"__object__\":\"BigInt\",\"__value__\":\"18446744060825763897\"}"],"targets":null}]
|
|
2022
1680
|
await nodeStorage.createContext('root').createContext('accessControl').set('acl', aclArray);
|
|
2023
1681
|
await nodeStorage
|
|
2024
1682
|
.createContext('root')
|
|
@@ -2041,25 +1699,6 @@ export class Matterbridge extends EventEmitter {
|
|
|
2041
1699
|
.createContext('root')
|
|
2042
1700
|
.createContext('productDescription')
|
|
2043
1701
|
.set('vendorId', await context.get('vendorId', 0xfff1));
|
|
2044
|
-
/*
|
|
2045
|
-
"Matterbridge.EndpointStructure": {
|
|
2046
|
-
"unique_d60ca095a002f160-index_0": 1,
|
|
2047
|
-
"unique_d60ca095a002f160-index_0-custom_Switch0": 2,
|
|
2048
|
-
"unique_d60ca095a002f160-index_0-custom_Outlet0": 3,
|
|
2049
|
-
"unique_d60ca095a002f160-index_0-custom_Light0": 4,
|
|
2050
|
-
"unique_d60ca095a002f160-index_0-unique_7ddb4752b982ee108d5928e934f0fcfa": 2,
|
|
2051
|
-
"unique_d60ca095a002f160-index_0-unique_7ddb4752b982ee108d5928e934f0fcfa-custom_PowerSource": 3,
|
|
2052
|
-
"unique_d60ca095a002f160-index_0-unique_7ddb4752b982ee108d5928e934f0fcfa-custom_light:0": 4,
|
|
2053
|
-
"unique_d60ca095a002f160-index_0-unique_7ddb4752b982ee108d5928e934f0fcfa-custom_light:1": 5,
|
|
2054
|
-
"unique_d60ca095a002f160-index_0-unique_7ddb4752b982ee108d5928e934f0fcfa-custom_light:2": 6,
|
|
2055
|
-
"unique_d60ca095a002f160-index_0-unique_7ddb4752b982ee108d5928e934f0fcfa-custom_light:3": 7,
|
|
2056
|
-
"unique_d60ca095a002f160-index_0-unique_7ddb4752b982ee108d5928e934f0fcfa-custom_meter:0": 8,
|
|
2057
|
-
"unique_d60ca095a002f160-index_0-unique_7ddb4752b982ee108d5928e934f0fcfa-custom_meter:1": 9,
|
|
2058
|
-
"unique_d60ca095a002f160-index_0-unique_7ddb4752b982ee108d5928e934f0fcfa-custom_meter:2": 10,
|
|
2059
|
-
"unique_d60ca095a002f160-index_0-unique_7ddb4752b982ee108d5928e934f0fcfa-custom_meter:3": 11,
|
|
2060
|
-
"nextEndpointId": 5
|
|
2061
|
-
},
|
|
2062
|
-
*/
|
|
2063
1702
|
const rootDeviceName = (await context.get('deviceName', '')).replace(/[ .]/g, '');
|
|
2064
1703
|
this.log.info(`Converting ${pluginName}.EndpointStructure to root.parts.${rootDeviceName}...`);
|
|
2065
1704
|
for (const key of await endpointStructureContext.keys()) {
|
|
@@ -2138,12 +1777,6 @@ export class Matterbridge extends EventEmitter {
|
|
|
2138
1777
|
this.log.error(`convertStorage error converting matter storage to Matterbridge edge for ${plg}${pluginName}${er}:`, error);
|
|
2139
1778
|
}
|
|
2140
1779
|
}
|
|
2141
|
-
/**
|
|
2142
|
-
* Makes a backup copy of the specified matter JSON storage file.
|
|
2143
|
-
*
|
|
2144
|
-
* @param storageName - The name of the JSON storage file to be backed up.
|
|
2145
|
-
* @param backupName - The name of the backup file to be created.
|
|
2146
|
-
*/
|
|
2147
1780
|
async backupMatterStorage(storageName, backupName) {
|
|
2148
1781
|
try {
|
|
2149
1782
|
this.log.debug(`Making backup copy of ${storageName}`);
|
|
@@ -2164,12 +1797,6 @@ export class Matterbridge extends EventEmitter {
|
|
|
2164
1797
|
}
|
|
2165
1798
|
}
|
|
2166
1799
|
}
|
|
2167
|
-
/**
|
|
2168
|
-
* Restore the specified matter JSON storage file.
|
|
2169
|
-
*
|
|
2170
|
-
* @param backupName - The name of the backup file to restore from.
|
|
2171
|
-
* @param storageName - The name of the JSON storage file to restored.
|
|
2172
|
-
*/
|
|
2173
1800
|
async restoreMatterStorage(backupName, storageName) {
|
|
2174
1801
|
try {
|
|
2175
1802
|
this.log.notice(`Restoring the backup copy of ${storageName}`);
|
|
@@ -2190,10 +1817,6 @@ export class Matterbridge extends EventEmitter {
|
|
|
2190
1817
|
}
|
|
2191
1818
|
}
|
|
2192
1819
|
}
|
|
2193
|
-
/**
|
|
2194
|
-
* Stops the matter storage.
|
|
2195
|
-
* @returns {Promise<void>} A promise that resolves when the storage is stopped.
|
|
2196
|
-
*/
|
|
2197
1820
|
async stopMatterStorage() {
|
|
2198
1821
|
this.log.debug('Stopping storage');
|
|
2199
1822
|
await this.storageManager?.close();
|
|
@@ -2202,14 +1825,8 @@ export class Matterbridge extends EventEmitter {
|
|
|
2202
1825
|
this.matterbridgeContext = undefined;
|
|
2203
1826
|
this.mattercontrollerContext = undefined;
|
|
2204
1827
|
}
|
|
2205
|
-
/**
|
|
2206
|
-
* Creates a Matter server using the provided storage manager and the provided mdnsInterface.
|
|
2207
|
-
* @param storageManager The storage manager to be used by the Matter server.
|
|
2208
|
-
*
|
|
2209
|
-
*/
|
|
2210
1828
|
async createMatterServer(storageManager) {
|
|
2211
1829
|
this.log.debug('Creating matter server');
|
|
2212
|
-
// Validate mdnsInterface
|
|
2213
1830
|
if (this.mdnsInterface) {
|
|
2214
1831
|
const networkInterfaces = os.networkInterfaces();
|
|
2215
1832
|
const availableInterfaces = Object.keys(networkInterfaces);
|
|
@@ -2225,10 +1842,6 @@ export class Matterbridge extends EventEmitter {
|
|
|
2225
1842
|
this.log.debug(`Created matter server with mdnsInterface: ${this.mdnsInterface ?? 'all available interfaces'}`);
|
|
2226
1843
|
return matterServer;
|
|
2227
1844
|
}
|
|
2228
|
-
/**
|
|
2229
|
-
* Starts the Matter server.
|
|
2230
|
-
* If the Matter server is not initialized, it logs an error and performs cleanup.
|
|
2231
|
-
*/
|
|
2232
1845
|
async startMatterServer() {
|
|
2233
1846
|
if (!this.matterServer) {
|
|
2234
1847
|
this.log.error('No matter server initialized');
|
|
@@ -2238,11 +1851,7 @@ export class Matterbridge extends EventEmitter {
|
|
|
2238
1851
|
this.log.debug('Starting matter server...');
|
|
2239
1852
|
await this.matterServer.start();
|
|
2240
1853
|
this.log.debug('Started matter server');
|
|
2241
|
-
// this.commissioningServer?.getRootEndpoint() && logEndpoint(this.commissioningServer?.getRootEndpoint());
|
|
2242
1854
|
}
|
|
2243
|
-
/**
|
|
2244
|
-
* Stops the Matter server, commissioningServer and commissioningController.
|
|
2245
|
-
*/
|
|
2246
1855
|
async stopMatterServer() {
|
|
2247
1856
|
this.log.debug('Stopping matter commissioningServer');
|
|
2248
1857
|
await this.commissioningServer?.close();
|
|
@@ -2256,35 +1865,23 @@ export class Matterbridge extends EventEmitter {
|
|
|
2256
1865
|
this.matterAggregator = undefined;
|
|
2257
1866
|
this.matterServer = undefined;
|
|
2258
1867
|
}
|
|
2259
|
-
/**
|
|
2260
|
-
* Creates a Matter Aggregator.
|
|
2261
|
-
* @param {StorageContext} context - The storage context.
|
|
2262
|
-
* @returns {Aggregator} - The created Matter Aggregator.
|
|
2263
|
-
*/
|
|
2264
1868
|
async createMatterAggregator(context, pluginName) {
|
|
2265
1869
|
this.log.debug(`Creating matter aggregator for ${plg}${pluginName}${db}`);
|
|
2266
1870
|
const matterAggregator = new Aggregator();
|
|
2267
1871
|
return matterAggregator;
|
|
2268
1872
|
}
|
|
2269
|
-
/**
|
|
2270
|
-
* Creates a matter commissioning server.
|
|
2271
|
-
*
|
|
2272
|
-
* @param {StorageContext} context - The storage context.
|
|
2273
|
-
* @param {string} pluginName - The name of the commissioning server.
|
|
2274
|
-
* @returns {CommissioningServer} The created commissioning server.
|
|
2275
|
-
*/
|
|
2276
1873
|
async createCommisioningServer(context, pluginName) {
|
|
2277
1874
|
this.log.debug(`Creating matter commissioning server for plugin ${plg}${pluginName}${db}`);
|
|
2278
1875
|
const deviceName = await context.get('deviceName');
|
|
2279
1876
|
const deviceType = await context.get('deviceType');
|
|
2280
1877
|
const vendorId = await context.get('vendorId');
|
|
2281
|
-
const vendorName = await context.get('vendorName');
|
|
1878
|
+
const vendorName = await context.get('vendorName');
|
|
2282
1879
|
const productId = await context.get('productId');
|
|
2283
|
-
const productName = await context.get('productName');
|
|
1880
|
+
const productName = await context.get('productName');
|
|
2284
1881
|
const serialNumber = await context.get('serialNumber');
|
|
2285
1882
|
const uniqueId = await context.get('uniqueId');
|
|
2286
1883
|
const softwareVersion = await context.get('softwareVersion', 1);
|
|
2287
|
-
const softwareVersionString = await context.get('softwareVersionString', '1.0.0');
|
|
1884
|
+
const softwareVersionString = await context.get('softwareVersionString', '1.0.0');
|
|
2288
1885
|
const hardwareVersion = await context.get('hardwareVersion', 1);
|
|
2289
1886
|
const hardwareVersionString = await context.get('hardwareVersionString', '1.0.0');
|
|
2290
1887
|
this.log.debug(`Creating matter commissioning server for plugin ${plg}${pluginName}${db} with deviceName '${deviceName}' deviceType ${deviceType}(0x${deviceType.toString(16).padStart(4, '0')})`);
|
|
@@ -2292,7 +1889,6 @@ export class Matterbridge extends EventEmitter {
|
|
|
2292
1889
|
this.log.debug(`Creating matter commissioning server for plugin ${plg}${pluginName}${db} with softwareVersion ${softwareVersion} softwareVersionString ${softwareVersionString}`);
|
|
2293
1890
|
this.log.debug(`Creating matter commissioning server for plugin ${plg}${pluginName}${db} with hardwareVersion ${hardwareVersion} hardwareVersionString ${hardwareVersionString}`);
|
|
2294
1891
|
this.log.debug(`Creating matter commissioning server for plugin ${plg}${pluginName}${db} with nodeLabel '${productName}' port ${CYAN}${this.port}${db} discriminator ${CYAN}${this.discriminator}${db} passcode ${CYAN}${this.passcode}${db} `);
|
|
2295
|
-
// Validate ipv4address
|
|
2296
1892
|
if (this.ipv4address) {
|
|
2297
1893
|
const networkInterfaces = os.networkInterfaces();
|
|
2298
1894
|
const availableAddresses = Object.values(networkInterfaces)
|
|
@@ -2307,7 +1903,6 @@ export class Matterbridge extends EventEmitter {
|
|
|
2307
1903
|
this.log.info(`Using ipv4address '${this.ipv4address}' for the Matter commissioning server.`);
|
|
2308
1904
|
}
|
|
2309
1905
|
}
|
|
2310
|
-
// Validate ipv6address
|
|
2311
1906
|
if (this.ipv6address) {
|
|
2312
1907
|
const networkInterfaces = os.networkInterfaces();
|
|
2313
1908
|
const availableAddresses = Object.values(networkInterfaces)
|
|
@@ -2338,7 +1933,7 @@ export class Matterbridge extends EventEmitter {
|
|
|
2338
1933
|
nodeLabel: productName,
|
|
2339
1934
|
productLabel: productName,
|
|
2340
1935
|
softwareVersion,
|
|
2341
|
-
softwareVersionString,
|
|
1936
|
+
softwareVersionString,
|
|
2342
1937
|
hardwareVersion,
|
|
2343
1938
|
hardwareVersionString,
|
|
2344
1939
|
uniqueId,
|
|
@@ -2434,24 +2029,6 @@ export class Matterbridge extends EventEmitter {
|
|
|
2434
2029
|
commissioningServer.addCommandHandler('testEventTrigger', async ({ request: { enableKey, eventTrigger } }) => this.log.info(`testEventTrigger called on GeneralDiagnostic cluster: ${enableKey} ${eventTrigger}`));
|
|
2435
2030
|
return commissioningServer;
|
|
2436
2031
|
}
|
|
2437
|
-
/**
|
|
2438
|
-
* Creates a commissioning server storage context.
|
|
2439
|
-
*
|
|
2440
|
-
* @param pluginName - The name of the plugin.
|
|
2441
|
-
* @param deviceName - The name of the device.
|
|
2442
|
-
* @param deviceType - The type of the device.
|
|
2443
|
-
* @param vendorId - The vendor ID.
|
|
2444
|
-
* @param vendorName - The vendor name.
|
|
2445
|
-
* @param productId - The product ID.
|
|
2446
|
-
* @param productName - The product name.
|
|
2447
|
-
* @param serialNumber - The serial number of the device (optional).
|
|
2448
|
-
* @param uniqueId - The unique ID of the device (optional).
|
|
2449
|
-
* @param softwareVersion - The software version of the device (optional).
|
|
2450
|
-
* @param softwareVersionString - The software version string of the device (optional).
|
|
2451
|
-
* @param hardwareVersion - The hardware version of the device (optional).
|
|
2452
|
-
* @param hardwareVersionString - The hardware version string of the device (optional).
|
|
2453
|
-
* @returns The storage context for the commissioning server.
|
|
2454
|
-
*/
|
|
2455
2032
|
async createCommissioningServerContext(pluginName, deviceName, deviceType, vendorId, vendorName, productId, productName) {
|
|
2456
2033
|
if (!this.storageManager)
|
|
2457
2034
|
throw new Error('No storage manager initialized');
|
|
@@ -2479,13 +2056,6 @@ export class Matterbridge extends EventEmitter {
|
|
|
2479
2056
|
this.log.debug(`- hardwareVersion: ${await storageContext.get('hardwareVersion')} hardwareVersionString: ${await storageContext.get('hardwareVersionString')}`);
|
|
2480
2057
|
return storageContext;
|
|
2481
2058
|
}
|
|
2482
|
-
/**
|
|
2483
|
-
* Imports the commissioning server context for a specific plugin and device.
|
|
2484
|
-
* @param pluginName - The name of the plugin.
|
|
2485
|
-
* @param device - The MatterbridgeDevice object representing the device.
|
|
2486
|
-
* @returns The commissioning server context.
|
|
2487
|
-
* @throws Error if the BasicInformationCluster is not found.
|
|
2488
|
-
*/
|
|
2489
2059
|
async importCommissioningServerContext(pluginName, device) {
|
|
2490
2060
|
this.log.debug(`Importing matter commissioning server storage context from device for ${plg}${pluginName}${db}`);
|
|
2491
2061
|
const basic = device.getClusterServer(BasicInformationCluster);
|
|
@@ -2520,14 +2090,6 @@ export class Matterbridge extends EventEmitter {
|
|
|
2520
2090
|
this.log.debug(`- hardwareVersion: ${await storageContext.get('hardwareVersion')} hardwareVersionString: ${await storageContext.get('hardwareVersionString')}`);
|
|
2521
2091
|
return storageContext;
|
|
2522
2092
|
}
|
|
2523
|
-
/**
|
|
2524
|
-
* Shows the commissioning server QR code for a given plugin.
|
|
2525
|
-
* @param {CommissioningServer} commissioningServer - The commissioning server instance.
|
|
2526
|
-
* @param {StorageContext} storageContext - The storage context instance.
|
|
2527
|
-
* @param {NodeStorage} nodeContext - The node storage instance.
|
|
2528
|
-
* @param {string} pluginName - The name of the plugin of Matterbridge in bridge mode.
|
|
2529
|
-
* @returns {Promise<void>} - A promise that resolves when the QR code is shown.
|
|
2530
|
-
*/
|
|
2531
2093
|
async showCommissioningQRCode(commissioningServer, storageContext, nodeContext, pluginName) {
|
|
2532
2094
|
if (!commissioningServer || !storageContext || !nodeContext || !pluginName) {
|
|
2533
2095
|
this.log.error(`showCommissioningQRCode error: commissioningServer: ${!commissioningServer} storageContext: ${!storageContext} nodeContext: ${!nodeContext} pluginName: ${pluginName}`);
|
|
@@ -2538,8 +2100,7 @@ export class Matterbridge extends EventEmitter {
|
|
|
2538
2100
|
const { qrPairingCode, manualPairingCode } = commissioningServer.getPairingCode();
|
|
2539
2101
|
const QrCode = new QrCodeSchema();
|
|
2540
2102
|
this.log.info(`*The commissioning server on port ${commissioningServer.getPort()} for ${plg}${pluginName}${nf} is not commissioned. Pair it scanning the QR code:\n\n`);
|
|
2541
|
-
|
|
2542
|
-
if (this.log.logLevel === "debug" /* LogLevel.DEBUG */ || this.log.logLevel === "info" /* LogLevel.INFO */)
|
|
2103
|
+
if (this.log.logLevel === "debug" || this.log.logLevel === "info")
|
|
2543
2104
|
console.log(`${QrCode.encode(qrPairingCode)}\n`);
|
|
2544
2105
|
this.log.info(`${plg}${pluginName}${nf} \n\nqrPairingCode: ${qrPairingCode} \n\nManual pairing code: ${manualPairingCode}\n`);
|
|
2545
2106
|
if (pluginName === 'Matterbridge') {
|
|
@@ -2586,12 +2147,6 @@ export class Matterbridge extends EventEmitter {
|
|
|
2586
2147
|
}
|
|
2587
2148
|
this.wssSendRefreshRequired();
|
|
2588
2149
|
}
|
|
2589
|
-
/**
|
|
2590
|
-
* Sanitizes the fabric information by converting bigint properties to string cause res.json doesn't know bigint.
|
|
2591
|
-
*
|
|
2592
|
-
* @param fabricInfo - The array of exposed fabric information objects.
|
|
2593
|
-
* @returns An array of sanitized exposed fabric information objects.
|
|
2594
|
-
*/
|
|
2595
2150
|
sanitizeFabricInformations(fabricInfo) {
|
|
2596
2151
|
return fabricInfo.map((info) => {
|
|
2597
2152
|
return {
|
|
@@ -2605,12 +2160,6 @@ export class Matterbridge extends EventEmitter {
|
|
|
2605
2160
|
};
|
|
2606
2161
|
});
|
|
2607
2162
|
}
|
|
2608
|
-
/**
|
|
2609
|
-
* Sanitizes the session information by converting bigint properties to string.
|
|
2610
|
-
*
|
|
2611
|
-
* @param sessionInfo - The array of session information objects.
|
|
2612
|
-
* @returns An array of sanitized session information objects.
|
|
2613
|
-
*/
|
|
2614
2163
|
sanitizeSessionInformation(sessionInfo) {
|
|
2615
2164
|
return sessionInfo
|
|
2616
2165
|
.filter((session) => session.isPeerActive)
|
|
@@ -2638,12 +2187,6 @@ export class Matterbridge extends EventEmitter {
|
|
|
2638
2187
|
};
|
|
2639
2188
|
});
|
|
2640
2189
|
}
|
|
2641
|
-
/**
|
|
2642
|
-
* Sets the reachability of a commissioning server and trigger.
|
|
2643
|
-
*
|
|
2644
|
-
* @param {CommissioningServer} commissioningServer - The commissioning server to set the reachability for.
|
|
2645
|
-
* @param {boolean} reachable - The new reachability status.
|
|
2646
|
-
*/
|
|
2647
2190
|
setCommissioningServerReachability(commissioningServer, reachable) {
|
|
2648
2191
|
const basicInformationCluster = commissioningServer?.getRootClusterServer(BasicInformationCluster);
|
|
2649
2192
|
if (basicInformationCluster && basicInformationCluster.attributes.reachable !== undefined)
|
|
@@ -2651,11 +2194,6 @@ export class Matterbridge extends EventEmitter {
|
|
|
2651
2194
|
if (basicInformationCluster && basicInformationCluster.triggerReachableChangedEvent)
|
|
2652
2195
|
basicInformationCluster.triggerReachableChangedEvent({ reachableNewValue: reachable });
|
|
2653
2196
|
}
|
|
2654
|
-
/**
|
|
2655
|
-
* Sets the reachability of the specified matter aggregator and its bridged devices and trigger.
|
|
2656
|
-
* @param {Aggregator} matterAggregator - The matter aggregator to set the reachability for.
|
|
2657
|
-
* @param {boolean} reachable - A boolean indicating the reachability status to set.
|
|
2658
|
-
*/
|
|
2659
2197
|
setAggregatorReachability(matterAggregator, reachable) {
|
|
2660
2198
|
const basicInformationCluster = matterAggregator.getClusterServer(BasicInformationCluster);
|
|
2661
2199
|
if (basicInformationCluster && basicInformationCluster.attributes.reachable !== undefined)
|
|
@@ -2668,12 +2206,6 @@ export class Matterbridge extends EventEmitter {
|
|
|
2668
2206
|
device.getClusterServer(BridgedDeviceBasicInformationCluster)?.triggerReachableChangedEvent({ reachableNewValue: reachable });
|
|
2669
2207
|
});
|
|
2670
2208
|
}
|
|
2671
|
-
/**
|
|
2672
|
-
* Sets the reachability of a device and trigger.
|
|
2673
|
-
*
|
|
2674
|
-
* @param {MatterbridgeDevice} device - The device to set the reachability for.
|
|
2675
|
-
* @param {boolean} reachable - The new reachability status of the device.
|
|
2676
|
-
*/
|
|
2677
2209
|
setDeviceReachability(device, reachable) {
|
|
2678
2210
|
const basicInformationCluster = device.getClusterServer(BasicInformationCluster);
|
|
2679
2211
|
if (basicInformationCluster && basicInformationCluster.attributes.reachable !== undefined)
|
|
@@ -2722,10 +2254,6 @@ export class Matterbridge extends EventEmitter {
|
|
|
2722
2254
|
}
|
|
2723
2255
|
return vendorName;
|
|
2724
2256
|
};
|
|
2725
|
-
/**
|
|
2726
|
-
* Retrieves the base registered plugins sanitized for res.json().
|
|
2727
|
-
* @returns {BaseRegisteredPlugin[]} A promise that resolves to an array of BaseRegisteredPlugin objects.
|
|
2728
|
-
*/
|
|
2729
2257
|
async getBaseRegisteredPlugins() {
|
|
2730
2258
|
const baseRegisteredPlugins = [];
|
|
2731
2259
|
for (const plugin of this.plugins) {
|
|
@@ -2757,36 +2285,13 @@ export class Matterbridge extends EventEmitter {
|
|
|
2757
2285
|
}
|
|
2758
2286
|
return baseRegisteredPlugins;
|
|
2759
2287
|
}
|
|
2760
|
-
/**
|
|
2761
|
-
* Spawns a child process with the given command and arguments.
|
|
2762
|
-
* @param {string} command - The command to execute.
|
|
2763
|
-
* @param {string[]} args - The arguments to pass to the command (default: []).
|
|
2764
|
-
* @returns {Promise<boolean>} A promise that resolves when the child process exits successfully, or rejects if there is an error.
|
|
2765
|
-
*/
|
|
2766
2288
|
async spawnCommand(command, args = []) {
|
|
2767
|
-
/*
|
|
2768
|
-
npm > npm.cmd on windows
|
|
2769
|
-
cmd.exe ['dir'] on windows
|
|
2770
|
-
await this.spawnCommand('npm', ['install', '-g', 'matterbridge']);
|
|
2771
|
-
process.on('unhandledRejection', (reason, promise) => {
|
|
2772
|
-
this.log.error('Unhandled Rejection at:', promise, 'reason:', reason);
|
|
2773
|
-
});
|
|
2774
|
-
|
|
2775
|
-
spawn - [14:27:21.125] [Matterbridge:spawn]: changed 38 packages in 4s
|
|
2776
|
-
spawn - [14:27:21.125] [Matterbridge:spawn]: 10 packages are looking for funding run `npm fund` for details
|
|
2777
|
-
debug - [14:27:21.131] [Matterbridge]: Child process exited with code 0 and signal null
|
|
2778
|
-
debug - [14:27:21.131] [Matterbridge]: Child process stdio streams have closed with code 0
|
|
2779
|
-
*/
|
|
2780
2289
|
const cmdLine = command + ' ' + args.join(' ');
|
|
2781
2290
|
if (process.platform === 'win32' && command === 'npm') {
|
|
2782
|
-
// Must be spawn('cmd.exe', ['/c', 'npm -g install <package>']);
|
|
2783
2291
|
const argstring = 'npm ' + args.join(' ');
|
|
2784
2292
|
args.splice(0, args.length, '/c', argstring);
|
|
2785
2293
|
command = 'cmd.exe';
|
|
2786
2294
|
}
|
|
2787
|
-
// Decide when using sudo on linux
|
|
2788
|
-
// When you need sudo: Spawn stderr: npm error Error: EACCES: permission denied
|
|
2789
|
-
// When you don't need sudo: Failed to start child process "npm install -g matterbridge-eve-door": spawn sudo ENOENT
|
|
2790
2295
|
if (hasParameter('sudo') || (process.platform === 'linux' && command === 'npm' && !hasParameter('docker') && !hasParameter('nosudo'))) {
|
|
2791
2296
|
args.unshift(command);
|
|
2792
2297
|
command = 'sudo';
|
|
@@ -2844,102 +2349,55 @@ export class Matterbridge extends EventEmitter {
|
|
|
2844
2349
|
}
|
|
2845
2350
|
});
|
|
2846
2351
|
}
|
|
2847
|
-
/**
|
|
2848
|
-
* Sends a WebSocket message to all connected clients.
|
|
2849
|
-
*
|
|
2850
|
-
* @param {string} level - The logger level of the message: debug info notice warn error fatal...
|
|
2851
|
-
* @param {string} time - The time string of the message
|
|
2852
|
-
* @param {string} name - The logger name of the message
|
|
2853
|
-
* @param {string} message - The content of the message.
|
|
2854
|
-
*/
|
|
2855
2352
|
wssSendMessage(level, time, name, message) {
|
|
2856
2353
|
if (!level || !time || !name || !message)
|
|
2857
2354
|
return;
|
|
2858
|
-
// Remove ANSI escape codes from the message
|
|
2859
|
-
// eslint-disable-next-line no-control-regex
|
|
2860
2355
|
message = message.replace(/\x1B\[[0-9;]*[m|s|u|K]/g, '');
|
|
2861
|
-
// Remove leading asterisks from the message
|
|
2862
2356
|
message = message.replace(/^\*+/, '');
|
|
2863
|
-
// Replace all occurrences of \t and \n
|
|
2864
2357
|
message = message.replace(/[\t\n]/g, '');
|
|
2865
|
-
// Remove non-printable characters
|
|
2866
|
-
// eslint-disable-next-line no-control-regex
|
|
2867
2358
|
message = message.replace(/[\x00-\x1F\x7F]/g, '');
|
|
2868
|
-
// Replace all occurrences of \" with "
|
|
2869
2359
|
message = message.replace(/\\"/g, '"');
|
|
2870
|
-
// Define the maximum allowed length for continuous characters without a space
|
|
2871
2360
|
const maxContinuousLength = 100;
|
|
2872
2361
|
const keepStartLength = 20;
|
|
2873
2362
|
const keepEndLength = 20;
|
|
2874
|
-
// Split the message into words
|
|
2875
2363
|
message = message
|
|
2876
2364
|
.split(' ')
|
|
2877
2365
|
.map((word) => {
|
|
2878
|
-
// If the word length exceeds the max continuous length, insert spaces and truncate
|
|
2879
2366
|
if (word.length > maxContinuousLength) {
|
|
2880
2367
|
return word.slice(0, keepStartLength) + ' ... ' + word.slice(-keepEndLength);
|
|
2881
2368
|
}
|
|
2882
2369
|
return word;
|
|
2883
2370
|
})
|
|
2884
2371
|
.join(' ');
|
|
2885
|
-
// Send the message to all connected clients
|
|
2886
2372
|
this.webSocketServer?.clients.forEach((client) => {
|
|
2887
2373
|
if (client.readyState === WebSocket.OPEN) {
|
|
2888
2374
|
client.send(JSON.stringify({ id: WS_ID_LOG, src: 'Matterbridge', level, time, name, message }));
|
|
2889
2375
|
}
|
|
2890
2376
|
});
|
|
2891
2377
|
}
|
|
2892
|
-
/**
|
|
2893
|
-
* Sends a need to refresh WebSocket message to all connected clients.
|
|
2894
|
-
*
|
|
2895
|
-
*/
|
|
2896
2378
|
wssSendRefreshRequired() {
|
|
2897
2379
|
this.matterbridgeInformation.refreshRequired = true;
|
|
2898
|
-
// Send the message to all connected clients
|
|
2899
2380
|
this.webSocketServer?.clients.forEach((client) => {
|
|
2900
2381
|
if (client.readyState === WebSocket.OPEN) {
|
|
2901
2382
|
client.send(JSON.stringify({ id: WS_ID_REFRESH_NEEDED, src: 'Matterbridge', dst: 'Frontend', method: 'refresh_required', params: {} }));
|
|
2902
2383
|
}
|
|
2903
2384
|
});
|
|
2904
2385
|
}
|
|
2905
|
-
/**
|
|
2906
|
-
* Sends a need to restart WebSocket message to all connected clients.
|
|
2907
|
-
*
|
|
2908
|
-
*/
|
|
2909
2386
|
wssSendRestartRequired() {
|
|
2910
2387
|
this.matterbridgeInformation.restartRequired = true;
|
|
2911
|
-
// Send the message to all connected clients
|
|
2912
2388
|
this.webSocketServer?.clients.forEach((client) => {
|
|
2913
2389
|
if (client.readyState === WebSocket.OPEN) {
|
|
2914
2390
|
client.send(JSON.stringify({ id: WS_ID_RESTART_NEEDED, src: 'Matterbridge', dst: 'Frontend', method: 'restart_required', params: {} }));
|
|
2915
2391
|
}
|
|
2916
2392
|
});
|
|
2917
2393
|
}
|
|
2918
|
-
/**
|
|
2919
|
-
* Initializes the frontend of Matterbridge.
|
|
2920
|
-
*
|
|
2921
|
-
* @param port The port number to run the frontend server on. Default is 8283.
|
|
2922
|
-
*/
|
|
2923
2394
|
async initializeFrontend(port = 8283) {
|
|
2924
2395
|
let initializeError = false;
|
|
2925
2396
|
this.log.debug(`Initializing the frontend ${hasParameter('ssl') ? 'https' : 'http'} server on port ${YELLOW}${port}${db}`);
|
|
2926
|
-
// Create the express app that serves the frontend
|
|
2927
2397
|
this.expressApp = express();
|
|
2928
|
-
// Log all requests to the server for debugging
|
|
2929
|
-
/*
|
|
2930
|
-
if (hasParameter('homedir')) {
|
|
2931
|
-
this.expressApp.use((req, res, next) => {
|
|
2932
|
-
this.log.debug(`Received request on expressApp: ${req.method} ${req.url}`);
|
|
2933
|
-
next();
|
|
2934
|
-
});
|
|
2935
|
-
}
|
|
2936
|
-
*/
|
|
2937
|
-
// Serve static files from '/static' endpoint
|
|
2938
2398
|
this.expressApp.use(express.static(path.join(this.rootDirectory, 'frontend/build')));
|
|
2939
2399
|
if (!hasParameter('ssl')) {
|
|
2940
|
-
// Create an HTTP server and attach the express app
|
|
2941
2400
|
this.httpServer = createServer(this.expressApp);
|
|
2942
|
-
// Listen on the specified port
|
|
2943
2401
|
if (hasParameter('ingress')) {
|
|
2944
2402
|
this.httpServer.listen(port, '0.0.0.0', () => {
|
|
2945
2403
|
this.log.info(`The frontend http server is listening on ${UNDERLINE}http://0.0.0.0:${port}${UNDERLINEOFF}${rs}`);
|
|
@@ -2953,7 +2411,6 @@ export class Matterbridge extends EventEmitter {
|
|
|
2953
2411
|
this.log.info(`The frontend http server is listening on ${UNDERLINE}http://[${this.systemInformation.ipv6Address}]:${port}${UNDERLINEOFF}${rs}`);
|
|
2954
2412
|
});
|
|
2955
2413
|
}
|
|
2956
|
-
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
2957
2414
|
this.httpServer.on('error', (error) => {
|
|
2958
2415
|
this.log.error(`Frontend http server error listening on ${port}`);
|
|
2959
2416
|
switch (error.code) {
|
|
@@ -2969,7 +2426,6 @@ export class Matterbridge extends EventEmitter {
|
|
|
2969
2426
|
});
|
|
2970
2427
|
}
|
|
2971
2428
|
else {
|
|
2972
|
-
// Load the SSL certificate, the private key and optionally the CA certificate
|
|
2973
2429
|
let cert;
|
|
2974
2430
|
try {
|
|
2975
2431
|
cert = await fs.readFile(path.join(this.matterbridgeDirectory, 'certs/cert.pem'), 'utf8');
|
|
@@ -2997,9 +2453,7 @@ export class Matterbridge extends EventEmitter {
|
|
|
2997
2453
|
this.log.info(`CA certificate file ${path.join(this.matterbridgeDirectory, 'certs/ca.pem')} not loaded: ${error}`);
|
|
2998
2454
|
}
|
|
2999
2455
|
const serverOptions = { cert, key, ca };
|
|
3000
|
-
// Create an HTTPS server with the SSL certificate and private key (ca is optional) and attach the express app
|
|
3001
2456
|
this.httpsServer = https.createServer(serverOptions, this.expressApp);
|
|
3002
|
-
// Listen on the specified port
|
|
3003
2457
|
if (hasParameter('ingress')) {
|
|
3004
2458
|
this.httpsServer.listen(port, '0.0.0.0', () => {
|
|
3005
2459
|
this.log.info(`The frontend https server is listening on ${UNDERLINE}https://0.0.0.0:${port}${UNDERLINEOFF}${rs}`);
|
|
@@ -3013,7 +2467,6 @@ export class Matterbridge extends EventEmitter {
|
|
|
3013
2467
|
this.log.info(`The frontend https server is listening on ${UNDERLINE}https://[${this.systemInformation.ipv6Address}]:${port}${UNDERLINEOFF}${rs}`);
|
|
3014
2468
|
});
|
|
3015
2469
|
}
|
|
3016
|
-
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
3017
2470
|
this.httpsServer.on('error', (error) => {
|
|
3018
2471
|
this.log.error(`Frontend https server error listening on ${port}`);
|
|
3019
2472
|
switch (error.code) {
|
|
@@ -3030,13 +2483,12 @@ export class Matterbridge extends EventEmitter {
|
|
|
3030
2483
|
}
|
|
3031
2484
|
if (initializeError)
|
|
3032
2485
|
return;
|
|
3033
|
-
// Createe a WebSocket server and attach it to the http or https server
|
|
3034
2486
|
const wssPort = port;
|
|
3035
2487
|
const wssHost = hasParameter('ssl') ? `wss://${this.systemInformation.ipv4Address}:${wssPort}` : `ws://${this.systemInformation.ipv4Address}:${wssPort}`;
|
|
3036
2488
|
this.webSocketServer = new WebSocketServer(hasParameter('ssl') ? { server: this.httpsServer } : { server: this.httpServer });
|
|
3037
2489
|
this.webSocketServer.on('connection', (ws, request) => {
|
|
3038
2490
|
const clientIp = request.socket.remoteAddress;
|
|
3039
|
-
AnsiLogger.setGlobalCallback(this.wssSendMessage.bind(this), "debug"
|
|
2491
|
+
AnsiLogger.setGlobalCallback(this.wssSendMessage.bind(this), "debug");
|
|
3040
2492
|
this.log.info(`WebSocketServer client "${clientIp}" connected to Matterbridge`);
|
|
3041
2493
|
ws.on('message', (message) => {
|
|
3042
2494
|
this.log.debug(`WebSocket client message: ${message}`);
|
|
@@ -3069,7 +2521,6 @@ export class Matterbridge extends EventEmitter {
|
|
|
3069
2521
|
this.webSocketServer.on('error', (ws, error) => {
|
|
3070
2522
|
this.log.error(`WebSocketServer error: ${error}`);
|
|
3071
2523
|
});
|
|
3072
|
-
// Endpoint to validate login code
|
|
3073
2524
|
this.expressApp.post('/api/login', express.json(), async (req, res) => {
|
|
3074
2525
|
const { password } = req.body;
|
|
3075
2526
|
this.log.debug('The frontend sent /api/login', password);
|
|
@@ -3088,14 +2539,12 @@ export class Matterbridge extends EventEmitter {
|
|
|
3088
2539
|
this.log.warn('/api/login error wrong password');
|
|
3089
2540
|
res.json({ valid: false });
|
|
3090
2541
|
}
|
|
3091
|
-
// eslint-disable-next-line @typescript-eslint/no-unused-vars
|
|
3092
2542
|
}
|
|
3093
2543
|
catch (error) {
|
|
3094
2544
|
this.log.error('/api/login error getting password');
|
|
3095
2545
|
res.json({ valid: false });
|
|
3096
2546
|
}
|
|
3097
2547
|
});
|
|
3098
|
-
// Endpoint to provide settings
|
|
3099
2548
|
this.expressApp.get('/api/settings', express.json(), async (req, res) => {
|
|
3100
2549
|
this.log.debug('The frontend sent /api/settings');
|
|
3101
2550
|
this.matterbridgeInformation.bridgeMode = this.bridgeMode;
|
|
@@ -3116,17 +2565,13 @@ export class Matterbridge extends EventEmitter {
|
|
|
3116
2565
|
this.matterbridgeInformation.matterbridgeSessionInformations = Array.from(this.matterbridgeSessionInformations.values());
|
|
3117
2566
|
this.matterbridgeInformation.profile = this.profile;
|
|
3118
2567
|
const response = { systemInformation: this.systemInformation, matterbridgeInformation: this.matterbridgeInformation };
|
|
3119
|
-
// this.log.debug('Response:', debugStringify(response));
|
|
3120
2568
|
res.json(response);
|
|
3121
2569
|
});
|
|
3122
|
-
// Endpoint to provide plugins
|
|
3123
2570
|
this.expressApp.get('/api/plugins', async (req, res) => {
|
|
3124
2571
|
this.log.debug('The frontend sent /api/plugins');
|
|
3125
2572
|
const response = await this.getBaseRegisteredPlugins();
|
|
3126
|
-
// this.log.debug('Response:', debugStringify(response));
|
|
3127
2573
|
res.json(response);
|
|
3128
2574
|
});
|
|
3129
|
-
// Endpoint to provide devices
|
|
3130
2575
|
this.expressApp.get('/api/devices', (req, res) => {
|
|
3131
2576
|
this.log.debug('The frontend sent /api/devices');
|
|
3132
2577
|
const devices = [];
|
|
@@ -3159,10 +2604,8 @@ export class Matterbridge extends EventEmitter {
|
|
|
3159
2604
|
cluster: cluster,
|
|
3160
2605
|
});
|
|
3161
2606
|
});
|
|
3162
|
-
// this.log.debug('Response:', debugStringify(data));
|
|
3163
2607
|
res.json(devices);
|
|
3164
2608
|
});
|
|
3165
|
-
// Endpoint to provide the cluster servers of the devices
|
|
3166
2609
|
this.expressApp.get('/api/devices_clusters/:selectedPluginName/:selectedDeviceEndpoint', (req, res) => {
|
|
3167
2610
|
const selectedPluginName = req.params.selectedPluginName;
|
|
3168
2611
|
const selectedDeviceEndpoint = parseInt(req.params.selectedDeviceEndpoint, 10);
|
|
@@ -3182,7 +2625,6 @@ export class Matterbridge extends EventEmitter {
|
|
|
3182
2625
|
Object.entries(clusterServer.attributes).forEach(([key, value]) => {
|
|
3183
2626
|
if (clusterServer.name === 'EveHistory')
|
|
3184
2627
|
return;
|
|
3185
|
-
// this.log.debug(`***--clusterServer: ${clusterServer.name}(${clusterServer.id}) attribute:${key}(${value.id}) ${value.isFixed} ${value.isWritable} ${value.isWritable}`);
|
|
3186
2628
|
let attributeValue;
|
|
3187
2629
|
try {
|
|
3188
2630
|
if (typeof value.getLocal() === 'object')
|
|
@@ -3193,7 +2635,6 @@ export class Matterbridge extends EventEmitter {
|
|
|
3193
2635
|
catch (error) {
|
|
3194
2636
|
attributeValue = 'Fabric-Scoped';
|
|
3195
2637
|
this.log.debug(`GetLocal value ${error} in clusterServer: ${clusterServer.name}(${clusterServer.id}) attribute: ${key}(${value.id})`);
|
|
3196
|
-
// console.log(error);
|
|
3197
2638
|
}
|
|
3198
2639
|
data.push({
|
|
3199
2640
|
endpoint: device.number ? device.number.toString() : '...',
|
|
@@ -3206,14 +2647,12 @@ export class Matterbridge extends EventEmitter {
|
|
|
3206
2647
|
});
|
|
3207
2648
|
});
|
|
3208
2649
|
device.getChildEndpoints().forEach((childEndpoint) => {
|
|
3209
|
-
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
3210
2650
|
const name = this.edge ? childEndpoint.endpoint?.id : childEndpoint.uniqueStorageKey;
|
|
3211
2651
|
const clusterServers = childEndpoint.getAllClusterServers();
|
|
3212
2652
|
clusterServers.forEach((clusterServer) => {
|
|
3213
2653
|
Object.entries(clusterServer.attributes).forEach(([key, value]) => {
|
|
3214
2654
|
if (clusterServer.name === 'EveHistory')
|
|
3215
2655
|
return;
|
|
3216
|
-
// this.log.debug(`***--clusterServer: ${clusterServer.name}(${clusterServer.id}) attribute:${key}(${value.id}) ${value.isFixed} ${value.isWritable} ${value.isWritable}`);
|
|
3217
2656
|
let attributeValue;
|
|
3218
2657
|
try {
|
|
3219
2658
|
if (typeof value.getLocal() === 'object')
|
|
@@ -3224,7 +2663,6 @@ export class Matterbridge extends EventEmitter {
|
|
|
3224
2663
|
catch (error) {
|
|
3225
2664
|
attributeValue = 'Unavailable';
|
|
3226
2665
|
this.log.debug(`GetLocal error ${error} in clusterServer: ${clusterServer.name}(${clusterServer.id}) attribute: ${key}(${value.id})`);
|
|
3227
|
-
// console.log(error);
|
|
3228
2666
|
}
|
|
3229
2667
|
data.push({
|
|
3230
2668
|
endpoint: (childEndpoint.number ? childEndpoint.number.toString() : '...') + (name ? ' (' + name + ')' : ''),
|
|
@@ -3241,7 +2679,6 @@ export class Matterbridge extends EventEmitter {
|
|
|
3241
2679
|
});
|
|
3242
2680
|
res.json(data);
|
|
3243
2681
|
});
|
|
3244
|
-
// Endpoint to view the log
|
|
3245
2682
|
this.expressApp.get('/api/view-log', async (req, res) => {
|
|
3246
2683
|
this.log.debug('The frontend sent /api/log');
|
|
3247
2684
|
try {
|
|
@@ -3254,12 +2691,10 @@ export class Matterbridge extends EventEmitter {
|
|
|
3254
2691
|
res.status(500).send('Error reading log file');
|
|
3255
2692
|
}
|
|
3256
2693
|
});
|
|
3257
|
-
// Endpoint to download the matterbridge log
|
|
3258
2694
|
this.expressApp.get('/api/download-mblog', async (req, res) => {
|
|
3259
2695
|
this.log.debug('The frontend sent /api/download-mblog');
|
|
3260
2696
|
try {
|
|
3261
2697
|
await fs.access(path.join(this.matterbridgeDirectory, this.matterbrideLoggerFile), fs.constants.F_OK);
|
|
3262
|
-
// eslint-disable-next-line @typescript-eslint/no-unused-vars
|
|
3263
2698
|
}
|
|
3264
2699
|
catch (error) {
|
|
3265
2700
|
fs.appendFile(path.join(this.matterbridgeDirectory, this.matterbrideLoggerFile), 'Enable the log on file in the settings to enable the file logger');
|
|
@@ -3271,12 +2706,10 @@ export class Matterbridge extends EventEmitter {
|
|
|
3271
2706
|
}
|
|
3272
2707
|
});
|
|
3273
2708
|
});
|
|
3274
|
-
// Endpoint to download the matter log
|
|
3275
2709
|
this.expressApp.get('/api/download-mjlog', async (req, res) => {
|
|
3276
2710
|
this.log.debug('The frontend sent /api/download-mjlog');
|
|
3277
2711
|
try {
|
|
3278
2712
|
await fs.access(path.join(this.matterbridgeDirectory, this.matterLoggerFile), fs.constants.F_OK);
|
|
3279
|
-
// eslint-disable-next-line @typescript-eslint/no-unused-vars
|
|
3280
2713
|
}
|
|
3281
2714
|
catch (error) {
|
|
3282
2715
|
fs.appendFile(path.join(this.matterbridgeDirectory, this.matterLoggerFile), 'Enable the log on file in the settings to enable the file logger');
|
|
@@ -3288,7 +2721,6 @@ export class Matterbridge extends EventEmitter {
|
|
|
3288
2721
|
}
|
|
3289
2722
|
});
|
|
3290
2723
|
});
|
|
3291
|
-
// Endpoint to download the matter storage file
|
|
3292
2724
|
this.expressApp.get('/api/download-mjstorage', (req, res) => {
|
|
3293
2725
|
this.log.debug('The frontend sent /api/download-mjstorage');
|
|
3294
2726
|
res.download(path.join(this.matterbridgeDirectory, this.matterStorageName), 'matterbridge.json', (error) => {
|
|
@@ -3298,7 +2730,6 @@ export class Matterbridge extends EventEmitter {
|
|
|
3298
2730
|
}
|
|
3299
2731
|
});
|
|
3300
2732
|
});
|
|
3301
|
-
// Endpoint to download the matterbridge storage directory
|
|
3302
2733
|
this.expressApp.get('/api/download-mbstorage', async (req, res) => {
|
|
3303
2734
|
this.log.debug('The frontend sent /api/download-mbstorage');
|
|
3304
2735
|
await createZip(path.join(os.tmpdir(), `matterbridge.${this.nodeStorageName}.zip`), path.join(this.matterbridgeDirectory, this.nodeStorageName));
|
|
@@ -3309,7 +2740,6 @@ export class Matterbridge extends EventEmitter {
|
|
|
3309
2740
|
}
|
|
3310
2741
|
});
|
|
3311
2742
|
});
|
|
3312
|
-
// Endpoint to download the matterbridge plugin directory
|
|
3313
2743
|
this.expressApp.get('/api/download-pluginstorage', async (req, res) => {
|
|
3314
2744
|
this.log.debug('The frontend sent /api/download-pluginstorage');
|
|
3315
2745
|
await createZip(path.join(os.tmpdir(), `matterbridge.pluginstorage.zip`), this.matterbridgePluginDirectory);
|
|
@@ -3320,11 +2750,9 @@ export class Matterbridge extends EventEmitter {
|
|
|
3320
2750
|
}
|
|
3321
2751
|
});
|
|
3322
2752
|
});
|
|
3323
|
-
// Endpoint to download the matterbridge plugin config files
|
|
3324
2753
|
this.expressApp.get('/api/download-pluginconfig', async (req, res) => {
|
|
3325
2754
|
this.log.debug('The frontend sent /api/download-pluginconfig');
|
|
3326
2755
|
await createZip(path.join(os.tmpdir(), `matterbridge.pluginconfig.zip`), path.relative(process.cwd(), path.join(this.matterbridgeDirectory, '*.config.json')));
|
|
3327
|
-
// await createZip(path.join(os.tmpdir(), `matterbridge.pluginconfig.zip`), path.relative(process.cwd(), path.join(this.matterbridgeDirectory, 'certs', '*.*')), path.relative(process.cwd(), path.join(this.matterbridgeDirectory, '*.config.json')));
|
|
3328
2756
|
res.download(path.join(os.tmpdir(), `matterbridge.pluginconfig.zip`), `matterbridge.pluginconfig.zip`, (error) => {
|
|
3329
2757
|
if (error) {
|
|
3330
2758
|
this.log.error(`Error downloading file matterbridge.pluginstorage.zip: ${error instanceof Error ? error.message : error}`);
|
|
@@ -3332,7 +2760,6 @@ export class Matterbridge extends EventEmitter {
|
|
|
3332
2760
|
}
|
|
3333
2761
|
});
|
|
3334
2762
|
});
|
|
3335
|
-
// Endpoint to download the matterbridge plugin config files
|
|
3336
2763
|
this.expressApp.get('/api/download-backup', async (req, res) => {
|
|
3337
2764
|
this.log.debug('The frontend sent /api/download-backup');
|
|
3338
2765
|
res.download(path.join(os.tmpdir(), `matterbridge.backup.zip`), `matterbridge.backup.zip`, (error) => {
|
|
@@ -3342,7 +2769,6 @@ export class Matterbridge extends EventEmitter {
|
|
|
3342
2769
|
}
|
|
3343
2770
|
});
|
|
3344
2771
|
});
|
|
3345
|
-
// Endpoint to receive commands
|
|
3346
2772
|
this.expressApp.post('/api/command/:command/:param', express.json(), async (req, res) => {
|
|
3347
2773
|
const command = req.params.command;
|
|
3348
2774
|
let param = req.params.param;
|
|
@@ -3352,15 +2778,13 @@ export class Matterbridge extends EventEmitter {
|
|
|
3352
2778
|
return;
|
|
3353
2779
|
}
|
|
3354
2780
|
this.log.debug(`Received frontend command: ${command}:${param}`);
|
|
3355
|
-
// Handle the command setpassword from Settings
|
|
3356
2781
|
if (command === 'setpassword') {
|
|
3357
|
-
const password = param.slice(1, -1);
|
|
2782
|
+
const password = param.slice(1, -1);
|
|
3358
2783
|
this.log.debug('setpassword', param, password);
|
|
3359
2784
|
await this.nodeContext?.set('password', password);
|
|
3360
2785
|
res.json({ message: 'Command received' });
|
|
3361
2786
|
return;
|
|
3362
2787
|
}
|
|
3363
|
-
// Handle the command setbridgemode from Settings
|
|
3364
2788
|
if (command === 'setbridgemode') {
|
|
3365
2789
|
this.log.debug(`setbridgemode: ${param}`);
|
|
3366
2790
|
this.wssSendRestartRequired();
|
|
@@ -3368,7 +2792,6 @@ export class Matterbridge extends EventEmitter {
|
|
|
3368
2792
|
res.json({ message: 'Command received' });
|
|
3369
2793
|
return;
|
|
3370
2794
|
}
|
|
3371
|
-
// Handle the command backup from Settings
|
|
3372
2795
|
if (command === 'backup') {
|
|
3373
2796
|
this.log.notice(`Prepairing the backup...`);
|
|
3374
2797
|
await createZip(path.join(os.tmpdir(), `matterbridge.backup.zip`), path.join(this.matterbridgeDirectory), path.join(this.matterbridgePluginDirectory));
|
|
@@ -3376,26 +2799,25 @@ export class Matterbridge extends EventEmitter {
|
|
|
3376
2799
|
res.json({ message: 'Command received' });
|
|
3377
2800
|
return;
|
|
3378
2801
|
}
|
|
3379
|
-
// Handle the command setmbloglevel from Settings
|
|
3380
2802
|
if (command === 'setmbloglevel') {
|
|
3381
2803
|
this.log.debug('Matterbridge log level:', param);
|
|
3382
2804
|
if (param === 'Debug') {
|
|
3383
|
-
this.log.logLevel = "debug"
|
|
2805
|
+
this.log.logLevel = "debug";
|
|
3384
2806
|
}
|
|
3385
2807
|
else if (param === 'Info') {
|
|
3386
|
-
this.log.logLevel = "info"
|
|
2808
|
+
this.log.logLevel = "info";
|
|
3387
2809
|
}
|
|
3388
2810
|
else if (param === 'Notice') {
|
|
3389
|
-
this.log.logLevel = "notice"
|
|
2811
|
+
this.log.logLevel = "notice";
|
|
3390
2812
|
}
|
|
3391
2813
|
else if (param === 'Warn') {
|
|
3392
|
-
this.log.logLevel = "warn"
|
|
2814
|
+
this.log.logLevel = "warn";
|
|
3393
2815
|
}
|
|
3394
2816
|
else if (param === 'Error') {
|
|
3395
|
-
this.log.logLevel = "error"
|
|
2817
|
+
this.log.logLevel = "error";
|
|
3396
2818
|
}
|
|
3397
2819
|
else if (param === 'Fatal') {
|
|
3398
|
-
this.log.logLevel = "fatal"
|
|
2820
|
+
this.log.logLevel = "fatal";
|
|
3399
2821
|
}
|
|
3400
2822
|
await this.nodeContext?.set('matterbridgeLogLevel', this.log.logLevel);
|
|
3401
2823
|
MatterbridgeDevice.logLevel = this.log.logLevel;
|
|
@@ -3403,13 +2825,12 @@ export class Matterbridge extends EventEmitter {
|
|
|
3403
2825
|
for (const plugin of this.plugins) {
|
|
3404
2826
|
if (!plugin.platform || !plugin.platform.config)
|
|
3405
2827
|
continue;
|
|
3406
|
-
plugin.platform.log.logLevel = plugin.platform.config.debug ? "debug"
|
|
3407
|
-
await plugin.platform.onChangeLoggerLevel(plugin.platform.config.debug ? "debug"
|
|
2828
|
+
plugin.platform.log.logLevel = plugin.platform.config.debug ? "debug" : this.log.logLevel;
|
|
2829
|
+
await plugin.platform.onChangeLoggerLevel(plugin.platform.config.debug ? "debug" : this.log.logLevel);
|
|
3408
2830
|
}
|
|
3409
2831
|
res.json({ message: 'Command received' });
|
|
3410
2832
|
return;
|
|
3411
2833
|
}
|
|
3412
|
-
// Handle the command setmbloglevel from Settings
|
|
3413
2834
|
if (command === 'setmjloglevel') {
|
|
3414
2835
|
this.log.debug('Matter.js log level:', param);
|
|
3415
2836
|
if (param === 'Debug') {
|
|
@@ -3434,34 +2855,30 @@ export class Matterbridge extends EventEmitter {
|
|
|
3434
2855
|
res.json({ message: 'Command received' });
|
|
3435
2856
|
return;
|
|
3436
2857
|
}
|
|
3437
|
-
// Handle the command setmdnsinterface from Settings
|
|
3438
2858
|
if (command === 'setmdnsinterface') {
|
|
3439
|
-
param = param.slice(1, -1);
|
|
2859
|
+
param = param.slice(1, -1);
|
|
3440
2860
|
this.matterbridgeInformation.mattermdnsinterface = param;
|
|
3441
2861
|
this.log.debug('Matter.js mdns interface:', param === '' ? 'All interfaces' : param);
|
|
3442
2862
|
await this.nodeContext?.set('mattermdnsinterface', param);
|
|
3443
2863
|
res.json({ message: 'Command received' });
|
|
3444
2864
|
return;
|
|
3445
2865
|
}
|
|
3446
|
-
// Handle the command setipv4address from Settings
|
|
3447
2866
|
if (command === 'setipv4address') {
|
|
3448
|
-
param = param.slice(1, -1);
|
|
2867
|
+
param = param.slice(1, -1);
|
|
3449
2868
|
this.matterbridgeInformation.matteripv4address = param;
|
|
3450
2869
|
this.log.debug('Matter.js ipv4 address:', param === '' ? 'All ipv4 addresses' : param);
|
|
3451
2870
|
await this.nodeContext?.set('matteripv4address', param);
|
|
3452
2871
|
res.json({ message: 'Command received' });
|
|
3453
2872
|
return;
|
|
3454
2873
|
}
|
|
3455
|
-
// Handle the command setipv6address from Settings
|
|
3456
2874
|
if (command === 'setipv6address') {
|
|
3457
|
-
param = param.slice(1, -1);
|
|
2875
|
+
param = param.slice(1, -1);
|
|
3458
2876
|
this.matterbridgeInformation.matteripv6address = param;
|
|
3459
2877
|
this.log.debug('Matter.js ipv6 address:', param === '' ? 'All ipv6 addresses' : param);
|
|
3460
2878
|
await this.nodeContext?.set('matteripv6address', param);
|
|
3461
2879
|
res.json({ message: 'Command received' });
|
|
3462
2880
|
return;
|
|
3463
2881
|
}
|
|
3464
|
-
// Handle the command setmatterport from Settings
|
|
3465
2882
|
if (command === 'setmatterport') {
|
|
3466
2883
|
const port = Math.min(Math.max(parseInt(param), 5540), 5560);
|
|
3467
2884
|
this.matterbridgeInformation.matterPort = port;
|
|
@@ -3470,7 +2887,6 @@ export class Matterbridge extends EventEmitter {
|
|
|
3470
2887
|
res.json({ message: 'Command received' });
|
|
3471
2888
|
return;
|
|
3472
2889
|
}
|
|
3473
|
-
// Handle the command setmatterdiscriminator from Settings
|
|
3474
2890
|
if (command === 'setmatterdiscriminator') {
|
|
3475
2891
|
const discriminator = Math.min(Math.max(parseInt(param), 1000), 4095);
|
|
3476
2892
|
this.matterbridgeInformation.matterDiscriminator = discriminator;
|
|
@@ -3479,7 +2895,6 @@ export class Matterbridge extends EventEmitter {
|
|
|
3479
2895
|
res.json({ message: 'Command received' });
|
|
3480
2896
|
return;
|
|
3481
2897
|
}
|
|
3482
|
-
// Handle the command setmatterpasscode from Settings
|
|
3483
2898
|
if (command === 'setmatterpasscode') {
|
|
3484
2899
|
const passcode = Math.min(Math.max(parseInt(param), 10000000), 90000000);
|
|
3485
2900
|
this.matterbridgeInformation.matterPasscode = passcode;
|
|
@@ -3488,20 +2903,17 @@ export class Matterbridge extends EventEmitter {
|
|
|
3488
2903
|
res.json({ message: 'Command received' });
|
|
3489
2904
|
return;
|
|
3490
2905
|
}
|
|
3491
|
-
// Handle the command setmbloglevel from Settings
|
|
3492
2906
|
if (command === 'setmblogfile') {
|
|
3493
2907
|
this.log.debug('Matterbridge file log:', param);
|
|
3494
2908
|
this.matterbridgeInformation.fileLogger = param === 'true';
|
|
3495
2909
|
await this.nodeContext?.set('matterbridgeFileLog', param === 'true');
|
|
3496
|
-
// Create the file logger for matterbridge
|
|
3497
2910
|
if (param === 'true')
|
|
3498
|
-
AnsiLogger.setGlobalLogfile(path.join(this.matterbridgeDirectory, this.matterbrideLoggerFile), "debug"
|
|
2911
|
+
AnsiLogger.setGlobalLogfile(path.join(this.matterbridgeDirectory, this.matterbrideLoggerFile), "debug", true);
|
|
3499
2912
|
else
|
|
3500
2913
|
AnsiLogger.setGlobalLogfile(undefined);
|
|
3501
2914
|
res.json({ message: 'Command received' });
|
|
3502
2915
|
return;
|
|
3503
2916
|
}
|
|
3504
|
-
// Handle the command setmbloglevel from Settings
|
|
3505
2917
|
if (command === 'setmjlogfile') {
|
|
3506
2918
|
this.log.debug('Matter file log:', param);
|
|
3507
2919
|
this.matterbridgeInformation.matterFileLogger = param === 'true';
|
|
@@ -3528,43 +2940,36 @@ export class Matterbridge extends EventEmitter {
|
|
|
3528
2940
|
res.json({ message: 'Command received' });
|
|
3529
2941
|
return;
|
|
3530
2942
|
}
|
|
3531
|
-
// Handle the command unregister from Settings
|
|
3532
2943
|
if (command === 'unregister') {
|
|
3533
2944
|
await this.unregisterAndShutdownProcess();
|
|
3534
2945
|
res.json({ message: 'Command received' });
|
|
3535
2946
|
return;
|
|
3536
2947
|
}
|
|
3537
|
-
// Handle the command reset from Settings
|
|
3538
2948
|
if (command === 'reset') {
|
|
3539
2949
|
await this.shutdownProcessAndReset();
|
|
3540
2950
|
res.json({ message: 'Command received' });
|
|
3541
2951
|
return;
|
|
3542
2952
|
}
|
|
3543
|
-
// Handle the command factoryreset from Settings
|
|
3544
2953
|
if (command === 'factoryreset') {
|
|
3545
2954
|
await this.shutdownProcessAndFactoryReset();
|
|
3546
2955
|
res.json({ message: 'Command received' });
|
|
3547
2956
|
return;
|
|
3548
2957
|
}
|
|
3549
|
-
// Handle the command shutdown from Header
|
|
3550
2958
|
if (command === 'shutdown') {
|
|
3551
2959
|
await this.shutdownProcess();
|
|
3552
2960
|
res.json({ message: 'Command received' });
|
|
3553
2961
|
return;
|
|
3554
2962
|
}
|
|
3555
|
-
// Handle the command restart from Header
|
|
3556
2963
|
if (command === 'restart') {
|
|
3557
2964
|
await this.restartProcess();
|
|
3558
2965
|
res.json({ message: 'Command received' });
|
|
3559
2966
|
return;
|
|
3560
2967
|
}
|
|
3561
|
-
// Handle the command update from Header
|
|
3562
2968
|
if (command === 'update') {
|
|
3563
2969
|
this.log.info('Updating matterbridge...');
|
|
3564
2970
|
try {
|
|
3565
2971
|
await this.spawnCommand('npm', ['install', '-g', 'matterbridge', '--omit=dev', '--verbose']);
|
|
3566
2972
|
this.log.info('Matterbridge has been updated. Full restart required.');
|
|
3567
|
-
// eslint-disable-next-line @typescript-eslint/no-unused-vars
|
|
3568
2973
|
}
|
|
3569
2974
|
catch (error) {
|
|
3570
2975
|
this.log.error('Error updating matterbridge');
|
|
@@ -3574,11 +2979,9 @@ export class Matterbridge extends EventEmitter {
|
|
|
3574
2979
|
res.json({ message: 'Command received' });
|
|
3575
2980
|
return;
|
|
3576
2981
|
}
|
|
3577
|
-
// Handle the command saveconfig from Home
|
|
3578
2982
|
if (command === 'saveconfig') {
|
|
3579
2983
|
param = param.replace(/\*/g, '\\');
|
|
3580
2984
|
this.log.info(`Saving config for plugin ${plg}${param}${nf}...`);
|
|
3581
|
-
// console.log('Req.body:', JSON.stringify(req.body, null, 2));
|
|
3582
2985
|
if (!this.plugins.has(param)) {
|
|
3583
2986
|
this.log.warn(`Plugin ${plg}${param}${wr} not found in matterbridge`);
|
|
3584
2987
|
}
|
|
@@ -3592,39 +2995,33 @@ export class Matterbridge extends EventEmitter {
|
|
|
3592
2995
|
res.json({ message: 'Command received' });
|
|
3593
2996
|
return;
|
|
3594
2997
|
}
|
|
3595
|
-
// Handle the command installplugin from Home
|
|
3596
2998
|
if (command === 'installplugin') {
|
|
3597
2999
|
param = param.replace(/\*/g, '\\');
|
|
3598
3000
|
this.log.info(`Installing plugin ${plg}${param}${nf}...`);
|
|
3599
3001
|
try {
|
|
3600
3002
|
await this.spawnCommand('npm', ['install', '-g', param, '--omit=dev', '--verbose']);
|
|
3601
3003
|
this.log.info(`Plugin ${plg}${param}${nf} installed. Full restart required.`);
|
|
3602
|
-
// eslint-disable-next-line @typescript-eslint/no-unused-vars
|
|
3603
3004
|
}
|
|
3604
3005
|
catch (error) {
|
|
3605
3006
|
this.log.error(`Error installing plugin ${plg}${param}${er}`);
|
|
3606
3007
|
}
|
|
3607
3008
|
this.wssSendRestartRequired();
|
|
3608
3009
|
param = param.split('@')[0];
|
|
3609
|
-
// Also add the plugin to matterbridge so no return!
|
|
3610
3010
|
if (param === 'matterbridge') {
|
|
3611
|
-
// 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
|
|
3612
3011
|
res.json({ message: 'Command received' });
|
|
3613
3012
|
return;
|
|
3614
3013
|
}
|
|
3615
3014
|
}
|
|
3616
|
-
// Handle the command addplugin from Home
|
|
3617
3015
|
if (command === 'addplugin' || command === 'installplugin') {
|
|
3618
3016
|
param = param.replace(/\*/g, '\\');
|
|
3619
3017
|
const plugin = await this.plugins.add(param);
|
|
3620
3018
|
if (plugin) {
|
|
3621
|
-
this.plugins.load(plugin, true, 'The plugin has been added', true);
|
|
3019
|
+
this.plugins.load(plugin, true, 'The plugin has been added', true);
|
|
3622
3020
|
}
|
|
3623
3021
|
res.json({ message: 'Command received' });
|
|
3624
3022
|
this.wssSendRefreshRequired();
|
|
3625
3023
|
return;
|
|
3626
3024
|
}
|
|
3627
|
-
// Handle the command removeplugin from Home
|
|
3628
3025
|
if (command === 'removeplugin') {
|
|
3629
3026
|
if (!this.plugins.has(param)) {
|
|
3630
3027
|
this.log.warn(`Plugin ${plg}${param}${wr} not found in matterbridge`);
|
|
@@ -3638,7 +3035,6 @@ export class Matterbridge extends EventEmitter {
|
|
|
3638
3035
|
this.wssSendRefreshRequired();
|
|
3639
3036
|
return;
|
|
3640
3037
|
}
|
|
3641
|
-
// Handle the command enableplugin from Home
|
|
3642
3038
|
if (command === 'enableplugin') {
|
|
3643
3039
|
if (!this.plugins.has(param)) {
|
|
3644
3040
|
this.log.warn(`Plugin ${plg}${param}${wr} not found in matterbridge`);
|
|
@@ -3656,14 +3052,13 @@ export class Matterbridge extends EventEmitter {
|
|
|
3656
3052
|
plugin.registeredDevices = undefined;
|
|
3657
3053
|
plugin.addedDevices = undefined;
|
|
3658
3054
|
await this.plugins.enable(param);
|
|
3659
|
-
this.plugins.load(plugin, true, 'The plugin has been enabled', true);
|
|
3055
|
+
this.plugins.load(plugin, true, 'The plugin has been enabled', true);
|
|
3660
3056
|
}
|
|
3661
3057
|
}
|
|
3662
3058
|
res.json({ message: 'Command received' });
|
|
3663
3059
|
this.wssSendRefreshRequired();
|
|
3664
3060
|
return;
|
|
3665
3061
|
}
|
|
3666
|
-
// Handle the command disableplugin from Home
|
|
3667
3062
|
if (command === 'disableplugin') {
|
|
3668
3063
|
if (!this.plugins.has(param)) {
|
|
3669
3064
|
this.log.warn(`Plugin ${plg}${param}${wr} not found in matterbridge`);
|
|
@@ -3680,7 +3075,6 @@ export class Matterbridge extends EventEmitter {
|
|
|
3680
3075
|
return;
|
|
3681
3076
|
}
|
|
3682
3077
|
});
|
|
3683
|
-
// Fallback for routing (must be the last route)
|
|
3684
3078
|
this.expressApp.get('*', (req, res) => {
|
|
3685
3079
|
this.log.debug('The frontend sent:', req.url);
|
|
3686
3080
|
this.log.debug('Response send file:', path.join(this.rootDirectory, 'frontend/build/index.html'));
|
|
@@ -3688,11 +3082,6 @@ export class Matterbridge extends EventEmitter {
|
|
|
3688
3082
|
});
|
|
3689
3083
|
this.log.debug(`Frontend initialized on port ${YELLOW}${port}${db} static ${UNDERLINE}${path.join(this.rootDirectory, 'frontend/build')}${UNDERLINEOFF}${rs}`);
|
|
3690
3084
|
}
|
|
3691
|
-
/**
|
|
3692
|
-
* Retrieves the cluster text description from a given device.
|
|
3693
|
-
* @param {MatterbridgeDevice} device - The MatterbridgeDevice object.
|
|
3694
|
-
* @returns {string} The attributes description of the cluster servers in the device.
|
|
3695
|
-
*/
|
|
3696
3085
|
getClusterTextFromDevice(device) {
|
|
3697
3086
|
const stringifyUserLabel = (endpoint) => {
|
|
3698
3087
|
const labelList = endpoint.getClusterServer(UserLabelCluster)?.attributes.labelList.getLocal();
|
|
@@ -3715,11 +3104,9 @@ export class Matterbridge extends EventEmitter {
|
|
|
3715
3104
|
return '';
|
|
3716
3105
|
};
|
|
3717
3106
|
let attributes = '';
|
|
3718
|
-
// this.log.debug(`***getClusterTextFromDevice: ${device.deviceName} (${device.name})`);
|
|
3719
3107
|
const clusterServers = device.getAllClusterServers();
|
|
3720
3108
|
clusterServers.forEach((clusterServer) => {
|
|
3721
3109
|
try {
|
|
3722
|
-
// this.log.debug(`**--clusterServer: ${clusterServer.id} (${clusterServer.name})`);
|
|
3723
3110
|
if (clusterServer.name === 'OnOff')
|
|
3724
3111
|
attributes += `OnOff: ${clusterServer.attributes.onOff.getLocal()} `;
|
|
3725
3112
|
if (clusterServer.name === 'Switch')
|
|
@@ -3770,30 +3157,18 @@ export class Matterbridge extends EventEmitter {
|
|
|
3770
3157
|
attributes += `${stringifyFixedLabel(device)} `;
|
|
3771
3158
|
if (clusterServer.name === 'UserLabel')
|
|
3772
3159
|
attributes += `${stringifyUserLabel(device)} `;
|
|
3773
|
-
// this.log.debug(`*--clusterServer: ${clusterServer.id} (${clusterServer.name})`);
|
|
3774
3160
|
}
|
|
3775
3161
|
catch (error) {
|
|
3776
3162
|
this.log.error(`getClusterTextFromDevice with ${clusterServer.name} error: ${error}`);
|
|
3777
3163
|
}
|
|
3778
3164
|
});
|
|
3779
|
-
// this.log.debug(`*getClusterTextFromDevice: ${device.deviceName} (${device.name})`);
|
|
3780
3165
|
return attributes;
|
|
3781
3166
|
}
|
|
3782
|
-
/**
|
|
3783
|
-
* Initializes the Matterbridge instance as extension for zigbee2mqtt.
|
|
3784
|
-
* @deprecated This method is deprecated and will be removed in a future version.
|
|
3785
|
-
*
|
|
3786
|
-
* @returns A Promise that resolves when the initialization is complete.
|
|
3787
|
-
*/
|
|
3788
3167
|
async startExtension(dataPath, extensionVersion, port = 5540) {
|
|
3789
|
-
// Set the bridge mode
|
|
3790
3168
|
this.bridgeMode = 'bridge';
|
|
3791
|
-
// Set the first port to use
|
|
3792
3169
|
this.port = port;
|
|
3793
|
-
|
|
3794
|
-
this.log = new AnsiLogger({ logName: 'Matterbridge', logTimestampFormat: 4 /* TimestampFormat.TIME_MILLIS */, logLevel: "info" /* LogLevel.INFO */ });
|
|
3170
|
+
this.log = new AnsiLogger({ logName: 'Matterbridge', logTimestampFormat: 4, logLevel: "info" });
|
|
3795
3171
|
this.log.debug('Matterbridge extension is starting...');
|
|
3796
|
-
// Initialize NodeStorage
|
|
3797
3172
|
this.matterbridgeDirectory = dataPath;
|
|
3798
3173
|
this.log.debug('Creating node storage manager dir: ' + path.join(this.matterbridgeDirectory, 'node_storage'));
|
|
3799
3174
|
this.nodeStorage = new NodeStorageManager({ dir: path.join(this.matterbridgeDirectory, 'node_storage'), logging: false });
|
|
@@ -3812,13 +3187,10 @@ export class Matterbridge extends EventEmitter {
|
|
|
3812
3187
|
};
|
|
3813
3188
|
this.plugins.set(plugin);
|
|
3814
3189
|
this.plugins.saveToStorage();
|
|
3815
|
-
// Log system info and create .matterbridge directory
|
|
3816
3190
|
await this.logNodeAndSystemInfo();
|
|
3817
3191
|
this.matterbridgeDirectory = dataPath;
|
|
3818
|
-
// Set matter.js logger level and format
|
|
3819
3192
|
Logger.defaultLogLevel = MatterLogLevel.INFO;
|
|
3820
3193
|
Logger.format = MatterLogFormat.ANSI;
|
|
3821
|
-
// Start the storage and create matterbridgeContext
|
|
3822
3194
|
await this.startMatterStorage('json', path.join(this.matterbridgeDirectory, this.matterStorageName));
|
|
3823
3195
|
if (!this.storageManager)
|
|
3824
3196
|
return false;
|
|
@@ -3828,7 +3200,7 @@ export class Matterbridge extends EventEmitter {
|
|
|
3828
3200
|
await this.matterbridgeContext.set('softwareVersion', 1);
|
|
3829
3201
|
await this.matterbridgeContext.set('softwareVersionString', this.matterbridgeVersion);
|
|
3830
3202
|
await this.matterbridgeContext.set('hardwareVersion', 1);
|
|
3831
|
-
await this.matterbridgeContext.set('hardwareVersionString', extensionVersion);
|
|
3203
|
+
await this.matterbridgeContext.set('hardwareVersionString', extensionVersion);
|
|
3832
3204
|
this.matterServer = await this.createMatterServer(this.storageManager);
|
|
3833
3205
|
this.log.debug(`Creating commissioning server for ${plg}Matterbridge${db}`);
|
|
3834
3206
|
this.commissioningServer = await this.createCommisioningServer(this.matterbridgeContext, 'Matterbridge');
|
|
@@ -3841,7 +3213,6 @@ export class Matterbridge extends EventEmitter {
|
|
|
3841
3213
|
await this.startMatterServer();
|
|
3842
3214
|
this.log.info('Matter server started');
|
|
3843
3215
|
await this.showCommissioningQRCode(this.commissioningServer, this.matterbridgeContext, this.nodeContext, 'Matterbridge');
|
|
3844
|
-
// Set reachability to true and trigger event after 60 seconds
|
|
3845
3216
|
setTimeout(() => {
|
|
3846
3217
|
this.log.info(`Setting reachability to true for ${plg}Matterbridge${db}`);
|
|
3847
3218
|
if (this.commissioningServer)
|
|
@@ -3851,31 +3222,14 @@ export class Matterbridge extends EventEmitter {
|
|
|
3851
3222
|
}, 60 * 1000);
|
|
3852
3223
|
return this.commissioningServer.isCommissioned();
|
|
3853
3224
|
}
|
|
3854
|
-
/**
|
|
3855
|
-
* Close the Matterbridge instance as extension for zigbee2mqtt.
|
|
3856
|
-
* @deprecated This method is deprecated and will be removed in a future version.
|
|
3857
|
-
*
|
|
3858
|
-
* @returns A Promise that resolves when the initialization is complete.
|
|
3859
|
-
*/
|
|
3860
3225
|
async stopExtension() {
|
|
3861
|
-
// Closing matter
|
|
3862
3226
|
await this.stopMatterServer();
|
|
3863
|
-
// Clearing the session manager
|
|
3864
|
-
// this.matterbridgeContext?.createContext('SessionManager').clear();
|
|
3865
|
-
// Closing storage
|
|
3866
3227
|
await this.stopMatterStorage();
|
|
3867
3228
|
this.log.info('Matter server stopped');
|
|
3868
3229
|
}
|
|
3869
|
-
/**
|
|
3870
|
-
* Checks if the extension is commissioned.
|
|
3871
|
-
* @deprecated This method is deprecated and will be removed in a future version.
|
|
3872
|
-
*
|
|
3873
|
-
* @returns {boolean} Returns true if the extension is commissioned, false otherwise.
|
|
3874
|
-
*/
|
|
3875
3230
|
isExtensionCommissioned() {
|
|
3876
3231
|
if (!this.commissioningServer)
|
|
3877
3232
|
return false;
|
|
3878
3233
|
return this.commissioningServer.isCommissioned();
|
|
3879
3234
|
}
|
|
3880
3235
|
}
|
|
3881
|
-
//# sourceMappingURL=matterbridge.js.map
|