matterbridge 3.0.8-dev-20250624-5abb0bb → 3.0.8-dev-20250625-61b3769
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/dist/frontend.js +1 -1
- package/dist/matterbridge.js +83 -12
- package/dist/matterbridgeEndpoint.js +3 -2
- package/dist/pluginManager.js +11 -1
- package/npm-shrinkwrap.json +2 -2
- package/package.json +1 -1
package/dist/frontend.js
CHANGED
|
@@ -769,7 +769,7 @@ export class Frontend {
|
|
|
769
769
|
this.matterbridge.devices.forEach(async (device) => {
|
|
770
770
|
if (pluginName && pluginName !== device.plugin)
|
|
771
771
|
return;
|
|
772
|
-
if (!device.plugin || !device.name || !device.deviceName || !device.serialNumber || !device.uniqueId || !device.lifecycle.isReady)
|
|
772
|
+
if (!device.plugin || !device.deviceType || !device.name || !device.deviceName || !device.serialNumber || !device.uniqueId || !device.lifecycle.isReady)
|
|
773
773
|
return;
|
|
774
774
|
const cluster = this.getClusterTextFromDevice(device);
|
|
775
775
|
devices.push({
|
package/dist/matterbridge.js
CHANGED
|
@@ -198,12 +198,18 @@ export class Matterbridge extends EventEmitter {
|
|
|
198
198
|
if (this.serverNode)
|
|
199
199
|
servers.push(this.serverNode);
|
|
200
200
|
}
|
|
201
|
-
if (this.bridgeMode === 'childbridge') {
|
|
201
|
+
if (this.bridgeMode === 'childbridge' && this.plugins !== undefined) {
|
|
202
202
|
for (const plugin of this.plugins.array()) {
|
|
203
203
|
if (plugin.serverNode)
|
|
204
204
|
servers.push(plugin.serverNode);
|
|
205
205
|
}
|
|
206
206
|
}
|
|
207
|
+
if (this.devices !== undefined) {
|
|
208
|
+
for (const device of this.devices.array()) {
|
|
209
|
+
if (device.serverMode === 'server' && device.serverNode)
|
|
210
|
+
servers.push(device.serverNode);
|
|
211
|
+
}
|
|
212
|
+
}
|
|
207
213
|
await Promise.resolve();
|
|
208
214
|
await this.cleanup('destroying instance...', false);
|
|
209
215
|
this.log.info(`Dispose ${servers.length} MdnsService...`);
|
|
@@ -1075,6 +1081,12 @@ export class Matterbridge extends EventEmitter {
|
|
|
1075
1081
|
}
|
|
1076
1082
|
}
|
|
1077
1083
|
}
|
|
1084
|
+
for (const device of this.devices.array()) {
|
|
1085
|
+
if (device.serverMode === 'server' && device.serverNode) {
|
|
1086
|
+
await this.stopServerNode(device.serverNode);
|
|
1087
|
+
device.serverNode = undefined;
|
|
1088
|
+
}
|
|
1089
|
+
}
|
|
1078
1090
|
this.log.notice('Stopped matter server nodes');
|
|
1079
1091
|
if (message === 'shutting down with reset...') {
|
|
1080
1092
|
this.log.info('Resetting Matterbridge commissioning information...');
|
|
@@ -1168,8 +1180,18 @@ export class Matterbridge extends EventEmitter {
|
|
|
1168
1180
|
this.log.debug('Cleanup already started...');
|
|
1169
1181
|
}
|
|
1170
1182
|
}
|
|
1183
|
+
async createDeviceServerNode(plugin, device) {
|
|
1184
|
+
if (device.serverMode === 'server' && !device.serverNode && device.deviceType && device.deviceName && device.vendorId && device.productId && device.vendorName && device.productName) {
|
|
1185
|
+
this.log.debug(`Creating device ${plg}${plugin.name}${db}:${dev}${device.deviceName}${db} server node...`);
|
|
1186
|
+
const storageContext = await this.createServerNodeContext(device.deviceName.replace(/[ .]/g, ''), device.deviceName, DeviceTypeId(device.deviceType), device.vendorId, device.vendorName, device.productId, device.productName);
|
|
1187
|
+
device.serverNode = await this.createServerNode(storageContext, this.port ? this.port++ : undefined, this.passcode ? this.passcode++ : undefined, this.discriminator ? this.discriminator++ : undefined);
|
|
1188
|
+
this.log.debug(`Adding ${plg}${plugin.name}${db}:${dev}${device.deviceName}${db} to server node...`);
|
|
1189
|
+
await device.serverNode.add(device);
|
|
1190
|
+
this.log.debug(`Added ${plg}${plugin.name}${db}:${dev}${device.deviceName}${db} to server node`);
|
|
1191
|
+
}
|
|
1192
|
+
}
|
|
1171
1193
|
async createAccessoryPlugin(plugin, device, start = false) {
|
|
1172
|
-
if (!plugin.locked && device.deviceName && device.vendorId && device.productId && device.vendorName && device.productName) {
|
|
1194
|
+
if (!plugin.locked && device.deviceType && device.deviceName && device.vendorId && device.productId && device.vendorName && device.productName) {
|
|
1173
1195
|
plugin.locked = true;
|
|
1174
1196
|
plugin.device = device;
|
|
1175
1197
|
plugin.storageContext = await this.createServerNodeContext(plugin.name, device.deviceName, DeviceTypeId(device.deviceType), device.vendorId, device.vendorName, device.productId, device.productName);
|
|
@@ -1233,6 +1255,12 @@ export class Matterbridge extends EventEmitter {
|
|
|
1233
1255
|
this.startMatterInterval = undefined;
|
|
1234
1256
|
this.log.debug('Cleared startMatterInterval interval for Matterbridge');
|
|
1235
1257
|
this.startServerNode(this.serverNode);
|
|
1258
|
+
for (const device of this.devices.array()) {
|
|
1259
|
+
if (device.serverMode === 'server' && device.serverNode) {
|
|
1260
|
+
this.log.debug(`Starting server node for device ${dev}${device.deviceName}${db} in server mode...`);
|
|
1261
|
+
await this.startServerNode(device.serverNode);
|
|
1262
|
+
}
|
|
1263
|
+
}
|
|
1236
1264
|
this.configureTimeout = setTimeout(async () => {
|
|
1237
1265
|
for (const plugin of this.plugins) {
|
|
1238
1266
|
if (!plugin.enabled || !plugin.loaded || !plugin.started || plugin.error)
|
|
@@ -1312,7 +1340,7 @@ export class Matterbridge extends EventEmitter {
|
|
|
1312
1340
|
}
|
|
1313
1341
|
this.frontend.wssSendRefreshRequired('plugins');
|
|
1314
1342
|
}, 30 * 1000);
|
|
1315
|
-
for (const plugin of this.plugins) {
|
|
1343
|
+
for (const plugin of this.plugins.array()) {
|
|
1316
1344
|
if (!plugin.enabled || plugin.error)
|
|
1317
1345
|
continue;
|
|
1318
1346
|
if (plugin.type !== 'DynamicPlatform' && (!plugin.addedDevices || plugin.addedDevices === 0)) {
|
|
@@ -1339,6 +1367,12 @@ export class Matterbridge extends EventEmitter {
|
|
|
1339
1367
|
this.frontend.wssSendRefreshRequired('reachability');
|
|
1340
1368
|
}, 60 * 1000);
|
|
1341
1369
|
}
|
|
1370
|
+
for (const device of this.devices.array()) {
|
|
1371
|
+
if (device.serverMode === 'server' && device.serverNode) {
|
|
1372
|
+
this.log.debug(`***Starting server node for device ${plg}${device.deviceName}${db} in server mode...`);
|
|
1373
|
+
await this.startServerNode(device.serverNode);
|
|
1374
|
+
}
|
|
1375
|
+
}
|
|
1342
1376
|
}, 1000);
|
|
1343
1377
|
}
|
|
1344
1378
|
async startController() {
|
|
@@ -1668,22 +1702,52 @@ export class Matterbridge extends EventEmitter {
|
|
|
1668
1702
|
this.log.error(`Error adding bridged endpoint ${dev}${device.deviceName}${er} (${zb}${device.id}${er}) plugin ${plg}${pluginName}${er} not found`);
|
|
1669
1703
|
return;
|
|
1670
1704
|
}
|
|
1671
|
-
if (
|
|
1672
|
-
this.log.debug(`Adding bridged endpoint ${plg}${pluginName}${db}:${dev}${device.deviceName}${db} to Matterbridge aggregator node`);
|
|
1673
|
-
if (!this.aggregatorNode) {
|
|
1674
|
-
this.log.error('Aggregator node not found for Matterbridge');
|
|
1675
|
-
return;
|
|
1676
|
-
}
|
|
1705
|
+
if (device.serverMode === 'server') {
|
|
1677
1706
|
try {
|
|
1678
|
-
|
|
1707
|
+
this.log.debug(`Creating server node for device ${dev}${device.deviceName}${db} of plugin ${plg}${plugin.name}${db}...`);
|
|
1708
|
+
await this.createDeviceServerNode(plugin, device);
|
|
1679
1709
|
}
|
|
1680
1710
|
catch (error) {
|
|
1681
1711
|
const errorMessage = error instanceof Error ? error.message : error;
|
|
1682
1712
|
const errorInspect = inspect(error, { depth: 10 });
|
|
1683
|
-
this.log.error(`Error
|
|
1713
|
+
this.log.error(`Error creating server node for device ${dev}${device.deviceName}${er} (${zb}${device.id}${er}) of plugin ${plg}${pluginName}${er}: ${errorMessage}\nstack: ${errorInspect}`);
|
|
1684
1714
|
return;
|
|
1685
1715
|
}
|
|
1686
1716
|
}
|
|
1717
|
+
else if (this.bridgeMode === 'bridge') {
|
|
1718
|
+
if (device.serverMode === 'matter') {
|
|
1719
|
+
this.log.debug(`Adding matter endpoint ${plg}${pluginName}${db}:${dev}${device.deviceName}${db} to Matterbridge server node...`);
|
|
1720
|
+
if (!this.serverNode) {
|
|
1721
|
+
this.log.error('Server node not found for Matterbridge');
|
|
1722
|
+
return;
|
|
1723
|
+
}
|
|
1724
|
+
try {
|
|
1725
|
+
await this.serverNode.add(device);
|
|
1726
|
+
}
|
|
1727
|
+
catch (error) {
|
|
1728
|
+
const errorMessage = error instanceof Error ? error.message : error;
|
|
1729
|
+
const errorInspect = inspect(error, { depth: 10 });
|
|
1730
|
+
this.log.error(`Error adding matter endpoint ${dev}${device.deviceName}${er} (${zb}${device.id}${er}) for plugin ${plg}${pluginName}${er}: ${errorMessage}\nstack: ${errorInspect}`);
|
|
1731
|
+
return;
|
|
1732
|
+
}
|
|
1733
|
+
}
|
|
1734
|
+
else {
|
|
1735
|
+
this.log.debug(`Adding bridged endpoint ${plg}${pluginName}${db}:${dev}${device.deviceName}${db} to Matterbridge aggregator node`);
|
|
1736
|
+
if (!this.aggregatorNode) {
|
|
1737
|
+
this.log.error('Aggregator node not found for Matterbridge');
|
|
1738
|
+
return;
|
|
1739
|
+
}
|
|
1740
|
+
try {
|
|
1741
|
+
await this.aggregatorNode.add(device);
|
|
1742
|
+
}
|
|
1743
|
+
catch (error) {
|
|
1744
|
+
const errorMessage = error instanceof Error ? error.message : error;
|
|
1745
|
+
const errorInspect = inspect(error, { depth: 10 });
|
|
1746
|
+
this.log.error(`Error adding bridged endpoint ${dev}${device.deviceName}${er} (${zb}${device.id}${er}) for plugin ${plg}${pluginName}${er}: ${errorMessage}\nstack: ${errorInspect}`);
|
|
1747
|
+
return;
|
|
1748
|
+
}
|
|
1749
|
+
}
|
|
1750
|
+
}
|
|
1687
1751
|
else if (this.bridgeMode === 'childbridge') {
|
|
1688
1752
|
if (plugin.type === 'AccessoryPlatform') {
|
|
1689
1753
|
try {
|
|
@@ -1706,11 +1770,18 @@ export class Matterbridge extends EventEmitter {
|
|
|
1706
1770
|
this.log.debug(`Adding bridged endpoint ${dev}${device.deviceName}${db} for DynamicPlatform plugin ${plg}${plugin.name}${db} aggregator node`);
|
|
1707
1771
|
await this.createDynamicPlugin(plugin);
|
|
1708
1772
|
await waiter(`createDynamicPlugin(${plugin.name})`, () => plugin.serverNode?.hasParts === true);
|
|
1773
|
+
if (!plugin.serverNode) {
|
|
1774
|
+
this.log.error(`Server node not found for plugin ${plg}${plugin.name}${er}`);
|
|
1775
|
+
return;
|
|
1776
|
+
}
|
|
1709
1777
|
if (!plugin.aggregatorNode) {
|
|
1710
1778
|
this.log.error(`Aggregator node not found for plugin ${plg}${plugin.name}${er}`);
|
|
1711
1779
|
return;
|
|
1712
1780
|
}
|
|
1713
|
-
|
|
1781
|
+
if (device.serverMode === 'matter')
|
|
1782
|
+
await plugin.serverNode.add(device);
|
|
1783
|
+
else
|
|
1784
|
+
await plugin.aggregatorNode.add(device);
|
|
1714
1785
|
}
|
|
1715
1786
|
catch (error) {
|
|
1716
1787
|
const errorMessage = error instanceof Error ? error.message : error;
|
|
@@ -68,6 +68,8 @@ import { addClusterServers, addFixedLabel, addOptionalClusterServers, addRequire
|
|
|
68
68
|
export class MatterbridgeEndpoint extends Endpoint {
|
|
69
69
|
static bridgeMode = '';
|
|
70
70
|
static logLevel = "info";
|
|
71
|
+
serverMode = undefined;
|
|
72
|
+
serverNode;
|
|
71
73
|
log;
|
|
72
74
|
plugin = undefined;
|
|
73
75
|
configUrl = undefined;
|
|
@@ -83,9 +85,8 @@ export class MatterbridgeEndpoint extends Endpoint {
|
|
|
83
85
|
hardwareVersion = undefined;
|
|
84
86
|
hardwareVersionString = undefined;
|
|
85
87
|
productUrl = 'https://www.npmjs.com/package/matterbridge';
|
|
86
|
-
serverNode;
|
|
87
88
|
name = undefined;
|
|
88
|
-
deviceType;
|
|
89
|
+
deviceType = undefined;
|
|
89
90
|
uniqueStorageKey = undefined;
|
|
90
91
|
tagList = undefined;
|
|
91
92
|
deviceTypes = new Map();
|
package/dist/pluginManager.js
CHANGED
|
@@ -1,11 +1,13 @@
|
|
|
1
|
+
import EventEmitter from 'node:events';
|
|
1
2
|
import { AnsiLogger, UNDERLINE, UNDERLINEOFF, BLUE, db, er, nf, nt, rs, wr } from 'node-ansi-logger';
|
|
2
3
|
import { plg, typ } from './matterbridgeTypes.js';
|
|
3
|
-
export class PluginManager {
|
|
4
|
+
export class PluginManager extends EventEmitter {
|
|
4
5
|
_plugins = new Map();
|
|
5
6
|
nodeContext;
|
|
6
7
|
matterbridge;
|
|
7
8
|
log;
|
|
8
9
|
constructor(matterbridge) {
|
|
10
|
+
super();
|
|
9
11
|
this.matterbridge = matterbridge;
|
|
10
12
|
this.nodeContext = matterbridge.nodeContext;
|
|
11
13
|
this.log = new AnsiLogger({ logName: 'PluginManager', logTimestampFormat: 4, logLevel: matterbridge.log.logLevel });
|
|
@@ -319,6 +321,7 @@ export class PluginManager {
|
|
|
319
321
|
plugin.enabled = true;
|
|
320
322
|
this.log.info(`Enabled plugin ${plg}${plugin.name}${nf}`);
|
|
321
323
|
await this.saveToStorage();
|
|
324
|
+
this.emit('enabled', plugin.name);
|
|
322
325
|
return plugin;
|
|
323
326
|
}
|
|
324
327
|
catch (err) {
|
|
@@ -352,6 +355,7 @@ export class PluginManager {
|
|
|
352
355
|
plugin.enabled = false;
|
|
353
356
|
this.log.info(`Disabled plugin ${plg}${plugin.name}${nf}`);
|
|
354
357
|
await this.saveToStorage();
|
|
358
|
+
this.emit('disabled', plugin.name);
|
|
355
359
|
return plugin;
|
|
356
360
|
}
|
|
357
361
|
catch (err) {
|
|
@@ -385,6 +389,7 @@ export class PluginManager {
|
|
|
385
389
|
this._plugins.delete(packageJson.name);
|
|
386
390
|
this.log.info(`Removed plugin ${plg}${plugin.name}${nf}`);
|
|
387
391
|
await this.saveToStorage();
|
|
392
|
+
this.emit('removed', plugin.name);
|
|
388
393
|
return plugin;
|
|
389
394
|
}
|
|
390
395
|
catch (err) {
|
|
@@ -419,6 +424,7 @@ export class PluginManager {
|
|
|
419
424
|
this.log.info(`Added plugin ${plg}${packageJson.name}${nf}`);
|
|
420
425
|
await this.saveToStorage();
|
|
421
426
|
const plugin = this._plugins.get(packageJson.name);
|
|
427
|
+
this.emit('added', packageJson.name);
|
|
422
428
|
return plugin || null;
|
|
423
429
|
}
|
|
424
430
|
catch (err) {
|
|
@@ -529,6 +535,7 @@ export class PluginManager {
|
|
|
529
535
|
plugin.addedDevices = 0;
|
|
530
536
|
await this.saveToStorage();
|
|
531
537
|
this.log.notice(`Loaded plugin ${plg}${plugin.name}${nt} type ${typ}${platform.type}${nt} (entrypoint ${UNDERLINE}${pluginEntry}${UNDERLINEOFF})`);
|
|
538
|
+
this.emit('loaded', plugin.name);
|
|
532
539
|
if (start)
|
|
533
540
|
await this.start(plugin, message, false);
|
|
534
541
|
if (configure)
|
|
@@ -565,6 +572,7 @@ export class PluginManager {
|
|
|
565
572
|
this.log.notice(`Started plugin ${plg}${plugin.name}${nt} type ${typ}${plugin.type}${nt}`);
|
|
566
573
|
plugin.started = true;
|
|
567
574
|
await this.saveConfigFromPlugin(plugin);
|
|
575
|
+
this.emit('started', plugin.name);
|
|
568
576
|
if (configure)
|
|
569
577
|
await this.configure(plugin);
|
|
570
578
|
return plugin;
|
|
@@ -597,6 +605,7 @@ export class PluginManager {
|
|
|
597
605
|
await plugin.platform.onConfigure();
|
|
598
606
|
this.log.notice(`Configured plugin ${plg}${plugin.name}${nt} type ${typ}${plugin.type}${nt}`);
|
|
599
607
|
plugin.configured = true;
|
|
608
|
+
this.emit('configured', plugin.name);
|
|
600
609
|
return plugin;
|
|
601
610
|
}
|
|
602
611
|
catch (err) {
|
|
@@ -640,6 +649,7 @@ export class PluginManager {
|
|
|
640
649
|
plugin.registeredDevices = undefined;
|
|
641
650
|
plugin.addedDevices = undefined;
|
|
642
651
|
this.log.notice(`Shutdown of plugin ${plg}${plugin.name}${nt} completed`);
|
|
652
|
+
this.emit('shutdown', plugin.name);
|
|
643
653
|
return plugin;
|
|
644
654
|
}
|
|
645
655
|
catch (err) {
|
package/npm-shrinkwrap.json
CHANGED
|
@@ -1,12 +1,12 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "matterbridge",
|
|
3
|
-
"version": "3.0.8-dev-
|
|
3
|
+
"version": "3.0.8-dev-20250625-61b3769",
|
|
4
4
|
"lockfileVersion": 3,
|
|
5
5
|
"requires": true,
|
|
6
6
|
"packages": {
|
|
7
7
|
"": {
|
|
8
8
|
"name": "matterbridge",
|
|
9
|
-
"version": "3.0.8-dev-
|
|
9
|
+
"version": "3.0.8-dev-20250625-61b3769",
|
|
10
10
|
"license": "Apache-2.0",
|
|
11
11
|
"dependencies": {
|
|
12
12
|
"@matter/main": "0.14.0",
|
package/package.json
CHANGED