matterbridge 1.4.1 → 1.4.2

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.
Files changed (33) hide show
  1. package/CHANGELOG.md +21 -0
  2. package/README.md +1 -2
  3. package/dist/cluster/AirQualityCluster.d.ts.map +1 -1
  4. package/dist/cluster/AirQualityCluster.js +1 -0
  5. package/dist/cluster/AirQualityCluster.js.map +1 -1
  6. package/dist/cluster/BridgedDeviceBasicInformationCluster.d.ts.map +1 -1
  7. package/dist/cluster/BridgedDeviceBasicInformationCluster.js +1 -0
  8. package/dist/cluster/BridgedDeviceBasicInformationCluster.js.map +1 -1
  9. package/dist/cluster/PowerTopologyCluster.d.ts.map +1 -1
  10. package/dist/cluster/PowerTopologyCluster.js +1 -1
  11. package/dist/cluster/PowerTopologyCluster.js.map +1 -1
  12. package/dist/cluster/TvocCluster.d.ts.map +1 -1
  13. package/dist/cluster/TvocCluster.js +1 -0
  14. package/dist/cluster/TvocCluster.js.map +1 -1
  15. package/dist/matterbridge.d.ts +3 -0
  16. package/dist/matterbridge.d.ts.map +1 -1
  17. package/dist/matterbridge.js +133 -25
  18. package/dist/matterbridge.js.map +1 -1
  19. package/dist/matterbridgeDevice.d.ts +65 -157
  20. package/dist/matterbridgeDevice.d.ts.map +1 -1
  21. package/dist/matterbridgeDevice.js +224 -26
  22. package/dist/matterbridgeDevice.js.map +1 -1
  23. package/dist/utils/utils.d.ts +57 -0
  24. package/dist/utils/utils.d.ts.map +1 -1
  25. package/dist/utils/utils.js +103 -0
  26. package/dist/utils/utils.js.map +1 -1
  27. package/frontend/build/asset-manifest.json +3 -3
  28. package/frontend/build/index.html +1 -1
  29. package/frontend/build/static/js/{main.fd6f85a1.js → main.dec34964.js} +3 -3
  30. package/frontend/build/static/js/main.dec34964.js.map +1 -0
  31. package/package.json +24 -24
  32. package/frontend/build/static/js/main.fd6f85a1.js.map +0 -1
  33. /package/frontend/build/static/js/{main.fd6f85a1.js.LICENSE.txt → main.dec34964.js.LICENSE.txt} +0 -0
@@ -20,12 +20,12 @@
20
20
  * See the License for the specific language governing permissions and
21
21
  * limitations under the License. *
22
22
  */
23
- import { BasicInformationCluster, BooleanState, BooleanStateCluster, ClusterServer, ColorControl, ColorControlCluster, DoorLock, DoorLockCluster, ElectricalMeasurement, ElectricalMeasurementCluster, FanControl, FanControlCluster, FixedLabelCluster, FlowMeasurement, FlowMeasurementCluster, Groups, GroupsCluster, GroupsClusterHandler, Identify, IdentifyCluster, IlluminanceMeasurement, IlluminanceMeasurementCluster, LevelControl, LevelControlCluster, ModeSelectCluster, OccupancySensing, OccupancySensingCluster, OnOff, OnOffCluster, PowerSource, PowerSourceCluster, PowerSourceConfigurationCluster, PressureMeasurement, PressureMeasurementCluster, RelativeHumidityMeasurement, RelativeHumidityMeasurementCluster, Scenes, ScenesCluster, ScenesClusterHandler, Switch, SwitchCluster, TemperatureMeasurement, TemperatureMeasurementCluster, Thermostat, ThermostatCluster, ThreadNetworkDiagnostics, ThreadNetworkDiagnosticsCluster, TimeSync, TimeSyncCluster, WindowCovering, WindowCoveringCluster, getClusterNameById, } from '@project-chip/matter-node.js/cluster';
23
+ import { BasicInformationCluster, BooleanState, BooleanStateCluster, ClusterServer, ColorControl, ColorControlCluster, DoorLock, DoorLockCluster, FanControl, FanControlCluster, FixedLabelCluster, FlowMeasurement, FlowMeasurementCluster, Groups, GroupsCluster, GroupsClusterHandler, Identify, IdentifyCluster, IlluminanceMeasurement, IlluminanceMeasurementCluster, LevelControl, LevelControlCluster, ModeSelectCluster, OccupancySensing, OccupancySensingCluster, OnOff, OnOffCluster, PowerSource, PowerSourceCluster, PowerSourceConfigurationCluster, PressureMeasurement, PressureMeasurementCluster, RelativeHumidityMeasurement, RelativeHumidityMeasurementCluster, Scenes, ScenesCluster, ScenesClusterHandler, Switch, SwitchCluster, TemperatureMeasurement, TemperatureMeasurementCluster, Thermostat, ThermostatCluster, ThreadNetworkDiagnostics, ThreadNetworkDiagnosticsCluster, TimeSync, TimeSyncCluster, WindowCovering, WindowCoveringCluster, getClusterNameById, } from '@project-chip/matter-node.js/cluster';
24
24
  import { EndpointNumber, GroupId, VendorId } from '@project-chip/matter-node.js/datatype';
