matterbridge-example-dynamic-platform 1.3.4 → 1.3.5-dev-20250723-2f335a4

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,11 +23,13 @@ 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
26
+ ## [1.3.5] - 2025-07-22
27
27
 
28
28
  ### Added
29
29
 
30
30
  - [platform]: Changed to the new ExtratorHood() and Dishwasher() from Matterbridge.
31
+ - [platform]: Added a Fan with On Off Low Med High.
32
+ - [platform]: Added a Fan with complete set of features.
31
33
 
32
34
  ### Changed
33
35
 
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 45 virtual devices:
20
+ It exposes 46 virtual devices:
21
21
 
22
22
  - a switch with onOff cluster
23
23
  - a light with onOff
@@ -34,8 +34,9 @@ It exposes 45 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 FanControl cluster
38
- - a fan with all the features from FanControl cluster
37
+ - a fan with Off Low Med High presets
38
+ - a fan with Off Low Med High Auto presets and step
39
+ - a fan with all the features
39
40
  - a rainSensor device
40
41
  - a waterFreezeDetector device
41
42
  - a waterLeakDetector device
package/dist/platform.js CHANGED
@@ -23,6 +23,7 @@ export class ExampleMatterbridgeDynamicPlatform extends MatterbridgeDynamicPlatf
23
23
  thermoHeat;
24
24
  thermoCool;
25
25
  fan;
26
+ fanauto;
26
27
  fanComplete;
27
28
  waterLeak;
28
29
  waterFreeze;
@@ -38,6 +39,7 @@ export class ExampleMatterbridgeDynamicPlatform extends MatterbridgeDynamicPlatf
38
39
  momentarySwitch;
39
40
  latchingSwitch;
40
41
  vacuum;
42
+ roboticVacuum;
41
43
  waterHeater;
42
44
  evse;
43
45
  laundryWasher;
@@ -93,14 +95,7 @@ export class ExampleMatterbridgeDynamicPlatform extends MatterbridgeDynamicPlatf
93
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)
94
96
  .createDefaultOnOffClusterServer()
95
97
  .createDefaultPowerSourceRechargeableBatteryClusterServer(70);
96
- this.setSelectDevice(this.switch.serialNumber ?? '', this.switch.deviceName ?? '', undefined, 'hub');
97
- if (this.validateDevice(this.switch.deviceName ?? '')) {
98
- await this.registerDevice(this.switch);
99
- this.bridgedDevices.set(this.switch.deviceName ?? '', this.switch);
100
- }
101
- else {
102
- this.switch = undefined;
103
- }
98
+ this.switch = await this.addDevice(this.switch);
104
99
  this.switch?.addCommandHandler('identify', async ({ request: { identifyTime } }) => {
105
100
  this.log.info(`Command identify called identifyTime:${identifyTime}`);
106
101
  });
@@ -118,14 +113,7 @@ export class ExampleMatterbridgeDynamicPlatform extends MatterbridgeDynamicPlatf
118
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)
119
114
  .createDefaultOnOffClusterServer()
120
115
  .createDefaultPowerSourceRechargeableBatteryClusterServer(70);
121
- this.setSelectDevice(this.mountedOnOffSwitch.serialNumber ?? '', this.mountedOnOffSwitch.deviceName ?? '', undefined, 'hub');
122
- if (this.validateDevice(this.mountedOnOffSwitch.deviceName ?? '')) {
123
- await this.registerDevice(this.mountedOnOffSwitch);
124
- this.bridgedDevices.set(this.mountedOnOffSwitch.deviceName ?? '', this.mountedOnOffSwitch);
125
- }
126
- else {
127
- this.mountedOnOffSwitch = undefined;
128
- }
116
+ this.mountedOnOffSwitch = await this.addDevice(this.mountedOnOffSwitch);
129
117
  this.mountedOnOffSwitch?.addCommandHandler('identify', async ({ request: { identifyTime } }) => {
130
118
  this.mountedOnOffSwitch?.log.info(`Command identify called identifyTime:${identifyTime}`);
131
119
  });
@@ -145,14 +133,7 @@ export class ExampleMatterbridgeDynamicPlatform extends MatterbridgeDynamicPlatf
145
133
  .createDefaultLevelControlClusterServer()
146
134
  .createDefaultPowerSourceWiredClusterServer()
147
135
  .addRequiredClusterServers();
148
- this.setSelectDevice(this.mountedDimmerSwitch.serialNumber ?? '', this.mountedDimmerSwitch.deviceName ?? '', undefined, 'hub');
149
- if (this.validateDevice(this.mountedDimmerSwitch.deviceName ?? '')) {
150
- await this.registerDevice(this.mountedDimmerSwitch);
151
- this.bridgedDevices.set(this.mountedDimmerSwitch.deviceName ?? '', this.mountedDimmerSwitch);
152
- }
153
- else {
154
- this.mountedDimmerSwitch = undefined;
155
- }
136
+ this.mountedDimmerSwitch = await this.addDevice(this.mountedDimmerSwitch);
156
137
  this.mountedDimmerSwitch?.addCommandHandler('identify', async ({ request: { identifyTime } }) => {
157
138
  this.mountedDimmerSwitch?.log.info(`Command identify called identifyTime:${identifyTime}`);
158
139
  });
@@ -178,14 +159,7 @@ export class ExampleMatterbridgeDynamicPlatform extends MatterbridgeDynamicPlatf
178
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)
179
160
  .createDefaultOnOffClusterServer()
180
161
  .createDefaultPowerSourceWiredClusterServer();
181
- this.setSelectDevice(this.lightOnOff.serialNumber ?? '', this.lightOnOff.deviceName ?? '', undefined, 'hub');
182
- if (this.validateDevice(this.lightOnOff.deviceName ?? '')) {
183
- await this.registerDevice(this.lightOnOff);
184
- this.bridgedDevices.set(this.lightOnOff.deviceName ?? '', this.lightOnOff);
185
- }
186
- else {
187
- this.lightOnOff = undefined;
188
- }
162
+ this.lightOnOff = await this.addDevice(this.lightOnOff);
189
163
  this.lightOnOff?.addCommandHandler('identify', async ({ request: { identifyTime } }) => {
190
164
  this.lightOnOff?.log.info(`Command identify called identifyTime:${identifyTime}`);
191
165
  });
@@ -204,14 +178,7 @@ export class ExampleMatterbridgeDynamicPlatform extends MatterbridgeDynamicPlatf
204
178
  .createDefaultOnOffClusterServer()
205
179
  .createDefaultLevelControlClusterServer()
206
180
  .createDefaultPowerSourceReplaceableBatteryClusterServer(70, PowerSource.BatChargeLevel.Ok, 2990, '2 x AA', 2);
