base_light.py 3.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109
  1. from __future__ import annotations
  2. import asyncio
  3. import logging
  4. import time
  5. from abc import abstractmethod
  6. from typing import Any
  7. from ..models import SwitchBotAdvertisement
  8. from .device import ColorMode, SwitchbotDevice
  9. _LOGGER = logging.getLogger(__name__)
  10. class SwitchbotBaseLight(SwitchbotDevice):
  11. """Representation of a Switchbot light."""
  12. def __init__(self, *args: Any, **kwargs: Any) -> None:
  13. """Switchbot bulb constructor."""
  14. super().__init__(*args, **kwargs)
  15. self._state: dict[str, Any] = {}
  16. @property
  17. def on(self) -> bool | None:
  18. """Return if bulb is on."""
  19. return self.is_on()
  20. @property
  21. def rgb(self) -> tuple[int, int, int] | None:
  22. """Return the current rgb value."""
  23. if "r" not in self._state or "g" not in self._state or "b" not in self._state:
  24. return None
  25. return self._state["r"], self._state["g"], self._state["b"]
  26. @property
  27. def color_temp(self) -> int | None:
  28. """Return the current color temp value."""
  29. return self._state.get("cw") or self.min_temp
  30. @property
  31. def brightness(self) -> int | None:
  32. """Return the current brightness value."""
  33. return self._get_adv_value("brightness") or 0
  34. @property
  35. def color_mode(self) -> ColorMode:
  36. """Return the current color mode."""
  37. return ColorMode(self._get_adv_value("color_mode") or 0)
  38. @property
  39. def min_temp(self) -> int:
  40. """Return minimum color temp."""
  41. return 2700
  42. @property
  43. def max_temp(self) -> int:
  44. """Return maximum color temp."""
  45. return 6500
  46. def is_on(self) -> bool | None:
  47. """Return bulb state from cache."""
  48. return self._get_adv_value("isOn")
  49. @abstractmethod
  50. async def turn_on(self) -> bool:
  51. """Turn device on."""
  52. @abstractmethod
  53. async def turn_off(self) -> bool:
  54. """Turn device off."""
  55. @abstractmethod
  56. async def set_brightness(self, brightness: int) -> bool:
  57. """Set brightness."""
  58. @abstractmethod
  59. async def set_color_temp(self, brightness: int, color_temp: int) -> bool:
  60. """Set color temp."""
  61. @abstractmethod
  62. async def set_rgb(self, brightness: int, r: int, g: int, b: int) -> bool:
  63. """Set rgb."""
  64. def poll_needed(self, last_poll_time: float | None) -> bool:
  65. """Return if poll is needed."""
  66. return False
  67. async def update(self) -> None:
  68. """Update device data."""
  69. self._last_full_update = time.monotonic()
  70. class SwitchbotSequenceBaseLight(SwitchbotBaseLight):
  71. """Representation of a Switchbot light."""
  72. def update_from_advertisement(self, advertisement: SwitchBotAdvertisement) -> None:
  73. """Update device data from advertisement."""
  74. current_state = self._get_adv_value("sequence_number")
  75. super().update_from_advertisement(advertisement)
  76. new_state = self._get_adv_value("sequence_number")
  77. _LOGGER.debug(
  78. "%s: update advertisement: %s (seq before: %s) (seq after: %s)",
  79. self.name,
  80. advertisement,
  81. current_state,
  82. new_state,
  83. )
  84. if current_state != new_state:
  85. asyncio.ensure_future(self.update())