25
25
  import { Device, DeviceClasses, DeviceTypeDefinition, Endpoint } from '@project-chip/matter-node.js/device';
26
26
  import { extendPublicHandlerMethods } from '@project-chip/matter-node.js/util';
27
- import { EveHistory, EveHistoryCluster } from 'matter-history';
28
- import { AnsiLogger, CYAN, db, hk, zb } from 'node-ansi-logger';
27
+ import { EveHistory, EveHistoryCluster, MatterHistory } from 'matter-history';
28
+ import { AnsiLogger, CYAN, YELLOW, db, debugStringify, hk, or, zb } from 'node-ansi-logger';
29
29
  import { AirQuality, AirQualityCluster } from './cluster/AirQualityCluster.js';
30
30
  import { createHash } from 'crypto';
31
31
  import { TvocMeasurement, TvocMeasurementCluster } from './cluster/TvocCluster.js';
@@ -439,9 +439,8 @@ export class MatterbridgeDevice extends extendPublicHandlerMethods(Device) {
439
439
  if (includeServerList.includes(PowerSource.Cluster.id))
440
440
  endpoint.addClusterServer(this.getDefaultPowerSourceWiredClusterServer());
441
441
  if (includeServerList.includes(EveHistory.Cluster.id))
442
- endpoint.addClusterServer(this.getDefaultStaticEveHistoryClusterServer());
443
- if (includeServerList.includes(ElectricalMeasurement.Cluster.id))
444
- endpoint.addClusterServer(this.getDefaultElectricalMeasurementClusterServer());
442
+ endpoint.addClusterServer(MatterHistory.getEveHistoryClusterServer());
443
+ // if (includeServerList.includes(ElectricalMeasurement.Cluster.id)) endpoint.addClusterServer(this.getDefaultElectricalMeasurementClusterServer());
445
444
  if (includeServerList.includes(PowerTopology.Cluster.id))
446
445
  endpoint.addClusterServer(this.getDefaultPowerTopologyClusterServer());
447
446
  if (includeServerList.includes(ElectricalPowerMeasurement.Cluster.id))
@@ -549,6 +548,88 @@ export class MatterbridgeDevice extends extendPublicHandlerMethods(Device) {
549
548
  return endpoint;
550
549
  }
551
550
  }
