matterbridge-example-dynamic-platform 1.3.5-dev-20250723-2f335a4 → 1.3.6-dev-20250725-69a3f4f

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,23 @@ 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.6] - 2025-07-25
27
+
28
+ ### Added
29
+
30
+ - [platform]: Added a Fan with Off High.
31
+ - [momentary]: Added 3 other child endpoint to the Momentary Switch to show createDefaultMomentarySwitchClusterServer(). It creates a single click only switch. It is supported by the Home app.
32
+ - [platform]: Refactor platform code to improve readability.
33
+
34
+ ### Changed
35
+
36
+ - [package]: Updated dependencies.
37
+ - [package]: Required matterbridge 3.1.7.
38
+
39
+ <a href="https://www.buymeacoffee.com/luligugithub">
40
+ <img src="bmc-button.svg" alt="Buy me a coffee" width="80">
41
+ </a>
42
+
26
43
  ## [1.3.5] - 2025-07-22
27
44
 
28
45
  ### 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 46 virtual devices:
20
+ It exposes 47 virtual devices:
21
21
 
22
22
  - a switch with onOff cluster
23
23
  - a light with onOff
@@ -34,9 +34,10 @@ It exposes 46 virtual devices:
34
34
  and relativeHumidityMeasurement cluster (to show how to create a composed device with sub endpoints)
35
35
  - a thermo heat only with two external temperature sensors (tagged like Indoor and Outdoor)
36
36
  - a thermo cool only
37
+ - a fan with Off High presets
37
38
  - a fan with Off Low Med High presets
38
39
  - a fan with Off Low Med High Auto presets and step
39
- - a fan with all the features
40
+ - a fan with all the features MultiSpeed, Auto, Step, Rock, Wind and AirflowDirection and mode Off Low Med High Auto.
40
41
  - a rainSensor device
41
42
  - a waterFreezeDetector device
42
43
  - a waterLeakDetector device
@@ -48,7 +49,7 @@ It exposes 46 virtual devices:
48
49
  - a pumpDevice device
49
50
  - a waterValve device
50
51
  - an airQuality device with all concentration measurements clusters (supported by Apple Home with the concentration measurements from version 18.5)
51
- - a momentary switch composed by three switches (tagged with One Two Three and Top Middle Bottom)
52
+ - a momentary switch composed by three switches with Single Double Long (tagged with One Two Three and Top Middle Bottom) and three switches with Single only.
52
53
  - a latching switch
53
54
  - a Robot Vacuum Cleaner device (supported by SmartThings, Alexa, Home Assistant and partially by Apple Home). Read also https://github.com/Luligu/matterbridge/discussions/264.
54
55
  - a onOff Mounted Switch device (supported by SmartThings, Alexa, Home Assistant)
