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 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
- The legacy old api have been removed.
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
- The frontend has a new dark and light mode. The dark mode is now the default mode.
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]: Removed legacy imports.
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
- res.json(pairingCodes);
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
- Object.entries(device.state).forEach(([clusterName, clusterAttributes]) => {
834
- Object.entries(clusterAttributes).forEach(([attributeName, attributeValue]) => {
835
- if (typeof attributeValue === 'undefined')
836
- return;
837
- if (clusterName === 'onOff' && attributeName === 'onOff')
838
- attributes += `OnOff: ${attributeValue} `;
839
- if (clusterName === 'switch' && attributeName === 'currentPosition')
840
- attributes += `Position: ${attributeValue} `;
841
- if (clusterName === 'windowCovering' && attributeName === 'currentPositionLiftPercent100ths')
842
- attributes += `Cover position: ${attributeValue / 100}% `;
843
- if (clusterName === 'doorLock' && attributeName === 'lockState')
844
- attributes += `State: ${attributeValue === 1 ? 'Locked' : 'Not locked'} `;
845
- if (clusterName === 'thermostat' && attributeName === 'localTemperature')
846
- attributes += `Temperature: ${attributeValue / 100}°C `;
847
- if (clusterName === 'thermostat' && attributeName === 'occupiedHeatingSetpoint')
848
- attributes += `Heat to: ${attributeValue / 100}°C `;
849
- if (clusterName === 'thermostat' && attributeName === 'occupiedCoolingSetpoint')
850
- attributes += `Cool to: ${attributeValue / 100}°C `;
851
- if (clusterName === 'pumpConfigurationAndControl' && attributeName === 'operationMode')
852
- attributes += `Mode: ${attributeValue} `;
853
- if (clusterName === 'valveConfigurationAndControl' && attributeName === 'currentState')
854
- attributes += `State: ${attributeValue} `;
855
- if (clusterName === 'levelControl' && attributeName === 'currentLevel')
856
- attributes += `Level: ${attributeValue}% `;
857
- if (clusterName === 'colorControl' && attributeName === 'colorMode')
858
- attributes += `Mode: ${['HS', 'XY', 'CT'][attributeValue]} `;
859
- if (clusterName === 'colorControl' && getAttribute(device, 'colorControl', 'colorMode') === 0 && attributeName === 'currentHue')
860
- attributes += `Hue: ${Math.round(attributeValue)} `;
861
- if (clusterName === 'colorControl' && getAttribute(device, 'colorControl', 'colorMode') === 0 && attributeName === 'currentSaturation')
862
- attributes += `Saturation: ${Math.round(attributeValue)} `;
863
- if (clusterName === 'colorControl' && getAttribute(device, 'colorControl', 'colorMode') === 1 && attributeName === 'currentX')
864
- attributes += `X: ${Math.round(attributeValue)} `;
865
- if (clusterName === 'colorControl' && getAttribute(device, 'colorControl', 'colorMode') === 1 && attributeName === 'currentY')
866
- attributes += `Y: ${Math.round(attributeValue)} `;
867
- if (clusterName === 'colorControl' && getAttribute(device, 'colorControl', 'colorMode') === 2 && attributeName === 'colorTemperatureMireds')
868
- attributes += `ColorTemp: ${Math.round(attributeValue)} `;
869
- if (clusterName === 'booleanState' && attributeName === 'stateValue')
870
- attributes += `Contact: ${attributeValue} `;
871
- if (clusterName === 'booleanStateConfiguration' && attributeName === 'alarmsActive')
872
- attributes += `Active alarms: ${stringify(attributeValue)} `;
873
- if (clusterName === 'smokeCoAlarm' && attributeName === 'smokeState')
874
- attributes += `Smoke: ${attributeValue} `;
875
- if (clusterName === 'smokeCoAlarm' && attributeName === 'coState')
876
- attributes += `Co: ${attributeValue} `;
877
- if (clusterName === 'fanControl' && attributeName === 'fanMode')
878
- attributes += `Mode: ${attributeValue} `;
879
- if (clusterName === 'fanControl' && attributeName === 'percentCurrent')
880
- attributes += `Percent: ${attributeValue} `;
881
- if (clusterName === 'fanControl' && attributeName === 'speedCurrent')
882
- attributes += `Speed: ${attributeValue} `;
883
- if (clusterName === 'occupancySensing' && attributeName === 'occupancy')
884
- attributes += `Occupancy: ${attributeValue.occupied} `;
885
- if (clusterName === 'illuminanceMeasurement' && attributeName === 'measuredValue')
886
- attributes += `Illuminance: ${attributeValue} `;
887
- if (clusterName === 'airQuality' && attributeName === 'airQuality')
888
- attributes += `Air quality: ${attributeValue} `;
889
- if (clusterName === 'tvocMeasurement' && attributeName === 'measuredValue')
890
- attributes += `Voc: ${attributeValue} `;
891
- if (clusterName === 'temperatureMeasurement' && attributeName === 'measuredValue')
892
- attributes += `Temperature: ${attributeValue / 100}°C `;
893
- if (clusterName === 'relativeHumidityMeasurement' && attributeName === 'measuredValue')
894
- attributes += `Humidity: ${attributeValue / 100}% `;
895
- if (clusterName === 'pressureMeasurement' && attributeName === 'measuredValue')
896
- attributes += `Pressure: ${attributeValue} `;
897
- if (clusterName === 'flowMeasurement' && attributeName === 'measuredValue')
898
- attributes += `Flow: ${attributeValue} `;
899
- if (clusterName === 'fixedLabel' && attributeName === 'labelList')
900
- attributes += `${getFixedLabel(device)} `;
901
- if (clusterName === 'userLabel' && attributeName === 'labelList')
902
- attributes += `${getUserLabel(device)} `;
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
- return;
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';
@@ -1,6 +1,3 @@
1
1
  export * from '@matter/main';
2
- export { AggregatorEndpoint } from '@matter/main/endpoints';
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';
@@ -0,0 +1,2 @@
1
+ export * from '@matter/types';
2
+ export { ClusterRegistry } from '@matter/types';
@@ -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, wait, waiter, copyDirectory, getParameter, getIntParameter, hasParameter } from './utils/utils.js';
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
+ }