matterbridge 2.1.0-dev.3 → 2.1.0-dev.4

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
@@ -21,7 +21,7 @@ The legacy old api have been removed.
21
21
  The frontend has a new dark and light mode. The dark mode is now the default mode.
22
22
  It is possible to change the mode (Classic, Dark or Light) in Settings, Matterbridge settings.
23
23
 
24
- ## [2.1.0.dev.3] - 2025-01-27
24
+ ## [2.1.0.dev.4] - 2025-01-28
25
25
 
26
26
  ### Added
27
27
 
package/dist/frontend.js CHANGED
@@ -830,77 +830,75 @@ export class Frontend {
830
830
  return '';
831
831
  };
832
832
  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
- });
833
+ device.forEachAttribute((clusterName, attributeName, attributeValue) => {
834
+ if (typeof attributeValue === 'undefined')
835
+ return;
836
+ if (clusterName === 'onOff' && attributeName === 'onOff')
837
+ attributes += `OnOff: ${attributeValue} `;
838
+ if (clusterName === 'switch' && attributeName === 'currentPosition')
839
+ attributes += `Position: ${attributeValue} `;
840
+ if (clusterName === 'windowCovering' && attributeName === 'currentPositionLiftPercent100ths' && isValidNumber(attributeValue, 0, 10000))
841
+ attributes += `Cover position: ${attributeValue / 100}% `;
842
+ if (clusterName === 'doorLock' && attributeName === 'lockState')
843
+ attributes += `State: ${attributeValue === 1 ? 'Locked' : 'Not locked'} `;
844
+ if (clusterName === 'thermostat' && attributeName === 'localTemperature' && isValidNumber(attributeValue))
845
+ attributes += `Temperature: ${attributeValue / 100}°C `;
846
+ if (clusterName === 'thermostat' && attributeName === 'occupiedHeatingSetpoint' && isValidNumber(attributeValue))
847
+ attributes += `Heat to: ${attributeValue / 100}°C `;
848
+ if (clusterName === 'thermostat' && attributeName === 'occupiedCoolingSetpoint' && isValidNumber(attributeValue))
849
+ attributes += `Cool to: ${attributeValue / 100}°C `;
850
+ if (clusterName === 'pumpConfigurationAndControl' && attributeName === 'operationMode')
851
+ attributes += `Mode: ${attributeValue} `;
852
+ if (clusterName === 'valveConfigurationAndControl' && attributeName === 'currentState')
853
+ attributes += `State: ${attributeValue} `;
854
+ if (clusterName === 'levelControl' && attributeName === 'currentLevel')
855
+ attributes += `Level: ${attributeValue} `;
856
+ if (clusterName === 'colorControl' && attributeName === 'colorMode' && isValidNumber(attributeValue, 0, 2))
857
+ attributes += `Mode: ${['HS', 'XY', 'CT'][attributeValue]} `;
858
+ if (clusterName === 'colorControl' && getAttribute(device, 'colorControl', 'colorMode') === 0 && attributeName === 'currentHue' && isValidNumber(attributeValue))
859
+ attributes += `Hue: ${Math.round(attributeValue)} `;
860
+ if (clusterName === 'colorControl' && getAttribute(device, 'colorControl', 'colorMode') === 0 && attributeName === 'currentSaturation' && isValidNumber(attributeValue))
861
+ attributes += `Saturation: ${Math.round(attributeValue)} `;
862
+ if (clusterName === 'colorControl' && getAttribute(device, 'colorControl', 'colorMode') === 1 && attributeName === 'currentX' && isValidNumber(attributeValue))
863
+ attributes += `X: ${Math.round(attributeValue / 655.36) / 100} `;
864
+ if (clusterName === 'colorControl' && getAttribute(device, 'colorControl', 'colorMode') === 1 && attributeName === 'currentY' && isValidNumber(attributeValue))
865
+ attributes += `Y: ${Math.round(attributeValue / 655.36) / 100} `;
866
+ if (clusterName === 'colorControl' && getAttribute(device, 'colorControl', 'colorMode') === 2 && attributeName === 'colorTemperatureMireds' && isValidNumber(attributeValue))
867
+ attributes += `ColorTemp: ${Math.round(attributeValue)} `;
868
+ if (clusterName === 'booleanState' && attributeName === 'stateValue')
869
+ attributes += `Contact: ${attributeValue} `;
870
+ if (clusterName === 'booleanStateConfiguration' && attributeName === 'alarmsActive' && isValidObject(attributeValue))
871
+ attributes += `Active alarms: ${stringify(attributeValue)} `;
872
+ if (clusterName === 'smokeCoAlarm' && attributeName === 'smokeState')
873
+ attributes += `Smoke: ${attributeValue} `;
874
+ if (clusterName === 'smokeCoAlarm' && attributeName === 'coState')
875
+ attributes += `Co: ${attributeValue} `;
876
+ if (clusterName === 'fanControl' && attributeName === 'fanMode')
877
+ attributes += `Mode: ${attributeValue} `;
878
+ if (clusterName === 'fanControl' && attributeName === 'percentCurrent')
879
+ attributes += `Percent: ${attributeValue} `;
880
+ if (clusterName === 'fanControl' && attributeName === 'speedCurrent')
881
+ attributes += `Speed: ${attributeValue} `;
882
+ if (clusterName === 'occupancySensing' && attributeName === 'occupancy' && isValidObject(attributeValue, 1))
883
+ attributes += `Occupancy: ${attributeValue.occupied} `;
884
+ if (clusterName === 'illuminanceMeasurement' && attributeName === 'measuredValue')
885
+ attributes += `Illuminance: ${attributeValue} `;
886
+ if (clusterName === 'airQuality' && attributeName === 'airQuality')
887
+ attributes += `Air quality: ${attributeValue} `;
888
+ if (clusterName === 'tvocMeasurement' && attributeName === 'measuredValue')
889
+ attributes += `Voc: ${attributeValue} `;
890
+ if (clusterName === 'temperatureMeasurement' && attributeName === 'measuredValue' && isValidNumber(attributeValue))
891
+ attributes += `Temperature: ${attributeValue / 100}°C `;
892
+ if (clusterName === 'relativeHumidityMeasurement' && attributeName === 'measuredValue' && isValidNumber(attributeValue))
893
+ attributes += `Humidity: ${attributeValue / 100}% `;
894
+ if (clusterName === 'pressureMeasurement' && attributeName === 'measuredValue')
895
+ attributes += `Pressure: ${attributeValue} `;
896
+ if (clusterName === 'flowMeasurement' && attributeName === 'measuredValue')
897
+ attributes += `Flow: ${attributeValue} `;
898
+ if (clusterName === 'fixedLabel' && attributeName === 'labelList')
899
+ attributes += `${getFixedLabel(device)} `;
900
+ if (clusterName === 'userLabel' && attributeName === 'labelList')
901
+ attributes += `${getUserLabel(device)} `;
904
902
  });
905
903
  return attributes.trimStart().trimEnd();
906
904
  }
