lock.py 3.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100
  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._req_unlock_dp = dps_map.pop("request_unlock", None)
  28. self._approve_unlock_dp = dps_map.pop("approve_unlock", None)
  29. self._jam_dp = dps_map.pop("jammed", None)
  30. self._init_end(dps_map)
  31. @property
  32. def is_locked(self):
  33. """Return the a boolean representing whether the lock is locked."""
  34. lock = None
  35. if self._lock_dp:
  36. lock = self._lock_dp.get_value(self._device)
  37. else:
  38. for d in (
  39. self._unlock_card_dp,
  40. self._unlock_dynpw_dp,
  41. self._unlock_fp_dp,
  42. self._unlock_pw_dp,
  43. self._unlock_tmppw_dp,
  44. self._unlock_app_dp,
  45. ):
  46. if d:
  47. if d.get_value(self._device):
  48. lock = False
  49. elif lock is None:
  50. lock = True
  51. return lock
  52. @property
  53. def is_jammed(self):
  54. if self._jam_dp:
  55. return self._jam_dp.get_value(self._device)
  56. def unlocker_id(self, dp, type):
  57. if dp:
  58. id = dp.get_value(self._device)
  59. if id:
  60. return f"{type} #{id}"
  61. @property
  62. def changed_by(self):
  63. for dp, desc in {
  64. self._unlock_app_dp: "App",
  65. self._unlock_card_dp: "Card",
  66. self._unlock_dynpw_dp: "Dynamic Password",
  67. self._unlock_fp_dp: "Finger",
  68. self._unlock_pw_dp: "Password",
  69. self._unlock_tmppw_dp: "Temporary Password",
  70. }.items():
  71. by = self.unlocker_id(dp, desc)
  72. if by:
  73. return by
  74. async def async_lock(self, **kwargs):
  75. """Lock the lock."""
  76. if self._lock_dp:
  77. await self._lock_dp.async_set_value(self._device, True)
  78. else:
  79. raise NotImplementedError()
  80. async def async_unlock(self, **kwargs):
  81. """Unlock the lock."""
  82. if self._lock_dp:
  83. await self._lock_dp.async_set_value(self._device, False)
  84. elif self._approve_unlock_dp:
  85. if self._req_unlock_dp and not self._req_unlock_dp.get_value(self._device):
  86. raise TimeoutError()
  87. await self._approve_unlock_dp.async_set_value(self._device, True)
  88. else:
  89. raise NotImplementedError()