matterbridge-example-dynamic-platform 1.3.3 → 1.3.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
@@ -23,6 +23,21 @@ If you like this project and find it useful, please consider giving it a star on
23
23
  <img src="bmc-button.svg" alt="Buy me a coffee" width="120">
24
24
  </a>
25
25
 
26
+ ## [1.3.4] - 2025-07-22
27
+
28
+ ### Added
29
+
30
+ - [platform]: Changed to the new ExtratorHood() and Dishwasher() from Matterbridge.
31
+
32
+ ### Changed
33
+
34
+ - [package]: Updated dependencies.
35
+ - [package]: Required matterbridge 3.1.6.
36
+
37
+ <a href="https://www.buymeacoffee.com/luligugithub">
38
+ <img src="bmc-button.svg" alt="Buy me a coffee" width="80">
39
+ </a>
40
+
26
41
  ## [1.3.3] - 2025-07-20
27
42
 
28
43
  ### Added
package/README.md CHANGED
@@ -17,7 +17,7 @@
17
17
 
18
18
  Matterbridge dynamic platform example plugin is a template to develop your own plugin using the dynamic platform.
19
19
 
20
- It exposes 44 virtual devices:
20
+ It exposes 45 virtual devices:
21
21
 
22
22
  - a switch with onOff cluster
23
23
  - a light with onOff
@@ -35,6 +35,7 @@ It exposes 44 virtual devices:
35
35
  - a thermo heat only with two external temperature sensors (tagged like Indoor and Outdoor)
36
36
  - a thermo cool only
37
37
  - a fan with FanControl cluster
38
+ - a fan with all the features from FanControl cluster
38
39
  - a rainSensor device
39
40
  - a waterFreezeDetector device
40
41
  - a waterLeakDetector device
package/dist/platform.js CHANGED
@@ -1,6 +1,7 @@
1
- import { MatterbridgeEndpoint, MatterbridgeDynamicPlatform, airQualitySensor, bridgedNode, colorTemperatureLight, coverDevice, dimmableLight, doorLockDevice, fanDevice, flowSensor, humiditySensor, onOffLight, onOffOutlet, onOffSwitch, powerSource, rainSensor, smokeCoAlarm, temperatureSensor, thermostatDevice, waterFreezeDetector, waterLeakDetector, airPurifier, pumpDevice, waterValve, genericSwitch, airConditioner, cooktop, extractorHood, microwaveOven, oven, refrigerator, dishwasher, onOffMountedSwitch, dimmableMountedSwitch, extendedColorLight, } from 'matterbridge';
2
- import { RoboticVacuumCleaner, LaundryWasher, WaterHeater, Evse, SolarPower, BatteryStorage, LaundryDryer, HeatPump } from 'matterbridge/devices';
1
+ import { MatterbridgeEndpoint, MatterbridgeDynamicPlatform, airQualitySensor, bridgedNode, colorTemperatureLight, coverDevice, dimmableLight, doorLockDevice, fanDevice, flowSensor, humiditySensor, onOffLight, onOffOutlet, onOffSwitch, powerSource, rainSensor, smokeCoAlarm, temperatureSensor, thermostatDevice, waterFreezeDetector, waterLeakDetector, airPurifier, pumpDevice, waterValve, genericSwitch, airConditioner, cooktop, microwaveOven, oven, refrigerator, onOffMountedSwitch, dimmableMountedSwitch, extendedColorLight, } from 'matterbridge';
2
+ import { RoboticVacuumCleaner, LaundryWasher, WaterHeater, Evse, SolarPower, BatteryStorage, LaundryDryer, HeatPump, Dishwasher, ExtractorHood } from 'matterbridge/devices';
3
3
  import { isValidBoolean, isValidNumber } from 'matterbridge/utils';
4
+ import { debugStringify } from 'matterbridge/logger';
4
5
  import { AreaNamespaceTag, LocationTag, NumberTag, PositionTag } from 'matterbridge/matter';
5
6
  import { PowerSource, BooleanState, OnOff, LevelControl, AirQuality, CarbonDioxideConcentrationMeasurement, CarbonMonoxideConcentrationMeasurement, FlowMeasurement, ColorControl, DoorLock, FanControl, FormaldehydeConcentrationMeasurement, NitrogenDioxideConcentrationMeasurement, OzoneConcentrationMeasurement, Pm10ConcentrationMeasurement, Pm1ConcentrationMeasurement, Pm25ConcentrationMeasurement, RadonConcentrationMeasurement, RelativeHumidityMeasurement, RelativeHumidityMeasurementCluster, SmokeCoAlarm, TemperatureMeasurement, Thermostat, ThermostatCluster, TotalVolatileOrganicCompoundsConcentrationMeasurement, WindowCovering, EnergyEvseMode, EnergyEvse, RvcRunMode, RvcCleanMode, } from 'matterbridge/matter/clusters';
