matterbridge-example-dynamic-platform 1.2.2 → 1.2.3

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,10 +8,27 @@ 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.2] - 2025-05-19
11
+ ## [1.2.3] - 2025-05-25
12
+
13
+ ### Added
14
+
15
+ - [platform]: Added a cover device with both lift and tilt (supported by the Home app).
16
+ - [platform]: Added evse (EV charger) device type (not supported by the Home app).
12
17
 
13
18
  ### Changed
14
19
 
20
+ - [package]: Require matterbridge 3.0.5.
21
+ - [package]: Updated package.
22
+ - [package]: Updated dependencies.
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
+
28
+ ## [1.2.2] - 2025-05-19
29
+
30
+ ### Added
31
+
15
32
  - [package]: Added waterHeater device type (not supported by Alexa and Apple Home)
16
33
 
17
34
  ### Changed
package/README.md CHANGED
@@ -16,7 +16,7 @@
16
16
 
17
17
  Matterbridge dynamic platform example plugin is a template to develop your own plugin using the dynamic platform.
18
18
 
19
- It exposes 38 devices:
19
+ It exposes 41 virtual devices:
20
20
 
21
21
  - a switch with onOff cluster
22
22
  - a light with onOff
@@ -26,7 +26,8 @@ It exposes 38 devices:
26
26
  - a light with onOff, levelControl and colorControl (with XY and CT) clusters
27
27
  - a light with onOff, levelControl and colorControl (with CT only) clusters
28
28
  - an outlet (plug) with onOff cluster
29
- - a cover with windowCovering cluster
29
+ - a cover with windowCovering cluster and lift feature
30
+ - a cover with windowCovering cluster and both lift and tilt features
30
31
  - a lock with doorLock cluster
31
32
  - a thermo autoMode (i.e. with Auto Heat and Cool features) with thermostat cluster and 3 sub endpoints with flowMeasurement cluster, temperatureMeasurement cluster
32
33
  and relativeHumidityMeasurement cluster (to show how to create a composed device with sub endpoints)
@@ -58,6 +59,7 @@ It exposes 38 devices:
58
59
  - an extractor Hood device (supported by SmartThings, Alexa and Home Assistant)
59
60
  - a cooktop device (supported by SmartThings, Alexa and Home Assistant)
60
61
  - a water heater device (supported by SmartThings and Home Assistant)
62
+ - a car charger device (supported by Home Assistant)
61
63
 
62
64
  All these devices continuously change state and position. The plugin also shows how to use all the command handlers (you can control all the devices), how to subscribe to attributes and how to trigger events.
63
65
 
@@ -1,7 +1,7 @@
1
1
  import { MatterbridgeEndpoint, MatterbridgeServer, MatterbridgeOnOffServer, laundryWasher, laundryDryer, dishwasher, refrigerator, temperatureControlledCabinetCooler, oven, temperatureControlledCabinetHeater, microwaveOven, extractorHood, cooktop, cookSurface, powerSource, } from 'matterbridge';
