matterbridge 2.1.0-dev.1 → 2.1.0-dev.11
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +10 -6
- package/dist/frontend.js +159 -91
- package/dist/index.js +1 -0
- package/dist/matter/behaviors.js +1 -0
- package/dist/matter/clusters.js +1 -0
- package/dist/matter/devices.js +1 -0
- package/dist/matter/endpoints.js +1 -0
- package/dist/matter/export.js +1 -4
- package/dist/matter/types.js +2 -0
- package/dist/matterbridge.js +4 -14
- package/dist/matterbridgeBehaviors.js +5 -0
- package/dist/matterbridgeEndpoint.js +53 -398
- package/dist/matterbridgeEndpointHelpers.js +513 -0
- package/dist/matterbridgePlatform.js +3 -3
- package/dist/matterbridgeTypes.js +0 -3
- package/npm-shrinkwrap.json +47 -54
- package/package.json +22 -2
package/CHANGELOG.md
CHANGED
|
@@ -16,24 +16,28 @@ Tamer (https://github.com/tammeryousef1006) has created the Matterbridge Discord
|
|
|
16
16
|
### Breaking Changes
|
|
17
17
|
|
|
18
18
|
Starting from v. 2.0.0 Matterbridge is running only in mode edge (no parameter needed and no badge in the frontend).
|
|
19
|
-
|
|
19
|
+
With this release v. 2.1.0, the legacy old api of matter.js have been completely removed from Matterbridge and from all plugins.
|
|
20
|
+
For this reason there is no compatibility for old versions of the plugins.
|
|
21
|
+
You need to update all plugins you use and Matterbridge in the same moment.
|
|
22
|
+
I suggest to first update all plugins without restarting and then to update Matterbridge so when it restarts, all versions will be the latest.
|
|
20
23
|
|
|
21
|
-
|
|
22
|
-
It is possible to change the mode (Classic, Dark or Light) in Settings, Matterbridge settings.
|
|
23
|
-
|
|
24
|
-
## [2.1.0.dev.1] - 2025-01-26
|
|
24
|
+
## [2.1.0.dev.11] - 2025-02-01
|
|
25
25
|
|
|
26
26
|
### Added
|
|
27
27
|
|
|
28
28
|
- [matterbridge]: Add MatterbridgeModeSelectServer.
|
|
29
|
+
- [matterbridge]: Add MatterbridgeSwitchServer.
|
|
29
30
|
- [frontend]: Add api/advertise to turn on matter advertising in bridge mode.
|
|
30
31
|
- [frontend]: Frontend v.2.4.0.
|
|
32
|
+
- [matterbridge]: Added deep memory scan details.
|
|
33
|
+
|
|
31
34
|
|
|
32
35
|
### Changed
|
|
33
36
|
|
|
37
|
+
- [package]: Removed legacy imports.
|
|
34
38
|
- [package]: Update dependencies.
|
|
35
39
|
- [package]: Update matter.js to 0.12.0.
|
|
36
|
-
- [package]:
|
|
40
|
+
- [package]: Update matter.js to 0.12.1.
|
|
37
41
|
|
|
38
42
|
### Fixed
|
|
39
43
|
|
package/dist/frontend.js
CHANGED
|
@@ -7,7 +7,7 @@ import os from 'os';
|
|
|
7
7
|
import path from 'path';
|
|
8
8
|
import { promises as fs } from 'fs';
|
|
9
9
|
import { AnsiLogger, CYAN, db, debugStringify, er, nf, rs, stringify, UNDERLINE, UNDERLINEOFF, wr, YELLOW } from './logger/export.js';
|
|
10
|
-
import { createZip, hasParameter, isValidNumber, isValidObject, isValidString } from './utils/utils.js';
|
|
10
|
+
import { createZip, getIntParameter, hasParameter, isValidNumber, isValidObject, isValidString } from './utils/utils.js';
|
|
11
11
|
import { plg } from './matterbridgeTypes.js';
|
|
12
12
|
import { MatterbridgeEndpoint } from './matterbridgeEndpoint.js';
|
|
13
13
|
export const WS_ID_LOG = 0;
|
|
@@ -22,10 +22,16 @@ export class Frontend {
|
|
|
22
22
|
httpServer;
|
|
23
23
|
httpsServer;
|
|
24
24
|
webSocketServer;
|
|
25
|
+
memoryData = [];
|
|
26
|
+
memoryInterval;
|
|
27
|
+
memoryTimeout;
|
|
25
28
|
constructor(matterbridge) {
|
|
26
29
|
this.matterbridge = matterbridge;
|
|
27
30
|
this.log = new AnsiLogger({ logName: 'Frontend', logTimestampFormat: 4, logLevel: hasParameter('debug') ? "debug" : "info" });
|
|
28
31
|
}
|
|
32
|
+
set logLevel(logLevel) {
|
|
33
|
+
this.log.logLevel = logLevel;
|
|
34
|
+
}
|
|
29
35
|
async start(port = 8283) {
|
|
30
36
|
this.port = port;
|
|
31
37
|
this.log.debug(`Initializing the frontend ${hasParameter('ssl') ? 'https' : 'http'} server on port ${YELLOW}${this.port}${db}`);
|
|
@@ -155,6 +161,9 @@ export class Frontend {
|
|
|
155
161
|
this.webSocketServer.on('error', (ws, error) => {
|
|
156
162
|
this.log.error(`WebSocketServer error: ${error}`);
|
|
157
163
|
});
|
|
164
|
+
if (hasParameter('memorydump')) {
|
|
165
|
+
this.startMemoryDump();
|
|
166
|
+
}
|
|
158
167
|
this.expressApp.post('/api/login', express.json(), async (req, res) => {
|
|
159
168
|
const { password } = req.body;
|
|
160
169
|
this.log.debug('The frontend sent /api/login', password);
|
|
@@ -190,29 +199,24 @@ export class Frontend {
|
|
|
190
199
|
});
|
|
191
200
|
this.expressApp.get('/memory', async (req, res) => {
|
|
192
201
|
this.log.debug('Express received /memory');
|
|
193
|
-
const formatMemoryUsage = (bytes) => {
|
|
194
|
-
const kb = bytes / 1024;
|
|
195
|
-
const mb = kb / 1024;
|
|
196
|
-
return mb >= 1 ? `${mb.toFixed(2)} MB` : `${kb.toFixed(2)} KB`;
|
|
197
|
-
};
|
|
198
202
|
const memoryUsageRaw = process.memoryUsage();
|
|
199
203
|
const memoryUsage = {
|
|
200
|
-
rss: formatMemoryUsage(memoryUsageRaw.rss),
|
|
201
|
-
heapTotal: formatMemoryUsage(memoryUsageRaw.heapTotal),
|
|
202
|
-
heapUsed: formatMemoryUsage(memoryUsageRaw.heapUsed),
|
|
203
|
-
external: formatMemoryUsage(memoryUsageRaw.external),
|
|
204
|
-
arrayBuffers: formatMemoryUsage(memoryUsageRaw.arrayBuffers),
|
|
204
|
+
rss: this.formatMemoryUsage(memoryUsageRaw.rss),
|
|
205
|
+
heapTotal: this.formatMemoryUsage(memoryUsageRaw.heapTotal),
|
|
206
|
+
heapUsed: this.formatMemoryUsage(memoryUsageRaw.heapUsed),
|
|
207
|
+
external: this.formatMemoryUsage(memoryUsageRaw.external),
|
|
208
|
+
arrayBuffers: this.formatMemoryUsage(memoryUsageRaw.arrayBuffers),
|
|
205
209
|
};
|
|
206
210
|
const { default: v8 } = await import('node:v8');
|
|
207
211
|
const heapStatsRaw = v8.getHeapStatistics();
|
|
208
212
|
const heapSpacesRaw = v8.getHeapSpaceStatistics();
|
|
209
|
-
const heapStats = Object.fromEntries(Object.entries(heapStatsRaw).map(([key, value]) => [key, formatMemoryUsage(value)]));
|
|
213
|
+
const heapStats = Object.fromEntries(Object.entries(heapStatsRaw).map(([key, value]) => [key, this.formatMemoryUsage(value)]));
|
|
210
214
|
const heapSpaces = heapSpacesRaw.map((space) => ({
|
|
211
215
|
...space,
|
|
212
|
-
space_size: formatMemoryUsage(space.space_size),
|
|
213
|
-
space_used_size: formatMemoryUsage(space.space_used_size),
|
|
214
|
-
space_available_size: formatMemoryUsage(space.space_available_size),
|
|
215
|
-
physical_space_size: formatMemoryUsage(space.physical_space_size),
|
|
216
|
+
space_size: this.formatMemoryUsage(space.space_size),
|
|
217
|
+
space_used_size: this.formatMemoryUsage(space.space_used_size),
|
|
218
|
+
space_available_size: this.formatMemoryUsage(space.space_available_size),
|
|
219
|
+
physical_space_size: this.formatMemoryUsage(space.physical_space_size),
|
|
216
220
|
}));
|
|
217
221
|
const { default: module } = await import('module');
|
|
218
222
|
const loadedModules = module._cache ? Object.keys(module._cache).sort() : [];
|
|
@@ -226,7 +230,13 @@ export class Frontend {
|
|
|
226
230
|
});
|
|
227
231
|
this.expressApp.get('/api/advertise', express.json(), async (req, res) => {
|
|
228
232
|
const pairingCodes = await this.matterbridge.advertiseServerNode(this.matterbridge.serverNode);
|
|
229
|
-
|
|
233
|
+
if (pairingCodes) {
|
|
234
|
+
const { manualPairingCode, qrPairingCode } = pairingCodes;
|
|
235
|
+
res.json({ manualPairingCode, qrPairingCode: 'https://project-chip.github.io/connectedhomeip/qrcode.html?data=' + qrPairingCode });
|
|
236
|
+
}
|
|
237
|
+
else {
|
|
238
|
+
res.status(500).json({ error: 'Failed to generate pairing codes' });
|
|
239
|
+
}
|
|
230
240
|
});
|
|
231
241
|
this.expressApp.get('/api/settings', express.json(), async (req, res) => {
|
|
232
242
|
this.log.debug('The frontend sent /api/settings');
|
|
@@ -472,7 +482,9 @@ export class Frontend {
|
|
|
472
482
|
this.log.logLevel = "fatal";
|
|
473
483
|
}
|
|
474
484
|
await this.matterbridge.nodeContext?.set('matterbridgeLogLevel', this.log.logLevel);
|
|
485
|
+
this.matterbridge.log.logLevel = this.log.logLevel;
|
|
475
486
|
MatterbridgeEndpoint.logLevel = this.log.logLevel;
|
|
487
|
+
this.matterbridge.devices.logLevel = this.log.logLevel;
|
|
476
488
|
this.matterbridge.plugins.logLevel = this.log.logLevel;
|
|
477
489
|
for (const plugin of this.matterbridge.plugins) {
|
|
478
490
|
if (!plugin.platform || !plugin.platform.config)
|
|
@@ -773,11 +785,58 @@ export class Frontend {
|
|
|
773
785
|
});
|
|
774
786
|
this.webSocketServer = undefined;
|
|
775
787
|
}
|
|
788
|
+
if (hasParameter('memorydump')) {
|
|
789
|
+
this.stopMemoryDump();
|
|
790
|
+
}
|
|
791
|
+
}
|
|
792
|
+
formatMemoryUsage = (bytes) => {
|
|
793
|
+
const kb = bytes / 1024;
|
|
794
|
+
const mb = kb / 1024;
|
|
795
|
+
return mb >= 1 ? `${mb.toFixed(2)} MB` : `${kb.toFixed(2)} KB`;
|
|
796
|
+
};
|
|
797
|
+
startMemoryDump() {
|
|
798
|
+
clearInterval(this.memoryInterval);
|
|
799
|
+
clearTimeout(this.memoryTimeout);
|
|
800
|
+
const interval = () => {
|
|
801
|
+
const memoryUsageRaw = process.memoryUsage();
|
|
802
|
+
this.memoryData.push(memoryUsageRaw);
|
|
803
|
+
const memoryUsage = {
|
|
804
|
+
rss: this.formatMemoryUsage(memoryUsageRaw.rss),
|
|
805
|
+
heapTotal: this.formatMemoryUsage(memoryUsageRaw.heapTotal),
|
|
806
|
+
heapUsed: this.formatMemoryUsage(memoryUsageRaw.heapUsed),
|
|
807
|
+
external: this.formatMemoryUsage(memoryUsageRaw.external),
|
|
808
|
+
arrayBuffers: this.formatMemoryUsage(memoryUsageRaw.arrayBuffers),
|
|
809
|
+
};
|
|
810
|
+
this.log.debug(`***Memory usage rss ${CYAN}${memoryUsage.rss}${db} heapTotal ${CYAN}${memoryUsage.heapTotal}${db} heapUsed ${CYAN}${memoryUsage.heapUsed}${db} external ${memoryUsage.external} arrayBuffers ${memoryUsage.arrayBuffers}`);
|
|
811
|
+
};
|
|
812
|
+
interval();
|
|
813
|
+
this.memoryInterval = setInterval(interval, getIntParameter('memorydump') ?? 1000);
|
|
814
|
+
this.memoryInterval.unref();
|
|
815
|
+
this.memoryTimeout = setTimeout(() => {
|
|
816
|
+
this.stopMemoryDump();
|
|
817
|
+
}, 360000);
|
|
818
|
+
this.memoryTimeout.unref();
|
|
819
|
+
}
|
|
820
|
+
stopMemoryDump() {
|
|
821
|
+
clearInterval(this.memoryInterval);
|
|
822
|
+
this.memoryInterval = undefined;
|
|
823
|
+
clearTimeout(this.memoryTimeout);
|
|
824
|
+
this.memoryTimeout = undefined;
|
|
825
|
+
for (const memory of this.memoryData) {
|
|
826
|
+
const memoryUsage = {
|
|
827
|
+
rss: this.formatMemoryUsage(memory.rss),
|
|
828
|
+
heapTotal: this.formatMemoryUsage(memory.heapTotal),
|
|
829
|
+
heapUsed: this.formatMemoryUsage(memory.heapUsed),
|
|
830
|
+
external: this.formatMemoryUsage(memory.external),
|
|
831
|
+
arrayBuffers: this.formatMemoryUsage(memory.arrayBuffers),
|
|
832
|
+
};
|
|
833
|
+
this.log.debug(`***Memory usage rss ${CYAN}${memoryUsage.rss}${db} heapTotal ${CYAN}${memoryUsage.heapTotal}${db} heapUsed ${CYAN}${memoryUsage.heapUsed}${db} external ${memoryUsage.external} arrayBuffers ${memoryUsage.arrayBuffers}`);
|
|
834
|
+
}
|
|
776
835
|
}
|
|
777
836
|
async getApiSettings() {
|
|
778
837
|
this.matterbridge.matterbridgeInformation.bridgeMode = this.matterbridge.bridgeMode;
|
|
779
838
|
this.matterbridge.matterbridgeInformation.restartMode = this.matterbridge.restartMode;
|
|
780
|
-
this.matterbridge.matterbridgeInformation.loggerLevel = this.log.logLevel;
|
|
839
|
+
this.matterbridge.matterbridgeInformation.loggerLevel = this.matterbridge.log.logLevel;
|
|
781
840
|
this.matterbridge.matterbridgeInformation.matterLoggerLevel = Logger.defaultLogLevel;
|
|
782
841
|
this.matterbridge.matterbridgeInformation.mattermdnsinterface = this.matterbridge.mdnsInterface;
|
|
783
842
|
this.matterbridge.matterbridgeInformation.matteripv4address = this.matterbridge.ipv4address;
|
|
@@ -830,77 +889,83 @@ export class Frontend {
|
|
|
830
889
|
return '';
|
|
831
890
|
};
|
|
832
891
|
let attributes = '';
|
|
833
|
-
|
|
834
|
-
|
|
835
|
-
|
|
836
|
-
|
|
837
|
-
|
|
838
|
-
|
|
839
|
-
|
|
840
|
-
|
|
841
|
-
|
|
842
|
-
|
|
843
|
-
|
|
844
|
-
|
|
845
|
-
|
|
846
|
-
|
|
847
|
-
|
|
848
|
-
|
|
849
|
-
|
|
850
|
-
|
|
851
|
-
|
|
852
|
-
|
|
853
|
-
|
|
854
|
-
|
|
855
|
-
|
|
856
|
-
|
|
857
|
-
|
|
858
|
-
|
|
859
|
-
|
|
860
|
-
|
|
861
|
-
|
|
862
|
-
|
|
863
|
-
|
|
864
|
-
|
|
865
|
-
|
|
866
|
-
|
|
867
|
-
|
|
868
|
-
|
|
869
|
-
|
|
870
|
-
|
|
871
|
-
|
|
872
|
-
|
|
873
|
-
|
|
874
|
-
|
|
875
|
-
|
|
876
|
-
|
|
877
|
-
|
|
878
|
-
|
|
879
|
-
|
|
880
|
-
|
|
881
|
-
|
|
882
|
-
|
|
883
|
-
|
|
884
|
-
|
|
885
|
-
|
|
886
|
-
|
|
887
|
-
|
|
888
|
-
|
|
889
|
-
|
|
890
|
-
|
|
891
|
-
|
|
892
|
-
|
|
893
|
-
|
|
894
|
-
|
|
895
|
-
|
|
896
|
-
|
|
897
|
-
|
|
898
|
-
|
|
899
|
-
|
|
900
|
-
|
|
901
|
-
|
|
902
|
-
|
|
903
|
-
|
|
892
|
+
device.forEachAttribute((clusterName, clusterId, attributeName, attributeId, attributeValue) => {
|
|
893
|
+
if (typeof attributeValue === 'undefined')
|
|
894
|
+
return;
|
|
895
|
+
if (clusterName === 'onOff' && attributeName === 'onOff')
|
|
896
|
+
attributes += `OnOff: ${attributeValue} `;
|
|
897
|
+
if (clusterName === 'switch' && attributeName === 'currentPosition')
|
|
898
|
+
attributes += `Position: ${attributeValue} `;
|
|
899
|
+
if (clusterName === 'windowCovering' && attributeName === 'currentPositionLiftPercent100ths' && isValidNumber(attributeValue, 0, 10000))
|
|
900
|
+
attributes += `Cover position: ${attributeValue / 100}% `;
|
|
901
|
+
if (clusterName === 'doorLock' && attributeName === 'lockState')
|
|
902
|
+
attributes += `State: ${attributeValue === 1 ? 'Locked' : 'Not locked'} `;
|
|
903
|
+
if (clusterName === 'thermostat' && attributeName === 'localTemperature' && isValidNumber(attributeValue))
|
|
904
|
+
attributes += `Temperature: ${attributeValue / 100}°C `;
|
|
905
|
+
if (clusterName === 'thermostat' && attributeName === 'occupiedHeatingSetpoint' && isValidNumber(attributeValue))
|
|
906
|
+
attributes += `Heat to: ${attributeValue / 100}°C `;
|
|
907
|
+
if (clusterName === 'thermostat' && attributeName === 'occupiedCoolingSetpoint' && isValidNumber(attributeValue))
|
|
908
|
+
attributes += `Cool to: ${attributeValue / 100}°C `;
|
|
909
|
+
if (clusterName === 'pumpConfigurationAndControl' && attributeName === 'operationMode')
|
|
910
|
+
attributes += `Mode: ${attributeValue} `;
|
|
911
|
+
if (clusterName === 'valveConfigurationAndControl' && attributeName === 'currentState')
|
|
912
|
+
attributes += `State: ${attributeValue} `;
|
|
913
|
+
if (clusterName === 'levelControl' && attributeName === 'currentLevel')
|
|
914
|
+
attributes += `Level: ${attributeValue} `;
|
|
915
|
+
if (clusterName === 'colorControl' && attributeName === 'colorMode' && isValidNumber(attributeValue, 0, 2))
|
|
916
|
+
attributes += `Mode: ${['HS', 'XY', 'CT'][attributeValue]} `;
|
|
917
|
+
if (clusterName === 'colorControl' && getAttribute(device, 'colorControl', 'colorMode') === 0 && attributeName === 'currentHue' && isValidNumber(attributeValue))
|
|
918
|
+
attributes += `Hue: ${Math.round(attributeValue)} `;
|
|
919
|
+
if (clusterName === 'colorControl' && getAttribute(device, 'colorControl', 'colorMode') === 0 && attributeName === 'currentSaturation' && isValidNumber(attributeValue))
|
|
920
|
+
attributes += `Saturation: ${Math.round(attributeValue)} `;
|
|
921
|
+
if (clusterName === 'colorControl' && getAttribute(device, 'colorControl', 'colorMode') === 1 && attributeName === 'currentX' && isValidNumber(attributeValue))
|
|
922
|
+
attributes += `X: ${Math.round(attributeValue / 655.36) / 100} `;
|
|
923
|
+
if (clusterName === 'colorControl' && getAttribute(device, 'colorControl', 'colorMode') === 1 && attributeName === 'currentY' && isValidNumber(attributeValue))
|
|
924
|
+
attributes += `Y: ${Math.round(attributeValue / 655.36) / 100} `;
|
|
925
|
+
if (clusterName === 'colorControl' && getAttribute(device, 'colorControl', 'colorMode') === 2 && attributeName === 'colorTemperatureMireds' && isValidNumber(attributeValue))
|
|
926
|
+
attributes += `ColorTemp: ${Math.round(attributeValue)} `;
|
|
927
|
+
if (clusterName === 'booleanState' && attributeName === 'stateValue')
|
|
928
|
+
attributes += `Contact: ${attributeValue} `;
|
|
929
|
+
if (clusterName === 'booleanStateConfiguration' && attributeName === 'alarmsActive' && isValidObject(attributeValue))
|
|
930
|
+
attributes += `Active alarms: ${stringify(attributeValue)} `;
|
|
931
|
+
if (clusterName === 'smokeCoAlarm' && attributeName === 'smokeState')
|
|
932
|
+
attributes += `Smoke: ${attributeValue} `;
|
|
933
|
+
if (clusterName === 'smokeCoAlarm' && attributeName === 'coState')
|
|
934
|
+
attributes += `Co: ${attributeValue} `;
|
|
935
|
+
if (clusterName === 'fanControl' && attributeName === 'fanMode')
|
|
936
|
+
attributes += `Mode: ${attributeValue} `;
|
|
937
|
+
if (clusterName === 'fanControl' && attributeName === 'percentCurrent')
|
|
938
|
+
attributes += `Percent: ${attributeValue} `;
|
|
939
|
+
if (clusterName === 'fanControl' && attributeName === 'speedCurrent')
|
|
940
|
+
attributes += `Speed: ${attributeValue} `;
|
|
941
|
+
if (clusterName === 'occupancySensing' && attributeName === 'occupancy' && isValidObject(attributeValue, 1))
|
|
942
|
+
attributes += `Occupancy: ${attributeValue.occupied} `;
|
|
943
|
+
if (clusterName === 'illuminanceMeasurement' && attributeName === 'measuredValue' && isValidNumber(attributeValue))
|
|
944
|
+
attributes += `Illuminance: ${Math.round(Math.max(Math.pow(10, attributeValue / 10000), 0))} `;
|
|
945
|
+
if (clusterName === 'airQuality' && attributeName === 'airQuality')
|
|
946
|
+
attributes += `Air quality: ${attributeValue} `;
|
|
947
|
+
if (clusterName === 'totalVolatileOrganicCompoundsConcentrationMeasurement' && attributeName === 'measuredValue')
|
|
948
|
+
attributes += `Voc: ${attributeValue} `;
|
|
949
|
+
if (clusterName === 'pm1ConcentrationMeasurement' && attributeName === 'measuredValue')
|
|
950
|
+
attributes += `Pm1: ${attributeValue} `;
|
|
951
|
+
if (clusterName === 'pm25ConcentrationMeasurement' && attributeName === 'measuredValue')
|
|
952
|
+
attributes += `Pm2.5: ${attributeValue} `;
|
|
953
|
+
if (clusterName === 'pm10ConcentrationMeasurement' && attributeName === 'measuredValue')
|
|
954
|
+
attributes += `Pm10: ${attributeValue} `;
|
|
955
|
+
if (clusterName === 'formaldehydeConcentrationMeasurement' && attributeName === 'measuredValue')
|
|
956
|
+
attributes += `CH₂O: ${attributeValue} `;
|
|
957
|
+
if (clusterName === 'temperatureMeasurement' && attributeName === 'measuredValue' && isValidNumber(attributeValue))
|
|
958
|
+
attributes += `Temperature: ${attributeValue / 100}°C `;
|
|
959
|
+
if (clusterName === 'relativeHumidityMeasurement' && attributeName === 'measuredValue' && isValidNumber(attributeValue))
|
|
960
|
+
attributes += `Humidity: ${attributeValue / 100}% `;
|
|
961
|
+
if (clusterName === 'pressureMeasurement' && attributeName === 'measuredValue')
|
|
962
|
+
attributes += `Pressure: ${attributeValue} `;
|
|
963
|
+
if (clusterName === 'flowMeasurement' && attributeName === 'measuredValue')
|
|
964
|
+
attributes += `Flow: ${attributeValue} `;
|
|
965
|
+
if (clusterName === 'fixedLabel' && attributeName === 'labelList')
|
|
966
|
+
attributes += `${getFixedLabel(device)} `;
|
|
967
|
+
if (clusterName === 'userLabel' && attributeName === 'labelList')
|
|
968
|
+
attributes += `${getUserLabel(device)} `;
|
|
904
969
|
});
|
|
905
970
|
return attributes.trimStart().trimEnd();
|
|
906
971
|
}
|
|
@@ -1066,8 +1131,11 @@ export class Frontend {
|
|
|
1066
1131
|
const clusterServers = endpointServer.getAllClusterServers();
|
|
1067
1132
|
clusterServers.forEach((clusterServer) => {
|
|
1068
1133
|
Object.entries(clusterServer.attributes).forEach(([key, value]) => {
|
|
1069
|
-
if (clusterServer.name === 'EveHistory')
|
|
1070
|
-
|
|
1134
|
+
if (clusterServer.name === 'EveHistory') {
|
|
1135
|
+
if (['configDataGet', 'configDataSet', 'historyStatus', 'historyEntries', 'historyRequest', 'historySetTime', 'rLoc'].includes(key)) {
|
|
1136
|
+
return;
|
|
1137
|
+
}
|
|
1138
|
+
}
|
|
1071
1139
|
if (clusterServer.name === 'Descriptor' && key === 'deviceTypeList') {
|
|
1072
1140
|
value.getLocal().forEach((deviceType) => {
|
|
1073
1141
|
deviceTypes.push(deviceType.deviceType);
|
package/dist/index.js
CHANGED
|
@@ -5,6 +5,7 @@ export * from '@matter/main/types';
|
|
|
5
5
|
export * from './matterbridge.js';
|
|
6
6
|
export * from './matterbridgeTypes.js';
|
|
7
7
|
export * from './matterbridgeEndpoint.js';
|
|
8
|
+
export * from './matterbridgeEndpointHelpers.js';
|
|
8
9
|
export * from './matterbridgeBehaviors.js';
|
|
9
10
|
export * from './matterbridgeDeviceTypes.js';
|
|
10
11
|
export * from './matterbridgePlatform.js';
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export * from '@matter/node/behaviors';
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export * from '@matter/types/clusters';
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export * from '@matter/node/devices';
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export { AggregatorEndpoint, ElectricalSensorEndpoint, PowerSourceEndpoint, BridgedNodeEndpoint, RootEndpoint, DeviceEnergyManagementEndpoint, OtaProviderEndpoint, OtaRequestorEndpoint } from '@matter/node/endpoints';
|
package/dist/matter/export.js
CHANGED
|
@@ -1,6 +1,3 @@
|
|
|
1
1
|
export * from '@matter/main';
|
|
2
|
-
export {
|
|
3
|
-
export * from '@matter/main/devices';
|
|
4
|
-
export * from '@matter/main/behaviors';
|
|
5
|
-
export { FabricAction, MdnsService, PaseClient } from '@matter/main/protocol';
|
|
2
|
+
export { SemanticNamespace, ClosureTag, CompassDirectionTag, CompassLocationTag, DirectionTag, ElectricalMeasurementTag, LaundryTag, LevelTag, LocationTag, NumberTag, PositionTag, PowerSourceTag, RefrigeratorTag, RoomAirConditionerTag, SwitchesTag, } from '@matter/main';
|
|
6
3
|
export { AttributeElement, ClusterElement, ClusterModel, CommandElement, EventElement, FieldElement } from '@matter/main/model';
|
package/dist/matterbridge.js
CHANGED
|
@@ -7,7 +7,7 @@ import path from 'path';
|
|
|
7
7
|
import { randomBytes } from 'crypto';
|
|
8
8
|
import { NodeStorageManager } from './storage/export.js';
|
|
9
9
|
import { AnsiLogger, UNDERLINE, UNDERLINEOFF, YELLOW, db, debugStringify, BRIGHT, RESET, er, nf, rs, wr, RED, GREEN, zb, CYAN, nt } from './logger/export.js';
|
|
10
|
-
import { logInterfaces,
|
|
10
|
+
import { logInterfaces, copyDirectory, getParameter, getIntParameter, hasParameter } from './utils/utils.js';
|
|
11
11
|
import { PluginManager } from './pluginManager.js';
|
|
12
12
|
import { DeviceManager } from './deviceManager.js';
|
|
13
13
|
import { MatterbridgeEndpoint } from './matterbridgeEndpoint.js';
|
|
@@ -140,10 +140,6 @@ export class Matterbridge extends EventEmitter {
|
|
|
140
140
|
}
|
|
141
141
|
async destroyInstance() {
|
|
142
142
|
await this.cleanup('destroying instance...', false);
|
|
143
|
-
await waiter('destroying instance...', () => {
|
|
144
|
-
return this.initialized === false && this.execRunningCount <= 0 ? true : false;
|
|
145
|
-
}, false, 60000, 100, false);
|
|
146
|
-
await wait(1000, 'Wait for the global node_modules and matterbridge version', false);
|
|
147
143
|
}
|
|
148
144
|
async initialize() {
|
|
149
145
|
if (hasParameter('service'))
|
|
@@ -314,7 +310,9 @@ export class Matterbridge extends EventEmitter {
|
|
|
314
310
|
}
|
|
315
311
|
this.plugins = new PluginManager(this);
|
|
316
312
|
await this.plugins.loadFromStorage();
|
|
313
|
+
this.plugins.logLevel = this.log.logLevel;
|
|
317
314
|
this.devices = new DeviceManager(this, this.nodeContext);
|
|
315
|
+
this.devices.logLevel = this.log.logLevel;
|
|
318
316
|
for (const plugin of this.plugins) {
|
|
319
317
|
const packageJson = await this.plugins.parse(plugin);
|
|
320
318
|
if (packageJson === null && !hasParameter('add') && !hasParameter('remove') && !hasParameter('enable') && !hasParameter('disable') && !hasParameter('reset') && !hasParameter('factoryreset')) {
|
|
@@ -499,6 +497,7 @@ export class Matterbridge extends EventEmitter {
|
|
|
499
497
|
}
|
|
500
498
|
if (getIntParameter('frontend') !== 0 || getIntParameter('frontend') === undefined)
|
|
501
499
|
await this.frontend.start(getIntParameter('frontend'));
|
|
500
|
+
this.frontend.logLevel = this.log.logLevel;
|
|
502
501
|
this.checkUpdateInterval = setInterval(() => {
|
|
503
502
|
this.getMatterbridgeLatestVersion();
|
|
504
503
|
for (const plugin of this.plugins) {
|
|
@@ -1021,15 +1020,6 @@ export class Matterbridge extends EventEmitter {
|
|
|
1021
1020
|
catch (error) {
|
|
1022
1021
|
}
|
|
1023
1022
|
if (this.nodeStorage && this.nodeContext) {
|
|
1024
|
-
this.log.info('Saving registered devices...');
|
|
1025
|
-
const serializedRegisteredDevices = [];
|
|
1026
|
-
this.devices.forEach(async (device) => {
|
|
1027
|
-
const serializedMatterbridgeDevice = MatterbridgeEndpoint.serialize(device);
|
|
1028
|
-
if (serializedMatterbridgeDevice)
|
|
1029
|
-
serializedRegisteredDevices.push(serializedMatterbridgeDevice);
|
|
1030
|
-
});
|
|
1031
|
-
await this.nodeContext.set('devices', serializedRegisteredDevices);
|
|
1032
|
-
this.log.info(`Saved registered devices (${serializedRegisteredDevices?.length})`);
|
|
1033
1023
|
this.log.debug(`Closing node storage context for ${plg}Matterbridge${db}...`);
|
|
1034
1024
|
await this.nodeContext.close();
|
|
1035
1025
|
this.nodeContext = undefined;
|
|
@@ -18,6 +18,7 @@ import { ThermostatServer } from '@matter/main/behaviors/thermostat';
|
|
|
18
18
|
import { ValveConfigurationAndControlServer } from '@matter/main/behaviors/valve-configuration-and-control';
|
|
19
19
|
import { ModeSelectServer } from '@matter/main/behaviors/mode-select';
|
|
20
20
|
import { SmokeCoAlarmServer } from '@matter/main/behaviors/smoke-co-alarm';
|
|
21
|
+
import { SwitchServer } from '@matter/main/behaviors/switch';
|
|
21
22
|
export class MatterbridgeBehaviorDevice {
|
|
22
23
|
log;
|
|
23
24
|
commandHandler;
|
|
@@ -338,3 +339,7 @@ export class MatterbridgeBooleanStateConfigurationServer extends BooleanStateCon
|
|
|
338
339
|
super.enableDisableAlarm({ alarmsToEnableDisable });
|
|
339
340
|
}
|
|
340
341
|
}
|
|
342
|
+
export class MatterbridgeSwitchServer extends SwitchServer {
|
|
343
|
+
initialize() {
|
|
344
|
+
}
|
|
345
|
+
}
|