207
- this.setSelectDevice(this.dimmer.serialNumber ?? '', this.dimmer.deviceName ?? '', undefined, 'hub');
208
- if (this.validateDevice(this.dimmer.deviceName ?? '')) {
209
- await this.registerDevice(this.dimmer);
210
- this.bridgedDevices.set(this.dimmer.deviceName ?? '', this.dimmer);
211
- }
212
- else {
213
- this.dimmer = undefined;
214
- }
181
+ this.dimmer = await this.addDevice(this.dimmer);
215
182
  this.dimmer?.addCommandHandler('identify', async ({ request: { identifyTime } }) => {
216
183
  this.dimmer?.log.info(`Command identify called identifyTime:${identifyTime}`);
217
184
  });
@@ -239,14 +206,7 @@ export class ExampleMatterbridgeDynamicPlatform extends MatterbridgeDynamicPlatf
239
206
  .createDefaultLevelControlClusterServer()
240
207
  .createDefaultColorControlClusterServer()
241
208
  .createDefaultPowerSourceReplaceableBatteryClusterServer(70);
242
- this.setSelectDevice(this.light.serialNumber ?? '', this.light.deviceName ?? '', undefined, 'hub');
243
- if (this.validateDevice(this.light.deviceName ?? '')) {
244
- await this.registerDevice(this.light);
245
- this.bridgedDevices.set(this.light.deviceName ?? '', this.light);
246
- }
247
- else {
248
- this.light = undefined;
249
- }
209
+ this.light = await this.addDevice(this.light);
250
210
  this.light?.addCommandHandler('identify', async ({ request: { identifyTime } }) => {
251
211
  this.light?.log.info(`Command identify called identifyTime:${identifyTime}`);
252
212
  });
@@ -296,14 +256,7 @@ export class ExampleMatterbridgeDynamicPlatform extends MatterbridgeDynamicPlatf
296
256
  .createDefaultLevelControlClusterServer()
297
257
  .createHsColorControlClusterServer()
298
258
  .createDefaultPowerSourceWiredClusterServer();
299
- this.setSelectDevice(this.lightHS.serialNumber ?? '', this.lightHS.deviceName ?? '', undefined, 'hub');
300
- if (this.validateDevice(this.lightHS.deviceName ?? '')) {
301
- await this.registerDevice(this.lightHS);
302
- this.bridgedDevices.set(this.lightHS.deviceName ?? '', this.lightHS);
303
- }
304
- else {
305
- this.lightHS = undefined;
306
- }
259
+ this.lightHS = await this.addDevice(this.lightHS);
307
260
  this.lightHS?.addCommandHandler('identify', async ({ request: { identifyTime } }) => {
308
261
  this.lightHS?.log.info(`Command identify called identifyTime:${identifyTime}`);
309
262
  });
@@ -348,14 +301,7 @@ export class ExampleMatterbridgeDynamicPlatform extends MatterbridgeDynamicPlatf
348
301
  .createDefaultLevelControlClusterServer()
349
302
  .createXyColorControlClusterServer()
350
303
  .createDefaultPowerSourceWiredClusterServer();
351
- this.setSelectDevice(this.lightXY.serialNumber ?? '', this.lightXY.deviceName ?? '', undefined, 'hub');
352
- if (this.validateDevice(this.lightXY.deviceName ?? '')) {
353
- await this.registerDevice(this.lightXY);
354
- this.bridgedDevices.set(this.lightXY.deviceName ?? '', this.lightXY);
355
- }
356
- else {
357
- this.lightXY = undefined;
358
- }
304
+ this.lightXY = await this.addDevice(this.lightXY);
359
305
  this.lightXY?.addCommandHandler('identify', async ({ request: { identifyTime } }) => {
360
306
  this.lightXY?.log.info(`Command identify called identifyTime:${identifyTime}`);
361
307
  });
@@ -392,14 +338,7 @@ export class ExampleMatterbridgeDynamicPlatform extends MatterbridgeDynamicPlatf
392
338
  .createDefaultLevelControlClusterServer()
393
339
  .createCtColorControlClusterServer()
394
340
  .createDefaultPowerSourceReplaceableBatteryClusterServer(70);
395
- this.setSelectDevice(this.lightCT.serialNumber ?? '', this.lightCT.deviceName ?? '', undefined, 'hub');
396
- if (this.validateDevice(this.lightCT.deviceName ?? '')) {
397
- await this.registerDevice(this.lightCT);
398
- this.bridgedDevices.set(this.lightCT.deviceName ?? '', this.lightCT);
399
- }
400
- else {
401
- this.lightCT = undefined;
402
- }
341
+ this.lightCT = await this.addDevice(this.lightCT);
403
342
  this.lightCT?.addCommandHandler('identify', async ({ request: { identifyTime } }) => {
404
343
  this.lightCT?.log.info(`Command identify called identifyTime:${identifyTime}`);
405
344
  });
@@ -429,14 +368,7 @@ export class ExampleMatterbridgeDynamicPlatform extends MatterbridgeDynamicPlatf
429
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)
430
369
  .createDefaultOnOffClusterServer()
431
370
  .createDefaultPowerSourceWiredClusterServer();
432
- this.setSelectDevice(this.outlet.serialNumber ?? '', this.outlet.deviceName ?? '', undefined, 'hub');
433
- if (this.validateDevice(this.outlet.deviceName ?? '')) {
434
- await this.registerDevice(this.outlet);
435
- this.bridgedDevices.set(this.outlet.deviceName ?? '', this.outlet);
436
- }
437
- else {
438
- this.outlet = undefined;
439
- }
371
+ this.outlet = await this.addDevice(this.outlet);
440
372
  this.outlet?.addCommandHandler('identify', async ({ request: { identifyTime } }) => {
441
373
  this.outlet?.log.info(`Command identify called identifyTime:${identifyTime}`);
442
374
  });
@@ -454,14 +386,7 @@ export class ExampleMatterbridgeDynamicPlatform extends MatterbridgeDynamicPlatf
454
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)
455
387
  .createDefaultWindowCoveringClusterServer()
456
388
  .createDefaultPowerSourceRechargeableBatteryClusterServer(86);
457
- this.setSelectDevice(this.coverLift.serialNumber ?? '', this.coverLift.deviceName ?? '', undefined, 'hub');
458
- if (this.validateDevice(this.coverLift.deviceName ?? '')) {
459
- await this.registerDevice(this.coverLift);
460
- this.bridgedDevices.set(this.coverLift.deviceName ?? '', this.coverLift);
461
- }
462
- else {
463
- this.coverLift = undefined;
464
- }
389
+ this.coverLift = await this.addDevice(this.coverLift);
465
390
  this.coverLift?.addCommandHandler('identify', async ({ request: { identifyTime } }) => {
466
391
  this.coverLift?.log.info(`Command identify called identifyTime:${identifyTime}`);
467
392
  });
@@ -487,14 +412,7 @@ export class ExampleMatterbridgeDynamicPlatform extends MatterbridgeDynamicPlatf
487
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)
488
413
  .createDefaultLiftTiltWindowCoveringClusterServer()
489
414
  .createDefaultPowerSourceRechargeableBatteryClusterServer(86);
