diff --git a/bundles/org.openhab.binding.matter/README.md b/bundles/org.openhab.binding.matter/README.md index 25c1fe13cc7d4..6d717847d8f38 100644 --- a/bundles/org.openhab.binding.matter/README.md +++ b/bundles/org.openhab.binding.matter/README.md @@ -227,9 +227,10 @@ Possible channels include: | colorcontrol-temperature | Dimmer | Color Temperature | Sets the color temperature of the light | ColorLight | | | | | colorcontrol-temperature-abs | Number:Temperature | Color Temperature | Sets the color temperature of the light in mirek | ColorLight | | %.0f %unit% | | | doorlock-alarm | Trigger | Door Lock Alarm | Event that fires when a lock alarm occurs | | | | 0=Lock Jammed, 1=Lock Factory Reset, 3=Lock Radio Power Cycled, 4=Wrong Code Entry Limit, 5=Front Escutcheon Removed, 6=Door Forced Open, 7=Door Ajar, 8=Forced User | +| doorlock-boltstate | Switch | Door Bolt State | Bolts and unbolts the door and maintains the bolt state | Door | | | | | doorlock-doorstate | Contact | Door Sensor State | Door Sensor State | Door | true | | | | doorlock-lockoperationerror | Trigger | Lock Operation Error | Event that fires when a lock operation error occurs | | | | 0=Lock, 1=Unlock, 2=Non Access User Event, 3=Forced User Event, 4=Unlatch | -| doorlock-lockstate | Switch | Door Lock State | Locks and unlocks the door and maintains the lock state | Door | | | | +| doorlock-lockstate | Switch | Door Lock State | Locks and unlocks the door and maintains the lock state. If the door lock supports unbolting, this will reflect the latched state. | Door | | | | | electricalenergymeasurement-cumulativeenergyexported-energy | Number:Energy | Cumulative Energy Exported | The cumulative energy exported measurement | Energy | true | %.1f %unit% | | | electricalenergymeasurement-cumulativeenergyimported-energy | Number:Energy | Cumulative Energy Imported | The cumulative energy imported measurement | Energy | true | %.1f %unit% | | | electricalenergymeasurement-energymeasurmement-energy | Number:Energy | Energy | The measured energy | Energy | true | %.1f %unit% | | @@ -308,6 +309,7 @@ Possible channels include: | threadnetworkdiagnostics-routingrole | Number | Routing Role | The Thread routing role | Network | true | %d | 0=Unspecified, 1=Unassigned, 2=Sleepy End Device, 3=End Device, 4=Reed, 5=Router, 6=Leader | | wifinetworkdiagnostics-rssi | Number:Power | Signal | Wi-Fi signal strength indicator. | QualityOfService | true | %d %unit% | | | windowcovering-lift | Rollershutter | Window Covering Lift | Sets the window covering level - supporting open/close and up/down type commands | Blinds | | %.0f %% | | +>>>>>>> main ## Supported Matter Device Types diff --git a/bundles/org.openhab.binding.matter/src/main/java/org/openhab/binding/matter/internal/MatterBindingConstants.java b/bundles/org.openhab.binding.matter/src/main/java/org/openhab/binding/matter/internal/MatterBindingConstants.java index 853997fdb067f..c7290607bafe8 100644 --- a/bundles/org.openhab.binding.matter/src/main/java/org/openhab/binding/matter/internal/MatterBindingConstants.java +++ b/bundles/org.openhab.binding.matter/src/main/java/org/openhab/binding/matter/internal/MatterBindingConstants.java @@ -196,6 +196,9 @@ public class MatterBindingConstants { public static final String CHANNEL_ID_DOORLOCK_STATE = "doorlock-lockstate"; public static final ChannelTypeUID CHANNEL_DOORLOCK_STATE = new ChannelTypeUID(BINDING_ID, CHANNEL_ID_DOORLOCK_STATE); + public static final String CHANNEL_ID_DOORLOCK_BOLTSTATE = "doorlock-boltstate"; + public static final ChannelTypeUID CHANNEL_DOORLOCK_BOLTSTATE = new ChannelTypeUID(BINDING_ID, + CHANNEL_ID_DOORLOCK_BOLTSTATE); public static final String CHANNEL_ID_DOORLOCK_DOORSTATE = "doorlock-doorstate"; public static final ChannelTypeUID CHANNEL_DOORLOCK_DOORSTATE = new ChannelTypeUID(BINDING_ID, CHANNEL_ID_DOORLOCK_DOORSTATE); diff --git a/bundles/org.openhab.binding.matter/src/main/java/org/openhab/binding/matter/internal/controller/devices/converter/DoorLockConverter.java b/bundles/org.openhab.binding.matter/src/main/java/org/openhab/binding/matter/internal/controller/devices/converter/DoorLockConverter.java index 6b5f29314deae..080f1970fd625 100644 --- a/bundles/org.openhab.binding.matter/src/main/java/org/openhab/binding/matter/internal/controller/devices/converter/DoorLockConverter.java +++ b/bundles/org.openhab.binding.matter/src/main/java/org/openhab/binding/matter/internal/controller/devices/converter/DoorLockConverter.java @@ -63,6 +63,7 @@ import org.openhab.core.types.StateDescription; import org.openhab.core.types.StateDescriptionFragmentBuilder; import org.openhab.core.types.StateOption; +import org.openhab.core.types.UnDefType; /** * A converter for translating {@link DoorLockCluster} events and attributes to @@ -189,15 +190,32 @@ public DoorLockConverter(DoorLockCluster cluster, MatterBaseThingHandler handler channels.put(doorStateChannel, null); } + if (initializingCluster.featureMap.unbolting) { + Channel boltStateChannel = ChannelBuilder + .create(new ChannelUID(channelGroupUID, CHANNEL_ID_DOORLOCK_BOLTSTATE), CoreItemFactory.SWITCH) + .withType(CHANNEL_DOORLOCK_BOLTSTATE).build(); + channels.put(boltStateChannel, null); + } + return channels; } @Override public void handleCommand(ChannelUID channelUID, Command command) { if (command instanceof OnOffType onOffType) { + String channelId = channelUID.getIdWithoutGroup(); OctetString pinCode = getPinCodeForRemoteOperation(); - ClusterCommand doorLockCommand = onOffType == OnOffType.ON ? DoorLockCluster.lockDoor(pinCode) - : DoorLockCluster.unlockDoor(pinCode); + ClusterCommand doorLockCommand; + + if (channelId.equals(CHANNEL_ID_DOORLOCK_BOLTSTATE)) { + // Bolt state: lock (bolt) or unbolt + doorLockCommand = onOffType == OnOffType.ON ? DoorLockCluster.lockDoor(pinCode) + : DoorLockCluster.unboltDoor(pinCode); + } else { + // Lock state: lock or unlock (which unlatches) + doorLockCommand = onOffType == OnOffType.ON ? DoorLockCluster.lockDoor(pinCode) + : DoorLockCluster.unlockDoor(pinCode); + } handler.sendClusterCommand(endpointNumber, DoorLockCluster.CLUSTER_NAME, doorLockCommand); } super.handleCommand(channelUID, command); @@ -208,8 +226,7 @@ public void onEvent(AttributeChangedMessage message) { switch (message.path.attributeName) { case DoorLockCluster.ATTRIBUTE_LOCK_STATE: if (message.value instanceof DoorLockCluster.LockStateEnum lockState) { - updateState(CHANNEL_ID_DOORLOCK_STATE, - lockState == DoorLockCluster.LockStateEnum.LOCKED ? OnOffType.ON : OnOffType.OFF); + updateLockState(lockState); } break; case DoorLockCluster.ATTRIBUTE_DOOR_STATE: @@ -277,8 +294,7 @@ public void onEvent(EventTriggeredMessage message) { @Override public void initState() { - updateState(CHANNEL_ID_DOORLOCK_STATE, - initializingCluster.lockState == DoorLockCluster.LockStateEnum.LOCKED ? OnOffType.ON : OnOffType.OFF); + updateLockState(initializingCluster.lockState); if (initializingCluster.featureMap.doorPositionSensor) { updateState(CHANNEL_ID_DOORLOCK_DOORSTATE, @@ -964,4 +980,42 @@ private String buildPinCodePattern(int minLength, int maxLength) { private String buildPinCodeDescription(String descriptionKey) { return handler.getTranslation(descriptionKey, minPinCodeLength, maxPinCodeLength); } + + /** + * Updates the lock state and bolt state channels based on the lock state enum. + * + * @param lockState The lock state from the door lock cluster + */ + private void updateLockState(DoorLockCluster.LockStateEnum lockState) { + switch (lockState) { + case LOCKED: + // Both the lock and bolt state are locked + updateState(CHANNEL_ID_DOORLOCK_STATE, OnOffType.ON); + if (initializingCluster.featureMap.unbolting) { + updateState(CHANNEL_ID_DOORLOCK_BOLTSTATE, OnOffType.ON); + } + break; + case UNLOCKED: + // Both the lock and bolt state are unlocked + updateState(CHANNEL_ID_DOORLOCK_STATE, OnOffType.OFF); + if (initializingCluster.featureMap.unbolting) { + updateState(CHANNEL_ID_DOORLOCK_BOLTSTATE, OnOffType.OFF); + } + break; + case UNLATCHED: + // The lock state is locked (latched), but the bolt state is unlocked + updateState(CHANNEL_ID_DOORLOCK_STATE, OnOffType.ON); + if (initializingCluster.featureMap.unbolting) { + updateState(CHANNEL_ID_DOORLOCK_BOLTSTATE, OnOffType.OFF); + } + break; + case NOT_FULLY_LOCKED: + // We don't know the state of the lock or bolt, something is wrong + updateState(CHANNEL_ID_DOORLOCK_STATE, UnDefType.UNDEF); + if (initializingCluster.featureMap.unbolting) { + updateState(CHANNEL_ID_DOORLOCK_BOLTSTATE, UnDefType.UNDEF); + } + break; + } + } } diff --git a/bundles/org.openhab.binding.matter/src/main/resources/OH-INF/i18n/matter.properties b/bundles/org.openhab.binding.matter/src/main/resources/OH-INF/i18n/matter.properties index 46cdaf0c3dd48..85a8351d1744d 100644 --- a/bundles/org.openhab.binding.matter/src/main/resources/OH-INF/i18n/matter.properties +++ b/bundles/org.openhab.binding.matter/src/main/resources/OH-INF/i18n/matter.properties @@ -83,12 +83,14 @@ channel-type.matter.concentrationmeasurement-peakmeasuredvalue.label = Peak Conc channel-type.matter.concentrationmeasurement-peakmeasuredvalue.description = Indicates the peak (maximum) concentration measured during the measurement window. channel-type.matter.doorlock-alarm.label = Door Lock Alarm channel-type.matter.doorlock-alarm.description = Event that fires when a lock alarm occurs with a payload containing the alarm code +channel-type.matter.doorlock-boltstate.label = Door Bolt State +channel-type.matter.doorlock-boltstate.description = Bolts and unbolts the door and maintains the bolt state. channel-type.matter.doorlock-doorstate.label = Door Sensor State channel-type.matter.doorlock-doorstate.description = Door Sensor State channel-type.matter.doorlock-lockoperationerror.label = Door Lock Lock Operation Error channel-type.matter.doorlock-lockoperationerror.description = Event that fires when a lock operation error occurs with a payload containing the lock operation type channel-type.matter.doorlock-lockstate.label = Door Lock State -channel-type.matter.doorlock-lockstate.description = Locks and unlocks the door and maintains the lock state +channel-type.matter.doorlock-lockstate.description = Locks and unlocks the door and maintains the lock state. If the door lock supports unbolting, this will reflect the latched state. channel-type.matter.electricalenergymeasurement-energymeasurmement-energy.label = Energy channel-type.matter.electricalpowermeasurement-activecurrent.label = Active Current channel-type.matter.electricalpowermeasurement-activepower.label = Active Power diff --git a/bundles/org.openhab.binding.matter/src/main/resources/OH-INF/thing/channels.xml b/bundles/org.openhab.binding.matter/src/main/resources/OH-INF/thing/channels.xml index 8e00aff4b23b6..78bb8528dfd73 100644 --- a/bundles/org.openhab.binding.matter/src/main/resources/OH-INF/thing/channels.xml +++ b/bundles/org.openhab.binding.matter/src/main/resources/OH-INF/thing/channels.xml @@ -393,7 +393,19 @@ Switch - Locks and unlocks the door and maintains the lock state + Locks and unlocks the door and maintains the lock state. If the door lock supports unbolting, this will + reflect the latched state. + + Status + LockState + + veto + + + + Switch + + Bolts and unbolts the door and maintains the bolt state. Status LockState