551
+ /**
552
+ * Retrieves the value of the specified attribute from the given endpoint and cluster.
553
+ *
554
+ * @param {ClusterId} clusterId - The ID of the cluster to retrieve the attribute from.
555
+ * @param {string} attribute - The name of the attribute to retrieve.
556
+ * @param {AnsiLogger} [log] - Optional logger for error and info messages.
557
+ * @param {Endpoint} [endpoint] - Optional the child endpoint to retrieve the attribute from.
558
+ * @returns {any} The value of the attribute, or undefined if the attribute is not found.
559
+ */
560
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
561
+ getAttribute(clusterId, attribute, log, endpoint) {
562
+ if (!endpoint)
563
+ endpoint = this;
564
+ const clusterServer = endpoint.getClusterServerById(clusterId);
565
+ if (!clusterServer) {
566
+ log?.error(`getAttribute error: Cluster ${clusterId} not found on endpoint ${endpoint.name}:${endpoint.number}`);
567
+ return undefined;
568
+ }
569
+ const capitalizedAttributeName = attribute.charAt(0).toUpperCase() + attribute.slice(1);
570
+ if (!clusterServer.isAttributeSupportedByName(attribute) && !clusterServer.isAttributeSupportedByName(capitalizedAttributeName)) {
571
+ if (log)
572
+ log.error(`getAttribute error: Attribute ${attribute} not found on Cluster ${clusterServer.name} on endpoint ${endpoint.name}:${endpoint.number}`);
573
+ return undefined;
574
+ }
575
+ // Find the getter method
576
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
577
+ if (!clusterServer[`get${capitalizedAttributeName}Attribute`]) {
578
+ log?.error(`getAttribute error: Getter get${capitalizedAttributeName}Attribute not found on Cluster ${clusterServer.name} on endpoint ${endpoint.name}:${endpoint.number}`);
579
+ return undefined;
580
+ }
581
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any, @typescript-eslint/no-empty-object-type
582
+ const getter = clusterServer[`get${capitalizedAttributeName}Attribute`];
583
+ const value = getter();
584
+ log?.info(`${db}Get endpoint ${or}${endpoint.name}:${endpoint.number}${db} attribute ${hk}${clusterServer.name}.${capitalizedAttributeName}${db} value ${YELLOW}${typeof value === 'object' ? debugStringify(value) : value}${db}`);
585
+ return value;
586
+ }
587
+ /**
588
+ * Sets the value of an attribute on a cluster server endpoint.
589
+ *
590
+ * @param {ClusterId} clusterId - The ID of the cluster.
591
+ * @param {string} attribute - The name of the attribute.
592
+ * @param {any} value - The value to set for the attribute.
593
+ * @param {AnsiLogger} [log] - (Optional) The logger to use for logging errors and information.
594
+ * @param {Endpoint} [endpoint] - (Optional) The endpoint to set the attribute on. If not provided, the attribute will be set on the current endpoint.
595
+ */
596
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
597
+ setAttribute(clusterId, attribute, value, log, endpoint) {
598
+ if (!endpoint)
599
+ endpoint = this;
600
+ const clusterServer = endpoint.getClusterServerById(clusterId);
601
+ if (!clusterServer) {
602
+ log?.error(`setAttribute error: Cluster ${clusterId} not found on endpoint ${endpoint.name}:${endpoint.number}`);
603
+ return;
604
+ }
605
+ const capitalizedAttributeName = attribute.charAt(0).toUpperCase() + attribute.slice(1);
606
+ if (!clusterServer.isAttributeSupportedByName(attribute) && !clusterServer.isAttributeSupportedByName(capitalizedAttributeName)) {
607
+ if (log)
608
+ log.error(`setAttribute error: Attribute ${attribute} not found on Cluster ${clusterId} on endpoint ${endpoint.name}:${endpoint.number}`);
609
+ return;
610
+ }
611
+ // Find the getter method
612
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
613
+ if (!clusterServer[`get${capitalizedAttributeName}Attribute`]) {
614
+ log?.error(`setAttribute error: Getter get${capitalizedAttributeName}Attribute not found on Cluster ${clusterServer.name} on endpoint ${endpoint.name}:${endpoint.number}`);
615
+ return;
616
+ }
617
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any, @typescript-eslint/no-empty-object-type
618
+ const getter = clusterServer[`get${capitalizedAttributeName}Attribute`];
619
+ // Find the setter method
620
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
621
+ if (!clusterServer[`set${capitalizedAttributeName}Attribute`]) {
622
+ log?.error(`setAttribute error: Setter set${capitalizedAttributeName}Attribute not found on Cluster ${clusterServer.name} on endpoint ${endpoint.name}:${endpoint.number}`);
623
+ return;
624
+ }
625
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any, @typescript-eslint/no-empty-object-type
626
+ const setter = clusterServer[`set${capitalizedAttributeName}Attribute`];
627
+ const oldValue = getter();
628
+ setter(value);
629
+ log?.info(`${db}Set endpoint ${or}${endpoint.name}:${endpoint.number}${db} attribute ${hk}${clusterServer.name}.${capitalizedAttributeName}${db} ` +
630
+ `from ${YELLOW}${typeof oldValue === 'object' ? debugStringify(oldValue) : oldValue}${db} ` +
631
+ `to ${YELLOW}${typeof value === 'object' ? debugStringify(value) : value}${db}`);
632
+ }
552
633
  /**
553
634
  * Serializes the Matterbridge device into a serialized object.
554
635
  *
@@ -603,7 +684,7 @@ export class MatterbridgeDevice extends extendPublicHandlerMethods(Device) {
603
684
  /**
604
685
  * Returns a default static EveHistoryClusterServer object with the specified voltage, current, power, and consumption values.
605
686
  * This shows up in HA as a static sensor!
606
- * @deprecated This method is deprecated and will be removed in a future version.
687
+ * @deprecated This method is deprecated and will be removed in a future version. Use MatterHistory.
607
688
  * @param voltage - The voltage value (default: 0).
608
689
  * @param current - The current value (default: 0).
609
690
  * @param power - The power value (default: 0).
@@ -634,7 +715,7 @@ export class MatterbridgeDevice extends extendPublicHandlerMethods(Device) {
634
715
  /**
635
716
  * Create a default static EveHistoryClusterServer object with the specified voltage, current, power, and consumption values.
636
717
  * This shows up in HA as a static sensor!
637
- * @deprecated This method is deprecated and will be removed in a future version.
718
+ * @deprecated This method is deprecated and will be removed in a future version. Use MatterHistory.
638
719
  * @param voltage - The voltage value (default: 0).
639
720
  * @param current - The current value (default: 0).
640
721
  * @param power - The power value (default: 0).
@@ -646,7 +727,7 @@ export class MatterbridgeDevice extends extendPublicHandlerMethods(Device) {
646
727
  }
647
728
  /**
648
729
  * Creates a room Eve History Cluster Server.
649
- * @deprecated This method is deprecated and will be removed in a future version.
730
+ * @deprecated This method is deprecated and will be removed in a future version. Use MatterHistory.
650
731
  *
651
732
  * @param history - The MatterHistory object.
652
733
  * @param log - The AnsiLogger object.
@@ -705,7 +786,7 @@ export class MatterbridgeDevice extends extendPublicHandlerMethods(Device) {
705
786
  }
706
787
  /**
707
788
  * Creates a Weather Eve History Cluster Server.
708
- * @deprecated This method is deprecated and will be removed in a future version.
789
+ * @deprecated This method is deprecated and will be removed in a future version. Use MatterHistory.
709
790
  *
710
791
  * @param history - The MatterHistory instance.
711
792
  * @param log - The AnsiLogger instance.
@@ -767,7 +848,7 @@ export class MatterbridgeDevice extends extendPublicHandlerMethods(Device) {
767
848
  }
768
849
  /**
769
850
  * Creates an Energy Eve History Cluster Server.
770
- * @deprecated This method is deprecated and will be removed in a future version.
851
+ * @deprecated This method is deprecated and will be removed in a future version. Use MatterHistory.
771
852
  *
772
853
  * @param history - The MatterHistory object.
773
854
  * @param log - The AnsiLogger object.
@@ -845,7 +926,7 @@ export class MatterbridgeDevice extends extendPublicHandlerMethods(Device) {
845
926
  }
846
927
  /**
847
928
  * Creates a Motion Eve History Cluster Server.
848
- * @deprecated This method is deprecated and will be removed in a future version.
929
+ * @deprecated This method is deprecated and will be removed in a future version. Use MatterHistory.
849
930
  *
850
931
  * @param history - The MatterHistory object.
851
932
  * @param log - The AnsiLogger object.
@@ -909,7 +990,7 @@ export class MatterbridgeDevice extends extendPublicHandlerMethods(Device) {
909
990
  }
910
991
  /**
911
992
  * Creates a door EveHistoryCluster server.
912
- * @deprecated This method is deprecated and will be removed in a future version.
993
+ * @deprecated This method is deprecated and will be removed in a future version. Use MatterHistory.
913
994
  *
914
995
  * @param history - The MatterHistory instance.
915
996
  * @param log - The AnsiLogger instance.
@@ -1250,14 +1331,21 @@ export class MatterbridgeDevice extends extendPublicHandlerMethods(Device) {
1250
1331
  * @param power - The active power value.
1251
1332
  * @param consumption - The total active power consumption value.
1252
1333
  */