6
7
  import { Appliances } from './appliances.js';
@@ -22,6 +23,7 @@ export class ExampleMatterbridgeDynamicPlatform extends MatterbridgeDynamicPlatf
22
23
  thermoHeat;
23
24
  thermoCool;
24
25
  fan;
26
+ fanComplete;
25
27
  waterLeak;
26
28
  waterFreeze;
27
29
  rain;
@@ -40,6 +42,8 @@ export class ExampleMatterbridgeDynamicPlatform extends MatterbridgeDynamicPlatf
40
42
  evse;
41
43
  laundryWasher;
42
44
  laundryDryer;
45
+ dishwasher;
46
+ extractorHood;
43
47
  solarPower;
44
48
  batteryStorage;
45
49
  heatPump;
@@ -63,10 +67,11 @@ export class ExampleMatterbridgeDynamicPlatform extends MatterbridgeDynamicPlatf
63
67
  intervalColorTemperature = 147;
64
68
  bridgedDevices = new Map();
65
69
  fanModeLookup = ['Off', 'Low', 'Medium', 'High', 'On', 'Auto', 'Smart'];
70
+ fanDirectionLookup = ['Forward', 'Reverse'];
66
71
  constructor(matterbridge, log, config) {
67
72
  super(matterbridge, log, config);
68
- if (this.verifyMatterbridgeVersion === undefined || typeof this.verifyMatterbridgeVersion !== 'function' || !this.verifyMatterbridgeVersion('3.1.5')) {
69
- throw new Error(`This plugin requires Matterbridge version >= "3.1.5". Please update Matterbridge from ${this.matterbridge.matterbridgeVersion} to the latest version in the frontend.`);
73
+ if (this.verifyMatterbridgeVersion === undefined || typeof this.verifyMatterbridgeVersion !== 'function' || !this.verifyMatterbridgeVersion('3.1.6')) {
74
+ throw new Error(`This plugin requires Matterbridge version >= "3.1.6". Please update Matterbridge from ${this.matterbridge.matterbridgeVersion} to the latest version in the frontend.`);
70
75
  }
71
76
  this.log.info('Initializing platform:', this.config.name);
72
77
  if (config.whiteList === undefined)
@@ -842,6 +847,64 @@ export class ExampleMatterbridgeDynamicPlatform extends MatterbridgeDynamicPlatf
842
847
  if (isValidNumber(newValue, 0, 100))
843
848
  this.fan?.setAttribute(FanControl.Cluster.id, 'percentCurrent', newValue, this.fan?.log);
844
849
  }, this.fan.log);
