Skip to content

Commit

Permalink
Merge branch 'dev' into main
Browse files Browse the repository at this point in the history
  • Loading branch information
xaviml committed Feb 24, 2021
2 parents 3eb094c + 654ab16 commit 2471db8
Show file tree
Hide file tree
Showing 33 changed files with 523 additions and 125 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.6.0"
version = "4.7.0"
tag_format = "v$major.$minor.$patch$prerelease"
version_files = [
"apps/controllerx/cx_version.py",
Expand Down
17 changes: 8 additions & 9 deletions .github/ISSUE_TEMPLATE/new_device.md
Original file line number Diff line number Diff line change
Expand Up @@ -12,24 +12,23 @@ assignees: xaviml

## Device Information

* Device Model: [ eg. E1743 ]
* Device Description: [ eg. IKEA TRADFRI E1743 wireless dimmer ]
* Device Manufacturer: [ eg. IKEA ]
- Device Model: [ eg. E1743 ]
- Device Description: [ eg. IKEA TRADFRI E1743 wireless dimmer ]
- Device Manufacturer: [ eg. IKEA ]

## Integrations

If possible, provide the event mappings for the different actions that can be performed on the controller. Specify the integration.
<!-- If possible, provide the event mappings for the different actions that can be performed on the controller. Specify the integration.
If you can provide mappings for multiple integrations, copy the section below as many times as needed.
If you can provide mappings for multiple integrations, copy the section below as many times as needed. -->

### Integration: [ Choose from `z2m | deconz | zha` ]

#### Actions

* `button_xyz_press`: Sent when button xyz is pressed
* `button_xyz_hold`: Sent when button xyz is held
- `button_xyz_press`: Sent when button xyz is pressed
- `button_xyz_hold`: Sent when button xyz is held

#### Notes

(Optional) Additional notes for the integration, eg. known bugs, issues or limitations of the device for the specified integration.

<!-- (Optional) Additional notes for the integration, eg. known bugs, issues or limitations of the device for the specified integration. -->
4 changes: 2 additions & 2 deletions Pipfile
Original file line number Diff line number Diff line change
Expand Up @@ -12,8 +12,8 @@ pytest-mock = "==3.5.1"
pytest-timeout = "==1.4.2"
mock = "==4.0.3"
pre-commit = "==2.10.1"
commitizen = "==2.14.2"
mypy = "==0.800"
commitizen = "==2.15.2"
mypy = "==0.812"
flake8 = "==3.8.4"
isort = "==5.7.0"
controllerx = {path = ".", editable = true}
Expand Down
1 change: 0 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,6 @@
[![last-release](https://img.shields.io/github/v/release/xaviml/controllerx.svg?style=for-the-badge)](https://github.com/xaviml/controllerx/releases)
[![downloads-latest](https://img.shields.io/github/downloads/xaviml/controllerx/latest/total?style=for-the-badge)](http://github.com/xaviml/controllerx/releases/latest)
[![azure-pipelines-coverage](https://img.shields.io/azure-devops/coverage/xaviml93/ControllerX/1/main.svg?style=for-the-badge)](https://dev.azure.com/xaviml93/ControllerX/_build/latest?definitionId=1&branchName=main)
[![Codacy Badge](https://img.shields.io/codacy/grade/542f29ab55a449099488601ec7400563/main?style=for-the-badge)](https://app.codacy.com/manual/xaviml/controllerx?utm_source=github.com&utm_medium=referral&utm_content=xaviml/controllerx&utm_campaign=Badge_Grade_Dashboard)
[![community-topic](https://img.shields.io/badge/community-topic-blue?style=for-the-badge)](https://community.home-assistant.io/t/controllerx-bring-full-functionality-to-light-and-media-player-controllers/148855)
[![buy-me-a-beer](https://img.shields.io/badge/sponsor-Buy%20me%20a%20beer-orange?style=for-the-badge)](https://www.buymeacoffee.com/xaviml)

Expand Down
8 changes: 8 additions & 0 deletions apps/controllerx/cx_core/controller.py
Original file line number Diff line number Diff line change
Expand Up @@ -488,5 +488,13 @@ def get_zha_action(self, data: EventData) -> Optional[str]:
"""
return None

def get_lutron_caseta_actions_mapping(self) -> Optional[DefaultActionsMapping]:
"""
Controllers can implement this function. It should return a dict
with the command that a controller can take and the functions as values.
This is used for Lutron support.
"""
return None

def get_predefined_actions_mapping(self) -> PredefinedActionsMapping:
return {}
10 changes: 5 additions & 5 deletions apps/controllerx/cx_core/custom_controller.py
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ async def init(self) -> None:
level="WARNING",
ascii_encode=False,
)
await super().init()
await super().init() # pragma: no cover


class CustomMediaPlayerController(MediaPlayerController):
Expand All @@ -22,7 +22,7 @@ async def init(self) -> None:
level="WARNING",
ascii_encode=False,
)
await super().init()
await super().init() # pragma: no cover


class CustomSwitchController(SwitchController):
Expand All @@ -32,7 +32,7 @@ async def init(self) -> None:
level="WARNING",
ascii_encode=False,
)
await super().init()
await super().init() # pragma: no cover


class CustomCoverController(CoverController):
Expand All @@ -42,7 +42,7 @@ async def init(self) -> None:
level="WARNING",
ascii_encode=False,
)
await super().init()
await super().init() # pragma: no cover


class CallServiceController(Controller):
Expand All @@ -52,4 +52,4 @@ async def init(self) -> None:
level="WARNING",
ascii_encode=False,
)
await super().init()
await super().init() # pragma: no cover
26 changes: 26 additions & 0 deletions apps/controllerx/cx_core/integration/lutron_caseta.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
from typing import Optional

from appdaemon.plugins.hass.hassapi import Hass # type: ignore
from cx_const import DefaultActionsMapping
from cx_core.integration import EventData, Integration


class LutronIntegration(Integration):
name = "lutron_caseta"

def get_default_actions_mapping(self) -> Optional[DefaultActionsMapping]:
return self.controller.get_lutron_caseta_actions_mapping()

def listen_changes(self, controller_id: str) -> None:
Hass.listen_event(
self.controller,
self.callback,
"lutron_caseta_button_event",
serial=controller_id,
)

async def callback(self, event_name: str, data: EventData, kwargs: dict) -> None:
button = data["button_number"]
action_type = data["action"]
action = f"button_{button}_{action_type}"
await self.controller.handle_action(action, extra=data)
14 changes: 14 additions & 0 deletions apps/controllerx/cx_devices/ikea.py
Original file line number Diff line number Diff line change
Expand Up @@ -486,3 +486,17 @@ def get_zha_actions_mapping(self) -> DefaultActionsMapping:
"down_close": Cover.TOGGLE_CLOSE,
"stop": Cover.STOP,
}


class E1812LightController(LightController):
def get_z2m_actions_mapping(self) -> DefaultActionsMapping:
return {
"on": Light.TOGGLE,
"brightness_move_up": Light.HOLD_BRIGHTNESS_TOGGLE,
"brightness_stop": Light.RELEASE,
}


class E1812SwitchController(SwitchController):
def get_z2m_actions_mapping(self) -> DefaultActionsMapping:
return {"on": Switch.TOGGLE}
168 changes: 106 additions & 62 deletions apps/controllerx/cx_devices/lutron.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,109 +2,153 @@
from cx_core import LightController, MediaPlayerController


class LutronCasetaProPicoLightController(LightController):
# This requires the LutronCasetaPro CUSTOM integration by upsert
# https://github.com/upsert/lutron-caseta-pro
# THIS WILL NOT WORK with the default Lutron Caseta integration
# Pico remotes using this integration report 6 states from their sensor:
# top button = "1", up button = "8", middle round = "2", down arrow = "16",
# bottom button = "4", no button pressed = "0"
class LZL4BWHL01LightController(LightController):
# Each button press fires an event but no separate
# hold event. Press of up or down generates a stop event
# when released.

def get_deconz_actions_mapping(self) -> DefaultActionsMapping:
return {
1002: Light.ON_FULL_BRIGHTNESS,
2001: Light.HOLD_BRIGHTNESS_UP,
2003: Light.RELEASE,
3001: Light.HOLD_BRIGHTNESS_DOWN,
3003: Light.RELEASE,
4002: Light.OFF,
}

def get_zha_actions_mapping(self) -> DefaultActionsMapping:
return {
"move_to_level_with_on_off_254_4": Light.ON_FULL_BRIGHTNESS,
"step_with_on_off_0_30_6": Light.HOLD_BRIGHTNESS_UP,
"step_1_30_6": Light.HOLD_BRIGHTNESS_DOWN,
"move_to_level_with_on_off_0_4": Light.OFF,
"stop": Light.RELEASE,
}


class Z31BRLLightController(LightController):
def get_deconz_actions_mapping(self) -> DefaultActionsMapping:
return {
1002: Light.TOGGLE,
2002: Light.CLICK_BRIGHTNESS_UP,
3002: Light.CLICK_BRIGHTNESS_DOWN,
}


class LutronPJ22BLightController(LightController):
def get_z2m_actions_mapping(self) -> DefaultActionsMapping:
return {
"1": Light.ON_FULL_BRIGHTNESS,
"4": Light.OFF,
}

def get_lutron_caseta_actions_mapping(self) -> DefaultActionsMapping:
return {
"button_2_press": Light.ON,
"button_4_press": Light.OFF,
}


class LutronPJ22BMediaPlayerController(MediaPlayerController):
def get_z2m_actions_mapping(self) -> DefaultActionsMapping:
return {
"1": MediaPlayer.PLAY_PAUSE,
"4": MediaPlayer.NEXT_TRACK,
}

def get_lutron_caseta_actions_mapping(self) -> DefaultActionsMapping:
return {
"button_2_press": MediaPlayer.PLAY_PAUSE,
"button_4_press": MediaPlayer.NEXT_TRACK,
}


class LutronPJ22BRLLightController(LightController):
def get_z2m_actions_mapping(self) -> DefaultActionsMapping:
return {
"1": Light.ON_FULL_BRIGHTNESS,
"8": Light.HOLD_BRIGHTNESS_UP,
"2": Light.SET_HALF_BRIGHTNESS,
"16": Light.HOLD_BRIGHTNESS_DOWN,
"4": Light.OFF,
"0": Light.RELEASE,
}


class LutronCasetaProPicoMediaPlayerController(MediaPlayerController):
# This requires the LutronCasetaPro CUSTOM integration by upsert
# https://github.com/upsert/lutron-caseta-pro
# THIS WILL NOT WORK with the default Lutron Caseta integration
# Pico remotes using this integration report 6 states from their sensor:
# top button = "1", up button = "8", middle round = "2", down arrow = "16",
# bottom button = "4", no button pressed = "0"

class LutronPJ22BRLMediaPlayerController(MediaPlayerController):
def get_z2m_actions_mapping(self) -> DefaultActionsMapping:
return {
"1": MediaPlayer.PLAY_PAUSE,
"8": MediaPlayer.HOLD_VOLUME_UP,
"2": MediaPlayer.NEXT_SOURCE,
"16": MediaPlayer.HOLD_VOLUME_DOWN,
"4": MediaPlayer.NEXT_TRACK,
"0": MediaPlayer.RELEASE,
}


class LutronCasetaProPJ24BLightController(LightController):
# This requires the LutronCasetaPro CUSTOM integration by upsert
# https://github.com/upsert/lutron-caseta-pro
# THIS WILL NOT WORK with the default Lutron Caseta integration
# Pico remotes using this integration report 5 states from their sensor:
# top button = "1", second button = "2", third button = "4",
# bottom button = "8", no button pressed = "0"

class LutronPJ23BRLLightController(LightController):
def get_z2m_actions_mapping(self) -> DefaultActionsMapping:
return {
"1": Light.ON_FULL_BRIGHTNESS,
"2": Light.HOLD_BRIGHTNESS_UP,
"4": Light.HOLD_BRIGHTNESS_DOWN,
"8": Light.OFF,
"8": Light.HOLD_BRIGHTNESS_UP,
"2": Light.SET_HALF_BRIGHTNESS,
"16": Light.HOLD_BRIGHTNESS_DOWN,
"4": Light.OFF,
"0": Light.RELEASE,
}

def get_lutron_caseta_actions_mapping(self) -> DefaultActionsMapping:
return {
"button_2_press": Light.ON_FULL_BRIGHTNESS,
"button_4_press": Light.OFF,
"button_3_press": Light.SET_HALF_BRIGHTNESS,
"button_5_press": Light.HOLD_BRIGHTNESS_UP,
"button_5_release": Light.RELEASE,
"button_6_press": Light.HOLD_BRIGHTNESS_DOWN,
"button_6_release": Light.RELEASE,
}

class LutronCasetaProPJ24BMediaPlayerController(MediaPlayerController):
# This requires the LutronCasetaPro CUSTOM integration by upsert
# https://github.com/upsert/lutron-caseta-pro
# THIS WILL NOT WORK with the default Lutron Caseta integration
# Pico remotes using this integration report 5 states from their sensor:
# top button = "1", second button = "2", third button = "4",
# bottom button = "8", no button pressed = "0"

class LutronPJ23BRLMediaPlayerController(MediaPlayerController):
def get_z2m_actions_mapping(self) -> DefaultActionsMapping:
return {
"1": MediaPlayer.PLAY_PAUSE,
"2": MediaPlayer.HOLD_VOLUME_UP,
"4": MediaPlayer.HOLD_VOLUME_DOWN,
"8": MediaPlayer.NEXT_TRACK,
"8": MediaPlayer.HOLD_VOLUME_UP,
"2": MediaPlayer.NEXT_SOURCE,
"16": MediaPlayer.HOLD_VOLUME_DOWN,
"4": MediaPlayer.NEXT_TRACK,
"0": MediaPlayer.RELEASE,
}


class LZL4BWHL01LightController(LightController):
# Each button press fires an event but no separate
# hold event. Press of up or down generates a stop event
# when released.

def get_deconz_actions_mapping(self) -> DefaultActionsMapping:
def get_lutron_caseta_actions_mapping(self) -> DefaultActionsMapping:
return {
1002: Light.ON_FULL_BRIGHTNESS,
2001: Light.HOLD_BRIGHTNESS_UP,
2003: Light.RELEASE,
3001: Light.HOLD_BRIGHTNESS_DOWN,
3003: Light.RELEASE,
4002: Light.OFF,
"button_2_press": MediaPlayer.PLAY_PAUSE,
"button_4_press": MediaPlayer.NEXT_TRACK,
"button_3_press": MediaPlayer.NEXT_SOURCE,
"button_5_press": MediaPlayer.HOLD_VOLUME_UP,
"button_5_release": MediaPlayer.RELEASE,
"button_6_press": MediaPlayer.HOLD_VOLUME_DOWN,
"button_6_release": MediaPlayer.RELEASE,
}

def get_zha_actions_mapping(self) -> DefaultActionsMapping:

class LutronPJ24BLightController(LightController):
def get_z2m_actions_mapping(self) -> DefaultActionsMapping:
return {
"move_to_level_with_on_off_254_4": Light.ON_FULL_BRIGHTNESS,
"step_with_on_off_0_30_6": Light.HOLD_BRIGHTNESS_UP,
"step_1_30_6": Light.HOLD_BRIGHTNESS_DOWN,
"move_to_level_with_on_off_0_4": Light.OFF,
"stop": Light.RELEASE,
"1": Light.ON_FULL_BRIGHTNESS,
"2": Light.HOLD_BRIGHTNESS_UP,
"4": Light.HOLD_BRIGHTNESS_DOWN,
"8": Light.OFF,
"0": Light.RELEASE,
}


class Z31BRLLightController(LightController):
def get_deconz_actions_mapping(self) -> DefaultActionsMapping:
class LutronPJ24BMediaPlayerController(MediaPlayerController):
def get_z2m_actions_mapping(self) -> DefaultActionsMapping:
return {
1002: Light.TOGGLE,
2002: Light.CLICK_BRIGHTNESS_UP,
3002: Light.CLICK_BRIGHTNESS_DOWN,
"1": MediaPlayer.PLAY_PAUSE,
"2": MediaPlayer.HOLD_VOLUME_UP,
"4": MediaPlayer.HOLD_VOLUME_DOWN,
"8": MediaPlayer.NEXT_TRACK,
"0": MediaPlayer.RELEASE,
}
Loading

0 comments on commit 2471db8

Please sign in to comment.