1334
+ /*
1253
1335
  getDefaultElectricalMeasurementClusterServer(voltage = 0, current = 0, power = 0, consumption = 0) {
1254
- return ClusterServer(ElectricalMeasurementCluster, {
1255
- rmsVoltage: voltage,
1256
- rmsCurrent: current,
1257
- activePower: power,
1258
- totalActivePower: consumption,
1259
- }, {}, {});
1336
+ return ClusterServer(
1337
+ ElectricalMeasurementCluster,
1338
+ {
1339
+ rmsVoltage: voltage,
1340
+ rmsCurrent: current,
1341
+ activePower: power,
1342
+ totalActivePower: consumption,
1343
+ },
1344
+ {},
1345
+ {},
1346
+ );
1260
1347
  }
1348
+ */
1261
1349
  /**
1262
1350
  * @deprecated This method is deprecated and will be removed in a future version.
1263
1351
  * Creates a default Electrical Measurement Cluster Server.
@@ -1267,9 +1355,11 @@ export class MatterbridgeDevice extends extendPublicHandlerMethods(Device) {
1267
1355
  * @param power - The active power value.
1268
1356
  * @param consumption - The total active power consumption value.
1269
1357
  */
1358
+ /*
1270
1359
  createDefaultElectricalMeasurementClusterServer(voltage = 0, current = 0, power = 0, consumption = 0) {
1271
- this.addClusterServer(this.getDefaultElectricalMeasurementClusterServer(voltage, current, power, consumption));
1360
+ this.addClusterServer(this.getDefaultElectricalMeasurementClusterServer(voltage, current, power, consumption));
1272
1361
  }
1362
+ */
1273
1363
  /**
1274
1364
  * Creates a default Dummy Thread Network Diagnostics Cluster server.
1275
1365
  * @deprecated This method is deprecated and is only used for testing.
@@ -1558,6 +1648,39 @@ export class MatterbridgeDevice extends extendPublicHandlerMethods(Device) {
1558
1648
  createDefaultXYColorControlClusterServer(currentX = 0, currentY = 0, colorTemperatureMireds = 500, colorTempPhysicalMinMireds = 147, colorTempPhysicalMaxMireds = 500) {
1559
1649
  this.addClusterServer(this.getDefaultXYColorControlClusterServer(currentX, currentY, colorTemperatureMireds, colorTempPhysicalMinMireds, colorTempPhysicalMaxMireds));
1560
1650
  }
1651
+ /**
1652
+ * Configures the color control cluster for a device.
1653
+ *
1654
+ * @param {boolean} hueSaturation - A boolean indicating whether the device supports hue and saturation control.
1655
+ * @param {boolean} xy - A boolean indicating whether the device supports XY control.
1656
+ * @param {boolean} colorTemperature - A boolean indicating whether the device supports color temperature control.
1657
+ * @param {ColorControl.ColorMode} colorMode - An optional parameter specifying the color mode of the device.
1658
+ * @param {Endpoint} endpoint - An optional parameter specifying the endpoint to configure. If not provided, the device endpoint will be used.
1659
+ */
1660
+ configureColorControlCluster(hueSaturation, xy, colorTemperature, colorMode, endpoint) {
1661
+ if (!endpoint)
1662
+ endpoint = this;
1663
+ endpoint.getClusterServer(ColorControlCluster)?.setFeatureMapAttribute({ hueSaturation, enhancedHue: false, colorLoop: false, xy, colorTemperature });
1664
+ endpoint.getClusterServer(ColorControlCluster)?.setColorCapabilitiesAttribute({ hueSaturation, enhancedHue: false, colorLoop: false, xy, colorTemperature });
1665
+ if (colorMode !== undefined && colorMode >= 0 && colorMode <= 2) {
1666
+ endpoint.getClusterServer(ColorControlCluster)?.setColorModeAttribute(colorMode);
1667
+ endpoint.getClusterServer(ColorControlCluster)?.setEnhancedColorModeAttribute(colorMode);
1668
+ }
1669
+ }
1670
+ /**
1671
+ * Configures the color control mode for the device.
1672
+ *
1673
+ * @param {ColorControl.ColorMode} colorMode - The color mode to set.
1674
+ * @param {Endpoint} endpoint - The optional endpoint to configure. If not provided, the method will configure the current endpoint.
1675
+ */
1676
+ configureColorControlMode(colorMode, endpoint) {
1677
+ if (!endpoint)
1678
+ endpoint = this;
1679
+ if (colorMode !== undefined && colorMode >= 0 && colorMode <= 2) {
1680
+ endpoint.getClusterServer(ColorControlCluster)?.setColorModeAttribute(colorMode);
1681
+ endpoint.getClusterServer(ColorControlCluster)?.setEnhancedColorModeAttribute(colorMode);
1682
+ }
1683
+ }
1561
1684
  /**
1562
1685
  * Get a default window covering cluster server.
1563
1686
  *
@@ -1612,6 +1735,7 @@ export class MatterbridgeDevice extends extendPublicHandlerMethods(Device) {
1612
1735
  }
1613
1736
  /**
1614
1737
  * Sets the window covering target position as the current position and stops the movement.
1738
+ * @param {Endpoint} endpoint - The endpoint on which to set the window covering (default the device endpoint).
1615
1739
  */
