Browse Source

Restore ColorMode methods for backwards compat (#356)

J. Nick Koston 1 ngày trước cách đây
mục cha
commit
fa141f7b89

+ 2 - 0
switchbot/__init__.py

@@ -13,6 +13,7 @@ from .const import (
     AirPurifierMode,
     BulbColorMode,
     CeilingLightColorMode,
+    ColorMode,
     FanMode,
     HumidifierAction,
     HumidifierMode,
@@ -48,6 +49,7 @@ __all__ = [
     "AirPurifierMode",
     "BulbColorMode",
     "CeilingLightColorMode",
+    "ColorMode",
     "FanMode",
     "GetSwitchbotDevices",
     "HumidifierAction",

+ 7 - 1
switchbot/const/__init__.py

@@ -10,7 +10,12 @@ from .evaporative_humidifier import (
     HumidifierWaterLevel,
 )
 from .fan import FanMode
-from .light import BulbColorMode, CeilingLightColorMode, StripLightColorMode
+from .light import (
+    BulbColorMode,
+    CeilingLightColorMode,
+    ColorMode,
+    StripLightColorMode,
+)
 
 # Preserve old LockStatus export for backwards compatibility
 from .lock import LockStatus
@@ -97,6 +102,7 @@ __all__ = [
     "AirPurifierMode",
     "BulbColorMode",
     "CeilingLightColorMode",
+    "ColorMode",
     "FanMode",
     "HumidifierAction",
     "HumidifierMode",

+ 7 - 0
switchbot/const/light.py

@@ -1,6 +1,13 @@
 from enum import Enum
 
 
+class ColorMode(Enum):
+    OFF = 0
+    COLOR_TEMP = 1
+    RGB = 2
+    EFFECT = 3
+
+
 class StripLightColorMode(Enum):
     RGB = 2
     SCENE = 3

+ 14 - 5
switchbot/devices/bulb.py

@@ -3,7 +3,7 @@ from __future__ import annotations
 import logging
 from typing import Any
 
-from ..const.light import BulbColorMode
+from ..const.light import BulbColorMode, ColorMode
 from .base_light import SwitchbotSequenceBaseLight
 from .device import REQ_HEADER, SwitchbotOperationError, update_after_operation
 
@@ -32,19 +32,28 @@ EFFECT_DICT = {
     "Breathing": "570F4701010302",
 }
 
+# Private mapping from device-specific color modes to original ColorMode enum
+_BULB_COLOR_MODE_MAP = {
+    BulbColorMode.COLOR_TEMP: ColorMode.COLOR_TEMP,
+    BulbColorMode.RGB: ColorMode.RGB,
+    BulbColorMode.DYNAMIC: ColorMode.EFFECT,
+    BulbColorMode.UNKNOWN: ColorMode.OFF,
+}
+
 
 class SwitchbotBulb(SwitchbotSequenceBaseLight):
     """Representation of a Switchbot bulb."""
 
     @property
-    def color_modes(self) -> set[BulbColorMode]:
+    def color_modes(self) -> set[ColorMode]:
         """Return the supported color modes."""
-        return {BulbColorMode.RGB, BulbColorMode.COLOR_TEMP}
+        return {ColorMode.RGB, ColorMode.COLOR_TEMP}
 
     @property
-    def color_mode(self) -> BulbColorMode:
+    def color_mode(self) -> ColorMode:
         """Return the current color mode."""
-        return BulbColorMode(self._get_adv_value("color_mode") or 10)
+        device_mode = BulbColorMode(self._get_adv_value("color_mode") or 10)
+        return _BULB_COLOR_MODE_MAP.get(device_mode, ColorMode.OFF)
 
     @property
     def get_effect_list(self) -> list[str]:

+ 18 - 5
switchbot/devices/ceiling_light.py

@@ -3,7 +3,11 @@ from __future__ import annotations
 import logging
 from typing import Any
 
-from ..const.light import DEFAULT_COLOR_TEMP, CeilingLightColorMode
+from ..const.light import (
+    DEFAULT_COLOR_TEMP,
+    CeilingLightColorMode,
+    ColorMode,
+)
 from .base_light import SwitchbotSequenceBaseLight
 from .device import REQ_HEADER, update_after_operation
 
@@ -21,19 +25,28 @@ DEVICE_GET_BASIC_SETTINGS_KEY = "570f5581"
 
 _LOGGER = logging.getLogger(__name__)
 
+# Private mapping from device-specific color modes to original ColorMode enum
+_CEILING_LIGHT_COLOR_MODE_MAP = {
+    CeilingLightColorMode.COLOR_TEMP: ColorMode.COLOR_TEMP,
+    CeilingLightColorMode.NIGHT: ColorMode.COLOR_TEMP,
+    CeilingLightColorMode.MUSIC: ColorMode.EFFECT,
+    CeilingLightColorMode.UNKNOWN: ColorMode.OFF,
+}
+
 
 class SwitchbotCeilingLight(SwitchbotSequenceBaseLight):
     """Representation of a Switchbot ceiling light."""
 
     @property
-    def color_modes(self) -> set[CeilingLightColorMode]:
+    def color_modes(self) -> set[ColorMode]:
         """Return the supported color modes."""
-        return {CeilingLightColorMode.COLOR_TEMP}
+        return {ColorMode.COLOR_TEMP}
 
     @property
-    def color_mode(self) -> CeilingLightColorMode:
+    def color_mode(self) -> ColorMode:
         """Return the current color mode."""
-        return CeilingLightColorMode(self._get_adv_value("color_mode") or 10)
+        device_mode = CeilingLightColorMode(self._get_adv_value("color_mode") or 10)
+        return _CEILING_LIGHT_COLOR_MODE_MAP.get(device_mode, ColorMode.OFF)
 
     @update_after_operation
     async def turn_on(self) -> bool:

+ 1 - 0
switchbot/devices/device.py

@@ -28,6 +28,7 @@ from ..api_config import SWITCHBOT_APP_API_BASE_URL, SWITCHBOT_APP_CLIENT_ID
 from ..const import (
     DEFAULT_RETRY_COUNT,
     DEFAULT_SCAN_TIMEOUT,
+    ColorMode,  # noqa: F401
     SwitchbotAccountConnectionError,
     SwitchbotApiError,
     SwitchbotAuthenticationError,

+ 18 - 7
switchbot/devices/light_strip.py

@@ -6,7 +6,7 @@ from typing import Any
 from bleak.backends.device import BLEDevice
 
 from ..const import SwitchbotModel
-from ..const.light import StripLightColorMode
+from ..const.light import ColorMode, StripLightColorMode
 from .base_light import SwitchbotSequenceBaseLight
 from .device import (
     REQ_HEADER,
@@ -109,19 +109,30 @@ EFFECT_DICT = {
     ],
 }
 
+# Private mapping from device-specific color modes to original ColorMode enum
+_STRIP_LIGHT_COLOR_MODE_MAP = {
+    StripLightColorMode.RGB: ColorMode.RGB,
+    StripLightColorMode.SCENE: ColorMode.EFFECT,
+    StripLightColorMode.MUSIC: ColorMode.EFFECT,
+    StripLightColorMode.CONTROLLER: ColorMode.EFFECT,
+    StripLightColorMode.COLOR_TEMP: ColorMode.COLOR_TEMP,
+    StripLightColorMode.UNKNOWN: ColorMode.OFF,
+}
+
 
 class SwitchbotLightStrip(SwitchbotSequenceBaseLight):
     """Representation of a Switchbot light strip."""
 
     @property
-    def color_modes(self) -> set[StripLightColorMode]:
+    def color_modes(self) -> set[ColorMode]:
         """Return the supported color modes."""
-        return {StripLightColorMode.RGB}
+        return {ColorMode.RGB}
 
     @property
-    def color_mode(self) -> StripLightColorMode:
+    def color_mode(self) -> ColorMode:
         """Return the current color mode."""
-        return StripLightColorMode(self._get_adv_value("color_mode") or 10)
+        device_mode = StripLightColorMode(self._get_adv_value("color_mode") or 10)
+        return _STRIP_LIGHT_COLOR_MODE_MAP.get(device_mode, ColorMode.OFF)
 
     @property
     def get_effect_list(self) -> list[str]:
@@ -233,9 +244,9 @@ class SwitchbotStripLight3(SwitchbotEncryptedDevice, SwitchbotLightStrip):
         )
 
     @property
-    def color_modes(self) -> set[StripLightColorMode]:
+    def color_modes(self) -> set[ColorMode]:
         """Return the supported color modes."""
-        return {StripLightColorMode.RGB, StripLightColorMode.COLOR_TEMP}
+        return {ColorMode.RGB, ColorMode.COLOR_TEMP}
 
     @update_after_operation
     async def set_color_temp(self, brightness: int, color_temp: int) -> bool:

+ 3 - 2
tests/test_bulb.py

@@ -4,6 +4,7 @@ import pytest
 from bleak.backends.device import BLEDevice
 
 from switchbot import SwitchBotAdvertisement, SwitchbotModel
+from switchbot.const.light import ColorMode
 from switchbot.devices import bulb
 from switchbot.devices.device import SwitchbotOperationError
 
@@ -62,8 +63,8 @@ async def test_default_info():
 
     assert device.is_on() is True
     assert device.on is True
-    assert device.color_mode == bulb.BulbColorMode.RGB
-    assert device.color_modes == {bulb.BulbColorMode.RGB, bulb.BulbColorMode.COLOR_TEMP}
+    assert device.color_mode == ColorMode.RGB
+    assert device.color_modes == {ColorMode.RGB, ColorMode.COLOR_TEMP}
     assert device.rgb == (30, 0, 0)
     assert device.color_temp == 3200
     assert device.brightness == 1

+ 3 - 2
tests/test_ceiling_light.py

@@ -4,6 +4,7 @@ import pytest
 from bleak.backends.device import BLEDevice
 
 from switchbot import SwitchBotAdvertisement, SwitchbotModel
+from switchbot.const.light import ColorMode
 from switchbot.devices import ceiling_light
 
 from .test_adv_parser import generate_ble_device
@@ -58,8 +59,8 @@ async def test_default_info():
 
     assert device.is_on() is False
     assert device.on is False
-    assert device.color_mode == ceiling_light.CeilingLightColorMode.NIGHT
-    assert device.color_modes == {ceiling_light.CeilingLightColorMode.COLOR_TEMP}
+    assert device.color_mode == ColorMode.COLOR_TEMP
+    assert device.color_modes == {ColorMode.COLOR_TEMP}
     assert device.color_temp == 3200
     assert device.brightness == 1
     assert device.min_temp == 2700

+ 88 - 0
tests/test_colormode_imports.py

@@ -0,0 +1,88 @@
+"""Test ColorMode imports for backward compatibility."""
+
+
+def test_colormode_import_from_main_module():
+    """Test that ColorMode can be imported from the main switchbot module."""
+    from switchbot import ColorMode
+
+    # Verify it's the enum we expect
+    assert hasattr(ColorMode, "OFF")
+    assert hasattr(ColorMode, "COLOR_TEMP")
+    assert hasattr(ColorMode, "RGB")
+    assert hasattr(ColorMode, "EFFECT")
+
+    # Verify the values
+    assert ColorMode.OFF.value == 0
+    assert ColorMode.COLOR_TEMP.value == 1
+    assert ColorMode.RGB.value == 2
+    assert ColorMode.EFFECT.value == 3
+
+
+def test_colormode_import_from_device_module():
+    """Test that ColorMode can be imported from switchbot.devices.device for backward compatibility."""
+    from switchbot.devices.device import ColorMode
+
+    # Verify it's the enum we expect
+    assert hasattr(ColorMode, "OFF")
+    assert hasattr(ColorMode, "COLOR_TEMP")
+    assert hasattr(ColorMode, "RGB")
+    assert hasattr(ColorMode, "EFFECT")
+
+    # Verify the values
+    assert ColorMode.OFF.value == 0
+    assert ColorMode.COLOR_TEMP.value == 1
+    assert ColorMode.RGB.value == 2
+    assert ColorMode.EFFECT.value == 3
+
+
+def test_colormode_import_from_const():
+    """Test that ColorMode can be imported from switchbot.const."""
+    from switchbot.const import ColorMode
+
+    # Verify it's the enum we expect
+    assert hasattr(ColorMode, "OFF")
+    assert hasattr(ColorMode, "COLOR_TEMP")
+    assert hasattr(ColorMode, "RGB")
+    assert hasattr(ColorMode, "EFFECT")
+
+    # Verify the values
+    assert ColorMode.OFF.value == 0
+    assert ColorMode.COLOR_TEMP.value == 1
+    assert ColorMode.RGB.value == 2
+    assert ColorMode.EFFECT.value == 3
+
+
+def test_colormode_import_from_const_light():
+    """Test that ColorMode can be imported from switchbot.const.light."""
+    from switchbot.const.light import ColorMode
+
+    # Verify it's the enum we expect
+    assert hasattr(ColorMode, "OFF")
+    assert hasattr(ColorMode, "COLOR_TEMP")
+    assert hasattr(ColorMode, "RGB")
+    assert hasattr(ColorMode, "EFFECT")
+
+    # Verify the values
+    assert ColorMode.OFF.value == 0
+    assert ColorMode.COLOR_TEMP.value == 1
+    assert ColorMode.RGB.value == 2
+    assert ColorMode.EFFECT.value == 3
+
+
+def test_all_colormode_imports_are_same_object():
+    """Test that all ColorMode imports reference the same enum object."""
+    from switchbot import ColorMode as ColorMode1
+    from switchbot.const import ColorMode as ColorMode3
+    from switchbot.const.light import ColorMode as ColorMode4
+    from switchbot.devices.device import ColorMode as ColorMode2
+
+    # They should all be the exact same object
+    assert ColorMode1 is ColorMode2
+    assert ColorMode2 is ColorMode3
+    assert ColorMode3 is ColorMode4
+
+    # And their members should be the same
+    assert ColorMode1.OFF is ColorMode2.OFF
+    assert ColorMode1.COLOR_TEMP is ColorMode3.COLOR_TEMP
+    assert ColorMode1.RGB is ColorMode4.RGB
+    assert ColorMode1.EFFECT is ColorMode2.EFFECT

+ 5 - 4
tests/test_strip_light.py

@@ -4,6 +4,7 @@ import pytest
 from bleak.backends.device import BLEDevice
 
 from switchbot import SwitchBotAdvertisement, SwitchbotModel
+from switchbot.const.light import ColorMode
 from switchbot.devices import light_strip
 from switchbot.devices.base_light import SwitchbotBaseLight
 from switchbot.devices.device import SwitchbotEncryptedDevice, SwitchbotOperationError
@@ -64,10 +65,10 @@ async def test_default_info():
 
     assert device.is_on() is True
     assert device.on is True
-    assert device.color_mode == light_strip.StripLightColorMode.RGB
+    assert device.color_mode == ColorMode.RGB
     assert device.color_modes == {
-        light_strip.StripLightColorMode.RGB,
-        light_strip.StripLightColorMode.COLOR_TEMP,
+        ColorMode.RGB,
+        ColorMode.COLOR_TEMP,
     }
     assert device.rgb == (30, 0, 0)
     assert device.color_temp == 3200
@@ -263,7 +264,7 @@ async def test_strip_light_supported_color_modes():
     device = create_strip_light_device()
 
     assert device.color_modes == {
-        light_strip.StripLightColorMode.RGB,
+        ColorMode.RGB,
     }