490
- this.setSelectDevice(this.coverLiftTilt.serialNumber ?? '', this.coverLiftTilt.deviceName ?? '', undefined, 'hub');
491
- if (this.validateDevice(this.coverLiftTilt.deviceName ?? '')) {
492
- await this.registerDevice(this.coverLiftTilt);
493
- this.bridgedDevices.set(this.coverLiftTilt.deviceName ?? '', this.coverLiftTilt);
494
- }
495
- else {
496
- this.coverLiftTilt = undefined;
497
- }
415
+ this.coverLiftTilt = await this.addDevice(this.coverLiftTilt);
498
416
  this.coverLiftTilt?.addCommandHandler('identify', async ({ request: { identifyTime } }) => {
499
417
  this.coverLiftTilt?.log.info(`Command identify called identifyTime:${identifyTime}`);
500
418
  });
@@ -524,14 +442,7 @@ export class ExampleMatterbridgeDynamicPlatform extends MatterbridgeDynamicPlatf
524
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)
525
443
  .createDefaultDoorLockClusterServer()
526
444
  .createDefaultPowerSourceRechargeableBatteryClusterServer(30);
527
- this.setSelectDevice(this.lock.serialNumber ?? '', this.lock.deviceName ?? '', undefined, 'hub');
528
- if (this.validateDevice(this.lock.deviceName ?? '')) {
529
- await this.registerDevice(this.lock);
530
- this.bridgedDevices.set(this.lock.deviceName ?? '', this.lock);
531
- }
532
- else {
533
- this.lock = undefined;
534
- }
445
+ this.lock = await this.addDevice(this.lock);
535
446
  this.lock?.addCommandHandler('identify', async ({ request: { identifyTime } }) => {
536
447
  this.lock?.log.info(`Command identify called identifyTime:${identifyTime}`);
537
448
  });
@@ -561,14 +472,7 @@ export class ExampleMatterbridgeDynamicPlatform extends MatterbridgeDynamicPlatf
561
472
  .addChildDeviceType('Humidity', humiditySensor)
562
473
  .createDefaultRelativeHumidityMeasurementClusterServer(50 * 100)
563
474
  .addRequiredClusterServers();
564
- this.setSelectDevice(this.thermoAuto.serialNumber ?? '', this.thermoAuto.deviceName ?? '', undefined, 'hub');
565
- if (this.validateDevice(this.thermoAuto.deviceName ?? '')) {
566
- await this.registerDevice(this.thermoAuto);
567
- this.bridgedDevices.set(this.thermoAuto.deviceName ?? '', this.thermoAuto);
568
- }
569
- else {
570
- this.thermoAuto = undefined;
571
- }
475
+ this.thermoAuto = await this.addDevice(this.thermoAuto);
572
476
  this.thermoAuto?.addCommandHandler('identify', async ({ request: { identifyTime } }) => {
573
477
  this.thermoAuto?.log.info(`Command identify called identifyTime ${identifyTime}`);
574
478
  });
@@ -617,14 +521,7 @@ export class ExampleMatterbridgeDynamicPlatform extends MatterbridgeDynamicPlatf
617
521
  })
618
522
  .createDefaultIdentifyClusterServer()
619
523
  .createDefaultTemperatureMeasurementClusterServer(15 * 100);
620
- this.setSelectDevice(this.thermoHeat.serialNumber ?? '', this.thermoHeat.deviceName ?? '', undefined, 'hub');
621
- if (this.validateDevice(this.thermoHeat.deviceName ?? '')) {
622
- await this.registerDevice(this.thermoHeat);
623
- this.bridgedDevices.set(this.thermoHeat.deviceName ?? '', this.thermoHeat);
624
- }
625
- else {
626
- this.thermoHeat = undefined;
627
- }
524
+ this.thermoHeat = await this.addDevice(this.thermoHeat);
628
525
  this.thermoHeat?.addCommandHandler('identify', async ({ request: { identifyTime } }) => {
629
526
  this.thermoHeat?.log.info(`Command identify called identifyTime ${identifyTime}`);
630
527
  });
@@ -644,14 +541,7 @@ export class ExampleMatterbridgeDynamicPlatform extends MatterbridgeDynamicPlatf
644
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)
645
542
  .createDefaultCoolingThermostatClusterServer(20, 18, 5, 35)
646
543
  .createDefaultPowerSourceReplaceableBatteryClusterServer(40, PowerSource.BatChargeLevel.Ok, 5080, 'AA 1.5V', 4);
647
- this.setSelectDevice(this.thermoCool.serialNumber ?? '', this.thermoCool.deviceName ?? '', undefined, 'hub');
648
- if (this.validateDevice(this.thermoCool.deviceName ?? '')) {
649
- await this.registerDevice(this.thermoCool);
650
- this.bridgedDevices.set(this.thermoCool.deviceName ?? '', this.thermoCool);
651
- }
652
- else {
653
- this.thermoCool = undefined;
654
- }
544
+ this.thermoCool = await this.addDevice(this.thermoCool);
655
545
  this.thermoCool?.addCommandHandler('identify', async ({ request: { identifyTime } }) => {
656
546
  this.thermoCool?.log.info(`Command identify called identifyTime ${identifyTime}`);
657
547
  });
@@ -674,14 +564,7 @@ export class ExampleMatterbridgeDynamicPlatform extends MatterbridgeDynamicPlatf
674
564
  .createDefaultPowerSourceWiredClusterServer()
675
565
  .createDefaultActivatedCarbonFilterMonitoringClusterServer()
676
566
  .createDefaultHepaFilterMonitoringClusterServer();
677
- this.setSelectDevice(this.airPurifier.serialNumber ?? '', this.airPurifier.deviceName ?? '', undefined, 'hub');
678
- if (this.validateDevice(this.airPurifier.deviceName ?? '')) {
679
- await this.registerDevice(this.airPurifier);
680
- this.bridgedDevices.set(this.airPurifier.deviceName ?? '', this.airPurifier);
681
- }
682
- else {
683
- this.airPurifier = undefined;
684
- }
567
+ this.airPurifier = await this.addDevice(this.airPurifier);
685
568
  this.airPurifier?.addCommandHandler('identify', async ({ request: { identifyTime } }) => {
686
569
  this.airPurifier?.log.info(`Command identify called identifyTime:${identifyTime}`);
687
570
  });
@@ -728,14 +611,7 @@ export class ExampleMatterbridgeDynamicPlatform extends MatterbridgeDynamicPlatf
728
611
  .createDefaultRelativeHumidityMeasurementClusterServer(50 * 100)
729
612
  .createDefaultPowerSourceWiredClusterServer()
730
613
  .addRequiredClusterServers();
