From 408ae44bdd065775dd5b7de4a309d1464e9ee3e7 Mon Sep 17 00:00:00 2001 From: Andre Lengwenus Date: Wed, 5 Jun 2019 11:12:05 +0200 Subject: [PATCH] Add LCN scene platform (#24242) --- homeassistant/components/lcn/__init__.py | 26 ++++++++-- homeassistant/components/lcn/const.py | 4 ++ homeassistant/components/lcn/scene.py | 66 ++++++++++++++++++++++++ 3 files changed, 92 insertions(+), 4 deletions(-) create mode 100755 homeassistant/components/lcn/scene.py diff --git a/homeassistant/components/lcn/__init__.py b/homeassistant/components/lcn/__init__.py index 4a421274a18..cf21f705b31 100644 --- a/homeassistant/components/lcn/__init__.py +++ b/homeassistant/components/lcn/__init__.py @@ -16,10 +16,11 @@ from homeassistant.helpers.entity import Entity from .const import ( BINSENSOR_PORTS, CONF_CLIMATES, CONF_CONNECTIONS, CONF_DIM_MODE, CONF_DIMMABLE, CONF_LOCKABLE, CONF_MAX_TEMP, CONF_MIN_TEMP, CONF_MOTOR, - CONF_OUTPUT, CONF_SETPOINT, CONF_SK_NUM_TRIES, CONF_SOURCE, - CONF_TRANSITION, DATA_LCN, DIM_MODES, DOMAIN, KEYS, LED_PORTS, - LOGICOP_PORTS, MOTOR_PORTS, OUTPUT_PORTS, RELAY_PORTS, S0_INPUTS, - SETPOINTS, THRESHOLDS, VAR_UNITS, VARIABLES) + CONF_OUTPUT, CONF_OUTPUTS, CONF_REGISTER, CONF_SCENE, CONF_SCENES, + CONF_SETPOINT, CONF_SK_NUM_TRIES, CONF_SOURCE, CONF_TRANSITION, DATA_LCN, + DIM_MODES, DOMAIN, KEYS, LED_PORTS, LOGICOP_PORTS, MOTOR_PORTS, + OUTPUT_PORTS, RELAY_PORTS, S0_INPUTS, SETPOINTS, THRESHOLDS, VAR_UNITS, + VARIABLES) from .helpers import has_unique_connection_names, is_address from .services import ( DynText, Led, LockKeys, LockRegulator, OutputAbs, OutputRel, OutputToggle, @@ -64,6 +65,20 @@ LIGHTS_SCHEMA = vol.Schema({ lambda value: value * 1000), }) +SCENES_SCHEMA = vol.Schema({ + vol.Required(CONF_NAME): cv.string, + vol.Required(CONF_ADDRESS): is_address, + vol.Required(CONF_REGISTER): vol.All(vol.Coerce(int), vol.Range(0, 9)), + vol.Required(CONF_SCENE): vol.All(vol.Coerce(int), vol.Range(0, 9)), + vol.Optional(CONF_OUTPUTS): vol.All( + cv.ensure_list, [vol.All(vol.Upper, + vol.In(OUTPUT_PORTS + RELAY_PORTS))]), + vol.Optional(CONF_TRANSITION, default=None): + vol.Any(vol.All(vol.Coerce(int), vol.Range(min=0., max=486.), + lambda value: value * 1000), + None) +}) + SENSORS_SCHEMA = vol.Schema({ vol.Required(CONF_NAME): cv.string, vol.Required(CONF_ADDRESS): is_address, @@ -105,6 +120,8 @@ CONFIG_SCHEMA = vol.Schema({ cv.ensure_list, [COVERS_SCHEMA]), vol.Optional(CONF_LIGHTS): vol.All( cv.ensure_list, [LIGHTS_SCHEMA]), + vol.Optional(CONF_SCENES): vol.All( + cv.ensure_list, [SCENES_SCHEMA]), vol.Optional(CONF_SENSORS): vol.All( cv.ensure_list, [SENSORS_SCHEMA]), vol.Optional(CONF_SWITCHES): vol.All( @@ -152,6 +169,7 @@ async def async_setup(hass, config): ('climate', CONF_CLIMATES), ('cover', CONF_COVERS), ('light', CONF_LIGHTS), + ('scene', CONF_SCENES), ('sensor', CONF_SENSORS), ('switch', CONF_SWITCHES)): if conf_key in config[DOMAIN]: diff --git a/homeassistant/components/lcn/const.py b/homeassistant/components/lcn/const.py index 9307fb4d706..1cf88851456 100644 --- a/homeassistant/components/lcn/const.py +++ b/homeassistant/components/lcn/const.py @@ -32,6 +32,10 @@ CONF_PCK = 'pck' CONF_CLIMATES = 'climates' CONF_MAX_TEMP = 'max_temp' CONF_MIN_TEMP = 'min_temp' +CONF_SCENES = 'scenes' +CONF_REGISTER = 'register' +CONF_SCENE = 'scene' +CONF_OUTPUTS = 'outputs' DIM_MODES = ['STEPS50', 'STEPS200'] diff --git a/homeassistant/components/lcn/scene.py b/homeassistant/components/lcn/scene.py new file mode 100755 index 00000000000..09f0292758a --- /dev/null +++ b/homeassistant/components/lcn/scene.py @@ -0,0 +1,66 @@ +"""Support for LCN scenes.""" +import pypck + +from homeassistant.components.scene import Scene +from homeassistant.const import CONF_ADDRESS + +from . import LcnDevice +from .const import ( + CONF_CONNECTIONS, CONF_OUTPUTS, CONF_REGISTER, CONF_SCENE, CONF_TRANSITION, + DATA_LCN, OUTPUT_PORTS) +from .helpers import get_connection + + +async def async_setup_platform(hass, hass_config, async_add_entities, + discovery_info=None): + """Set up the LCN scene platform.""" + if discovery_info is None: + return + + devices = [] + for config in discovery_info: + address, connection_id = config[CONF_ADDRESS] + addr = pypck.lcn_addr.LcnAddr(*address) + connections = hass.data[DATA_LCN][CONF_CONNECTIONS] + connection = get_connection(connections, connection_id) + address_connection = connection.get_address_conn(addr) + + devices.append(LcnScene(config, address_connection)) + + async_add_entities(devices) + + +class LcnScene(LcnDevice, Scene): + """Representation of a LCN scene.""" + + def __init__(self, config, address_connection): + """Initialize the LCN scene.""" + super().__init__(config, address_connection) + + self.register_id = config[CONF_REGISTER] + self.scene_id = config[CONF_SCENE] + self.output_ports = [] + self.relay_ports = [] + + for port in config[CONF_OUTPUTS]: + if port in OUTPUT_PORTS: + self.output_ports.append(pypck.lcn_defs.OutputPort[port]) + else: # in RELEAY_PORTS + self.relay_ports.append(pypck.lcn_defs.RelayPort[port]) + + if config[CONF_TRANSITION] is None: + self.transition = None + else: + self.transition = pypck.lcn_defs.time_to_ramp_value( + config[CONF_TRANSITION]) + + async def async_added_to_hass(self): + """Run when entity about to be added to hass.""" + + async def async_activate(self): + """Activate scene.""" + self.address_connection.activate_scene(self.register_id, + self.scene_id, + self.output_ports, + self.relay_ports, + self.transition)