lock.py 2.9 KB

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