matterbridge 1.2.16 → 1.2.18
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 +37 -0
- package/dist/AirQualityCluster.d.ts.map +1 -1
- package/dist/AirQualityCluster.js +1 -1
- package/dist/AirQualityCluster.js.map +1 -1
- package/dist/BridgedDeviceBasicInformationCluster.d.ts +1 -1
- package/dist/BridgedDeviceBasicInformationCluster.d.ts.map +1 -1
- package/dist/BridgedDeviceBasicInformationCluster.js +1 -1
- package/dist/BridgedDeviceBasicInformationCluster.js.map +1 -1
- package/dist/TvocCluster.d.ts.map +1 -1
- package/dist/TvocCluster.js.map +1 -1
- package/dist/cli.js +8 -5
- package/dist/cli.js.map +1 -1
- package/dist/defaultConfigSchema.d.ts +2 -0
- package/dist/defaultConfigSchema.d.ts.map +1 -1
- package/dist/defaultConfigSchema.js +74 -0
- package/dist/defaultConfigSchema.js.map +1 -1
- package/dist/matterbridge.d.ts +3 -6
- package/dist/matterbridge.d.ts.map +1 -1
- package/dist/matterbridge.js +114 -153
- package/dist/matterbridge.js.map +1 -1
- package/dist/matterbridgeController.js +1 -1
- package/dist/matterbridgeController.js.map +1 -1
- package/dist/matterbridgeDevice.d.ts +40 -47
- package/dist/matterbridgeDevice.d.ts.map +1 -1
- package/dist/matterbridgeDevice.js +119 -67
- package/dist/matterbridgeDevice.js.map +1 -1
- package/dist/utils.d.ts +19 -1
- package/dist/utils.d.ts.map +1 -1
- package/dist/utils.js +104 -35
- package/dist/utils.js.map +1 -1
- package/frontend/build/asset-manifest.json +3 -3
- package/frontend/build/index.html +1 -1
- package/frontend/build/static/js/{main.b08bfdf4.js → main.5e82a930.js} +3 -3
- package/frontend/build/static/js/main.5e82a930.js.map +1 -0
- package/package.json +3 -4
- package/frontend/build/static/js/main.b08bfdf4.js.map +0 -1
- /package/frontend/build/static/js/{main.b08bfdf4.js.LICENSE.txt → main.5e82a930.js.LICENSE.txt} +0 -0
package/dist/matterbridge.js
CHANGED
|
@@ -22,7 +22,7 @@
|
|
|
22
22
|
*/
|
|
23
23
|
import { MatterbridgeDevice } from './matterbridgeDevice.js';
|
|
24
24
|
import { NodeStorageManager } from 'node-persist-manager';
|
|
25
|
-
import { AnsiLogger, BRIGHT, RESET, UNDERLINE, UNDERLINEOFF, YELLOW, db, debugStringify, stringify, er, nf, rs, wr, RED, GREEN } from 'node-ansi-logger';
|
|
25
|
+
import { AnsiLogger, BRIGHT, RESET, UNDERLINE, UNDERLINEOFF, YELLOW, db, debugStringify, stringify, er, nf, rs, wr, RED, GREEN, zb } from 'node-ansi-logger';
|
|
26
26
|
import { fileURLToPath, pathToFileURL } from 'url';
|
|
27
27
|
import { promises as fs } from 'fs';
|
|
28
28
|
import { exec, spawn } from 'child_process';
|
|
@@ -42,7 +42,7 @@ import { ManualPairingCodeCodec, QrCodeSchema } from '@project-chip/matter-node.
|
|
|
42
42
|
import { StorageBackendDisk, StorageBackendJsonFile, StorageManager } from '@project-chip/matter-node.js/storage';
|
|
43
43
|
import { requireMinNodeVersion, getParameter, getIntParameter, hasParameter } from '@project-chip/matter-node.js/util';
|
|
44
44
|
import { CryptoNode } from '@project-chip/matter-node.js/crypto';
|
|
45
|
-
import { somfytahoma_config, somfytahoma_schema, zigbee2mqtt_config, zigbee2mqtt_schema } from './defaultConfigSchema.js';
|
|
45
|
+
import { shelly_config, shelly_schema, somfytahoma_config, somfytahoma_schema, zigbee2mqtt_config, zigbee2mqtt_schema } from './defaultConfigSchema.js';
|
|
46
46
|
const plg = '\u001B[38;5;33m';
|
|
47
47
|
const dev = '\u001B[38;5;79m';
|
|
48
48
|
const typ = '\u001B[38;5;207m';
|
|
@@ -478,7 +478,7 @@ export class Matterbridge extends EventEmitter {
|
|
|
478
478
|
this.log.debug(`Package.json not found at ${packageJsonPath}`);
|
|
479
479
|
this.log.debug(`Trying at ${this.globalModulesDirectory}`);
|
|
480
480
|
packageJsonPath = path.join(this.globalModulesDirectory, pluginPath);
|
|
481
|
-
//this.log.debug(`Got ${packageJsonPath}`);
|
|
481
|
+
// this.log.debug(`Got ${packageJsonPath}`);
|
|
482
482
|
}
|
|
483
483
|
try {
|
|
484
484
|
// Load the package.json of the plugin
|
|
@@ -760,8 +760,9 @@ export class Matterbridge extends EventEmitter {
|
|
|
760
760
|
const serializedRegisteredDevices = [];
|
|
761
761
|
this.registeredDevices.forEach((registeredDevice) => {
|
|
762
762
|
const serializedMatterbridgeDevice = registeredDevice.device.serialize(registeredDevice.plugin);
|
|
763
|
-
//this.log.info(`- ${serializedMatterbridgeDevice.deviceName}${rs}\n`, serializedMatterbridgeDevice);
|
|
764
|
-
|
|
763
|
+
// this.log.info(`- ${serializedMatterbridgeDevice.deviceName}${rs}\n`, serializedMatterbridgeDevice);
|
|
764
|
+
if (serializedMatterbridgeDevice)
|
|
765
|
+
serializedRegisteredDevices.push(serializedMatterbridgeDevice);
|
|
765
766
|
});
|
|
766
767
|
await this.nodeContext.set('devices', serializedRegisteredDevices);
|
|
767
768
|
this.log.info('Saved registered devices');
|
|
@@ -918,7 +919,7 @@ export class Matterbridge extends EventEmitter {
|
|
|
918
919
|
if (this.bridgeMode === 'bridge') {
|
|
919
920
|
device.setBridgedDeviceReachability(false);
|
|
920
921
|
device.getClusterServerById(BridgedDeviceBasicInformation.Cluster.id)?.triggerReachableChangedEvent({ reachableNewValue: false });
|
|
921
|
-
this.matterAggregator
|
|
922
|
+
this.matterAggregator?.removeBridgedDevice(device);
|
|
922
923
|
this.registeredDevices.forEach((registeredDevice, index) => {
|
|
923
924
|
if (registeredDevice.device === device) {
|
|
924
925
|
this.registeredDevices.splice(index, 1);
|
|
@@ -945,7 +946,7 @@ export class Matterbridge extends EventEmitter {
|
|
|
945
946
|
});
|
|
946
947
|
device.setBridgedDeviceReachability(false);
|
|
947
948
|
device.getClusterServerById(BridgedDeviceBasicInformation.Cluster.id)?.triggerReachableChangedEvent({ reachableNewValue: false });
|
|
948
|
-
plugin.aggregator
|
|
949
|
+
plugin.aggregator?.removeBridgedDevice(device);
|
|
949
950
|
}
|
|
950
951
|
this.log.info(`Removed bridged device(${plugin.registeredDevices}/${plugin.addedDevices}) ${dev}${device.deviceName}${nf} (${dev}${device.name}${nf}) for plugin ${plg}${pluginName}${nf}`);
|
|
951
952
|
if (plugin.registeredDevices !== undefined)
|
|
@@ -1051,85 +1052,7 @@ export class Matterbridge extends EventEmitter {
|
|
|
1051
1052
|
this.mattercontrollerContext = undefined;
|
|
1052
1053
|
}
|
|
1053
1054
|
async testStartMatterBridge() {
|
|
1054
|
-
|
|
1055
|
-
if (!this.storageManager) {
|
|
1056
|
-
this.log.error('No storage manager initialized');
|
|
1057
|
-
await this.cleanup('No storage manager initialized');
|
|
1058
|
-
return;
|
|
1059
|
-
}
|
|
1060
|
-
this.log.debug('Starting matterbridge in mode', this.bridgeMode);
|
|
1061
|
-
this.matterServer = this.createMatterServer(this.storageManager);
|
|
1062
|
-
|
|
1063
|
-
this.log.debug('***Starting startMatterbridge interval for Matterbridge');
|
|
1064
|
-
let failCount = 0;
|
|
1065
|
-
const startInterval = setInterval(async () => {
|
|
1066
|
-
for (const plugin of this.registeredPlugins) {
|
|
1067
|
-
if (!plugin.enabled) continue;
|
|
1068
|
-
if (!plugin.loaded) {
|
|
1069
|
-
this.log.info(`***Waiting (failSafeCount=${failCount}/30) in startMatterbridge interval for plugin ${plg}${plugin.name}${db} loaded: ${plugin.loaded}...`);
|
|
1070
|
-
failCount++;
|
|
1071
|
-
if (failCount > 30) {
|
|
1072
|
-
this.log.error(`***Failed to load plugin ${plg}${plugin.name}${er}`);
|
|
1073
|
-
plugin.error = true;
|
|
1074
|
-
} else {
|
|
1075
|
-
return;
|
|
1076
|
-
}
|
|
1077
|
-
}
|
|
1078
|
-
}
|
|
1079
|
-
clearInterval(startInterval);
|
|
1080
|
-
this.log.debug('***Cleared startMatterbridge interval for Matterbridge');
|
|
1081
|
-
|
|
1082
|
-
this.log.debug(`Creating commissioning server context for ${plg}Matterbridge${db}`);
|
|
1083
|
-
this.matterbridgeContext = await this.createCommissioningServerContext('Matterbridge', 'Matterbridge', DeviceTypes.AGGREGATOR.code, 0xfff1, 'Matterbridge', 0x8000, 'Matterbridge Aggregator');
|
|
1084
|
-
if (!this.matterbridgeContext) {
|
|
1085
|
-
this.log.error(`Error creating storage context for ${plg}Matterbridge${er}`);
|
|
1086
|
-
return;
|
|
1087
|
-
}
|
|
1088
|
-
if (!this.nodeContext) {
|
|
1089
|
-
this.log.error(`Node storage context undefined for ${plg}Matterbridge${er}`);
|
|
1090
|
-
return;
|
|
1091
|
-
}
|
|
1092
|
-
await this.matterbridgeContext.set('softwareVersion', 1);
|
|
1093
|
-
await this.matterbridgeContext.set('softwareVersionString', this.matterbridgeVersion);
|
|
1094
|
-
this.log.debug(`Creating commissioning server for ${plg}Matterbridge${db}`);
|
|
1095
|
-
this.commissioningServer = await this.createCommisioningServer(this.matterbridgeContext, 'Matterbridge');
|
|
1096
|
-
|
|
1097
|
-
this.log.debug(`Creating matter aggregator for ${plg}Matterbridge${db}`);
|
|
1098
|
-
this.matterAggregator = await this.createMatterAggregator(this.matterbridgeContext, 'Matterbridge');
|
|
1099
|
-
this.log.debug('Adding matterbridge aggregator to commissioning server');
|
|
1100
|
-
this.commissioningServer.addDevice(this.matterAggregator);
|
|
1101
|
-
|
|
1102
|
-
const device = new MatterbridgeDevice(DeviceTypes.CONTACT_SENSOR);
|
|
1103
|
-
device.createDefaultIdentifyClusterServer();
|
|
1104
|
-
device.createDefaultBridgedDeviceBasicInformationClusterServer('Boolean test', '0x89930475', 0x8000, 'Matterbridge', 'Boolean');
|
|
1105
|
-
device.createDefaultBooleanStateClusterServer(true);
|
|
1106
|
-
device.createDefaultPowerSourceReplaceableBatteryClusterServer(75);
|
|
1107
|
-
device.createDefaultPowerSourceConfigurationClusterServer(1);
|
|
1108
|
-
|
|
1109
|
-
this.log.debug('Adding matterbridge commissioning server to matter server');
|
|
1110
|
-
await this.matterServer?.addCommissioningServer(this.commissioningServer, { uniqueStorageKey: 'Matterbridge' });
|
|
1111
|
-
this.log.debug(`Setting reachability to true for ${plg}Matterbridge${db}`);
|
|
1112
|
-
this.commissioningServer.setReachability(true);
|
|
1113
|
-
this.log.debug('Starting matter server...');
|
|
1114
|
-
await this.startMatterServer();
|
|
1115
|
-
this.log.info('Matter server started');
|
|
1116
|
-
await this.showCommissioningQRCode(this.commissioningServer, this.matterbridgeContext, this.nodeContext, 'Matterbridge');
|
|
1117
|
-
|
|
1118
|
-
setTimeout(() => {
|
|
1119
|
-
this.matterAggregator?.addBridgedDevice(device);
|
|
1120
|
-
this.log.info('Added device to aggregator');
|
|
1121
|
-
}, 30 * 1000);
|
|
1122
|
-
|
|
1123
|
-
setInterval(() => {
|
|
1124
|
-
const cluster = device.getClusterServer(BooleanStateCluster);
|
|
1125
|
-
if (!cluster) return;
|
|
1126
|
-
const contact = cluster.getStateValueAttribute();
|
|
1127
|
-
cluster.setStateValueAttribute(!contact);
|
|
1128
|
-
if (cluster.isEventSupportedByName('stateChange')) cluster.triggerStateChangeEvent!({ stateValue: !contact });
|
|
1129
|
-
this.log.info('Set attribute and event for BooleanStateCluster to', !contact);
|
|
1130
|
-
}, 60 * 1000);
|
|
1131
|
-
}, 1000);
|
|
1132
|
-
*/
|
|
1055
|
+
// Start the Matterbridge
|
|
1133
1056
|
}
|
|
1134
1057
|
/**
|
|
1135
1058
|
* Loads the schema for a plugin.
|
|
@@ -1160,6 +1083,8 @@ export class Matterbridge extends EventEmitter {
|
|
|
1160
1083
|
schema = zigbee2mqtt_schema;
|
|
1161
1084
|
else if (plugin.name === 'matterbridge-somfy-tahoma')
|
|
1162
1085
|
schema = somfytahoma_schema;
|
|
1086
|
+
else if (plugin.name === 'matterbridge-shelly')
|
|
1087
|
+
schema = shelly_schema;
|
|
1163
1088
|
else
|
|
1164
1089
|
schema = {
|
|
1165
1090
|
title: plugin.description,
|
|
@@ -1252,6 +1177,8 @@ export class Matterbridge extends EventEmitter {
|
|
|
1252
1177
|
config = zigbee2mqtt_config;
|
|
1253
1178
|
else if (plugin.name === 'matterbridge-somfy-tahoma')
|
|
1254
1179
|
config = somfytahoma_config;
|
|
1180
|
+
else if (plugin.name === 'matterbridge-shelly')
|
|
1181
|
+
config = shelly_config;
|
|
1255
1182
|
else
|
|
1256
1183
|
config = { name: plugin.name, type: plugin.type, unregisterOnShutdown: false };
|
|
1257
1184
|
try {
|
|
@@ -1421,7 +1348,7 @@ export class Matterbridge extends EventEmitter {
|
|
|
1421
1348
|
if (pluginInstance.default) {
|
|
1422
1349
|
const config = await this.loadPluginConfig(plugin);
|
|
1423
1350
|
const log = new AnsiLogger({ logName: plugin.description, logTimestampFormat: 4 /* TimestampFormat.TIME_MILLIS */, logDebug: this.debugEnabled });
|
|
1424
|
-
//log.setCallback(this.wssSendMessage.bind(this));
|
|
1351
|
+
// log.setCallback(this.wssSendMessage.bind(this));
|
|
1425
1352
|
const platform = pluginInstance.default(this, log, config);
|
|
1426
1353
|
platform.name = packageJson.name;
|
|
1427
1354
|
platform.config = config;
|
|
@@ -1446,14 +1373,14 @@ export class Matterbridge extends EventEmitter {
|
|
|
1446
1373
|
this.log.error(`Plugin ${plg}${plugin.name}${er} does not provide a default export`);
|
|
1447
1374
|
plugin.error = true;
|
|
1448
1375
|
return;
|
|
1449
|
-
//return Promise.reject(new Error(`Plugin ${plg}${plugin.name}${er} does not provide a default export`));
|
|
1376
|
+
// return Promise.reject(new Error(`Plugin ${plg}${plugin.name}${er} does not provide a default export`));
|
|
1450
1377
|
}
|
|
1451
1378
|
}
|
|
1452
1379
|
catch (err) {
|
|
1453
1380
|
this.log.error(`Failed to load plugin ${plg}${plugin.name}${er}: ${err}`);
|
|
1454
1381
|
plugin.error = true;
|
|
1455
1382
|
return;
|
|
1456
|
-
//return Promise.reject(new Error(`Failed to load plugin ${plg}${plugin.name}${er}: ${err}`));
|
|
1383
|
+
// return Promise.reject(new Error(`Failed to load plugin ${plg}${plugin.name}${er}: ${err}`));
|
|
1457
1384
|
}
|
|
1458
1385
|
}
|
|
1459
1386
|
/**
|
|
@@ -1534,8 +1461,8 @@ export class Matterbridge extends EventEmitter {
|
|
|
1534
1461
|
return;
|
|
1535
1462
|
}
|
|
1536
1463
|
if (hasParameter('discover')) {
|
|
1537
|
-
//const discover = await this.commissioningController.discoverCommissionableDevices({ productId: 0x8000, deviceType: 0xfff1 });
|
|
1538
|
-
//console.log(discover);
|
|
1464
|
+
// const discover = await this.commissioningController.discoverCommissionableDevices({ productId: 0x8000, deviceType: 0xfff1 });
|
|
1465
|
+
// console.log(discover);
|
|
1539
1466
|
}
|
|
1540
1467
|
if (!this.commissioningController.isCommissioned()) {
|
|
1541
1468
|
this.log.info('***Commissioning controller is not commissioned: use matterbridge -controller -pairingcode [pairingcode] to commission a device');
|
|
@@ -1575,7 +1502,7 @@ export class Matterbridge extends EventEmitter {
|
|
|
1575
1502
|
}
|
|
1576
1503
|
},
|
|
1577
1504
|
});
|
|
1578
|
-
//node.logStructure();
|
|
1505
|
+
// node.logStructure();
|
|
1579
1506
|
// Get the interaction client
|
|
1580
1507
|
this.log.info('Getting the interaction client');
|
|
1581
1508
|
const interactionClient = await node.getInteractionClient();
|
|
@@ -1678,7 +1605,7 @@ export class Matterbridge extends EventEmitter {
|
|
|
1678
1605
|
this.log.info('Matter server started');
|
|
1679
1606
|
await this.showCommissioningQRCode(this.commissioningServer, this.matterbridgeContext, this.nodeContext, 'Matterbridge');
|
|
1680
1607
|
// logEndpoint(this.commissioningServer.getRootEndpoint());
|
|
1681
|
-
//if (hasParameter('advertise')) await this.commissioningServer.advertise();
|
|
1608
|
+
// if (hasParameter('advertise')) await this.commissioningServer.advertise();
|
|
1682
1609
|
setTimeout(() => {
|
|
1683
1610
|
this.log.info(`Setting reachability to true for ${plg}Matterbridge${db}`);
|
|
1684
1611
|
if (this.commissioningServer)
|
|
@@ -1725,7 +1652,8 @@ export class Matterbridge extends EventEmitter {
|
|
|
1725
1652
|
plugin.device = registeredDevice.device;
|
|
1726
1653
|
}
|
|
1727
1654
|
this.log.debug(`Adding commissioning server to matter server for plugin ${plg}${plugin.name}${db}`);
|
|
1728
|
-
|
|
1655
|
+
if (plugin.commissioningServer)
|
|
1656
|
+
await this.matterServer?.addCommissioningServer(plugin.commissioningServer, { uniqueStorageKey: plugin.name });
|
|
1729
1657
|
}
|
|
1730
1658
|
if (plugin.type === 'DynamicPlatform') {
|
|
1731
1659
|
this.log.debug(`Creating commissioning server context for ${plg}${plugin.name}${db}`);
|
|
@@ -1790,7 +1718,7 @@ export class Matterbridge extends EventEmitter {
|
|
|
1790
1718
|
this.setAggregatorReachability(plugin.aggregator, true);
|
|
1791
1719
|
}
|
|
1792
1720
|
Logger.defaultLogLevel = this.debugEnabled ? Level.DEBUG : Level.INFO;
|
|
1793
|
-
//clearInterval(startMatterInterval);
|
|
1721
|
+
// clearInterval(startMatterInterval);
|
|
1794
1722
|
}, 1000);
|
|
1795
1723
|
}
|
|
1796
1724
|
}
|
|
@@ -1807,7 +1735,7 @@ export class Matterbridge extends EventEmitter {
|
|
|
1807
1735
|
this.log.debug('Starting matter server...');
|
|
1808
1736
|
await this.matterServer.start();
|
|
1809
1737
|
this.log.debug('Started matter server');
|
|
1810
|
-
//this.commissioningServer?.getRootEndpoint() && logEndpoint(this.commissioningServer?.getRootEndpoint());
|
|
1738
|
+
// this.commissioningServer?.getRootEndpoint() && logEndpoint(this.commissioningServer?.getRootEndpoint());
|
|
1811
1739
|
}
|
|
1812
1740
|
/**
|
|
1813
1741
|
* Imports the commissioning server context for a specific plugin and device.
|
|
@@ -1928,7 +1856,13 @@ export class Matterbridge extends EventEmitter {
|
|
|
1928
1856
|
await this.nodeContext?.set('plugins', await this.getBaseRegisteredPlugins());
|
|
1929
1857
|
}
|
|
1930
1858
|
else {
|
|
1931
|
-
this.log.info(`*The commissioning server on port ${commissioningServer.getPort()} for ${plg}${pluginName}${nf} is already commissioned
|
|
1859
|
+
this.log.info(`*The commissioning server on port ${commissioningServer.getPort()} for ${plg}${pluginName}${nf} is already commissioned. Waiting for controllers to connect ...`);
|
|
1860
|
+
const fabricInfo = commissioningServer.getCommissionedFabricInformation();
|
|
1861
|
+
if (fabricInfo.length > 0)
|
|
1862
|
+
this.log.info('Commissioned fabric information:');
|
|
1863
|
+
fabricInfo?.forEach((info) => {
|
|
1864
|
+
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}`);
|
|
1865
|
+
});
|
|
1932
1866
|
if (pluginName !== 'Matterbridge') {
|
|
1933
1867
|
const plugin = this.findPlugin(pluginName);
|
|
1934
1868
|
if (plugin) {
|
|
@@ -1995,6 +1929,41 @@ export class Matterbridge extends EventEmitter {
|
|
|
1995
1929
|
if (basicInformationCluster && basicInformationCluster.triggerReachableChangedEvent)
|
|
1996
1930
|
basicInformationCluster.triggerReachableChangedEvent({ reachableNewValue: reachable });
|
|
1997
1931
|
}
|
|
1932
|
+
getVendorIdName = (vendorId) => {
|
|
1933
|
+
if (!vendorId)
|
|
1934
|
+
return '';
|
|
1935
|
+
let vendorName = '';
|
|
1936
|
+
switch (vendorId) {
|
|
1937
|
+
case 4937:
|
|
1938
|
+
vendorName = '(AppleHome)';
|
|
1939
|
+
break;
|
|
1940
|
+
case 4996:
|
|
1941
|
+
vendorName = '(AppleKeyChain)';
|
|
1942
|
+
break;
|
|
1943
|
+
case 4362:
|
|
1944
|
+
vendorName = '(SmartThings)';
|
|
1945
|
+
break;
|
|
1946
|
+
case 4939:
|
|
1947
|
+
vendorName = '(HomeAssistant)';
|
|
1948
|
+
break;
|
|
1949
|
+
case 24582:
|
|
1950
|
+
vendorName = '(GoogleHome)';
|
|
1951
|
+
break;
|
|
1952
|
+
case 4631:
|
|
1953
|
+
vendorName = '(Alexa)';
|
|
1954
|
+
break;
|
|
1955
|
+
case 4701:
|
|
1956
|
+
vendorName = '(Tuya)';
|
|
1957
|
+
break;
|
|
1958
|
+
case 4742:
|
|
1959
|
+
vendorName = '(eWeLink)';
|
|
1960
|
+
break;
|
|
1961
|
+
default:
|
|
1962
|
+
vendorName = '(unknown)';
|
|
1963
|
+
break;
|
|
1964
|
+
}
|
|
1965
|
+
return vendorName;
|
|
1966
|
+
};
|
|
1998
1967
|
/**
|
|
1999
1968
|
* Creates a matter commissioning server.
|
|
2000
1969
|
*
|
|
@@ -2003,38 +1972,6 @@ export class Matterbridge extends EventEmitter {
|
|
|
2003
1972
|
* @returns {CommissioningServer} The created commissioning server.
|
|
2004
1973
|
*/
|
|
2005
1974
|
async createCommisioningServer(context, pluginName) {
|
|
2006
|
-
const getVendorIdName = (vendorId) => {
|
|
2007
|
-
if (!vendorId)
|
|
2008
|
-
return '';
|
|
2009
|
-
let vendorName = '';
|
|
2010
|
-
switch (vendorId) {
|
|
2011
|
-
case 4937:
|
|
2012
|
-
vendorName = '(AppleHome)';
|
|
2013
|
-
break;
|
|
2014
|
-
case 4996:
|
|
2015
|
-
vendorName = '(AppleKeyChain)';
|
|
2016
|
-
break;
|
|
2017
|
-
case 4362:
|
|
2018
|
-
vendorName = '(SmartThings)';
|
|
2019
|
-
break;
|
|
2020
|
-
case 4939:
|
|
2021
|
-
vendorName = '(HomeAssistant)';
|
|
2022
|
-
break;
|
|
2023
|
-
case 24582:
|
|
2024
|
-
vendorName = '(GoogleHome)';
|
|
2025
|
-
break;
|
|
2026
|
-
case 4701:
|
|
2027
|
-
vendorName = '(Tuya)';
|
|
2028
|
-
break;
|
|
2029
|
-
case 4742:
|
|
2030
|
-
vendorName = '(eWeLink)';
|
|
2031
|
-
break;
|
|
2032
|
-
default:
|
|
2033
|
-
vendorName = '(unknown)';
|
|
2034
|
-
break;
|
|
2035
|
-
}
|
|
2036
|
-
return vendorName;
|
|
2037
|
-
};
|
|
2038
1975
|
this.log.debug(`Creating matter commissioning server for plugin ${plg}${pluginName}${db}`);
|
|
2039
1976
|
const deviceName = await context.get('deviceName');
|
|
2040
1977
|
const deviceType = await context.get('deviceType');
|
|
@@ -2077,9 +2014,9 @@ export class Matterbridge extends EventEmitter {
|
|
|
2077
2014
|
const info = commissioningServer.getActiveSessionInformation(fabricIndex);
|
|
2078
2015
|
let connected = false;
|
|
2079
2016
|
info.forEach((session) => {
|
|
2080
|
-
this.log.info(`*Active session changed on fabric ${fabricIndex} ${session.fabric?.rootVendorId}${getVendorIdName(session.fabric?.rootVendorId)}
|
|
2017
|
+
this.log.info(`*Active session changed on fabric ${zb}${fabricIndex}${nf} vendor ${zb}${session.fabric?.rootVendorId}${nf} ${this.getVendorIdName(session.fabric?.rootVendorId)} ${session.fabric?.label} for ${plg}${pluginName}${nf}`, debugStringify(session));
|
|
2081
2018
|
if (session.isPeerActive === true && session.secure === true && session.numberOfActiveSubscriptions >= 1) {
|
|
2082
|
-
this.log.info(`*Controller ${session.fabric?.rootVendorId}${getVendorIdName(session.fabric?.rootVendorId)}
|
|
2019
|
+
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}`);
|
|
2083
2020
|
connected = true;
|
|
2084
2021
|
}
|
|
2085
2022
|
});
|
|
@@ -2093,7 +2030,7 @@ export class Matterbridge extends EventEmitter {
|
|
|
2093
2030
|
}
|
|
2094
2031
|
setTimeout(() => {
|
|
2095
2032
|
if (this.bridgeMode === 'bridge') {
|
|
2096
|
-
//Logger.defaultLogLevel = Level.INFO;
|
|
2033
|
+
// Logger.defaultLogLevel = Level.INFO;
|
|
2097
2034
|
for (const plugin of this.registeredPlugins) {
|
|
2098
2035
|
if (!plugin.enabled || !plugin.loaded || plugin.error)
|
|
2099
2036
|
continue;
|
|
@@ -2108,7 +2045,7 @@ export class Matterbridge extends EventEmitter {
|
|
|
2108
2045
|
Logger.defaultLogLevel = this.debugEnabled ? Level.DEBUG : Level.INFO;
|
|
2109
2046
|
}
|
|
2110
2047
|
if (this.bridgeMode === 'childbridge') {
|
|
2111
|
-
//Logger.defaultLogLevel = Level.INFO;
|
|
2048
|
+
// Logger.defaultLogLevel = Level.INFO;
|
|
2112
2049
|
const plugin = this.findPlugin(pluginName);
|
|
2113
2050
|
if (plugin && plugin.type === 'DynamicPlatform' && plugin.configured !== true) {
|
|
2114
2051
|
for (const registeredDevice of this.registeredDevices) {
|
|
@@ -2140,10 +2077,10 @@ export class Matterbridge extends EventEmitter {
|
|
|
2140
2077
|
}
|
|
2141
2078
|
},
|
|
2142
2079
|
commissioningChangedCallback: async (fabricIndex) => {
|
|
2143
|
-
const
|
|
2144
|
-
this.log.debug(`*Commissioning changed on fabric ${fabricIndex} for ${plg}${pluginName}${nf}`, debugStringify(
|
|
2145
|
-
if (
|
|
2146
|
-
this.log.warn(`*Commissioning removed from fabric ${fabricIndex} for ${plg}${pluginName}${wr}. Resetting the commissioning server ...`);
|
|
2080
|
+
const fabricInfo = commissioningServer.getCommissionedFabricInformation(fabricIndex);
|
|
2081
|
+
this.log.debug(`*Commissioning changed on fabric ${zb}${fabricIndex}${nf} for ${plg}${pluginName}${nf}`, debugStringify(fabricInfo));
|
|
2082
|
+
if (commissioningServer.getCommissionedFabricInformation().length === 0) {
|
|
2083
|
+
this.log.warn(`*Commissioning removed from fabric ${zb}${fabricIndex}${nf} for ${plg}${pluginName}${wr}. Resetting the commissioning server ...`);
|
|
2147
2084
|
await commissioningServer.factoryReset();
|
|
2148
2085
|
if (pluginName === 'Matterbridge') {
|
|
2149
2086
|
await this.matterbridgeContext?.clearAll();
|
|
@@ -2609,14 +2546,14 @@ export class Matterbridge extends EventEmitter {
|
|
|
2609
2546
|
if (childProcess.stdout) {
|
|
2610
2547
|
childProcess.stdout.on('data', (data) => {
|
|
2611
2548
|
const message = data.toString().trim();
|
|
2612
|
-
//this.log.info('\n' + message);
|
|
2549
|
+
// this.log.info('\n' + message);
|
|
2613
2550
|
this.wssSendMessage('Matterbridge:spawn', 'spawn', message);
|
|
2614
2551
|
});
|
|
2615
2552
|
}
|
|
2616
2553
|
if (childProcess.stderr) {
|
|
2617
2554
|
childProcess.stderr.on('data', (data) => {
|
|
2618
2555
|
const message = data.toString().trim();
|
|
2619
|
-
//this.log.debug('\n' + message);
|
|
2556
|
+
// this.log.debug('\n' + message);
|
|
2620
2557
|
this.wssSendMessage('Matterbridge:spawn', 'spawn', message);
|
|
2621
2558
|
});
|
|
2622
2559
|
}
|
|
@@ -2650,12 +2587,12 @@ export class Matterbridge extends EventEmitter {
|
|
|
2650
2587
|
this.log.debug(`Initializing the frontend on port ${YELLOW}${port}${db} static ${UNDERLINE}${path.join(this.rootDirectory, 'frontend/build')}${UNDERLINEOFF}${rs}`);
|
|
2651
2588
|
const wssPort = 8284;
|
|
2652
2589
|
const useHttps = false;
|
|
2653
|
-
//const wssHost = (useHttps ? 'wss://' : 'ws://') + `${os.hostname().toLowerCase()}:${wssPort}`;
|
|
2590
|
+
// const wssHost = (useHttps ? 'wss://' : 'ws://') + `${os.hostname().toLowerCase()}:${wssPort}`;
|
|
2654
2591
|
const wssHost = (useHttps ? 'wss://' : 'ws://') + `${this.systemInformation.ipv4Address}:${wssPort}`;
|
|
2655
2592
|
if (!useHttps) {
|
|
2656
2593
|
// Create a WebSocket server no certificate required
|
|
2657
2594
|
this.webSocketServer = new WebSocketServer({ port: wssPort });
|
|
2658
|
-
this.log.info(`WebSocket server listening on ${UNDERLINE}${wssHost}${UNDERLINEOFF}${rs}`);
|
|
2595
|
+
// this.log.info(`WebSocket server listening on ${UNDERLINE}${wssHost}${UNDERLINEOFF}${rs}`);
|
|
2659
2596
|
}
|
|
2660
2597
|
else {
|
|
2661
2598
|
// Define the options for HTTPS server
|
|
@@ -2682,19 +2619,27 @@ export class Matterbridge extends EventEmitter {
|
|
|
2682
2619
|
this.log.debug('WebSocketServer activated logger callback');
|
|
2683
2620
|
this.wssSendMessage('Matterbridge', 'info', 'WebSocketServer client connected to Matterbridge');
|
|
2684
2621
|
ws.on('message', (message) => {
|
|
2685
|
-
this.log.info(`
|
|
2622
|
+
this.log.info(`WebSocket received message => ${message}`);
|
|
2686
2623
|
});
|
|
2687
2624
|
ws.on('close', () => {
|
|
2688
|
-
this.log.info('
|
|
2625
|
+
this.log.info('WebSocket client disconnected');
|
|
2689
2626
|
if (this.webSocketServer?.clients.size === 0) {
|
|
2690
2627
|
this.log.setGlobalCallback(undefined);
|
|
2691
|
-
this.log.debug('
|
|
2628
|
+
this.log.debug('WebSocket deactivated logger callback');
|
|
2692
2629
|
}
|
|
2693
2630
|
});
|
|
2694
2631
|
ws.on('error', (error) => {
|
|
2695
|
-
this.log.error(`
|
|
2632
|
+
this.log.error(`WebSocket error: ${error}`);
|
|
2696
2633
|
});
|
|
2697
2634
|
});
|
|
2635
|
+
this.webSocketServer.on('error', (ws, error) => {
|
|
2636
|
+
this.log.error(`WebSocketServer error: ${error}`);
|
|
2637
|
+
return;
|
|
2638
|
+
});
|
|
2639
|
+
this.webSocketServer.on('listening', () => {
|
|
2640
|
+
this.log.info(`WebSocketServer is listening on ${UNDERLINE}${wssHost}${UNDERLINEOFF}${rs}`);
|
|
2641
|
+
return;
|
|
2642
|
+
});
|
|
2698
2643
|
// Serve React build directory
|
|
2699
2644
|
this.expressApp = express();
|
|
2700
2645
|
this.expressApp.use(express.static(path.join(this.rootDirectory, 'frontend/build')));
|
|
@@ -2735,6 +2680,7 @@ export class Matterbridge extends EventEmitter {
|
|
|
2735
2680
|
if (this.bridgeMode === 'bridge')
|
|
2736
2681
|
this.log.error('pairingCode for /api/settings not found');
|
|
2737
2682
|
res.json({});
|
|
2683
|
+
return;
|
|
2738
2684
|
}
|
|
2739
2685
|
this.matterbridgeInformation.bridgeMode = this.bridgeMode;
|
|
2740
2686
|
this.matterbridgeInformation.restartMode = this.restartMode;
|
|
@@ -2793,7 +2739,7 @@ export class Matterbridge extends EventEmitter {
|
|
|
2793
2739
|
Object.entries(clusterServer.attributes).forEach(([key, value]) => {
|
|
2794
2740
|
if (clusterServer.name === 'EveHistory')
|
|
2795
2741
|
return;
|
|
2796
|
-
//this.log.debug(`***--clusterServer: ${clusterServer.name}(${clusterServer.id}) attribute:${key}(${value.id}) ${value.isFixed} ${value.isWritable} ${value.isWritable}`);
|
|
2742
|
+
// this.log.debug(`***--clusterServer: ${clusterServer.name}(${clusterServer.id}) attribute:${key}(${value.id}) ${value.isFixed} ${value.isWritable} ${value.isWritable}`);
|
|
2797
2743
|
let attributeValue;
|
|
2798
2744
|
try {
|
|
2799
2745
|
if (typeof value.getLocal() === 'object')
|
|
@@ -2804,7 +2750,7 @@ export class Matterbridge extends EventEmitter {
|
|
|
2804
2750
|
catch (error) {
|
|
2805
2751
|
attributeValue = 'Unavailable';
|
|
2806
2752
|
this.log.debug(`GetLocal value ${error} in clusterServer: ${clusterServer.name}(${clusterServer.id}) attribute: ${key}(${value.id})`);
|
|
2807
|
-
//console.log(error);
|
|
2753
|
+
// console.log(error);
|
|
2808
2754
|
}
|
|
2809
2755
|
data.push({
|
|
2810
2756
|
endpoint: registeredDevice.device.number ? registeredDevice.device.number.toString() : '...',
|
|
@@ -2823,7 +2769,7 @@ export class Matterbridge extends EventEmitter {
|
|
|
2823
2769
|
Object.entries(clusterServer.attributes).forEach(([key, value]) => {
|
|
2824
2770
|
if (clusterServer.name === 'EveHistory')
|
|
2825
2771
|
return;
|
|
2826
|
-
//this.log.debug(`***--clusterServer: ${clusterServer.name}(${clusterServer.id}) attribute:${key}(${value.id}) ${value.isFixed} ${value.isWritable} ${value.isWritable}`);
|
|
2772
|
+
// this.log.debug(`***--clusterServer: ${clusterServer.name}(${clusterServer.id}) attribute:${key}(${value.id}) ${value.isFixed} ${value.isWritable} ${value.isWritable}`);
|
|
2827
2773
|
let attributeValue;
|
|
2828
2774
|
try {
|
|
2829
2775
|
if (typeof value.getLocal() === 'object')
|
|
@@ -2834,7 +2780,7 @@ export class Matterbridge extends EventEmitter {
|
|
|
2834
2780
|
catch (error) {
|
|
2835
2781
|
attributeValue = 'Unavailable';
|
|
2836
2782
|
this.log.debug(`GetLocal error ${error} in clusterServer: ${clusterServer.name}(${clusterServer.id}) attribute: ${key}(${value.id})`);
|
|
2837
|
-
//console.log(error);
|
|
2783
|
+
// console.log(error);
|
|
2838
2784
|
}
|
|
2839
2785
|
data.push({
|
|
2840
2786
|
endpoint: (childEndpoint.number ? childEndpoint.number.toString() : '...') + (name ? ' (' + name + ')' : ''),
|
|
@@ -2932,7 +2878,7 @@ export class Matterbridge extends EventEmitter {
|
|
|
2932
2878
|
if (command === 'saveconfig') {
|
|
2933
2879
|
param = param.replace(/\*/g, '\\');
|
|
2934
2880
|
this.log.info(`Saving config for plugin ${plg}${param}${nf}...`);
|
|
2935
|
-
//console.log('Req.body:', JSON.stringify(req.body, null, 2));
|
|
2881
|
+
// console.log('Req.body:', JSON.stringify(req.body, null, 2));
|
|
2936
2882
|
const plugins = await this.nodeContext?.get('plugins');
|
|
2937
2883
|
if (!plugins)
|
|
2938
2884
|
return;
|
|
@@ -3085,6 +3031,21 @@ export class Matterbridge extends EventEmitter {
|
|
|
3085
3031
|
this.expressServer = this.expressApp.listen(port, () => {
|
|
3086
3032
|
this.log.info(`The frontend is listening on ${UNDERLINE}http://${this.systemInformation.ipv4Address}:${port}${UNDERLINEOFF}${rs}`);
|
|
3087
3033
|
});
|
|
3034
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
3035
|
+
this.expressServer.on('error', (error) => {
|
|
3036
|
+
this.log.error(`Frontend error listening on ${UNDERLINE}http://${this.systemInformation.ipv4Address}:${port}${UNDERLINEOFF}${rs}`);
|
|
3037
|
+
switch (error.code) {
|
|
3038
|
+
case 'EACCES':
|
|
3039
|
+
this.log.error(`Port ${port} requires elevated privileges`);
|
|
3040
|
+
break;
|
|
3041
|
+
case 'EADDRINUSE':
|
|
3042
|
+
this.log.error(`Port ${port} is already in use`);
|
|
3043
|
+
break;
|
|
3044
|
+
default:
|
|
3045
|
+
this.log.error(`Port ${port} requires elevated privileges`);
|
|
3046
|
+
}
|
|
3047
|
+
process.exit(1);
|
|
3048
|
+
});
|
|
3088
3049
|
}
|
|
3089
3050
|
else {
|
|
3090
3051
|
// SSL certificate and private key paths
|
|
@@ -3116,13 +3077,13 @@ export class Matterbridge extends EventEmitter {
|
|
|
3116
3077
|
if (composed)
|
|
3117
3078
|
return 'Composed: ' + composed.value;
|
|
3118
3079
|
else
|
|
3119
|
-
return ''; //'FixedLabel: ' + labelList.map((entry) => entry.label + ': ' + entry.value).join(' ');
|
|
3080
|
+
return ''; // 'FixedLabel: ' + labelList.map((entry) => entry.label + ': ' + entry.value).join(' ');
|
|
3120
3081
|
};
|
|
3121
3082
|
let attributes = '';
|
|
3122
|
-
//this.log.debug(`getClusterTextFromDevice: ${device.name}`);
|
|
3083
|
+
// this.log.debug(`getClusterTextFromDevice: ${device.name}`);
|
|
3123
3084
|
const clusterServers = device.getAllClusterServers();
|
|
3124
3085
|
clusterServers.forEach((clusterServer) => {
|
|
3125
|
-
//this.log.debug(`***--clusterServer: ${clusterServer.id} (${clusterServer.name})`);
|
|
3086
|
+
// this.log.debug(`***--clusterServer: ${clusterServer.id} (${clusterServer.name})`);
|
|
3126
3087
|
if (clusterServer.name === 'OnOff')
|
|
3127
3088
|
attributes += `OnOff: ${clusterServer.getOnOffAttribute()} `;
|
|
3128
3089
|
if (clusterServer.name === 'Switch')
|