matterbridge-example-dynamic-platform 1.2.3 → 1.2.4-dev-20250612-926c70e

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
@@ -8,6 +8,23 @@ If you like this project and find it useful, please consider giving it a star on
8
8
  <img src="bmc-button.svg" alt="Buy me a coffee" width="120">
9
9
  </a>
10
10
 
11
+ ## [1.2.4] - 2025-06-11
12
+
13
+ ### Added
14
+
15
+ - [npm]: The dev of matterbridge-example-dynamic-platform is published with tag **dev** on **npm** each day at 00:00 UTC if there is a new commit.
16
+
17
+ ### Changed
18
+
19
+ - [package]: Require matterbridge 3.0.6.
20
+ - [package]: Updated package.
21
+ - [package]: Updated dependencies.
22
+ - [subscribe]: Prevent attribute setting when offline for air purifier and fan.
23
+
24
+ <a href="https://www.buymeacoffee.com/luligugithub">
25
+ <img src="bmc-button.svg" alt="Buy me a coffee" width="80">
26
+ </a>
27
+
11
28
  ## [1.2.3] - 2025-05-25
12
29
 
13
30
  ### Added
@@ -276,12 +276,12 @@ export class Appliances extends MatterbridgeEndpoint {
276
276
  class MatterbridgeLevelTemperatureControlServer extends TemperatureControlBehavior.with(TemperatureControl.Feature.TemperatureLevel) {
277
277
  initialize() {
278
278
  if (this.state.supportedTemperatureLevels.length >= 2) {
279
- const device = this.endpoint.stateOf(MatterbridgeServer).deviceCommand;
279
+ const device = this.endpoint.stateOf(MatterbridgeServer);
280
280
  device.log.info('MatterbridgeLevelTemperatureControlServer initialized');
281
281
  }
282
282
  }
283
283
  setTemperature(request) {
284
- const device = this.endpoint.stateOf(MatterbridgeServer).deviceCommand;
284
+ const device = this.endpoint.stateOf(MatterbridgeServer);
285
285
  if (request.targetTemperatureLevel !== undefined && request.targetTemperatureLevel >= 0 && request.targetTemperatureLevel < this.state.supportedTemperatureLevels.length) {
286
286
  device.log.info(`MatterbridgeLevelTemperatureControlServer: setTemperature called setting selectedTemperatureLevel to ${request.targetTemperatureLevel}: ${this.state.supportedTemperatureLevels[request.targetTemperatureLevel]}`);
287
287
  this.state.selectedTemperatureLevel = request.targetTemperatureLevel;
@@ -293,11 +293,11 @@ class MatterbridgeLevelTemperatureControlServer extends TemperatureControlBehavi
293
293
  }
294
294
  class MatterbridgeNumberTemperatureControlServer extends TemperatureControlBehavior.with(TemperatureControl.Feature.TemperatureNumber) {
295
295
  initialize() {
296
- const device = this.endpoint.stateOf(MatterbridgeServer).deviceCommand;
296
+ const device = this.endpoint.stateOf(MatterbridgeServer);
297
297
  device.log.info('MatterbridgeNumberTemperatureControlServer initialized');
298
298
  }
299
299
  setTemperature(request) {
300
- const device = this.endpoint.stateOf(MatterbridgeServer).deviceCommand;
300
+ const device = this.endpoint.stateOf(MatterbridgeServer);
301
301
  if (request.targetTemperature !== undefined && request.targetTemperature >= this.state.minTemperature && request.targetTemperature <= this.state.maxTemperature) {
302
302
  device.log.info(`MatterbridgeNumberTemperatureControlServer: setTemperature called setting temperatureSetpoint to ${request.targetTemperature}`);
303
303
  this.state.temperatureSetpoint = request.targetTemperature;
@@ -309,11 +309,11 @@ class MatterbridgeNumberTemperatureControlServer extends TemperatureControlBehav
309
309
  }
310
310
  class MatterbridgeMicrowaveOvenControlServer extends MicrowaveOvenControlBehavior.with(MicrowaveOvenControl.Feature.PowerInWatts) {
311
311
  initialize() {
312
- const device = this.endpoint.stateOf(MatterbridgeServer).deviceCommand;
312
+ const device = this.endpoint.stateOf(MatterbridgeServer);
313
313
  device.log.info('MatterbridgeMicrowaveOvenControlServer initialized');
314
314
  }
315
315
  setCookingParameters(request) {
316
- const device = this.endpoint.stateOf(MatterbridgeServer).deviceCommand;
316
+ const device = this.endpoint.stateOf(MatterbridgeServer);
317
317
  if (request.cookMode !== undefined) {
318
318
  device.log.info(`MatterbridgeMicrowaveOvenControlServer: setCookingParameters called setting cookMode to ${request.cookMode}`);
319
319
  this.endpoint.setStateOf(MicrowaveOvenModeServer, { currentMode: request.cookMode });
@@ -340,7 +340,7 @@ class MatterbridgeMicrowaveOvenControlServer extends MicrowaveOvenControlBehavio
340
340
  }
341
341
  }
342
342
  addMoreTime(request) {
343
- const device = this.endpoint.stateOf(MatterbridgeServer).deviceCommand;
343
+ const device = this.endpoint.stateOf(MatterbridgeServer);
344
344
  if (request.timeToAdd !== undefined && request.timeToAdd >= 0) {
345
345
  device.log.info(`MatterbridgeMicrowaveOvenControlServer: addMoreTime called setting cookTime to ${this.state.cookTime + request.timeToAdd}`);
346
346
  this.state.cookTime += request.timeToAdd;
@@ -352,13 +352,13 @@ class MatterbridgeMicrowaveOvenControlServer extends MicrowaveOvenControlBehavio
352
352
  }
353
353
  export class MatterbridgeOvenCavityOperationalStateServer extends OvenCavityOperationalStateBehavior {
354
354
  initialize() {
355
- const device = this.endpoint.stateOf(MatterbridgeServer).deviceCommand;
355
+ const device = this.endpoint.stateOf(MatterbridgeServer);
356
356
  device.log.info('OvenCavityOperationalStateServer initialized: setting operational state to Stopped and operational error to No error');
357
357
  this.state.operationalState = OperationalState.OperationalStateEnum.Stopped;
358
358
  this.state.operationalError = { errorStateId: OperationalState.ErrorState.NoError, errorStateLabel: 'No error', errorStateDetails: 'Fully operational' };
359
359
  }
360
360
  stop() {
361
- const device = this.endpoint.stateOf(MatterbridgeServer).deviceCommand;
361
+ const device = this.endpoint.stateOf(MatterbridgeServer);
362
362
  device.log.info('OvenCavityOperationalStateServer: stop called setting operational state to Stopped and operational error to No error');
363
363
  this.state.operationalState = OperationalState.OperationalStateEnum.Stopped;
364
364
  this.state.operationalError = { errorStateId: OperationalState.ErrorState.NoError, errorStateLabel: 'No error', errorStateDetails: 'Fully operational' };
@@ -367,7 +367,7 @@ export class MatterbridgeOvenCavityOperationalStateServer extends OvenCavityOper
367
367
  };
368
368
  }
369
369
  start() {
370
- const device = this.endpoint.stateOf(MatterbridgeServer).deviceCommand;
370
+ const device = this.endpoint.stateOf(MatterbridgeServer);
371
371
  device.log.info('OvenCavityOperationalStateServer: start called setting operational state to Running and operational error to No error');
372
372
  this.state.operationalState = OperationalState.OperationalStateEnum.Running;
373
373
  this.state.operationalError = { errorStateId: OperationalState.ErrorState.NoError, errorStateLabel: 'No error', errorStateDetails: 'Fully operational' };
@@ -378,12 +378,12 @@ export class MatterbridgeOvenCavityOperationalStateServer extends OvenCavityOper
378
378
  }
379
379
  class MatterbridgeRefrigeratorAndTemperatureControlledCabinetModeServer extends RefrigeratorAndTemperatureControlledCabinetModeBehavior {
380
380
  initialize() {
381
- const device = this.endpoint.stateOf(MatterbridgeServer).deviceCommand;
381
+ const device = this.endpoint.stateOf(MatterbridgeServer);
382
382
  device.log.info('MatterbridgeRefrigeratorAndTemperatureControlledCabinetModeServer initialized: setting currentMode to 1');
383
383
  this.state.currentMode = 1;
384
384
  }
385
385
  changeToMode(request) {
386
- const device = this.endpoint.stateOf(MatterbridgeServer).deviceCommand;
386
+ const device = this.endpoint.stateOf(MatterbridgeServer);
387
387
  const supportedMode = this.state.supportedModes.find((supportedMode) => supportedMode.mode === request.newMode);
388
388
  if (supportedMode) {
389
389
  device.log.info(`MatterbridgeRefrigeratorAndTemperatureControlledCabinetModeServer: changeToMode called with mode ${supportedMode.mode} = ${supportedMode.label}`);
@@ -398,12 +398,12 @@ class MatterbridgeRefrigeratorAndTemperatureControlledCabinetModeServer extends
398
398
  }
399
399
  class MatterbridgeOvenModeServer extends OvenModeBehavior {
400
400
  initialize() {
401
- const device = this.endpoint.stateOf(MatterbridgeServer).deviceCommand;
401
+ const device = this.endpoint.stateOf(MatterbridgeServer);
402
402
  device.log.info('OvenModeServer initialized: setting currentMode to 3');
403
403
  this.state.currentMode = 3;
404
404
  }
405
405
  changeToMode(request) {
406
- const device = this.endpoint.stateOf(MatterbridgeServer).deviceCommand;
406
+ const device = this.endpoint.stateOf(MatterbridgeServer);
407
407
  const supportedMode = this.state.supportedModes.find((supportedMode) => supportedMode.mode === request.newMode);
408
408
  if (supportedMode) {
409
409
  device.log.info(`OvenModeServer: changeToMode called with mode ${supportedMode.mode} = ${supportedMode.label}`);
@@ -418,20 +418,20 @@ class MatterbridgeOvenModeServer extends OvenModeBehavior {
418
418
  }
419
419
  class MatterbridgeDishwasherModeServer extends DishwasherModeBehavior {
420
420
  initialize() {
421
- const device = this.endpoint.stateOf(MatterbridgeServer).deviceCommand;
421
+ const device = this.endpoint.stateOf(MatterbridgeServer);
422
422
  device.log.info('DishwasherModeServer initialized: setting currentMode to 3');
423
423
  this.state.currentMode = 2;
424
424
  this.reactTo(this.agent.get(MatterbridgeOnOffServer).events.onOff$Changed, this.handleOnOffChange);
425
425
  }
426
426
  handleOnOffChange(onOff) {
427
- const device = this.endpoint.stateOf(MatterbridgeServer).deviceCommand;
427
+ const device = this.endpoint.stateOf(MatterbridgeServer);
428
428
  if (onOff === false) {
429
429
  device.log.info('***OnOffServer changed to OFF: setting Dead Front state to Manufacturer Specific');
430
430
  this.state.currentMode = 2;
431
431
  }
432
432
  }
433
433
  changeToMode(request) {
434
- const device = this.endpoint.stateOf(MatterbridgeServer).deviceCommand;
434
+ const device = this.endpoint.stateOf(MatterbridgeServer);
435
435
  const supportedMode = this.state.supportedModes.find((supportedMode) => supportedMode.mode === request.newMode);
436
436
  if (supportedMode) {
437
437
  device.log.info(`DishwasherModeServer: changeToMode called with mode ${supportedMode.mode} = ${supportedMode.label}`);
@@ -446,20 +446,20 @@ class MatterbridgeDishwasherModeServer extends DishwasherModeBehavior {
446
446
  }
447
447
  class MatterbridgeLaundryWasherModeServer extends LaundryWasherModeBehavior {
448
448
  initialize() {
449
- const device = this.endpoint.stateOf(MatterbridgeServer).deviceCommand;
449
+ const device = this.endpoint.stateOf(MatterbridgeServer);
450
450
  device.log.info('LaundryWasherModeServer initialized: setting currentMode to 3');
451
451
  this.state.currentMode = 2;
452
452
  this.reactTo(this.agent.get(MatterbridgeOnOffServer).events.onOff$Changed, this.handleOnOffChange);
453
453
  }
454
454
  handleOnOffChange(onOff) {
455
- const device = this.endpoint.stateOf(MatterbridgeServer).deviceCommand;
455
+ const device = this.endpoint.stateOf(MatterbridgeServer);
456
456
  if (onOff === false) {
457
457
  device.log.notice('OnOffServer changed to OFF: setting Dead Front state to Manufacturer Specific');
458
458
  this.state.currentMode = 2;
459
459
  }
460
460
  }
461
461
  changeToMode(request) {
462
- const device = this.endpoint.stateOf(MatterbridgeServer).deviceCommand;
462
+ const device = this.endpoint.stateOf(MatterbridgeServer);
463
463
  const supportedMode = this.state.supportedModes.find((supportedMode) => supportedMode.mode === request.newMode);
464
464
  if (supportedMode) {
465
465
  device.log.info(`LaundryWasherModeServer: changeToMode called with mode ${supportedMode.mode} = ${supportedMode.label}`);
package/dist/platform.js CHANGED
@@ -59,8 +59,8 @@ export class ExampleMatterbridgeDynamicPlatform extends MatterbridgeDynamicPlatf
59
59
  fanModeLookup = ['Off', 'Low', 'Medium', 'High', 'On', 'Auto', 'Smart'];
60
60
  constructor(matterbridge, log, config) {
61
61
  super(matterbridge, log, config);
62
- if (this.verifyMatterbridgeVersion === undefined || typeof this.verifyMatterbridgeVersion !== 'function' || !this.verifyMatterbridgeVersion('3.0.5')) {
63
- throw new Error(`This plugin requires Matterbridge version >= "3.0.5". Please update Matterbridge from ${this.matterbridge.matterbridgeVersion} to the latest version in the frontend.`);
62
+ if (this.verifyMatterbridgeVersion === undefined || typeof this.verifyMatterbridgeVersion !== 'function' || !this.verifyMatterbridgeVersion('3.0.6')) {
63
+ throw new Error(`This plugin requires Matterbridge version >= "3.0.6". Please update Matterbridge from ${this.matterbridge.matterbridgeVersion} to the latest version in the frontend.`);
64
64
  }
65
65
  this.log.info('Initializing platform:', this.config.name);
66
66
  if (config.whiteList === undefined)
@@ -673,6 +673,8 @@ export class ExampleMatterbridgeDynamicPlatform extends MatterbridgeDynamicPlatf
673
673
  });
674
674
  await this.airPurifier?.subscribeAttribute(FanControl.Cluster.id, 'fanMode', (newValue, oldValue, context) => {
675
675
  this.airPurifier?.log.info(`Fan mode changed from ${this.fanModeLookup[oldValue]} to ${this.fanModeLookup[newValue]} context: ${context.offline === true ? 'offline' : 'online'}`);
676
+ if (context.offline === true)
677
+ return;
676
678
  if (newValue === FanControl.FanMode.Off) {
677
679
  this.airPurifier?.setAttribute(FanControl.Cluster.id, 'percentCurrent', 0, this.airPurifier?.log);
678
680
  }
@@ -691,6 +693,8 @@ export class ExampleMatterbridgeDynamicPlatform extends MatterbridgeDynamicPlatf
691
693
  }, this.airPurifier.log);
692
694
  await this.airPurifier?.subscribeAttribute(FanControl.Cluster.id, 'percentSetting', (newValue, oldValue, context) => {
693
695
  this.airPurifier?.log.info(`Percent setting changed from ${oldValue} to ${newValue} context: ${context.offline === true ? 'offline' : 'online'}`);
696
+ if (context.offline === true)
697
+ return;
694
698
  if (isValidNumber(newValue, 0, 100))
695
699
  this.airPurifier?.setAttribute(FanControl.Cluster.id, 'percentCurrent', newValue, this.airPurifier?.log);
696
700
  }, this.airPurifier.log);
@@ -721,7 +725,6 @@ export class ExampleMatterbridgeDynamicPlatform extends MatterbridgeDynamicPlatf
721
725
  await this.airConditioner?.setAttribute(ThermostatCluster.id, 'localTemperature', 20 * 100, this.airConditioner?.log);
722
726
  await this.airConditioner?.setAttribute(TemperatureMeasurement.Cluster.id, 'measuredValue', 20 * 100, this.airConditioner?.log);
723
727
  await this.airConditioner?.setAttribute(RelativeHumidityMeasurementCluster.id, 'measuredValue', 50 * 100, this.airConditioner?.log);
724
- await this.airConditioner?.setAttribute(FanControl.Cluster.id, 'speedSetting', 50, this.airConditioner?.log);
725
728
  await this.airConditioner?.setAttribute(FanControl.Cluster.id, 'percentSetting', 50, this.airConditioner?.log);
726
729
  });
727
730
  this.airConditioner?.addCommandHandler('off', async () => {
@@ -729,7 +732,6 @@ export class ExampleMatterbridgeDynamicPlatform extends MatterbridgeDynamicPlatf
729
732
  await this.airConditioner?.setAttribute(ThermostatCluster.id, 'localTemperature', null, this.airConditioner?.log);
730
733
  await this.airConditioner?.setAttribute(TemperatureMeasurement.Cluster.id, 'measuredValue', null, this.airConditioner?.log);
731
734
  await this.airConditioner?.setAttribute(RelativeHumidityMeasurementCluster.id, 'measuredValue', null, this.airConditioner?.log);
732
- await this.airConditioner?.setAttribute(FanControl.Cluster.id, 'speedSetting', null, this.airConditioner?.log);
733
735
  await this.airConditioner?.setAttribute(FanControl.Cluster.id, 'percentSetting', null, this.airConditioner?.log);
734
736
  });
735
737
  this.pump = new MatterbridgeEndpoint([pumpDevice, bridgedNode, powerSource], { uniqueStorageKey: 'Pump' }, this.config.debug)
@@ -792,6 +794,8 @@ export class ExampleMatterbridgeDynamicPlatform extends MatterbridgeDynamicPlatf
792
794
  }
793
795
  await this.fan?.subscribeAttribute(FanControl.Cluster.id, 'fanMode', (newValue, oldValue, context) => {
794
796
  this.fan?.log.info(`Fan mode changed from ${this.fanModeLookup[oldValue]} to ${this.fanModeLookup[newValue]} context: ${context.offline === true ? 'offline' : 'online'}`);
797
+ if (context.offline === true)
798
+ return;
795
799
  if (newValue === FanControl.FanMode.Off) {
796
800
  this.fan?.setAttribute(FanControl.Cluster.id, 'percentSetting', 0, this.fan?.log);
797
801
  this.fan?.setAttribute(FanControl.Cluster.id, 'percentCurrent', 0, this.fan?.log);
@@ -819,14 +823,11 @@ export class ExampleMatterbridgeDynamicPlatform extends MatterbridgeDynamicPlatf
819
823
  }, this.fan.log);
820
824
  await this.fan?.subscribeAttribute(FanControl.Cluster.id, 'percentSetting', (newValue, oldValue, context) => {
821
825
  this.fan?.log.info(`Percent setting changed from ${oldValue} to ${newValue} context: ${context.offline === true ? 'offline' : 'online'}`);
826
+ if (context.offline === true)
827
+ return;
822
828
  if (isValidNumber(newValue, 0, 100))
823
829
  this.fan?.setAttribute(FanControl.Cluster.id, 'percentCurrent', newValue, this.fan?.log);
824
830
  }, this.fan.log);
825
- await this.fan?.subscribeAttribute(FanControl.Cluster.id, 'speedSetting', (newValue, oldValue, context) => {
826
- this.fan?.log.info(`Speed setting changed from ${oldValue} to ${newValue} context: ${context.offline === true ? 'offline' : 'online'}`);
827
- if (isValidNumber(newValue, 0, 100))
828
- this.fan?.setAttribute(FanControl.Cluster.id, 'speedCurrent', newValue, this.fan?.log);
829
- }, this.fan.log);
830
831
  this.waterLeak = new MatterbridgeEndpoint([waterLeakDetector, bridgedNode, powerSource], { uniqueStorageKey: 'Water leak detector' }, this.config.debug)
831
832
  .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)
832
833
  .createDefaultPowerSourceRechargeableBatteryClusterServer()
@@ -1209,12 +1210,10 @@ export class ExampleMatterbridgeDynamicPlatform extends MatterbridgeDynamicPlatf
1209
1210
  }
1210
1211
  }, 60 * 1000 + 550);
1211
1212
  }
1212
- this.fan?.log.info('Set fan initial fanMode to Auto, percentCurrent and percentSetting to 50 and speedCurrent and speedSetting to 50');
1213
+ this.fan?.log.info('Set fan initial fanMode to Auto, percentCurrent and percentSetting to 50');
1213
1214
  await this.fan?.setAttribute(FanControl.Cluster.id, 'fanMode', FanControl.FanMode.Auto, this.fan.log);
1214
1215
  await this.fan?.setAttribute(FanControl.Cluster.id, 'percentCurrent', 50, this.fan.log);
1215
1216
  await this.fan?.setAttribute(FanControl.Cluster.id, 'percentSetting', 50, this.fan.log);
1216
- await this.fan?.setAttribute(FanControl.Cluster.id, 'speedCurrent', 50, this.fan.log);
1217
- await this.fan?.setAttribute(FanControl.Cluster.id, 'speedSetting', 50, this.fan.log);
1218
1217
  if (this.config.useInterval) {
1219
1218
  this.fanInterval = setInterval(async () => {
1220
1219
  const mode = this.fan?.getAttribute(FanControl.Cluster.id, 'fanMode', this.fan.log);
@@ -1,12 +1,12 @@
1
1
  {
2
2
  "name": "matterbridge-example-dynamic-platform",
3
- "version": "1.2.3",
3
+ "version": "1.2.4-dev-20250612-926c70e",
4
4
  "lockfileVersion": 3,
5
5
  "requires": true,
6
6
  "packages": {
7
7
  "": {
8
8
  "name": "matterbridge-example-dynamic-platform",
9
- "version": "1.2.3",
9
+ "version": "1.2.4-dev-20250612-926c70e",
10
10
  "license": "MIT",
11
11
  "dependencies": {
12
12
  "node-ansi-logger": "3.0.1",
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "matterbridge-example-dynamic-platform",
3
- "version": "1.2.3",
3
+ "version": "1.2.4-dev-20250612-926c70e",
4
4
  "description": "Matterbridge dynamic plugin",
5
5
  "author": "https://github.com/Luligu",
6
6
  "license": "MIT",