Skip to content

Commit

Permalink
refactor(light_controller): add xycolor_from_controller and colortemp…
Browse files Browse the repository at this point in the history
…_from_controller predefined actions

related to #236
  • Loading branch information
xaviml committed Feb 6, 2021
1 parent 52b402d commit 0852b4e
Show file tree
Hide file tree
Showing 8 changed files with 58 additions and 37 deletions.
4 changes: 3 additions & 1 deletion apps/controllerx/cx_const.py
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@

CustomAction = Union[str, Dict[str, Any]]
CustomActions = Union[List[CustomAction], CustomAction]
CustomActionsMapping = Mapping[ActionEvent, CustomActions]
CustomActionsMapping = Dict[ActionEvent, CustomActions]


class Light:
Expand Down Expand Up @@ -58,6 +58,8 @@ class Light:
HOLD_XY_COLOR_UP = "hold_xycolor_up"
HOLD_XY_COLOR_DOWN = "hold_xycolor_down"
HOLD_XY_COLOR_TOGGLE = "hold_xycolor_toggle"
XYCOLOR_FROM_CONTROLLER = "xycolor_from_controller"
COLORTEMP_FROM_CONTROLLER = "colortemp_from_controller"


class MediaPlayer:
Expand Down
2 changes: 1 addition & 1 deletion apps/controllerx/cx_core/integration/z2m.py
Original file line number Diff line number Diff line change
Expand Up @@ -58,7 +58,7 @@ async def event_callback(
level="DEBUG",
)
return
await self.controller.handle_action(payload[action_key])
await self.controller.handle_action(payload[action_key], extra=payload)

async def state_callback(
self, entity: Optional[str], attribute: Optional[str], old, new, kwargs
Expand Down
38 changes: 38 additions & 0 deletions apps/controllerx/cx_core/type/light_controller.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,9 @@
from cx_core.color_helper import get_color_wheel
from cx_core.controller import action
from cx_core.feature_support.light import LightSupport
from cx_core.integration import EventData
from cx_core.integration.deconz import DeCONZIntegration
from cx_core.integration.z2m import Z2MIntegration
from cx_core.release_hold_controller import ReleaseHoldController
from cx_core.stepper import Stepper
from cx_core.stepper.circular_stepper import CircularStepper
Expand Down Expand Up @@ -371,6 +374,8 @@ def get_predefined_actions_mapping(self) -> PredefinedActionsMapping:
Stepper.TOGGLE,
),
),
Light.XYCOLOR_FROM_CONTROLLER: self.xycolor_from_controller,
Light.COLORTEMP_FROM_CONTROLLER: self.colortemp_from_controller,
}

async def call_light_service(
Expand Down Expand Up @@ -455,6 +460,39 @@ async def sync(self) -> None:
)
await self.on(**attributes, brightness=self.max_brightness)

@action
async def xycolor_from_controller(self, extra: Optional[EventData]) -> None:
if extra is None:
self.log("No event data present", level="WARNING")
return
if isinstance(self.integration, Z2MIntegration):
if "action_color" not in extra:
self.log(
"`action_color` is not present in the MQTT payload", level="WARNING"
)
return
xy_color = extra["action_color"]
await self.on(xy_color=(xy_color["x"], xy_color["y"]))
elif isinstance(self.integration, DeCONZIntegration):
if "xy" not in extra:
self.log("`xy` is not present in the deCONZ event", level="WARNING")
return
await self.on(xy_color=extra["xy"])

@action
async def colortemp_from_controller(self, extra: Optional[EventData]) -> None:
if extra is None:
self.log("No event data present", level="WARNING")
return
if isinstance(self.integration, Z2MIntegration):
if "action_color_temperature" not in extra:
self.log(
"`action_color_temperature` is not present in the MQTT payload",
level="WARNING",
)
return
await self.on(color_temp=extra["action_color_temperature"])

async def get_attribute(self, attribute: str) -> str:
if attribute == LightController.ATTRIBUTE_COLOR:
if self.entity.color_mode == "auto":
Expand Down
23 changes: 2 additions & 21 deletions apps/controllerx/cx_devices/muller_licht.py
Original file line number Diff line number Diff line change
@@ -1,27 +1,8 @@
from cx_const import DefaultActionsMapping, Light, PredefinedActionsMapping
from cx_const import DefaultActionsMapping, Light
from cx_core import LightController
from cx_core.controller import action
from cx_core.integration import EventData
from cx_core.integration.deconz import DeCONZIntegration


class MLI404011LightController(LightController):

CHANGE_XY_COLOR = "change_xy_color"

@action
async def change_xy_color(self, extra: EventData) -> None:
if isinstance(self.integration, DeCONZIntegration):
await self.on(xy_color=extra["xy"])

