lock.py 3.2 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798
  1. """Lock parser."""
  2. from __future__ import annotations
  3. import logging
  4. from ..const.lock import LockStatus
  5. _LOGGER = logging.getLogger(__name__)
  6. def process_wolock(data: bytes | None, mfr_data: bytes | None) -> dict[str, bool | int]:
  7. """Support for lock and lock lite process data."""
  8. common_data = process_locklite(data, mfr_data)
  9. if not common_data:
  10. return {}
  11. common_data["door_open"] = bool(mfr_data[7] & 0b00000100)
  12. common_data["unclosed_alarm"] = bool(mfr_data[8] & 0b00100000)
  13. common_data["auto_lock_paused"] = bool(mfr_data[8] & 0b00000010)
  14. return common_data
  15. def process_locklite(
  16. data: bytes | None, mfr_data: bytes | None
  17. ) -> dict[str, bool | int]:
  18. """Support for lock lite process data."""
  19. if mfr_data is None:
  20. return {}
  21. _LOGGER.debug("mfr_data: %s", mfr_data.hex())
  22. if data:
  23. _LOGGER.debug("data: %s", data.hex())
  24. return {
  25. "sequence_number": mfr_data[6],
  26. "battery": data[2] & 0b01111111 if data else None,
  27. "calibration": bool(mfr_data[7] & 0b10000000),
  28. "status": LockStatus((mfr_data[7] & 0b01110000) >> 4),
  29. "update_from_secondary_lock": bool(mfr_data[7] & 0b00001000),
  30. "double_lock_mode": bool(mfr_data[8] & 0b10000000),
  31. "unlocked_alarm": bool(mfr_data[8] & 0b00010000),
  32. "night_latch": bool(mfr_data[9] & 0b00000001) if len(mfr_data) > 9 else False,
  33. }
  34. def parse_common_data(mfr_data: bytes | None) -> dict[str, bool | int]:
  35. if mfr_data is None:
  36. return {}
  37. _LOGGER.debug("mfr_data: %s", mfr_data.hex())
  38. return {
  39. "sequence_number": mfr_data[6],
  40. "calibration": bool(mfr_data[7] & 0b10000000),
  41. "status": LockStatus((mfr_data[7] & 0b01111000) >> 3),
  42. "update_from_secondary_lock": bool(mfr_data[8] & 0b11000000),
  43. "door_open_from_secondary_lock": bool(mfr_data[8] & 0b00100000),
  44. "door_open": bool(mfr_data[8] & 0b00010000),
  45. "auto_lock_paused": bool(mfr_data[8] & 0b00001000),
  46. "battery": mfr_data[9] & 0b01111111,
  47. "double_lock_mode": bool(mfr_data[10] & 0b10000000),
  48. "is_secondary_lock": bool(mfr_data[10] & 0b01000000),
  49. "manual_unlock_linkage": bool(mfr_data[10] & 0b00100000),
  50. "unclosed_alarm": bool(mfr_data[11] & 0b10000000),
  51. "unlocked_alarm": bool(mfr_data[11] & 0b01000000),
  52. "night_latch": False,
  53. }
  54. def process_wolock_pro(
  55. data: bytes | None, mfr_data: bytes | None
  56. ) -> dict[str, bool | int]:
  57. """Support for lock pro process data."""
  58. common_data = parse_common_data(mfr_data)
  59. if not common_data:
  60. return {}
  61. lock_pro_data = {
  62. "low_temperature_alarm": bool(mfr_data[11] & 0b00100000),
  63. "left_battery_compartment_alarm": mfr_data[11] & 0b000000100,
  64. "right_battery_compartment_alarm": mfr_data[11] & 0b000000010,
  65. }
  66. return common_data | lock_pro_data
  67. def process_lock2(data: bytes | None, mfr_data: bytes | None) -> dict[str, bool | int]:
  68. """Support for lock2 process data."""
  69. common_data = parse_common_data(mfr_data)
  70. if not common_data:
  71. return {}
  72. lock2_data = {
  73. "power_alarm": bool(mfr_data[11] & 0b00010000),
  74. "battery_status": mfr_data[11] & 0b00000111,
  75. }
  76. return common_data | lock2_data