731
- this.setSelectDevice(this.airConditioner.serialNumber ?? '', this.airConditioner.deviceName ?? '', undefined, 'hub');
732
- if (this.validateDevice(this.airConditioner.deviceName ?? '')) {
733
- await this.registerDevice(this.airConditioner);
734
- this.bridgedDevices.set(this.airConditioner.deviceName ?? '', this.airConditioner);
735
- }
736
- else {
737
- this.airConditioner = undefined;
738
- }
614
+ this.airConditioner = await this.addDevice(this.airConditioner);
739
615
  this.airConditioner?.addCommandHandler('identify', async ({ request: { identifyTime } }) => {
740
616
  this.airConditioner?.log.info(`Command identify called identifyTime:${identifyTime}`);
741
617
  });
@@ -760,14 +636,7 @@ export class ExampleMatterbridgeDynamicPlatform extends MatterbridgeDynamicPlatf
760
636
  .createLevelControlClusterServer()
761
637
  .createDefaultPumpConfigurationAndControlClusterServer()
762
638
  .createDefaultPowerSourceWiredClusterServer();
763
- this.setSelectDevice(this.pump.serialNumber ?? '', this.pump.deviceName ?? '', undefined, 'hub');
764
- if (this.validateDevice(this.pump.deviceName ?? '')) {
765
- await this.registerDevice(this.pump);
766
- this.bridgedDevices.set(this.pump.deviceName ?? '', this.pump);
767
- }
768
- else {
769
- this.pump = undefined;
770
- }
639
+ this.pump = await this.addDevice(this.pump);
771
640
  this.pump?.addCommandHandler('identify', async ({ request: { identifyTime } }) => {
772
641
  this.pump?.log.info(`Command identify called identifyTime:${identifyTime}`);
773
642
  });
@@ -788,29 +657,16 @@ export class ExampleMatterbridgeDynamicPlatform extends MatterbridgeDynamicPlatf
788
657
  .createDefaultIdentifyClusterServer()
789
658
  .createDefaultValveConfigurationAndControlClusterServer()
790
659
  .createDefaultPowerSourceWiredClusterServer();
791
- this.setSelectDevice(this.valve.serialNumber ?? '', this.valve.deviceName ?? '', undefined, 'hub');
792
- if (this.validateDevice(this.valve.deviceName ?? '')) {
793
- await this.registerDevice(this.valve);
794
- this.bridgedDevices.set(this.valve.deviceName ?? '', this.valve);
795
- }
796
- else {
797
- this.valve = undefined;
798
- }
660
+ this.valve = await this.addDevice(this.valve);
799
661
  this.valve?.addCommandHandler('identify', async ({ request: { identifyTime } }) => {
800
662
  this.valve?.log.info(`Command identify called identifyTime:${identifyTime}`);
801
663
  });
802
- this.fan = new MatterbridgeEndpoint([fanDevice, bridgedNode, powerSource], { uniqueStorageKey: 'Fan off low medium high auto' }, this.config.debug)
803
- .createDefaultBridgedDeviceBasicInformationClusterServer('Fan auto', 'serial_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)
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)
804
666
  .createDefaultPowerSourceWiredClusterServer()
667
+ .createBaseFanControlClusterServer()
805
668
  .addRequiredClusterServers();
806
- this.setSelectDevice(this.fan.serialNumber ?? '', this.fan.deviceName ?? '', undefined, 'hub');
807
- if (this.validateDevice(this.fan.deviceName ?? '')) {
808
- await this.registerDevice(this.fan);
809
- this.bridgedDevices.set(this.fan.deviceName ?? '', this.fan);
810
- }
811
- else {
812
- this.fan = undefined;
813
- }
669
+ this.fan = await this.addDevice(this.fan);
814
670
  await this.fan?.subscribeAttribute(FanControl.Cluster.id, 'fanMode', (newValue, oldValue, context) => {
815
671
  this.fan?.log.info(`Fan mode changed from ${this.fanModeLookup[oldValue]} to ${this.fanModeLookup[newValue]} context: ${context.offline === true ? 'offline' : 'online'}`);
816
672
  if (context.offline === true)
@@ -847,19 +703,53 @@ export class ExampleMatterbridgeDynamicPlatform extends MatterbridgeDynamicPlatf
847
703
  if (isValidNumber(newValue, 0, 100))
848
704
  this.fan?.setAttribute(FanControl.Cluster.id, 'percentCurrent', newValue, this.fan?.log);
849
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)
708
+ .createDefaultPowerSourceWiredClusterServer()
709
+ .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'}`);
713
+ if (context.offline === true)
714
+ return;
715
+ 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);
718
+ }
719
+ 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);
722
+ }
723
+ 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);
726
+ }
727
+ 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);
730
+ }
731
+ 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);
734
+ }
735
+ 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);
738
+ }
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'}`);
742
+ if (context.offline === true)
743
+ return;
744
+ if (isValidNumber(newValue, 0, 100))
745
+ this.fanauto?.setAttribute(FanControl.Cluster.id, 'percentCurrent', newValue, this.fanauto?.log);
746
+ }, this.fanauto.log);
850
747
  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)
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)
852
749
  .createDefaultPowerSourceWiredClusterServer()
853
750
  .createCompleteFanControlClusterServer()
854
751
  .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
- }
752
+ this.fanComplete = await this.addDevice(this.fanComplete);
863
753
  await this.fanComplete?.subscribeAttribute(FanControl.Cluster.id, 'fanMode', (newValue, oldValue, context) => {
864
754
  this.fanComplete?.log.info(`Fan mode changed from ${this.fanModeLookup[oldValue]} to ${this.fanModeLookup[newValue]} context: ${context.offline === true ? 'offline' : 'online'}`);
865
755
  if (context.offline === true)
@@ -911,83 +801,41 @@ export class ExampleMatterbridgeDynamicPlatform extends MatterbridgeDynamicPlatf
911
801
  .createDefaultBooleanStateClusterServer(false)
912
802
  .addRequiredClusterServers()
913
803
  .addOptionalClusterServers();
914
- this.setSelectDevice(this.waterLeak.serialNumber ?? '', this.waterLeak.deviceName ?? '', undefined, 'hub');
915
- if (this.validateDevice(this.waterLeak.deviceName ?? '')) {
916
- await this.registerDevice(this.waterLeak);
917
- this.bridgedDevices.set(this.waterLeak.deviceName ?? '', this.waterLeak);
918
- }
919
- else {
920
- this.waterLeak = undefined;
921
- }
804
+ this.waterLeak = await this.addDevice(this.waterLeak);
922
805
  this.waterFreeze = new MatterbridgeEndpoint([waterFreezeDetector, bridgedNode, powerSource], { uniqueStorageKey: 'Water freeze detector' }, this.config.debug)
923
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)
924
807
  .createDefaultPowerSourceRechargeableBatteryClusterServer()
925
808
  .createDefaultBooleanStateClusterServer(false)
926
809
  .addRequiredClusterServers()
927
810
  .addOptionalClusterServers();
928
- this.setSelectDevice(this.waterFreeze.serialNumber ?? '', this.waterFreeze.deviceName ?? '', undefined, 'hub');
929
- if (this.validateDevice(this.waterFreeze.deviceName ?? '')) {
930
- await this.registerDevice(this.waterFreeze);
931
- this.bridgedDevices.set(this.waterFreeze.deviceName ?? '', this.waterFreeze);
932
- }
933
- else {
934
- this.waterFreeze = undefined;
935
- }
811
+ this.waterFreeze = await this.addDevice(this.waterFreeze);
936
812
  this.rain = new MatterbridgeEndpoint([rainSensor, bridgedNode, powerSource], { uniqueStorageKey: 'Rain sensor' }, this.config.debug)
937
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)
938
814
  .createDefaultPowerSourceRechargeableBatteryClusterServer()