def get_predefined_actions_mapping(self) -> PredefinedActionsMapping:
parent_mapping = super().get_predefined_actions_mapping()
mapping: PredefinedActionsMapping = {
MLI404011LightController.CHANGE_XY_COLOR: self.change_xy_color,
}
parent_mapping.update(mapping)
return parent_mapping

def get_z2m_actions_mapping(self) -> DefaultActionsMapping:
return {
"on": Light.TOGGLE,
Expand Down Expand Up @@ -53,7 +34,7 @@ def get_deconz_actions_mapping(self) -> DefaultActionsMapping:
3003: Light.RELEASE,
4002: Light.CLICK_COLOR_UP,
5002: Light.CLICK_COLOR_DOWN,
6002: MLI404011LightController.CHANGE_XY_COLOR, # Color ring press
6002: Light.XYCOLOR_FROM_CONTROLLER, # Color ring press
# 7002: "", # reading button
# 8002: "", # sunset button
# 9002: "", # party button
Expand Down
23 changes: 10 additions & 13 deletions docs/advanced/predefined-actions.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,18 +4,17 @@ layout: page
---

_This page assumes you already know how the [`mapping` attribute](custom-controllers) works._

Here you can find a list of predefined actions (one of the [action types](action-types)) for each type of controller.

Here you can find a list of predefined actions (one of the [action types](action-types)) for each type of controller.

## Light

When using a [light controller](/controllerx/start/type-configuration#light-controller) (e.g. `E1743Controller`) or `LightController`, the following actions can be used as a predefined action:

| value | description |
| ------------------------- | ---------------------------------------------------------------------------------------------------------------------------- |
| `"on"` | It turns on the light |
| `"off"` | It turns off the light |
| `"on"` | It turns on the light |
| `"off"` | It turns off the light |
| `toggle` | It toggles the light |
| `toggle_full_brightness` | It toggles the light, setting the brightness to the maximum value when turning on. |
| `toggle_full_white_value` | It toggles the light, setting the white value to the maximum value when turning on. |
Expand Down Expand Up @@ -59,14 +58,14 @@ When using a [light controller](/controllerx/start/type-configuration#light-cont
| `hold_xycolor_up` | It turns the xy color up until release accordingly with the `automatic_steps` attribute |
| `hold_xycolor_down` | It turns the xy color down until release accordingly with the `automatic_steps` attribute |
| `hold_xycolor_toggle` | It turns the xy color up/down until release accordingly with the `automatic_steps` attribute and alternates in each click |

| `xycolor_from_controller` | It changes the color of the light from the value sent by the controller (if supported) |

## Media Player

When using a [media player controller](/controllerx/start/type-configuration#media-player-controller) (e.g. `E1743MediaPlayerController`) or `MediaPlayerController`, the following actions can be used as a predefined action:

| value | description |
| ----------------- | -------------------------------------------------- |
| value | description |
| ------------------- | -------------------------------------------------- |
| `hold_volume_down` | It turns the volume down until `release` is called |
| `hold_volume_up` | It turns the volume up until `release` is called |
| `click_volume_down` | It turns the volume down one step |
Expand All @@ -78,24 +77,22 @@ When using a [media player controller](/controllerx/start/type-configuration#med
| `next_source` | It changes to the next source |
| `previous_source` | It changes to the previous source |


## Switch

When using a [switch controller](/controllerx/start/type-configuration#switch-controller) (e.g. `E1743SwitchController`) or `SwitchController`, the following actions can be used as a predefined action:

| value | description |
| ------ | ---------------------------------- |
| value | description |
| -------- | ---------------------------------- |
| `on` | It turns the switch on |
| `off` | It turns the switch off |
| `toggle` | It toggles the state of the switch |


## Cover

When using a [cover controller](/controllerx/start/type-configuration#cover-controller) (e.g. `E1743CoverController`) or `CoverController`, the following actions can be used as a predefined action:

| value | description |
| ------------ | -------------------------------------------------- |
| value | description |
| -------------- | -------------------------------------------------- |
| `open` | It opens the cover |
| `close` | It closes the cover |
| `stop` | It stops the cover |
Expand Down
File renamed without changes.
5 changes: 4 additions & 1 deletion tests/unit_tests/cx_core/integration/z2m_test.py
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
import json
from typing import Any, Dict, Optional

import pytest
Expand Down Expand Up @@ -50,6 +51,8 @@ async def test_event_callback(
await z2m_integration.event_callback("test", data, {})

if handle_action_called:
handle_action_patch.assert_called_once_with(expected_called_with)
handle_action_patch.assert_called_once_with(
expected_called_with, extra=json.loads(data["payload"])
)
else:
handle_action_patch.assert_not_called()

0 comments on commit 0852b4e

Please sign in to comment.