package/dist/platform.js CHANGED
@@ -2,7 +2,7 @@ import { MatterbridgeEndpoint, MatterbridgeDynamicPlatform, airQualitySensor, br
2
2
  import { RoboticVacuumCleaner, LaundryWasher, WaterHeater, Evse, SolarPower, BatteryStorage, LaundryDryer, HeatPump, Dishwasher, ExtractorHood } from 'matterbridge/devices';
3
3
  import { isValidBoolean, isValidNumber } from 'matterbridge/utils';
4
4
  import { debugStringify } from 'matterbridge/logger';
5
- import { AreaNamespaceTag, LocationTag, NumberTag, PositionTag } from 'matterbridge/matter';
5
+ import { AreaNamespaceTag, LocationTag, NumberTag, PositionTag, SwitchesTag } from 'matterbridge/matter';
6
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';
7
7
  import { Appliances } from './appliances.js';
8
8
  export class ExampleMatterbridgeDynamicPlatform extends MatterbridgeDynamicPlatform {
@@ -22,8 +22,9 @@ export class ExampleMatterbridgeDynamicPlatform extends MatterbridgeDynamicPlatf
22
22
  thermoAuto;
23
23
  thermoHeat;
24
24
  thermoCool;
25
- fan;
26
- fanauto;
25
+ fanBase;
26
+ fanOnHigh;
27
+ fanDefault;
27
28
  fanComplete;
28
29
  waterLeak;
29
30
  waterFreeze;
@@ -72,8 +73,8 @@ export class ExampleMatterbridgeDynamicPlatform extends MatterbridgeDynamicPlatf
72
73
  fanDirectionLookup = ['Forward', 'Reverse'];
73
74
  constructor(matterbridge, log, config) {
74
75
  super(matterbridge, log, config);
75
- if (this.verifyMatterbridgeVersion === undefined || typeof this.verifyMatterbridgeVersion !== 'function' || !this.verifyMatterbridgeVersion('3.1.6')) {
76
- 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.`);
76
+ if (this.verifyMatterbridgeVersion === undefined || typeof this.verifyMatterbridgeVersion !== 'function' || !this.verifyMatterbridgeVersion('3.1.7')) {
77
+ throw new Error(`This plugin requires Matterbridge version >= "3.1.7". Please update Matterbridge from ${this.matterbridge.matterbridgeVersion} to the latest version in the frontend.`);
77
78
  }
78
79
  this.log.info('Initializing platform:', this.config.name);
79
80
  if (config.whiteList === undefined)
@@ -92,7 +93,7 @@ export class ExampleMatterbridgeDynamicPlatform extends MatterbridgeDynamicPlatf
92
93
  this.switch = new MatterbridgeEndpoint([onOffSwitch, bridgedNode, powerSource], { uniqueStorageKey: 'Switch' }, this.config.debug)
93
94
  .createDefaultIdentifyClusterServer()
94
95
  .createDefaultGroupsClusterServer()
95
- .createDefaultBridgedDeviceBasicInformationClusterServer('Switch', '0x23452164', 0xfff1, 'Matterbridge', 'Matterbridge Switch', parseInt(this.version.replace(/\D/g, '')), this.version === '' ? 'Unknown' : this.version, parseInt(this.matterbridge.matterbridgeVersion.replace(/\D/g, '')), this.matterbridge.matterbridgeVersion)
96
+ .createDefaultBridgedDeviceBasicInformationClusterServer('Switch', '0x23452164', 0xfff1, 'Matterbridge', 'Matterbridge Switch')
96
97
  .createDefaultOnOffClusterServer()
97
98
  .createDefaultPowerSourceRechargeableBatteryClusterServer(70);
98
99
  this.switch = await this.addDevice(this.switch);
@@ -110,7 +111,7 @@ export class ExampleMatterbridgeDynamicPlatform extends MatterbridgeDynamicPlatf
110
111
  this.mountedOnOffSwitch = new MatterbridgeEndpoint([onOffMountedSwitch, bridgedNode, powerSource], { uniqueStorageKey: 'OnOffMountedSwitch' }, this.config.debug)
111
112
  .createDefaultIdentifyClusterServer()
112
113
  .createDefaultGroupsClusterServer()
113
- .createDefaultBridgedDeviceBasicInformationClusterServer('OnOff Mounted Switch', '0x298242164', 0xfff1, 'Matterbridge', 'Matterbridge OnOff Mounted Switch', parseInt(this.version.replace(/\D/g, '')), this.version === '' ? 'Unknown' : this.version, parseInt(this.matterbridge.matterbridgeVersion.replace(/\D/g, '')), this.matterbridge.matterbridgeVersion)
114
+ .createDefaultBridgedDeviceBasicInformationClusterServer('OnOff Mounted Switch', '0x298242164', 0xfff1, 'Matterbridge', 'Matterbridge OnOff Mounted Switch')
114
115
  .createDefaultOnOffClusterServer()
115
116
  .createDefaultPowerSourceRechargeableBatteryClusterServer(70);
116
117
  this.mountedOnOffSwitch = await this.addDevice(this.mountedOnOffSwitch);
@@ -128,7 +129,7 @@ export class ExampleMatterbridgeDynamicPlatform extends MatterbridgeDynamicPlatf
128
129
  this.mountedDimmerSwitch = new MatterbridgeEndpoint([dimmableMountedSwitch, bridgedNode, powerSource], { uniqueStorageKey: 'DimmerMountedSwitch' }, this.config.debug)
129
130
  .createDefaultIdentifyClusterServer()
130
131
  .createDefaultGroupsClusterServer()
131
- .createDefaultBridgedDeviceBasicInformationClusterServer('Dimmer Mounted Switch', '0x22145578864', 0xfff1, 'Matterbridge', 'Matterbridge Dimmer Mounted Switch', parseInt(this.version.replace(/\D/g, '')), this.version === '' ? 'Unknown' : this.version, parseInt(this.matterbridge.matterbridgeVersion.replace(/\D/g, '')), this.matterbridge.matterbridgeVersion)
132
+ .createDefaultBridgedDeviceBasicInformationClusterServer('Dimmer Mounted Switch', '0x22145578864', 0xfff1, 'Matterbridge', 'Matterbridge Dimmer Mounted Switch')
132
133
  .createDefaultOnOffClusterServer()
133
134
  .createDefaultLevelControlClusterServer()
134
135
  .createDefaultPowerSourceWiredClusterServer()
@@ -156,7 +157,7 @@ export class ExampleMatterbridgeDynamicPlatform extends MatterbridgeDynamicPlatf
156
157
  this.lightOnOff = new MatterbridgeEndpoint([onOffLight, bridgedNode, powerSource], { uniqueStorageKey: 'Light (on/off)' }, this.config.debug)
157
158
  .createDefaultIdentifyClusterServer()
158
159
  .createDefaultGroupsClusterServer()
159
- .createDefaultBridgedDeviceBasicInformationClusterServer('Light (on/off)', '0x2342375564', 0xfff1, 'Matterbridge', 'Matterbridge Light on/off', parseInt(this.version.replace(/\D/g, '')), this.version === '' ? 'Unknown' : this.version, parseInt(this.matterbridge.matterbridgeVersion.replace(/\D/g, '')), this.matterbridge.matterbridgeVersion)
160
+ .createDefaultBridgedDeviceBasicInformationClusterServer('Light (on/off)', '0x2342375564', 0xfff1, 'Matterbridge', 'Matterbridge Light on/off')
160
161
  .createDefaultOnOffClusterServer()
161
162
  .createDefaultPowerSourceWiredClusterServer();
162
163
  this.lightOnOff = await this.addDevice(this.lightOnOff);
@@ -174,7 +175,7 @@ export class ExampleMatterbridgeDynamicPlatform extends MatterbridgeDynamicPlatf
174
175
  this.dimmer = new MatterbridgeEndpoint([dimmableLight, bridgedNode, powerSource], { uniqueStorageKey: 'Dimmer' }, this.config.debug)
175
176
  .createDefaultIdentifyClusterServer()
176
177
  .createDefaultGroupsClusterServer()
177
- .createDefaultBridgedDeviceBasicInformationClusterServer('Dimmer', '0x234554564', 0xfff1, 'Matterbridge', 'Matterbridge Dimmer', parseInt(this.version.replace(/\D/g, '')), this.version === '' ? 'Unknown' : this.version, parseInt(this.matterbridge.matterbridgeVersion.replace(/\D/g, '')), this.matterbridge.matterbridgeVersion)
178
+ .createDefaultBridgedDeviceBasicInformationClusterServer('Dimmer', '0x234554564', 0xfff1, 'Matterbridge', 'Matterbridge Dimmer')
178
179
  .createDefaultOnOffClusterServer()
179
180
  .createDefaultLevelControlClusterServer()
180
181
  .createDefaultPowerSourceReplaceableBatteryClusterServer(70, PowerSource.BatChargeLevel.Ok, 2990, '2 x AA', 2);
@@ -201,7 +202,7 @@ export class ExampleMatterbridgeDynamicPlatform extends MatterbridgeDynamicPlatf
201
202
  this.light = new MatterbridgeEndpoint([extendedColorLight, bridgedNode, powerSource], { uniqueStorageKey: 'Light (XY, HS and CT)' }, this.config.debug)
202
203
  .createDefaultIdentifyClusterServer()
203
204
  .createDefaultGroupsClusterServer()
204
- .createDefaultBridgedDeviceBasicInformationClusterServer('Light (XY, HS and CT)', '0x23480564', 0xfff1, 'Matterbridge', 'Matterbridge Light', parseInt(this.version.replace(/\D/g, '')), this.version === '' ? 'Unknown' : this.version, parseInt(this.matterbridge.matterbridgeVersion.replace(/\D/g, '')), this.matterbridge.matterbridgeVersion)
205
+ .createDefaultBridgedDeviceBasicInformationClusterServer('Light (XY, HS and CT)', '0x23480564', 0xfff1, 'Matterbridge', 'Matterbridge Light')
205
206
  .createDefaultOnOffClusterServer()
206
207
  .createDefaultLevelControlClusterServer()
207
208
  .createDefaultColorControlClusterServer()
@@ -251,7 +252,7 @@ export class ExampleMatterbridgeDynamicPlatform extends MatterbridgeDynamicPlatf
251
252
  this.lightHS = new MatterbridgeEndpoint([colorTemperatureLight, bridgedNode, powerSource], { uniqueStorageKey: 'Light (HS, CT)' }, this.config.debug)
252
253
  .createDefaultIdentifyClusterServer()
253
254
  .createDefaultGroupsClusterServer()
254
- .createDefaultBridgedDeviceBasicInformationClusterServer('Light (HS, CT)', '0x25097564', 0xfff1, 'Matterbridge', 'Matterbridge Light', parseInt(this.version.replace(/\D/g, '')), this.version === '' ? 'Unknown' : this.version, parseInt(this.matterbridge.matterbridgeVersion.replace(/\D/g, '')), this.matterbridge.matterbridgeVersion)
255
+ .createDefaultBridgedDeviceBasicInformationClusterServer('Light (HS, CT)', '0x25097564', 0xfff1, 'Matterbridge', 'Matterbridge Light')
255
256
  .createDefaultOnOffClusterServer()
256
257
  .createDefaultLevelControlClusterServer()
257
258
  .createHsColorControlClusterServer()
@@ -296,7 +297,7 @@ export class ExampleMatterbridgeDynamicPlatform extends MatterbridgeDynamicPlatf
296
297
  this.lightXY = new MatterbridgeEndpoint([extendedColorLight, bridgedNode, powerSource], { uniqueStorageKey: 'Light (XY, CT)' }, this.config.debug)
297
298
  .createDefaultIdentifyClusterServer()
298
299
  .createDefaultGroupsClusterServer()
299
- .createDefaultBridgedDeviceBasicInformationClusterServer('Light (XY, CT)', '0x23497564', 0xfff1, 'Matterbridge', 'Matterbridge Light', parseInt(this.version.replace(/\D/g, '')), this.version === '' ? 'Unknown' : this.version, parseInt(this.matterbridge.matterbridgeVersion.replace(/\D/g, '')), this.matterbridge.matterbridgeVersion)
300
+ .createDefaultBridgedDeviceBasicInformationClusterServer('Light (XY, CT)', '0x23497564', 0xfff1, 'Matterbridge', 'Matterbridge Light')
300
301
  .createDefaultOnOffClusterServer()
301
302
  .createDefaultLevelControlClusterServer()
302
303
  .createXyColorControlClusterServer()
@@ -333,7 +334,7 @@ export class ExampleMatterbridgeDynamicPlatform extends MatterbridgeDynamicPlatf
333
334
  this.lightCT = new MatterbridgeEndpoint([colorTemperatureLight, bridgedNode, powerSource], { uniqueStorageKey: 'Light (CT)' }, this.config.debug)
334
335
  .createDefaultIdentifyClusterServer()
335
336
  .createDefaultGroupsClusterServer()
336
- .createDefaultBridgedDeviceBasicInformationClusterServer('Light (CT)', '0x23480749', 0xfff1, 'Matterbridge', 'Matterbridge Light', parseInt(this.version.replace(/\D/g, '')), this.version === '' ? 'Unknown' : this.version, parseInt(this.matterbridge.matterbridgeVersion.replace(/\D/g, '')), this.matterbridge.matterbridgeVersion)
337
+ .createDefaultBridgedDeviceBasicInformationClusterServer('Light (CT)', '0x23480749', 0xfff1, 'Matterbridge', 'Matterbridge Light')
337
338
  .createDefaultOnOffClusterServer()
338
339
  .createDefaultLevelControlClusterServer()
339
340
  .createCtColorControlClusterServer()
@@ -365,7 +366,7 @@ export class ExampleMatterbridgeDynamicPlatform extends MatterbridgeDynamicPlatf
365
366
  this.outlet = new MatterbridgeEndpoint([onOffOutlet, bridgedNode, powerSource], { uniqueStorageKey: 'Outlet' }, this.config.debug)
366
367
  .createDefaultIdentifyClusterServer()
367
368
  .createDefaultGroupsClusterServer()
368
- .createDefaultBridgedDeviceBasicInformationClusterServer('Outlet', '0x29252164', 0xfff1, 'Matterbridge', 'Matterbridge Outlet', parseInt(this.version.replace(/\D/g, '')), this.version === '' ? 'Unknown' : this.version, parseInt(this.matterbridge.matterbridgeVersion.replace(/\D/g, '')), this.matterbridge.matterbridgeVersion)
369
+ .createDefaultBridgedDeviceBasicInformationClusterServer('Outlet', '0x29252164', 0xfff1, 'Matterbridge', 'Matterbridge Outlet')
369
370
  .createDefaultOnOffClusterServer()
370
371
  .createDefaultPowerSourceWiredClusterServer();
371
372
  this.outlet = await this.addDevice(this.outlet);
@@ -383,7 +384,7 @@ export class ExampleMatterbridgeDynamicPlatform extends MatterbridgeDynamicPlatf
383
384
  this.coverLift = new MatterbridgeEndpoint([coverDevice, bridgedNode, powerSource], { uniqueStorageKey: 'CoverLift' }, this.config.debug)
384
385
  .createDefaultIdentifyClusterServer()
385
386
  .createDefaultGroupsClusterServer()
386
- .createDefaultBridgedDeviceBasicInformationClusterServer('Cover lift', 'CL01020564', 0xfff1, 'Matterbridge', 'Matterbridge Cover', parseInt(this.version.replace(/\D/g, '')), this.version === '' ? 'Unknown' : this.version, parseInt(this.matterbridge.matterbridgeVersion.replace(/\D/g, '')), this.matterbridge.matterbridgeVersion)
387
+ .createDefaultBridgedDeviceBasicInformationClusterServer('Cover lift', 'CL01020564', 0xfff1, 'Matterbridge', 'Matterbridge Cover')
387
388
  .createDefaultWindowCoveringClusterServer()
388
389
  .createDefaultPowerSourceRechargeableBatteryClusterServer(86);
389
390
  this.coverLift = await this.addDevice(this.coverLift);
@@ -409,7 +410,7 @@ export class ExampleMatterbridgeDynamicPlatform extends MatterbridgeDynamicPlatf
409
410
  this.coverLiftTilt = new MatterbridgeEndpoint([coverDevice, bridgedNode, powerSource], { uniqueStorageKey: 'CoverLiftTilt' }, this.config.debug)
410
411
  .createDefaultIdentifyClusterServer()
411
412
  .createDefaultGroupsClusterServer()
412
- .createDefaultBridgedDeviceBasicInformationClusterServer('Cover lift and tilt', 'CLT01020554', 0xfff1, 'Matterbridge', 'Matterbridge Cover', parseInt(this.version.replace(/\D/g, '')), this.version === '' ? 'Unknown' : this.version, parseInt(this.matterbridge.matterbridgeVersion.replace(/\D/g, '')), this.matterbridge.matterbridgeVersion)
413
+ .createDefaultBridgedDeviceBasicInformationClusterServer('Cover lift and tilt', 'CLT01020554', 0xfff1, 'Matterbridge', 'Matterbridge Cover')
413
414
  .createDefaultLiftTiltWindowCoveringClusterServer()
414
415
  .createDefaultPowerSourceRechargeableBatteryClusterServer(86);
415
416
  this.coverLiftTilt = await this.addDevice(this.coverLiftTilt);
@@ -439,7 +440,7 @@ export class ExampleMatterbridgeDynamicPlatform extends MatterbridgeDynamicPlatf
439
440
  });
440
441
  this.lock = new MatterbridgeEndpoint([doorLockDevice, bridgedNode, powerSource], { uniqueStorageKey: 'Lock' }, this.config.debug)
441
442
  .createDefaultIdentifyClusterServer()
442
- .createDefaultBridgedDeviceBasicInformationClusterServer('Lock', '0x96352164', 0xfff1, 'Matterbridge', 'Matterbridge Lock', parseInt(this.version.replace(/\D/g, '')), this.version === '' ? 'Unknown' : this.version, parseInt(this.matterbridge.matterbridgeVersion.replace(/\D/g, '')), this.matterbridge.matterbridgeVersion)
443
+ .createDefaultBridgedDeviceBasicInformationClusterServer('Lock', '0x96352164', 0xfff1, 'Matterbridge', 'Matterbridge Lock')
443
444
  .createDefaultDoorLockClusterServer()
444
445
  .createDefaultPowerSourceRechargeableBatteryClusterServer(30);
445
446
  this.lock = await this.addDevice(this.lock);
@@ -457,7 +458,7 @@ export class ExampleMatterbridgeDynamicPlatform extends MatterbridgeDynamicPlatf
457
458
  this.thermoAuto = new MatterbridgeEndpoint([thermostatDevice, bridgedNode, powerSource], { uniqueStorageKey: 'Thermostat (AutoMode)' }, this.config.debug)
458
459
  .createDefaultIdentifyClusterServer()
459
460
  .createDefaultGroupsClusterServer()
460
- .createDefaultBridgedDeviceBasicInformationClusterServer('Thermostat (AutoMode)', '0x96382164A', 0xfff1, 'Matterbridge', 'Matterbridge Thermostat', parseInt(this.version.replace(/\D/g, '')), this.version === '' ? 'Unknown' : this.version, parseInt(this.matterbridge.matterbridgeVersion.replace(/\D/g, '')), this.matterbridge.matterbridgeVersion)
461
+ .createDefaultBridgedDeviceBasicInformationClusterServer('Thermostat (AutoMode)', '0x96382164A', 0xfff1, 'Matterbridge', 'Matterbridge Thermostat')
461
462
  .createDefaultThermostatClusterServer(20, 18, 22)
462
463
  .createDefaultPowerSourceRechargeableBatteryClusterServer(70, PowerSource.BatChargeLevel.Ok, 4700);
463
464
  this.thermoAuto
@@ -506,18 +507,24 @@ export class ExampleMatterbridgeDynamicPlatform extends MatterbridgeDynamicPlatf
506
507
  this.thermoHeat = new MatterbridgeEndpoint([thermostatDevice, bridgedNode, powerSource], { uniqueStorageKey: 'Thermostat (Heat)' }, this.config.debug)
507
508
  .createDefaultIdentifyClusterServer()
508
509
  .createDefaultGroupsClusterServer()
509
- .createDefaultBridgedDeviceBasicInformationClusterServer('Thermostat (Heat)', '0x96382164H', 0xfff1, 'Matterbridge', 'Matterbridge Thermostat', parseInt(this.version.replace(/\D/g, '')), this.version === '' ? 'Unknown' : this.version, parseInt(this.matterbridge.matterbridgeVersion.replace(/\D/g, '')), this.matterbridge.matterbridgeVersion)
510
+ .createDefaultBridgedDeviceBasicInformationClusterServer('Thermostat (Heat)', '0x96382164H', 0xfff1, 'Matterbridge', 'Matterbridge Thermostat')
510
511
  .createDefaultHeatingThermostatClusterServer(20, 18, 5, 35)
511
512
  .createDefaultPowerSourceReplaceableBatteryClusterServer(70, PowerSource.BatChargeLevel.Ok, 6010, 'AA 1.5V', 4);
512
513
  this.thermoHeat
513
514
  .addChildDeviceType('TemperatureIN', [temperatureSensor], {
514
- tagList: [{ mfgCode: null, namespaceId: LocationTag.Indoor.namespaceId, tag: LocationTag.Indoor.tag, label: null }],
515
+ tagList: [
516
+ { mfgCode: null, namespaceId: LocationTag.Indoor.namespaceId, tag: LocationTag.Indoor.tag, label: null },
517
+ { mfgCode: null, namespaceId: NumberTag.One.namespaceId, tag: NumberTag.One.tag, label: null },
518
+ ],
515
519
  })
516
520
  .createDefaultIdentifyClusterServer()
517
521
  .createDefaultTemperatureMeasurementClusterServer(21 * 100);
518
522
  this.thermoHeat
519
523
  .addChildDeviceType('TemperatureOUT', [temperatureSensor], {
520
- tagList: [{ mfgCode: null, namespaceId: LocationTag.Outdoor.namespaceId, tag: LocationTag.Outdoor.tag, label: null }],
524
+ tagList: [
525
+ { mfgCode: null, namespaceId: LocationTag.Outdoor.namespaceId, tag: LocationTag.Outdoor.tag, label: null },
526
+ { mfgCode: null, namespaceId: NumberTag.Two.namespaceId, tag: NumberTag.Two.tag, label: null },
527
+ ],
521
528
  })
522
529
  .createDefaultIdentifyClusterServer()
523
530
  .createDefaultTemperatureMeasurementClusterServer(15 * 100);
@@ -538,7 +545,7 @@ export class ExampleMatterbridgeDynamicPlatform extends MatterbridgeDynamicPlatf
538
545
  this.thermoCool = new MatterbridgeEndpoint([thermostatDevice, bridgedNode, powerSource], { uniqueStorageKey: 'Thermostat (Cool)' }, this.config.debug)
539
546
  .createDefaultIdentifyClusterServer()
540
547
  .createDefaultGroupsClusterServer()
541
- .createDefaultBridgedDeviceBasicInformationClusterServer('Thermostat (Cool)', '0x96382164C', 0xfff1, 'Matterbridge', 'Matterbridge Thermostat', parseInt(this.version.replace(/\D/g, '')), this.version === '' ? 'Unknown' : this.version, parseInt(this.matterbridge.matterbridgeVersion.replace(/\D/g, '')), this.matterbridge.matterbridgeVersion)
548
+ .createDefaultBridgedDeviceBasicInformationClusterServer('Thermostat (Cool)', '0x96382164C', 0xfff1, 'Matterbridge', 'Matterbridge Thermostat')
542
549
  .createDefaultCoolingThermostatClusterServer(20, 18, 5, 35)
543
550
  .createDefaultPowerSourceReplaceableBatteryClusterServer(40, PowerSource.BatChargeLevel.Ok, 5080, 'AA 1.5V', 4);
544
551
  this.thermoCool = await this.addDevice(this.thermoCool);
@@ -556,7 +563,7 @@ export class ExampleMatterbridgeDynamicPlatform extends MatterbridgeDynamicPlatf
556
563
  this.thermoCool?.log.info('Subscribe occupiedCoolingSetpoint called with:', value / 100);
557
564
  }, this.thermoCool.log);
558
565
  this.airPurifier = new MatterbridgeEndpoint([airPurifier, temperatureSensor, humiditySensor, bridgedNode, powerSource], { uniqueStorageKey: 'Air purifier' }, this.config.debug)
559
- .createDefaultBridgedDeviceBasicInformationClusterServer('Air purifier', '0x96584864AP', 0xfff1, 'Matterbridge', 'Matterbridge Air purifier', parseInt(this.version.replace(/\D/g, '')), this.version === '' ? 'Unknown' : this.version, parseInt(this.matterbridge.matterbridgeVersion.replace(/\D/g, '')), this.matterbridge.matterbridgeVersion)
566
+ .createDefaultBridgedDeviceBasicInformationClusterServer('Air purifier', '0x96584864AP', 0xfff1, 'Matterbridge', 'Matterbridge Air purifier')
560
567
  .createDefaultIdentifyClusterServer()
561
568
  .createDefaultFanControlClusterServer()
562
569
  .createDefaultTemperatureMeasurementClusterServer(20 * 100)
@@ -601,7 +608,7 @@ export class ExampleMatterbridgeDynamicPlatform extends MatterbridgeDynamicPlatf
601
608
  this.airPurifier?.setAttribute(FanControl.Cluster.id, 'percentCurrent', newValue, this.airPurifier?.log);
602
609
  }, this.airPurifier.log);
603
610
  this.airConditioner = new MatterbridgeEndpoint([airConditioner, bridgedNode, powerSource], { uniqueStorageKey: 'Air Conditioner' }, this.config.debug)
604
- .createDefaultBridgedDeviceBasicInformationClusterServer('Air Conditioner', '0x96382864AC', 0xfff1, 'Matterbridge', 'Matterbridge Air Conditioner', parseInt(this.version.replace(/\D/g, '')), this.version === '' ? 'Unknown' : this.version, parseInt(this.matterbridge.matterbridgeVersion.replace(/\D/g, '')), this.matterbridge.matterbridgeVersion)
611
+ .createDefaultBridgedDeviceBasicInformationClusterServer('Air Conditioner', '0x96382864AC', 0xfff1, 'Matterbridge', 'Matterbridge Air Conditioner')
605
612
  .createDefaultIdentifyClusterServer()
606
613
  .createDeadFrontOnOffClusterServer(true)
607
614
  .createDefaultThermostatClusterServer(20, 18, 22)
@@ -630,7 +637,7 @@ export class ExampleMatterbridgeDynamicPlatform extends MatterbridgeDynamicPlatf
630
637
  await this.airConditioner?.setAttribute(FanControl.Cluster.id, 'percentSetting', null, this.airConditioner?.log);
631
638
  });
632
639
  this.pump = new MatterbridgeEndpoint([pumpDevice, bridgedNode, powerSource], { uniqueStorageKey: 'Pump' }, this.config.debug)
633
- .createDefaultBridgedDeviceBasicInformationClusterServer('Pump', '0x96382864PUMP', 0xfff1, 'Matterbridge', 'Matterbridge Pump', parseInt(this.version.replace(/\D/g, '')), this.version === '' ? 'Unknown' : this.version, parseInt(this.matterbridge.matterbridgeVersion.replace(/\D/g, '')), this.matterbridge.matterbridgeVersion)
640
+ .createDefaultBridgedDeviceBasicInformationClusterServer('Pump', '0x96382864PUMP', 0xfff1, 'Matterbridge', 'Matterbridge Pump')
634
641
  .createDefaultIdentifyClusterServer()
635
642
  .createOnOffClusterServer()
636
643
  .createLevelControlClusterServer()
@@ -653,7 +660,7 @@ export class ExampleMatterbridgeDynamicPlatform extends MatterbridgeDynamicPlatf
653
660
  this.pump?.log.info(`Command moveToLevelWithOnOff called request: ${level}`);
654
661
  });
655
662
  this.valve = new MatterbridgeEndpoint([waterValve, bridgedNode, powerSource], { uniqueStorageKey: 'Water valve' }, this.config.debug)
656
- .createDefaultBridgedDeviceBasicInformationClusterServer('Water valve', '0x96382864WV', 0xfff1, 'Matterbridge', 'Matterbridge Water valve', parseInt(this.version.replace(/\D/g, '')), this.version === '' ? 'Unknown' : this.version, parseInt(this.matterbridge.matterbridgeVersion.replace(/\D/g, '')), this.matterbridge.matterbridgeVersion)
663
+ .createDefaultBridgedDeviceBasicInformationClusterServer('Water valve', '0x96382864WV', 0xfff1, 'Matterbridge', 'Matterbridge Water valve')
657
664
  .createDefaultIdentifyClusterServer()
658
665
  .createDefaultValveConfigurationAndControlClusterServer()
659
666
  .createDefaultPowerSourceWiredClusterServer();
@@ -661,91 +668,121 @@ export class ExampleMatterbridgeDynamicPlatform extends MatterbridgeDynamicPlatf
661
668
  this.valve?.addCommandHandler('identify', async ({ request: { identifyTime } }) => {
662
669
  this.valve?.log.info(`Command identify called identifyTime:${identifyTime}`);
663
670
  });
664
- this.fan = new MatterbridgeEndpoint([fanDevice, bridgedNode, powerSource], { uniqueStorageKey: 'Fan off low medium high' }, this.config.debug)
665
- .createDefaultBridgedDeviceBasicInformationClusterServer('Fan', 'FNB_980545631228', 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)
671
+ this.fanDefault = new MatterbridgeEndpoint([fanDevice, bridgedNode, powerSource], { uniqueStorageKey: 'Fan off low medium high auto' }, this.config.debug)
672
+ .createDefaultBridgedDeviceBasicInformationClusterServer('Fan', 'FAN_980545631228', 0xfff1, 'Matterbridge', 'Matterbridge Fan')
666
673
  .createDefaultPowerSourceWiredClusterServer()
667
- .createBaseFanControlClusterServer()
668
674
  .addRequiredClusterServers();
669
- this.fan = await this.addDevice(this.fan);
670
- await this.fan?.subscribeAttribute(FanControl.Cluster.id, 'fanMode', (newValue, oldValue, context) => {
671
- this.fan?.log.info(`Fan mode changed from ${this.fanModeLookup[oldValue]} to ${this.fanModeLookup[newValue]} context: ${context.offline === true ? 'offline' : 'online'}`);
675
+ this.fanDefault = await this.addDevice(this.fanDefault);
676
+ await this.fanDefault?.subscribeAttribute(FanControl.Cluster.id, 'fanMode', (newValue, oldValue, context) => {
677
+ this.fanDefault?.log.info(`Fan mode changed from ${this.fanModeLookup[oldValue]} to ${this.fanModeLookup[newValue]} context: ${context.offline === true ? 'offline' : 'online'}`);
672
678
  if (context.offline === true)
673
679
  return;
674
680
  if (newValue === FanControl.FanMode.Off) {
675
- this.fan?.setAttribute(FanControl.Cluster.id, 'percentSetting', 0, this.fan?.log);
676
- this.fan?.setAttribute(FanControl.Cluster.id, 'percentCurrent', 0, this.fan?.log);
681
+ this.fanDefault?.setAttribute(FanControl.Cluster.id, 'percentSetting', 0, this.fanDefault?.log);
682
+ this.fanDefault?.setAttribute(FanControl.Cluster.id, 'percentCurrent', 0, this.fanDefault?.log);
677
683
  }
678
684
  else if (newValue === FanControl.FanMode.Low) {
679
- this.fan?.setAttribute(FanControl.Cluster.id, 'percentSetting', 33, this.fan?.log);
680
- this.fan?.setAttribute(FanControl.Cluster.id, 'percentCurrent', 33, this.fan?.log);
685
+ this.fanDefault?.setAttribute(FanControl.Cluster.id, 'percentSetting', 33, this.fanDefault?.log);
686
+ this.fanDefault?.setAttribute(FanControl.Cluster.id, 'percentCurrent', 33, this.fanDefault?.log);
681
687
  }
682
688
  else if (newValue === FanControl.FanMode.Medium) {
683
- this.fan?.setAttribute(FanControl.Cluster.id, 'percentSetting', 66, this.fan?.log);
684
- this.fan?.setAttribute(FanControl.Cluster.id, 'percentCurrent', 66, this.fan?.log);
689
+ this.fanDefault?.setAttribute(FanControl.Cluster.id, 'percentSetting', 66, this.fanDefault?.log);
690
+ this.fanDefault?.setAttribute(FanControl.Cluster.id, 'percentCurrent', 66, this.fanDefault?.log);
685
691
  }
686
692
  else if (newValue === FanControl.FanMode.High) {
687
- this.fan?.setAttribute(FanControl.Cluster.id, 'percentSetting', 100, this.fan?.log);
688
- this.fan?.setAttribute(FanControl.Cluster.id, 'percentCurrent', 100, this.fan?.log);
693
+ this.fanDefault?.setAttribute(FanControl.Cluster.id, 'percentSetting', 100, this.fanDefault?.log);
694
+ this.fanDefault?.setAttribute(FanControl.Cluster.id, 'percentCurrent', 100, this.fanDefault?.log);
689
695
  }
690
696
  else if (newValue === FanControl.FanMode.On) {
691
- this.fan?.setAttribute(FanControl.Cluster.id, 'percentSetting', 100, this.fan?.log);
692
- this.fan?.setAttribute(FanControl.Cluster.id, 'percentCurrent', 100, this.fan?.log);
697
+ this.fanDefault?.setAttribute(FanControl.Cluster.id, 'percentSetting', 100, this.fanDefault?.log);
698
+ this.fanDefault?.setAttribute(FanControl.Cluster.id, 'percentCurrent', 100, this.fanDefault?.log);
693
699
  }
694
700
  else if (newValue === FanControl.FanMode.Auto) {
695
- this.fan?.setAttribute(FanControl.Cluster.id, 'percentSetting', 50, this.fan?.log);
696
- this.fan?.setAttribute(FanControl.Cluster.id, 'percentCurrent', 50, this.fan?.log);
701
+ this.fanDefault?.setAttribute(FanControl.Cluster.id, 'percentSetting', 50, this.fanDefault?.log);
702
+ this.fanDefault?.setAttribute(FanControl.Cluster.id, 'percentCurrent', 50, this.fanDefault?.log);
697
703
  }
698
- }, this.fan.log);
699
- await this.fan?.subscribeAttribute(FanControl.Cluster.id, 'percentSetting', (newValue, oldValue, context) => {
700
- this.fan?.log.info(`Percent setting changed from ${oldValue} to ${newValue} context: ${context.offline === true ? 'offline' : 'online'}`);
704
+ }, this.fanDefault.log);
705
+ await this.fanDefault?.subscribeAttribute(FanControl.Cluster.id, 'percentSetting', (newValue, oldValue, context) => {
706
+ this.fanDefault?.log.info(`Percent setting changed from ${oldValue} to ${newValue} context: ${context.offline === true ? 'offline' : 'online'}`);
701
707
  if (context.offline === true)
702
708
  return;
703
709
  if (isValidNumber(newValue, 0, 100))
704
- this.fan?.setAttribute(FanControl.Cluster.id, 'percentCurrent', newValue, this.fan?.log);
705
- }, this.fan.log);
706
- this.fanauto = new MatterbridgeEndpoint([fanDevice, bridgedNode, powerSource], { uniqueStorageKey: 'Fan off low medium high auto' }, this.config.debug)
707
- .createDefaultBridgedDeviceBasicInformationClusterServer('Fan auto', 'FNA_980545631228', 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)
710
+ this.fanDefault?.setAttribute(FanControl.Cluster.id, 'percentCurrent', newValue, this.fanDefault?.log);
711
+ }, this.fanDefault.log);
712
+ this.fanBase = new MatterbridgeEndpoint([fanDevice, bridgedNode, powerSource], { uniqueStorageKey: 'Fan off low medium high' }, this.config.debug)
713
+ .createDefaultBridgedDeviceBasicInformationClusterServer('Fan base', 'FANB_980545631228', 0xfff1, 'Matterbridge', 'Matterbridge Fan')
708
714
  .createDefaultPowerSourceWiredClusterServer()
715
+ .createBaseFanControlClusterServer()
709
716
  .addRequiredClusterServers();
710
- this.fanauto = await this.addDevice(this.fanauto);
711
- await this.fanauto?.subscribeAttribute(FanControl.Cluster.id, 'fanMode', (newValue, oldValue, context) => {
712
- this.fanauto?.log.info(`Fan mode changed from ${this.fanModeLookup[oldValue]} to ${this.fanModeLookup[newValue]} context: ${context.offline === true ? 'offline' : 'online'}`);
717
+ this.fanBase = await this.addDevice(this.fanBase);
718
+ await this.fanBase?.subscribeAttribute(FanControl.Cluster.id, 'fanMode', (newValue, oldValue, context) => {
719
+ this.fanBase?.log.info(`Fan mode changed from ${this.fanModeLookup[oldValue]} to ${this.fanModeLookup[newValue]} context: ${context.offline === true ? 'offline' : 'online'}`);
713
720
  if (context.offline === true)
714
721
  return;
715
722
  if (newValue === FanControl.FanMode.Off) {
716
- this.fanauto?.setAttribute(FanControl.Cluster.id, 'percentSetting', 0, this.fanauto?.log);
717
- this.fanauto?.setAttribute(FanControl.Cluster.id, 'percentCurrent', 0, this.fanauto?.log);
723
+ this.fanBase?.setAttribute(FanControl.Cluster.id, 'percentSetting', 0, this.fanBase?.log);
724
+ this.fanBase?.setAttribute(FanControl.Cluster.id, 'percentCurrent', 0, this.fanBase?.log);
718
725
  }
719
726
  else if (newValue === FanControl.FanMode.Low) {
720
- this.fanauto?.setAttribute(FanControl.Cluster.id, 'percentSetting', 33, this.fanauto?.log);
721
- this.fanauto?.setAttribute(FanControl.Cluster.id, 'percentCurrent', 33, this.fanauto?.log);
727
+ this.fanBase?.setAttribute(FanControl.Cluster.id, 'percentSetting', 33, this.fanBase?.log);
728
+ this.fanBase?.setAttribute(FanControl.Cluster.id, 'percentCurrent', 33, this.fanBase?.log);
722
729
  }
723
730
  else if (newValue === FanControl.FanMode.Medium) {
724
- this.fanauto?.setAttribute(FanControl.Cluster.id, 'percentSetting', 66, this.fanauto?.log);
725
- this.fanauto?.setAttribute(FanControl.Cluster.id, 'percentCurrent', 66, this.fanauto?.log);
731
+ this.fanBase?.setAttribute(FanControl.Cluster.id, 'percentSetting', 66, this.fanBase?.log);
732
+ this.fanBase?.setAttribute(FanControl.Cluster.id, 'percentCurrent', 66, this.fanBase?.log);
726
733
  }
727
734
  else if (newValue === FanControl.FanMode.High) {
728
- this.fanauto?.setAttribute(FanControl.Cluster.id, 'percentSetting', 100, this.fanauto?.log);
729
- this.fanauto?.setAttribute(FanControl.Cluster.id, 'percentCurrent', 100, this.fanauto?.log);
735
+ this.fanBase?.setAttribute(FanControl.Cluster.id, 'percentSetting', 100, this.fanBase?.log);
736
+ this.fanBase?.setAttribute(FanControl.Cluster.id, 'percentCurrent', 100, this.fanBase?.log);
730
737
  }
731
738
  else if (newValue === FanControl.FanMode.On) {
732
- this.fanauto?.setAttribute(FanControl.Cluster.id, 'percentSetting', 100, this.fanauto?.log);
733
- this.fanauto?.setAttribute(FanControl.Cluster.id, 'percentCurrent', 100, this.fanauto?.log);
739
+ this.fanBase?.setAttribute(FanControl.Cluster.id, 'percentSetting', 100, this.fanBase?.log);
740
+ this.fanBase?.setAttribute(FanControl.Cluster.id, 'percentCurrent', 100, this.fanBase?.log);
734
741
  }
735
742
  else if (newValue === FanControl.FanMode.Auto) {
736
- this.fanauto?.setAttribute(FanControl.Cluster.id, 'percentSetting', 50, this.fanauto?.log);
737
- this.fanauto?.setAttribute(FanControl.Cluster.id, 'percentCurrent', 50, this.fanauto?.log);
743
+ this.fanBase?.setAttribute(FanControl.Cluster.id, 'percentSetting', 50, this.fanBase?.log);
744
+ this.fanBase?.setAttribute(FanControl.Cluster.id, 'percentCurrent', 50, this.fanBase?.log);
738
745
  }
739
- }, this.fanauto.log);
740
- await this.fanauto?.subscribeAttribute(FanControl.Cluster.id, 'percentSetting', (newValue, oldValue, context) => {
741
- this.fanauto?.log.info(`Percent setting changed from ${oldValue} to ${newValue} context: ${context.offline === true ? 'offline' : 'online'}`);
746
+ }, this.fanBase.log);
747
+ await this.fanBase?.subscribeAttribute(FanControl.Cluster.id, 'percentSetting', (newValue, oldValue, context) => {
748
+ this.fanBase?.log.info(`Percent setting changed from ${oldValue} to ${newValue} context: ${context.offline === true ? 'offline' : 'online'}`);
742
749
  if (context.offline === true)
743
750
  return;
744
751
  if (isValidNumber(newValue, 0, 100))
745
- this.fanauto?.setAttribute(FanControl.Cluster.id, 'percentCurrent', newValue, this.fanauto?.log);
746
- }, this.fanauto.log);
752
+ this.fanBase?.setAttribute(FanControl.Cluster.id, 'percentCurrent', newValue, this.fanBase?.log);
753
+ }, this.fanBase.log);
754
+ this.fanOnHigh = new MatterbridgeEndpoint([fanDevice, bridgedNode, powerSource], { uniqueStorageKey: 'Fan off high' }, this.config.debug)
755
+ .createDefaultBridgedDeviceBasicInformationClusterServer('Fan off high', 'FANOH_980545631228', 0xfff1, 'Matterbridge', 'Matterbridge Fan')
756
+ .createDefaultPowerSourceWiredClusterServer()
757
+ .createOnOffFanControlClusterServer()
758
+ .addRequiredClusterServers();
759
+ this.fanOnHigh = await this.addDevice(this.fanOnHigh);
760
+ await this.fanOnHigh?.subscribeAttribute(FanControl.Cluster.id, 'fanMode', (newValue, oldValue, context) => {
761
+ this.fanOnHigh?.log.info(`Fan mode changed from ${this.fanModeLookup[oldValue]} to ${this.fanModeLookup[newValue]} context: ${context.offline === true ? 'offline' : 'online'}`);
762
+ if (context.offline === true)
763
+ return;
764
+ if (newValue === FanControl.FanMode.Off) {
765
+ this.fanOnHigh?.setAttribute(FanControl.Cluster.id, 'percentSetting', 0, this.fanOnHigh?.log);
766
+ this.fanOnHigh?.setAttribute(FanControl.Cluster.id, 'percentCurrent', 0, this.fanOnHigh?.log);
767
+ }
768
+ else if (newValue === FanControl.FanMode.High) {
769
+ this.fanOnHigh?.setAttribute(FanControl.Cluster.id, 'percentSetting', 100, this.fanOnHigh?.log);
770
+ this.fanOnHigh?.setAttribute(FanControl.Cluster.id, 'percentCurrent', 100, this.fanOnHigh?.log);
771
+ }
772
+ }, this.fanOnHigh.log);
773
+ await this.fanOnHigh?.subscribeAttribute(FanControl.Cluster.id, 'percentSetting', (newValue, oldValue, context) => {
774
+ this.fanOnHigh?.log.info(`Percent setting changed from ${oldValue} to ${newValue} context: ${context.offline === true ? 'offline' : 'online'}`);
775
+ if (context.offline === true)
776
+ return;
777
+ if (isValidNumber(newValue, 0, 100)) {
778
+ if (newValue > 0)
779
+ newValue = 100;
780
+ this.fanOnHigh?.setAttribute(FanControl.Cluster.id, 'percentCurrent', newValue, this.fanOnHigh?.log);
781
+ this.fanOnHigh?.setAttribute(FanControl.Cluster.id, 'percentSetting', newValue, this.fanOnHigh?.log);
782
+ }
783
+ }, this.fanOnHigh.log);
747
784
  this.fanComplete = new MatterbridgeEndpoint([fanDevice, bridgedNode, powerSource], { uniqueStorageKey: 'Fan complete' }, this.config.debug)
748
- .createDefaultBridgedDeviceBasicInformationClusterServer('Fan complete', 'FNC_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)
785
+ .createDefaultBridgedDeviceBasicInformationClusterServer('Fan complete', 'FANC_980995631228', 0xfff1, 'Matterbridge', 'Matterbridge Fan')
749
786
  .createDefaultPowerSourceWiredClusterServer()
750
787
  .createCompleteFanControlClusterServer()
751
788
  .addRequiredClusterServers();
@@ -796,48 +833,48 @@ export class ExampleMatterbridgeDynamicPlatform extends MatterbridgeDynamicPlatf
796
833
  this.fanComplete?.log.info(`Airflow direction changed from ${this.fanDirectionLookup[oldValue]} to ${this.fanDirectionLookup[newValue]} context: ${context.offline === true ? 'offline' : 'online'}`);
797
834
  }, this.fanComplete?.log);
798
835
  this.waterLeak = new MatterbridgeEndpoint([waterLeakDetector, bridgedNode, powerSource], { uniqueStorageKey: 'Water leak detector' }, this.config.debug)
799
- .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)
836
+ .createDefaultBridgedDeviceBasicInformationClusterServer('Water leak detector', 'serial_98745631222', 0xfff1, 'Matterbridge', 'Matterbridge WaterLeakDetector')
800
837
  .createDefaultPowerSourceRechargeableBatteryClusterServer()
801
838
  .createDefaultBooleanStateClusterServer(false)
802
839
  .addRequiredClusterServers()
803
840
  .addOptionalClusterServers();
804
841
  this.waterLeak = await this.addDevice(this.waterLeak);
805
842
  this.waterFreeze = new MatterbridgeEndpoint([waterFreezeDetector, bridgedNode, powerSource], { uniqueStorageKey: 'Water freeze detector' }, this.config.debug)
806
- .createDefaultBridgedDeviceBasicInformationClusterServer('Water freeze detector', 'serial_98745631223', 0xfff1, 'Matterbridge', 'Matterbridge WaterFreezeDetector', parseInt(this.version.replace(/\D/g, '')), this.version === '' ? 'Unknown' : this.version, parseInt(this.matterbridge.matterbridgeVersion.replace(/\D/g, '')), this.matterbridge.matterbridgeVersion)
843
+ .createDefaultBridgedDeviceBasicInformationClusterServer('Water freeze detector', 'serial_98745631223', 0xfff1, 'Matterbridge', 'Matterbridge WaterFreezeDetector')
807
844
  .createDefaultPowerSourceRechargeableBatteryClusterServer()
808
845
  .createDefaultBooleanStateClusterServer(false)
809
846
  .addRequiredClusterServers()
810
847
  .addOptionalClusterServers();
811
848
  this.waterFreeze = await this.addDevice(this.waterFreeze);
812
849
  this.rain = new MatterbridgeEndpoint([rainSensor, bridgedNode, powerSource], { uniqueStorageKey: 'Rain sensor' }, this.config.debug)
813
- .createDefaultBridgedDeviceBasicInformationClusterServer('Rain sensor', 'serial_98745631224', 0xfff1, 'Matterbridge', 'Matterbridge RainSensor', parseInt(this.version.replace(/\D/g, '')), this.version === '' ? 'Unknown' : this.version, parseInt(this.matterbridge.matterbridgeVersion.replace(/\D/g, '')), this.matterbridge.matterbridgeVersion)
850
+ .createDefaultBridgedDeviceBasicInformationClusterServer('Rain sensor', 'serial_98745631224', 0xfff1, 'Matterbridge', 'Matterbridge RainSensor')
814
851
  .createDefaultPowerSourceRechargeableBatteryClusterServer()
815
852
  .createDefaultIdentifyClusterServer()
816
853
  .createDefaultBooleanStateClusterServer(false)
817
854
  .createDefaultBooleanStateConfigurationClusterServer();
818
855
  this.rain = await this.addDevice(this.rain);
819
856
  this.smokeCo = new MatterbridgeEndpoint([smokeCoAlarm, bridgedNode, powerSource], { uniqueStorageKey: 'SmokeCo alarm sensor' }, this.config.debug)
820
- .createDefaultBridgedDeviceBasicInformationClusterServer('SmokeCo alarm sensor', 'serial_94745631225', 0xfff1, 'Matterbridge', 'Matterbridge SmokeCoAlarm', parseInt(this.version.replace(/\D/g, '')), this.version === '' ? 'Unknown' : this.version, parseInt(this.matterbridge.matterbridgeVersion.replace(/\D/g, '')), this.matterbridge.matterbridgeVersion)
857
+ .createDefaultBridgedDeviceBasicInformationClusterServer('SmokeCo alarm sensor', 'serial_94745631225', 0xfff1, 'Matterbridge', 'Matterbridge SmokeCoAlarm')
821
858
  .createDefaultIdentifyClusterServer()
822
859
  .createDefaultSmokeCOAlarmClusterServer(SmokeCoAlarm.AlarmState.Normal, SmokeCoAlarm.AlarmState.Normal)
823
860
  .createDefaultPowerSourceReplaceableBatteryClusterServer()
824
861
  .createDefaultCarbonMonoxideConcentrationMeasurementClusterServer(100);
825
862
  this.smokeCo = await this.addDevice(this.smokeCo);
826
863
  this.smokeOnly = new MatterbridgeEndpoint([smokeCoAlarm, bridgedNode, powerSource], { uniqueStorageKey: 'Smoke alarm sensor' }, this.config.debug)
827
- .createDefaultBridgedDeviceBasicInformationClusterServer('Smoke alarm sensor', 'serial_94755661225', 0xfff1, 'Matterbridge', 'Matterbridge SmokeCoAlarm', parseInt(this.version.replace(/\D/g, '')), this.version === '' ? 'Unknown' : this.version, parseInt(this.matterbridge.matterbridgeVersion.replace(/\D/g, '')), this.matterbridge.matterbridgeVersion)
864
+ .createDefaultBridgedDeviceBasicInformationClusterServer('Smoke alarm sensor', 'serial_94755661225', 0xfff1, 'Matterbridge', 'Matterbridge SmokeCoAlarm')
828
865
  .createDefaultIdentifyClusterServer()
829
866
  .createSmokeOnlySmokeCOAlarmClusterServer(SmokeCoAlarm.AlarmState.Normal)
830
867
  .createDefaultPowerSourceReplaceableBatteryClusterServer();
831
868
  this.smokeOnly = await this.addDevice(this.smokeOnly);
832
869
  this.coOnly = new MatterbridgeEndpoint([smokeCoAlarm, bridgedNode, powerSource], { uniqueStorageKey: 'Co alarm sensor' }, this.config.debug)
833
- .createDefaultBridgedDeviceBasicInformationClusterServer('Co alarm sensor', 'serial_947456317488', 0xfff1, 'Matterbridge', 'Matterbridge SmokeCoAlarm', parseInt(this.version.replace(/\D/g, '')), this.version === '' ? 'Unknown' : this.version, parseInt(this.matterbridge.matterbridgeVersion.replace(/\D/g, '')), this.matterbridge.matterbridgeVersion)
870
+ .createDefaultBridgedDeviceBasicInformationClusterServer('Co alarm sensor', 'serial_947456317488', 0xfff1, 'Matterbridge', 'Matterbridge SmokeCoAlarm')
834
871
  .createDefaultIdentifyClusterServer()
835
872
  .createCoOnlySmokeCOAlarmClusterServer(SmokeCoAlarm.AlarmState.Normal)
836
873
  .createDefaultPowerSourceReplaceableBatteryClusterServer()
837
874
  .createDefaultCarbonMonoxideConcentrationMeasurementClusterServer(100);
838
875
  this.coOnly = await this.addDevice(this.coOnly);
839
876
  this.airQuality = new MatterbridgeEndpoint([airQualitySensor, bridgedNode, powerSource], { uniqueStorageKey: 'Air quality sensor' }, this.config.debug)
840
- .createDefaultBridgedDeviceBasicInformationClusterServer('Air quality sensor', 'serial_987484318322', 0xfff1, 'Matterbridge', 'Matterbridge Air Quality Sensor', parseInt(this.version.replace(/\D/g, '')), this.version === '' ? 'Unknown' : this.version, parseInt(this.matterbridge.matterbridgeVersion.replace(/\D/g, '')), this.matterbridge.matterbridgeVersion)
877
+ .createDefaultBridgedDeviceBasicInformationClusterServer('Air quality sensor', 'serial_987484318322', 0xfff1, 'Matterbridge', 'Matterbridge Air Quality Sensor')
841
878
  .createDefaultPowerSourceReplaceableBatteryClusterServer(50, PowerSource.BatChargeLevel.Warning, 2900, 'CR2450', 1)
842
879
  .addRequiredClusterServers()
843
880
  .addClusterServers([TemperatureMeasurement.Cluster.id, RelativeHumidityMeasurement.Cluster.id])
@@ -853,7 +890,7 @@ export class ExampleMatterbridgeDynamicPlatform extends MatterbridgeDynamicPlatf
853
890
  .createDefaultTvocMeasurementClusterServer(100);
854
891
  this.airQuality = await this.addDevice(this.airQuality);
855
892
  this.momentarySwitch = new MatterbridgeEndpoint([bridgedNode, powerSource], { uniqueStorageKey: 'Momentary switch composed' }, this.config.debug)
856
- .createDefaultBridgedDeviceBasicInformationClusterServer('Momentary switch (Top-1 Middle-2 Bottom-3)', 'serial_947942331225', 0xfff1, 'Matterbridge', 'Matterbridge MomentarySwitch', parseInt(this.version.replace(/\D/g, '')), this.version === '' ? 'Unknown' : this.version, parseInt(this.matterbridge.matterbridgeVersion.replace(/\D/g, '')), this.matterbridge.matterbridgeVersion)
893
+ .createDefaultBridgedDeviceBasicInformationClusterServer('Momentary switch (Top-1 Middle-2 Bottom-3)', 'serial_947942331225', 0xfff1, 'Matterbridge', 'Matterbridge MomentarySwitch')
857
894
  .createDefaultIdentifyClusterServer()
858
895
  .createDefaultPowerSourceReplaceableBatteryClusterServer(50, PowerSource.BatChargeLevel.Ok, 2900, 'CR2450', 1);
859
896
  this.momentarySwitch
@@ -883,9 +920,59 @@ export class ExampleMatterbridgeDynamicPlatform extends MatterbridgeDynamicPlatf
883
920
  })
884
921
  .createDefaultIdentifyClusterServer()
885
922
  .createDefaultSwitchClusterServer();
923
+ const switch4 = this.momentarySwitch
924
+ .addChildDeviceType('Momentary switch 4', [genericSwitch], {
925
+ tagList: [
926
+ { mfgCode: null, namespaceId: NumberTag.Four.namespaceId, tag: NumberTag.Four.tag, label: null },
927
+ { mfgCode: null, namespaceId: PositionTag.Bottom.namespaceId, tag: PositionTag.Bottom.tag, label: null },
928
+ { mfgCode: null, namespaceId: SwitchesTag.Custom.namespaceId, tag: SwitchesTag.Custom.tag, label: 'Turn on' },
929
+ { mfgCode: null, namespaceId: LocationTag.Indoor.namespaceId, tag: LocationTag.Indoor.tag, label: null },
930
+ { mfgCode: null, namespaceId: AreaNamespaceTag.Bedroom.namespaceId, tag: AreaNamespaceTag.Bedroom.tag, label: null },
931
+ ],
932
+ })
933
+ .createDefaultIdentifyClusterServer()
934
+ .createDefaultMomentarySwitchClusterServer();
935
+ const switch5 = this.momentarySwitch
936
+ .addChildDeviceType('Momentary switch 5', [genericSwitch], {
937
+ tagList: [
938
+ { mfgCode: null, namespaceId: NumberTag.Five.namespaceId, tag: NumberTag.Five.tag, label: null },
939
+ { mfgCode: null, namespaceId: PositionTag.Middle.namespaceId, tag: PositionTag.Middle.tag, label: null },
940
+ { mfgCode: null, namespaceId: SwitchesTag.Custom.namespaceId, tag: SwitchesTag.Custom.tag, label: 'Turn off' },
941
+ { mfgCode: null, namespaceId: LocationTag.Indoor.namespaceId, tag: LocationTag.Indoor.tag, label: null },
942
+ { mfgCode: null, namespaceId: AreaNamespaceTag.Bedroom.namespaceId, tag: AreaNamespaceTag.Bedroom.tag, label: null },
943
+ ],
944
+ })
945
+ .createDefaultIdentifyClusterServer()
946
+ .createDefaultMomentarySwitchClusterServer();
947
+ const switch6 = this.momentarySwitch
948
+ .addChildDeviceType('Momentary switch 6', [genericSwitch], {
949
+ tagList: [
950
+ { mfgCode: null, namespaceId: NumberTag.Seven.namespaceId, tag: NumberTag.Seven.tag, label: null },
951
+ { mfgCode: null, namespaceId: PositionTag.Bottom.namespaceId, tag: PositionTag.Bottom.tag, label: null },
952
+ { mfgCode: null, namespaceId: SwitchesTag.Custom.namespaceId, tag: SwitchesTag.Custom.tag, label: 'Toggle' },
953
+ { mfgCode: null, namespaceId: LocationTag.Indoor.namespaceId, tag: LocationTag.Indoor.tag, label: null },
954
+ { mfgCode: null, namespaceId: AreaNamespaceTag.Bedroom.namespaceId, tag: AreaNamespaceTag.Bedroom.tag, label: null },
955
+ ],
956
+ })
957
+ .createDefaultIdentifyClusterServer()
958
+ .createDefaultMomentarySwitchClusterServer();
886
959
  this.momentarySwitch = await this.addDevice(this.momentarySwitch);
960
+ if (this.momentarySwitch) {
961
+ await switch4.addFixedLabel('name', 'Switch 4');
962
+ await switch4.addFixedLabel('room', 'Living Room');
963
+ await switch4.addFixedLabel('switch', 'Switch 4');
964
+ await switch4.addFixedLabel('button', 'Button 4');
965
+ await switch5.addFixedLabel('name', 'Switch 5');
966
+ await switch5.addFixedLabel('room', 'Living Room');
967
+ await switch5.addFixedLabel('switch', 'Switch 5');
968
+ await switch5.addFixedLabel('button', 'Button 5');
969
+ await switch6.addFixedLabel('name', 'Switch 6');
970
+ await switch6.addFixedLabel('room', 'Living Room');
971
+ await switch6.addFixedLabel('switch', 'Switch 6');
972
+ await switch6.addFixedLabel('button', 'Button 6');
973
+ }
887
974
  this.latchingSwitch = new MatterbridgeEndpoint([genericSwitch, bridgedNode, powerSource], { uniqueStorageKey: 'Latching switch' }, this.config.debug)
888
- .createDefaultBridgedDeviceBasicInformationClusterServer('Latching switch', 'serial_947442331225', 0xfff1, 'Matterbridge', 'Matterbridge LatchingSwitch', parseInt(this.version.replace(/\D/g, '')), this.version === '' ? 'Unknown' : this.version, parseInt(this.matterbridge.matterbridgeVersion.replace(/\D/g, '')), this.matterbridge.matterbridgeVersion)
975
+ .createDefaultBridgedDeviceBasicInformationClusterServer('Latching switch', 'serial_947442331225', 0xfff1, 'Matterbridge', 'Matterbridge LatchingSwitch')
889
976
  .createDefaultIdentifyClusterServer()
890
977
  .createDefaultLatchingSwitchClusterServer()
891
978
  .createDefaultPowerSourceReplaceableBatteryClusterServer(10, PowerSource.BatChargeLevel.Critical, 2850, 'CR2032', 1);
@@ -1150,27 +1237,27 @@ export class ExampleMatterbridgeDynamicPlatform extends MatterbridgeDynamicPlatf
1150
1237
  }
1151
1238
  }, 60 * 1000 + 550);
1152
1239
  }
1153
- this.fan?.log.info('Set fan initial fanMode to Off, percentCurrent and percentSetting to 0');
1154
- await this.fan?.setAttribute(FanControl.Cluster.id, 'fanMode', FanControl.FanMode.Off, this.fan.log);
1155
- await this.fan?.setAttribute(FanControl.Cluster.id, 'percentCurrent', 0, this.fan.log);
1156
- await this.fan?.setAttribute(FanControl.Cluster.id, 'percentSetting', 0, this.fan.log);
1157
- await this.fanauto?.setAttribute(FanControl.Cluster.id, 'fanMode', FanControl.FanMode.Auto, this.fanauto.log);
1158
- await this.fanauto?.setAttribute(FanControl.Cluster.id, 'percentCurrent', 0, this.fanauto.log);
1159
- await this.fanauto?.setAttribute(FanControl.Cluster.id, 'percentSetting', 0, this.fanauto.log);
1240
+ this.fanBase?.log.info('Set fan initial fanMode to Off, percentCurrent and percentSetting to 0');
1241
+ await this.fanBase?.setAttribute(FanControl.Cluster.id, 'fanMode', FanControl.FanMode.Off, this.fanBase.log);
1242
+ await this.fanBase?.setAttribute(FanControl.Cluster.id, 'percentCurrent', 0, this.fanBase.log);
1243
+ await this.fanBase?.setAttribute(FanControl.Cluster.id, 'percentSetting', 0, this.fanBase.log);
1244
+ await this.fanDefault?.setAttribute(FanControl.Cluster.id, 'fanMode', FanControl.FanMode.Auto, this.fanDefault.log);
1245
+ await this.fanDefault?.setAttribute(FanControl.Cluster.id, 'percentCurrent', 0, this.fanDefault.log);
1246
+ await this.fanDefault?.setAttribute(FanControl.Cluster.id, 'percentSetting', 0, this.fanDefault.log);
1160
1247
  await this.fanComplete?.setAttribute(FanControl.Cluster.id, 'fanMode', FanControl.FanMode.Auto, this.fanComplete.log);
1161
1248
  await this.fanComplete?.setAttribute(FanControl.Cluster.id, 'percentCurrent', 0, this.fanComplete.log);
1162
1249
  await this.fanComplete?.setAttribute(FanControl.Cluster.id, 'percentSetting', 0, this.fanComplete.log);
1163
1250
  if (this.config.useInterval) {
1164
1251
  this.fanInterval = setInterval(async () => {
1165
- let mode = this.fan?.getAttribute(FanControl.Cluster.id, 'fanMode', this.fan.log);
1166
- let value = this.fan?.getAttribute(FanControl.Cluster.id, 'percentCurrent', this.fan.log);
1167
- mode = this.fanauto?.getAttribute(FanControl.Cluster.id, 'fanMode', this.fanauto.log);
1168
- value = this.fanauto?.getAttribute(FanControl.Cluster.id, 'percentCurrent', this.fanauto.log);
1252
+ let mode = this.fanBase?.getAttribute(FanControl.Cluster.id, 'fanMode', this.fanBase.log);
1253
+ let value = this.fanBase?.getAttribute(FanControl.Cluster.id, 'percentCurrent', this.fanBase.log);
1254
+ mode = this.fanDefault?.getAttribute(FanControl.Cluster.id, 'fanMode', this.fanDefault.log);
1255
+ value = this.fanDefault?.getAttribute(FanControl.Cluster.id, 'percentCurrent', this.fanDefault.log);
1169
1256
  if (isValidNumber(mode, FanControl.FanMode.Off, FanControl.FanMode.Auto) && mode === FanControl.FanMode.Auto && isValidNumber(value, 0, 100)) {
1170
1257
  value = value + 10 >= 100 ? 0 : value + 10;
1171
- await this.fanauto?.setAttribute(FanControl.Cluster.id, 'percentCurrent', value, this.fanauto.log);
1172
- await this.fanauto?.setAttribute(FanControl.Cluster.id, 'percentSetting', value, this.fanauto.log);
1173
- this.fanauto?.log.info(`Set fan percentCurrent and percentSetting to ${value}`);
1258
+ await this.fanDefault?.setAttribute(FanControl.Cluster.id, 'percentCurrent', value, this.fanDefault.log);
1259
+ await this.fanDefault?.setAttribute(FanControl.Cluster.id, 'percentSetting', value, this.fanDefault.log);
1260
+ this.fanDefault?.log.info(`Set fan percentCurrent and percentSetting to ${value}`);
1174
1261
  }
1175
1262
  mode = this.fanComplete?.getAttribute(FanControl.Cluster.id, 'fanMode', this.fanComplete.log);
1176
1263
  value = this.fanComplete?.getAttribute(FanControl.Cluster.id, 'percentCurrent', this.fanComplete.log);
@@ -1281,6 +1368,9 @@ export class ExampleMatterbridgeDynamicPlatform extends MatterbridgeDynamicPlatf
1281
1368
  await this.momentarySwitch?.getChildEndpointByName('Momentaryswitch1')?.triggerSwitchEvent('Single', this.momentarySwitch?.log);
1282
1369
  await this.momentarySwitch?.getChildEndpointByName('Momentaryswitch2')?.triggerSwitchEvent('Double', this.momentarySwitch?.log);
1283
1370
  await this.momentarySwitch?.getChildEndpointByName('Momentaryswitch3')?.triggerSwitchEvent('Long', this.momentarySwitch?.log);
1371
+ await this.momentarySwitch?.getChildEndpointByName('Momentaryswitch4')?.triggerSwitchEvent('Single', this.momentarySwitch?.log);
1372
+ await this.momentarySwitch?.getChildEndpointByName('Momentaryswitch5')?.triggerSwitchEvent('Single', this.momentarySwitch?.log);
1373
+ await this.momentarySwitch?.getChildEndpointByName('Momentaryswitch6')?.triggerSwitchEvent('Single', this.momentarySwitch?.log);
1284
1374
  }
1285
1375
  else if (this.genericSwitchLastEvent === 'Single') {
1286
1376
  this.genericSwitchLastEvent = 'Double';
@@ -1330,6 +1420,10 @@ export class ExampleMatterbridgeDynamicPlatform extends MatterbridgeDynamicPlatf
1330
1420
  return;
1331
1421
  this.setSelectDevice(device.serialNumber, device.deviceName, undefined, 'hub');
1332
1422
  if (this.validateDevice(device.deviceName)) {
1423
+ device.softwareVersion = parseInt(this.version.replace(/\D/g, ''));
1424
+ device.softwareVersionString = this.version === '' ? 'Unknown' : this.version;
1425
+ device.hardwareVersion = parseInt(this.matterbridge.matterbridgeVersion.replace(/\D/g, ''));
1426
+ device.hardwareVersionString = this.matterbridge.matterbridgeVersion;
1333
1427
  await this.registerDevice(device);
1334
1428
  this.bridgedDevices.set(device.deviceName, device);
1335
1429
  return device;
@@ -1,12 +1,12 @@
1
1
  {
2
2
  "name": "matterbridge-example-dynamic-platform",
3
- "version": "1.3.5-dev-20250723-2f335a4",
3
+ "version": "1.3.6-dev-20250725-69a3f4f",
4
4
  "lockfileVersion": 3,
5
5
  "requires": true,
6
6
  "packages": {
7
7
  "": {
8
8
  "name": "matterbridge-example-dynamic-platform",
9
- "version": "1.3.5-dev-20250723-2f335a4",
9
+ "version": "1.3.6-dev-20250725-69a3f4f",
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.5-dev-20250723-2f335a4",
3
+ "version": "1.3.6-dev-20250725-69a3f4f",
4
4
  "description": "Matterbridge dynamic plugin",
5
5
  "author": "https://github.com/Luligu",
6
6
  "license": "Apache-2.0",