850
+ this.fanComplete = new MatterbridgeEndpoint([fanDevice, bridgedNode, powerSource], { uniqueStorageKey: 'Fan complete' }, this.config.debug)
851
+ .createDefaultBridgedDeviceBasicInformationClusterServer('Fan complete', 'serial_980995631228', 0xfff1, 'Matterbridge', 'Matterbridge Fan', parseInt(this.version.replace(/\D/g, '')), this.version === '' ? 'Unknown' : this.version, parseInt(this.matterbridge.matterbridgeVersion.replace(/\D/g, '')), this.matterbridge.matterbridgeVersion)
852
+ .createDefaultPowerSourceWiredClusterServer()
853
+ .createCompleteFanControlClusterServer()
854
+ .addRequiredClusterServers();
855
+ this.setSelectDevice(this.fanComplete.serialNumber ?? '', this.fanComplete.deviceName ?? '', undefined, 'hub');
856
+ if (this.validateDevice(this.fanComplete.deviceName ?? '')) {
857
+ await this.registerDevice(this.fanComplete);
858
+ this.bridgedDevices.set(this.fanComplete.deviceName ?? '', this.fanComplete);
859
+ }
860
+ else {
861
+ this.fanComplete = undefined;
862
+ }
863
+ await this.fanComplete?.subscribeAttribute(FanControl.Cluster.id, 'fanMode', (newValue, oldValue, context) => {
864
+ this.fanComplete?.log.info(`Fan mode changed from ${this.fanModeLookup[oldValue]} to ${this.fanModeLookup[newValue]} context: ${context.offline === true ? 'offline' : 'online'}`);
865
+ if (context.offline === true)
866
+ return;
867
+ if (newValue === FanControl.FanMode.Off) {
868
+ this.fanComplete?.setAttribute(FanControl.Cluster.id, 'percentSetting', 0, this.fanComplete?.log);
869
+ this.fanComplete?.setAttribute(FanControl.Cluster.id, 'percentCurrent', 0, this.fanComplete?.log);
870
+ }
871
+ else if (newValue === FanControl.FanMode.Low) {
872
+ this.fanComplete?.setAttribute(FanControl.Cluster.id, 'percentSetting', 33, this.fanComplete?.log);
873
+ this.fanComplete?.setAttribute(FanControl.Cluster.id, 'percentCurrent', 33, this.fanComplete?.log);
874
+ }
875
+ else if (newValue === FanControl.FanMode.Medium) {
876
+ this.fanComplete?.setAttribute(FanControl.Cluster.id, 'percentSetting', 66, this.fanComplete?.log);
877
+ this.fanComplete?.setAttribute(FanControl.Cluster.id, 'percentCurrent', 66, this.fanComplete?.log);
878
+ }
879
+ else if (newValue === FanControl.FanMode.High) {
880
+ this.fanComplete?.setAttribute(FanControl.Cluster.id, 'percentSetting', 100, this.fanComplete?.log);
881
+ this.fanComplete?.setAttribute(FanControl.Cluster.id, 'percentCurrent', 100, this.fanComplete?.log);
882
+ }
883
+ else if (newValue === FanControl.FanMode.On) {
884
+ this.fanComplete?.setAttribute(FanControl.Cluster.id, 'percentSetting', 100, this.fanComplete?.log);
885
+ this.fanComplete?.setAttribute(FanControl.Cluster.id, 'percentCurrent', 100, this.fanComplete?.log);
886
+ }
887
+ else if (newValue === FanControl.FanMode.Auto) {
888
+ this.fanComplete?.setAttribute(FanControl.Cluster.id, 'percentSetting', 50, this.fanComplete?.log);
889
+ this.fanComplete?.setAttribute(FanControl.Cluster.id, 'percentCurrent', 50, this.fanComplete?.log);
890
+ }
891
+ }, this.fanComplete?.log);
892
+ await this.fanComplete?.subscribeAttribute(FanControl.Cluster.id, 'percentSetting', (newValue, oldValue, context) => {
893
+ this.fanComplete?.log.info(`Percent setting changed from ${oldValue} to ${newValue} context: ${context.offline === true ? 'offline' : 'online'}`);
894
+ if (context.offline === true)
895
+ return;
896
+ if (isValidNumber(newValue, 0, 100))
897
+ this.fanComplete?.setAttribute(FanControl.Cluster.id, 'percentCurrent', newValue, this.fanComplete?.log);
898
+ }, this.fanComplete?.log);
899
+ await this.fanComplete?.subscribeAttribute(FanControl.Cluster.id, 'rockSetting', (newValue, oldValue, context) => {
900
+ this.fanComplete?.log.info(`Rock setting changed from ${debugStringify(oldValue)} to ${debugStringify(newValue)} context: ${context.offline === true ? 'offline' : 'online'}`);
901
+ }, this.fanComplete?.log);
902
+ await this.fanComplete?.subscribeAttribute(FanControl.Cluster.id, 'windSetting', (newValue, oldValue, context) => {
903
+ this.fanComplete?.log.info(`Wind setting changed from ${debugStringify(oldValue)} to ${debugStringify(newValue)} context: ${context.offline === true ? 'offline' : 'online'}`);
904
+ }, this.fanComplete?.log);
905
+ await this.fanComplete?.subscribeAttribute(FanControl.Cluster.id, 'airflowDirection', (newValue, oldValue, context) => {
906
+ this.fanComplete?.log.info(`Airflow direction changed from ${this.fanDirectionLookup[oldValue]} to ${this.fanDirectionLookup[newValue]} context: ${context.offline === true ? 'offline' : 'online'}`);
907
+ }, this.fanComplete?.log);
845
908
  this.waterLeak = new MatterbridgeEndpoint([waterLeakDetector, bridgedNode, powerSource], { uniqueStorageKey: 'Water leak detector' }, this.config.debug)
846
909
  .createDefaultBridgedDeviceBasicInformationClusterServer('Water leak detector', 'serial_98745631222', 0xfff1, 'Matterbridge', 'Matterbridge WaterLeakDetector', parseInt(this.version.replace(/\D/g, '')), this.version === '' ? 'Unknown' : this.version, parseInt(this.matterbridge.matterbridgeVersion.replace(/\D/g, '')), this.matterbridge.matterbridgeVersion)
