matterbridge 1.3.9 → 1.3.11
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 +47 -0
- package/__mocks__/@project-chip/matter-node.js/util.js +41 -0
- package/dist/matterbridge.d.ts +57 -8
- package/dist/matterbridge.d.ts.map +1 -1
- package/dist/matterbridge.js +201 -82
- package/dist/matterbridge.js.map +1 -1
- package/dist/matterbridgeDevice.d.ts +146 -15
- package/dist/matterbridgeDevice.d.ts.map +1 -1
- package/dist/matterbridgeDevice.js +239 -35
- package/dist/matterbridgeDevice.js.map +1 -1
- package/dist/matterbridgePlatform.js +1 -1
- package/dist/matterbridgePlatform.js.map +1 -1
- package/dist/utils/utils.d.ts +1 -1
- package/dist/utils/utils.js +5 -5
- package/dist/utils/utils.js.map +1 -1
- package/dist/utils.d.ts +21 -1
- package/dist/utils.d.ts.map +1 -1
- package/dist/utils.js +23 -2
- package/dist/utils.js.map +1 -1
- package/frontend/build/asset-manifest.json +6 -6
- package/frontend/build/index.html +1 -1
- package/frontend/build/static/css/main.3986966b.css +2 -0
- package/frontend/build/static/css/main.3986966b.css.map +1 -0
- package/frontend/build/static/js/{main.942a74a2.js → main.c9f97470.js} +3 -3
- package/frontend/build/static/js/{main.942a74a2.js.map → main.c9f97470.js.map} +1 -1
- package/package.json +9 -5
- package/frontend/build/static/css/main.abff2627.css +0 -8
- package/frontend/build/static/css/main.abff2627.css.map +0 -1
- /package/frontend/build/static/js/{main.942a74a2.js.LICENSE.txt → main.c9f97470.js.LICENSE.txt} +0 -0
package/dist/matterbridge.js
CHANGED
|
@@ -79,12 +79,14 @@ export class Matterbridge extends EventEmitter {
|
|
|
79
79
|
globalModulesDirectory: '',
|
|
80
80
|
matterbridgeVersion: '',
|
|
81
81
|
matterbridgeLatestVersion: '',
|
|
82
|
-
|
|
82
|
+
matterbridgeFabricInformations: [],
|
|
83
|
+
matterbridgeSessionInformations: [],
|
|
83
84
|
matterbridgePaired: false,
|
|
84
85
|
matterbridgeConnected: false,
|
|
85
86
|
bridgeMode: '',
|
|
86
87
|
restartMode: '',
|
|
87
88
|
debugEnabled: false,
|
|
89
|
+
matterLoggerLevel: Level.INFO,
|
|
88
90
|
};
|
|
89
91
|
homeDirectory = '';
|
|
90
92
|
rootDirectory = '';
|
|
@@ -93,9 +95,10 @@ export class Matterbridge extends EventEmitter {
|
|
|
93
95
|
globalModulesDirectory = '';
|
|
94
96
|
matterbridgeVersion = '';
|
|
95
97
|
matterbridgeLatestVersion = '';
|
|
96
|
-
|
|
98
|
+
matterbridgeFabricInformations = [];
|
|
97
99
|
matterbridgePaired = false;
|
|
98
100
|
matterbridgeConnected = false;
|
|
101
|
+
matterbridgeSessionInformations = [];
|
|
99
102
|
checkUpdateInterval; // = 24 * 60 * 60 * 1000; // 24 hours
|
|
100
103
|
bridgeMode = '';
|
|
101
104
|
restartMode = '';
|
|
@@ -113,7 +116,7 @@ export class Matterbridge extends EventEmitter {
|
|
|
113
116
|
nodeStorage;
|
|
114
117
|
nodeContext;
|
|
115
118
|
expressApp;
|
|
116
|
-
expressServer;
|
|
119
|
+
// private expressServer: Server | undefined;
|
|
117
120
|
httpServer;
|
|
118
121
|
httpsServer;
|
|
119
122
|
webSocketServer;
|
|
@@ -147,6 +150,14 @@ export class Matterbridge extends EventEmitter {
|
|
|
147
150
|
}
|
|
148
151
|
return Matterbridge.instance;
|
|
149
152
|
}
|
|
153
|
+
/**
|
|
154
|
+
* Call shutdownProcess.
|
|
155
|
+
* @deprecated This method is deprecated and is only used for jest.
|
|
156
|
+
*
|
|
157
|
+
*/
|
|
158
|
+
async destroyInstance() {
|
|
159
|
+
await this.shutdownProcess();
|
|
160
|
+
}
|
|
150
161
|
/**
|
|
151
162
|
* Initializes the Matterbridge instance as extension for zigbee2mqtt.
|
|
152
163
|
* @deprecated This method is deprecated and will be removed in a future version.
|
|
@@ -273,7 +284,7 @@ export class Matterbridge extends EventEmitter {
|
|
|
273
284
|
- reset: remove the commissioning for Matterbridge (bridge mode). Shutdown Matterbridge before using it!
|
|
274
285
|
- factoryreset: remove all commissioning information and reset all internal storages. Shutdown Matterbridge before using it!
|
|
275
286
|
- list: list the registered plugins
|
|
276
|
-
- loginterfaces: log the network interfaces
|
|
287
|
+
- loginterfaces: log the network interfaces (usefull for finding the name of the interface to use with -mdnsinterface option)
|
|
277
288
|
- logstorage: log the node storage
|
|
278
289
|
- ssl: enable SSL for the frontend and WebSockerServer (certificates in .matterbridge/certs directory cert.pem, key.pem and ca.pem (optional))
|
|
279
290
|
- add [plugin path]: register the plugin from the given absolute or relative path
|
|
@@ -290,11 +301,11 @@ export class Matterbridge extends EventEmitter {
|
|
|
290
301
|
}
|
|
291
302
|
// Set the interface to use for the matter server mdnsInterface
|
|
292
303
|
this.mdnsInterface = getParameter('mdnsinterface');
|
|
293
|
-
// Set the first port to use for the commissioning server
|
|
304
|
+
// Set the first port to use for the commissioning server (will be incremented in childbridge mode)
|
|
294
305
|
this.port = getIntParameter('port') ?? 5540;
|
|
295
|
-
// Set the first passcode to use for the commissioning server
|
|
306
|
+
// Set the first passcode to use for the commissioning server (will be incremented in childbridge mode)
|
|
296
307
|
this.passcode = getIntParameter('passcode');
|
|
297
|
-
// Set the first discriminator to use for the commissioning server
|
|
308
|
+
// Set the first discriminator to use for the commissioning server (will be incremented in childbridge mode)
|
|
298
309
|
this.discriminator = getIntParameter('discriminator');
|
|
299
310
|
// Set the restart mode
|
|
300
311
|
if (hasParameter('service'))
|
|
@@ -316,6 +327,27 @@ export class Matterbridge extends EventEmitter {
|
|
|
316
327
|
// Get the plugins from node storage and create the plugin node storage contexts
|
|
317
328
|
this.registeredPlugins = await this.nodeContext.get('plugins', []);
|
|
318
329
|
for (const plugin of this.registeredPlugins) {
|
|
330
|
+
const packageJson = await this.parsePlugin(plugin);
|
|
331
|
+
if (packageJson) {
|
|
332
|
+
// Update the plugin information
|
|
333
|
+
plugin.name = packageJson.name;
|
|
334
|
+
plugin.version = packageJson.version;
|
|
335
|
+
plugin.description = packageJson.description;
|
|
336
|
+
plugin.author = packageJson.author;
|
|
337
|
+
}
|
|
338
|
+
else {
|
|
339
|
+
this.log.info(`Error parsing plugin ${plg}${plugin.name}${nf}. Trying to reinstall it from npm.`);
|
|
340
|
+
try {
|
|
341
|
+
await this.spawnCommand('npm', ['install', '-g', plugin.name]);
|
|
342
|
+
this.log.info(`Plugin ${plg}${plugin.name}${nf} reinstalled.`);
|
|
343
|
+
plugin.error = false;
|
|
344
|
+
}
|
|
345
|
+
catch (error) {
|
|
346
|
+
plugin.error = true;
|
|
347
|
+
plugin.enabled = false;
|
|
348
|
+
this.log.error(`Error installing plugin ${plg}${plugin.name}${er}. The plugin is disabled.`);
|
|
349
|
+
}
|
|
350
|
+
}
|
|
319
351
|
this.log.debug(`Creating node storage context for plugin ${plugin.name}`);
|
|
320
352
|
plugin.nodeContext = await this.nodeStorage.createStorage(plugin.name);
|
|
321
353
|
await plugin.nodeContext.set('name', plugin.name);
|
|
@@ -328,7 +360,7 @@ export class Matterbridge extends EventEmitter {
|
|
|
328
360
|
// Log system info and create .matterbridge directory
|
|
329
361
|
await this.logNodeAndSystemInfo();
|
|
330
362
|
this.log.info(`Matterbridge version ${this.matterbridgeVersion} mode ${hasParameter('bridge') ? 'bridge' : ''}${hasParameter('childbridge') ? 'childbridge' : ''}${hasParameter('controller') ? 'controller' : ''} ` +
|
|
331
|
-
`${this.restartMode !== '' ? 'restart mode ' + this.restartMode + ' ' : ''}running on ${this.systemInformation.osType} ${this.systemInformation.osRelease} ${this.systemInformation.osPlatform} ${this.systemInformation.osArch}`);
|
|
363
|
+
`${this.restartMode !== '' ? 'restart mode ' + this.restartMode + ' ' : ''}running on ${this.systemInformation.osType} ${this.systemInformation.osRelease} ${this.systemInformation.osPlatform} ${this.systemInformation.osArch} `);
|
|
332
364
|
// Check node version and throw error
|
|
333
365
|
requireMinNodeVersion(18);
|
|
334
366
|
// Register SIGINT SIGTERM signal handlers
|
|
@@ -364,12 +396,12 @@ export class Matterbridge extends EventEmitter {
|
|
|
364
396
|
}
|
|
365
397
|
Logger.format = Format.ANSI;
|
|
366
398
|
// Parse command line
|
|
367
|
-
this.parseCommandLine();
|
|
399
|
+
await this.parseCommandLine();
|
|
368
400
|
}
|
|
369
401
|
/**
|
|
370
402
|
* Parses the command line arguments and performs the corresponding actions.
|
|
371
403
|
* @private
|
|
372
|
-
* @returns {Promise<void>} A promise that resolves when the command line arguments have been processed.
|
|
404
|
+
* @returns {Promise<void>} A promise that resolves when the command line arguments have been processed, or the process exits.
|
|
373
405
|
*/
|
|
374
406
|
async parseCommandLine() {
|
|
375
407
|
if (hasParameter('list')) {
|
|
@@ -477,7 +509,8 @@ export class Matterbridge extends EventEmitter {
|
|
|
477
509
|
process.exit(0);
|
|
478
510
|
}
|
|
479
511
|
// Initialize frontend
|
|
480
|
-
|
|
512
|
+
if (getIntParameter('frontend') !== 0 || getIntParameter('frontend') === undefined)
|
|
513
|
+
await this.initializeFrontend(getIntParameter('frontend'));
|
|
481
514
|
// Check each 60 minutes the latest versions
|
|
482
515
|
this.checkUpdateInterval = setInterval(() => {
|
|
483
516
|
this.getMatterbridgeLatestVersion();
|
|
@@ -488,7 +521,7 @@ export class Matterbridge extends EventEmitter {
|
|
|
488
521
|
if (hasParameter('test')) {
|
|
489
522
|
this.bridgeMode = 'childbridge';
|
|
490
523
|
MatterbridgeDevice.bridgeMode = 'childbridge';
|
|
491
|
-
await this.testStartMatterBridge();
|
|
524
|
+
await this.testStartMatterBridge();
|
|
492
525
|
return;
|
|
493
526
|
}
|
|
494
527
|
if (hasParameter('controller')) {
|
|
@@ -527,6 +560,14 @@ export class Matterbridge extends EventEmitter {
|
|
|
527
560
|
for (const plugin of this.registeredPlugins) {
|
|
528
561
|
plugin.configJson = await this.loadPluginConfig(plugin);
|
|
529
562
|
plugin.schemaJson = await this.loadPluginSchema(plugin);
|
|
563
|
+
// Check if the plugin is available
|
|
564
|
+
if (!(await this.resolvePluginName(plugin.path))) {
|
|
565
|
+
this.log.error(`Plugin ${plg}${plugin.name}${er} not found. Disabling it.`);
|
|
566
|
+
plugin.enabled = false;
|
|
567
|
+
plugin.error = true;
|
|
568
|
+
continue;
|
|
569
|
+
}
|
|
570
|
+
// Check if the plugin has a new version
|
|
530
571
|
this.getPluginLatestVersion(plugin);
|
|
531
572
|
if (!plugin.enabled) {
|
|
532
573
|
this.log.info(`Plugin ${plg}${plugin.name}${nf} not enabled`);
|
|
@@ -560,6 +601,14 @@ export class Matterbridge extends EventEmitter {
|
|
|
560
601
|
for (const plugin of this.registeredPlugins) {
|
|
561
602
|
plugin.configJson = await this.loadPluginConfig(plugin);
|
|
562
603
|
plugin.schemaJson = await this.loadPluginSchema(plugin);
|
|
604
|
+
// Check if the plugin is available
|
|
605
|
+
if (!(await this.resolvePluginName(plugin.path))) {
|
|
606
|
+
this.log.error(`Plugin ${plg}${plugin.name}${er} not found. Disabling it.`);
|
|
607
|
+
plugin.enabled = false;
|
|
608
|
+
plugin.error = true;
|
|
609
|
+
continue;
|
|
610
|
+
}
|
|
611
|
+
// Check if the plugin has a new version
|
|
563
612
|
this.getPluginLatestVersion(plugin);
|
|
564
613
|
if (!plugin.enabled) {
|
|
565
614
|
this.log.info(`Plugin ${plg}${plugin.name}${nf} not enabled`);
|
|
@@ -743,6 +792,7 @@ export class Matterbridge extends EventEmitter {
|
|
|
743
792
|
* When either of these signals are received, the cleanup method is called with an appropriate message.
|
|
744
793
|
*/
|
|
745
794
|
async registerSignalHandlers() {
|
|
795
|
+
this.log.debug(`Registering SIGINT and SIGTERM signal handlers...`);
|
|
746
796
|
process.once('SIGINT', async () => {
|
|
747
797
|
await this.cleanup('SIGINT received, cleaning up...');
|
|
748
798
|
});
|
|
@@ -806,11 +856,14 @@ export class Matterbridge extends EventEmitter {
|
|
|
806
856
|
if (!this.hasCleanupStarted) {
|
|
807
857
|
this.hasCleanupStarted = true;
|
|
808
858
|
this.log.info(message);
|
|
809
|
-
process
|
|
810
|
-
process.removeAllListeners(
|
|
859
|
+
// Remove all listeners from the process
|
|
860
|
+
process.removeAllListeners();
|
|
811
861
|
this.log.debug('All listeners removed');
|
|
812
|
-
|
|
862
|
+
// Clear the update interval
|
|
863
|
+
if (this.checkUpdateInterval)
|
|
864
|
+
clearInterval(this.checkUpdateInterval);
|
|
813
865
|
this.checkUpdateInterval = undefined;
|
|
866
|
+
this.log.debug('Update interval cleared');
|
|
814
867
|
// Calling the shutdown method of each plugin
|
|
815
868
|
for (const plugin of this.registeredPlugins) {
|
|
816
869
|
if (!plugin.enabled || plugin.error)
|
|
@@ -868,12 +921,14 @@ export class Matterbridge extends EventEmitter {
|
|
|
868
921
|
}
|
|
869
922
|
*/
|
|
870
923
|
// Close the express server
|
|
924
|
+
/*
|
|
871
925
|
if (this.expressServer) {
|
|
872
|
-
|
|
873
|
-
|
|
874
|
-
|
|
875
|
-
|
|
926
|
+
this.expressServer.close();
|
|
927
|
+
this.expressServer.removeAllListeners();
|
|
928
|
+
this.expressServer = undefined;
|
|
929
|
+
this.log.debug('Express server closed successfully');
|
|
876
930
|
}
|
|
931
|
+
*/
|
|
877
932
|
// Close the http server
|
|
878
933
|
if (this.httpServer) {
|
|
879
934
|
this.httpServer.close();
|
|
@@ -912,7 +967,7 @@ export class Matterbridge extends EventEmitter {
|
|
|
912
967
|
});
|
|
913
968
|
this.webSocketServer = undefined;
|
|
914
969
|
}
|
|
915
|
-
setTimeout(async () => {
|
|
970
|
+
const cleanupTimeout1 = setTimeout(async () => {
|
|
916
971
|
// Closing matter
|
|
917
972
|
await this.stopMatter();
|
|
918
973
|
// Closing storage
|
|
@@ -943,7 +998,7 @@ export class Matterbridge extends EventEmitter {
|
|
|
943
998
|
this.registeredPlugins = [];
|
|
944
999
|
this.registeredDevices = [];
|
|
945
1000
|
this.log.info('Waiting for matter to deliver last messages...');
|
|
946
|
-
setTimeout(async () => {
|
|
1001
|
+
const cleanupTimeout2 = setTimeout(async () => {
|
|
947
1002
|
if (restart) {
|
|
948
1003
|
if (message === 'updating...') {
|
|
949
1004
|
this.log.info('Cleanup completed. Updating...');
|
|
@@ -977,7 +1032,9 @@ export class Matterbridge extends EventEmitter {
|
|
|
977
1032
|
this.emit('shutdown');
|
|
978
1033
|
}
|
|
979
1034
|
}, 2 * 1000);
|
|
1035
|
+
cleanupTimeout2.unref();
|
|
980
1036
|
}, 3 * 1000);
|
|
1037
|
+
cleanupTimeout1.unref();
|
|
981
1038
|
}
|
|
982
1039
|
}
|
|
983
1040
|
/**
|
|
@@ -1460,6 +1517,23 @@ export class Matterbridge extends EventEmitter {
|
|
|
1460
1517
|
return Promise.resolve();
|
|
1461
1518
|
}
|
|
1462
1519
|
}
|
|
1520
|
+
/**
|
|
1521
|
+
* Loads and parse the plugin package.json and returns it.
|
|
1522
|
+
* @param plugin - The plugin to load the package from.
|
|
1523
|
+
* @returns A Promise that resolves to the package.json object or undefined if the package.json could not be loaded.
|
|
1524
|
+
*/
|
|
1525
|
+
async parsePlugin(plugin) {
|
|
1526
|
+
this.log.debug(`Parsing package.json of plugin ${plg}${plugin.name}${nf} type ${typ}${plugin.type}${nf}`);
|
|
1527
|
+
try {
|
|
1528
|
+
const packageJson = JSON.parse(await fs.readFile(plugin.path, 'utf8'));
|
|
1529
|
+
return packageJson;
|
|
1530
|
+
}
|
|
1531
|
+
catch (err) {
|
|
1532
|
+
this.log.error(`Failed to parse plugin ${plg}${plugin.name}${er} package.json: ${err}`);
|
|
1533
|
+
plugin.error = true;
|
|
1534
|
+
return undefined;
|
|
1535
|
+
}
|
|
1536
|
+
}
|
|
1463
1537
|
/**
|
|
1464
1538
|
* Loads a plugin and returns the corresponding MatterbridgePlatform instance.
|
|
1465
1539
|
* @param plugin - The plugin to load.
|
|
@@ -1944,12 +2018,21 @@ export class Matterbridge extends EventEmitter {
|
|
|
1944
2018
|
const QrCode = new QrCodeSchema();
|
|
1945
2019
|
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` +
|
|
1946
2020
|
`${QrCode.encode(qrPairingCode)}\n${plg}${pluginName}${nf}\n\nqrPairingCode: ${qrPairingCode}\n\nManual pairing code: ${manualPairingCode}\n`);
|
|
2021
|
+
if (pluginName === 'Matterbridge') {
|
|
2022
|
+
this.matterbridgeFabricInformations = [];
|
|
2023
|
+
this.matterbridgeSessionInformations = [];
|
|
2024
|
+
this.matterbridgePaired = false;
|
|
2025
|
+
this.matterbridgeConnected = false;
|
|
2026
|
+
}
|
|
1947
2027
|
if (pluginName !== 'Matterbridge') {
|
|
1948
2028
|
const plugin = this.findPlugin(pluginName);
|
|
1949
2029
|
if (plugin) {
|
|
1950
2030
|
plugin.qrPairingCode = qrPairingCode;
|
|
1951
2031
|
plugin.manualPairingCode = manualPairingCode;
|
|
2032
|
+
plugin.fabricInformations = [];
|
|
2033
|
+
plugin.sessionInformations = [];
|
|
1952
2034
|
plugin.paired = false;
|
|
2035
|
+
plugin.connected = false;
|
|
1953
2036
|
}
|
|
1954
2037
|
}
|
|
1955
2038
|
await this.nodeContext?.set('plugins', await this.getBaseRegisteredPlugins());
|
|
@@ -1963,19 +2046,71 @@ export class Matterbridge extends EventEmitter {
|
|
|
1963
2046
|
this.log.info(`- fabric index ${zb}${info.fabricIndex}${nf} id ${zb}${info.fabricId}${nf} vendor ${zb}${info.rootVendorId}${nf} ${this.getVendorIdName(info.rootVendorId)} ${info.label}`);
|
|
1964
2047
|
});
|
|
1965
2048
|
if (pluginName === 'Matterbridge') {
|
|
1966
|
-
this.
|
|
2049
|
+
this.matterbridgeFabricInformations = this.sanitizeFabricInformations(fabricInfo);
|
|
2050
|
+
this.matterbridgeSessionInformations = [];
|
|
1967
2051
|
this.matterbridgePaired = true;
|
|
1968
2052
|
}
|
|
1969
2053
|
if (pluginName !== 'Matterbridge') {
|
|
1970
2054
|
const plugin = this.findPlugin(pluginName);
|
|
1971
2055
|
if (plugin) {
|
|
1972
|
-
plugin.
|
|
2056
|
+
plugin.fabricInformations = this.sanitizeFabricInformations(fabricInfo);
|
|
2057
|
+
plugin.sessionInformations = [];
|
|
1973
2058
|
plugin.paired = true;
|
|
1974
2059
|
}
|
|
1975
2060
|
}
|
|
1976
2061
|
await this.nodeContext?.set('plugins', await this.getBaseRegisteredPlugins());
|
|
1977
2062
|
}
|
|
1978
2063
|
}
|
|
2064
|
+
/**
|
|
2065
|
+
* Sanitizes the fabric information by converting bigint properties to string cause res..
|
|
2066
|
+
*
|
|
2067
|
+
* @param fabricInfo - The array of exposed fabric information objects.
|
|
2068
|
+
* @returns An array of sanitized exposed fabric information objects.
|
|
2069
|
+
*/
|
|
2070
|
+
sanitizeFabricInformations(fabricInfo) {
|
|
2071
|
+
return fabricInfo.map((info) => {
|
|
2072
|
+
return {
|
|
2073
|
+
fabricIndex: info.fabricIndex,
|
|
2074
|
+
fabricId: info.fabricId.toString(),
|
|
2075
|
+
nodeId: info.nodeId.toString(),
|
|
2076
|
+
rootNodeId: info.rootNodeId.toString(),
|
|
2077
|
+
rootVendorId: info.rootVendorId,
|
|
2078
|
+
rootVendorName: this.getVendorIdName(info.rootVendorId),
|
|
2079
|
+
label: info.label,
|
|
2080
|
+
};
|
|
2081
|
+
});
|
|
2082
|
+
}
|
|
2083
|
+
/**
|
|
2084
|
+
* Sanitizes the session information by converting bigint properties to string.
|
|
2085
|
+
*
|
|
2086
|
+
* @param sessionInfo - The array of session information objects.
|
|
2087
|
+
* @returns An array of sanitized session information objects.
|
|
2088
|
+
*/
|
|
2089
|
+
sanitizeSessionInformation(sessionInfo) {
|
|
2090
|
+
return sessionInfo.map((info) => {
|
|
2091
|
+
return {
|
|
2092
|
+
name: info.name,
|
|
2093
|
+
nodeId: info.nodeId.toString(),
|
|
2094
|
+
peerNodeId: info.peerNodeId.toString(),
|
|
2095
|
+
fabric: info.fabric
|
|
2096
|
+
? {
|
|
2097
|
+
fabricIndex: info.fabric.fabricIndex,
|
|
2098
|
+
fabricId: info.fabric.fabricId.toString(),
|
|
2099
|
+
nodeId: info.fabric.nodeId.toString(),
|
|
2100
|
+
rootNodeId: info.fabric.rootNodeId.toString(),
|
|
2101
|
+
rootVendorId: info.fabric.rootVendorId,
|
|
2102
|
+
rootVendorName: this.getVendorIdName(info.fabric.rootVendorId),
|
|
2103
|
+
label: info.fabric.label,
|
|
2104
|
+
}
|
|
2105
|
+
: undefined,
|
|
2106
|
+
isPeerActive: info.isPeerActive,
|
|
2107
|
+
secure: info.secure,
|
|
2108
|
+
lastInteractionTimestamp: info.lastInteractionTimestamp,
|
|
2109
|
+
lastActiveTimestamp: info.lastActiveTimestamp,
|
|
2110
|
+
numberOfActiveSubscriptions: info.numberOfActiveSubscriptions,
|
|
2111
|
+
};
|
|
2112
|
+
});
|
|
2113
|
+
}
|
|
1979
2114
|
/**
|
|
1980
2115
|
* Finds a plugin by its name.
|
|
1981
2116
|
*
|
|
@@ -2062,6 +2197,9 @@ export class Matterbridge extends EventEmitter {
|
|
|
2062
2197
|
case 4742:
|
|
2063
2198
|
vendorName = '(eWeLink)';
|
|
2064
2199
|
break;
|
|
2200
|
+
case 65521:
|
|
2201
|
+
vendorName = '(PythonMatterServer)';
|
|
2202
|
+
break;
|
|
2065
2203
|
default:
|
|
2066
2204
|
vendorName = '(unknown)';
|
|
2067
2205
|
break;
|
|
@@ -2118,9 +2256,9 @@ export class Matterbridge extends EventEmitter {
|
|
|
2118
2256
|
reachable: true,
|
|
2119
2257
|
},
|
|
2120
2258
|
activeSessionsChangedCallback: (fabricIndex) => {
|
|
2121
|
-
const
|
|
2259
|
+
const sessionInformations = commissioningServer.getActiveSessionInformation(fabricIndex);
|
|
2122
2260
|
let connected = false;
|
|
2123
|
-
|
|
2261
|
+
sessionInformations.forEach((session) => {
|
|
2124
2262
|
this.log.info(`*Active session changed on fabric ${zb}${fabricIndex}${nf} id ${zb}${session.fabric?.fabricId}${nf} vendor ${zb}${session.fabric?.rootVendorId}${nf} ${this.getVendorIdName(session.fabric?.rootVendorId)} ${session.fabric?.label} for ${plg}${pluginName}${nf}`, debugStringify(session));
|
|
2125
2263
|
if (session.isPeerActive === true && session.secure === true && session.numberOfActiveSubscriptions >= 1) {
|
|
2126
2264
|
this.log.info(`*Controller ${zb}${session.fabric?.rootVendorId}${nf} ${this.getVendorIdName(session.fabric?.rootVendorId)} ${session.fabric?.label} connected to ${plg}${pluginName}${nf} on session ${session.name}`);
|
|
@@ -2131,12 +2269,14 @@ export class Matterbridge extends EventEmitter {
|
|
|
2131
2269
|
if (this.bridgeMode === 'bridge') {
|
|
2132
2270
|
this.matterbridgePaired = true;
|
|
2133
2271
|
this.matterbridgeConnected = true;
|
|
2272
|
+
this.matterbridgeSessionInformations = this.sanitizeSessionInformation(sessionInformations);
|
|
2134
2273
|
}
|
|
2135
2274
|
if (this.bridgeMode === 'childbridge') {
|
|
2136
2275
|
const plugin = this.findPlugin(pluginName);
|
|
2137
2276
|
if (plugin) {
|
|
2138
2277
|
plugin.paired = true;
|
|
2139
2278
|
plugin.connected = true;
|
|
2279
|
+
plugin.sessionInformations = this.sanitizeSessionInformation(sessionInformations);
|
|
2140
2280
|
}
|
|
2141
2281
|
}
|
|
2142
2282
|
setTimeout(() => {
|
|
@@ -2179,7 +2319,8 @@ export class Matterbridge extends EventEmitter {
|
|
|
2179
2319
|
await commissioningServer.factoryReset();
|
|
2180
2320
|
if (pluginName === 'Matterbridge') {
|
|
2181
2321
|
await this.matterbridgeContext?.clearAll();
|
|
2182
|
-
this.
|
|
2322
|
+
this.matterbridgeFabricInformations = [];
|
|
2323
|
+
this.matterbridgeSessionInformations = [];
|
|
2183
2324
|
this.matterbridgePaired = false;
|
|
2184
2325
|
this.matterbridgeConnected = false;
|
|
2185
2326
|
}
|
|
@@ -2187,14 +2328,29 @@ export class Matterbridge extends EventEmitter {
|
|
|
2187
2328
|
for (const plugin of this.registeredPlugins) {
|
|
2188
2329
|
if (plugin.name === pluginName) {
|
|
2189
2330
|
await plugin.platform?.onShutdown('Commissioning removed by the controller');
|
|
2190
|
-
plugin.
|
|
2331
|
+
plugin.fabricInformations = [];
|
|
2332
|
+
plugin.sessionInformations = [];
|
|
2191
2333
|
plugin.paired = false;
|
|
2192
2334
|
plugin.connected = false;
|
|
2193
2335
|
await plugin.storageContext?.clearAll();
|
|
2194
2336
|
}
|
|
2195
2337
|
}
|
|
2196
2338
|
}
|
|
2197
|
-
this.log.warn(`*Restart to activate the pairing for ${plg}${pluginName}${wr}
|
|
2339
|
+
this.log.warn(`*Restart to activate the pairing for ${plg}${pluginName}${wr}.`);
|
|
2340
|
+
}
|
|
2341
|
+
else {
|
|
2342
|
+
const fabricInfo = commissioningServer.getCommissionedFabricInformation();
|
|
2343
|
+
if (pluginName === 'Matterbridge') {
|
|
2344
|
+
this.matterbridgeFabricInformations = this.sanitizeFabricInformations(fabricInfo);
|
|
2345
|
+
this.matterbridgePaired = true;
|
|
2346
|
+
}
|
|
2347
|
+
else {
|
|
2348
|
+
const plugin = this.findPlugin(pluginName);
|
|
2349
|
+
if (plugin) {
|
|
2350
|
+
plugin.fabricInformations = this.sanitizeFabricInformations(fabricInfo);
|
|
2351
|
+
plugin.paired = true;
|
|
2352
|
+
}
|
|
2353
|
+
}
|
|
2198
2354
|
}
|
|
2199
2355
|
},
|
|
2200
2356
|
});
|
|
@@ -2549,7 +2705,8 @@ export class Matterbridge extends EventEmitter {
|
|
|
2549
2705
|
configured: plugin.configured,
|
|
2550
2706
|
paired: plugin.paired,
|
|
2551
2707
|
connected: plugin.connected,
|
|
2552
|
-
|
|
2708
|
+
fabricInformations: plugin.fabricInformations,
|
|
2709
|
+
sessionInformations: plugin.sessionInformations,
|
|
2553
2710
|
registeredDevices: plugin.registeredDevices,
|
|
2554
2711
|
addedDevices: plugin.addedDevices,
|
|
2555
2712
|
qrPairingCode: plugin.qrPairingCode,
|
|
@@ -2773,43 +2930,6 @@ export class Matterbridge extends EventEmitter {
|
|
|
2773
2930
|
this.webSocketServer.on('error', (ws, error) => {
|
|
2774
2931
|
this.log.error(`WebSocketServer error: ${error}`);
|
|
2775
2932
|
});
|
|
2776
|
-
/*
|
|
2777
|
-
// Create a WebSocket server
|
|
2778
|
-
const wssPort = 8284;
|
|
2779
|
-
const wssHost = `ws://${this.systemInformation.ipv4Address}:${wssPort}`;
|
|
2780
|
-
this.webSocketServer = new WebSocketServer({ port: wssPort, host: this.systemInformation.ipv4Address });
|
|
2781
|
-
this.log.debug(`WebSocket server created on ${UNDERLINE}${wssHost}${UNDERLINEOFF}${rs}`);
|
|
2782
|
-
|
|
2783
|
-
this.webSocketServer.on('listening', () => {
|
|
2784
|
-
this.log.info(`WebSocketServer is listening on ${UNDERLINE}${wssHost}${UNDERLINEOFF}${rs}`);
|
|
2785
|
-
return;
|
|
2786
|
-
});
|
|
2787
|
-
*/
|
|
2788
|
-
/*
|
|
2789
|
-
// Serve React build directory
|
|
2790
|
-
this.expressApp = express();
|
|
2791
|
-
this.expressApp.use(express.static(path.join(this.rootDirectory, 'frontend/build')));
|
|
2792
|
-
|
|
2793
|
-
// Listen on HTTP
|
|
2794
|
-
this.expressServer = this.expressApp.listen(port, () => {
|
|
2795
|
-
this.log.info(`The frontend is listening on ${UNDERLINE}http://${this.systemInformation.ipv4Address}:${port}${UNDERLINEOFF}${rs}`);
|
|
2796
|
-
this.log.debug(`The frontend is listening on ${UNDERLINE}http://[${this.systemInformation.ipv6Address}]:${port}${UNDERLINEOFF}${rs}`);
|
|
2797
|
-
});
|
|
2798
|
-
|
|
2799
|
-
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
2800
|
-
this.expressServer.on('error', (error: any) => {
|
|
2801
|
-
this.log.error(`Frontend error listening on ${UNDERLINE}http://${this.systemInformation.ipv4Address}:${port}${UNDERLINEOFF}${rs}`);
|
|
2802
|
-
switch (error.code) {
|
|
2803
|
-
case 'EACCES':
|
|
2804
|
-
this.log.error(`Port ${port} requires elevated privileges`);
|
|
2805
|
-
break;
|
|
2806
|
-
case 'EADDRINUSE':
|
|
2807
|
-
this.log.error(`Port ${port} is already in use`);
|
|
2808
|
-
break;
|
|
2809
|
-
}
|
|
2810
|
-
process.exit(1);
|
|
2811
|
-
});
|
|
2812
|
-
*/
|
|
2813
2933
|
// Endpoint to validate login code
|
|
2814
2934
|
this.expressApp.post('/api/login', express.json(), async (req, res) => {
|
|
2815
2935
|
const { password } = req.body;
|
|
@@ -2856,9 +2976,11 @@ export class Matterbridge extends EventEmitter {
|
|
|
2856
2976
|
this.matterbridgeInformation.bridgeMode = this.bridgeMode;
|
|
2857
2977
|
this.matterbridgeInformation.restartMode = this.restartMode;
|
|
2858
2978
|
this.matterbridgeInformation.debugEnabled = this.debugEnabled;
|
|
2979
|
+
this.matterbridgeInformation.matterLoggerLevel = Logger.defaultLogLevel;
|
|
2859
2980
|
this.matterbridgeInformation.matterbridgePaired = this.matterbridgePaired;
|
|
2860
2981
|
this.matterbridgeInformation.matterbridgeConnected = this.matterbridgeConnected;
|
|
2861
|
-
|
|
2982
|
+
this.matterbridgeInformation.matterbridgeFabricInformations = this.matterbridgeFabricInformations;
|
|
2983
|
+
this.matterbridgeInformation.matterbridgeSessionInformations = this.matterbridgeSessionInformations;
|
|
2862
2984
|
const response = { wssHost, qrPairingCode, manualPairingCode, systemInformation: this.systemInformation, matterbridgeInformation: this.matterbridgeInformation };
|
|
2863
2985
|
// this.log.debug('Response:', debugStringify(response));
|
|
2864
2986
|
res.json(response);
|
|
@@ -2989,42 +3111,39 @@ export class Matterbridge extends EventEmitter {
|
|
|
2989
3111
|
this.log.debug('setpassword', param, password);
|
|
2990
3112
|
await this.nodeContext?.set('password', password);
|
|
2991
3113
|
}
|
|
2992
|
-
// Handle the command
|
|
2993
|
-
if (command === '
|
|
2994
|
-
this.log.debug('
|
|
3114
|
+
// Handle the command setmbloglevel from Settings
|
|
3115
|
+
if (command === 'setmbloglevel') {
|
|
3116
|
+
this.log.debug('Matterbridge log level:', param);
|
|
2995
3117
|
if (param === 'Debug') {
|
|
2996
3118
|
this.log.setLogDebug(true);
|
|
2997
3119
|
this.debugEnabled = true;
|
|
2998
|
-
Logger.defaultLogLevel = Level.DEBUG;
|
|
2999
3120
|
}
|
|
3000
3121
|
else if (param === 'Info') {
|
|
3001
3122
|
this.log.setLogDebug(false);
|
|
3002
3123
|
this.debugEnabled = false;
|
|
3124
|
+
}
|
|
3125
|
+
}
|
|
3126
|
+
// Handle the command setmbloglevel from Settings
|
|
3127
|
+
if (command === 'setmjloglevel') {
|
|
3128
|
+
this.log.debug('Matter.js log level::', param);
|
|
3129
|
+
if (param === 'Debug') {
|
|
3130
|
+
Logger.defaultLogLevel = Level.DEBUG;
|
|
3131
|
+
}
|
|
3132
|
+
else if (param === 'Info') {
|
|
3003
3133
|
Logger.defaultLogLevel = Level.INFO;
|
|
3004
3134
|
}
|
|
3005
3135
|
else if (param === 'Notice') {
|
|
3006
|
-
this.log.setLogDebug(false);
|
|
3007
|
-
this.debugEnabled = false;
|
|
3008
3136
|
Logger.defaultLogLevel = Level.NOTICE;
|
|
3009
3137
|
}
|
|
3010
3138
|
else if (param === 'Warn') {
|
|
3011
|
-
this.log.setLogDebug(false);
|
|
3012
|
-
this.debugEnabled = false;
|
|
3013
3139
|
Logger.defaultLogLevel = Level.WARN;
|
|
3014
3140
|
}
|
|
3015
3141
|
else if (param === 'Error') {
|
|
3016
|
-
this.log.setLogDebug(false);
|
|
3017
|
-
this.debugEnabled = false;
|
|
3018
3142
|
Logger.defaultLogLevel = Level.ERROR;
|
|
3019
3143
|
}
|
|
3020
3144
|
else if (param === 'Fatal') {
|
|
3021
|
-
this.log.setLogDebug(false);
|
|
3022
|
-
this.debugEnabled = false;
|
|
3023
3145
|
Logger.defaultLogLevel = Level.FATAL;
|
|
3024
3146
|
}
|
|
3025
|
-
this.registeredPlugins.forEach((plugin) => {
|
|
3026
|
-
plugin.platform?.log.setLogDebug(this.debugEnabled);
|
|
3027
|
-
});
|
|
3028
3147
|
}
|
|
3029
3148
|
// Handle the command unregister from Settings
|
|
3030
3149
|
if (command === 'unregister') {
|