matterbridge 1.1.11 → 1.2.0
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 +18 -3
- package/README.md +59 -14
- package/dist/AirQualityCluster.d.ts.map +1 -1
- package/dist/AirQualityCluster.js +1 -10
- package/dist/AirQualityCluster.js.map +1 -1
- package/dist/index.d.ts +0 -1
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +0 -1
- package/dist/index.js.map +1 -1
- package/dist/matterbridge.d.ts +90 -14
- package/dist/matterbridge.d.ts.map +1 -1
- package/dist/matterbridge.js +249 -90
- package/dist/matterbridge.js.map +1 -1
- package/dist/matterbridgeAccessoryPlatform.d.ts +5 -7
- package/dist/matterbridgeAccessoryPlatform.d.ts.map +1 -1
- package/dist/matterbridgeAccessoryPlatform.js +6 -8
- package/dist/matterbridgeAccessoryPlatform.js.map +1 -1
- package/dist/matterbridgeDevice.d.ts +66 -1
- package/dist/matterbridgeDevice.d.ts.map +1 -1
- package/dist/matterbridgeDevice.js +128 -10
- package/dist/matterbridgeDevice.js.map +1 -1
- package/dist/matterbridgeDynamicPlatform.d.ts +5 -7
- package/dist/matterbridgeDynamicPlatform.d.ts.map +1 -1
- package/dist/matterbridgeDynamicPlatform.js +6 -8
- package/dist/matterbridgeDynamicPlatform.js.map +1 -1
- package/dist/matterbridgePlatform.d.ts +43 -0
- package/dist/matterbridgePlatform.d.ts.map +1 -0
- package/dist/matterbridgePlatform.js +45 -0
- package/dist/matterbridgePlatform.js.map +1 -0
- package/frontend/build/asset-manifest.json +6 -6
- package/frontend/build/index.html +1 -1
- package/frontend/build/static/css/{main.70102d98.css → main.b996bc4e.css} +2 -2
- package/frontend/build/static/css/main.b996bc4e.css.map +1 -0
- package/frontend/build/static/js/{main.5d39b100.js → main.657bca15.js} +3 -3
- package/frontend/build/static/js/main.657bca15.js.map +1 -0
- package/package.json +12 -10
- package/dist/ColorControlServer.d.ts +0 -86
- package/dist/ColorControlServer.d.ts.map +0 -1
- package/dist/ColorControlServer.js +0 -102
- package/dist/ColorControlServer.js.map +0 -1
- package/frontend/build/static/css/main.70102d98.css.map +0 -1
- package/frontend/build/static/js/main.5d39b100.js.map +0 -1
- /package/frontend/build/static/js/{main.5d39b100.js.LICENSE.txt → main.657bca15.js.LICENSE.txt} +0 -0
package/dist/matterbridge.js
CHANGED
|
@@ -4,7 +4,7 @@
|
|
|
4
4
|
* @file matterbridge.ts
|
|
5
5
|
* @author Luca Liguori
|
|
6
6
|
* @date 2023-12-29
|
|
7
|
-
* @version 1.
|
|
7
|
+
* @version 1.2.0
|
|
8
8
|
*
|
|
9
9
|
* Copyright 2023, 2024 Luca Liguori.
|
|
10
10
|
*
|
|
@@ -102,7 +102,9 @@ export class Matterbridge extends EventEmitter {
|
|
|
102
102
|
/**
|
|
103
103
|
* Loads an instance of the Matterbridge class.
|
|
104
104
|
* If an instance already exists, return that instance.
|
|
105
|
-
*
|
|
105
|
+
*
|
|
106
|
+
* @param initialize - Whether to initialize the Matterbridge instance after loading.
|
|
107
|
+
* @returns The loaded Matterbridge instance.
|
|
106
108
|
*/
|
|
107
109
|
static async loadInstance(initialize = false) {
|
|
108
110
|
if (!Matterbridge.instance) {
|
|
@@ -129,10 +131,6 @@ export class Matterbridge extends EventEmitter {
|
|
|
129
131
|
* @returns A Promise that resolves when the initialization is complete.
|
|
130
132
|
*/
|
|
131
133
|
async initialize() {
|
|
132
|
-
/*
|
|
133
|
-
const wtf = await import('wtfnode');
|
|
134
|
-
wtf.dump();
|
|
135
|
-
*/
|
|
136
134
|
// Display the help
|
|
137
135
|
if (hasParameter('help')) {
|
|
138
136
|
// eslint-disable-next-line no-console
|
|
@@ -163,7 +161,7 @@ export class Matterbridge extends EventEmitter {
|
|
|
163
161
|
await this.logNodeAndSystemInfo();
|
|
164
162
|
this.log.info(
|
|
165
163
|
// eslint-disable-next-line max-len
|
|
166
|
-
`Matterbridge version ${this.matterbridgeVersion} mode ${hasParameter('bridge') ? 'bridge' : ''}${hasParameter('childbridge') ? 'childbridge' : ''} running on ${this.systemInformation.osType} ${this.systemInformation.osRelease} ${this.systemInformation.osPlatform} ${this.systemInformation.osArch}`);
|
|
164
|
+
`Matterbridge version ${this.matterbridgeVersion} mode ${hasParameter('bridge') ? 'bridge' : ''}${hasParameter('childbridge') ? 'childbridge' : ''}${hasParameter('controller') ? 'controller' : ''} running on ${this.systemInformation.osType} ${this.systemInformation.osRelease} ${this.systemInformation.osPlatform} ${this.systemInformation.osArch}`);
|
|
167
165
|
// check node version and throw error
|
|
168
166
|
requireMinNodeVersion(18);
|
|
169
167
|
// register SIGINT SIGTERM signal handlers
|
|
@@ -282,12 +280,14 @@ export class Matterbridge extends EventEmitter {
|
|
|
282
280
|
this.bridgeMode = 'childbridge';
|
|
283
281
|
MatterbridgeDevice.bridgeMode = 'childbridge';
|
|
284
282
|
await this.testStartMatterBridge(); // No await do it asyncronously
|
|
283
|
+
return;
|
|
285
284
|
}
|
|
286
285
|
if (hasParameter('controller')) {
|
|
287
286
|
this.bridgeMode = 'controller';
|
|
288
287
|
this.log.info('Creating mattercontrollerContext: mattercontrollerContext');
|
|
289
288
|
this.mattercontrollerContext = this.storageManager?.createContext('mattercontrollerContext');
|
|
290
289
|
await this.startMatterBridge();
|
|
290
|
+
return;
|
|
291
291
|
}
|
|
292
292
|
if (hasParameter('bridge')) {
|
|
293
293
|
this.bridgeMode = 'bridge';
|
|
@@ -306,6 +306,7 @@ export class Matterbridge extends EventEmitter {
|
|
|
306
306
|
this.loadPlugin(plugin); // No await do it asyncronously
|
|
307
307
|
}
|
|
308
308
|
await this.startMatterBridge();
|
|
309
|
+
return;
|
|
309
310
|
}
|
|
310
311
|
if (hasParameter('childbridge')) {
|
|
311
312
|
this.bridgeMode = 'childbridge';
|
|
@@ -324,8 +325,14 @@ export class Matterbridge extends EventEmitter {
|
|
|
324
325
|
this.loadPlugin(plugin, true, 'Matterbridge is starting'); // No await do it asyncronously
|
|
325
326
|
}
|
|
326
327
|
await this.startMatterBridge();
|
|
328
|
+
return;
|
|
327
329
|
}
|
|
328
330
|
}
|
|
331
|
+
/**
|
|
332
|
+
* Resolves the name of a plugin by loading and parsing its package.json file.
|
|
333
|
+
* @param pluginPath - The path to the plugin or the path to the plugin's package.json file.
|
|
334
|
+
* @returns The path to the resolved package.json file, or null if the package.json file is not found or does not contain a name.
|
|
335
|
+
*/
|
|
329
336
|
async resolvePluginName(pluginPath) {
|
|
330
337
|
if (!pluginPath.endsWith('package.json'))
|
|
331
338
|
pluginPath = path.join(pluginPath, 'package.json');
|
|
@@ -451,14 +458,14 @@ export class Matterbridge extends EventEmitter {
|
|
|
451
458
|
* Restarts the process by spawning a new process and exiting the current process.
|
|
452
459
|
*/
|
|
453
460
|
async restartProcess() {
|
|
454
|
-
//this.log.info('Restarting still not implemented');
|
|
455
|
-
//return;
|
|
456
461
|
await this.cleanup('restarting...', true);
|
|
457
462
|
this.hasCleanupStarted = false;
|
|
458
463
|
}
|
|
459
464
|
/**
|
|
460
|
-
*
|
|
461
|
-
* @param message - The
|
|
465
|
+
* Cleans up the Matterbridge instance.
|
|
466
|
+
* @param message - The cleanup message.
|
|
467
|
+
* @param restart - Indicates whether to restart the instance after cleanup. Default is `false`.
|
|
468
|
+
* @returns A promise that resolves when the cleanup is completed.
|
|
462
469
|
*/
|
|
463
470
|
async cleanup(message, restart = false) {
|
|
464
471
|
if (!this.hasCleanupStarted) {
|
|
@@ -468,8 +475,10 @@ export class Matterbridge extends EventEmitter {
|
|
|
468
475
|
process.removeAllListeners('SIGTERM');
|
|
469
476
|
// Calling the shutdown functions with a reason
|
|
470
477
|
for (const plugin of this.registeredPlugins) {
|
|
471
|
-
if (plugin.platform)
|
|
478
|
+
if (plugin.platform) {
|
|
472
479
|
await plugin.platform.onShutdown('Matterbridge is closing: ' + message);
|
|
480
|
+
await this.savePluginConfig(plugin);
|
|
481
|
+
}
|
|
473
482
|
}
|
|
474
483
|
// Set reachability to false
|
|
475
484
|
/*
|
|
@@ -565,14 +574,14 @@ export class Matterbridge extends EventEmitter {
|
|
|
565
574
|
*/
|
|
566
575
|
async addDevice(pluginName, device) {
|
|
567
576
|
if (this.bridgeMode === 'bridge' && !this.matterAggregator) {
|
|
568
|
-
this.log.error(`Adding device ${dev}${device.
|
|
577
|
+
this.log.error(`Adding device ${dev}${device.deviceName}${er} (${dev}${device.name}${er}) for plugin ${plg}${pluginName}${er} error: matterAggregator not found`);
|
|
569
578
|
return;
|
|
570
579
|
}
|
|
571
|
-
this.log.debug(`Adding device ${dev}${device.
|
|
580
|
+
this.log.debug(`Adding device ${dev}${device.deviceName}${db} (${dev}${device.name}${db}) for plugin ${plg}${pluginName}${db}`);
|
|
572
581
|
// Check if the plugin is registered
|
|
573
582
|
const plugin = this.registeredPlugins.find((plugin) => plugin.name === pluginName);
|
|
574
583
|
if (!plugin) {
|
|
575
|
-
this.log.error(`Error adding device ${dev}${device.
|
|
584
|
+
this.log.error(`Error adding device ${dev}${device.deviceName}${er} (${dev}${device.name}${er}) plugin ${plg}${pluginName}${er} not found`);
|
|
576
585
|
return;
|
|
577
586
|
}
|
|
578
587
|
// Register and add the device to matterbridge aggregator in bridge mode
|
|
@@ -583,14 +592,14 @@ export class Matterbridge extends EventEmitter {
|
|
|
583
592
|
plugin.registeredDevices++;
|
|
584
593
|
if (plugin.addedDevices !== undefined)
|
|
585
594
|
plugin.addedDevices++;
|
|
586
|
-
this.log.info(`Added and registered device(${plugin.registeredDevices}/${plugin.addedDevices}) ${dev}${device.
|
|
595
|
+
this.log.info(`Added and registered device (${plugin.registeredDevices}/${plugin.addedDevices}) ${dev}${device.deviceName}${nf} (${dev}${device.name}${nf}) for plugin ${plg}${pluginName}${nf}`);
|
|
587
596
|
}
|
|
588
597
|
// Only register the device in childbridge mode
|
|
589
598
|
if (this.bridgeMode === 'childbridge') {
|
|
590
599
|
this.registeredDevices.push({ plugin: pluginName, device, added: false });
|
|
591
600
|
if (plugin.registeredDevices !== undefined)
|
|
592
601
|
plugin.registeredDevices++;
|
|
593
|
-
this.log.info(`Registered device ${dev}${device.
|
|
602
|
+
this.log.info(`Registered device ${dev}${device.deviceName}${nf} (${dev}${device.name}${nf}) for plugin ${plg}${pluginName}${nf}`);
|
|
594
603
|
}
|
|
595
604
|
}
|
|
596
605
|
/**
|
|
@@ -601,14 +610,14 @@ export class Matterbridge extends EventEmitter {
|
|
|
601
610
|
*/
|
|
602
611
|
async addBridgedDevice(pluginName, device) {
|
|
603
612
|
if (this.bridgeMode === 'bridge' && !this.matterAggregator) {
|
|
604
|
-
this.log.error(`Adding bridged device ${dev}${device.
|
|
613
|
+
this.log.error(`Adding bridged device ${dev}${device.deviceName}${er} (${dev}${device.name}${er}) for plugin ${plg}${pluginName}${er} error: matterAggregator not found`);
|
|
605
614
|
return;
|
|
606
615
|
}
|
|
607
|
-
this.log.debug(`Adding bridged device ${
|
|
616
|
+
this.log.debug(`Adding bridged device ${dev}${device.deviceName}${db} (${dev}${device.name}${db}) for plugin ${plg}${pluginName}${db}`);
|
|
608
617
|
// Check if the plugin is registered
|
|
609
618
|
const plugin = this.registeredPlugins.find((plugin) => plugin.name === pluginName);
|
|
610
619
|
if (!plugin) {
|
|
611
|
-
this.log.error(`Error adding bridged device ${dev}${device.
|
|
620
|
+
this.log.error(`Error adding bridged device ${dev}${device.deviceName}${er} (${dev}${device.name}${er}) plugin ${plg}${pluginName}${er} not found`);
|
|
612
621
|
return;
|
|
613
622
|
}
|
|
614
623
|
// Register and add the device to matterbridge aggregator in bridge mode
|
|
@@ -619,34 +628,40 @@ export class Matterbridge extends EventEmitter {
|
|
|
619
628
|
plugin.registeredDevices++;
|
|
620
629
|
if (plugin.addedDevices !== undefined)
|
|
621
630
|
plugin.addedDevices++;
|
|
622
|
-
this.log.info(`Added and registered bridged device(${plugin.registeredDevices}/${plugin.addedDevices}) ${dev}${device.
|
|
631
|
+
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}`);
|
|
623
632
|
}
|
|
624
633
|
// Only register the device in childbridge mode
|
|
625
634
|
if (this.bridgeMode === 'childbridge') {
|
|
626
635
|
this.registeredDevices.push({ plugin: pluginName, device, added: false });
|
|
627
636
|
if (plugin.registeredDevices !== undefined)
|
|
628
637
|
plugin.registeredDevices++;
|
|
629
|
-
this.log.info(`Registered bridged device ${dev}${device.
|
|
638
|
+
this.log.info(`Registered bridged device ${dev}${device.deviceName}${nf} (${dev}${device.name}${nf}) for plugin ${plg}${pluginName}${nf}`);
|
|
630
639
|
}
|
|
631
640
|
}
|
|
641
|
+
/**
|
|
642
|
+
* Removes a bridged device from the Matterbridge.
|
|
643
|
+
* @param pluginName - The name of the plugin.
|
|
644
|
+
* @param device - The device to be removed.
|
|
645
|
+
* @returns A Promise that resolves when the device is successfully removed.
|
|
646
|
+
*/
|
|
632
647
|
async removeBridgedDevice(pluginName, device) {
|
|
633
648
|
if (this.bridgeMode === 'bridge' && !this.matterAggregator) {
|
|
634
|
-
this.log.error(`Removing bridged device ${dev}${device.
|
|
649
|
+
this.log.error(`Removing bridged device ${dev}${device.deviceName}${er} (${dev}${device.name}${er}) for plugin ${plg}${pluginName}${er} error: matterAggregator not found`);
|
|
635
650
|
return;
|
|
636
651
|
}
|
|
637
|
-
this.log.debug(`Removing bridged device ${
|
|
652
|
+
this.log.debug(`Removing bridged device ${dev}${device.deviceName}${db} (${dev}${device.name}${db}) for plugin ${plg}${pluginName}${db}`);
|
|
638
653
|
// Check if the plugin is registered
|
|
639
654
|
const plugin = this.findPlugin(pluginName);
|
|
640
655
|
if (!plugin) {
|
|
641
|
-
this.log.error(`Error removing bridged device ${dev}${device.
|
|
656
|
+
this.log.error(`Error removing bridged device ${dev}${device.deviceName}${er} (${dev}${device.name}${er}) plugin ${plg}${pluginName}${er} not found`);
|
|
642
657
|
return;
|
|
643
658
|
}
|
|
644
659
|
if (this.bridgeMode === 'childbridge' && !plugin.aggregator) {
|
|
645
|
-
this.log.error(`Error removing bridged device ${dev}${device.
|
|
660
|
+
this.log.error(`Error removing bridged device ${dev}${device.deviceName}${er} (${dev}${device.name}${er}) plugin ${plg}${pluginName}${er} aggregator not found`);
|
|
646
661
|
return;
|
|
647
662
|
}
|
|
648
663
|
if (this.bridgeMode === 'childbridge' && !plugin.connected) {
|
|
649
|
-
this.log.
|
|
664
|
+
this.log.warn(`Not removing bridged device ${dev}${device.deviceName}${wr} (${dev}${device.name}${wr}) plugin ${plg}${pluginName}${wr} not connected`);
|
|
650
665
|
return;
|
|
651
666
|
}
|
|
652
667
|
// Register and add the device to matterbridge aggregator in bridge mode
|
|
@@ -662,12 +677,12 @@ export class Matterbridge extends EventEmitter {
|
|
|
662
677
|
plugin.registeredDevices--;
|
|
663
678
|
if (plugin.addedDevices !== undefined)
|
|
664
679
|
plugin.addedDevices--;
|
|
665
|
-
this.log.info(`
|
|
680
|
+
this.log.info(`Removed bridged device(${plugin.registeredDevices}/${plugin.addedDevices}) ${dev}${device.deviceName}${nf} (${dev}${device.name}${nf}) for plugin ${plg}${pluginName}${nf}`);
|
|
666
681
|
}
|
|
667
682
|
// Only register the device in childbridge mode
|
|
668
683
|
if (this.bridgeMode === 'childbridge') {
|
|
669
684
|
if (plugin.type === 'AccessoryPlatform') {
|
|
670
|
-
this.log.warn(`Removing bridged device ${dev}${device.
|
|
685
|
+
this.log.warn(`Removing bridged device ${dev}${device.deviceName}${wr} (${dev}${device.name}${wr}) for plugin ${plg}${pluginName}${wr} error: AccessoryPlatform not supported in childbridge mode`);
|
|
671
686
|
}
|
|
672
687
|
else if (plugin.type === 'DynamicPlatform') {
|
|
673
688
|
this.registeredDevices.forEach((registeredDevice, index) => {
|
|
@@ -678,11 +693,11 @@ export class Matterbridge extends EventEmitter {
|
|
|
678
693
|
});
|
|
679
694
|
plugin.aggregator.removeBridgedDevice(device);
|
|
680
695
|
}
|
|
696
|
+
this.log.info(`Removed bridged device(${plugin.registeredDevices}/${plugin.addedDevices}) ${dev}${device.deviceName}${nf} (${dev}${device.name}${nf}) for plugin ${plg}${pluginName}${nf}`);
|
|
681
697
|
if (plugin.registeredDevices !== undefined)
|
|
682
698
|
plugin.registeredDevices--;
|
|
683
699
|
if (plugin.addedDevices !== undefined)
|
|
684
700
|
plugin.addedDevices--;
|
|
685
|
-
this.log.info(`Removed bridged device(${plugin.registeredDevices}/${plugin.addedDevices}) ${dev}${device.name}-${device.deviceName}${nf} for plugin ${plg}${pluginName}${nf}`);
|
|
686
701
|
}
|
|
687
702
|
}
|
|
688
703
|
/**
|
|
@@ -826,6 +841,92 @@ export class Matterbridge extends EventEmitter {
|
|
|
826
841
|
}
|
|
827
842
|
*/
|
|
828
843
|
}
|
|
844
|
+
/**
|
|
845
|
+
* Loads the configuration for a plugin.
|
|
846
|
+
* If the configuration file exists, it reads the file and returns the parsed JSON data.
|
|
847
|
+
* If the configuration file does not exist, it creates a new file with default configuration and returns it.
|
|
848
|
+
* If any error occurs during file access or creation, it logs an error and rejects the promise with the error.
|
|
849
|
+
*
|
|
850
|
+
* @param plugin - The plugin for which to load the configuration.
|
|
851
|
+
* @returns A promise that resolves to the loaded or created configuration.
|
|
852
|
+
*/
|
|
853
|
+
async loadPluginConfig(plugin) {
|
|
854
|
+
const configFile = path.join(this.matterbridgeDirectory, `${plugin.name}.config.json`);
|
|
855
|
+
try {
|
|
856
|
+
await fs.access(configFile);
|
|
857
|
+
const data = await fs.readFile(configFile, 'utf8');
|
|
858
|
+
this.log.debug(`Config file found: ${configFile}.\nConfig:${rs}\n`, JSON.parse(data));
|
|
859
|
+
return JSON.parse(data);
|
|
860
|
+
}
|
|
861
|
+
catch (err) {
|
|
862
|
+
if (err instanceof Error) {
|
|
863
|
+
const nodeErr = err;
|
|
864
|
+
if (nodeErr.code === 'ENOENT') {
|
|
865
|
+
try {
|
|
866
|
+
await this.writeFile(configFile, JSON.stringify({ name: plugin.name, type: plugin.type }, null, 2));
|
|
867
|
+
this.log.debug(`Created config file: ${configFile}.\nConfig:${rs}\n`, { name: plugin.name, type: plugin.type });
|
|
868
|
+
return { name: plugin.name, type: plugin.type };
|
|
869
|
+
}
|
|
870
|
+
catch (err) {
|
|
871
|
+
this.log.error(`Error creating config file ${configFile}: ${err}`);
|
|
872
|
+
return Promise.reject(err);
|
|
873
|
+
}
|
|
874
|
+
}
|
|
875
|
+
else {
|
|
876
|
+
this.log.error(`Error accessing config file ${configFile}: ${err}`);
|
|
877
|
+
return Promise.reject(err);
|
|
878
|
+
}
|
|
879
|
+
}
|
|
880
|
+
return Promise.reject(err);
|
|
881
|
+
}
|
|
882
|
+
}
|
|
883
|
+
/**
|
|
884
|
+
* Saves the configuration of a registered plugin.
|
|
885
|
+
* @param {RegisteredPlugin} plugin - The plugin whose configuration needs to be saved.
|
|
886
|
+
* @returns {Promise<void>} - A promise that resolves when the configuration is successfully saved.
|
|
887
|
+
* @throws {Error} - If the plugin's configuration is not found or if there is an error while saving the configuration.
|
|
888
|
+
*/
|
|
889
|
+
async savePluginConfig(plugin) {
|
|
890
|
+
if (!plugin.platform?.config) {
|
|
891
|
+
this.log.error(`Error saving plugin ${plg}${plugin.name}${er} config: config not found`);
|
|
892
|
+
return Promise.reject(new Error(`Error saving plugin ${plg}${plugin.name}${er} config: config not found`));
|
|
893
|
+
}
|
|
894
|
+
const configFile = path.join(this.matterbridgeDirectory, `${plugin.name}.config.json`);
|
|
895
|
+
try {
|
|
896
|
+
await this.writeFile(configFile, JSON.stringify(plugin.platform.config, null, 2));
|
|
897
|
+
this.log.debug(`Saved config file: ${configFile}.\nConfig:${rs}\n`, plugin.platform.config);
|
|
898
|
+
}
|
|
899
|
+
catch (err) {
|
|
900
|
+
this.log.error(`Error saving plugin ${plg}${plugin.name}${er} config: ${err}`);
|
|
901
|
+
return Promise.reject(err);
|
|
902
|
+
}
|
|
903
|
+
}
|
|
904
|
+
/**
|
|
905
|
+
* Writes data to a file.
|
|
906
|
+
*
|
|
907
|
+
* @param {string} filePath - The path of the file to write to.
|
|
908
|
+
* @param {string} data - The data to write to the file.
|
|
909
|
+
* @returns {Promise<void>} - A promise that resolves when the data is successfully written to the file.
|
|
910
|
+
*/
|
|
911
|
+
async writeFile(filePath, data) {
|
|
912
|
+
// Write the data to a file
|
|
913
|
+
await fs
|
|
914
|
+
.writeFile(`${filePath}`, data, 'utf8')
|
|
915
|
+
.then(() => {
|
|
916
|
+
this.log.debug(`Successfully wrote to ${filePath}`);
|
|
917
|
+
})
|
|
918
|
+
.catch((error) => {
|
|
919
|
+
this.log.error(`Error writing to ${filePath}:`, error);
|
|
920
|
+
});
|
|
921
|
+
}
|
|
922
|
+
/**
|
|
923
|
+
* Starts a plugin.
|
|
924
|
+
*
|
|
925
|
+
* @param {RegisteredPlugin} plugin - The plugin to start.
|
|
926
|
+
* @param {string} [message] - Optional message to pass to the plugin's onStart method.
|
|
927
|
+
* @param {boolean} [configure=false] - Indicates whether to configure the plugin after starting.
|
|
928
|
+
* @returns {Promise<void>} A promise that resolves when the plugin is started successfully, or rejects with an error if starting the plugin fails.
|
|
929
|
+
*/
|
|
829
930
|
async startPlugin(plugin, message, configure = false) {
|
|
830
931
|
if (!plugin.loaded || !plugin.platform) {
|
|
831
932
|
this.log.error(`Plugin ${plg}${plugin.name}${er} not loaded or no platform`);
|
|
@@ -856,6 +957,12 @@ export class Matterbridge extends EventEmitter {
|
|
|
856
957
|
return Promise.reject(new Error(`Failed to start plugin ${plg}${plugin.name}${er}: ${err}`));
|
|
857
958
|
}
|
|
858
959
|
}
|
|
960
|
+
/**
|
|
961
|
+
* Configures a plugin.
|
|
962
|
+
*
|
|
963
|
+
* @param {RegisteredPlugin} plugin - The plugin to configure.
|
|
964
|
+
* @returns {Promise<void>} A promise that resolves when the plugin is configured successfully, or rejects with an error if configuration fails.
|
|
965
|
+
*/
|
|
859
966
|
async configurePlugin(plugin) {
|
|
860
967
|
if (!plugin.loaded || !plugin.started || !plugin.platform) {
|
|
861
968
|
this.log.error(`Plugin ${plg}${plugin.name}${er} not loaded or not started or not platform`);
|
|
@@ -884,6 +991,14 @@ export class Matterbridge extends EventEmitter {
|
|
|
884
991
|
return Promise.reject(new Error(`Failed to configure plugin ${plg}${plugin.name}${er}: ${err}`));
|
|
885
992
|
}
|
|
886
993
|
}
|
|
994
|
+
/**
|
|
995
|
+
* Loads a plugin and returns the corresponding MatterbridgePlatform instance.
|
|
996
|
+
* @param plugin - The plugin to load.
|
|
997
|
+
* @param start - Optional flag indicating whether to start the plugin after loading. Default is false.
|
|
998
|
+
* @param message - Optional message to pass to the plugin when starting.
|
|
999
|
+
* @returns A Promise that resolves to the loaded MatterbridgePlatform instance.
|
|
1000
|
+
* @throws An error if the plugin is not enabled, already loaded, or fails to load.
|
|
1001
|
+
*/
|
|
887
1002
|
async loadPlugin(plugin, start = false, message = '') {
|
|
888
1003
|
if (!plugin.enabled) {
|
|
889
1004
|
this.log.error(`Plugin ${plg}${plugin.name}${er} not enabled`);
|
|
@@ -906,8 +1021,10 @@ export class Matterbridge extends EventEmitter {
|
|
|
906
1021
|
this.log.debug(`Imported plugin ${plg}${plugin.name}${db} from ${pluginUrl.href}`);
|
|
907
1022
|
// Call the default export function of the plugin, passing this MatterBridge instance
|
|
908
1023
|
if (pluginInstance.default) {
|
|
909
|
-
const
|
|
1024
|
+
const config = await this.loadPluginConfig(plugin);
|
|
1025
|
+
const platform = pluginInstance.default(this, new AnsiLogger({ logName: plugin.description, logTimestampFormat: 4 /* TimestampFormat.TIME_MILLIS */, logDebug: this.debugEnabled }), config);
|
|
910
1026
|
platform.name = packageJson.name;
|
|
1027
|
+
platform.config = config;
|
|
911
1028
|
plugin.name = packageJson.name;
|
|
912
1029
|
plugin.description = packageJson.description;
|
|
913
1030
|
plugin.version = packageJson.version;
|
|
@@ -966,8 +1083,8 @@ export class Matterbridge extends EventEmitter {
|
|
|
966
1083
|
await this.matterServer.start();
|
|
967
1084
|
this.log.info('Matter server started');
|
|
968
1085
|
if (hasParameter('discover')) {
|
|
969
|
-
const discover = await this.commissioningController.discoverCommissionableDevices({ productId: 0x8000, deviceType: 0xfff1 });
|
|
970
|
-
console.log(discover);
|
|
1086
|
+
//const discover = await this.commissioningController.discoverCommissionableDevices({ productId: 0x8000, deviceType: 0xfff1 });
|
|
1087
|
+
//console.log(discover);
|
|
971
1088
|
}
|
|
972
1089
|
this.log.info(`Commissioning controller is already commisioned: ${this.commissioningController.isCommissioned()}`);
|
|
973
1090
|
const nodes = this.commissioningController.getCommissionedNodes();
|
|
@@ -979,11 +1096,17 @@ export class Matterbridge extends EventEmitter {
|
|
|
979
1096
|
// Plugins are loaded by loadPlugin on startup and plugin.loaded is set to true
|
|
980
1097
|
// Plugins are started and configured by callback when Matterbridge is commissioned
|
|
981
1098
|
this.log.debug(`Creating commissioning server context for ${plg}Matterbridge${db}`);
|
|
982
|
-
this.matterbridgeContext = this.createCommissioningServerContext('Matterbridge', 'Matterbridge', DeviceTypes.AGGREGATOR.code, 0xfff1, 'Matterbridge', 0x8000, 'Matterbridge
|
|
1099
|
+
this.matterbridgeContext = this.createCommissioningServerContext('Matterbridge', 'Matterbridge', DeviceTypes.AGGREGATOR.code, 0xfff1, 'Matterbridge', 0x8000, 'Matterbridge Aggregator');
|
|
983
1100
|
if (!this.matterbridgeContext) {
|
|
984
1101
|
this.log.error(`Error creating storage context for ${plg}Matterbridge${er}`);
|
|
985
1102
|
return;
|
|
986
1103
|
}
|
|
1104
|
+
if (!this.nodeContext) {
|
|
1105
|
+
this.log.error(`Node storage context undefined for ${plg}Matterbridge${er}`);
|
|
1106
|
+
return;
|
|
1107
|
+
}
|
|
1108
|
+
this.matterbridgeContext.set('softwareVersion', 1);
|
|
1109
|
+
this.matterbridgeContext.set('softwareVersionString', this.matterbridgeVersion);
|
|
987
1110
|
this.log.debug(`Creating commissioning server for ${plg}Matterbridge${db}`);
|
|
988
1111
|
this.commissioningServer = this.createCommisioningServer(this.matterbridgeContext, 'Matterbridge');
|
|
989
1112
|
this.log.debug(`Creating matter aggregator for ${plg}Matterbridge${db}`);
|
|
@@ -995,7 +1118,7 @@ export class Matterbridge extends EventEmitter {
|
|
|
995
1118
|
this.log.debug('Starting matter server...');
|
|
996
1119
|
await this.startMatterServer();
|
|
997
1120
|
this.log.info('Matter server started');
|
|
998
|
-
this.showCommissioningQRCode(this.commissioningServer, this.matterbridgeContext, 'Matterbridge');
|
|
1121
|
+
await this.showCommissioningQRCode(this.commissioningServer, this.matterbridgeContext, this.nodeContext, 'Matterbridge');
|
|
999
1122
|
}
|
|
1000
1123
|
if (this.bridgeMode === 'childbridge') {
|
|
1001
1124
|
// Plugins are loaded and started by loadPlugin on startup
|
|
@@ -1033,7 +1156,9 @@ export class Matterbridge extends EventEmitter {
|
|
|
1033
1156
|
await this.matterServer.addCommissioningServer(plugin.commissioningServer, { uniqueStorageKey: plugin.name });
|
|
1034
1157
|
}
|
|
1035
1158
|
if (plugin.type === 'DynamicPlatform') {
|
|
1036
|
-
plugin.storageContext = this.createCommissioningServerContext(plugin.name, 'Matterbridge
|
|
1159
|
+
plugin.storageContext = this.createCommissioningServerContext(plugin.name, 'Matterbridge', DeviceTypes.AGGREGATOR.code, 0xfff1, 'Matterbridge', 0x8000, 'Matterbridge Dynamic Platform');
|
|
1160
|
+
plugin.storageContext.set('softwareVersion', 1);
|
|
1161
|
+
plugin.storageContext.set('softwareVersionString', this.matterbridgeVersion);
|
|
1037
1162
|
plugin.commissioningServer = this.createCommisioningServer(plugin.storageContext, plugin.name);
|
|
1038
1163
|
this.log.debug(`Creating aggregator for plugin ${plg}${plugin.name}${db}`);
|
|
1039
1164
|
plugin.aggregator = this.createMatterAggregator(plugin.storageContext); // Generate serialNumber and uniqueId
|
|
@@ -1079,13 +1204,31 @@ export class Matterbridge extends EventEmitter {
|
|
|
1079
1204
|
await this.startMatterServer();
|
|
1080
1205
|
this.log.info('Matter server started');
|
|
1081
1206
|
for (const plugin of this.registeredPlugins) {
|
|
1082
|
-
|
|
1207
|
+
if (!plugin.enabled)
|
|
1208
|
+
continue;
|
|
1209
|
+
if (!plugin.commissioningServer) {
|
|
1210
|
+
this.log.error(`Commissioning server not found for plugin ${plg}${plugin.name}${er}`);
|
|
1211
|
+
continue;
|
|
1212
|
+
}
|
|
1213
|
+
if (!plugin.storageContext) {
|
|
1214
|
+
this.log.error(`Storage context not found for plugin ${plg}${plugin.name}${er}`);
|
|
1215
|
+
continue;
|
|
1216
|
+
}
|
|
1217
|
+
if (!plugin.nodeContext) {
|
|
1218
|
+
this.log.error(`Node storage context not found for plugin ${plg}${plugin.name}${er}`);
|
|
1219
|
+
continue;
|
|
1220
|
+
}
|
|
1221
|
+
await this.showCommissioningQRCode(plugin.commissioningServer, plugin.storageContext, plugin.nodeContext, plugin.name);
|
|
1083
1222
|
}
|
|
1084
1223
|
Logger.defaultLogLevel = this.debugEnabled ? Level.DEBUG : Level.INFO;
|
|
1085
1224
|
clearInterval(startMatterInterval);
|
|
1086
1225
|
}, 1000);
|
|
1087
1226
|
}
|
|
1088
1227
|
}
|
|
1228
|
+
/**
|
|
1229
|
+
* Starts the Matter server.
|
|
1230
|
+
* If the Matter server is not initialized, it logs an error and performs cleanup.
|
|
1231
|
+
*/
|
|
1089
1232
|
async startMatterServer() {
|
|
1090
1233
|
if (!this.matterServer) {
|
|
1091
1234
|
this.log.error('No matter server initialized');
|
|
@@ -1155,17 +1298,14 @@ export class Matterbridge extends EventEmitter {
|
|
|
1155
1298
|
return storageContext;
|
|
1156
1299
|
}
|
|
1157
1300
|
/**
|
|
1158
|
-
* Shows the commissioning QR code for a given
|
|
1159
|
-
*
|
|
1160
|
-
*
|
|
1161
|
-
*
|
|
1162
|
-
*
|
|
1163
|
-
*
|
|
1164
|
-
* @param commissioningServer - The commissioning server to show the QR code for.
|
|
1165
|
-
* @param storageContext - The storage context to store the pairing codes.
|
|
1166
|
-
* @param pluginName - The name of the commissioning server.
|
|
1301
|
+
* Shows the commissioning QR code for a given plugin.
|
|
1302
|
+
* @param {CommissioningServer} commissioningServer - The commissioning server instance.
|
|
1303
|
+
* @param {StorageContext} storageContext - The storage context instance.
|
|
1304
|
+
* @param {NodeStorage} nodeContext - The node storage instance.
|
|
1305
|
+
* @param {string} pluginName - The name of the plugin.
|
|
1306
|
+
* @returns {Promise<void>} - A promise that resolves when the QR code is shown.
|
|
1167
1307
|
*/
|
|
1168
|
-
async showCommissioningQRCode(commissioningServer, storageContext, pluginName) {
|
|
1308
|
+
async showCommissioningQRCode(commissioningServer, storageContext, nodeContext, pluginName) {
|
|
1169
1309
|
if (!commissioningServer || !storageContext || !pluginName)
|
|
1170
1310
|
return;
|
|
1171
1311
|
if (!commissioningServer.isCommissioned()) {
|
|
@@ -1173,41 +1313,29 @@ export class Matterbridge extends EventEmitter {
|
|
|
1173
1313
|
const { qrPairingCode, manualPairingCode } = commissioningServer.getPairingCode();
|
|
1174
1314
|
storageContext.set('qrPairingCode', qrPairingCode);
|
|
1175
1315
|
storageContext.set('manualPairingCode', manualPairingCode);
|
|
1316
|
+
await nodeContext.set('qrPairingCode', qrPairingCode);
|
|
1317
|
+
await nodeContext.set('manualPairingCode', manualPairingCode);
|
|
1176
1318
|
const QrCode = new QrCodeSchema();
|
|
1177
|
-
this.log.info(`Pairing code:\n\n${QrCode.encode(qrPairingCode)}\nManual pairing code: ${manualPairingCode}\n`);
|
|
1178
|
-
if (
|
|
1179
|
-
await this.nodeContext?.set('qrPairingCode', qrPairingCode);
|
|
1180
|
-
await this.nodeContext?.set('manualPairingCode', manualPairingCode);
|
|
1181
|
-
}
|
|
1182
|
-
if (this.bridgeMode === 'childbridge') {
|
|
1319
|
+
this.log.info(`Pairing code:\n\n${QrCode.encode(qrPairingCode)}\n${plg}${pluginName}${nf}\n\nqrPairingCode: ${qrPairingCode}\n\nManual pairing code: ${manualPairingCode}\n`);
|
|
1320
|
+
if (pluginName !== 'Matterbridge') {
|
|
1183
1321
|
const plugin = this.findPlugin(pluginName);
|
|
1184
1322
|
if (plugin) {
|
|
1185
|
-
|
|
1186
|
-
|
|
1187
|
-
await this.nodeContext?.set('plugins', this.getBaseRegisteredPlugins());
|
|
1323
|
+
plugin.qrPairingCode = qrPairingCode;
|
|
1324
|
+
plugin.manualPairingCode = manualPairingCode;
|
|
1188
1325
|
plugin.paired = false;
|
|
1189
1326
|
}
|
|
1190
1327
|
}
|
|
1328
|
+
await this.nodeContext?.set('plugins', this.getBaseRegisteredPlugins());
|
|
1191
1329
|
}
|
|
1192
1330
|
else {
|
|
1193
1331
|
this.log.info(`***The commissioning server for ${plg}${pluginName}${nf} is already commissioned. Waiting for controllers to connect ...`);
|
|
1194
|
-
if (
|
|
1195
|
-
const qrPairingCode = storageContext.get('qrPairingCode', '');
|
|
1196
|
-
const manualPairingCode = storageContext.get('manualPairingCode', '');
|
|
1197
|
-
await this.nodeContext?.set('qrPairingCode', qrPairingCode);
|
|
1198
|
-
await this.nodeContext?.set('manualPairingCode', manualPairingCode);
|
|
1199
|
-
}
|
|
1200
|
-
if (this.bridgeMode === 'childbridge') {
|
|
1332
|
+
if (pluginName !== 'Matterbridge') {
|
|
1201
1333
|
const plugin = this.findPlugin(pluginName);
|
|
1202
|
-
if (plugin
|
|
1203
|
-
plugin.qrPairingCode = plugin.storageContext.get('qrPairingCode', '');
|
|
1204
|
-
plugin.manualPairingCode = plugin.storageContext.get('manualPairingCode', '');
|
|
1205
|
-
await plugin.nodeContext.set('qrPairingCode', plugin.qrPairingCode);
|
|
1206
|
-
await plugin.nodeContext.set('manualPairingCode', plugin.manualPairingCode);
|
|
1207
|
-
await this.nodeContext?.set('plugins', this.getBaseRegisteredPlugins());
|
|
1334
|
+
if (plugin) {
|
|
1208
1335
|
plugin.paired = true;
|
|
1209
1336
|
}
|
|
1210
1337
|
}
|
|
1338
|
+
await this.nodeContext?.set('plugins', this.getBaseRegisteredPlugins());
|
|
1211
1339
|
}
|
|
1212
1340
|
}
|
|
1213
1341
|
/**
|
|
@@ -1228,11 +1356,11 @@ export class Matterbridge extends EventEmitter {
|
|
|
1228
1356
|
* Creates a matter commissioning server.
|
|
1229
1357
|
*
|
|
1230
1358
|
* @param {StorageContext} context - The storage context.
|
|
1231
|
-
* @param {string}
|
|
1359
|
+
* @param {string} pluginName - The name of the commissioning server.
|
|
1232
1360
|
* @returns {CommissioningServer} The created commissioning server.
|
|
1233
1361
|
*/
|
|
1234
|
-
createCommisioningServer(context,
|
|
1235
|
-
this.log.debug(`Creating matter commissioning server for plugin ${plg}${
|
|
1362
|
+
createCommisioningServer(context, pluginName) {
|
|
1363
|
+
this.log.debug(`Creating matter commissioning server for plugin ${plg}${pluginName}${db}`);
|
|
1236
1364
|
const deviceName = context.get('deviceName');
|
|
1237
1365
|
const deviceType = context.get('deviceType');
|
|
1238
1366
|
const vendorId = context.get('vendorId');
|
|
@@ -1241,9 +1369,14 @@ export class Matterbridge extends EventEmitter {
|
|
|
1241
1369
|
const productName = context.get('productName'); // Home app = Model
|
|
1242
1370
|
const serialNumber = context.get('serialNumber');
|
|
1243
1371
|
const uniqueId = context.get('uniqueId');
|
|
1244
|
-
|
|
1245
|
-
//
|
|
1246
|
-
|
|
1372
|
+
const softwareVersion = context.get('softwareVersion', 1);
|
|
1373
|
+
const softwareVersionString = context.get('softwareVersionString', '1.0.0'); // Home app = Firmware Revision
|
|
1374
|
+
const hardwareVersion = context.get('hardwareVersion', 1);
|
|
1375
|
+
const hardwareVersionString = context.get('hardwareVersionString', '1.0.0');
|
|
1376
|
+
this.log.debug(`Creating matter commissioning server for plugin ${plg}${pluginName}${db} with deviceName ${deviceName} deviceType ${deviceType}(0x${deviceType.toString(16).padStart(4, '0')})`);
|
|
1377
|
+
this.log.debug(`Creating matter commissioning server for plugin ${plg}${pluginName}${db} with uniqueId ${uniqueId} serialNumber ${serialNumber}`);
|
|
1378
|
+
this.log.debug(`Creating matter commissioning server for plugin ${plg}${pluginName}${db} with softwareVersion ${softwareVersion} softwareVersionString ${softwareVersionString}`);
|
|
1379
|
+
this.log.debug(`Creating matter commissioning server for plugin ${plg}${pluginName}${db} with hardwareVersion ${hardwareVersion} hardwareVersionString ${hardwareVersionString}`);
|
|
1247
1380
|
const commissioningServer = new CommissioningServer({
|
|
1248
1381
|
port: undefined,
|
|
1249
1382
|
passcode: undefined,
|
|
@@ -1257,10 +1390,10 @@ export class Matterbridge extends EventEmitter {
|
|
|
1257
1390
|
productName,
|
|
1258
1391
|
nodeLabel: productName,
|
|
1259
1392
|
productLabel: productName,
|
|
1260
|
-
softwareVersion
|
|
1261
|
-
softwareVersionString
|
|
1262
|
-
hardwareVersion
|
|
1263
|
-
hardwareVersionString
|
|
1393
|
+
softwareVersion,
|
|
1394
|
+
softwareVersionString, // Home app = Firmware Revision
|
|
1395
|
+
hardwareVersion,
|
|
1396
|
+
hardwareVersionString,
|
|
1264
1397
|
uniqueId,
|
|
1265
1398
|
serialNumber,
|
|
1266
1399
|
reachable: true,
|
|
@@ -1269,15 +1402,15 @@ export class Matterbridge extends EventEmitter {
|
|
|
1269
1402
|
const info = commissioningServer.getActiveSessionInformation(fabricIndex);
|
|
1270
1403
|
let connected = false;
|
|
1271
1404
|
info.forEach((session) => {
|
|
1272
|
-
this.log.debug(`***Active session changed on fabric ${fabricIndex} ${session.fabric?.rootVendorId}/${session.fabric?.label} for ${plg}${
|
|
1405
|
+
this.log.debug(`***Active session changed on fabric ${fabricIndex} ${session.fabric?.rootVendorId}/${session.fabric?.label} for ${plg}${pluginName}${nf}`, debugStringify(session));
|
|
1273
1406
|
if (session.isPeerActive === true && session.secure === true && session.numberOfActiveSubscriptions >= 1) {
|
|
1274
|
-
this.log.info(`***Controller ${session.fabric?.rootVendorId}/${session.fabric?.label} connected to ${plg}${
|
|
1407
|
+
this.log.info(`***Controller ${session.fabric?.rootVendorId}/${session.fabric?.label} connected to ${plg}${pluginName}${nf}`);
|
|
1275
1408
|
connected = true;
|
|
1276
1409
|
}
|
|
1277
1410
|
});
|
|
1278
1411
|
if (connected) {
|
|
1279
1412
|
if (this.bridgeMode === 'childbridge') {
|
|
1280
|
-
const plugin = this.findPlugin(
|
|
1413
|
+
const plugin = this.findPlugin(pluginName);
|
|
1281
1414
|
if (plugin) {
|
|
1282
1415
|
plugin.paired = true;
|
|
1283
1416
|
plugin.connected = true;
|
|
@@ -1290,16 +1423,15 @@ export class Matterbridge extends EventEmitter {
|
|
|
1290
1423
|
if (!plugin.enabled)
|
|
1291
1424
|
continue;
|
|
1292
1425
|
this.startPlugin(plugin, 'Matterbridge is commissioned and controllers are connected', true); // No await do it asyncronously with also configurePlugin
|
|
1293
|
-
//this.configurePlugin(plugin); // No await do it asyncronously
|
|
1294
1426
|
}
|
|
1295
1427
|
Logger.defaultLogLevel = this.debugEnabled ? Level.DEBUG : Level.INFO;
|
|
1296
1428
|
}
|
|
1297
1429
|
if (this.bridgeMode === 'childbridge') {
|
|
1298
1430
|
//Logger.defaultLogLevel = Level.INFO;
|
|
1299
|
-
const plugin = this.findPlugin(
|
|
1431
|
+
const plugin = this.findPlugin(pluginName);
|
|
1300
1432
|
if (plugin && plugin.type === 'DynamicPlatform' && plugin.configured !== true) {
|
|
1301
1433
|
for (const registeredDevice of this.registeredDevices) {
|
|
1302
|
-
if (registeredDevice.plugin ===
|
|
1434
|
+
if (registeredDevice.plugin === pluginName) {
|
|
1303
1435
|
this.log.info(`Adding bridged device ${dev}${registeredDevice.device.name}-${registeredDevice.device.deviceName}${nf} to aggregator for plugin ${plg}${plugin.name}${db}`);
|
|
1304
1436
|
if (!plugin.aggregator) {
|
|
1305
1437
|
this.log.error(`****Aggregator not found for plugin ${plg}${plugin.name}${er}`);
|
|
@@ -1316,7 +1448,7 @@ export class Matterbridge extends EventEmitter {
|
|
|
1316
1448
|
}
|
|
1317
1449
|
}
|
|
1318
1450
|
for (const plugin of this.registeredPlugins) {
|
|
1319
|
-
if (plugin.name ===
|
|
1451
|
+
if (plugin.name === pluginName && plugin.platform && plugin.configured !== true) {
|
|
1320
1452
|
this.configurePlugin(plugin); // No await do it asyncronously
|
|
1321
1453
|
}
|
|
1322
1454
|
}
|
|
@@ -1326,12 +1458,29 @@ export class Matterbridge extends EventEmitter {
|
|
|
1326
1458
|
}, 2000);
|
|
1327
1459
|
}
|
|
1328
1460
|
},
|
|
1329
|
-
commissioningChangedCallback: (fabricIndex) => {
|
|
1461
|
+
commissioningChangedCallback: async (fabricIndex) => {
|
|
1330
1462
|
const info = commissioningServer.getCommissionedFabricInformation(fabricIndex);
|
|
1331
|
-
this.log.debug(`***Commissioning changed on fabric ${fabricIndex} for ${plg}${
|
|
1463
|
+
this.log.debug(`***Commissioning changed on fabric ${fabricIndex} for ${plg}${pluginName}${nf}`, debugStringify(info));
|
|
1332
1464
|
if (info.length === 0) {
|
|
1333
|
-
this.log.warn(`***Commissioning removed from fabric ${fabricIndex} for ${plg}${
|
|
1334
|
-
commissioningServer.factoryReset();
|
|
1465
|
+
this.log.warn(`***Commissioning removed from fabric ${fabricIndex} for ${plg}${pluginName}${nf}. Resetting the commissioning server ...`);
|
|
1466
|
+
await commissioningServer.factoryReset();
|
|
1467
|
+
if (pluginName === 'Matterbridge') {
|
|
1468
|
+
this.matterbridgeContext?.delete(`${pluginName}.EndpointStructure`);
|
|
1469
|
+
this.matterbridgeContext?.delete(`${pluginName}.EventHandler`);
|
|
1470
|
+
this.matterbridgeContext?.delete(`${pluginName}.SessionManager`);
|
|
1471
|
+
}
|
|
1472
|
+
else {
|
|
1473
|
+
for (const plugin of this.registeredPlugins) {
|
|
1474
|
+
if (plugin.name === pluginName) {
|
|
1475
|
+
await plugin.platform?.onShutdown('Commissioning removed by the controller');
|
|
1476
|
+
plugin.paired = false;
|
|
1477
|
+
plugin.connected = false;
|
|
1478
|
+
plugin.storageContext?.delete(`${pluginName}.EndpointStructure`);
|
|
1479
|
+
plugin.storageContext?.delete(`${pluginName}.EventHandler`);
|
|
1480
|
+
plugin.storageContext?.delete(`${pluginName}.SessionManager`);
|
|
1481
|
+
}
|
|
1482
|
+
}
|
|
1483
|
+
}
|
|
1335
1484
|
}
|
|
1336
1485
|
},
|
|
1337
1486
|
});
|
|
@@ -1563,6 +1712,11 @@ export class Matterbridge extends EventEmitter {
|
|
|
1563
1712
|
const cmdArgs = process.argv.slice(2).join(' ');
|
|
1564
1713
|
this.log.debug(`Command Line Arguments: ${cmdArgs}`);
|
|
1565
1714
|
}
|
|
1715
|
+
/**
|
|
1716
|
+
* Retrieves an array of base registered plugins.
|
|
1717
|
+
*
|
|
1718
|
+
* @returns {BaseRegisteredPlugin[]} An array of base registered plugins.
|
|
1719
|
+
*/
|
|
1566
1720
|
getBaseRegisteredPlugins() {
|
|
1567
1721
|
const baseRegisteredPlugins = this.registeredPlugins.map((plugin) => ({
|
|
1568
1722
|
path: plugin.path,
|
|
@@ -1583,6 +1737,10 @@ export class Matterbridge extends EventEmitter {
|
|
|
1583
1737
|
}));
|
|
1584
1738
|
return baseRegisteredPlugins;
|
|
1585
1739
|
}
|
|
1740
|
+
/**
|
|
1741
|
+
* Retrieves an array of base registered devices from the registered plugins.
|
|
1742
|
+
* @returns {BaseRegisteredPlugin[]} An array of base registered devices.
|
|
1743
|
+
*/
|
|
1586
1744
|
getBaseRegisteredDevices() {
|
|
1587
1745
|
const baseRegisteredPlugins = this.registeredPlugins.map((plugin) => ({
|
|
1588
1746
|
path: plugin.path,
|
|
@@ -1614,6 +1772,7 @@ export class Matterbridge extends EventEmitter {
|
|
|
1614
1772
|
this.expressApp.get('/api/qr-code', (req, res) => {
|
|
1615
1773
|
this.log.debug('The frontend sent /api/qr-code');
|
|
1616
1774
|
if (!this.matterbridgeContext) {
|
|
1775
|
+
this.log.error('/api/qr-code matterbridgeContext not found');
|
|
1617
1776
|
res.json([]);
|
|
1618
1777
|
return;
|
|
1619
1778
|
}
|