847
910
  .createDefaultPowerSourceRechargeableBatteryClusterServer()
@@ -1103,11 +1166,17 @@ export class ExampleMatterbridgeDynamicPlatform extends MatterbridgeDynamicPlatf
1103
1166
  await this.registerDevice(this.laundryDryer);
1104
1167
  this.bridgedDevices.set(this.laundryDryer.deviceName ?? '', this.laundryDryer);
1105
1168
  }
1106
- const dishwasherDevice = new Appliances(dishwasher, 'Dishwasher', 'DW0987654321');
1107
- this.setSelectDevice(dishwasherDevice.serialNumber ?? '', dishwasherDevice.deviceName ?? '', undefined, 'hub');
1108
- if (this.validateDevice(dishwasherDevice.deviceName ?? '')) {
1109
- await this.registerDevice(dishwasherDevice);
1110
- this.bridgedDevices.set(dishwasherDevice.deviceName ?? '', dishwasherDevice);
1169
+ this.dishwasher = new Dishwasher('Dishwasher', 'DW1234567890');
1170
+ this.setSelectDevice(this.dishwasher.serialNumber ?? '', this.dishwasher.deviceName ?? '', undefined, 'hub');
1171
+ if (this.validateDevice(this.dishwasher.deviceName ?? '')) {
1172
+ await this.registerDevice(this.dishwasher);
1173
+ this.bridgedDevices.set(this.dishwasher.deviceName ?? '', this.dishwasher);
1174
+ }
1175
+ this.extractorHood = new ExtractorHood('Extractor Hood', 'EH1234567893');
1176
+ this.setSelectDevice(this.extractorHood.serialNumber ?? '', this.extractorHood.deviceName ?? '', undefined, 'hub');
1177
+ if (this.validateDevice(this.extractorHood.deviceName ?? '')) {
1178
+ await this.registerDevice(this.extractorHood);
1179
+ this.bridgedDevices.set(this.extractorHood.deviceName ?? '', this.extractorHood);
1111
1180
  }
1112
1181
  const refrigeratorDevice = new Appliances(refrigerator, 'Refrigerator', 'RE9987654322');
1113
1182
  refrigeratorDevice.addFixedLabel('composed', 'Refrigerator');
@@ -1129,12 +1198,6 @@ export class ExampleMatterbridgeDynamicPlatform extends MatterbridgeDynamicPlatf
1129
1198
  await this.registerDevice(microwaveOvenDevice);
1130
1199
  this.bridgedDevices.set(microwaveOvenDevice.deviceName ?? '', microwaveOvenDevice);
1131
1200
  }
1132
- const extractorHoodDevice = new Appliances(extractorHood, 'Extractor Hood', 'EH1234567893');
1133
- this.setSelectDevice(extractorHoodDevice.serialNumber ?? '', extractorHoodDevice.deviceName ?? '', undefined, 'hub');
1134
- if (this.validateDevice(extractorHoodDevice.deviceName ?? '')) {
1135
- await this.registerDevice(extractorHoodDevice);
1136
- this.bridgedDevices.set(extractorHoodDevice.deviceName ?? '', extractorHoodDevice);
1137
- }
1138
1201
  const cooktopDevice = new Appliances(cooktop, 'Cooktop', 'CT1255887894');
1139
1202
  this.setSelectDevice(cooktopDevice.serialNumber ?? '', cooktopDevice.deviceName ?? '', undefined, 'hub');
1140
1203
  if (this.validateDevice(cooktopDevice.deviceName ?? '')) {
@@ -1,12 +1,12 @@
1
1
  {
2
2
  "name": "matterbridge-example-dynamic-platform",
3
- "version": "1.3.3",
3
+ "version": "1.3.4",
4
4
  "lockfileVersion": 3,
5
5
  "requires": true,
6
6
  "packages": {
7
7
  "": {
8
8
  "name": "matterbridge-example-dynamic-platform",
9
- "version": "1.3.3",
9
+ "version": "1.3.4",
10
10
  "license": "Apache-2.0",
11
11
  "dependencies": {
12
12
  "node-ansi-logger": "3.1.1",
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "matterbridge-example-dynamic-platform",
3
- "version": "1.3.3",
3
+ "version": "1.3.4",
4
4
  "description": "Matterbridge dynamic plugin",
5
5
  "author": "https://github.com/Luligu",
6
6
  "license": "Apache-2.0",