mirror of
https://github.com/home-assistant/core.git
synced 2025-07-23 21:27:38 +00:00
LCN cover control via output ports (#25511)
* LCN motor control via oputput ports * Remove default value from cover validator
This commit is contained in:
parent
dc722adbb5
commit
c4f673c894
@ -4,23 +4,23 @@ import logging
|
|||||||
import pypck
|
import pypck
|
||||||
import voluptuous as vol
|
import voluptuous as vol
|
||||||
|
|
||||||
|
import homeassistant.helpers.config_validation as cv
|
||||||
from homeassistant.components.climate import DEFAULT_MAX_TEMP, DEFAULT_MIN_TEMP
|
from homeassistant.components.climate import DEFAULT_MAX_TEMP, DEFAULT_MIN_TEMP
|
||||||
from homeassistant.const import (
|
from homeassistant.const import (
|
||||||
CONF_ADDRESS, CONF_BINARY_SENSORS, CONF_COVERS, CONF_HOST, CONF_LIGHTS,
|
CONF_ADDRESS, CONF_BINARY_SENSORS, CONF_COVERS, CONF_HOST, CONF_LIGHTS,
|
||||||
CONF_NAME, CONF_PASSWORD, CONF_PORT, CONF_SENSORS, CONF_SWITCHES,
|
CONF_NAME, CONF_PASSWORD, CONF_PORT, CONF_SENSORS, CONF_SWITCHES,
|
||||||
CONF_UNIT_OF_MEASUREMENT, CONF_USERNAME, TEMP_CELSIUS, TEMP_FAHRENHEIT)
|
CONF_UNIT_OF_MEASUREMENT, CONF_USERNAME, TEMP_CELSIUS, TEMP_FAHRENHEIT)
|
||||||
import homeassistant.helpers.config_validation as cv
|
|
||||||
from homeassistant.helpers.discovery import async_load_platform
|
from homeassistant.helpers.discovery import async_load_platform
|
||||||
from homeassistant.helpers.entity import Entity
|
from homeassistant.helpers.entity import Entity
|
||||||
|
|
||||||
from .const import (
|
from .const import (
|
||||||
BINSENSOR_PORTS, CONF_CLIMATES, CONF_CONNECTIONS, CONF_DIM_MODE,
|
BINSENSOR_PORTS, CONF_CLIMATES, CONF_CONNECTIONS, CONF_DIM_MODE,
|
||||||
CONF_DIMMABLE, CONF_LOCKABLE, CONF_MAX_TEMP, CONF_MIN_TEMP, CONF_MOTOR,
|
CONF_DIMMABLE, CONF_LOCKABLE, CONF_MAX_TEMP, CONF_MIN_TEMP, CONF_MOTOR,
|
||||||
CONF_OUTPUT, CONF_OUTPUTS, CONF_REGISTER, CONF_SCENE, CONF_SCENES,
|
CONF_OUTPUT, CONF_OUTPUTS, CONF_REGISTER, CONF_REVERSE_TIME, CONF_SCENE,
|
||||||
CONF_SETPOINT, CONF_SK_NUM_TRIES, CONF_SOURCE, CONF_TRANSITION, DATA_LCN,
|
CONF_SCENES, CONF_SETPOINT, CONF_SK_NUM_TRIES, CONF_SOURCE,
|
||||||
DIM_MODES, DOMAIN, KEYS, LED_PORTS, LOGICOP_PORTS, MOTOR_PORTS,
|
CONF_TRANSITION, DATA_LCN, DIM_MODES, DOMAIN, KEYS, LED_PORTS,
|
||||||
OUTPUT_PORTS, RELAY_PORTS, S0_INPUTS, SETPOINTS, THRESHOLDS, VAR_UNITS,
|
LOGICOP_PORTS, MOTOR_PORTS, MOTOR_REVERSE_TIME, OUTPUT_PORTS, RELAY_PORTS,
|
||||||
VARIABLES)
|
S0_INPUTS, SETPOINTS, THRESHOLDS, VAR_UNITS, VARIABLES)
|
||||||
from .helpers import has_unique_connection_names, is_address
|
from .helpers import has_unique_connection_names, is_address
|
||||||
from .services import (
|
from .services import (
|
||||||
DynText, Led, LockKeys, LockRegulator, OutputAbs, OutputRel, OutputToggle,
|
DynText, Led, LockKeys, LockRegulator, OutputAbs, OutputRel, OutputToggle,
|
||||||
@ -51,7 +51,9 @@ CLIMATES_SCHEMA = vol.Schema({
|
|||||||
COVERS_SCHEMA = vol.Schema({
|
COVERS_SCHEMA = vol.Schema({
|
||||||
vol.Required(CONF_NAME): cv.string,
|
vol.Required(CONF_NAME): cv.string,
|
||||||
vol.Required(CONF_ADDRESS): is_address,
|
vol.Required(CONF_ADDRESS): is_address,
|
||||||
vol.Required(CONF_MOTOR): vol.All(vol.Upper, vol.In(MOTOR_PORTS))
|
vol.Required(CONF_MOTOR): vol.All(vol.Upper, vol.In(MOTOR_PORTS)),
|
||||||
|
vol.Optional(CONF_REVERSE_TIME): vol.All(vol.Upper,
|
||||||
|
vol.In(MOTOR_REVERSE_TIME))
|
||||||
})
|
})
|
||||||
|
|
||||||
LIGHTS_SCHEMA = vol.Schema({
|
LIGHTS_SCHEMA = vol.Schema({
|
||||||
|
@ -36,6 +36,7 @@ CONF_SCENES = 'scenes'
|
|||||||
CONF_REGISTER = 'register'
|
CONF_REGISTER = 'register'
|
||||||
CONF_SCENE = 'scene'
|
CONF_SCENE = 'scene'
|
||||||
CONF_OUTPUTS = 'outputs'
|
CONF_OUTPUTS = 'outputs'
|
||||||
|
CONF_REVERSE_TIME = 'reverse_time'
|
||||||
|
|
||||||
DIM_MODES = ['STEPS50', 'STEPS200']
|
DIM_MODES = ['STEPS50', 'STEPS200']
|
||||||
|
|
||||||
@ -46,7 +47,7 @@ RELAY_PORTS = ['RELAY1', 'RELAY2', 'RELAY3', 'RELAY4',
|
|||||||
'MOTORONOFF1', 'MOTORUPDOWN1', 'MOTORONOFF2', 'MOTORUPDOWN2',
|
'MOTORONOFF1', 'MOTORUPDOWN1', 'MOTORONOFF2', 'MOTORUPDOWN2',
|
||||||
'MOTORONOFF3', 'MOTORUPDOWN3', 'MOTORONOFF4', 'MOTORUPDOWN4']
|
'MOTORONOFF3', 'MOTORUPDOWN3', 'MOTORONOFF4', 'MOTORUPDOWN4']
|
||||||
|
|
||||||
MOTOR_PORTS = ['MOTOR1', 'MOTOR2', 'MOTOR3', 'MOTOR4']
|
MOTOR_PORTS = ['MOTOR1', 'MOTOR2', 'MOTOR3', 'MOTOR4', 'OUTPUTS']
|
||||||
|
|
||||||
LED_PORTS = ['LED1', 'LED2', 'LED3', 'LED4', 'LED5', 'LED6',
|
LED_PORTS = ['LED1', 'LED2', 'LED3', 'LED4', 'LED5', 'LED6',
|
||||||
'LED7', 'LED8', 'LED9', 'LED10', 'LED11', 'LED12']
|
'LED7', 'LED8', 'LED9', 'LED10', 'LED11', 'LED12']
|
||||||
@ -96,3 +97,5 @@ TIME_UNITS = ['SECONDS', 'SECOND', 'SEC', 'S',
|
|||||||
'MINUTES', 'MINUTE', 'MIN', 'M',
|
'MINUTES', 'MINUTE', 'MIN', 'M',
|
||||||
'HOURS', 'HOUR', 'H',
|
'HOURS', 'HOUR', 'H',
|
||||||
'DAYS', 'DAY', 'D']
|
'DAYS', 'DAY', 'D']
|
||||||
|
|
||||||
|
MOTOR_REVERSE_TIME = ['RT70', 'RT600', 'RT1200']
|
||||||
|
@ -5,7 +5,7 @@ from homeassistant.components.cover import CoverDevice
|
|||||||
from homeassistant.const import CONF_ADDRESS
|
from homeassistant.const import CONF_ADDRESS
|
||||||
|
|
||||||
from . import LcnDevice
|
from . import LcnDevice
|
||||||
from .const import CONF_CONNECTIONS, CONF_MOTOR, DATA_LCN
|
from .const import CONF_CONNECTIONS, CONF_MOTOR, CONF_REVERSE_TIME, DATA_LCN
|
||||||
from .helpers import get_connection
|
from .helpers import get_connection
|
||||||
|
|
||||||
|
|
||||||
@ -23,13 +23,91 @@ async def async_setup_platform(hass, hass_config, async_add_entities,
|
|||||||
connection = get_connection(connections, connection_id)
|
connection = get_connection(connections, connection_id)
|
||||||
address_connection = connection.get_address_conn(addr)
|
address_connection = connection.get_address_conn(addr)
|
||||||
|
|
||||||
devices.append(LcnCover(config, address_connection))
|
if config[CONF_MOTOR] == 'OUTPUTS':
|
||||||
|
devices.append(LcnOutputsCover(config, address_connection))
|
||||||
|
else: # RELAYS
|
||||||
|
devices.append(LcnRelayCover(config, address_connection))
|
||||||
|
|
||||||
async_add_entities(devices)
|
async_add_entities(devices)
|
||||||
|
|
||||||
|
|
||||||
class LcnCover(LcnDevice, CoverDevice):
|
class LcnOutputsCover(LcnDevice, CoverDevice):
|
||||||
"""Representation of a LCN cover."""
|
"""Representation of a LCN cover connected to output ports."""
|
||||||
|
|
||||||
|
def __init__(self, config, address_connection):
|
||||||
|
"""Initialize the LCN cover."""
|
||||||
|
super().__init__(config, address_connection)
|
||||||
|
|
||||||
|
self.output_ids = [pypck.lcn_defs.OutputPort['OUTPUTUP'].value,
|
||||||
|
pypck.lcn_defs.OutputPort['OUTPUTDOWN'].value]
|
||||||
|
if CONF_REVERSE_TIME in config:
|
||||||
|
self.reverse_time = pypck.lcn_defs.MotorReverseTime[
|
||||||
|
config[CONF_REVERSE_TIME]]
|
||||||
|
else:
|
||||||
|
self.reverse_time = None
|
||||||
|
self._closed = None
|
||||||
|
self.state_up = False
|
||||||
|
self.state_down = False
|
||||||
|
|
||||||
|
async def async_added_to_hass(self):
|
||||||
|
"""Run when entity about to be added to hass."""
|
||||||
|
await super().async_added_to_hass()
|
||||||
|
await self.address_connection.activate_status_request_handler(
|
||||||
|
pypck.lcn_defs.OutputPort['OUTPUTUP'])
|
||||||
|
await self.address_connection.activate_status_request_handler(
|
||||||
|
pypck.lcn_defs.OutputPort['OUTPUTDOWN'])
|
||||||
|
|
||||||
|
@property
|
||||||
|
def is_closed(self):
|
||||||
|
"""Return if the cover is closed."""
|
||||||
|
return self._closed
|
||||||
|
|
||||||
|
async def async_close_cover(self, **kwargs):
|
||||||
|
"""Close the cover."""
|
||||||
|
self._closed = True
|
||||||
|
|
||||||
|
state = pypck.lcn_defs.MotorStateModifier.DOWN
|
||||||
|
self.address_connection.control_motors_outputs(
|
||||||
|
state)
|
||||||
|
await self.async_update_ha_state()
|
||||||
|
|
||||||
|
async def async_open_cover(self, **kwargs):
|
||||||
|
"""Open the cover."""
|
||||||
|
self._closed = False
|
||||||
|
state = pypck.lcn_defs.MotorStateModifier.UP
|
||||||
|
self.address_connection.control_motors_outputs(
|
||||||
|
state, self.reverse_time)
|
||||||
|
await self.async_update_ha_state()
|
||||||
|
|
||||||
|
async def async_stop_cover(self, **kwargs):
|
||||||
|
"""Stop the cover."""
|
||||||
|
self._closed = None
|
||||||
|
state = pypck.lcn_defs.MotorStateModifier.STOP
|
||||||
|
self.address_connection.control_motors_outputs(
|
||||||
|
state, self.reverse_time)
|
||||||
|
await self.async_update_ha_state()
|
||||||
|
|
||||||
|
def input_received(self, input_obj):
|
||||||
|
"""Set cover states when LCN input object (command) is received."""
|
||||||
|
if not isinstance(input_obj, pypck.inputs.ModStatusOutput) or \
|
||||||
|
input_obj.get_output_id() not in self.output_ids:
|
||||||
|
return
|
||||||
|
|
||||||
|
if input_obj.get_output_id() == self.output_ids[0]:
|
||||||
|
self.state_up = (input_obj.get_percent() > 0)
|
||||||
|
else: # self.output_ids[1]
|
||||||
|
self.state_down = (input_obj.get_percent() > 0)
|
||||||
|
|
||||||
|
if self.state_up and not self.state_down:
|
||||||
|
self._closed = False # Cover open
|
||||||
|
elif self.state_down and not self.state_up:
|
||||||
|
self._closed = True # Cover closed
|
||||||
|
|
||||||
|
self.async_schedule_update_ha_state()
|
||||||
|
|
||||||
|
|
||||||
|
class LcnRelayCover(LcnDevice, CoverDevice):
|
||||||
|
"""Representation of a LCN cover connected to relays."""
|
||||||
|
|
||||||
def __init__(self, config, address_connection):
|
def __init__(self, config, address_connection):
|
||||||
"""Initialize the LCN cover."""
|
"""Initialize the LCN cover."""
|
||||||
@ -57,7 +135,7 @@ class LcnCover(LcnDevice, CoverDevice):
|
|||||||
self._closed = True
|
self._closed = True
|
||||||
states = [pypck.lcn_defs.MotorStateModifier.NOCHANGE] * 4
|
states = [pypck.lcn_defs.MotorStateModifier.NOCHANGE] * 4
|
||||||
states[self.motor.value] = pypck.lcn_defs.MotorStateModifier.DOWN
|
states[self.motor.value] = pypck.lcn_defs.MotorStateModifier.DOWN
|
||||||
self.address_connection.control_motors(states)
|
self.address_connection.control_motors_relays(states)
|
||||||
await self.async_update_ha_state()
|
await self.async_update_ha_state()
|
||||||
|
|
||||||
async def async_open_cover(self, **kwargs):
|
async def async_open_cover(self, **kwargs):
|
||||||
@ -65,7 +143,7 @@ class LcnCover(LcnDevice, CoverDevice):
|
|||||||
self._closed = False
|
self._closed = False
|
||||||
states = [pypck.lcn_defs.MotorStateModifier.NOCHANGE] * 4
|
states = [pypck.lcn_defs.MotorStateModifier.NOCHANGE] * 4
|
||||||
states[self.motor.value] = pypck.lcn_defs.MotorStateModifier.UP
|
states[self.motor.value] = pypck.lcn_defs.MotorStateModifier.UP
|
||||||
self.address_connection.control_motors(states)
|
self.address_connection.control_motors_relays(states)
|
||||||
await self.async_update_ha_state()
|
await self.async_update_ha_state()
|
||||||
|
|
||||||
async def async_stop_cover(self, **kwargs):
|
async def async_stop_cover(self, **kwargs):
|
||||||
@ -73,7 +151,7 @@ class LcnCover(LcnDevice, CoverDevice):
|
|||||||
self._closed = None
|
self._closed = None
|
||||||
states = [pypck.lcn_defs.MotorStateModifier.NOCHANGE] * 4
|
states = [pypck.lcn_defs.MotorStateModifier.NOCHANGE] * 4
|
||||||
states[self.motor.value] = pypck.lcn_defs.MotorStateModifier.STOP
|
states[self.motor.value] = pypck.lcn_defs.MotorStateModifier.STOP
|
||||||
self.address_connection.control_motors(states)
|
self.address_connection.control_motors_relays(states)
|
||||||
await self.async_update_ha_state()
|
await self.async_update_ha_state()
|
||||||
|
|
||||||
def input_received(self, input_obj):
|
def input_received(self, input_obj):
|
||||||
|
@ -3,7 +3,7 @@
|
|||||||
"name": "Lcn",
|
"name": "Lcn",
|
||||||
"documentation": "https://www.home-assistant.io/components/lcn",
|
"documentation": "https://www.home-assistant.io/components/lcn",
|
||||||
"requirements": [
|
"requirements": [
|
||||||
"pypck==0.6.2"
|
"pypck==0.6.3"
|
||||||
],
|
],
|
||||||
"dependencies": [],
|
"dependencies": [],
|
||||||
"codeowners": [
|
"codeowners": [
|
||||||
|
@ -1330,7 +1330,7 @@ pyowm==2.10.0
|
|||||||
pypca==0.0.4
|
pypca==0.0.4
|
||||||
|
|
||||||
# homeassistant.components.lcn
|
# homeassistant.components.lcn
|
||||||
pypck==0.6.2
|
pypck==0.6.3
|
||||||
|
|
||||||
# homeassistant.components.pjlink
|
# homeassistant.components.pjlink
|
||||||
pypjlink2==1.2.0
|
pypjlink2==1.2.0
|
||||||
|
Loading…
x
Reference in New Issue
Block a user