2
- import { ClusterBehavior, PositionTag, RefrigeratorTag } from 'matterbridge/matter';
3
- import { OperationalState, TemperatureControl, DishwasherMode, LaundryWasherControls, LaundryWasherMode, LaundryDryerControls, OvenMode, ModeBase, RefrigeratorAndTemperatureControlledCabinetMode, MicrowaveOvenMode, MicrowaveOvenControl, OvenCavityOperationalState, } from 'matterbridge/matter/clusters';
4
- import { DishwasherAlarmServer, LaundryDryerControlsServer, LaundryWasherControlsServer, MicrowaveOvenControlBehavior, MicrowaveOvenModeServer, TemperatureControlBehavior, } from 'matterbridge/matter/behaviors';
2
+ import { PositionTag, RefrigeratorTag } from 'matterbridge/matter';
3
+ import { OperationalState, TemperatureControl, DishwasherMode, LaundryWasherControls, LaundryWasherMode, LaundryDryerControls, OvenMode, ModeBase, RefrigeratorAndTemperatureControlledCabinetMode, MicrowaveOvenMode, MicrowaveOvenControl, } from 'matterbridge/matter/clusters';
4
+ import { DishwasherAlarmServer, DishwasherModeBehavior, LaundryDryerControlsServer, LaundryWasherControlsServer, LaundryWasherModeBehavior, MicrowaveOvenControlBehavior, MicrowaveOvenModeServer, OvenCavityOperationalStateBehavior, OvenModeBehavior, RefrigeratorAndTemperatureControlledCabinetModeBehavior, TemperatureControlBehavior, } from 'matterbridge/matter/behaviors';
5
5
  export class Appliances extends MatterbridgeEndpoint {
6
6
  constructor(deviceType, name, serial) {
7
7
  super([deviceType, powerSource], { uniqueStorageKey: `${name}-${serial}` }, true);
@@ -112,7 +112,7 @@ export class Appliances extends MatterbridgeEndpoint {
112
112
  }
113
113
  }
114
114
  createDefaultOvenCavityOperationalStateClusterServer(operationalState = OperationalState.OperationalStateEnum.Stopped) {
115
- this.behaviors.require(OvenCavityOperationalStateServer, {
115
+ this.behaviors.require(MatterbridgeOvenCavityOperationalStateServer, {
116
116
  phaseList: [],
117
117
  currentPhase: null,
118
118
  operationalStateList: [
@@ -126,7 +126,7 @@ export class Appliances extends MatterbridgeEndpoint {
126
126
  return this;
127
127
  }
128
128
  static createDefaultRefrigeratorAndTemperatureControlledCabinetModeClusterServer(endpoint, currentMode) {
129
- endpoint.behaviors.require(RefrigeratorAndTemperatureControlledCabinetModeServer, {
129
+ endpoint.behaviors.require(MatterbridgeRefrigeratorAndTemperatureControlledCabinetModeServer, {
130
130
  supportedModes: [
131
131
  { label: 'Auto', mode: 0, modeTags: [{ value: RefrigeratorAndTemperatureControlledCabinetMode.ModeTag.Auto }] },
132
132
  { label: 'RapidCool', mode: 1, modeTags: [{ value: RefrigeratorAndTemperatureControlledCabinetMode.ModeTag.RapidCool }] },
@@ -137,7 +137,7 @@ export class Appliances extends MatterbridgeEndpoint {
137
137
  return endpoint;
138
138
  }
139
139
  static createDefaultOvenModeClusterServer(endpoint, currentMode) {
140
- endpoint.behaviors.require(OvenModeServer, {
140
+ endpoint.behaviors.require(MatterbridgeOvenModeServer, {
141
141
  supportedModes: [
142
142
  { label: 'Bake', mode: 1, modeTags: [{ value: OvenMode.ModeTag.Bake }] },
143
143
  { label: 'Convection', mode: 2, modeTags: [{ value: OvenMode.ModeTag.Convection }] },
@@ -155,7 +155,7 @@ export class Appliances extends MatterbridgeEndpoint {
155
155
  return endpoint;
156
156
  }
157
157
  createDefaultDishwasherModeClusterServer(currentMode) {
158
- this.behaviors.require(DishwasherModeServer, {
158
+ this.behaviors.require(MatterbridgeDishwasherModeServer, {
159
159
  supportedModes: [
160
160
  { label: 'Light', mode: 1, modeTags: [{ value: DishwasherMode.ModeTag.Light }] },
161
161
  { label: 'Normal', mode: 2, modeTags: [{ value: DishwasherMode.ModeTag.Normal }] },
@@ -166,7 +166,7 @@ export class Appliances extends MatterbridgeEndpoint {
166
166
  return this;
167
167
  }
168
168
  createDefaultLaundryWasherModeClusterServer(currentMode) {
169
- this.behaviors.require(LaundryWasherModeServer, {
169
+ this.behaviors.require(MatterbridgeLaundryWasherModeServer, {
170
170
  supportedModes: [
171
171
  { label: 'Delicate', mode: 1, modeTags: [{ value: LaundryWasherMode.ModeTag.Delicate }] },
172
172
  { label: 'Normal', mode: 2, modeTags: [{ value: LaundryWasherMode.ModeTag.Normal }] },
@@ -350,8 +350,7 @@ class MatterbridgeMicrowaveOvenControlServer extends MicrowaveOvenControlBehavio
350
350
  }
351
351
  }
352
352
  }
353
- export const OvenCavityOperationalStateBehavior = ClusterBehavior.withInterface().for(OvenCavityOperationalState.Cluster);
354
- export class OvenCavityOperationalStateServer extends OvenCavityOperationalStateBehavior {
353
+ export class MatterbridgeOvenCavityOperationalStateServer extends OvenCavityOperationalStateBehavior {
355
354
  initialize() {
356
355
  const device = this.endpoint.stateOf(MatterbridgeServer).deviceCommand;
357
356
  device.log.info('OvenCavityOperationalStateServer initialized: setting operational state to Stopped and operational error to No error');
@@ -377,8 +376,7 @@ export class OvenCavityOperationalStateServer extends OvenCavityOperationalState
377
376
  };
378
377
  }
379
378
  }
380
- export const RefrigeratorAndTemperatureControlledCabinetModeBehavior = ClusterBehavior.withInterface().for(RefrigeratorAndTemperatureControlledCabinetMode.Cluster);
381
- class RefrigeratorAndTemperatureControlledCabinetModeServer extends RefrigeratorAndTemperatureControlledCabinetModeBehavior {
379
+ class MatterbridgeRefrigeratorAndTemperatureControlledCabinetModeServer extends RefrigeratorAndTemperatureControlledCabinetModeBehavior {
382
380
  initialize() {
383
381
  const device = this.endpoint.stateOf(MatterbridgeServer).deviceCommand;
384
382
  device.log.info('MatterbridgeRefrigeratorAndTemperatureControlledCabinetModeServer initialized: setting currentMode to 1');
@@ -398,8 +396,7 @@ class RefrigeratorAndTemperatureControlledCabinetModeServer extends Refrigerator
398
396
  }
399
397
  }
400
398
  }
401
- export const OvenModeBehavior = ClusterBehavior.withInterface().for(OvenMode.Cluster);
402
- class OvenModeServer extends OvenModeBehavior {
399
+ class MatterbridgeOvenModeServer extends OvenModeBehavior {
403
400
  initialize() {
404
401
  const device = this.endpoint.stateOf(MatterbridgeServer).deviceCommand;
405
402
  device.log.info('OvenModeServer initialized: setting currentMode to 3');
@@ -419,8 +416,7 @@ class OvenModeServer extends OvenModeBehavior {
419
416
  }
420
417
  }
421
418
  }
422
- export const DishwasherModeBehavior = ClusterBehavior.withInterface().for(DishwasherMode.Cluster);
423
- class DishwasherModeServer extends DishwasherModeBehavior {
419
+ class MatterbridgeDishwasherModeServer extends DishwasherModeBehavior {
424
420
  initialize() {
425
421
  const device = this.endpoint.stateOf(MatterbridgeServer).deviceCommand;
426
422
  device.log.info('DishwasherModeServer initialized: setting currentMode to 3');
@@ -448,8 +444,7 @@ class DishwasherModeServer extends DishwasherModeBehavior {
448
444
  }
449
445
  }
450
446
  }
451
- export const LaundryWasherModeBehavior = ClusterBehavior.withInterface().for(LaundryWasherMode.Cluster);
452
- class LaundryWasherModeServer extends LaundryWasherModeBehavior {
447
+ class MatterbridgeLaundryWasherModeServer extends LaundryWasherModeBehavior {
453
448
  initialize() {
454
449
  const device = this.endpoint.stateOf(MatterbridgeServer).deviceCommand;
455
450
  device.log.info('LaundryWasherModeServer initialized: setting currentMode to 3');
package/dist/platform.js CHANGED
@@ -1,7 +1,7 @@
1
- import { MatterbridgeEndpoint, MatterbridgeDynamicPlatform, airQualitySensor, bridgedNode, colorTemperatureLight, coverDevice, dimmableLight, doorLockDevice, fanDevice, flowSensor, humiditySensor, onOffLight, onOffOutlet, onOffSwitch, powerSource, rainSensor, smokeCoAlarm, temperatureSensor, thermostatDevice, waterFreezeDetector, waterLeakDetector, airPurifier, pumpDevice, waterValve, genericSwitch, airConditioner, laundryWasher, cooktop, extractorHood, microwaveOven, oven, refrigerator, dishwasher, laundryDryer, onOffMountedSwitch, dimmableMountedSwitch, extendedColorLight, RoboticVacuumCleaner, WaterHeater, } from 'matterbridge';
1
+ import { MatterbridgeEndpoint, MatterbridgeDynamicPlatform, airQualitySensor, bridgedNode, colorTemperatureLight, coverDevice, dimmableLight, doorLockDevice, fanDevice, flowSensor, humiditySensor, onOffLight, onOffOutlet, onOffSwitch, powerSource, rainSensor, smokeCoAlarm, temperatureSensor, thermostatDevice, waterFreezeDetector, waterLeakDetector, airPurifier, pumpDevice, waterValve, genericSwitch, airConditioner, laundryWasher, cooktop, extractorHood, microwaveOven, oven, refrigerator, dishwasher, laundryDryer, onOffMountedSwitch, dimmableMountedSwitch, extendedColorLight, RoboticVacuumCleaner, WaterHeater, Evse, } from 'matterbridge';
2
2
  import { isValidBoolean, isValidNumber } from 'matterbridge/utils';
3
3
  import { LocationTag } from 'matterbridge/matter';
4
- 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, } from 'matterbridge/matter/clusters';
4
+ 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, } from 'matterbridge/matter/clusters';
5
5
  import { Appliances } from './appliances.js';
6
6
  export class ExampleMatterbridgeDynamicPlatform extends MatterbridgeDynamicPlatform {
7
7
  switch;
@@ -14,7 +14,8 @@ export class ExampleMatterbridgeDynamicPlatform extends MatterbridgeDynamicPlatf
14
14
  lightHS;
15
15
  lightCT;
16
16
  outlet;
17
- cover;
17
+ coverLift;
18
+ coverLiftTilt;
18
19
  lock;
19
20
  thermoAuto;
20
21
  thermoHeat;
@@ -34,7 +35,8 @@ export class ExampleMatterbridgeDynamicPlatform extends MatterbridgeDynamicPlatf
34
35
  momentarySwitch;
35
36
  latchingSwitch;
36
37
  vacuum;
37
- heater;
38
+ waterHeater;
39
+ evse;
38
40
  switchInterval;
39
41
  lightInterval;
40
42
  outletInterval;
@@ -57,8 +59,8 @@ export class ExampleMatterbridgeDynamicPlatform extends MatterbridgeDynamicPlatf
57
59
  fanModeLookup = ['Off', 'Low', 'Medium', 'High', 'On', 'Auto', 'Smart'];
58
60
  constructor(matterbridge, log, config) {
59
61
  super(matterbridge, log, config);
60
- if (this.verifyMatterbridgeVersion === undefined || typeof this.verifyMatterbridgeVersion !== 'function' || !this.verifyMatterbridgeVersion('3.0.3')) {
61
- throw new Error(`This plugin requires Matterbridge version >= "3.0.3". 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.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
64
  }
63
65
  this.log.info('Initializing platform:', this.config.name);
64
66
  if (config.whiteList === undefined)
@@ -432,41 +434,76 @@ export class ExampleMatterbridgeDynamicPlatform extends MatterbridgeDynamicPlatf
432
434
  await this.outlet?.setAttribute(OnOff.Cluster.id, 'onOff', false, this.outlet?.log);
433
435
  this.outlet?.log.info('Command off called');
434
436
  });
435
- this.cover = new MatterbridgeEndpoint([coverDevice, bridgedNode, powerSource], { uniqueStorageKey: 'Cover' }, this.config.debug)
437
+ this.coverLift = new MatterbridgeEndpoint([coverDevice, bridgedNode, powerSource], { uniqueStorageKey: 'CoverLift' }, this.config.debug)
436
438
  .createDefaultIdentifyClusterServer()
437
439
  .createDefaultGroupsClusterServer()
438
- .createDefaultBridgedDeviceBasicInformationClusterServer('Cover', '0x01020564', 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)
440
+ .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)
439
441
  .createDefaultWindowCoveringClusterServer()
440
442
  .createDefaultPowerSourceRechargeableBatteryClusterServer(86);
441
- this.setSelectDevice(this.cover.serialNumber ?? '', this.cover.deviceName ?? '', undefined, 'hub');
442
- if (this.validateDevice(this.cover.deviceName ?? '')) {
443
- await this.registerDevice(this.cover);
444
- this.bridgedDevices.set(this.cover.deviceName ?? '', this.cover);
443
+ this.setSelectDevice(this.coverLift.serialNumber ?? '', this.coverLift.deviceName ?? '', undefined, 'hub');
444
+ if (this.validateDevice(this.coverLift.deviceName ?? '')) {
445
+ await this.registerDevice(this.coverLift);
446
+ this.bridgedDevices.set(this.coverLift.deviceName ?? '', this.coverLift);
445
447
  }
446
448
  else {
447
- this.cover = undefined;
449
+ this.coverLift = undefined;
448
450
  }
449
- this.cover?.subscribeAttribute(WindowCovering.Cluster.id, 'mode', (newValue, oldValue) => {
450
- this.cover?.log.info(`Attribute mode changed from ${oldValue} to ${newValue}. Reverse: ${newValue.motorDirectionReversed}. Calibration: ${newValue.calibrationMode}. Maintenance: ${newValue.maintenanceMode}. LED: ${newValue.ledFeedback}`);
451
- }, this.cover.log);
452
- this.cover?.addCommandHandler('identify', async ({ request: { identifyTime } }) => {
453
- this.cover?.log.info(`Command identify called identifyTime:${identifyTime}`);
451
+ this.coverLift?.addCommandHandler('identify', async ({ request: { identifyTime } }) => {
452
+ this.coverLift?.log.info(`Command identify called identifyTime:${identifyTime}`);
454
453
  });
455
- this.cover?.addCommandHandler('stopMotion', async () => {
456
- await this.cover?.setWindowCoveringTargetAsCurrentAndStopped();
457
- this.cover?.log.info(`Command stopMotion called`);
454
+ this.coverLift?.addCommandHandler('stopMotion', async () => {
455
+ await this.coverLift?.setWindowCoveringTargetAsCurrentAndStopped();
456
+ this.coverLift?.log.info(`Command stopMotion called`);
458
457
  });
459
- this.cover?.addCommandHandler('downOrClose', async () => {
460
- await this.cover?.setWindowCoveringCurrentTargetStatus(10000, 10000, WindowCovering.MovementStatus.Stopped);
461
- this.cover?.log.info(`Command downOrClose called`);
458
+ this.coverLift?.addCommandHandler('downOrClose', async () => {
459
+ await this.coverLift?.setWindowCoveringCurrentTargetStatus(10000, 10000, WindowCovering.MovementStatus.Stopped);
460
+ this.coverLift?.log.info(`Command downOrClose called`);
462
461
  });
463
- this.cover?.addCommandHandler('upOrOpen', async () => {
464
- await this.cover?.setWindowCoveringCurrentTargetStatus(0, 0, WindowCovering.MovementStatus.Stopped);
465
- this.cover?.log.info(`Command upOrOpen called`);
462
+ this.coverLift?.addCommandHandler('upOrOpen', async () => {
463
+ await this.coverLift?.setWindowCoveringCurrentTargetStatus(0, 0, WindowCovering.MovementStatus.Stopped);
464
+ this.coverLift?.log.info(`Command upOrOpen called`);
466
465
  });
467
- this.cover?.addCommandHandler('goToLiftPercentage', async ({ request: { liftPercent100thsValue } }) => {
468
- await this.cover?.setWindowCoveringCurrentTargetStatus(liftPercent100thsValue, liftPercent100thsValue, WindowCovering.MovementStatus.Stopped);
469
- this.cover?.log.info(`Command goToLiftPercentage ${liftPercent100thsValue} called`);
466
+ this.coverLift?.addCommandHandler('goToLiftPercentage', async ({ request: { liftPercent100thsValue } }) => {
467
+ await this.coverLift?.setWindowCoveringCurrentTargetStatus(liftPercent100thsValue, liftPercent100thsValue, WindowCovering.MovementStatus.Stopped);
468
+ this.coverLift?.log.info(`Command goToLiftPercentage ${liftPercent100thsValue} called`);
469
+ });
470
+ this.coverLiftTilt = new MatterbridgeEndpoint([coverDevice, bridgedNode, powerSource], { uniqueStorageKey: 'CoverLiftTilt' }, this.config.debug)
471
+ .createDefaultIdentifyClusterServer()
472
+ .createDefaultGroupsClusterServer()
473
+ .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)
474
+ .createDefaultLiftTiltWindowCoveringClusterServer()
475
+ .createDefaultPowerSourceRechargeableBatteryClusterServer(86);
476
+ this.setSelectDevice(this.coverLiftTilt.serialNumber ?? '', this.coverLiftTilt.deviceName ?? '', undefined, 'hub');
477
+ if (this.validateDevice(this.coverLiftTilt.deviceName ?? '')) {
478
+ await this.registerDevice(this.coverLiftTilt);
479
+ this.bridgedDevices.set(this.coverLiftTilt.deviceName ?? '', this.coverLiftTilt);
480
+ }
481
+ else {
482
+ this.coverLiftTilt = undefined;
483
+ }
484
+ this.coverLiftTilt?.addCommandHandler('identify', async ({ request: { identifyTime } }) => {
485
+ this.coverLiftTilt?.log.info(`Command identify called identifyTime:${identifyTime}`);
486
+ });
487
+ this.coverLiftTilt?.addCommandHandler('stopMotion', async () => {
488
+ await this.coverLiftTilt?.setWindowCoveringTargetAsCurrentAndStopped();
489
+ this.coverLiftTilt?.log.info(`Command stopMotion called`);
490
+ });
491
+ this.coverLiftTilt?.addCommandHandler('downOrClose', async () => {
492
+ await this.coverLiftTilt?.setWindowCoveringCurrentTargetStatus(10000, 10000, WindowCovering.MovementStatus.Stopped);
493
+ this.coverLiftTilt?.log.info(`Command downOrClose called`);
494
+ });
495
+ this.coverLiftTilt?.addCommandHandler('upOrOpen', async () => {
496
+ await this.coverLiftTilt?.setWindowCoveringCurrentTargetStatus(0, 0, WindowCovering.MovementStatus.Stopped);
497
+ this.coverLiftTilt?.log.info(`Command upOrOpen called`);
498
+ });
499
+ this.coverLiftTilt?.addCommandHandler('goToLiftPercentage', async ({ request: { liftPercent100thsValue } }) => {
500
+ await this.coverLiftTilt?.setWindowCoveringCurrentTargetStatus(liftPercent100thsValue, liftPercent100thsValue, WindowCovering.MovementStatus.Stopped);
501
+ this.coverLiftTilt?.log.info(`Command goToLiftPercentage ${liftPercent100thsValue} called`);
502
+ });
503
+ this.coverLiftTilt?.addCommandHandler('goToTiltPercentage', async ({ request: { tiltPercent100thsValue } }) => {
504
+ const position = this.coverLiftTilt?.getAttribute(WindowCovering.Cluster.id, 'currentPositionLiftPercent100ths', this.coverLiftTilt?.log);
505
+ await this.coverLiftTilt?.setWindowCoveringTargetAndCurrentPosition(position, tiltPercent100thsValue);
506
+ this.coverLiftTilt?.log.info(`Command goToTiltPercentage ${tiltPercent100thsValue} called`);
470
507
  });
471
508
  this.lock = new MatterbridgeEndpoint([doorLockDevice, bridgedNode, powerSource], { uniqueStorageKey: 'Lock' }, this.config.debug)
472
509
  .createDefaultIdentifyClusterServer()
@@ -538,14 +575,14 @@ export class ExampleMatterbridgeDynamicPlatform extends MatterbridgeDynamicPlatf
538
575
  this.thermoAuto?.log.info('Set occupiedCoolingSetpoint:', setpoint);
539
576
  }
540
577
  });
541
- this.thermoAuto?.subscribeAttribute(ThermostatCluster.id, 'systemMode', async (value) => {
578
+ await this.thermoAuto?.subscribeAttribute(ThermostatCluster.id, 'systemMode', (value) => {
542
579
  const lookupSystemMode = ['Off', 'Auto', '', 'Cool', 'Heat', 'EmergencyHeat', 'Precooling', 'FanOnly', 'Dry', 'Sleep'];
543
580
  this.thermoAuto?.log.info('Subscribe systemMode called with:', lookupSystemMode[value]);
544
581
  }, this.thermoAuto.log);
545
- this.thermoAuto?.subscribeAttribute(ThermostatCluster.id, 'occupiedHeatingSetpoint', async (value) => {
582
+ await this.thermoAuto?.subscribeAttribute(ThermostatCluster.id, 'occupiedHeatingSetpoint', (value) => {
546
583
  this.thermoAuto?.log.info('Subscribe occupiedHeatingSetpoint called with:', value / 100);
547
584
  }, this.thermoAuto.log);
548
- this.thermoAuto?.subscribeAttribute(ThermostatCluster.id, 'occupiedCoolingSetpoint', async (value) => {
585
+ await this.thermoAuto?.subscribeAttribute(ThermostatCluster.id, 'occupiedCoolingSetpoint', (value) => {
549
586
  this.thermoAuto?.log.info('Subscribe occupiedCoolingSetpoint called with:', value / 100);
550
587
  }, this.thermoAuto.log);
551
588
  this.thermoHeat = new MatterbridgeEndpoint([thermostatDevice, bridgedNode, powerSource], { uniqueStorageKey: 'Thermostat (Heat)' }, this.config.debug)
@@ -580,11 +617,11 @@ export class ExampleMatterbridgeDynamicPlatform extends MatterbridgeDynamicPlatf
580
617
  this.thermoHeat?.addCommandHandler('triggerEffect', async ({ request: { effectIdentifier, effectVariant } }) => {
581
618
  this.thermoHeat?.log.info(`Command identify called effectIdentifier ${effectIdentifier} effectVariant ${effectVariant}`);
582
619
  });
583
- this.thermoHeat?.subscribeAttribute(ThermostatCluster.id, 'systemMode', async (value) => {
620
+ await this.thermoHeat?.subscribeAttribute(ThermostatCluster.id, 'systemMode', (value) => {
584
621
  const lookupSystemMode = ['Off', 'Auto', '', 'Cool', 'Heat', 'EmergencyHeat', 'Precooling', 'FanOnly', 'Dry', 'Sleep'];
585
622
  this.thermoHeat?.log.info('Subscribe systemMode called with:', lookupSystemMode[value]);
586
623
  }, this.thermoHeat.log);
587
- this.thermoHeat?.subscribeAttribute(ThermostatCluster.id, 'occupiedHeatingSetpoint', async (value) => {
624
+ await this.thermoHeat?.subscribeAttribute(ThermostatCluster.id, 'occupiedHeatingSetpoint', (value) => {
588
625
  this.thermoHeat?.log.info('Subscribe occupiedHeatingSetpoint called with:', value / 100);
589
626
  }, this.thermoHeat.log);
590
627
  this.thermoCool = new MatterbridgeEndpoint([thermostatDevice, bridgedNode, powerSource], { uniqueStorageKey: 'Thermostat (Cool)' }, this.config.debug)
@@ -607,11 +644,11 @@ export class ExampleMatterbridgeDynamicPlatform extends MatterbridgeDynamicPlatf
607
644
  this.thermoCool?.addCommandHandler('triggerEffect', async ({ request: { effectIdentifier, effectVariant } }) => {
608
645
  this.thermoCool?.log.info(`Command identify called effectIdentifier ${effectIdentifier} effectVariant ${effectVariant}`);
609
646
  });
610
- this.thermoCool?.subscribeAttribute(ThermostatCluster.id, 'systemMode', async (value) => {
647
+ await this.thermoCool?.subscribeAttribute(ThermostatCluster.id, 'systemMode', (value) => {
611
648
  const lookupSystemMode = ['Off', 'Auto', '', 'Cool', 'Heat', 'EmergencyHeat', 'Precooling', 'FanOnly', 'Dry', 'Sleep'];
612
649
  this.thermoCool?.log.info('Subscribe systemMode called with:', lookupSystemMode[value]);
613
650
  }, this.thermoCool.log);
614
- this.thermoCool?.subscribeAttribute(ThermostatCluster.id, 'occupiedCoolingSetpoint', async (value) => {
651
+ await this.thermoCool?.subscribeAttribute(ThermostatCluster.id, 'occupiedCoolingSetpoint', (value) => {
615
652
  this.thermoCool?.log.info('Subscribe occupiedCoolingSetpoint called with:', value / 100);
616
653
  }, this.thermoCool.log);
617
654
  this.airPurifier = new MatterbridgeEndpoint([airPurifier, temperatureSensor, humiditySensor, bridgedNode, powerSource], { uniqueStorageKey: 'Air purifier' }, this.config.debug)
@@ -634,31 +671,28 @@ export class ExampleMatterbridgeDynamicPlatform extends MatterbridgeDynamicPlatf
634
671
  this.airPurifier?.addCommandHandler('identify', async ({ request: { identifyTime } }) => {
635
672
  this.airPurifier?.log.info(`Command identify called identifyTime:${identifyTime}`);
636
673
  });
637
- this.airPurifier?.subscribeAttribute(FanControl.Cluster.id, 'fanMode', async (newValue, oldValue) => {
638
- this.fan?.log.info(`Fan mode changed from ${this.fanModeLookup[oldValue]} to ${this.fanModeLookup[newValue]}`);
674
+ await this.airPurifier?.subscribeAttribute(FanControl.Cluster.id, 'fanMode', (newValue, oldValue, context) => {
675
+ this.airPurifier?.log.info(`Fan mode changed from ${this.fanModeLookup[oldValue]} to ${this.fanModeLookup[newValue]} context: ${context.offline === true ? 'offline' : 'online'}`);
639
676
  if (newValue === FanControl.FanMode.Off) {
640
- await this.airPurifier?.setAttribute(FanControl.Cluster.id, 'percentCurrent', 0, this.airPurifier?.log);
677
+ this.airPurifier?.setAttribute(FanControl.Cluster.id, 'percentCurrent', 0, this.airPurifier?.log);
641
678
  }
642
679
  else if (newValue === FanControl.FanMode.Low) {
643
- await this.airPurifier?.setAttribute(FanControl.Cluster.id, 'percentCurrent', 33, this.airPurifier?.log);
680
+ this.airPurifier?.setAttribute(FanControl.Cluster.id, 'percentCurrent', 33, this.airPurifier?.log);
644
681
  }
645
682
  else if (newValue === FanControl.FanMode.Medium) {
646
- await this.airPurifier?.setAttribute(FanControl.Cluster.id, 'percentCurrent', 66, this.airPurifier?.log);
683
+ this.airPurifier?.setAttribute(FanControl.Cluster.id, 'percentCurrent', 66, this.airPurifier?.log);
647
684
  }
648
685
  else if (newValue === FanControl.FanMode.High) {
649
- await this.airPurifier?.setAttribute(FanControl.Cluster.id, 'percentCurrent', 100, this.airPurifier?.log);
686
+ this.airPurifier?.setAttribute(FanControl.Cluster.id, 'percentCurrent', 100, this.airPurifier?.log);
650
687
  }
651
688
  else if (newValue === FanControl.FanMode.On) {
652
- await this.airPurifier?.setAttribute(FanControl.Cluster.id, 'percentCurrent', 100, this.airPurifier?.log);
653
- }
654
- else if (newValue === FanControl.FanMode.Auto) {
655
- await this.airPurifier?.setAttribute(FanControl.Cluster.id, 'percentCurrent', 50, this.airPurifier?.log);
689
+ this.airPurifier?.setAttribute(FanControl.Cluster.id, 'percentCurrent', 100, this.airPurifier?.log);
656
690
  }
657
691
  }, this.airPurifier.log);
658
- this.airPurifier?.subscribeAttribute(FanControl.Cluster.id, 'percentSetting', async (newValue, oldValue) => {
659
- this.fan?.log.info(`Percent setting changed from ${oldValue} to ${newValue}`);
692
+ await this.airPurifier?.subscribeAttribute(FanControl.Cluster.id, 'percentSetting', (newValue, oldValue, context) => {
693
+ this.airPurifier?.log.info(`Percent setting changed from ${oldValue} to ${newValue} context: ${context.offline === true ? 'offline' : 'online'}`);
660
694
  if (isValidNumber(newValue, 0, 100))
661
- await this.airPurifier?.setAttribute(FanControl.Cluster.id, 'percentCurrent', newValue, this.airPurifier?.log);
695
+ this.airPurifier?.setAttribute(FanControl.Cluster.id, 'percentCurrent', newValue, this.airPurifier?.log);
662
696
  }, this.airPurifier.log);
663
697
  this.airConditioner = new MatterbridgeEndpoint([airConditioner, bridgedNode, powerSource], { uniqueStorageKey: 'Air Conditioner' }, this.config.debug)
664
698
  .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)
@@ -756,42 +790,42 @@ export class ExampleMatterbridgeDynamicPlatform extends MatterbridgeDynamicPlatf
756
790
  else {
757
791
  this.fan = undefined;
758
792
  }
759
- this.fan?.subscribeAttribute(FanControl.Cluster.id, 'fanMode', async (newValue, oldValue) => {
760
- this.fan?.log.info(`Fan mode changed from ${this.fanModeLookup[oldValue]} to ${this.fanModeLookup[newValue]}`);
793
+ await this.fan?.subscribeAttribute(FanControl.Cluster.id, 'fanMode', (newValue, oldValue, context) => {
794
+ this.fan?.log.info(`Fan mode changed from ${this.fanModeLookup[oldValue]} to ${this.fanModeLookup[newValue]} context: ${context.offline === true ? 'offline' : 'online'}`);
761
795
  if (newValue === FanControl.FanMode.Off) {
762
- await this.fan?.setAttribute(FanControl.Cluster.id, 'percentSetting', 0, this.fan?.log);
763
- await this.fan?.setAttribute(FanControl.Cluster.id, 'percentCurrent', 0, this.fan?.log);
796
+ this.fan?.setAttribute(FanControl.Cluster.id, 'percentSetting', 0, this.fan?.log);
797
+ this.fan?.setAttribute(FanControl.Cluster.id, 'percentCurrent', 0, this.fan?.log);
764
798
  }
765
799
  else if (newValue === FanControl.FanMode.Low) {
766
- await this.fan?.setAttribute(FanControl.Cluster.id, 'percentSetting', 33, this.fan?.log);
767
- await this.fan?.setAttribute(FanControl.Cluster.id, 'percentCurrent', 33, this.fan?.log);
800
+ this.fan?.setAttribute(FanControl.Cluster.id, 'percentSetting', 33, this.fan?.log);
801
+ this.fan?.setAttribute(FanControl.Cluster.id, 'percentCurrent', 33, this.fan?.log);
768
802
  }
769
803
  else if (newValue === FanControl.FanMode.Medium) {
770
- await this.fan?.setAttribute(FanControl.Cluster.id, 'percentSetting', 66, this.fan?.log);
771
- await this.fan?.setAttribute(FanControl.Cluster.id, 'percentCurrent', 66, this.fan?.log);
804
+ this.fan?.setAttribute(FanControl.Cluster.id, 'percentSetting', 66, this.fan?.log);
805
+ this.fan?.setAttribute(FanControl.Cluster.id, 'percentCurrent', 66, this.fan?.log);
772
806
  }
773
807
  else if (newValue === FanControl.FanMode.High) {
774
- await this.fan?.setAttribute(FanControl.Cluster.id, 'percentSetting', 100, this.fan?.log);
775
- await this.fan?.setAttribute(FanControl.Cluster.id, 'percentCurrent', 100, this.fan?.log);
808
+ this.fan?.setAttribute(FanControl.Cluster.id, 'percentSetting', 100, this.fan?.log);
809
+ this.fan?.setAttribute(FanControl.Cluster.id, 'percentCurrent', 100, this.fan?.log);
776
810
  }
777
811
  else if (newValue === FanControl.FanMode.On) {
778
- await this.fan?.setAttribute(FanControl.Cluster.id, 'percentSetting', 100, this.fan?.log);
779
- await this.fan?.setAttribute(FanControl.Cluster.id, 'percentCurrent', 100, this.fan?.log);
812
+ this.fan?.setAttribute(FanControl.Cluster.id, 'percentSetting', 100, this.fan?.log);
813
+ this.fan?.setAttribute(FanControl.Cluster.id, 'percentCurrent', 100, this.fan?.log);
780
814
  }
781
815
  else if (newValue === FanControl.FanMode.Auto) {
782
- await this.fan?.setAttribute(FanControl.Cluster.id, 'percentSetting', 50, this.fan?.log);
783
- await this.fan?.setAttribute(FanControl.Cluster.id, 'percentCurrent', 50, this.fan?.log);
816
+ this.fan?.setAttribute(FanControl.Cluster.id, 'percentSetting', 50, this.fan?.log);
817
+ this.fan?.setAttribute(FanControl.Cluster.id, 'percentCurrent', 50, this.fan?.log);
784
818
  }
785
819
  }, this.fan.log);
786
- this.fan?.subscribeAttribute(FanControl.Cluster.id, 'percentSetting', async (newValue, oldValue) => {
787
- this.fan?.log.info(`Percent setting changed from ${oldValue} to ${newValue}`);
820
+ await this.fan?.subscribeAttribute(FanControl.Cluster.id, 'percentSetting', (newValue, oldValue, context) => {
821
+ this.fan?.log.info(`Percent setting changed from ${oldValue} to ${newValue} context: ${context.offline === true ? 'offline' : 'online'}`);
788
822
  if (isValidNumber(newValue, 0, 100))
789
- await this.fan?.setAttribute(FanControl.Cluster.id, 'percentCurrent', newValue, this.fan?.log);
823
+ this.fan?.setAttribute(FanControl.Cluster.id, 'percentCurrent', newValue, this.fan?.log);
790
824
  }, this.fan.log);
791
- this.fan?.subscribeAttribute(FanControl.Cluster.id, 'speedSetting', async (newValue, oldValue) => {
792
- this.fan?.log.info(`Speed setting changed from ${oldValue} to ${newValue}`);
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'}`);
793
827
  if (isValidNumber(newValue, 0, 100))
794
- await this.fan?.setAttribute(FanControl.Cluster.id, 'speedCurrent', newValue, this.fan?.log);
828
+ this.fan?.setAttribute(FanControl.Cluster.id, 'speedCurrent', newValue, this.fan?.log);
795
829
  }, this.fan.log);
796
830
  this.waterLeak = new MatterbridgeEndpoint([waterLeakDetector, bridgedNode, powerSource], { uniqueStorageKey: 'Water leak detector' }, this.config.debug)
797
831
  .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)
@@ -933,11 +967,22 @@ export class ExampleMatterbridgeDynamicPlatform extends MatterbridgeDynamicPlatf
933
967
  this.bridgedDevices.set(robot.deviceName ?? '', robot);
934
968
  }
935
969
  }
936
- const heater = new WaterHeater('Water Heater', '3456177820');
937
- this.setSelectDevice(heater.serialNumber ?? '', heater.deviceName ?? '', undefined, 'hub');
938
- if (this.validateDevice(heater.deviceName ?? '')) {
939
- await this.registerDevice(heater);
940
- this.bridgedDevices.set(heater.deviceName ?? '', heater);
970
+ this.waterHeater = new WaterHeater('Water Heater', '3456177820');
971
+ this.setSelectDevice(this.waterHeater.serialNumber ?? '', this.waterHeater.deviceName ?? '', undefined, 'hub');
972
+ if (this.validateDevice(this.waterHeater.deviceName ?? '')) {
973
+ await this.registerDevice(this.waterHeater);
974
+ this.bridgedDevices.set(this.waterHeater.deviceName ?? '', this.waterHeater);
975
+ }
976
+ this.evse = new Evse('Evse', '3456127820', 1, [
977
+ { label: 'On demand', mode: 1, modeTags: [{ value: EnergyEvseMode.ModeTag.Manual }] },
978
+ { label: 'Scheduled', mode: 2, modeTags: [{ value: EnergyEvseMode.ModeTag.TimeOfUse }] },
979
+ { label: 'Solar Charging', mode: 3, modeTags: [{ value: EnergyEvseMode.ModeTag.SolarCharging }] },
980
+ { label: 'Solar Charging Scheduled', mode: 4, modeTags: [{ value: EnergyEvseMode.ModeTag.SolarCharging }, { value: EnergyEvseMode.ModeTag.TimeOfUse }] },
981
+ ]);
982
+ this.setSelectDevice(this.evse.serialNumber ?? '', this.evse.deviceName ?? '', undefined, 'hub');
983
+ if (this.validateDevice(this.evse.deviceName ?? '')) {
984
+ await this.registerDevice(this.evse);
985
+ this.bridgedDevices.set(this.evse.deviceName ?? '', this.evse);
941
986
  }
942
987
  const laundryWasherDevice = new Appliances(laundryWasher, 'Laundry Washer', '1234567890');
943
988
  this.setSelectDevice(laundryWasherDevice.serialNumber ?? '', laundryWasherDevice.deviceName ?? '', undefined, 'hub');
@@ -1091,17 +1136,17 @@ export class ExampleMatterbridgeDynamicPlatform extends MatterbridgeDynamicPlatf
1091
1136
  }
1092
1137
  }, 60 * 1000 + 300);
1093
1138
  }
1094
- await this.cover?.setWindowCoveringTargetAsCurrentAndStopped();
1095
- this.cover?.log.info('Set cover initial targetPositionLiftPercent100ths = currentPositionLiftPercent100ths and operationalStatus to Stopped.');
1139
+ await this.coverLift?.setWindowCoveringTargetAsCurrentAndStopped();
1140
+ this.coverLift?.log.info('Set cover initial targetPositionLiftPercent100ths = currentPositionLiftPercent100ths and operationalStatus to Stopped.');
1096
1141
  if (this.config.useInterval) {
1097
1142
  this.coverInterval = setInterval(async () => {
1098
- let position = this.cover?.getAttribute(WindowCovering.Cluster.id, 'currentPositionLiftPercent100ths', this.cover.log);
1143
+ let position = this.coverLift?.getAttribute(WindowCovering.Cluster.id, 'currentPositionLiftPercent100ths', this.coverLift.log);
1099
1144
  if (isValidNumber(position, 0, 10000)) {
1100
1145
  position = position > 9000 ? 0 : position + 1000;
1101
- await this.cover?.setAttribute(WindowCovering.Cluster.id, 'targetPositionLiftPercent100ths', position, this.cover.log);
1102
- await this.cover?.setAttribute(WindowCovering.Cluster.id, 'currentPositionLiftPercent100ths', position, this.cover.log);
1103
- await this.cover?.setAttribute(WindowCovering.Cluster.id, 'operationalStatus', { global: WindowCovering.MovementStatus.Stopped, lift: WindowCovering.MovementStatus.Stopped, tilt: WindowCovering.MovementStatus.Stopped }, this.cover.log);
1104
- this.cover?.log.info(`Set cover current and target positionLiftPercent100ths to ${position} and operationalStatus to Stopped`);
1146
+ await this.coverLift?.setAttribute(WindowCovering.Cluster.id, 'targetPositionLiftPercent100ths', position, this.coverLift.log);
1147
+ await this.coverLift?.setAttribute(WindowCovering.Cluster.id, 'currentPositionLiftPercent100ths', position, this.coverLift.log);
1148
+ await this.coverLift?.setAttribute(WindowCovering.Cluster.id, 'operationalStatus', { global: WindowCovering.MovementStatus.Stopped, lift: WindowCovering.MovementStatus.Stopped, tilt: WindowCovering.MovementStatus.Stopped }, this.coverLift.log);
1149
+ this.coverLift?.log.info(`Set cover current and target positionLiftPercent100ths to ${position} and operationalStatus to Stopped`);
1105
1150
  }
1106
1151
  }, 60 * 1000 + 400);
1107
1152
  }
@@ -1276,26 +1321,27 @@ export class ExampleMatterbridgeDynamicPlatform extends MatterbridgeDynamicPlatf
1276
1321
  await surface2?.setAttribute(OnOff.Cluster.id, 'onOff', true, surface2.log);
1277
1322
  surface2?.log.info(`Set Surface 2 onOff only OnOff to on`);
1278
1323
  if (this.config.useInterval) {
1324
+ this.genericSwitchLastEvent = 'Release';
1279
1325
  this.genericSwitchInterval = setInterval(async () => {
1280
1326
  if (this.genericSwitchLastEvent === 'Release') {
1281
- await this.momentarySwitch?.triggerSwitchEvent('Single', this.momentarySwitch?.log);
1282
1327
  this.genericSwitchLastEvent = 'Single';
1328
+ await this.momentarySwitch?.triggerSwitchEvent('Single', this.momentarySwitch?.log);
1283
1329
  }
1284
1330
  else if (this.genericSwitchLastEvent === 'Single') {
1285
- await this.momentarySwitch?.triggerSwitchEvent('Double', this.momentarySwitch?.log);
1286
1331
  this.genericSwitchLastEvent = 'Double';
1332
+ await this.momentarySwitch?.triggerSwitchEvent('Double', this.momentarySwitch?.log);
1287
1333
  }
1288
1334
  else if (this.genericSwitchLastEvent === 'Double') {
1289
- await this.momentarySwitch?.triggerSwitchEvent('Long', this.momentarySwitch?.log);
1290
1335
  this.genericSwitchLastEvent = 'Long';
1336
+ await this.momentarySwitch?.triggerSwitchEvent('Long', this.momentarySwitch?.log);
1291
1337
  }
1292
1338
  else if (this.genericSwitchLastEvent === 'Long') {
1293
- await this.latchingSwitch?.triggerSwitchEvent('Press', this.latchingSwitch?.log);
1294
1339
  this.genericSwitchLastEvent = 'Press';
1340
+ await this.latchingSwitch?.triggerSwitchEvent('Press', this.latchingSwitch?.log);
1295
1341
  }
1296
1342
  else if (this.genericSwitchLastEvent === 'Press') {
1297
- await this.latchingSwitch?.triggerSwitchEvent('Release', this.latchingSwitch?.log);
1298
1343
  this.genericSwitchLastEvent = 'Release';
1344
+ await this.latchingSwitch?.triggerSwitchEvent('Release', this.latchingSwitch?.log);
1299
1345
  }
1300
1346
  }, 60 * 1000 + 1900);
1301
1347
  }
@@ -1,12 +1,12 @@
1
1
  {
2
2
  "name": "matterbridge-example-dynamic-platform",
3
- "version": "1.2.2",
3
+ "version": "1.2.3",
4
4
  "lockfileVersion": 3,
5
5
  "requires": true,
6
6
  "packages": {
7
7
  "": {
8
8
  "name": "matterbridge-example-dynamic-platform",
9
- "version": "1.2.2",
9
+ "version": "1.2.3",
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.2",
3
+ "version": "1.2.3",
4
4
  "description": "Matterbridge dynamic plugin",
5
5
  "author": "https://github.com/Luligu",
6
6
  "license": "MIT",
@@ -24,7 +24,11 @@
24
24
  "matter",
25
25
  "matter.js",
26
26
  "example",
27
- "plugin"
27
+ "plugin",
28
+ "dynamic",
29
+ "platform",
30
+ "virtual device",
31
+ "virtual devices"
28
32
  ],
29
33
  "engines": {
30
34
  "node": ">=18.0.0 <19.0.0 || >=20.0.0 <21.0.0 || >=22.0.0"