@@ -1066,8 +1064,11 @@ export class Frontend {
1066
1064
  const clusterServers = endpointServer.getAllClusterServers();
1067
1065
  clusterServers.forEach((clusterServer) => {
1068
1066
  Object.entries(clusterServer.attributes).forEach(([key, value]) => {
1069
- if (clusterServer.name === 'EveHistory')
1070
- return;
1067
+ if (clusterServer.name === 'EveHistory') {
1068
+ if (['configDataGet', 'configDataSet', 'historyStatus', 'historyEntries', 'historyRequest', 'historySetTime', 'rLoc'].includes(key)) {
1069
+ return;
1070
+ }
1071
+ }
1071
1072
  if (clusterServer.name === 'Descriptor' && key === 'deviceTypeList') {
1072
1073
  value.getLocal().forEach((deviceType) => {
1073
1074
  deviceTypes.push(deviceType.deviceType);
@@ -2,5 +2,5 @@ export * from '@matter/main';
2
2
  export { AggregatorEndpoint } from '@matter/main/endpoints';
3
3
  export * from '@matter/main/devices';
4
4
  export * from '@matter/main/behaviors';
5
- export { FabricAction, MdnsService, PaseClient } from '@matter/main/protocol';
5
+ export { FabricAction, MdnsService, PaseClient, logEndpoint } from '@matter/main/protocol';
6
6
  export { AttributeElement, ClusterElement, ClusterModel, CommandElement, EventElement, FieldElement } from '@matter/main/model';
@@ -1,18 +1,16 @@
1
- import { createHash } from 'crypto';
2
1
  import { AnsiLogger, BLUE, CYAN, YELLOW, db, debugStringify, er, hk, or, zb } from './logger/export.js';
3
2
  import { bridgedNode } from './matterbridgeDeviceTypes.js';
4
3
  import { deepCopy, isValidNumber } from './utils/utils.js';
5
4
  import { MatterbridgeBehavior, MatterbridgeBehaviorDevice, MatterbridgeIdentifyServer, MatterbridgeOnOffServer, MatterbridgeLevelControlServer, MatterbridgeColorControlServer, MatterbridgeWindowCoveringServer, MatterbridgeThermostatServer, MatterbridgeFanControlServer, MatterbridgeDoorLockServer, MatterbridgeModeSelectServer, MatterbridgeValveConfigurationAndControlServer, MatterbridgeSmokeCoAlarmServer, MatterbridgeBooleanStateConfigurationServer, } from './matterbridgeBehaviors.js';
5
+ import { addClusterServers, addOptionalClusterServers, addRequiredClusterServers, capitalizeFirstLetter, createUniqueId, getBehavior, getBehaviourTypesFromClusterClientIds, getBehaviourTypesFromClusterServerIds, lowercaseFirstLetter, optionsFor, } from './matterbridgeEndpointHelpers.js';
6
6
  import { Endpoint, Lifecycle, MutableEndpoint, NamedHandler, SupportedBehaviors, VendorId } from '@matter/main';
7
7
  import { getClusterNameById, MeasurementType } from '@matter/main/types';
8
8
  import { Descriptor } from '@matter/main/clusters/descriptor';
9
9
  import { PowerSource } from '@matter/main/clusters/power-source';
10
10
  import { UserLabel } from '@matter/main/clusters/user-label';
11
11
  import { FixedLabel } from '@matter/main/clusters/fixed-label';
12
- import { BasicInformation } from '@matter/main/clusters/basic-information';
13
12
  import { BridgedDeviceBasicInformation } from '@matter/main/clusters/bridged-device-basic-information';
14
13
  import { Identify } from '@matter/main/clusters/identify';
15
- import { Groups } from '@matter/main/clusters/groups';
16
14
  import { OnOff } from '@matter/main/clusters/on-off';
17
15
  import { LevelControl } from '@matter/main/clusters/level-control';
18
16
  import { ColorControl } from '@matter/main/clusters/color-control';
@@ -20,39 +18,21 @@ import { WindowCovering } from '@matter/main/clusters/window-covering';
20
18
  import { Thermostat } from '@matter/main/clusters/thermostat';
21
19
  import { FanControl } from '@matter/main/clusters/fan-control';
22
20
  import { DoorLock } from '@matter/main/clusters/door-lock';
23
- import { ModeSelect } from '@matter/main/clusters/mode-select';
24
21
  import { ValveConfigurationAndControl } from '@matter/main/clusters/valve-configuration-and-control';
25
22
  import { PumpConfigurationAndControl } from '@matter/main/clusters/pump-configuration-and-control';
26
23
  import { SmokeCoAlarm } from '@matter/main/clusters/smoke-co-alarm';
27
24
  import { Switch } from '@matter/main/clusters/switch';
28
- import { BooleanState } from '@matter/main/clusters/boolean-state';
29
25
  import { BooleanStateConfiguration } from '@matter/main/clusters/boolean-state-configuration';
30
26
  import { PowerTopology } from '@matter/main/clusters/power-topology';
31
27
  import { ElectricalPowerMeasurement } from '@matter/main/clusters/electrical-power-measurement';
32
28
  import { ElectricalEnergyMeasurement } from '@matter/main/clusters/electrical-energy-measurement';
33
- import { TemperatureMeasurement } from '@matter/main/clusters/temperature-measurement';
34
- import { RelativeHumidityMeasurement } from '@matter/main/clusters/relative-humidity-measurement';
35
- import { PressureMeasurement } from '@matter/main/clusters/pressure-measurement';
36
- import { FlowMeasurement } from '@matter/main/clusters/flow-measurement';
37
- import { IlluminanceMeasurement } from '@matter/main/clusters/illuminance-measurement';
38
29
  import { OccupancySensing } from '@matter/main/clusters/occupancy-sensing';
39
30
  import { AirQuality } from '@matter/main/clusters/air-quality';
40
- import { CarbonMonoxideConcentrationMeasurement } from '@matter/main/clusters/carbon-monoxide-concentration-measurement';
41
- import { CarbonDioxideConcentrationMeasurement } from '@matter/main/clusters/carbon-dioxide-concentration-measurement';
42
- import { NitrogenDioxideConcentrationMeasurement } from '@matter/main/clusters/nitrogen-dioxide-concentration-measurement';
43
- import { OzoneConcentrationMeasurement } from '@matter/main/clusters/ozone-concentration-measurement';
44
- import { FormaldehydeConcentrationMeasurement } from '@matter/main/clusters/formaldehyde-concentration-measurement';
45
- import { Pm1ConcentrationMeasurement } from '@matter/main/clusters/pm1-concentration-measurement';
46
- import { Pm25ConcentrationMeasurement } from '@matter/main/clusters/pm25-concentration-measurement';
47
- import { Pm10ConcentrationMeasurement } from '@matter/main/clusters/pm10-concentration-measurement';
48
- import { RadonConcentrationMeasurement } from '@matter/main/clusters/radon-concentration-measurement';
49
- import { TotalVolatileOrganicCompoundsConcentrationMeasurement } from '@matter/main/clusters/total-volatile-organic-compounds-concentration-measurement';
50
31
  import { ConcentrationMeasurement } from '@matter/main/clusters/concentration-measurement';
51
32
  import { DescriptorServer } from '@matter/main/behaviors/descriptor';
52
33
  import { PowerSourceServer } from '@matter/main/behaviors/power-source';
53
34
  import { UserLabelServer } from '@matter/main/behaviors/user-label';
54
35
  import { FixedLabelServer } from '@matter/main/behaviors/fixed-label';
55
- import { BasicInformationServer } from '@matter/main/behaviors/basic-information';
56
36
  import { BridgedDeviceBasicInformationServer } from '@matter/main/behaviors/bridged-device-basic-information';
57
37
  import { GroupsServer } from '@matter/main/behaviors/groups';
58
38
  import { ScenesManagementServer } from '@matter/main/behaviors/scenes-management';
@@ -79,242 +59,6 @@ import { Pm25ConcentrationMeasurementServer } from '@matter/main/behaviors/pm25-
79
59
  import { Pm10ConcentrationMeasurementServer } from '@matter/main/behaviors/pm10-concentration-measurement';
80
60
  import { RadonConcentrationMeasurementServer } from '@matter/main/behaviors/radon-concentration-measurement';
81
61
  import { TotalVolatileOrganicCompoundsConcentrationMeasurementServer } from '@matter/main/behaviors/total-volatile-organic-compounds-concentration-measurement';
82
- function capitalizeFirstLetter(name) {
83
- if (!name)
84
- return name;
85
- return name.charAt(0).toUpperCase() + name.slice(1);
86
- }
87
- function lowercaseFirstLetter(name) {
88
- if (!name)
89
- return name;
90
- return name.charAt(0).toLowerCase() + name.slice(1);
91
- }
92
- function createUniqueId(param1, param2, param3, param4) {
93
- const hash = createHash('md5');
94
- hash.update(param1 + param2 + param3 + param4);
95
- return hash.digest('hex');
96
- }
97
- function getBehaviourTypesFromClusterServerIds(clusterServerList) {
98
- const behaviorTypes = [];
99
- clusterServerList.forEach((clusterId) => {
100
- behaviorTypes.push(getBehaviourTypeFromClusterServerId(clusterId));
101
- });
102
- return behaviorTypes;
103
- }
104
- function getBehaviourTypesFromClusterClientIds(clusterClientList) {
105
- const behaviorTypes = [];
106
- clusterClientList.forEach((clusterId) => {
107
- });
108
- return behaviorTypes;
109
- }
110
- function getBehaviourTypeFromClusterServerId(clusterId) {
111
- if (clusterId === PowerSource.Cluster.id)
112
- return PowerSourceServer.with(PowerSource.Feature.Wired);
113
- if (clusterId === UserLabel.Cluster.id)
114
- return UserLabelServer;
115
- if (clusterId === FixedLabel.Cluster.id)
116
- return FixedLabelServer;
117
- if (clusterId === BasicInformation.Cluster.id)
118
- return BasicInformationServer;
119
- if (clusterId === BridgedDeviceBasicInformation.Cluster.id)
120
- return BridgedDeviceBasicInformationServer;
121
- if (clusterId === Identify.Cluster.id)
122
- return MatterbridgeIdentifyServer;
123
- if (clusterId === Groups.Cluster.id)
124
- return GroupsServer;
125
- if (clusterId === OnOff.Cluster.id)
126
- return MatterbridgeOnOffServer.with('Lighting');
127
- if (clusterId === LevelControl.Cluster.id)
128
- return MatterbridgeLevelControlServer.with('OnOff', 'Lighting');
129
- if (clusterId === ColorControl.Cluster.id)
130
- return MatterbridgeColorControlServer;
131
- if (clusterId === WindowCovering.Cluster.id)
132
- return MatterbridgeWindowCoveringServer.with('Lift', 'PositionAwareLift');
133
- if (clusterId === Thermostat.Cluster.id)
134
- return MatterbridgeThermostatServer.with('AutoMode', 'Heating', 'Cooling');
135
- if (clusterId === FanControl.Cluster.id)
136
- return MatterbridgeFanControlServer;
137
- if (clusterId === DoorLock.Cluster.id)
138
- return MatterbridgeDoorLockServer;
139
- if (clusterId === ModeSelect.Cluster.id)
140
- return MatterbridgeModeSelectServer;
141
- if (clusterId === ValveConfigurationAndControl.Cluster.id)
142
- return MatterbridgeValveConfigurationAndControlServer.with('Level');
143
- if (clusterId === PumpConfigurationAndControl.Cluster.id)
144
- return PumpConfigurationAndControlServer.with('ConstantSpeed');
145
- if (clusterId === SmokeCoAlarm.Cluster.id)
146
- return MatterbridgeSmokeCoAlarmServer.with('SmokeAlarm', 'CoAlarm');
147
- if (clusterId === Switch.Cluster.id)
148
- return SwitchServer.with('MomentarySwitch', 'MomentarySwitchRelease', 'MomentarySwitchLongPress', 'MomentarySwitchMultiPress');
149
- if (clusterId === BooleanState.Cluster.id)
150
- return BooleanStateServer.enable({ events: { stateChange: true } });
151
- if (clusterId === BooleanStateConfiguration.Cluster.id)
152
- return MatterbridgeBooleanStateConfigurationServer;
153
- if (clusterId === PowerTopology.Cluster.id)
154
- return PowerTopologyServer.with('TreeTopology');
155
- if (clusterId === ElectricalPowerMeasurement.Cluster.id)
156
- return ElectricalPowerMeasurementServer.with('AlternatingCurrent');
157
- if (clusterId === ElectricalEnergyMeasurement.Cluster.id)
158
- return ElectricalEnergyMeasurementServer.with('ImportedEnergy', 'ExportedEnergy', 'CumulativeEnergy');
159
- if (clusterId === TemperatureMeasurement.Cluster.id)
160
- return TemperatureMeasurementServer;
161
- if (clusterId === RelativeHumidityMeasurement.Cluster.id)
162
- return RelativeHumidityMeasurementServer;
163
- if (clusterId === PressureMeasurement.Cluster.id)
164
- return PressureMeasurementServer;
165
- if (clusterId === FlowMeasurement.Cluster.id)
166
- return FlowMeasurementServer;
167
- if (clusterId === IlluminanceMeasurement.Cluster.id)
168
- return IlluminanceMeasurementServer;
169
- if (clusterId === OccupancySensing.Cluster.id)
170
- return OccupancySensingServer;
171
- if (clusterId === AirQuality.Cluster.id)
172
- return AirQualityServer.with('Fair', 'Moderate', 'VeryPoor', 'ExtremelyPoor');
173
- if (clusterId === CarbonMonoxideConcentrationMeasurement.Cluster.id)
174
- return CarbonMonoxideConcentrationMeasurementServer.with('NumericMeasurement');
175
- if (clusterId === CarbonDioxideConcentrationMeasurement.Cluster.id)
176
- return CarbonDioxideConcentrationMeasurementServer.with('NumericMeasurement');
177
- if (clusterId === NitrogenDioxideConcentrationMeasurement.Cluster.id)
178
- return NitrogenDioxideConcentrationMeasurementServer.with('NumericMeasurement');
179
- if (clusterId === OzoneConcentrationMeasurement.Cluster.id)
180
- return OzoneConcentrationMeasurementServer.with('NumericMeasurement');
181
- if (clusterId === FormaldehydeConcentrationMeasurement.Cluster.id)
182
- return FormaldehydeConcentrationMeasurementServer.with('NumericMeasurement');
183
- if (clusterId === Pm1ConcentrationMeasurement.Cluster.id)
184
- return Pm1ConcentrationMeasurementServer.with('NumericMeasurement');
185
- if (clusterId === Pm25ConcentrationMeasurement.Cluster.id)
186
- return Pm25ConcentrationMeasurementServer.with('NumericMeasurement');
187
- if (clusterId === Pm10ConcentrationMeasurement.Cluster.id)
188
- return Pm10ConcentrationMeasurementServer.with('NumericMeasurement');
189
- if (clusterId === RadonConcentrationMeasurement.Cluster.id)
190
- return RadonConcentrationMeasurementServer.with('NumericMeasurement');
191
- if (clusterId === TotalVolatileOrganicCompoundsConcentrationMeasurement.Cluster.id)
192
- return TotalVolatileOrganicCompoundsConcentrationMeasurementServer.with('NumericMeasurement');
193
- return MatterbridgeIdentifyServer;
194
- }
195
- function getBehaviourTypeFromClusterClientId(clusterId) {
196
- }
197
- function getBehavior(endpoint, cluster) {
198
- let behavior;
199
- if (typeof cluster === 'string') {
200
- behavior = endpoint.behaviors.supported[lowercaseFirstLetter(cluster)];
201
- }
202
- else if (typeof cluster === 'number') {
203
- behavior = endpoint.behaviors.supported[lowercaseFirstLetter(getClusterNameById(cluster))];
204
- }
205
- else if (typeof cluster === 'object') {
206
- behavior = endpoint.behaviors.supported[lowercaseFirstLetter(cluster.name)];
207
- }
208
- else if (typeof cluster === 'function') {
209
- behavior = cluster;
210
- }
211
- return behavior;
212
- }
213
- function addRequiredClusterServers(endpoint) {
214
- const requiredServerList = [];
215
- endpoint.log.debug(`addRequiredClusterServers for ${CYAN}${endpoint.maybeId}${db}`);
216
- Array.from(endpoint.deviceTypes.values()).forEach((deviceType) => {
217
- endpoint.log.debug(`- for deviceType: ${zb}${'0x' + deviceType.code.toString(16).padStart(4, '0')}${db}-${zb}${deviceType.name}${db}`);
218
- deviceType.requiredServerClusters.forEach((clusterId) => {
219
- if (!requiredServerList.includes(clusterId) && !endpoint.hasClusterServer(clusterId)) {
220
- requiredServerList.push(clusterId);
221
- endpoint.log.debug(`- cluster: ${hk}${'0x' + clusterId.toString(16).padStart(4, '0')}${db}-${hk}${getClusterNameById(clusterId)}${db}`);
222
- }
223
- });
224
- });
225
- addClusterServers(endpoint, requiredServerList);
226
- }
227
- function addOptionalClusterServers(endpoint) {
228
- const optionalServerList = [];
229
- endpoint.log.debug(`addOptionalClusterServers for ${CYAN}${endpoint.maybeId}${db}`);
230
- Array.from(endpoint.deviceTypes.values()).forEach((deviceType) => {
231
- endpoint.log.debug(`- for deviceType: ${zb}${'0x' + deviceType.code.toString(16).padStart(4, '0')}${db}-${zb}${deviceType.name}${db}`);
232
- deviceType.optionalServerClusters.forEach((clusterId) => {
233
- if (!optionalServerList.includes(clusterId) && !endpoint.hasClusterServer(clusterId)) {
234
- optionalServerList.push(clusterId);
235
- endpoint.log.debug(`- cluster: ${hk}${'0x' + clusterId.toString(16).padStart(4, '0')}${db}-${hk}${getClusterNameById(clusterId)}${db}`);
236
- }
237
- });
238
- });
239
- addClusterServers(endpoint, optionalServerList);
240
- }
241
- function addClusterServers(endpoint, serverList) {
242
- if (serverList.includes(PowerSource.Cluster.id))
243
- endpoint.createDefaultPowerSourceWiredClusterServer();
244
- if (serverList.includes(Identify.Cluster.id))
245
- endpoint.createDefaultIdentifyClusterServer();
246
- if (serverList.includes(Groups.Cluster.id))
247
- endpoint.createDefaultGroupsClusterServer();
248
- if (serverList.includes(OnOff.Cluster.id))
249
- endpoint.createDefaultOnOffClusterServer();
250
- if (serverList.includes(LevelControl.Cluster.id))
251
- endpoint.createDefaultLevelControlClusterServer();
252
- if (serverList.includes(ColorControl.Cluster.id))
253
- endpoint.createDefaultColorControlClusterServer();
254
- if (serverList.includes(WindowCovering.Cluster.id))
255
- endpoint.createDefaultWindowCoveringClusterServer();
256
- if (serverList.includes(Thermostat.Cluster.id))
257
- endpoint.createDefaultThermostatClusterServer();
258
- if (serverList.includes(FanControl.Cluster.id))
259
- endpoint.createDefaultFanControlClusterServer();
260
- if (serverList.includes(DoorLock.Cluster.id))
261
- endpoint.createDefaultDoorLockClusterServer();
262
- if (serverList.includes(ValveConfigurationAndControl.Cluster.id))
263
- endpoint.createDefaultValveConfigurationAndControlClusterServer();
264
- if (serverList.includes(PumpConfigurationAndControl.Cluster.id))
265
- endpoint.createDefaultPumpConfigurationAndControlClusterServer();
266
- if (serverList.includes(SmokeCoAlarm.Cluster.id))
267
- endpoint.createDefaultSmokeCOAlarmClusterServer();
268
- if (serverList.includes(Switch.Cluster.id))
269
- endpoint.createDefaultSwitchClusterServer();
270
- if (serverList.includes(BooleanState.Cluster.id))
271
- endpoint.createDefaultBooleanStateClusterServer();
272
- if (serverList.includes(BooleanStateConfiguration.Cluster.id))
273
- endpoint.createDefaultBooleanStateConfigurationClusterServer();
274
- if (serverList.includes(PowerTopology.Cluster.id))
275
- endpoint.createDefaultPowerTopologyClusterServer();
276
- if (serverList.includes(ElectricalPowerMeasurement.Cluster.id))
277
- endpoint.createDefaultElectricalPowerMeasurementClusterServer();
278
- if (serverList.includes(ElectricalEnergyMeasurement.Cluster.id))
279
- endpoint.createDefaultElectricalEnergyMeasurementClusterServer();
280
- if (serverList.includes(TemperatureMeasurement.Cluster.id))
281
- endpoint.createDefaultTemperatureMeasurementClusterServer();
282
- if (serverList.includes(RelativeHumidityMeasurement.Cluster.id))
283
- endpoint.createDefaultRelativeHumidityMeasurementClusterServer();
284
- if (serverList.includes(PressureMeasurement.Cluster.id))
285
- endpoint.createDefaultPressureMeasurementClusterServer();
286
- if (serverList.includes(FlowMeasurement.Cluster.id))
287
- endpoint.createDefaultFlowMeasurementClusterServer();
288
- if (serverList.includes(IlluminanceMeasurement.Cluster.id))
289
- endpoint.createDefaultIlluminanceMeasurementClusterServer();
290
- if (serverList.includes(OccupancySensing.Cluster.id))
291
- endpoint.createDefaultOccupancySensingClusterServer();
292
- if (serverList.includes(AirQuality.Cluster.id))
293
- endpoint.createDefaultAirQualityClusterServer();
294
- if (serverList.includes(CarbonMonoxideConcentrationMeasurement.Cluster.id))
295
- endpoint.createDefaultCarbonMonoxideConcentrationMeasurementClusterServer();
296
- if (serverList.includes(CarbonDioxideConcentrationMeasurement.Cluster.id))
297
- endpoint.createDefaultCarbonDioxideConcentrationMeasurementClusterServer();
298
- if (serverList.includes(NitrogenDioxideConcentrationMeasurement.Cluster.id))
299
- endpoint.createDefaultNitrogenDioxideConcentrationMeasurementClusterServer();
300
- if (serverList.includes(OzoneConcentrationMeasurement.Cluster.id))
301
- endpoint.createDefaultOzoneConcentrationMeasurementClusterServer();
302
- if (serverList.includes(FormaldehydeConcentrationMeasurement.Cluster.id))
303
- endpoint.createDefaultFormaldehydeConcentrationMeasurementClusterServer();
304
- if (serverList.includes(Pm1ConcentrationMeasurement.Cluster.id))
305
- endpoint.createDefaultPm1ConcentrationMeasurementClusterServer();
306
- if (serverList.includes(Pm25ConcentrationMeasurement.Cluster.id))
307
- endpoint.createDefaultPm25ConcentrationMeasurementClusterServer();
308
- if (serverList.includes(Pm10ConcentrationMeasurement.Cluster.id))
309
- endpoint.createDefaultPm10ConcentrationMeasurementClusterServer();
310
- if (serverList.includes(RadonConcentrationMeasurement.Cluster.id))
311
- endpoint.createDefaultRadonConcentrationMeasurementClusterServer();
312
- if (serverList.includes(TotalVolatileOrganicCompoundsConcentrationMeasurement.Cluster.id))
313
- endpoint.createDefaultTvocMeasurementClusterServer();
314
- }
315
- export function optionsFor(type, options) {
316
- return options;
317
- }
318
62
  export class MatterbridgeEndpoint extends Endpoint {
319
63
  static bridgeMode = '';
320
64
  static logLevel = "info";
@@ -337,7 +81,6 @@ export class MatterbridgeEndpoint extends Endpoint {
337
81
  deviceType;
338
82
  uniqueStorageKey = undefined;
339
83
  tagList = undefined;
340
- subType = '';
341
84
  deviceTypes = new Map();
342
85
  commandHandler = new NamedHandler();
343
86
  constructor(definition, options = {}, debug = false) {
@@ -412,7 +155,8 @@ export class MatterbridgeEndpoint extends Endpoint {
412
155
  if (!behavior || !this.behaviors.supported[behavior.id])
413
156
  return false;
414
157
  const options = this.behaviors.optionsFor(behavior);
415
- return lowercaseFirstLetter(attribute) in options;
158
+ const defaults = this.behaviors.defaultsFor(behavior);
159
+ return lowercaseFirstLetter(attribute) in options || lowercaseFirstLetter(attribute) in defaults;
416
160
  }
417
161
  getClusterServerOptions(cluster) {
418
162
  const behavior = getBehavior(this, cluster);
@@ -484,21 +228,19 @@ export class MatterbridgeEndpoint extends Endpoint {
484
228
  log?.info(`${db}Subscribed endpoint ${or}${this.id}${db}:${or}${this.number}${db} attribute ${hk}${capitalizeFirstLetter(clusterName)}${db}.${hk}${attribute}${db}`);
485
229
  return true;
486
230
  }
487
- async triggerEvent(clusterId, event, payload, log, endpoint) {
488
- if (!endpoint)
489
- endpoint = this;
231
+ async triggerEvent(clusterId, event, payload, log) {
490
232
  const clusterName = lowercaseFirstLetter(getClusterNameById(clusterId));
491
- if (endpoint.construction.status !== Lifecycle.Status.Active) {
492
- this.log.error(`triggerEvent ${hk}${clusterName}.${event}${er} error: Endpoint ${or}${endpoint.maybeId}${er}:${or}${endpoint.maybeNumber}${er} is in the ${BLUE}${endpoint.construction.status}${er} state`);
233
+ if (this.construction.status !== Lifecycle.Status.Active) {
234
+ this.log.error(`triggerEvent ${hk}${clusterName}.${event}${er} error: Endpoint ${or}${this.maybeId}${er}:${or}${this.maybeNumber}${er} is in the ${BLUE}${this.construction.status}${er} state`);
493
235
  return false;
494
236
  }
495
- const events = endpoint.events;
237
+ const events = this.events;
496
238
  if (!(clusterName in events) || !(event in events[clusterName])) {
497
- this.log.error(`triggerEvent ${hk}${event}${er} error: Cluster ${'0x' + clusterId.toString(16).padStart(4, '0')}:${clusterName} not found on endpoint ${or}${endpoint.id}${er}:${or}${endpoint.number}${er}`);
239
+ this.log.error(`triggerEvent ${hk}${event}${er} error: Cluster ${'0x' + clusterId.toString(16).padStart(4, '0')}:${clusterName} not found on endpoint ${or}${this.id}${er}:${or}${this.number}${er}`);
498
240
  return false;
499
241
  }
500
- await endpoint.act((agent) => agent[clusterName].events[event].emit(payload, agent.context));
501
- log?.info(`${db}Trigger event ${hk}${capitalizeFirstLetter(clusterName)}${db}.${hk}${event}${db} with ${debugStringify(payload)}${db} on endpoint ${or}${endpoint.id}${db}:${or}${endpoint.number}${db} `);
242
+ await this.act((agent) => agent[clusterName].events[event].emit(payload, agent.context));
243
+ log?.info(`${db}Trigger event ${hk}${capitalizeFirstLetter(clusterName)}${db}.${hk}${event}${db} with ${debugStringify(payload)}${db} on endpoint ${or}${this.id}${db}:${or}${this.number}${db} `);
502
244
  return true;
503
245
  }
504
246
  addClusterServers(serverList) {
@@ -553,6 +295,15 @@ export class MatterbridgeEndpoint extends Endpoint {
553
295
  getAllClusterServerNames() {
554
296
  return Object.keys(this.behaviors.supported);
555
297
  }
298
+ forEachAttribute(callback) {
299
+ for (const [clusterName, clusterAttributes] of Object.entries(this.state)) {
300
+ for (const [attributeName, attributeValue] of Object.entries(clusterAttributes)) {
301
+ if (typeof attributeValue === 'undefined')
302
+ continue;
303
+ callback(clusterName, attributeName, attributeValue);
304
+ }
305
+ }
306
+ }
556
307
  addChildDeviceType(endpointName, definition, options = {}, debug = false) {
557
308
  this.log.debug(`addChildDeviceType: ${CYAN}${endpointName}${db}`);
558
309
  let alreadyAdded = false;
@@ -0,0 +1,316 @@
1
+ import { createHash } from 'crypto';
2
+ import { CYAN, db, hk, zb } from './logger/export.js';
3
+ import { MatterbridgeIdentifyServer, MatterbridgeOnOffServer, MatterbridgeLevelControlServer, MatterbridgeColorControlServer, MatterbridgeWindowCoveringServer, MatterbridgeThermostatServer, MatterbridgeFanControlServer, MatterbridgeDoorLockServer, MatterbridgeModeSelectServer, MatterbridgeValveConfigurationAndControlServer, MatterbridgeSmokeCoAlarmServer, MatterbridgeBooleanStateConfigurationServer, } from './matterbridgeBehaviors.js';
4
+ import { getClusterNameById } from '@matter/main/types';
5
+ import { PowerSource } from '@matter/main/clusters/power-source';
6
+ import { UserLabel } from '@matter/main/clusters/user-label';
7
+ import { FixedLabel } from '@matter/main/clusters/fixed-label';
8
+ import { BasicInformation } from '@matter/main/clusters/basic-information';
9
+ import { BridgedDeviceBasicInformation } from '@matter/main/clusters/bridged-device-basic-information';
10
+ import { Identify } from '@matter/main/clusters/identify';
11
+ import { Groups } from '@matter/main/clusters/groups';
12
+ import { OnOff } from '@matter/main/clusters/on-off';
13
+ import { LevelControl } from '@matter/main/clusters/level-control';
14
+ import { ColorControl } from '@matter/main/clusters/color-control';
15
+ import { WindowCovering } from '@matter/main/clusters/window-covering';
16
+ import { Thermostat } from '@matter/main/clusters/thermostat';
17
+ import { FanControl } from '@matter/main/clusters/fan-control';
18
+ import { DoorLock } from '@matter/main/clusters/door-lock';
19
+ import { ModeSelect } from '@matter/main/clusters/mode-select';
20
+ import { ValveConfigurationAndControl } from '@matter/main/clusters/valve-configuration-and-control';
21
+ import { PumpConfigurationAndControl } from '@matter/main/clusters/pump-configuration-and-control';
22
+ import { SmokeCoAlarm } from '@matter/main/clusters/smoke-co-alarm';
23
+ import { Switch } from '@matter/main/clusters/switch';
24
+ import { BooleanState } from '@matter/main/clusters/boolean-state';
25
+ import { BooleanStateConfiguration } from '@matter/main/clusters/boolean-state-configuration';
26
+ import { PowerTopology } from '@matter/main/clusters/power-topology';
27
+ import { ElectricalPowerMeasurement } from '@matter/main/clusters/electrical-power-measurement';
28
+ import { ElectricalEnergyMeasurement } from '@matter/main/clusters/electrical-energy-measurement';
29
+ import { TemperatureMeasurement } from '@matter/main/clusters/temperature-measurement';
30
+ import { RelativeHumidityMeasurement } from '@matter/main/clusters/relative-humidity-measurement';
31
+ import { PressureMeasurement } from '@matter/main/clusters/pressure-measurement';
32
+ import { FlowMeasurement } from '@matter/main/clusters/flow-measurement';
33
+ import { IlluminanceMeasurement } from '@matter/main/clusters/illuminance-measurement';
34
+ import { OccupancySensing } from '@matter/main/clusters/occupancy-sensing';
35
+ import { AirQuality } from '@matter/main/clusters/air-quality';
36
+ import { CarbonMonoxideConcentrationMeasurement } from '@matter/main/clusters/carbon-monoxide-concentration-measurement';
37
+ import { CarbonDioxideConcentrationMeasurement } from '@matter/main/clusters/carbon-dioxide-concentration-measurement';
38
+ import { NitrogenDioxideConcentrationMeasurement } from '@matter/main/clusters/nitrogen-dioxide-concentration-measurement';
39
+ import { OzoneConcentrationMeasurement } from '@matter/main/clusters/ozone-concentration-measurement';
40
+ import { FormaldehydeConcentrationMeasurement } from '@matter/main/clusters/formaldehyde-concentration-measurement';
41
+ import { Pm1ConcentrationMeasurement } from '@matter/main/clusters/pm1-concentration-measurement';
42
+ import { Pm25ConcentrationMeasurement } from '@matter/main/clusters/pm25-concentration-measurement';
43
+ import { Pm10ConcentrationMeasurement } from '@matter/main/clusters/pm10-concentration-measurement';
44
+ import { RadonConcentrationMeasurement } from '@matter/main/clusters/radon-concentration-measurement';
45
+ import { TotalVolatileOrganicCompoundsConcentrationMeasurement } from '@matter/main/clusters/total-volatile-organic-compounds-concentration-measurement';
46
+ import { PowerSourceServer } from '@matter/main/behaviors/power-source';
47
+ import { UserLabelServer } from '@matter/main/behaviors/user-label';
48
+ import { FixedLabelServer } from '@matter/main/behaviors/fixed-label';
49
+ import { BasicInformationServer } from '@matter/main/behaviors/basic-information';
50
+ import { BridgedDeviceBasicInformationServer } from '@matter/main/behaviors/bridged-device-basic-information';
51
+ import { GroupsServer } from '@matter/main/behaviors/groups';
52
+ import { PumpConfigurationAndControlServer } from '@matter/main/behaviors/pump-configuration-and-control';
53
+ import { SwitchServer } from '@matter/main/behaviors/switch';
54
+ import { BooleanStateServer } from '@matter/main/behaviors/boolean-state';
55
+ import { PowerTopologyServer } from '@matter/main/behaviors/power-topology';
56
+ import { ElectricalPowerMeasurementServer } from '@matter/main/behaviors/electrical-power-measurement';
57
+ import { ElectricalEnergyMeasurementServer } from '@matter/main/behaviors/electrical-energy-measurement';
58
+ import { TemperatureMeasurementServer } from '@matter/main/behaviors/temperature-measurement';
59
+ import { RelativeHumidityMeasurementServer } from '@matter/main/behaviors/relative-humidity-measurement';
60
+ import { PressureMeasurementServer } from '@matter/main/behaviors/pressure-measurement';
61
+ import { FlowMeasurementServer } from '@matter/main/behaviors/flow-measurement';
62
+ import { IlluminanceMeasurementServer } from '@matter/main/behaviors/illuminance-measurement';
63
+ import { OccupancySensingServer } from '@matter/main/behaviors/occupancy-sensing';
64
+ import { AirQualityServer } from '@matter/main/behaviors/air-quality';
65
+ import { CarbonMonoxideConcentrationMeasurementServer } from '@matter/main/behaviors/carbon-monoxide-concentration-measurement';
66
+ import { CarbonDioxideConcentrationMeasurementServer } from '@matter/main/behaviors/carbon-dioxide-concentration-measurement';
67
+ import { NitrogenDioxideConcentrationMeasurementServer } from '@matter/main/behaviors/nitrogen-dioxide-concentration-measurement';
68
+ import { OzoneConcentrationMeasurementServer } from '@matter/main/behaviors/ozone-concentration-measurement';
69
+ import { FormaldehydeConcentrationMeasurementServer } from '@matter/main/behaviors/formaldehyde-concentration-measurement';
70
+ import { Pm1ConcentrationMeasurementServer } from '@matter/main/behaviors/pm1-concentration-measurement';
71
+ import { Pm25ConcentrationMeasurementServer } from '@matter/main/behaviors/pm25-concentration-measurement';
72
+ import { Pm10ConcentrationMeasurementServer } from '@matter/main/behaviors/pm10-concentration-measurement';
73
+ import { RadonConcentrationMeasurementServer } from '@matter/main/behaviors/radon-concentration-measurement';
74
+ import { TotalVolatileOrganicCompoundsConcentrationMeasurementServer } from '@matter/main/behaviors/total-volatile-organic-compounds-concentration-measurement';
75
+ export function capitalizeFirstLetter(name) {
76
+ if (!name)
77
+ return name;
78
+ return name.charAt(0).toUpperCase() + name.slice(1);
79
+ }
80
+ export function lowercaseFirstLetter(name) {
81
+ if (!name)
82
+ return name;
83
+ return name.charAt(0).toLowerCase() + name.slice(1);
84
+ }
85
+ export function createUniqueId(param1, param2, param3, param4) {
86
+ const hash = createHash('md5');
87
+ hash.update(param1 + param2 + param3 + param4);
88
+ return hash.digest('hex');
89
+ }
90
+ export function getBehaviourTypesFromClusterServerIds(clusterServerList) {
91
+ const behaviorTypes = [];
92
+ clusterServerList.forEach((clusterId) => {
93
+ behaviorTypes.push(getBehaviourTypeFromClusterServerId(clusterId));
94
+ });
95
+ return behaviorTypes;
96
+ }
97
+ export function getBehaviourTypesFromClusterClientIds(clusterClientList) {
98
+ const behaviorTypes = [];
99
+ clusterClientList.forEach((clusterId) => {
100
+ });
101
+ return behaviorTypes;
102
+ }
103
+ export function getBehaviourTypeFromClusterServerId(clusterId) {
104
+ if (clusterId === PowerSource.Cluster.id)
105
+ return PowerSourceServer.with(PowerSource.Feature.Wired);
106
+ if (clusterId === UserLabel.Cluster.id)
107
+ return UserLabelServer;
108
+ if (clusterId === FixedLabel.Cluster.id)
109
+ return FixedLabelServer;
110
+ if (clusterId === BasicInformation.Cluster.id)
111
+ return BasicInformationServer;
112
+ if (clusterId === BridgedDeviceBasicInformation.Cluster.id)
113
+ return BridgedDeviceBasicInformationServer;
114
+ if (clusterId === Identify.Cluster.id)
115
+ return MatterbridgeIdentifyServer;
116
+ if (clusterId === Groups.Cluster.id)
117
+ return GroupsServer;
118
+ if (clusterId === OnOff.Cluster.id)
119
+ return MatterbridgeOnOffServer.with('Lighting');
120
+ if (clusterId === LevelControl.Cluster.id)
121
+ return MatterbridgeLevelControlServer.with('OnOff', 'Lighting');
122
+ if (clusterId === ColorControl.Cluster.id)
123
+ return MatterbridgeColorControlServer;
124
+ if (clusterId === WindowCovering.Cluster.id)
125
+ return MatterbridgeWindowCoveringServer.with('Lift', 'PositionAwareLift');
126
+ if (clusterId === Thermostat.Cluster.id)
127
+ return MatterbridgeThermostatServer.with('AutoMode', 'Heating', 'Cooling');
128
+ if (clusterId === FanControl.Cluster.id)
129
+ return MatterbridgeFanControlServer;
130
+ if (clusterId === DoorLock.Cluster.id)
131
+ return MatterbridgeDoorLockServer;
132
+ if (clusterId === ModeSelect.Cluster.id)
133
+ return MatterbridgeModeSelectServer;
134
+ if (clusterId === ValveConfigurationAndControl.Cluster.id)
135
+ return MatterbridgeValveConfigurationAndControlServer.with('Level');
136
+ if (clusterId === PumpConfigurationAndControl.Cluster.id)
137
+ return PumpConfigurationAndControlServer.with('ConstantSpeed');
138
+ if (clusterId === SmokeCoAlarm.Cluster.id)
139
+ return MatterbridgeSmokeCoAlarmServer.with('SmokeAlarm', 'CoAlarm');
140
+ if (clusterId === Switch.Cluster.id)
141
+ return SwitchServer.with('MomentarySwitch', 'MomentarySwitchRelease', 'MomentarySwitchLongPress', 'MomentarySwitchMultiPress');
142
+ if (clusterId === BooleanState.Cluster.id)
143
+ return BooleanStateServer.enable({ events: { stateChange: true } });
144
+ if (clusterId === BooleanStateConfiguration.Cluster.id)
145
+ return MatterbridgeBooleanStateConfigurationServer;
146
+ if (clusterId === PowerTopology.Cluster.id)
147
+ return PowerTopologyServer.with('TreeTopology');
148
+ if (clusterId === ElectricalPowerMeasurement.Cluster.id)
149
+ return ElectricalPowerMeasurementServer.with('AlternatingCurrent');
150
+ if (clusterId === ElectricalEnergyMeasurement.Cluster.id)
151
+ return ElectricalEnergyMeasurementServer.with('ImportedEnergy', 'ExportedEnergy', 'CumulativeEnergy');
152
+ if (clusterId === TemperatureMeasurement.Cluster.id)
153
+ return TemperatureMeasurementServer;
154
+ if (clusterId === RelativeHumidityMeasurement.Cluster.id)
155
+ return RelativeHumidityMeasurementServer;
156
+ if (clusterId === PressureMeasurement.Cluster.id)
157
+ return PressureMeasurementServer;
158
+ if (clusterId === FlowMeasurement.Cluster.id)
159
+ return FlowMeasurementServer;
160
+ if (clusterId === IlluminanceMeasurement.Cluster.id)
161
+ return IlluminanceMeasurementServer;
162
+ if (clusterId === OccupancySensing.Cluster.id)
163
+ return OccupancySensingServer;
164
+ if (clusterId === AirQuality.Cluster.id)
165
+ return AirQualityServer.with('Fair', 'Moderate', 'VeryPoor', 'ExtremelyPoor');
166
+ if (clusterId === CarbonMonoxideConcentrationMeasurement.Cluster.id)
167
+ return CarbonMonoxideConcentrationMeasurementServer.with('NumericMeasurement');
168
+ if (clusterId === CarbonDioxideConcentrationMeasurement.Cluster.id)
169
+ return CarbonDioxideConcentrationMeasurementServer.with('NumericMeasurement');
170
+ if (clusterId === NitrogenDioxideConcentrationMeasurement.Cluster.id)
171
+ return NitrogenDioxideConcentrationMeasurementServer.with('NumericMeasurement');
172
+ if (clusterId === OzoneConcentrationMeasurement.Cluster.id)
173
+ return OzoneConcentrationMeasurementServer.with('NumericMeasurement');
174
+ if (clusterId === FormaldehydeConcentrationMeasurement.Cluster.id)
175
+ return FormaldehydeConcentrationMeasurementServer.with('NumericMeasurement');
176
+ if (clusterId === Pm1ConcentrationMeasurement.Cluster.id)
177
+ return Pm1ConcentrationMeasurementServer.with('NumericMeasurement');
178
+ if (clusterId === Pm25ConcentrationMeasurement.Cluster.id)
179
+ return Pm25ConcentrationMeasurementServer.with('NumericMeasurement');
180
+ if (clusterId === Pm10ConcentrationMeasurement.Cluster.id)
181
+ return Pm10ConcentrationMeasurementServer.with('NumericMeasurement');
182
+ if (clusterId === RadonConcentrationMeasurement.Cluster.id)
183
+ return RadonConcentrationMeasurementServer.with('NumericMeasurement');
184
+ if (clusterId === TotalVolatileOrganicCompoundsConcentrationMeasurement.Cluster.id)
185
+ return TotalVolatileOrganicCompoundsConcentrationMeasurementServer.with('NumericMeasurement');
186
+ return MatterbridgeIdentifyServer;
187
+ }
188
+ export function getBehaviourTypeFromClusterClientId(clusterId) {
189
+ }
190
+ export function getBehavior(endpoint, cluster) {
191
+ let behavior;
192
+ if (typeof cluster === 'string') {
193
+ behavior = endpoint.behaviors.supported[lowercaseFirstLetter(cluster)];
194
+ }
195
+ else if (typeof cluster === 'number') {
196
+ behavior = endpoint.behaviors.supported[lowercaseFirstLetter(getClusterNameById(cluster))];
197
+ }
198
+ else if (typeof cluster === 'object') {
199
+ behavior = endpoint.behaviors.supported[lowercaseFirstLetter(cluster.name)];
200
+ }
201
+ else if (typeof cluster === 'function') {
202
+ behavior = cluster;
203
+ }
204
+ return behavior;
205
+ }
206
+ export function addRequiredClusterServers(endpoint) {
207
+ const requiredServerList = [];
208
+ endpoint.log.debug(`addRequiredClusterServers for ${CYAN}${endpoint.maybeId}${db}`);
209
+ Array.from(endpoint.deviceTypes.values()).forEach((deviceType) => {
210
+ endpoint.log.debug(`- for deviceType: ${zb}${'0x' + deviceType.code.toString(16).padStart(4, '0')}${db}-${zb}${deviceType.name}${db}`);
211
+ deviceType.requiredServerClusters.forEach((clusterId) => {
212
+ if (!requiredServerList.includes(clusterId) && !endpoint.hasClusterServer(clusterId)) {
213
+ requiredServerList.push(clusterId);
214
+ endpoint.log.debug(`- cluster: ${hk}${'0x' + clusterId.toString(16).padStart(4, '0')}${db}-${hk}${getClusterNameById(clusterId)}${db}`);
215
+ }
216
+ });
217
+ });
218
+ addClusterServers(endpoint, requiredServerList);
219
+ }
220
+ export function addOptionalClusterServers(endpoint) {
221
+ const optionalServerList = [];
222
+ endpoint.log.debug(`addOptionalClusterServers for ${CYAN}${endpoint.maybeId}${db}`);
223
+ Array.from(endpoint.deviceTypes.values()).forEach((deviceType) => {
224
+ endpoint.log.debug(`- for deviceType: ${zb}${'0x' + deviceType.code.toString(16).padStart(4, '0')}${db}-${zb}${deviceType.name}${db}`);
225
+ deviceType.optionalServerClusters.forEach((clusterId) => {
226
+ if (!optionalServerList.includes(clusterId) && !endpoint.hasClusterServer(clusterId)) {
227
+ optionalServerList.push(clusterId);
228
+ endpoint.log.debug(`- cluster: ${hk}${'0x' + clusterId.toString(16).padStart(4, '0')}${db}-${hk}${getClusterNameById(clusterId)}${db}`);
229
+ }
230
+ });
231
+ });
232
+ addClusterServers(endpoint, optionalServerList);
233
+ }
234
+ export function addClusterServers(endpoint, serverList) {
235
+ if (serverList.includes(PowerSource.Cluster.id))
236
+ endpoint.createDefaultPowerSourceWiredClusterServer();
237
+ if (serverList.includes(Identify.Cluster.id))
238
+ endpoint.createDefaultIdentifyClusterServer();
239
+ if (serverList.includes(Groups.Cluster.id))
240
+ endpoint.createDefaultGroupsClusterServer();
241
+ if (serverList.includes(OnOff.Cluster.id))
242
+ endpoint.createDefaultOnOffClusterServer();
243
+ if (serverList.includes(LevelControl.Cluster.id))
244
+ endpoint.createDefaultLevelControlClusterServer();
245
+ if (serverList.includes(ColorControl.Cluster.id))
246
+ endpoint.createDefaultColorControlClusterServer();
247
+ if (serverList.includes(WindowCovering.Cluster.id))
248
+ endpoint.createDefaultWindowCoveringClusterServer();
249
+ if (serverList.includes(Thermostat.Cluster.id))
250
+ endpoint.createDefaultThermostatClusterServer();
251
+ if (serverList.includes(FanControl.Cluster.id))
252
+ endpoint.createDefaultFanControlClusterServer();
253
+ if (serverList.includes(DoorLock.Cluster.id))
254
+ endpoint.createDefaultDoorLockClusterServer();
255
+ if (serverList.includes(ValveConfigurationAndControl.Cluster.id))
256
+ endpoint.createDefaultValveConfigurationAndControlClusterServer();
257
+ if (serverList.includes(PumpConfigurationAndControl.Cluster.id))
258
+ endpoint.createDefaultPumpConfigurationAndControlClusterServer();
259
+ if (serverList.includes(SmokeCoAlarm.Cluster.id))
260
+ endpoint.createDefaultSmokeCOAlarmClusterServer();
261
+ if (serverList.includes(Switch.Cluster.id))
262
+ endpoint.createDefaultSwitchClusterServer();
263
+ if (serverList.includes(BooleanState.Cluster.id))
264
+ endpoint.createDefaultBooleanStateClusterServer();
265
+ if (serverList.includes(BooleanStateConfiguration.Cluster.id))
266
+ endpoint.createDefaultBooleanStateConfigurationClusterServer();
267
+ if (serverList.includes(PowerTopology.Cluster.id))
268
+ endpoint.createDefaultPowerTopologyClusterServer();
269
+ if (serverList.includes(ElectricalPowerMeasurement.Cluster.id))
270
+ endpoint.createDefaultElectricalPowerMeasurementClusterServer();
271
+ if (serverList.includes(ElectricalEnergyMeasurement.Cluster.id))
272
+ endpoint.createDefaultElectricalEnergyMeasurementClusterServer();
273
+ if (serverList.includes(TemperatureMeasurement.Cluster.id))
274
+ endpoint.createDefaultTemperatureMeasurementClusterServer();
275
+ if (serverList.includes(RelativeHumidityMeasurement.Cluster.id))
276
+ endpoint.createDefaultRelativeHumidityMeasurementClusterServer();
277
+ if (serverList.includes(PressureMeasurement.Cluster.id))
278
+ endpoint.createDefaultPressureMeasurementClusterServer();
279
+ if (serverList.includes(FlowMeasurement.Cluster.id))
280
+ endpoint.createDefaultFlowMeasurementClusterServer();
281
+ if (serverList.includes(IlluminanceMeasurement.Cluster.id))
282
+ endpoint.createDefaultIlluminanceMeasurementClusterServer();
283
+ if (serverList.includes(OccupancySensing.Cluster.id))
284
+ endpoint.createDefaultOccupancySensingClusterServer();
285
+ if (serverList.includes(AirQuality.Cluster.id))
286
+ endpoint.createDefaultAirQualityClusterServer();
287
+ if (serverList.includes(CarbonMonoxideConcentrationMeasurement.Cluster.id))
288
+ endpoint.createDefaultCarbonMonoxideConcentrationMeasurementClusterServer();
289
+ if (serverList.includes(CarbonDioxideConcentrationMeasurement.Cluster.id))
290
+ endpoint.createDefaultCarbonDioxideConcentrationMeasurementClusterServer();
291
+ if (serverList.includes(NitrogenDioxideConcentrationMeasurement.Cluster.id))
292
+ endpoint.createDefaultNitrogenDioxideConcentrationMeasurementClusterServer();
293
+ if (serverList.includes(OzoneConcentrationMeasurement.Cluster.id))
294
+ endpoint.createDefaultOzoneConcentrationMeasurementClusterServer();
295
+ if (serverList.includes(FormaldehydeConcentrationMeasurement.Cluster.id))
296
+ endpoint.createDefaultFormaldehydeConcentrationMeasurementClusterServer();
297
+ if (serverList.includes(Pm1ConcentrationMeasurement.Cluster.id))
298
+ endpoint.createDefaultPm1ConcentrationMeasurementClusterServer();
299
+ if (serverList.includes(Pm25ConcentrationMeasurement.Cluster.id))
300
+ endpoint.createDefaultPm25ConcentrationMeasurementClusterServer();
301
+ if (serverList.includes(Pm10ConcentrationMeasurement.Cluster.id))
302
+ endpoint.createDefaultPm10ConcentrationMeasurementClusterServer();
303
+ if (serverList.includes(RadonConcentrationMeasurement.Cluster.id))
304
+ endpoint.createDefaultRadonConcentrationMeasurementClusterServer();
305
+ if (serverList.includes(TotalVolatileOrganicCompoundsConcentrationMeasurement.Cluster.id))
306
+ endpoint.createDefaultTvocMeasurementClusterServer();
307
+ }
308
+ export function optionsFor(type, options) {
309
+ return options;
310
+ }
311
+ export function getClusterId(endpoint, cluster) {
312
+ return endpoint.behaviors.supported[lowercaseFirstLetter(cluster)]?.schema?.id;
313
+ }
314
+ export function getAttributeId(endpoint, cluster, attribute) {
315
+ return endpoint.behaviors.supported[lowercaseFirstLetter(cluster)]?.schema?.children?.find((child) => child.name === capitalizeFirstLetter(attribute))?.id;
316
+ }
@@ -1,12 +1,12 @@
1
1
  {
2
2
  "name": "matterbridge",
3
- "version": "2.1.0-dev.3",
3
+ "version": "2.1.0-dev.4",
4
4
  "lockfileVersion": 3,
5
5
  "requires": true,
6
6
  "packages": {
7
7
  "": {
8
8
  "name": "matterbridge",
9
- "version": "2.1.0-dev.3",
9
+ "version": "2.1.0-dev.4",
10
10
  "license": "Apache-2.0",
11
11
  "dependencies": {
12
12
  "@matter/main": "0.12.1",
@@ -1491,12 +1491,6 @@
1491
1491
  "url": "https://github.com/sponsors/ljharb"
1492
1492
  }
1493
1493
  },
1494
- "node_modules/queue-tick": {
1495
- "version": "1.0.1",
1496
- "resolved": "https://registry.npmjs.org/queue-tick/-/queue-tick-1.0.1.tgz",
1497
- "integrity": "sha512-kJt5qhMxoszgU/62PLP1CJytzd2NKetjSRnyuj31fDd3Rlcz3fzlFdFLD1SItunPwyqEOkca6GbV612BWfaBag==",
1498
- "license": "MIT"
1499
- },
1500
1494
  "node_modules/range-parser": {
1501
1495
  "version": "1.2.1",
1502
1496
  "resolved": "https://registry.npmjs.org/range-parser/-/range-parser-1.2.1.tgz",
@@ -1777,13 +1771,12 @@
1777
1771
  }
1778
1772
  },
1779
1773
  "node_modules/streamx": {
1780
- "version": "2.21.1",
1781
- "resolved": "https://registry.npmjs.org/streamx/-/streamx-2.21.1.tgz",
1782
- "integrity": "sha512-PhP9wUnFLa+91CPy3N6tiQsK+gnYyUNuk15S3YG/zjYE7RuPeCjJngqnzpC31ow0lzBHQ+QGO4cNJnd0djYUsw==",
1774
+ "version": "2.22.0",
1775
+ "resolved": "https://registry.npmjs.org/streamx/-/streamx-2.22.0.tgz",
1776
+ "integrity": "sha512-sLh1evHOzBy/iWRiR6d1zRcLao4gGZr3C1kzNz4fopCOKJb6xD9ub8Mpi9Mr1R6id5o43S+d93fI48UC5uM9aw==",
1783
1777
  "license": "MIT",
1784
1778
  "dependencies": {
1785
1779
  "fast-fifo": "^1.3.2",
1786
- "queue-tick": "^1.0.1",
1787
1780
  "text-decoder": "^1.1.0"
1788
1781
  },
1789
1782
  "optionalDependencies": {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "matterbridge",
3
- "version": "2.1.0-dev.3",
3
+ "version": "2.1.0-dev.4",
4
4
  "description": "Matterbridge plugin manager for Matter",
5
5
  "author": "https://github.com/Luligu",
6
6
  "license": "Apache-2.0",