939
815
  .createDefaultIdentifyClusterServer()
940
816
  .createDefaultBooleanStateClusterServer(false)
941
817
  .createDefaultBooleanStateConfigurationClusterServer();
942
- this.setSelectDevice(this.rain.serialNumber ?? '', this.rain.deviceName ?? '', undefined, 'hub');
943
- if (this.validateDevice(this.rain.deviceName ?? '')) {
944
- await this.registerDevice(this.rain);
945
- this.bridgedDevices.set(this.rain.deviceName ?? '', this.rain);
946
- }
947
- else {
948
- this.rain = undefined;
949
- }
818
+ this.rain = await this.addDevice(this.rain);
950
819
  this.smokeCo = new MatterbridgeEndpoint([smokeCoAlarm, bridgedNode, powerSource], { uniqueStorageKey: 'SmokeCo alarm sensor' }, this.config.debug)
951
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)
952
821
  .createDefaultIdentifyClusterServer()
953
822
  .createDefaultSmokeCOAlarmClusterServer(SmokeCoAlarm.AlarmState.Normal, SmokeCoAlarm.AlarmState.Normal)
954
823
  .createDefaultPowerSourceReplaceableBatteryClusterServer()
955
824
  .createDefaultCarbonMonoxideConcentrationMeasurementClusterServer(100);
956
- this.setSelectDevice(this.smokeCo.serialNumber ?? '', this.smokeCo.deviceName ?? '', undefined, 'hub');
957
- if (this.validateDevice(this.smokeCo.deviceName ?? '')) {
958
- await this.registerDevice(this.smokeCo);
959
- this.bridgedDevices.set(this.smokeCo.deviceName ?? '', this.smokeCo);
960
- }
961
- else {
962
- this.smokeCo = undefined;
963
- }
825
+ this.smokeCo = await this.addDevice(this.smokeCo);
964
826
  this.smokeOnly = new MatterbridgeEndpoint([smokeCoAlarm, bridgedNode, powerSource], { uniqueStorageKey: 'Smoke alarm sensor' }, this.config.debug)
965
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)
966
828
  .createDefaultIdentifyClusterServer()
967
829
  .createSmokeOnlySmokeCOAlarmClusterServer(SmokeCoAlarm.AlarmState.Normal)
968
830
  .createDefaultPowerSourceReplaceableBatteryClusterServer();
969
- this.setSelectDevice(this.smokeOnly.serialNumber ?? '', this.smokeOnly.deviceName ?? '', undefined, 'hub');
970
- if (this.validateDevice(this.smokeOnly.deviceName ?? '')) {
971
- await this.registerDevice(this.smokeOnly);
972
- this.bridgedDevices.set(this.smokeOnly.deviceName ?? '', this.smokeOnly);
973
- }
974
- else {
975
- this.smokeOnly = undefined;
976
- }
831
+ this.smokeOnly = await this.addDevice(this.smokeOnly);
977
832
  this.coOnly = new MatterbridgeEndpoint([smokeCoAlarm, bridgedNode, powerSource], { uniqueStorageKey: 'Co alarm sensor' }, this.config.debug)
978
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)
979
834
  .createDefaultIdentifyClusterServer()
980
835
  .createCoOnlySmokeCOAlarmClusterServer(SmokeCoAlarm.AlarmState.Normal)
981
836
  .createDefaultPowerSourceReplaceableBatteryClusterServer()
982
837
  .createDefaultCarbonMonoxideConcentrationMeasurementClusterServer(100);
983
- this.setSelectDevice(this.coOnly.serialNumber ?? '', this.coOnly.deviceName ?? '', undefined, 'hub');
984
- if (this.validateDevice(this.coOnly.deviceName ?? '')) {
985
- await this.registerDevice(this.coOnly);
986
- this.bridgedDevices.set(this.coOnly.deviceName ?? '', this.coOnly);
987
- }
988
- else {
989
- this.coOnly = undefined;
990
- }
838
+ this.coOnly = await this.addDevice(this.coOnly);
991
839
  this.airQuality = new MatterbridgeEndpoint([airQualitySensor, bridgedNode, powerSource], { uniqueStorageKey: 'Air quality sensor' }, this.config.debug)
992
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)
993
841
  .createDefaultPowerSourceReplaceableBatteryClusterServer(50, PowerSource.BatChargeLevel.Warning, 2900, 'CR2450', 1)
@@ -1003,14 +851,7 @@ export class ExampleMatterbridgeDynamicPlatform extends MatterbridgeDynamicPlatf
1003
851
  .createDefaultPm10ConcentrationMeasurementClusterServer(100)
1004
852
  .createDefaultRadonConcentrationMeasurementClusterServer(100)
1005
853
  .createDefaultTvocMeasurementClusterServer(100);
1006
- this.setSelectDevice(this.airQuality.serialNumber ?? '', this.airQuality.deviceName ?? '', undefined, 'hub');
1007
- if (this.validateDevice(this.airQuality.deviceName ?? '')) {
1008
- await this.registerDevice(this.airQuality);
1009
- this.bridgedDevices.set(this.airQuality.deviceName ?? '', this.airQuality);
1010
- }
1011
- else {
1012
- this.airQuality = undefined;
1013
- }
854
+ this.airQuality = await this.addDevice(this.airQuality);
1014
855
  this.momentarySwitch = new MatterbridgeEndpoint([bridgedNode, powerSource], { uniqueStorageKey: 'Momentary switch composed' }, this.config.debug)
1015
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)
1016
857
  .createDefaultIdentifyClusterServer()
@@ -1042,28 +883,14 @@ export class ExampleMatterbridgeDynamicPlatform extends MatterbridgeDynamicPlatf
1042
883
  })
1043
884
  .createDefaultIdentifyClusterServer()
1044
885
  .createDefaultSwitchClusterServer();
1045
- this.setSelectDevice(this.momentarySwitch.serialNumber ?? '', this.momentarySwitch.deviceName ?? '', undefined, 'hub');
1046
- if (this.validateDevice(this.momentarySwitch.deviceName ?? '')) {
1047
- await this.registerDevice(this.momentarySwitch);
1048
- this.bridgedDevices.set(this.momentarySwitch.deviceName ?? '', this.momentarySwitch);
1049
- }
1050
- else {
1051
- this.momentarySwitch = undefined;
1052
- }
886
+ this.momentarySwitch = await this.addDevice(this.momentarySwitch);
1053
887
  this.latchingSwitch = new MatterbridgeEndpoint([genericSwitch, bridgedNode, powerSource], { uniqueStorageKey: 'Latching switch' }, this.config.debug)
