matterbridge 1.6.0 → 1.6.2
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 +53 -1
- package/README-DEV.md +0 -4
- package/README-NGINX.md +63 -0
- package/README.md +8 -0
- package/dist/cli.d.ts +1 -1
- package/dist/cli.js +18 -8
- package/dist/cli.js.map +1 -1
- package/dist/defaultConfigSchema.d.ts +1 -1
- package/dist/defaultConfigSchema.js +1 -1
- package/dist/deviceManager.d.ts +2 -2
- package/dist/deviceManager.d.ts.map +1 -1
- package/dist/deviceManager.js +2 -2
- package/dist/deviceManager.js.map +1 -1
- package/dist/index.d.ts +10 -10
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +24 -11
- package/dist/index.js.map +1 -1
- package/dist/matter/export.d.ts +5 -0
- package/dist/matter/export.d.ts.map +1 -0
- package/dist/matter/export.js +5 -0
- package/dist/matter/export.js.map +1 -0
- package/dist/matterbridge.d.ts +32 -16
- package/dist/matterbridge.d.ts.map +1 -1
- package/dist/matterbridge.js +254 -115
- package/dist/matterbridge.js.map +1 -1
- package/dist/matterbridgeAccessoryPlatform.d.ts +1 -1
- package/dist/matterbridgeAccessoryPlatform.d.ts.map +1 -1
- package/dist/matterbridgeAccessoryPlatform.js +1 -1
- package/dist/matterbridgeAccessoryPlatform.js.map +1 -1
- package/dist/matterbridgeBehaviors.d.ts +1123 -0
- package/dist/matterbridgeBehaviors.d.ts.map +1 -0
- package/dist/matterbridgeBehaviors.js +281 -0
- package/dist/matterbridgeBehaviors.js.map +1 -0
- package/dist/matterbridgeDevice.d.ts +2069 -1511
- package/dist/matterbridgeDevice.d.ts.map +1 -1
- package/dist/matterbridgeDevice.js +192 -196
- package/dist/matterbridgeDevice.js.map +1 -1
- package/dist/matterbridgeDeviceTypes.d.ts +58 -0
- package/dist/matterbridgeDeviceTypes.d.ts.map +1 -0
- package/dist/matterbridgeDeviceTypes.js +308 -0
- package/dist/matterbridgeDeviceTypes.js.map +1 -0
- package/dist/matterbridgeDynamicPlatform.d.ts +1 -1
- package/dist/matterbridgeDynamicPlatform.d.ts.map +1 -1
- package/dist/matterbridgeDynamicPlatform.js +1 -1
- package/dist/matterbridgeDynamicPlatform.js.map +1 -1
- package/dist/matterbridgeEdge.d.ts +20 -21
- package/dist/matterbridgeEdge.d.ts.map +1 -1
- package/dist/matterbridgeEdge.js +506 -103
- package/dist/matterbridgeEdge.js.map +1 -1
- package/dist/matterbridgeEndpoint.d.ts +3545 -2336
- package/dist/matterbridgeEndpoint.d.ts.map +1 -1
- package/dist/matterbridgeEndpoint.js +672 -468
- package/dist/matterbridgeEndpoint.js.map +1 -1
- package/dist/matterbridgePlatform.d.ts +5 -4
- package/dist/matterbridgePlatform.d.ts.map +1 -1
- package/dist/matterbridgePlatform.js +11 -3
- package/dist/matterbridgePlatform.js.map +1 -1
- package/dist/matterbridgeTypes.d.ts +7 -8
- package/dist/matterbridgeTypes.d.ts.map +1 -1
- package/dist/matterbridgeTypes.js.map +1 -1
- package/dist/matterbridgeWebsocket.d.ts +1 -1
- package/dist/matterbridgeWebsocket.d.ts.map +1 -1
- package/dist/matterbridgeWebsocket.js +41 -3
- package/dist/matterbridgeWebsocket.js.map +1 -1
- package/dist/pluginManager.d.ts +1 -1
- package/dist/pluginManager.d.ts.map +1 -1
- package/dist/pluginManager.js +17 -8
- package/dist/pluginManager.js.map +1 -1
- package/dist/utils/colorUtils.d.ts +1 -1
- package/dist/utils/colorUtils.js +2 -2
- package/dist/utils/colorUtils.js.map +1 -1
- package/dist/utils/utils.d.ts +42 -1
- package/dist/utils/utils.d.ts.map +1 -1
- package/dist/utils/utils.js +105 -3
- package/dist/utils/utils.js.map +1 -1
- package/frontend/build/asset-manifest.json +62 -6
- package/frontend/build/index.html +1 -1
- package/frontend/build/static/css/main.823e08b6.css +2 -0
- package/frontend/build/static/css/main.823e08b6.css.map +1 -0
- package/frontend/build/static/js/main.a14c87e7.js +115 -0
- package/frontend/build/static/js/{main.045d08f7.js.LICENSE.txt → main.a14c87e7.js.LICENSE.txt} +3 -3
- package/frontend/build/static/js/main.a14c87e7.js.map +1 -0
- package/frontend/build/static/media/roboto-cyrillic-300-normal.1b79538ccd585c259996.woff2 +0 -0
- package/frontend/build/static/media/roboto-cyrillic-300-normal.5f077fd7b977d1715acf.woff +0 -0
- package/frontend/build/static/media/roboto-cyrillic-400-normal.5d2930082227d172f62c.woff +0 -0
- package/frontend/build/static/media/roboto-cyrillic-400-normal.a9e19870cf6c4b973427.woff2 +0 -0
- package/frontend/build/static/media/roboto-cyrillic-500-normal.0ae2428323939af5e1ad.woff2 +0 -0
- package/frontend/build/static/media/roboto-cyrillic-500-normal.dd7bc8a52c6c70c5a3f5.woff +0 -0
- package/frontend/build/static/media/roboto-cyrillic-700-normal.3f6e1548bd5175a8c342.woff +0 -0
- package/frontend/build/static/media/roboto-cyrillic-700-normal.4fdfc29a10e7d4b7c527.woff2 +0 -0
- package/frontend/build/static/media/roboto-cyrillic-ext-300-normal.795dbc8140e3fef82983.woff +0 -0
- package/frontend/build/static/media/roboto-cyrillic-ext-300-normal.80947a31d23c70204b47.woff2 +0 -0
- package/frontend/build/static/media/roboto-cyrillic-ext-400-normal.135d076fa32aa0b4d105.woff +0 -0
- package/frontend/build/static/media/roboto-cyrillic-ext-400-normal.5cec61a21cc20180fbe1.woff2 +0 -0
- package/frontend/build/static/media/roboto-cyrillic-ext-500-normal.6de16332fda843a3dc3d.woff2 +0 -0
- package/frontend/build/static/media/roboto-cyrillic-ext-500-normal.c0a0638f90b31d6454ba.woff +0 -0
- package/frontend/build/static/media/roboto-cyrillic-ext-700-normal.4750292c47fa2bc6ac1a.woff2 +0 -0
- package/frontend/build/static/media/roboto-cyrillic-ext-700-normal.ca247189fc12d00de361.woff +0 -0
- package/frontend/build/static/media/roboto-greek-300-normal.285f3e6261d8eb20417d.woff2 +0 -0
- package/frontend/build/static/media/roboto-greek-300-normal.889beddda1c9bd9f97df.woff +0 -0
- package/frontend/build/static/media/roboto-greek-400-normal.160a791a8e4f46bca3cc.woff +0 -0
- package/frontend/build/static/media/roboto-greek-400-normal.2c32b1315be61477013a.woff2 +0 -0
- package/frontend/build/static/media/roboto-greek-500-normal.60810e07c7b0273013aa.woff +0 -0
- package/frontend/build/static/media/roboto-greek-500-normal.f95e757c5483310f9c11.woff2 +0 -0
- package/frontend/build/static/media/roboto-greek-700-normal.77dd370f2001e184ba0d.woff2 +0 -0
- package/frontend/build/static/media/roboto-greek-700-normal.df87b053fae3d7ad5f7a.woff +0 -0
- package/frontend/build/static/media/roboto-greek-ext-300-normal.b590dbe5c639944366d1.woff +0 -0
- package/frontend/build/static/media/roboto-greek-ext-300-normal.d6049cb54aa6fbe14c42.woff2 +0 -0
- package/frontend/build/static/media/roboto-greek-ext-400-normal.16eb83b4a3b1ea994243.woff +0 -0
- package/frontend/build/static/media/roboto-greek-ext-400-normal.1df4abad55796d11a0c8.woff2 +0 -0
- package/frontend/build/static/media/roboto-greek-ext-500-normal.4a96ba31abcce0f5d52b.woff2 +0 -0
- package/frontend/build/static/media/roboto-greek-ext-500-normal.fd28d9c008bf3af1bed7.woff +0 -0
- package/frontend/build/static/media/roboto-greek-ext-700-normal.2dd6febad11502dec6a6.woff2 +0 -0
- package/frontend/build/static/media/roboto-greek-ext-700-normal.4abdc9fff4507f17d726.woff +0 -0
- package/frontend/build/static/media/roboto-latin-300-normal.b850f1ff581ea232fac9.woff2 +0 -0
- package/frontend/build/static/media/roboto-latin-300-normal.c4bc0593c9954d79cb3a.woff +0 -0
- package/frontend/build/static/media/roboto-latin-400-normal.047a7839f69b209db815.woff +0 -0
- package/frontend/build/static/media/roboto-latin-400-normal.297d48e1b5a10c0831a9.woff2 +0 -0
- package/frontend/build/static/media/roboto-latin-500-normal.68d40d6d01c6f85d24ba.woff +0 -0
- package/frontend/build/static/media/roboto-latin-500-normal.7077203b1982951ecf76.woff2 +0 -0
- package/frontend/build/static/media/roboto-latin-700-normal.4535474e1cf8598695ad.woff2 +0 -0
- package/frontend/build/static/media/roboto-latin-700-normal.9f6a16a7770c87b2042b.woff +0 -0
- package/frontend/build/static/media/roboto-latin-ext-300-normal.14982a9e4857a93b6dce.woff +0 -0
- package/frontend/build/static/media/roboto-latin-ext-300-normal.97cbc447d4a8d41a9543.woff2 +0 -0
- package/frontend/build/static/media/roboto-latin-ext-400-normal.27da5b36b6d3a16f53f4.woff +0 -0
- package/frontend/build/static/media/roboto-latin-ext-400-normal.2eeae187764baf05867d.woff2 +0 -0
- package/frontend/build/static/media/roboto-latin-ext-500-normal.06c30711d588145a4541.woff +0 -0
- package/frontend/build/static/media/roboto-latin-ext-500-normal.9a18d7bb9ff7a6af7b32.woff2 +0 -0
- package/frontend/build/static/media/roboto-latin-ext-700-normal.18841836e391d39e83a8.woff2 +0 -0
- package/frontend/build/static/media/roboto-latin-ext-700-normal.3c5bcdd0e69c4c3ffafe.woff +0 -0
- package/frontend/build/static/media/roboto-vietnamese-300-normal.c96b16e5c05c7b7c3e89.woff2 +0 -0
- package/frontend/build/static/media/roboto-vietnamese-300-normal.f5e7cea32756dfe7af40.woff +0 -0
- package/frontend/build/static/media/roboto-vietnamese-400-normal.0dc97c66f9b542d6fa17.woff +0 -0
- package/frontend/build/static/media/roboto-vietnamese-400-normal.d3f8e26d6c27de8102b6.woff2 +0 -0
- package/frontend/build/static/media/roboto-vietnamese-500-normal.090fabef926bdc0e9b9f.woff2 +0 -0
- package/frontend/build/static/media/roboto-vietnamese-500-normal.23b7b8a2524d2d4b637b.woff +0 -0
- package/frontend/build/static/media/roboto-vietnamese-700-normal.0a79a9fabfc32e33f360.woff2 +0 -0
- package/frontend/build/static/media/roboto-vietnamese-700-normal.35ed0597568ff6f19c16.woff +0 -0
- package/npm-shrinkwrap.json +120 -39
- package/package.json +8 -3
- package/dist/matterbridgeController.d.ts +0 -24
- package/dist/matterbridgeController.d.ts.map +0 -1
- package/dist/matterbridgeController.js +0 -386
- package/dist/matterbridgeController.js.map +0 -1
- package/frontend/build/static/css/main.1cf003ae.css +0 -2
- package/frontend/build/static/css/main.1cf003ae.css.map +0 -1
- package/frontend/build/static/js/main.045d08f7.js +0 -3
- package/frontend/build/static/js/main.045d08f7.js.map +0 -1
package/dist/matterbridge.js
CHANGED
|
@@ -25,32 +25,32 @@ import { fileURLToPath } from 'url';
|
|
|
25
25
|
import { promises as fs } from 'fs';
|
|
26
26
|
import { exec, spawn } from 'child_process';
|
|
27
27
|
import { createServer } from 'http';
|
|
28
|
-
import https from 'https';
|
|
29
28
|
import EventEmitter from 'events';
|
|
30
|
-
import express from 'express';
|
|
31
29
|
import os from 'os';
|
|
32
30
|
import path from 'path';
|
|
31
|
+
import { randomBytes } from 'crypto';
|
|
32
|
+
// Package modules
|
|
33
|
+
import https from 'https';
|
|
34
|
+
import express from 'express';
|
|
33
35
|
import WebSocket, { WebSocketServer } from 'ws';
|
|
34
36
|
// NodeStorage and AnsiLogger modules
|
|
35
37
|
import { NodeStorageManager } from 'node-persist-manager';
|
|
36
|
-
import { AnsiLogger, UNDERLINE, UNDERLINEOFF, YELLOW, db, debugStringify, stringify, BRIGHT, RESET, er, nf, rs, wr, RED, GREEN, zb,
|
|
38
|
+
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';
|
|
37
39
|
// Matterbridge
|
|
38
40
|
import { MatterbridgeDevice } from './matterbridgeDevice.js';
|
|
39
|
-
import {
|
|
41
|
+
import { WS_ID_LOG, WS_ID_REFRESH_NEEDED, WS_ID_RESTART_NEEDED, wsMessageHandler } from './matterbridgeWebsocket.js';
|
|
42
|
+
import { logInterfaces, wait, waiter, createZip, copyDirectory, getParameter, getIntParameter, hasParameter } from './utils/utils.js';
|
|
40
43
|
import { PluginManager } from './pluginManager.js';
|
|
41
44
|
import { DeviceManager } from './deviceManager.js';
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
import {
|
|
45
|
-
import {
|
|
46
|
-
import {
|
|
47
|
-
import {
|
|
48
|
-
|
|
49
|
-
import {
|
|
50
|
-
import {
|
|
51
|
-
import { CryptoNode } from '@project-chip/matter-node.js/crypto';
|
|
52
|
-
import { Specification } from '@project-chip/matter-node.js/model';
|
|
53
|
-
import { WS_ID_LOG, WS_ID_REFRESH_NEEDED, WS_ID_RESTART_NEEDED, wsMessageHandler } from './matterbridgeWebsocket.js';
|
|
45
|
+
import { MatterbridgeEndpoint } from './matterbridgeEndpoint.js';
|
|
46
|
+
// @matter
|
|
47
|
+
import { DeviceTypeId, Logger, LogLevel as MatterLogLevel, LogFormat as MatterLogFormat, VendorId, StorageManager } from '@matter/main';
|
|
48
|
+
import { BasicInformationCluster, BridgedDeviceBasicInformation, BridgedDeviceBasicInformationCluster, FixedLabelCluster, GeneralCommissioning, PowerSourceCluster, SwitchCluster, ThreadNetworkDiagnosticsCluster } from '@matter/main/clusters';
|
|
49
|
+
import { getClusterNameById, ManualPairingCodeCodec, QrCodeSchema } from '@matter/main/types';
|
|
50
|
+
import { StorageBackendDisk, StorageBackendJsonFile } from '@matter/nodejs';
|
|
51
|
+
// @project-chip
|
|
52
|
+
import { CommissioningController, CommissioningServer, MatterServer } from '@project-chip/matter.js';
|
|
53
|
+
import { Aggregator, DeviceTypes, NodeStateInformation } from '@project-chip/matter.js/device';
|
|
54
54
|
// Default colors
|
|
55
55
|
const plg = '\u001B[38;5;33m';
|
|
56
56
|
const dev = '\u001B[38;5;79m';
|
|
@@ -91,9 +91,11 @@ export class Matterbridge extends EventEmitter {
|
|
|
91
91
|
matterbridgeConnected: false,
|
|
92
92
|
bridgeMode: '',
|
|
93
93
|
restartMode: '',
|
|
94
|
+
edge: hasParameter('edge'),
|
|
95
|
+
profile: getParameter('profile'),
|
|
94
96
|
loggerLevel: "info" /* LogLevel.INFO */,
|
|
95
97
|
fileLogger: false,
|
|
96
|
-
matterLoggerLevel:
|
|
98
|
+
matterLoggerLevel: MatterLogLevel.INFO,
|
|
97
99
|
matterFileLogger: false,
|
|
98
100
|
mattermdnsinterface: undefined,
|
|
99
101
|
matteripv4address: undefined,
|
|
@@ -117,6 +119,7 @@ export class Matterbridge extends EventEmitter {
|
|
|
117
119
|
bridgeMode = '';
|
|
118
120
|
restartMode = '';
|
|
119
121
|
profile = getParameter('profile');
|
|
122
|
+
edge = hasParameter('edge');
|
|
120
123
|
log;
|
|
121
124
|
matterbrideLoggerFile = 'matterbridge' + (getParameter('profile') ? '.' + getParameter('profile') : '') + '.log';
|
|
122
125
|
matterLoggerFile = 'matter' + (getParameter('profile') ? '.' + getParameter('profile') : '') + '.log';
|
|
@@ -136,6 +139,8 @@ export class Matterbridge extends EventEmitter {
|
|
|
136
139
|
reachabilityTimeout;
|
|
137
140
|
sigintHandler;
|
|
138
141
|
sigtermHandler;
|
|
142
|
+
exceptionHandler;
|
|
143
|
+
rejectionHandler;
|
|
139
144
|
// Frontend
|
|
140
145
|
expressApp;
|
|
141
146
|
httpServer;
|
|
@@ -155,6 +160,8 @@ export class Matterbridge extends EventEmitter {
|
|
|
155
160
|
matterAggregator;
|
|
156
161
|
commissioningServer;
|
|
157
162
|
commissioningController;
|
|
163
|
+
aggregatorVendorId = VendorId(getIntParameter('vendorId') ?? 0xfff1);
|
|
164
|
+
aggregatorProductId = getIntParameter('productId') ?? 0x8000;
|
|
158
165
|
static instance;
|
|
159
166
|
// We load asyncronously so is private
|
|
160
167
|
constructor() {
|
|
@@ -221,19 +228,54 @@ export class Matterbridge extends EventEmitter {
|
|
|
221
228
|
// Set the matterbridge directory
|
|
222
229
|
this.homeDirectory = getParameter('homedir') ?? os.homedir();
|
|
223
230
|
this.matterbridgeDirectory = path.join(this.homeDirectory, '.matterbridge');
|
|
224
|
-
// Initialize nodeStorage and nodeContext
|
|
225
|
-
// this.log.debug(`Creating node storage manager: ${CYAN}${this.nodeStorageName}${db}`);
|
|
226
|
-
this.nodeStorage = new NodeStorageManager({ dir: path.join(this.matterbridgeDirectory, this.nodeStorageName), writeQueue: false, expiredInterval: undefined, logging: false });
|
|
227
|
-
// this.log.debug('Creating node storage context for matterbridge');
|
|
228
|
-
this.nodeContext = await this.nodeStorage.createStorage('matterbridge');
|
|
229
|
-
// Check if the storage is corrupted and remove it
|
|
230
|
-
// TODO: Check if the storage is corrupted and remove it
|
|
231
231
|
// Create matterbridge logger
|
|
232
|
-
this.log = new AnsiLogger({ logName: 'Matterbridge', logTimestampFormat: 4 /* TimestampFormat.TIME_MILLIS */, logLevel: "info" /* LogLevel.INFO */ });
|
|
233
|
-
//
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
this.
|
|
232
|
+
this.log = new AnsiLogger({ logName: 'Matterbridge', logTimestampFormat: 4 /* TimestampFormat.TIME_MILLIS */, logLevel: hasParameter('debug') ? "debug" /* LogLevel.DEBUG */ : "info" /* LogLevel.INFO */ });
|
|
233
|
+
// Initialize nodeStorage and nodeContext
|
|
234
|
+
try {
|
|
235
|
+
this.log.debug(`Creating node storage manager: ${CYAN}${this.nodeStorageName}${db}`);
|
|
236
|
+
this.nodeStorage = new NodeStorageManager({ dir: path.join(this.matterbridgeDirectory, this.nodeStorageName), writeQueue: false, expiredInterval: undefined, logging: false });
|
|
237
|
+
this.log.debug('Creating node storage context for matterbridge');
|
|
238
|
+
this.nodeContext = await this.nodeStorage.createStorage('matterbridge');
|
|
239
|
+
// TODO: Remove this code when node-persist-manager is updated
|
|
240
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
241
|
+
const keys = (await this.nodeStorage?.storage.keys());
|
|
242
|
+
for (const key of keys) {
|
|
243
|
+
this.log.debug(`Checking node storage manager key: ${CYAN}${key}${db}`);
|
|
244
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
245
|
+
await this.nodeStorage?.storage.get(key);
|
|
246
|
+
}
|
|
247
|
+
const storages = await this.nodeStorage.getStorageNames();
|
|
248
|
+
for (const storage of storages) {
|
|
249
|
+
this.log.debug(`Checking storage: ${CYAN}${storage}${db}`);
|
|
250
|
+
const nodeContext = await this.nodeStorage?.createStorage(storage);
|
|
251
|
+
// TODO: Remove this code when node-persist-manager is updated
|
|
252
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
253
|
+
const keys = (await nodeContext?.storage.keys());
|
|
254
|
+
keys.forEach(async (key) => {
|
|
255
|
+
this.log.debug(`Checking key: ${CYAN}${storage}:${key}${db}`);
|
|
256
|
+
await nodeContext?.get(key);
|
|
257
|
+
});
|
|
258
|
+
}
|
|
259
|
+
// Creating a backup of the node storage since it is not corrupted
|
|
260
|
+
this.log.debug('Creating node storage backup...');
|
|
261
|
+
await copyDirectory(path.join(this.matterbridgeDirectory, this.nodeStorageName), path.join(this.matterbridgeDirectory, this.nodeStorageName + '.backup'));
|
|
262
|
+
this.log.debug('Created node storage backup');
|
|
263
|
+
}
|
|
264
|
+
catch (error) {
|
|
265
|
+
// Restoring the backup of the node storage since it is corrupted
|
|
266
|
+
this.log.error(`Error creating node storage manager and context: ${error instanceof Error ? error.message : error}`);
|
|
267
|
+
if (hasParameter('norestore')) {
|
|
268
|
+
this.log.fatal(`The matterbridge node storage is corrupted. Parameter -norestore found: exiting...`);
|
|
269
|
+
await this.cleanup('Fatal error creating node storage manager and context for matterbridge');
|
|
270
|
+
return;
|
|
271
|
+
}
|
|
272
|
+
this.log.notice(`The matterbridge storage is corrupted. Restoring it with backup...`);
|
|
273
|
+
await copyDirectory(path.join(this.matterbridgeDirectory, this.nodeStorageName + '.backup'), path.join(this.matterbridgeDirectory, this.nodeStorageName));
|
|
274
|
+
this.log.notice(`The matterbridge storage has been restored with backup`);
|
|
275
|
+
}
|
|
276
|
+
if (!this.nodeStorage || !this.nodeContext) {
|
|
277
|
+
this.log.fatal('Fatal error creating node storage manager and context for matterbridge');
|
|
278
|
+
throw new Error('Fatal error creating node storage manager and context for matterbridge');
|
|
237
279
|
}
|
|
238
280
|
// Set matterbridge logger level (context: matterbridgeLogLevel)
|
|
239
281
|
if (hasParameter('logger')) {
|
|
@@ -265,45 +307,50 @@ export class Matterbridge extends EventEmitter {
|
|
|
265
307
|
this.log.logLevel = await this.nodeContext.get('matterbridgeLogLevel', "info" /* LogLevel.INFO */);
|
|
266
308
|
}
|
|
267
309
|
MatterbridgeDevice.logLevel = this.log.logLevel;
|
|
310
|
+
// Create the file logger for matterbridge (context: matterbridgeFileLog)
|
|
311
|
+
if (hasParameter('filelogger') || (await this.nodeContext.get('matterbridgeFileLog', false))) {
|
|
312
|
+
AnsiLogger.setGlobalLogfile(path.join(this.matterbridgeDirectory, this.matterbrideLoggerFile), this.log.logLevel, true);
|
|
313
|
+
this.matterbridgeInformation.fileLogger = true;
|
|
314
|
+
}
|
|
268
315
|
this.log.notice('Matterbridge is starting...');
|
|
269
316
|
this.log.debug(`Matterbridge logLevel: ${this.log.logLevel} fileLoger: ${this.matterbridgeInformation.fileLogger}.`);
|
|
270
317
|
// Set matter.js logger level, format and logger (context: matterLogLevel)
|
|
271
318
|
if (hasParameter('matterlogger')) {
|
|
272
319
|
const level = getParameter('matterlogger');
|
|
273
320
|
if (level === 'debug') {
|
|
274
|
-
Logger.defaultLogLevel =
|
|
321
|
+
Logger.defaultLogLevel = MatterLogLevel.DEBUG;
|
|
275
322
|
}
|
|
276
323
|
else if (level === 'info') {
|
|
277
|
-
Logger.defaultLogLevel =
|
|
324
|
+
Logger.defaultLogLevel = MatterLogLevel.INFO;
|
|
278
325
|
}
|
|
279
326
|
else if (level === 'notice') {
|
|
280
|
-
Logger.defaultLogLevel =
|
|
327
|
+
Logger.defaultLogLevel = MatterLogLevel.NOTICE;
|
|
281
328
|
}
|
|
282
329
|
else if (level === 'warn') {
|
|
283
|
-
Logger.defaultLogLevel =
|
|
330
|
+
Logger.defaultLogLevel = MatterLogLevel.WARN;
|
|
284
331
|
}
|
|
285
332
|
else if (level === 'error') {
|
|
286
|
-
Logger.defaultLogLevel =
|
|
333
|
+
Logger.defaultLogLevel = MatterLogLevel.ERROR;
|
|
287
334
|
}
|
|
288
335
|
else if (level === 'fatal') {
|
|
289
|
-
Logger.defaultLogLevel =
|
|
336
|
+
Logger.defaultLogLevel = MatterLogLevel.FATAL;
|
|
290
337
|
}
|
|
291
338
|
else {
|
|
292
339
|
this.log.warn(`Invalid matter.js logger level: ${level}. Using default level "info".`);
|
|
293
|
-
Logger.defaultLogLevel =
|
|
340
|
+
Logger.defaultLogLevel = MatterLogLevel.INFO;
|
|
294
341
|
}
|
|
295
342
|
}
|
|
296
343
|
else {
|
|
297
|
-
Logger.defaultLogLevel = await this.nodeContext.get('matterLogLevel',
|
|
344
|
+
Logger.defaultLogLevel = await this.nodeContext.get('matterLogLevel', MatterLogLevel.INFO);
|
|
298
345
|
}
|
|
299
|
-
Logger.format =
|
|
346
|
+
Logger.format = MatterLogFormat.ANSI;
|
|
300
347
|
Logger.setLogger('default', this.createMatterLogger());
|
|
301
348
|
// Create the file logger for matter.js (context: matterFileLog)
|
|
302
349
|
if (hasParameter('matterfilelogger') || (await this.nodeContext.get('matterFileLog', false))) {
|
|
303
350
|
this.matterbridgeInformation.matterFileLogger = true;
|
|
304
351
|
Logger.addLogger('matterfilelogger', await this.createMatterFileLogger(path.join(this.matterbridgeDirectory, this.matterLoggerFile), true), {
|
|
305
|
-
defaultLogLevel:
|
|
306
|
-
logFormat:
|
|
352
|
+
defaultLogLevel: Logger.defaultLogLevel,
|
|
353
|
+
logFormat: MatterLogFormat.PLAIN,
|
|
307
354
|
});
|
|
308
355
|
}
|
|
309
356
|
this.log.debug(`Matter logLevel: ${Logger.defaultLogLevel} fileLoger: ${this.matterbridgeInformation.matterFileLogger}.`);
|
|
@@ -347,7 +394,7 @@ export class Matterbridge extends EventEmitter {
|
|
|
347
394
|
// We don't do this when the add parameter is set because we shut down the process after adding the plugin
|
|
348
395
|
this.log.info(`Error parsing plugin ${plg}${plugin.name}${nf}. Trying to reinstall it from npm.`);
|
|
349
396
|
try {
|
|
350
|
-
await this.spawnCommand('npm', ['install', '-g', '--omit=dev',
|
|
397
|
+
await this.spawnCommand('npm', ['install', '-g', plugin.name, '--omit=dev', '--verbose']);
|
|
351
398
|
this.log.info(`Plugin ${plg}${plugin.name}${nf} reinstalled.`);
|
|
352
399
|
plugin.error = false;
|
|
353
400
|
// eslint-disable-next-line @typescript-eslint/no-unused-vars
|
|
@@ -383,8 +430,8 @@ export class Matterbridge extends EventEmitter {
|
|
|
383
430
|
this.log.error(`Node version ${versionMajor} is not supported. Please upgrade to ${minNodeVersion} or above.`);
|
|
384
431
|
throw new Error(`Node version ${versionMajor} is not supported. Please upgrade to ${minNodeVersion} or above.`);
|
|
385
432
|
}
|
|
386
|
-
// Register
|
|
387
|
-
this.
|
|
433
|
+
// Register process handlers
|
|
434
|
+
this.registerProcessHandlers();
|
|
388
435
|
// Parse command line
|
|
389
436
|
await this.parseCommandLine();
|
|
390
437
|
this.initialized = true;
|
|
@@ -415,6 +462,7 @@ export class Matterbridge extends EventEmitter {
|
|
|
415
462
|
- logstorage: log the node storage
|
|
416
463
|
- sudo: force the use of sudo to install or update packages if the internal logic fails
|
|
417
464
|
- nosudo: force not to use sudo to install or update packages if the internal logic fails
|
|
465
|
+
- norestore: force not to automatically restore the matterbridge node storage and the matter storage from backup if it is corrupted
|
|
418
466
|
- ssl: enable SSL for the frontend and WebSockerServer (certificates in .matterbridge/certs directory cert.pem, key.pem and ca.pem (optional))
|
|
419
467
|
- add [plugin path]: register the plugin from the given absolute or relative path
|
|
420
468
|
- add [plugin name]: register the globally installed plugin with the given name
|
|
@@ -522,7 +570,13 @@ export class Matterbridge extends EventEmitter {
|
|
|
522
570
|
return;
|
|
523
571
|
}
|
|
524
572
|
// Start the matter storage and create the matterbridge context
|
|
525
|
-
|
|
573
|
+
try {
|
|
574
|
+
await this.startMatterStorage('json', path.join(this.matterbridgeDirectory, this.matterStorageName));
|
|
575
|
+
}
|
|
576
|
+
catch (error) {
|
|
577
|
+
this.log.fatal(`Fatal error creating matter storage: ${error instanceof Error ? error.message : error}`);
|
|
578
|
+
throw new Error(`Fatal error creating matter storage: ${error instanceof Error ? error.message : error}`);
|
|
579
|
+
}
|
|
526
580
|
if (hasParameter('reset') && getParameter('reset') === undefined) {
|
|
527
581
|
this.log.info('Resetting Matterbridge commissioning information...');
|
|
528
582
|
await this.matterbridgeContext?.clearAll();
|
|
@@ -581,6 +635,7 @@ export class Matterbridge extends EventEmitter {
|
|
|
581
635
|
if (hasParameter('bridge') || (!hasParameter('childbridge') && (await this.nodeContext?.get('bridgeMode', '')) === 'bridge')) {
|
|
582
636
|
this.bridgeMode = 'bridge';
|
|
583
637
|
MatterbridgeDevice.bridgeMode = 'bridge';
|
|
638
|
+
MatterbridgeEndpoint.bridgeMode = 'bridge';
|
|
584
639
|
this.log.debug(`Starting matterbridge in mode ${this.bridgeMode}`);
|
|
585
640
|
await this.startBridge();
|
|
586
641
|
return;
|
|
@@ -589,6 +644,7 @@ export class Matterbridge extends EventEmitter {
|
|
|
589
644
|
if (hasParameter('childbridge') || (!hasParameter('bridge') && (await this.nodeContext?.get('bridgeMode', '')) === 'childbridge')) {
|
|
590
645
|
this.bridgeMode = 'childbridge';
|
|
591
646
|
MatterbridgeDevice.bridgeMode = 'childbridge';
|
|
647
|
+
MatterbridgeEndpoint.bridgeMode = 'childbridge';
|
|
592
648
|
this.log.debug(`Starting matterbridge in mode ${this.bridgeMode}`);
|
|
593
649
|
await this.startChildbridge();
|
|
594
650
|
return;
|
|
@@ -635,10 +691,23 @@ export class Matterbridge extends EventEmitter {
|
|
|
635
691
|
this.wssSendRefreshRequired();
|
|
636
692
|
}
|
|
637
693
|
/**
|
|
638
|
-
* Registers the
|
|
694
|
+
* Registers the process handlers for uncaughtException, unhandledRejection, SIGINT and SIGTERM.
|
|
639
695
|
* When either of these signals are received, the cleanup method is called with an appropriate message.
|
|
640
696
|
*/
|
|
641
|
-
|
|
697
|
+
registerProcessHandlers() {
|
|
698
|
+
this.log.debug(`Registering uncaughtException and unhandledRejection handlers...`);
|
|
699
|
+
process.removeAllListeners('uncaughtException');
|
|
700
|
+
process.removeAllListeners('unhandledRejection');
|
|
701
|
+
this.exceptionHandler = async (error) => {
|
|
702
|
+
this.log.fatal('Unhandled Exception detected at:', error.stack || error, rs);
|
|
703
|
+
// await this.cleanup('Unhandled Exception detected, cleaning up...');
|
|
704
|
+
};
|
|
705
|
+
process.on('uncaughtException', this.exceptionHandler);
|
|
706
|
+
this.rejectionHandler = async (reason, promise) => {
|
|
707
|
+
this.log.fatal('Unhandled Rejection detected at:', promise, 'reason:', reason instanceof Error ? reason.stack : reason, rs);
|
|
708
|
+
// await this.cleanup('Unhandled Rejection detected, cleaning up...');
|
|
709
|
+
};
|
|
710
|
+
process.on('unhandledRejection', this.rejectionHandler);
|
|
642
711
|
this.log.debug(`Registering SIGINT and SIGTERM signal handlers...`);
|
|
643
712
|
this.sigintHandler = async () => {
|
|
644
713
|
await this.cleanup('SIGINT received, cleaning up...');
|
|
@@ -650,9 +719,16 @@ export class Matterbridge extends EventEmitter {
|
|
|
650
719
|
process.on('SIGTERM', this.sigtermHandler);
|
|
651
720
|
}
|
|
652
721
|
/**
|
|
653
|
-
* Deregisters the SIGINT and SIGTERM signal handlers.
|
|
722
|
+
* Deregisters the process uncaughtException, unhandledRejection, SIGINT and SIGTERM signal handlers.
|
|
654
723
|
*/
|
|
655
|
-
|
|
724
|
+
deregisterProcesslHandlers() {
|
|
725
|
+
this.log.debug(`Deregistering uncaughtException and unhandledRejection handlers...`);
|
|
726
|
+
if (this.exceptionHandler)
|
|
727
|
+
process.off('uncaughtException', this.exceptionHandler);
|
|
728
|
+
this.exceptionHandler = undefined;
|
|
729
|
+
if (this.rejectionHandler)
|
|
730
|
+
process.off('unhandledRejection', this.rejectionHandler);
|
|
731
|
+
this.rejectionHandler = undefined;
|
|
656
732
|
this.log.debug(`Deregistering SIGINT and SIGTERM signal handlers...`);
|
|
657
733
|
if (this.sigintHandler)
|
|
658
734
|
process.off('SIGINT', this.sigintHandler);
|
|
@@ -922,22 +998,22 @@ export class Matterbridge extends EventEmitter {
|
|
|
922
998
|
const message = formattedLog.slice(65);
|
|
923
999
|
matterLogger.logName = logger;
|
|
924
1000
|
switch (_level) {
|
|
925
|
-
case
|
|
1001
|
+
case MatterLogLevel.DEBUG:
|
|
926
1002
|
matterLogger.log("debug" /* LogLevel.DEBUG */, message);
|
|
927
1003
|
break;
|
|
928
|
-
case
|
|
1004
|
+
case MatterLogLevel.INFO:
|
|
929
1005
|
matterLogger.log("info" /* LogLevel.INFO */, message);
|
|
930
1006
|
break;
|
|
931
|
-
case
|
|
1007
|
+
case MatterLogLevel.NOTICE:
|
|
932
1008
|
matterLogger.log("notice" /* LogLevel.NOTICE */, message);
|
|
933
1009
|
break;
|
|
934
|
-
case
|
|
1010
|
+
case MatterLogLevel.WARN:
|
|
935
1011
|
matterLogger.log("warn" /* LogLevel.WARN */, message);
|
|
936
1012
|
break;
|
|
937
|
-
case
|
|
1013
|
+
case MatterLogLevel.ERROR:
|
|
938
1014
|
matterLogger.log("error" /* LogLevel.ERROR */, message);
|
|
939
1015
|
break;
|
|
940
|
-
case
|
|
1016
|
+
case MatterLogLevel.FATAL:
|
|
941
1017
|
matterLogger.log("fatal" /* LogLevel.FATAL */, message);
|
|
942
1018
|
break;
|
|
943
1019
|
default:
|
|
@@ -979,22 +1055,22 @@ export class Matterbridge extends EventEmitter {
|
|
|
979
1055
|
const logger = parts[1];
|
|
980
1056
|
const finalMessage = parts.slice(2).join(' ') + os.EOL;
|
|
981
1057
|
switch (_level) {
|
|
982
|
-
case
|
|
1058
|
+
case MatterLogLevel.DEBUG:
|
|
983
1059
|
await fs.appendFile(filePath, `[${timestamp}] [${logger}] [debug] ${finalMessage}`);
|
|
984
1060
|
break;
|
|
985
|
-
case
|
|
1061
|
+
case MatterLogLevel.INFO:
|
|
986
1062
|
await fs.appendFile(filePath, `[${timestamp}] [${logger}] [info] ${finalMessage}`);
|
|
987
1063
|
break;
|
|
988
|
-
case
|
|
1064
|
+
case MatterLogLevel.NOTICE:
|
|
989
1065
|
await fs.appendFile(filePath, `[${timestamp}] [${logger}] [notice] ${finalMessage}`);
|
|
990
1066
|
break;
|
|
991
|
-
case
|
|
1067
|
+
case MatterLogLevel.WARN:
|
|
992
1068
|
await fs.appendFile(filePath, `[${timestamp}] [${logger}] [warn] ${finalMessage}`);
|
|
993
1069
|
break;
|
|
994
|
-
case
|
|
1070
|
+
case MatterLogLevel.ERROR:
|
|
995
1071
|
await fs.appendFile(filePath, `[${timestamp}] [${logger}] [error] ${finalMessage}`);
|
|
996
1072
|
break;
|
|
997
|
-
case
|
|
1073
|
+
case MatterLogLevel.FATAL:
|
|
998
1074
|
await fs.appendFile(filePath, `[${timestamp}] [${logger}] [fatal] ${finalMessage}`);
|
|
999
1075
|
break;
|
|
1000
1076
|
default:
|
|
@@ -1053,8 +1129,8 @@ export class Matterbridge extends EventEmitter {
|
|
|
1053
1129
|
if (this.initialized && !this.hasCleanupStarted) {
|
|
1054
1130
|
this.hasCleanupStarted = true;
|
|
1055
1131
|
this.log.info(message);
|
|
1056
|
-
// Deregisters the
|
|
1057
|
-
this.
|
|
1132
|
+
// Deregisters the process handlers
|
|
1133
|
+
this.deregisterProcesslHandlers();
|
|
1058
1134
|
// Clear the start matter interval
|
|
1059
1135
|
if (this.startMatterInterval) {
|
|
1060
1136
|
clearInterval(this.startMatterInterval);
|
|
@@ -1209,6 +1285,18 @@ export class Matterbridge extends EventEmitter {
|
|
|
1209
1285
|
this.initialized = false;
|
|
1210
1286
|
}
|
|
1211
1287
|
}
|
|
1288
|
+
// eslint-disable-next-line @typescript-eslint/no-unused-vars
|
|
1289
|
+
async addBridgedEndpoint(pluginName, device) {
|
|
1290
|
+
// Nothing to do here
|
|
1291
|
+
}
|
|
1292
|
+
// eslint-disable-next-line @typescript-eslint/no-unused-vars
|
|
1293
|
+
async removeBridgedEndpoint(pluginName, device) {
|
|
1294
|
+
// Nothing to do here
|
|
1295
|
+
}
|
|
1296
|
+
// eslint-disable-next-line @typescript-eslint/no-unused-vars
|
|
1297
|
+
async removeAllBridgedEndpoints(pluginName) {
|
|
1298
|
+
// Nothing to do here
|
|
1299
|
+
}
|
|
1212
1300
|
/**
|
|
1213
1301
|
* Adds a bridged device to the Matterbridge.
|
|
1214
1302
|
* @param pluginName - The name of the plugin.
|
|
@@ -1717,7 +1805,7 @@ export class Matterbridge extends EventEmitter {
|
|
|
1717
1805
|
* @returns {Promise<void>} - A promise that resolves when the storage process is started.
|
|
1718
1806
|
*/
|
|
1719
1807
|
async startMatterStorage(storageType, storageName) {
|
|
1720
|
-
this.log.debug(`Starting ${storageType} storage ${CYAN}${storageName}${db}`);
|
|
1808
|
+
this.log.debug(`Starting matter ${storageType} storage ${CYAN}${storageName}${db}`);
|
|
1721
1809
|
if (storageType === 'disk') {
|
|
1722
1810
|
const storageDisk = new StorageBackendDisk(storageName);
|
|
1723
1811
|
this.storageManager = new StorageManager(storageDisk);
|
|
@@ -1729,22 +1817,34 @@ export class Matterbridge extends EventEmitter {
|
|
|
1729
1817
|
this.storageManager = new StorageManager(storageJson);
|
|
1730
1818
|
}
|
|
1731
1819
|
else {
|
|
1732
|
-
this.log.error(`Unsupported storage type ${storageType}`);
|
|
1733
|
-
await this.cleanup('Unsupported storage type');
|
|
1820
|
+
this.log.error(`Unsupported matter storage type ${storageType}`);
|
|
1821
|
+
await this.cleanup('Unsupported matter storage type');
|
|
1734
1822
|
return;
|
|
1735
1823
|
}
|
|
1736
1824
|
try {
|
|
1737
1825
|
await this.storageManager.initialize();
|
|
1738
|
-
this.log.debug('
|
|
1826
|
+
this.log.debug('Matter storage initialized');
|
|
1739
1827
|
if (storageType === 'json') {
|
|
1740
1828
|
await this.backupMatterStorage(storageName, storageName.replace('.json', '') + '.backup.json');
|
|
1741
1829
|
}
|
|
1742
|
-
// eslint-disable-next-line @typescript-eslint/no-unused-vars
|
|
1743
1830
|
}
|
|
1744
1831
|
catch (error) {
|
|
1745
|
-
this.log.error(`
|
|
1746
|
-
|
|
1747
|
-
|
|
1832
|
+
this.log.error(`Matter storage initialize error! The file .matterbridge/${storageName} may be corrupted: ${error instanceof Error ? error.message : error}`);
|
|
1833
|
+
if (hasParameter('norestore')) {
|
|
1834
|
+
this.log.fatal(`Please delete it and rename ${storageName.replace('.json', '.backup.json')} to ${storageName} and try to restart Matterbridge.`);
|
|
1835
|
+
await this.cleanup('Matter storage initialize error and -norestore parameter found!');
|
|
1836
|
+
return;
|
|
1837
|
+
}
|
|
1838
|
+
await this.restoreMatterStorage(storageName.replace('.json', '') + '.backup.json', storageName);
|
|
1839
|
+
try {
|
|
1840
|
+
await this.storageManager.initialize();
|
|
1841
|
+
this.log.notice('Matter storage initialized from the backup file');
|
|
1842
|
+
}
|
|
1843
|
+
catch (error) {
|
|
1844
|
+
this.log.error(`Matter storage initialize error! The backup file for .matterbridge/${storageName} may be corrupted too:`, error instanceof Error ? error.message : error);
|
|
1845
|
+
await this.cleanup('Matter storage initialize error from backup!');
|
|
1846
|
+
return;
|
|
1847
|
+
}
|
|
1748
1848
|
}
|
|
1749
1849
|
this.log.debug(`Creating commissioning server context for ${plg}Matterbridge${db}`);
|
|
1750
1850
|
this.matterbridgeContext = await this.createCommissioningServerContext('Matterbridge', 'Matterbridge', DeviceTypes.AGGREGATOR.code, 0xfff1, 'Matterbridge', 0x8000, 'Matterbridge aggregator');
|
|
@@ -1764,7 +1864,7 @@ export class Matterbridge extends EventEmitter {
|
|
|
1764
1864
|
catch (err) {
|
|
1765
1865
|
if (err instanceof Error && 'code' in err) {
|
|
1766
1866
|
if (err.code === 'ENOENT') {
|
|
1767
|
-
this.log.
|
|
1867
|
+
this.log.debug(`No existing file to back up for ${storageName}. This is expected on the first run.`);
|
|
1768
1868
|
}
|
|
1769
1869
|
else {
|
|
1770
1870
|
this.log.error(`Error making backup copy of ${storageName}: ${err.message}`);
|
|
@@ -1775,6 +1875,32 @@ export class Matterbridge extends EventEmitter {
|
|
|
1775
1875
|
}
|
|
1776
1876
|
}
|
|
1777
1877
|
}
|
|
1878
|
+
/**
|
|
1879
|
+
* Restore the specified matter JSON storage file.
|
|
1880
|
+
*
|
|
1881
|
+
* @param backupName - The name of the backup file to restore from.
|
|
1882
|
+
* @param storageName - The name of the JSON storage file to restored.
|
|
1883
|
+
*/
|
|
1884
|
+
async restoreMatterStorage(backupName, storageName) {
|
|
1885
|
+
try {
|
|
1886
|
+
this.log.notice(`Restoring the backup copy of ${storageName}`);
|
|
1887
|
+
await fs.copyFile(backupName, storageName);
|
|
1888
|
+
this.log.notice(`Successfully restored ${backupName} to ${storageName}`);
|
|
1889
|
+
}
|
|
1890
|
+
catch (err) {
|
|
1891
|
+
if (err instanceof Error && 'code' in err) {
|
|
1892
|
+
if (err.code === 'ENOENT') {
|
|
1893
|
+
this.log.info(`No existing file to restore: ${backupName}.`);
|
|
1894
|
+
}
|
|
1895
|
+
else {
|
|
1896
|
+
this.log.error(`Error restoring ${backupName}: ${err.message}`);
|
|
1897
|
+
}
|
|
1898
|
+
}
|
|
1899
|
+
else {
|
|
1900
|
+
this.log.error(`An unexpected error occurred during the restore of ${backupName}: ${String(err)}`);
|
|
1901
|
+
}
|
|
1902
|
+
}
|
|
1903
|
+
}
|
|
1778
1904
|
/**
|
|
1779
1905
|
* Stops the matter storage.
|
|
1780
1906
|
* @returns {Promise<void>} A promise that resolves when the storage is stopped.
|
|
@@ -1846,39 +1972,52 @@ export class Matterbridge extends EventEmitter {
|
|
|
1846
1972
|
* @param {StorageContext} context - The storage context.
|
|
1847
1973
|
* @returns {Aggregator} - The created Matter Aggregator.
|
|
1848
1974
|
*/
|
|
1975
|
+
// eslint-disable-next-line @typescript-eslint/no-unused-vars
|
|
1849
1976
|
async createMatterAggregator(context, pluginName) {
|
|
1850
|
-
|
|
1977
|
+
/*
|
|
1978
|
+
const random = randomBytes(8).toString('hex');
|
|
1851
1979
|
await context.set('aggregatorSerialNumber', await context.get('aggregatorSerialNumber', random));
|
|
1852
1980
|
await context.set('aggregatorUniqueId', await context.get('aggregatorUniqueId', random));
|
|
1853
|
-
|
|
1854
|
-
this.log.debug(`Creating matter aggregator for plugin ${plg}${pluginName}${db} with
|
|
1855
|
-
this.log.debug(`Creating matter aggregator for plugin ${plg}${pluginName}${db} with
|
|
1981
|
+
|
|
1982
|
+
this.log.debug(`Creating matter aggregator for plugin ${plg}${pluginName}${db} with uniqueId ${await context.get<string>('aggregatorUniqueId')} serialNumber ${await context.get<string>('aggregatorSerialNumber')}`);
|
|
1983
|
+
this.log.debug(`Creating matter aggregator for plugin ${plg}${pluginName}${db} with softwareVersion ${await context.get<number>('softwareVersion', 1)} softwareVersionString ${await context.get<string>('softwareVersionString', '1.0.0')}`);
|
|
1984
|
+
this.log.debug(`Creating matter aggregator for plugin ${plg}${pluginName}${db} with hardwareVersion ${await context.get<number>('hardwareVersion', 1)} hardwareVersionString ${await context.get<string>('hardwareVersionString', '1.0.0')}`);
|
|
1985
|
+
*/
|
|
1856
1986
|
const matterAggregator = new Aggregator();
|
|
1857
|
-
|
|
1858
|
-
|
|
1859
|
-
|
|
1860
|
-
|
|
1861
|
-
|
|
1862
|
-
|
|
1863
|
-
|
|
1864
|
-
|
|
1865
|
-
|
|
1866
|
-
|
|
1867
|
-
|
|
1868
|
-
|
|
1869
|
-
|
|
1870
|
-
|
|
1871
|
-
|
|
1872
|
-
|
|
1873
|
-
|
|
1874
|
-
|
|
1875
|
-
|
|
1876
|
-
|
|
1877
|
-
|
|
1878
|
-
|
|
1879
|
-
|
|
1880
|
-
|
|
1881
|
-
|
|
1987
|
+
/*
|
|
1988
|
+
matterAggregator.addClusterServer(
|
|
1989
|
+
ClusterServer(
|
|
1990
|
+
BasicInformationCluster,
|
|
1991
|
+
{
|
|
1992
|
+
dataModelRevision: 1,
|
|
1993
|
+
location: 'FR',
|
|
1994
|
+
vendorId: VendorId(0xfff1),
|
|
1995
|
+
vendorName: 'Matterbridge',
|
|
1996
|
+
productId: 0x8000,
|
|
1997
|
+
productName: 'Matterbridge aggregator',
|
|
1998
|
+
productLabel: 'Matterbridge aggregator',
|
|
1999
|
+
nodeLabel: 'Matterbridge aggregator',
|
|
2000
|
+
serialNumber: await context.get<string>('aggregatorSerialNumber'),
|
|
2001
|
+
uniqueId: await context.get<string>('aggregatorUniqueId'),
|
|
2002
|
+
softwareVersion: await context.get<number>('softwareVersion', 1),
|
|
2003
|
+
softwareVersionString: await context.get<string>('softwareVersionString', '1.0.0'),
|
|
2004
|
+
hardwareVersion: await context.get<number>('hardwareVersion', 1),
|
|
2005
|
+
hardwareVersionString: await context.get<string>('hardwareVersionString', '1.0.0'),
|
|
2006
|
+
reachable: true,
|
|
2007
|
+
capabilityMinima: { caseSessionsPerFabric: 3, subscriptionsPerFabric: 3 },
|
|
2008
|
+
specificationVersion: Specification.SPECIFICATION_VERSION,
|
|
2009
|
+
maxPathsPerInvoke: 1,
|
|
2010
|
+
},
|
|
2011
|
+
{},
|
|
2012
|
+
{
|
|
2013
|
+
startUp: true,
|
|
2014
|
+
shutDown: true,
|
|
2015
|
+
leave: true,
|
|
2016
|
+
reachableChanged: true,
|
|
2017
|
+
},
|
|
2018
|
+
),
|
|
2019
|
+
);
|
|
2020
|
+
*/
|
|
1882
2021
|
return matterAggregator;
|
|
1883
2022
|
}
|
|
1884
2023
|
/**
|
|
@@ -2071,7 +2210,7 @@ export class Matterbridge extends EventEmitter {
|
|
|
2071
2210
|
if (!this.storageManager)
|
|
2072
2211
|
throw new Error('No storage manager initialized');
|
|
2073
2212
|
this.log.debug(`Creating commissioning server storage context for ${plg}${pluginName}${db}`);
|
|
2074
|
-
const random =
|
|
2213
|
+
const random = randomBytes(8).toString('hex');
|
|
2075
2214
|
const storageContext = this.storageManager.createContext(pluginName);
|
|
2076
2215
|
await storageContext.set('deviceName', deviceName);
|
|
2077
2216
|
await storageContext.set('deviceType', deviceType);
|
|
@@ -2376,7 +2515,7 @@ export class Matterbridge extends EventEmitter {
|
|
|
2376
2515
|
* Spawns a child process with the given command and arguments.
|
|
2377
2516
|
* @param {string} command - The command to execute.
|
|
2378
2517
|
* @param {string[]} args - The arguments to pass to the command (default: []).
|
|
2379
|
-
* @returns {Promise<
|
|
2518
|
+
* @returns {Promise<boolean>} A promise that resolves when the child process exits successfully, or rejects if there is an error.
|
|
2380
2519
|
*/
|
|
2381
2520
|
async spawnCommand(command, args = []) {
|
|
2382
2521
|
/*
|
|
@@ -2421,7 +2560,7 @@ export class Matterbridge extends EventEmitter {
|
|
|
2421
2560
|
if (cmdLine.startsWith('npm install -g'))
|
|
2422
2561
|
this.log.notice(`Package ${cmdLine.replace('npm install -g ', '').replace('--verbose', '').replace('--omit=dev', '')} installed correctly`);
|
|
2423
2562
|
this.log.debug(`Child process "${cmdLine}" closed with code ${code} and signal ${signal}`);
|
|
2424
|
-
resolve();
|
|
2563
|
+
resolve(true);
|
|
2425
2564
|
}
|
|
2426
2565
|
else {
|
|
2427
2566
|
this.log.error(`Child process "${cmdLine}" closed with code ${code} and signal ${signal}`);
|
|
@@ -2432,7 +2571,7 @@ export class Matterbridge extends EventEmitter {
|
|
|
2432
2571
|
this.wssSendMessage('spawn', this.log.now(), 'Matterbridge:spawn', `child process exited with code ${code} and signal ${signal}`);
|
|
2433
2572
|
if (code === 0) {
|
|
2434
2573
|
this.log.debug(`Child process "${cmdLine}" exited with code ${code} and signal ${signal}`);
|
|
2435
|
-
resolve();
|
|
2574
|
+
resolve(true);
|
|
2436
2575
|
}
|
|
2437
2576
|
else {
|
|
2438
2577
|
this.log.error(`Child process "${cmdLine}" exited with code ${code} and signal ${signal}`);
|
|
@@ -2441,7 +2580,7 @@ export class Matterbridge extends EventEmitter {
|
|
|
2441
2580
|
});
|
|
2442
2581
|
childProcess.on('disconnect', () => {
|
|
2443
2582
|
this.log.debug(`Child process "${cmdLine}" has been disconnected from the parent`);
|
|
2444
|
-
resolve();
|
|
2583
|
+
resolve(true);
|
|
2445
2584
|
});
|
|
2446
2585
|
if (childProcess.stdout) {
|
|
2447
2586
|
childProcess.stdout.on('data', (data) => {
|
|
@@ -3013,22 +3152,22 @@ export class Matterbridge extends EventEmitter {
|
|
|
3013
3152
|
if (command === 'setmjloglevel') {
|
|
3014
3153
|
this.log.debug('Matter.js log level:', param);
|
|
3015
3154
|
if (param === 'Debug') {
|
|
3016
|
-
Logger.defaultLogLevel =
|
|
3155
|
+
Logger.defaultLogLevel = MatterLogLevel.DEBUG;
|
|
3017
3156
|
}
|
|
3018
3157
|
else if (param === 'Info') {
|
|
3019
|
-
Logger.defaultLogLevel =
|
|
3158
|
+
Logger.defaultLogLevel = MatterLogLevel.INFO;
|
|
3020
3159
|
}
|
|
3021
3160
|
else if (param === 'Notice') {
|
|
3022
|
-
Logger.defaultLogLevel =
|
|
3161
|
+
Logger.defaultLogLevel = MatterLogLevel.NOTICE;
|
|
3023
3162
|
}
|
|
3024
3163
|
else if (param === 'Warn') {
|
|
3025
|
-
Logger.defaultLogLevel =
|
|
3164
|
+
Logger.defaultLogLevel = MatterLogLevel.WARN;
|
|
3026
3165
|
}
|
|
3027
3166
|
else if (param === 'Error') {
|
|
3028
|
-
Logger.defaultLogLevel =
|
|
3167
|
+
Logger.defaultLogLevel = MatterLogLevel.ERROR;
|
|
3029
3168
|
}
|
|
3030
3169
|
else if (param === 'Fatal') {
|
|
3031
|
-
Logger.defaultLogLevel =
|
|
3170
|
+
Logger.defaultLogLevel = MatterLogLevel.FATAL;
|
|
3032
3171
|
}
|
|
3033
3172
|
await this.nodeContext?.set('matterLogLevel', Logger.defaultLogLevel);
|
|
3034
3173
|
res.json({ message: 'Command received' });
|
|
@@ -3082,8 +3221,8 @@ export class Matterbridge extends EventEmitter {
|
|
|
3082
3221
|
if (param === 'true') {
|
|
3083
3222
|
try {
|
|
3084
3223
|
Logger.addLogger('matterfilelogger', await this.createMatterFileLogger(path.join(this.matterbridgeDirectory, this.matterLoggerFile), true), {
|
|
3085
|
-
defaultLogLevel:
|
|
3086
|
-
logFormat:
|
|
3224
|
+
defaultLogLevel: MatterLogLevel.DEBUG,
|
|
3225
|
+
logFormat: MatterLogFormat.PLAIN,
|
|
3087
3226
|
});
|
|
3088
3227
|
}
|
|
3089
3228
|
catch (error) {
|
|
@@ -3371,8 +3510,8 @@ export class Matterbridge extends EventEmitter {
|
|
|
3371
3510
|
await this.logNodeAndSystemInfo();
|
|
3372
3511
|
this.matterbridgeDirectory = dataPath;
|
|
3373
3512
|
// Set matter.js logger level and format
|
|
3374
|
-
Logger.defaultLogLevel =
|
|
3375
|
-
Logger.format =
|
|
3513
|
+
Logger.defaultLogLevel = MatterLogLevel.INFO;
|
|
3514
|
+
Logger.format = MatterLogFormat.ANSI;
|
|
3376
3515
|
// Start the storage and create matterbridgeContext
|
|
3377
3516
|
await this.startMatterStorage('json', path.join(this.matterbridgeDirectory, this.matterStorageName));
|
|
3378
3517
|
if (!this.storageManager)
|