lock.py 3.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108
  1. """
  2. Platform to control Tuya lock devices.
  3. Initial implementation is based on the secondary child-lock feature of Goldair
  4. climate devices.
  5. """
  6. from homeassistant.components.lock import LockEntity
  7. from ..device import TuyaLocalDevice
  8. from ..helpers.device_config import TuyaEntityConfig
  9. from ..helpers.mixin import TuyaLocalEntity
  10. class TuyaLocalLock(TuyaLocalEntity, LockEntity):
  11. """Representation of a Tuya Wi-Fi connected lock."""
  12. def __init__(self, device: TuyaLocalDevice, config: TuyaEntityConfig):
  13. """
  14. Initialise the lock.
  15. Args:
  16. device (TuyaLocalDevice): The device API instance.
  17. config (TuyaEntityConfig): The configuration for this entity.
  18. """
  19. dps_map = self._init_begin(device, config)
  20. self._lock_dp = dps_map.pop("lock", None)
  21. self._unlock_fp_dp = dps_map.pop("unlock_fingerprint", None)
  22. self._unlock_pw_dp = dps_map.pop("unlock_password", None)
  23. self._unlock_tmppw_dp = dps_map.pop("unlock_temp_pwd", None)
  24. self._unlock_dynpw_dp = dps_map.pop("unlock_dynamic_pwd", None)
  25. self._unlock_card_dp = dps_map.pop("unlock_card", None)
  26. self._unlock_app_dp = dps_map.pop("unlock_app", None)
  27. self._unlock_key_dp = dps_map.pop("unlock_key", None)
  28. self._req_unlock_dp = dps_map.pop("request_unlock", None)
  29. self._approve_unlock_dp = dps_map.pop("approve_unlock", None)
  30. self._req_intercom_dp = dps_map.pop("request_intercom", None)
  31. self._approve_intercom_dp = dps_map.pop("approve_intercom", None)
  32. self._jam_dp = dps_map.pop("jammed", None)
  33. self._init_end(dps_map)
  34. @property
  35. def is_locked(self):
  36. """Return the a boolean representing whether the lock is locked."""
  37. lock = None
  38. if self._lock_dp:
  39. lock = self._lock_dp.get_value(self._device)
  40. else:
  41. for d in (
  42. self._unlock_card_dp,
  43. self._unlock_dynpw_dp,
  44. self._unlock_fp_dp,
  45. self._unlock_pw_dp,
  46. self._unlock_tmppw_dp,
  47. self._unlock_app_dp,
  48. self._unlock_key_dp,
  49. ):
  50. if d:
  51. if d.get_value(self._device):
  52. lock = False
  53. elif lock is None:
  54. lock = True
  55. return lock
  56. @property
  57. def is_jammed(self):
  58. if self._jam_dp:
  59. return self._jam_dp.get_value(self._device)
  60. def unlocker_id(self, dp, type):
  61. if dp:
  62. id = dp.get_value(self._device)
  63. if id:
  64. if id is True:
  65. return f"{type}"
  66. else:
  67. return f"{type} #{id}"
  68. @property
  69. def changed_by(self):
  70. for dp, desc in {
  71. self._unlock_app_dp: "App",
  72. self._unlock_card_dp: "Card",
  73. self._unlock_dynpw_dp: "Dynamic Password",
  74. self._unlock_fp_dp: "Finger",
  75. self._unlock_key_dp: "Key",
  76. self._unlock_pw_dp: "Password",
  77. self._unlock_tmppw_dp: "Temporary Password",
  78. }.items():
  79. by = self.unlocker_id(dp, desc)
  80. if by:
  81. return by
  82. async def async_lock(self, **kwargs):
  83. """Lock the lock."""
  84. if self._lock_dp:
  85. await self._lock_dp.async_set_value(self._device, True)
  86. else:
  87. raise NotImplementedError()
  88. async def async_unlock(self, **kwargs):
  89. """Unlock the lock."""
  90. if self._lock_dp:
  91. await self._lock_dp.async_set_value(self._device, False)
  92. elif self._approve_unlock_dp:
  93. if self._req_unlock_dp and not self._req_unlock_dp.get_value(self._device):
  94. raise TimeoutError()
  95. await self._approve_unlock_dp.async_set_value(self._device, True)
  96. else:
  97. raise NotImplementedError()