1054
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)
1055
889
  .createDefaultIdentifyClusterServer()
1056
890
  .createDefaultLatchingSwitchClusterServer()
1057
891
  .createDefaultPowerSourceReplaceableBatteryClusterServer(10, PowerSource.BatChargeLevel.Critical, 2850, 'CR2032', 1);
1058
- this.setSelectDevice(this.latchingSwitch.serialNumber ?? '', this.latchingSwitch.deviceName ?? '', undefined, 'hub');
1059
- if (this.validateDevice(this.latchingSwitch.deviceName ?? '')) {
1060
- await this.registerDevice(this.latchingSwitch);
1061
- this.bridgedDevices.set(this.latchingSwitch.deviceName ?? '', this.latchingSwitch);
1062
- }
1063
- else {
1064
- this.latchingSwitch = undefined;
1065
- }
1066
- const robot = new RoboticVacuumCleaner('Robot Vacuum', 'RVC1238777820', this.config.enableServerRvc === true ? 'server' : undefined, 1, [
892
+ this.latchingSwitch = await this.addDevice(this.latchingSwitch);
893
+ this.roboticVacuum = new RoboticVacuumCleaner('Robot Vacuum', 'RVC1238777820', this.config.enableServerRvc === true ? 'server' : undefined, 1, [
1067
894
  { label: 'Idle', mode: 1, modeTags: [{ value: RvcRunMode.ModeTag.Idle }] },
1068
895
  { label: 'Cleaning', mode: 2, modeTags: [{ value: RvcRunMode.ModeTag.Cleaning }] },
1069
896
  { label: 'Mapping', mode: 3, modeTags: [{ value: RvcRunMode.ModeTag.Mapping }] },
@@ -1114,96 +941,40 @@ export class ExampleMatterbridgeDynamicPlatform extends MatterbridgeDynamicPlatf
1114
941
  if (this.config.enableServerRvc === true) {
1115
942
  this.log.notice('RVC is in server mode');
1116
943
  }
1117
- this.setSelectDevice(robot.serialNumber ?? '', robot.deviceName ?? '', undefined, 'hub');
1118
- if (this.validateDevice(robot.deviceName ?? '')) {
1119
- await this.registerDevice(robot);
1120
- this.bridgedDevices.set(robot.deviceName ?? '', robot);
1121
- }
944
+ this.roboticVacuum = await this.addDevice(this.roboticVacuum);
1122
945
  this.waterHeater = new WaterHeater('Water Heater', 'WH3456177820', 50, 60, 20, 80, undefined, 85, 220_000, 1_000, 220_000, 12_000_000, 500_000, 3_000_000);
1123
- this.setSelectDevice(this.waterHeater.serialNumber ?? '', this.waterHeater.deviceName ?? '', undefined, 'hub');
1124
- if (this.validateDevice(this.waterHeater.deviceName ?? '')) {
1125
- await this.registerDevice(this.waterHeater);
1126
- this.bridgedDevices.set(this.waterHeater.deviceName ?? '', this.waterHeater);
1127
- }
946
+ this.waterHeater = await this.addDevice(this.waterHeater);
1128
947
  this.evse = new Evse('Evse', 'EV3456127820', 1, [
1129
948
  { label: 'On demand', mode: 1, modeTags: [{ value: EnergyEvseMode.ModeTag.Manual }] },
1130
949
  { label: 'Scheduled', mode: 2, modeTags: [{ value: EnergyEvseMode.ModeTag.TimeOfUse }] },
1131
950
  { label: 'Solar Charging', mode: 3, modeTags: [{ value: EnergyEvseMode.ModeTag.SolarCharging }] },
1132
951
  { label: 'Solar Charging Scheduled', mode: 4, modeTags: [{ value: EnergyEvseMode.ModeTag.SolarCharging }, { value: EnergyEvseMode.ModeTag.TimeOfUse }] },
1133
952
  ], EnergyEvse.State.PluggedInCharging, EnergyEvse.SupplyState.ChargingEnabled, EnergyEvse.FaultState.NoError, 220_000, 10_000, 2_200_000, 1_000_000, 500_000, 32_000_000);
1134
- this.setSelectDevice(this.evse.serialNumber ?? '', this.evse.deviceName ?? '', undefined, 'hub');
1135
- if (this.validateDevice(this.evse.deviceName ?? '')) {
1136
- await this.registerDevice(this.evse);
1137
- this.bridgedDevices.set(this.evse.deviceName ?? '', this.evse);
1138
- }
953
+ this.evse = await this.addDevice(this.evse);
1139
954
  this.solarPower = new SolarPower('Solar Power', 'SP3456127821', 220_000, 10_000, 2200_000, 2_200_000, -10_000_000, 500_000);
1140
- this.setSelectDevice(this.solarPower.serialNumber ?? '', this.solarPower.deviceName ?? '', undefined, 'hub');
1141
- if (this.validateDevice(this.solarPower.deviceName ?? '')) {
1142
- await this.registerDevice(this.solarPower);
1143
- this.bridgedDevices.set(this.solarPower.deviceName ?? '', this.solarPower);
1144
- }
955
+ this.solarPower = await this.addDevice(this.solarPower);
1145
956
  this.batteryStorage = new BatteryStorage('Battery Storage', 'BS3456127822', 75, PowerSource.BatChargeLevel.Ok, 220_000, 10_000, 2_200_000, 1_000_000, 2_000_000, -2_000_000, 3_000_000);
1146
- this.setSelectDevice(this.batteryStorage.serialNumber ?? '', this.batteryStorage.deviceName ?? '', undefined, 'hub');
1147
- if (this.validateDevice(this.batteryStorage.deviceName ?? '')) {
1148
- await this.registerDevice(this.batteryStorage);
1149
- this.bridgedDevices.set(this.batteryStorage.deviceName ?? '', this.batteryStorage);
1150
- }
957
+ this.batteryStorage = await this.addDevice(this.batteryStorage);
1151
958
  this.heatPump = new HeatPump('Heat Pump', 'HP1234567890', 220_000, 10_000, 2_200_000, 1_000_000, 500_000, 3_000_000);
1152
- this.setSelectDevice(this.heatPump.serialNumber ?? '', this.heatPump.deviceName ?? '', undefined, 'hub');
1153
- if (this.validateDevice(this.heatPump.deviceName ?? '')) {
1154
- await this.registerDevice(this.heatPump);
1155
- this.bridgedDevices.set(this.heatPump.deviceName ?? '', this.heatPump);
1156
- }
959
+ this.heatPump = await this.addDevice(this.heatPump);
1157
960
  this.laundryWasher = new LaundryWasher('Laundry Washer', 'LW1234567890');
1158
- this.setSelectDevice(this.laundryWasher.serialNumber ?? '', this.laundryWasher.deviceName ?? '', undefined, 'hub');
1159
- if (this.validateDevice(this.laundryWasher.deviceName ?? '')) {
1160
- await this.registerDevice(this.laundryWasher);
1161
- this.bridgedDevices.set(this.laundryWasher.deviceName ?? '', this.laundryWasher);
1162
- }
961
+ this.laundryWasher = await this.addDevice(this.laundryWasher);
1163
962
  this.laundryDryer = new LaundryDryer('Laundry Dryer', 'LDW1235227890');
1164
- this.setSelectDevice(this.laundryDryer.serialNumber ?? '', this.laundryDryer.deviceName ?? '', undefined, 'hub');
1165
- if (this.validateDevice(this.laundryDryer.deviceName ?? '')) {
1166
- await this.registerDevice(this.laundryDryer);
1167
- this.bridgedDevices.set(this.laundryDryer.deviceName ?? '', this.laundryDryer);
1168
- }
963
+ this.laundryDryer = await this.addDevice(this.laundryDryer);
1169
964
  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
- }
965
+ this.dishwasher = await this.addDevice(this.dishwasher);
1175
966
  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);
1180
- }
967
+ this.extractorHood = await this.addDevice(this.extractorHood);
1181
968
  const refrigeratorDevice = new Appliances(refrigerator, 'Refrigerator', 'RE9987654322');
1182
969
  refrigeratorDevice.addFixedLabel('composed', 'Refrigerator');
1183
- this.setSelectDevice(refrigeratorDevice.serialNumber ?? '', refrigeratorDevice.deviceName ?? '', undefined, 'hub');
1184
- if (this.validateDevice(refrigeratorDevice.deviceName ?? '')) {
1185
- await this.registerDevice(refrigeratorDevice);
1186
- this.bridgedDevices.set(refrigeratorDevice.deviceName ?? '', refrigeratorDevice);
1187
- }
970
+ await this.addDevice(refrigeratorDevice);
1188
971
  const ovenDevice = new Appliances(oven, 'Oven', 'OV1298867891');
1189
972
  ovenDevice.addFixedLabel('composed', 'Oven');
1190
- this.setSelectDevice(ovenDevice.serialNumber ?? '', ovenDevice.deviceName ?? '', undefined, 'hub');
1191
- if (this.validateDevice(ovenDevice.deviceName ?? '')) {
1192
- await this.registerDevice(ovenDevice);
1193
- this.bridgedDevices.set(ovenDevice.deviceName ?? '', ovenDevice);
1194
- }
973
+ await this.addDevice(ovenDevice);
1195
974
  const microwaveOvenDevice = new Appliances(microwaveOven, 'Microwave Oven', 'MO1234567892');
1196
- this.setSelectDevice(microwaveOvenDevice.serialNumber ?? '', microwaveOvenDevice.deviceName ?? '', undefined, 'hub');
1197
- if (this.validateDevice(microwaveOvenDevice.deviceName ?? '')) {
1198
- await this.registerDevice(microwaveOvenDevice);
1199
- this.bridgedDevices.set(microwaveOvenDevice.deviceName ?? '', microwaveOvenDevice);
1200
- }
975
+ await this.addDevice(microwaveOvenDevice);
1201
976
  const cooktopDevice = new Appliances(cooktop, 'Cooktop', 'CT1255887894');
1202
- this.setSelectDevice(cooktopDevice.serialNumber ?? '', cooktopDevice.deviceName ?? '', undefined, 'hub');
1203
- if (this.validateDevice(cooktopDevice.deviceName ?? '')) {
1204
- await this.registerDevice(cooktopDevice);
1205
- this.bridgedDevices.set(cooktopDevice.deviceName ?? '', cooktopDevice);
1206
- }
977
+ await this.addDevice(cooktopDevice);
1207
978
  }
