diff --git a/apps/controllerx/cx_devices/rgb_genie.py b/apps/controllerx/cx_devices/rgb_genie.py index 14620954..1e35c23a 100644 --- a/apps/controllerx/cx_devices/rgb_genie.py +++ b/apps/controllerx/cx_devices/rgb_genie.py @@ -1,5 +1,8 @@ -from cx_const import DefaultActionsMapping, Light +from cx_const import DefaultActionsMapping, Light, PredefinedActionsMapping from cx_core import LightController +from cx_core.controller import action +from cx_core.integration import EventData +from cx_core.integration.zha import ZHAIntegration class ZB5121LightController(LightController): @@ -14,3 +17,47 @@ def get_zha_actions_mapping(self) -> DefaultActionsMapping: # "recall_0_1": "", # Click clapperboard "stop": Light.RELEASE, # long release } + + +class ZB5122LightController(LightController): + + MOVE_TO_COLOR = "move_to_color" + + @action + async def move_to_color(self, extra: EventData) -> None: + if isinstance(self.integration, ZHAIntegration): + await self.on(rgb_color=extra["args"]) + + def get_predefined_actions_mapping(self) -> PredefinedActionsMapping: + parent_mapping = super().get_predefined_actions_mapping() + mapping: PredefinedActionsMapping = { + ZB5122LightController.MOVE_TO_COLOR: self.move_to_color, + } + parent_mapping.update(mapping) + return parent_mapping + + def get_zha_actions_mapping(self) -> DefaultActionsMapping: + return { + "on": Light.ON, # Click light on + "off": Light.OFF, # Click light off + "hold_brightness_up": Light.HOLD_BRIGHTNESS_UP, # Hold light on + "hold_brightness_down": Light.HOLD_BRIGHTNESS_DOWN, # Hold light off + "stop": Light.RELEASE, # long release + "move_to_color": ZB5122LightController.MOVE_TO_COLOR, # click RGB + "move_hue": Light.HOLD_XY_COLOR_UP, # hold RGB + "stop_move_hue": Light.RELEASE, # release RGB + "move_to_color_temp": Light.ON_FULL_COLOR_TEMP, # click CW + "move_color_temp": Light.HOLD_COLOR_TEMP_TOGGLE, # hold CW + "stop_move_step": Light.RELEASE, # release CW + # "recall_0_1": "", # Click clapperboard + } + + def get_zha_action(self, data: EventData) -> str: + command: str = data["command"] + if command == "move_with_on_off": + return ( + "hold_brightness_up" if data["args"][0] == 0 else "hold_brightness_down" + ) + elif command == "move_hue": + return "stop_move_hue" if tuple(data["args"]) == (0, 0) else "move_hue" + return command diff --git a/docs/_data/controllers/ZB-5122.yml b/docs/_data/controllers/ZB-5122.yml new file mode 100644 index 00000000..6139a223 --- /dev/null +++ b/docs/_data/controllers/ZB-5122.yml @@ -0,0 +1,33 @@ +name: ZB-5122 (RGB Genie) +device_support: + - type: Light + domain: light + controller: ZB5122LightController + delay: 350 + mapping: + - "Click light on → Turn on" + - "Click light off → Turn off" + - "Hold light on → Brighten up" + - "Hold light off → Dim down" + - "Click RGB → Change xy color (1 step)" + - "Hold RGB → Change xy color (loop)" + - "Click CW → Warm color" + - "Hold CW → Change color temp (toggle mode)" + +integrations: + - name: ZHA + codename: zha + actions: + - '"on" → Click light on' + - '"off" → Click light off' + - "hold_brightness_up → Hold light on" + - "hold_brightness_down → Hold light off" + - "stop → Release light on or off" + - "move_to_color → Click RGB" + - "move_hue → Hold RGB" + - "stop_move_hue → Release RGB" + - "move_to_color_temp → Click CW" + - "move_color_temp → Hold CW" + - "stop_move_step → Release CW" + - "recall_0_1 → Click clapperboard" + \ No newline at end of file diff --git a/docs/assets/img/ZB-5122.jpeg b/docs/assets/img/ZB-5122.jpeg new file mode 100644 index 00000000..faf37652 Binary files /dev/null and b/docs/assets/img/ZB-5122.jpeg differ diff --git a/docs/controllers/ZB-5122.md b/docs/controllers/ZB-5122.md new file mode 100644 index 00000000..53990742 --- /dev/null +++ b/docs/controllers/ZB-5122.md @@ -0,0 +1,5 @@ +--- +layout: controller +title: ZB-5122 (RGB Genie) +device: ZB-5122 +--- diff --git a/tests/integ_tests/zb5122/config.yaml b/tests/integ_tests/zb5122/config.yaml new file mode 100644 index 00000000..7a8131fe --- /dev/null +++ b/tests/integ_tests/zb5122/config.yaml @@ -0,0 +1,7 @@ +example_app: + module: controllerx + class: ZB5122LightController + integration: zha + controller: my_controller + light: light.my_light + \ No newline at end of file diff --git a/tests/integ_tests/zb5122/move_to_color_test.yaml b/tests/integ_tests/zb5122/move_to_color_test.yaml new file mode 100644 index 00000000..48a09073 --- /dev/null +++ b/tests/integ_tests/zb5122/move_to_color_test.yaml @@ -0,0 +1,12 @@ +entity_state_attributes: + supported_features: 191 +entity_state: "off" +fired_actions: ["move_to_color"] +extra: + args: !!python/tuple [255, 0, 150] +expected_calls: + - service: light/turn_on + data: + entity_id: light.my_light + rgb_color: !!python/tuple [255, 0, 150] +expected_calls_count: 1 diff --git a/tests/unit_tests/cx_devices/rgb_genie_test.py b/tests/unit_tests/cx_devices/rgb_genie_test.py new file mode 100644 index 00000000..3ecc5f13 --- /dev/null +++ b/tests/unit_tests/cx_devices/rgb_genie_test.py @@ -0,0 +1,22 @@ +import pytest +from cx_core.integration import EventData +from cx_devices.rgb_genie import ZB5122LightController + + +@pytest.mark.parametrize( + "data, expected_action", + [ + ({"command": "on"}, "on"), + ({"command": "off"}, "off"), + ({"command": "stop"}, "stop"), + ({"command": "move_to_color"}, "move_to_color"), + ({"command": "move_with_on_off", "args": [0, 50]}, "hold_brightness_up"), + ({"command": "move_with_on_off", "args": [1, 50]}, "hold_brightness_down"), + ({"command": "move_hue", "args": [0, 0]}, "stop_move_hue"), + ({"command": "move_hue", "args": [1, 2]}, "move_hue"), + ], +) +def test_zha_action_MFKZQ01LMLightController(data: EventData, expected_action: str): + sut = ZB5122LightController() # type: ignore + action = sut.get_zha_action(data) + assert action == expected_action