Skip to content

Commit

Permalink
Merge branch 'dev' into dependabot/pip/commitizen-2.14.1
Browse files Browse the repository at this point in the history
  • Loading branch information
xaviml committed Feb 6, 2021
2 parents 02bc71b + 18b4271 commit ab66c45
Show file tree
Hide file tree
Showing 20 changed files with 195 additions and 72 deletions.
2 changes: 1 addition & 1 deletion .cz.toml
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
[tool.commitizen]
name = "cz_conventional_commits"
version = "4.5.0"
version = "4.6.0b0"
tag_format = "v$major.$minor.$patch$prerelease"
version_files = [
"apps/controllerx/cx_version.py",
Expand Down
6 changes: 3 additions & 3 deletions Pipfile
Original file line number Diff line number Diff line change
Expand Up @@ -5,15 +5,15 @@ verify_ssl = true

[dev-packages]
black = "==20.8b1"
pytest = "==6.2.1"
pytest = "==6.2.2"
pytest-asyncio = "==0.14.0"
pytest-cov = "==2.11.1"
pytest-mock = "==3.5.1"
pytest-timeout = "==1.4.2"
mock = "==4.0.3"
pre-commit = "==2.9.3"
pre-commit = "==2.10.0"
commitizen = "==2.14.1"
mypy = "==0.790"
mypy = "==0.800"
flake8 = "==3.8.4"
isort = "==5.7.0"
controllerx = {path = ".", editable = true}
Expand Down
5 changes: 4 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 All @@ -73,6 +75,7 @@ class MediaPlayer:
PREVIOUS_TRACK = "previous_track"
NEXT_SOURCE = "next_source"
PREVIOUS_SOURCE = "previous_source"
MUTE = "mute"


class Switch:
Expand Down
6 changes: 2 additions & 4 deletions apps/controllerx/cx_core/integration/z2m.py
Original file line number Diff line number Diff line change
Expand Up @@ -50,17 +50,15 @@ async def event_callback(
)
return
if action_group_key in payload and "action_group" in self.kwargs:
action_group = self.kwargs["action_group"]
if isinstance(action_group, str):
action_group = [action_group]
action_group = self.controller.get_list(self.kwargs["action_group"])
if payload["action_group"] not in action_group:
self.controller.log(
f"Action group {payload['action_group']} not found in "
f"action groups: {action_group}",
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
9 changes: 8 additions & 1 deletion apps/controllerx/cx_core/integration/zha.py
Original file line number Diff line number Diff line change
Expand Up @@ -33,5 +33,12 @@ async def callback(self, event_name: str, data: EventData, kwargs: dict) -> None
if action is None:
# If there is no action extracted from the controller then
# we extract with the standard function
action = self.get_action(data)
try:
action = self.get_action(data)
except Exception:
self.controller.log(
f"The following event could not be parsed: {data}", level="WARNING"
)
return

await self.controller.handle_action(action)
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
5 changes: 5 additions & 0 deletions apps/controllerx/cx_core/type/media_player_controller.py
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,7 @@ def get_predefined_actions_mapping(self) -> PredefinedActionsMapping:
MediaPlayer.PREVIOUS_TRACK: self.previous_track,
MediaPlayer.NEXT_SOURCE: (self.change_source_list, (Stepper.UP,)),
MediaPlayer.PREVIOUS_SOURCE: (self.change_source_list, (Stepper.DOWN,)),
MediaPlayer.MUTE: self.volume_mute,
}

@action
Expand Down Expand Up @@ -103,6 +104,10 @@ async def volume_down(self) -> None:
await self.prepare_volume_change()
await self.volume_change(Stepper.DOWN)

@action
async def volume_mute(self) -> None:
await self.call_service("media_player/volume_mute", entity_id=self.entity.name)

@action
async def hold(self, direction: str) -> None:
await self.prepare_volume_change()
Expand Down
24 changes: 3 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 All @@ -32,6 +13,7 @@ def get_z2m_actions_mapping(self) -> DefaultActionsMapping:
"brightness_up_click": Light.CLICK_BRIGHTNESS_UP,
"brightness_up_hold": Light.HOLD_BRIGHTNESS_DOWN,
"brightness_up_release": Light.RELEASE,
"color_wheel": Light.XYCOLOR_FROM_CONTROLLER # Color ring press
# color_temp: "" # warm or cold
# color_wheel: "" # Color ring press
# "scene_3": "", # reading button
Expand All @@ -53,7 +35,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
36 changes: 22 additions & 14 deletions apps/controllerx/cx_devices/rgb_genie.py
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
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
Expand All @@ -20,22 +20,11 @@ def get_zha_actions_mapping(self) -> DefaultActionsMapping:


class ZB5122LightController(LightController):

MOVE_TO_COLOR_TEMP = "move_to_color_temp"

@action
async def move_to_color_temp(self, extra: EventData) -> None:
async def colortemp_from_controller(self, extra: EventData) -> None:
if isinstance(self.integration, ZHAIntegration):
await self.on(color_temp=extra["args"][0])

def get_predefined_actions_mapping(self) -> PredefinedActionsMapping:
parent_mapping = super().get_predefined_actions_mapping()
mapping: PredefinedActionsMapping = {
ZB5122LightController.MOVE_TO_COLOR_TEMP: self.move_to_color_temp,
}
parent_mapping.update(mapping)
return parent_mapping

def get_zha_actions_mapping(self) -> DefaultActionsMapping:
return {
"on": Light.ON, # Click light on
Expand All @@ -46,7 +35,7 @@ def get_zha_actions_mapping(self) -> DefaultActionsMapping:
"move_to_color": Light.CLICK_XY_COLOR_UP, # click RGB
"move_hue": Light.HOLD_XY_COLOR_UP, # hold RGB
"stop_move_hue": Light.RELEASE, # release RGB
"move_to_color_temp": ZB5122LightController.MOVE_TO_COLOR_TEMP, # click CW
"move_to_color_temp": Light.COLORTEMP_FROM_CONTROLLER, # click CW
"move_color_temp": Light.HOLD_COLOR_TEMP_TOGGLE, # hold CW
"stop_move_step": Light.RELEASE, # release CW
# "recall_0_1": "", # Click clapperboard
Expand All @@ -61,3 +50,22 @@ def get_zha_action(self, data: EventData) -> str:
elif command == "move_hue":
return "stop_move_hue" if tuple(data["args"]) == (0, 0) else "move_hue"
return command


class ZB3009LightController(LightController):
def get_z2m_actions_mapping(self) -> DefaultActionsMapping:
return {
"on": Light.TOGGLE,
"off": Light.TOGGLE,
"brightness_move_up": Light.HOLD_BRIGHTNESS_UP,
"brightness_move_down": Light.HOLD_BRIGHTNESS_DOWN,
"brightness_stop": Light.RELEASE,
"color_temperature_move_down": Light.CLICK_COLOR_TEMP_DOWN,
"color_temperature_move_up": Light.CLICK_COLOR_TEMP_UP,
"color_temperature_move": Light.COLORTEMP_FROM_CONTROLLER,
"color_move": Light.XYCOLOR_FROM_CONTROLLER,
# "hue_move": "", # Play/pause button
# "recall_1": "", # Scene 1
# "recall_3": "", # Scene 2
# "recall_2": "", # Scene 3
}
2 changes: 1 addition & 1 deletion apps/controllerx/cx_version.py
Original file line number Diff line number Diff line change
@@ -1 +1 @@
__version__ = "v4.5.0"
__version__ = "v4.6.0b0"
30 changes: 30 additions & 0 deletions docs/_data/controllers/ZB-3009.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
name: ZB-3009 (RGB Genie)
device_support:
- type: Light
domain: light
controller: ZB3009LightController
delay: 350
mapping:
- "Click on/off → Toggle"
- "Click red circle → Change color of the bulb to red"
- "Click blue circle → Change color of the bulb to blue"
- "Click green circle → Change color of the bulb to green"
- "Click white circle → Change color temperature"
- "Hold white circle → Change color temperature"
- "Click three rings → Toggle through white warmth"
- "Hold brightness button → Change brightness"
- "Click color wheel → Change xy color"

integrations:
- name: Zigbee2MQTT
codename: z2m
actions:
- '"on" → Click on/off'
- '"off" → Click on/off'
- "brightness_move_up → Hold brightness button"
- "brightness_move_down → Hold brightness button"
- "brightness_stop → Release brightness button"
- "color_temperature_move_down → Hold white circle"
- "color_temperature_move_up → Hold white circle"
- "color_temperature_move → Click white circle"
- "color_move → Click red/blue/green button, three wrings button and color wheel"
24 changes: 11 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 @@ -77,25 +76,24 @@ When using a [media player controller](/controllerx/start/type-configuration#med
| `previous_track` | It skips the track backward |
| `next_source` | It changes to the next source |
| `previous_source` | It changes to the previous source |

| `mute` | It mutes the media player |

## 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
Binary file added docs/assets/img/ZB-3009.jpeg
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
5 changes: 5 additions & 0 deletions docs/controllers/ZB-3009.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
layout: controller
title: ZB-3009 (RGB Genie)
device: ZB-3009
---
File renamed without changes.
9 changes: 9 additions & 0 deletions tests/integ_tests/muller_licht_z2m/config.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
example_app:
module: controllerx
class: MLI404011LightController
integration:
name: z2m
listen_to: mqtt
controller: my_controller
light: light.my_light

0 comments on commit ab66c45

Please sign in to comment.