1208
979
  async onConfigure() {
1209
980
  await super.onConfigure();
@@ -1327,7 +1098,7 @@ export class ExampleMatterbridgeDynamicPlatform extends MatterbridgeDynamicPlatf
1327
1098
  const status = this.lock?.getAttribute(DoorLock.Cluster.id, 'lockState', this.lock.log);
1328
1099
  if (isValidNumber(status, DoorLock.LockState.Locked, DoorLock.LockState.Unlocked)) {
1329
1100
  await this.lock?.setAttribute(DoorLock.Cluster.id, 'lockState', status === DoorLock.LockState.Locked ? DoorLock.LockState.Unlocked : DoorLock.LockState.Locked, this.lock.log);
1330
- this.lock?.log.info(`Set lock lockState to ${status === DoorLock.LockState.Locked ? 'Unlocked' : 'Locked'}`);
1101
+ this.lock?.log.info(`Set lock lockState to ${status === DoorLock.LockState.Locked ? 'Locked' : 'Unlocked'}`);
1331
1102
  }
1332
1103
  }, 60 * 1000 + 500);
1333
1104
  }
@@ -1379,19 +1150,35 @@ export class ExampleMatterbridgeDynamicPlatform extends MatterbridgeDynamicPlatf
1379
1150
  }
1380
1151
  }, 60 * 1000 + 550);
1381
1152
  }