1616
1740
  setWindowCoveringTargetAsCurrentAndStopped(endpoint) {
1617
1741
  if (!endpoint)
@@ -1624,7 +1748,7 @@ export class MatterbridgeDevice extends extendPublicHandlerMethods(Device) {
1624
1748
  windowCoveringCluster.setOperationalStatusAttribute({
1625
1749
  global: WindowCovering.MovementStatus.Stopped,
1626
1750
  lift: WindowCovering.MovementStatus.Stopped,
1627
- tilt: 0,
1751
+ tilt: WindowCovering.MovementStatus.Stopped,
1628
1752
  });
1629
1753
  }
1630
1754
  this.log.debug(`Set WindowCovering currentPositionLiftPercent100ths and targetPositionLiftPercent100ths to ${position} and operationalStatus to Stopped.`);
@@ -1632,9 +1756,10 @@ export class MatterbridgeDevice extends extendPublicHandlerMethods(Device) {
1632
1756
  }
1633
1757
  /**
1634
1758
  * Sets the current and target status of a window covering.
1635
- * @param current - The current position of the window covering.
1636
- * @param target - The target position of the window covering.
1637
- * @param status - The movement status of the window covering.
1759
+ * @param {number} current - The current position of the window covering.
1760
+ * @param {number} target - The target position of the window covering.
1761
+ * @param {WindowCovering.MovementStatus} status - The movement status of the window covering.
1762
+ * @param {Endpoint} endpoint - The endpoint on which to set the window covering (default the device endpoint).
1638
1763
  */
1639
1764
  setWindowCoveringCurrentTargetStatus(current, target, status, endpoint) {
1640
1765
  if (!endpoint)
@@ -1646,7 +1771,7 @@ export class MatterbridgeDevice extends extendPublicHandlerMethods(Device) {
1646
1771
  windowCoveringCluster.setOperationalStatusAttribute({
1647
1772
  global: status,
1648
1773
  lift: status,
1649
- tilt: 0,
1774
+ tilt: status,
1650
1775
  });
1651
1776
  }
1652
1777
  this.log.debug(`Set WindowCovering currentPositionLiftPercent100ths: ${current}, targetPositionLiftPercent100ths: ${target} and operationalStatus: ${status}.`);
@@ -1654,6 +1779,7 @@ export class MatterbridgeDevice extends extendPublicHandlerMethods(Device) {
1654
1779
  /**
1655
1780
  * Sets the status of the window covering.
1656
1781
  * @param {WindowCovering.MovementStatus} status - The movement status to set.
1782
+ * @param {Endpoint} endpoint - The endpoint on which to set the window covering (default the device endpoint).
1657
1783
  */
1658
1784
  setWindowCoveringStatus(status, endpoint) {
1659
1785
  if (!endpoint)
@@ -1661,11 +1787,13 @@ export class MatterbridgeDevice extends extendPublicHandlerMethods(Device) {
1661
1787
  const windowCovering = endpoint.getClusterServer(WindowCoveringCluster.with(WindowCovering.Feature.Lift, WindowCovering.Feature.PositionAwareLift, WindowCovering.Feature.AbsolutePosition));
1662
1788
  if (!windowCovering)
1663
1789
  return;
1664
- windowCovering.setOperationalStatusAttribute({ global: status, lift: status, tilt: 0 });
1790
+ windowCovering.setOperationalStatusAttribute({ global: status, lift: status, tilt: status });
1665
1791
  this.log.debug(`Set WindowCovering operationalStatus: ${status}`);
1666
1792
  }
1667
1793
  /**
1668
1794
  * Retrieves the status of the window covering.
1795
+ * @param {Endpoint} endpoint - The endpoint on which to get the window covering (default the device endpoint).
1796
+ *
1669
1797
  * @returns The global operational status of the window covering.
1670
1798
  */
1671
1799
  getWindowCoveringStatus(endpoint) {
@@ -1682,6 +1810,7 @@ export class MatterbridgeDevice extends extendPublicHandlerMethods(Device) {
1682
1810
  * Sets the target and current position of the window covering.
1683
1811
  *
1684
1812
  * @param position - The position to set, specified as a number.
1813
+ * @param {Endpoint} endpoint - The endpoint on which to set the window covering (default the device endpoint).
1685
1814
  */
1686
1815
  setWindowCoveringTargetAndCurrentPosition(position, endpoint) {
1687
1816
  if (!endpoint)
@@ -1788,6 +1917,75 @@ export class MatterbridgeDevice extends extendPublicHandlerMethods(Device) {
1788
1917
  this.addFixedLabel('orientation', 'Switch');
1789
1918
  this.addFixedLabel('label', 'Switch');
1790
1919
  }
1920
+ /**
1921
+ * Triggers a switch event on the specified endpoint.
1922
+ *
1923
+ * @param {string} event - The type of event to trigger. Possible values are 'Single', 'Double', 'Long', 'Press', and 'Release'.
1924
+ * @param {Endpoint} endpoint - The endpoint on which to trigger the event (default the device endpoint).
1925
+ * @returns {void}
1926
+ */
1927
+ triggerSwitchEvent(event, endpoint, log) {
1928
+ if (!endpoint)
1929
+ endpoint = this;
1930
+ if (['Single', 'Double', 'Long'].includes(event)) {
1931
+ const cluster = endpoint.getClusterServer(SwitchCluster.with(Switch.Feature.MomentarySwitch, Switch.Feature.MomentarySwitchRelease, Switch.Feature.MomentarySwitchLongPress, Switch.Feature.MomentarySwitchMultiPress));
1932
+ if (!cluster || !cluster.getFeatureMapAttribute().momentarySwitch) {
1933
+ log?.error(`triggerSwitchEvent ${event} error: Switch cluster with MomentarySwitch not found on endpoint ${endpoint.name}:${endpoint.number}`);
1934
+ return;
1935
+ }
1936
+ if (event === 'Single') {
1937
+ cluster.setCurrentPositionAttribute(1);
1938
+ cluster.triggerInitialPressEvent({ newPosition: 1 });
1939
+ cluster.setCurrentPositionAttribute(0);
1940
+ cluster.triggerShortReleaseEvent({ previousPosition: 1 });
1941
+ cluster.setCurrentPositionAttribute(0);
1942
+ cluster.triggerMultiPressCompleteEvent({ previousPosition: 1, totalNumberOfPressesCounted: 1 });
1943
+ log?.info(`${db}Trigger endpoint ${or}${endpoint.name}:${endpoint.number}${db} event ${hk}${cluster.name}.SinglePress${db}`);
1944
+ }
1945
+ if (event === 'Double') {
1946
+ cluster.setCurrentPositionAttribute(1);
1947
+ cluster.triggerInitialPressEvent({ newPosition: 1 });
1948
+ cluster.setCurrentPositionAttribute(0);
1949
+ cluster.triggerShortReleaseEvent({ previousPosition: 1 });
1950
+ cluster.setCurrentPositionAttribute(1);
1951
+ cluster.triggerInitialPressEvent({ newPosition: 1 });
1952
+ cluster.triggerMultiPressOngoingEvent({ newPosition: 1, currentNumberOfPressesCounted: 2 });
1953
+ cluster.setCurrentPositionAttribute(0);
1954
+ cluster.triggerShortReleaseEvent({ previousPosition: 1 });
1955
+ cluster.triggerMultiPressCompleteEvent({ previousPosition: 1, totalNumberOfPressesCounted: 2 });
1956
+ log?.info(`${db}Trigger endpoint ${or}${endpoint.name}:${endpoint.number}${db} event ${hk}${cluster.name}.DoublePress${db}`);
1957
+ }
1958
+ if (event === 'Long') {
1959
+ cluster.setCurrentPositionAttribute(1);
1960
+ cluster.triggerInitialPressEvent({ newPosition: 1 });
1961
+ cluster.triggerLongPressEvent({ newPosition: 1 });
1962
+ cluster.setCurrentPositionAttribute(0);
1963
+ cluster.triggerLongReleaseEvent({ previousPosition: 1 });
1964
+ log?.info(`${db}Trigger endpoint ${or}${endpoint.name}:${endpoint.number}${db} event ${hk}${cluster.name}.LongPress${db}`);
1965
+ }
1966
+ }
1967
+ if (['Press', 'Release'].includes(event)) {
1968
+ const cluster = endpoint.getClusterServer(Switch.Complete);
1969
+ if (!cluster || !cluster.getFeatureMapAttribute().latchingSwitch) {
1970
+ log?.error(`triggerSwitchEvent ${event} error: Switch cluster with LatchingSwitch not found on endpoint ${endpoint.name}:${endpoint.number}`);
1971
+ return;
1972
+ }
1973
+ if (event === 'Press') {
1974
+ cluster.setCurrentPositionAttribute(1);
1975
+ log?.info(`${db}Update endpoint ${or}${endpoint.name}:${endpoint.number}${db} attribute ${hk}${cluster.name}.CurrentPosition${db} to ${YELLOW}1${db}`);
1976
+ if (cluster.triggerSwitchLatchedEvent)
1977
+ cluster.triggerSwitchLatchedEvent({ newPosition: 1 });
1978
+ log?.info(`${db}Trigger endpoint ${or}${endpoint.name}:${endpoint.number}${db} event ${hk}${cluster.name}.Press${db}`);
1979
+ }
1980
+ if (event === 'Release') {
1981
+ cluster.setCurrentPositionAttribute(0);
1982
+ log?.info(`${db}Update endpoint ${or}${endpoint.name}:${endpoint.number}${db} attribute ${hk}${cluster.name}.CurrentPosition${db} to ${YELLOW}0${db}`);
1983
+ if (cluster.triggerSwitchLatchedEvent)
1984
+ cluster.triggerSwitchLatchedEvent({ newPosition: 0 });
1985
+ log?.info(`${db}Trigger endpoint ${or}${endpoint.name}:${endpoint.number}${db} event ${hk}${cluster.name}.Release${db}`);
1986
+ }
1987
+ }
1988
+ }
1791
1989
  /**
1792
1990
  * Retrieves the default mode select cluster server.
1793
1991
  *