humidifier.py 3.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107
  1. """Humidifier adv parser."""
  2. from __future__ import annotations
  3. import logging
  4. from datetime import timedelta
  5. from ..const.evaporative_humidifier import (
  6. HumidifierMode,
  7. HumidifierWaterLevel,
  8. )
  9. from ..helpers import celsius_to_fahrenheit
  10. _LOGGER = logging.getLogger(__name__)
  11. # mfr_data: 943cc68d3d2e
  12. # data: 650000cd802b6300
  13. # data: 650000cd802b6300
  14. # data: 658000c9802b6300
  15. # Low: 658000c5222b6300
  16. # Med: 658000c5432b6300
  17. # High: 658000c5642b6300
  18. def calculate_temperature_and_humidity(
  19. data: bytes, is_meter_binded: bool = True
  20. ) -> tuple[float | None, float | None, int | None]:
  21. """Calculate temperature and humidity based on the given flag."""
  22. if len(data) < 3 or not is_meter_binded:
  23. return None, None, None
  24. humidity = data[0] & 0b01111111
  25. if humidity > 100:
  26. return None, None, None
  27. _temp_sign = 1 if data[1] & 0b10000000 else -1
  28. _temp_c = _temp_sign * ((data[1] & 0b01111111) + ((data[2] >> 4) / 10))
  29. _temp_f = celsius_to_fahrenheit(_temp_c)
  30. return _temp_c, _temp_f, humidity
  31. def process_wohumidifier(
  32. data: bytes | None, mfr_data: bytes | None
  33. ) -> dict[str, bool | int]:
  34. """Process WoHumi services data."""
  35. if data is None:
  36. return {
  37. "isOn": None,
  38. "level": None,
  39. "switchMode": True,
  40. }
  41. return {
  42. "isOn": bool(data[1]),
  43. "level": data[4],
  44. "switchMode": True,
  45. }
  46. def process_evaporative_humidifier(
  47. data: bytes | None, mfr_data: bytes | None
  48. ) -> dict[str, bool | int]:
  49. """Process WoHumi services data."""
  50. if mfr_data is None:
  51. return {}
  52. seq_number = mfr_data[6]
  53. is_on = bool(mfr_data[7] & 0b10000000)
  54. mode = HumidifierMode(mfr_data[7] & 0b00001111)
  55. over_humidify_protection = bool(mfr_data[8] & 0b10000000)
  56. child_lock = bool(mfr_data[8] & 0b00100000)
  57. tank_removed = bool(mfr_data[8] & 0b00000100)
  58. tilted_alert = bool(mfr_data[8] & 0b00000010)
  59. filter_missing = bool(mfr_data[8] & 0b00000001)
  60. is_meter_binded = bool(mfr_data[9] & 0b10000000)
  61. _temp_c, _temp_f, humidity = calculate_temperature_and_humidity(
  62. mfr_data[9:12], is_meter_binded
  63. )
  64. water_level = HumidifierWaterLevel(mfr_data[11] & 0b00000011).name.lower()
  65. filter_run_time = timedelta(
  66. hours=int.from_bytes(mfr_data[12:14], byteorder="big") & 0xFFF
  67. )
  68. target_humidity = mfr_data[16] & 0b01111111
  69. return {
  70. "seq_number": seq_number,
  71. "isOn": is_on,
  72. "mode": mode,
  73. "over_humidify_protection": over_humidify_protection,
  74. "child_lock": child_lock,
  75. "tank_removed": tank_removed,
  76. "tilted_alert": tilted_alert,
  77. "filter_missing": filter_missing,
  78. "is_meter_binded": is_meter_binded,
  79. "humidity": humidity,
  80. "temperature": _temp_c,
  81. "temp": {"c": _temp_c, "f": _temp_f},
  82. "water_level": water_level,
  83. "filter_run_time": filter_run_time,
  84. "filter_alert": filter_run_time.days >= 10,
  85. "target_humidity": target_humidity,
  86. }