1382
- this.fan?.log.info('Set fan initial fanMode to Auto, percentCurrent and percentSetting to 50');
1383
- await this.fan?.setAttribute(FanControl.Cluster.id, 'fanMode', FanControl.FanMode.Auto, this.fan.log);
1384
- await this.fan?.setAttribute(FanControl.Cluster.id, 'percentCurrent', 50, this.fan.log);
1385
- await this.fan?.setAttribute(FanControl.Cluster.id, 'percentSetting', 50, this.fan.log);
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);
1160
+ await this.fanComplete?.setAttribute(FanControl.Cluster.id, 'fanMode', FanControl.FanMode.Auto, this.fanComplete.log);
1161
+ await this.fanComplete?.setAttribute(FanControl.Cluster.id, 'percentCurrent', 0, this.fanComplete.log);
1162
+ await this.fanComplete?.setAttribute(FanControl.Cluster.id, 'percentSetting', 0, this.fanComplete.log);
1386
1163
  if (this.config.useInterval) {
1387
1164
  this.fanInterval = setInterval(async () => {
1388
- const mode = this.fan?.getAttribute(FanControl.Cluster.id, 'fanMode', this.fan.log);
1165
+ let mode = this.fan?.getAttribute(FanControl.Cluster.id, 'fanMode', this.fan.log);
1389
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);
1390
1169
  if (isValidNumber(mode, FanControl.FanMode.Off, FanControl.FanMode.Auto) && mode === FanControl.FanMode.Auto && isValidNumber(value, 0, 100)) {
1391
1170
  value = value + 10 >= 100 ? 0 : value + 10;
1392
- await this.fan?.setAttribute(FanControl.Cluster.id, 'percentCurrent', value, this.fan.log);
1393
- await this.fan?.setAttribute(FanControl.Cluster.id, 'percentSetting', value, this.fan.log);
1394
- this.fan?.log.info(`Set fan percentCurrent and percentSetting to ${value}`);
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}`);
1174
+ }
1175
+ mode = this.fanComplete?.getAttribute(FanControl.Cluster.id, 'fanMode', this.fanComplete.log);
1176
+ value = this.fanComplete?.getAttribute(FanControl.Cluster.id, 'percentCurrent', this.fanComplete.log);
1177
+ if (isValidNumber(mode, FanControl.FanMode.Off, FanControl.FanMode.Auto) && mode === FanControl.FanMode.Auto && isValidNumber(value, 0, 100)) {
1178
+ value = value + 10 >= 100 ? 0 : value + 10;
1179
+ await this.fanComplete?.setAttribute(FanControl.Cluster.id, 'percentCurrent', value, this.fanComplete.log);
1180
+ await this.fanComplete?.setAttribute(FanControl.Cluster.id, 'percentSetting', value, this.fanComplete.log);
1181
+ this.fanComplete?.log.info(`Set fan percentCurrent and percentSetting to ${value}`);
1395
1182
  }
1396
1183
  }, 60 * 1000 + 700);
1397
1184
  }
@@ -1448,18 +1235,16 @@ export class ExampleMatterbridgeDynamicPlatform extends MatterbridgeDynamicPlatf
1448
1235
  await this.airQuality?.setAttribute(AirQuality.Cluster.id, 'airQuality', AirQuality.AirQualityEnum.Good, this.airQuality.log);
1449
1236
  await this.airQuality?.setAttribute(TemperatureMeasurement.Cluster.id, 'measuredValue', 2150, this.airQuality.log);
1450
1237
  await this.airQuality?.setAttribute(RelativeHumidityMeasurement.Cluster.id, 'measuredValue', 5500, this.airQuality.log);
1451
- if (this.config.enableConcentrationMeasurements === true) {
1452
- await this.airQuality?.setAttribute(CarbonMonoxideConcentrationMeasurement.Cluster.id, 'measuredValue', 10, this.airQuality.log);
1453
- await this.airQuality?.setAttribute(CarbonDioxideConcentrationMeasurement.Cluster.id, 'measuredValue', 400, this.airQuality.log);
1454
- await this.airQuality?.setAttribute(NitrogenDioxideConcentrationMeasurement.Cluster.id, 'measuredValue', 1, this.airQuality.log);
1455
- await this.airQuality?.setAttribute(OzoneConcentrationMeasurement.Cluster.id, 'measuredValue', 1, this.airQuality.log);
1456
- await this.airQuality?.setAttribute(FormaldehydeConcentrationMeasurement.Cluster.id, 'measuredValue', 1, this.airQuality.log);
1457
- await this.airQuality?.setAttribute(Pm1ConcentrationMeasurement.Cluster.id, 'measuredValue', 100, this.airQuality.log);
1458
- await this.airQuality?.setAttribute(Pm25ConcentrationMeasurement.Cluster.id, 'measuredValue', 100, this.airQuality.log);
1459
- await this.airQuality?.setAttribute(Pm10ConcentrationMeasurement.Cluster.id, 'measuredValue', 100, this.airQuality.log);
1460
- await this.airQuality?.setAttribute(RadonConcentrationMeasurement.Cluster.id, 'measuredValue', 100, this.airQuality.log);
1461
- await this.airQuality?.setAttribute(TotalVolatileOrganicCompoundsConcentrationMeasurement.Cluster.id, 'measuredValue', 100, this.airQuality.log);
1462
- }
1238
+ await this.airQuality?.setAttribute(CarbonMonoxideConcentrationMeasurement.Cluster.id, 'measuredValue', 10, this.airQuality.log);
1239
+ await this.airQuality?.setAttribute(CarbonDioxideConcentrationMeasurement.Cluster.id, 'measuredValue', 400, this.airQuality.log);
1240
+ await this.airQuality?.setAttribute(NitrogenDioxideConcentrationMeasurement.Cluster.id, 'measuredValue', 1, this.airQuality.log);
1241
+ await this.airQuality?.setAttribute(OzoneConcentrationMeasurement.Cluster.id, 'measuredValue', 1, this.airQuality.log);
1242
+ await this.airQuality?.setAttribute(FormaldehydeConcentrationMeasurement.Cluster.id, 'measuredValue', 1, this.airQuality.log);
1243
+ await this.airQuality?.setAttribute(Pm1ConcentrationMeasurement.Cluster.id, 'measuredValue', 100, this.airQuality.log);
1244
+ await this.airQuality?.setAttribute(Pm25ConcentrationMeasurement.Cluster.id, 'measuredValue', 100, this.airQuality.log);
1245
+ await this.airQuality?.setAttribute(Pm10ConcentrationMeasurement.Cluster.id, 'measuredValue', 100, this.airQuality.log);
1246
+ await this.airQuality?.setAttribute(RadonConcentrationMeasurement.Cluster.id, 'measuredValue', 100, this.airQuality.log);
1247
+ await this.airQuality?.setAttribute(TotalVolatileOrganicCompoundsConcentrationMeasurement.Cluster.id, 'measuredValue', 100, this.airQuality.log);
1463
1248
  if (this.config.useInterval) {
1464
1249
  this.airQualityInterval = setInterval(async () => {
1465
1250
  let value = this.airQuality?.getAttribute(AirQuality.Cluster.id, 'airQuality', this.airQuality?.log);
@@ -1540,4 +1325,17 @@ export class ExampleMatterbridgeDynamicPlatform extends MatterbridgeDynamicPlatf
1540
1325
  if (this.config.unregisterOnShutdown === true)
1541
1326
  await this.unregisterAllDevices(500);
1542
1327
  }
1328
+ async addDevice(device) {
1329
+ if (!device.serialNumber || !device.deviceName)
1330
+ return;
1331
+ this.setSelectDevice(device.serialNumber, device.deviceName, undefined, 'hub');
1332
+ if (this.validateDevice(device.deviceName)) {
1333
+ await this.registerDevice(device);
1334
+ this.bridgedDevices.set(device.deviceName, device);
1335
+ return device;
1336
+ }
1337
+ else {
1338
+ return undefined;
1339
+ }
1340
+ }
1543
1341
  }
@@ -1,12 +1,12 @@
1
1
  {
2
2
  "name": "matterbridge-example-dynamic-platform",
3
- "version": "1.3.4",
3
+ "version": "1.3.5-dev-20250723-2f335a4",
4
4
  "lockfileVersion": 3,
5
5
  "requires": true,
6
6
  "packages": {
7
7
  "": {
8
8
  "name": "matterbridge-example-dynamic-platform",
9
- "version": "1.3.4",
9
+ "version": "1.3.5-dev-20250723-2f335a4",
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.4",
3
+ "version": "1.3.5-dev-20250723-2f335a4",
4
4
  "description": "Matterbridge dynamic plugin",
5
5
  "author": "https://github.com/Luligu",
6
6
  "license": "Apache-2.0",