ceiling_light.py 3.3 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192
  1. from __future__ import annotations
  2. import logging
  3. from typing import Any
  4. from ..const.light import DEFAULT_COLOR_TEMP, CeilingLightColorMode
  5. from .base_light import SwitchbotSequenceBaseLight
  6. from .device import REQ_HEADER, update_after_operation
  7. CEILING_LIGHT_COMMAND_HEADER = "5401"
  8. CEILING_LIGHT_REQUEST = f"{REQ_HEADER}5501"
  9. CEILING_LIGHT_COMMAND = f"{REQ_HEADER}{CEILING_LIGHT_COMMAND_HEADER}"
  10. CEILING_LIGHT_ON_KEY = f"{CEILING_LIGHT_COMMAND}01FF01FFFF"
  11. CEILING_LIGHT_OFF_KEY = f"{CEILING_LIGHT_COMMAND}02FF01FFFF"
  12. CW_BRIGHTNESS_KEY = f"{CEILING_LIGHT_COMMAND}010001"
  13. BRIGHTNESS_KEY = f"{CEILING_LIGHT_COMMAND}01FF01"
  14. DEVICE_GET_VERSION_KEY = "5702"
  15. DEVICE_GET_BASIC_SETTINGS_KEY = "570f5581"
  16. _LOGGER = logging.getLogger(__name__)
  17. class SwitchbotCeilingLight(SwitchbotSequenceBaseLight):
  18. """Representation of a Switchbot ceiling light."""
  19. @property
  20. def color_modes(self) -> set[CeilingLightColorMode]:
  21. """Return the supported color modes."""
  22. return {CeilingLightColorMode.COLOR_TEMP}
  23. @property
  24. def color_mode(self) -> CeilingLightColorMode:
  25. """Return the current color mode."""
  26. return CeilingLightColorMode(self._get_adv_value("color_mode") or 10)
  27. @update_after_operation
  28. async def turn_on(self) -> bool:
  29. """Turn device on."""
  30. result = await self._send_command(CEILING_LIGHT_ON_KEY)
  31. return self._check_command_result(result, 0, {1})
  32. @update_after_operation
  33. async def turn_off(self) -> bool:
  34. """Turn device off."""
  35. result = await self._send_command(CEILING_LIGHT_OFF_KEY)
  36. return self._check_command_result(result, 0, {1})
  37. @update_after_operation
  38. async def set_brightness(self, brightness: int) -> bool:
  39. """Set brightness."""
  40. assert 0 <= brightness <= 100, "Brightness must be between 0 and 100"
  41. color_temp = self._state.get("cw", DEFAULT_COLOR_TEMP)
  42. result = await self._send_command(
  43. f"{BRIGHTNESS_KEY}{brightness:02X}{color_temp:04X}"
  44. )
  45. return self._check_command_result(result, 0, {1})
  46. @update_after_operation
  47. async def set_color_temp(self, brightness: int, color_temp: int) -> bool:
  48. """Set color temp."""
  49. assert 0 <= brightness <= 100, "Brightness must be between 0 and 100"
  50. assert 2700 <= color_temp <= 6500, "Color Temp must be between 2700 and 6500"
  51. result = await self._send_command(
  52. f"{CW_BRIGHTNESS_KEY}{brightness:02X}{color_temp:04X}"
  53. )
  54. return self._check_command_result(result, 0, {1})
  55. async def get_basic_info(self) -> dict[str, Any] | None:
  56. """Get device basic settings."""
  57. if not (_data := await self._get_basic_info(DEVICE_GET_BASIC_SETTINGS_KEY)):
  58. return None
  59. if not (_version_info := await self._get_basic_info(DEVICE_GET_VERSION_KEY)):
  60. return None
  61. _LOGGER.debug(
  62. "data: %s, version info: %s, address: %s",
  63. _data,
  64. _version_info,
  65. self._device.address,
  66. )
  67. self._state["cw"] = int.from_bytes(_data[3:5], "big")
  68. return {
  69. "isOn": bool(_data[1] & 0b10000000),
  70. "color_mode": _data[1] & 0b01000000,
  71. "brightness": _data[2] & 0b01111111,
  72. "cw": self._state["cw"],
  73. "firmware": _version_info[2] / 10.0,
  74. }