Browse Source

lock: Support open action and is_opened property.

Issue #1931
Available in HA 2024.5 and later
Jason Rumney 1 year ago
parent
commit
7251b3ae24

+ 2 - 1
custom_components/tuya_local/devices/README.md

@@ -646,7 +646,8 @@ Humidifer can also cover dehumidifiers (use class to specify which).
 The unlock... dps below are normally integers, but can also be boolean, in which case
 The unlock... dps below are normally integers, but can also be boolean, in which case
 no information will be available about which specific credential was used to unlock the lock.
 no information will be available about which specific credential was used to unlock the lock.
 
 
-- **lock** (optional, boolean): a dp to control the lock state: true = locked, false = unlocked
+- **lock** (optional, boolean): a dp to control the lock state: true = locked, false = unlocked.
+- **open** (optional, boolean): a dp to open or close the door or gate controlled by the lock, or if marked readonly to report the open status.
 - **unlock_fingerprint** (optional, integer): a dp to identify the fingerprint used to unlock the lock.
 - **unlock_fingerprint** (optional, integer): a dp to identify the fingerprint used to unlock the lock.
 - **unlock_password** (optional, integer): a dp to identify the password used to unlock the lock.
 - **unlock_password** (optional, integer): a dp to identify the password used to unlock the lock.
 - **unlock_temp_pwd** (optional, integer): a dp to identify the temporary password used to unlock the lock.
 - **unlock_temp_pwd** (optional, integer): a dp to identify the temporary password used to unlock the lock.

+ 14 - 1
custom_components/tuya_local/lock.py

@@ -2,7 +2,7 @@
 Setup for different kinds of Tuya lock devices
 Setup for different kinds of Tuya lock devices
 """
 """
 
 
-from homeassistant.components.lock import LockEntity
+from homeassistant.components.lock import LockEntity, LockEntityFeature
 
 
 from .device import TuyaLocalDevice
 from .device import TuyaLocalDevice
 from .helpers.config import async_tuya_setup_platform
 from .helpers.config import async_tuya_setup_platform
@@ -34,6 +34,7 @@ class TuyaLocalLock(TuyaLocalEntity, LockEntity):
         super().__init__()
         super().__init__()
         dps_map = self._init_begin(device, config)
         dps_map = self._init_begin(device, config)
         self._lock_dp = dps_map.pop("lock", None)
         self._lock_dp = dps_map.pop("lock", None)
+        self._open_dp = dps_map.pop("open", None)
         self._unlock_fp_dp = dps_map.pop("unlock_fingerprint", None)
         self._unlock_fp_dp = dps_map.pop("unlock_fingerprint", None)
         self._unlock_pw_dp = dps_map.pop("unlock_password", None)
         self._unlock_pw_dp = dps_map.pop("unlock_password", None)
         self._unlock_tmppw_dp = dps_map.pop("unlock_temp_pwd", None)
         self._unlock_tmppw_dp = dps_map.pop("unlock_temp_pwd", None)
@@ -52,6 +53,8 @@ class TuyaLocalLock(TuyaLocalEntity, LockEntity):
         self._approve_intercom_dp = dps_map.pop("approve_intercom", None)
         self._approve_intercom_dp = dps_map.pop("approve_intercom", None)
         self._jam_dp = dps_map.pop("jammed", None)
         self._jam_dp = dps_map.pop("jammed", None)
         self._init_end(dps_map)
         self._init_end(dps_map)
+        if self._open_dp and not self._open_dp.readonly:
+            self._attr_supported_features = LockEntityFeature.OPEN
 
 
     @property
     @property
     def is_locked(self):
     def is_locked(self):
@@ -81,6 +84,11 @@ class TuyaLocalLock(TuyaLocalEntity, LockEntity):
                         lock = True
                         lock = True
         return lock
         return lock
 
 
+    @property
+    def is_open(self):
+        if self._open_dp:
+            return self._open_dp.get_value(self._device)
+
     @property
     @property
     def is_jammed(self):
     def is_jammed(self):
         if self._jam_dp:
         if self._jam_dp:
@@ -143,3 +151,8 @@ class TuyaLocalLock(TuyaLocalEntity, LockEntity):
             await self._approve_intercom_dp.async_set_value(self._device, True)
             await self._approve_intercom_dp.async_set_value(self._device, True)
         else:
         else:
             raise NotImplementedError()
             raise NotImplementedError()
+
+    async def async_open(self, **kwargs):
+        """Open the door latch."""
+        if self._open_dp:
+            await self._open_dp.async_set_value(self._device, True)