189 lines
6.1 KiB
Python
189 lines
6.1 KiB
Python
"""Support for Modbus."""
|
|
import voluptuous as vol
|
|
|
|
from homeassistant.components.cover import (
|
|
DEVICE_CLASSES_SCHEMA as COVER_DEVICE_CLASSES_SCHEMA,
|
|
)
|
|
from homeassistant.const import (
|
|
ATTR_STATE,
|
|
CONF_COVERS,
|
|
CONF_DELAY,
|
|
CONF_DEVICE_CLASS,
|
|
CONF_HOST,
|
|
CONF_METHOD,
|
|
CONF_NAME,
|
|
CONF_OFFSET,
|
|
CONF_PORT,
|
|
CONF_SCAN_INTERVAL,
|
|
CONF_SLAVE,
|
|
CONF_STRUCTURE,
|
|
CONF_TIMEOUT,
|
|
CONF_TYPE,
|
|
)
|
|
import homeassistant.helpers.config_validation as cv
|
|
|
|
from .const import (
|
|
ATTR_ADDRESS,
|
|
ATTR_HUB,
|
|
ATTR_UNIT,
|
|
ATTR_VALUE,
|
|
CALL_TYPE_COIL,
|
|
CALL_TYPE_REGISTER_HOLDING,
|
|
CALL_TYPE_REGISTER_INPUT,
|
|
CONF_BAUDRATE,
|
|
CONF_BYTESIZE,
|
|
CONF_CLIMATES,
|
|
CONF_CURRENT_TEMP,
|
|
CONF_CURRENT_TEMP_REGISTER_TYPE,
|
|
CONF_DATA_COUNT,
|
|
CONF_DATA_TYPE,
|
|
CONF_INPUT_TYPE,
|
|
CONF_MAX_TEMP,
|
|
CONF_MIN_TEMP,
|
|
CONF_PARITY,
|
|
CONF_PRECISION,
|
|
CONF_REGISTER,
|
|
CONF_SCALE,
|
|
CONF_STATE_CLOSED,
|
|
CONF_STATE_CLOSING,
|
|
CONF_STATE_OPEN,
|
|
CONF_STATE_OPENING,
|
|
CONF_STATUS_REGISTER,
|
|
CONF_STATUS_REGISTER_TYPE,
|
|
CONF_STEP,
|
|
CONF_STOPBITS,
|
|
CONF_TARGET_TEMP,
|
|
CONF_UNIT,
|
|
DATA_TYPE_CUSTOM,
|
|
DATA_TYPE_FLOAT,
|
|
DATA_TYPE_INT,
|
|
DATA_TYPE_UINT,
|
|
DEFAULT_HUB,
|
|
DEFAULT_SCAN_INTERVAL,
|
|
DEFAULT_SLAVE,
|
|
DEFAULT_STRUCTURE_PREFIX,
|
|
DEFAULT_TEMP_UNIT,
|
|
MODBUS_DOMAIN as DOMAIN,
|
|
)
|
|
from .modbus import modbus_setup
|
|
|
|
BASE_SCHEMA = vol.Schema({vol.Optional(CONF_NAME, default=DEFAULT_HUB): cv.string})
|
|
|
|
CLIMATE_SCHEMA = vol.Schema(
|
|
{
|
|
vol.Required(CONF_CURRENT_TEMP): cv.positive_int,
|
|
vol.Required(CONF_NAME): cv.string,
|
|
vol.Required(CONF_SLAVE): cv.positive_int,
|
|
vol.Required(CONF_TARGET_TEMP): cv.positive_int,
|
|
vol.Optional(CONF_DATA_COUNT, default=2): cv.positive_int,
|
|
vol.Optional(
|
|
CONF_CURRENT_TEMP_REGISTER_TYPE, default=CALL_TYPE_REGISTER_HOLDING
|
|
): vol.In([CALL_TYPE_REGISTER_HOLDING, CALL_TYPE_REGISTER_INPUT]),
|
|
vol.Optional(CONF_DATA_TYPE, default=DATA_TYPE_FLOAT): vol.In(
|
|
[DATA_TYPE_INT, DATA_TYPE_UINT, DATA_TYPE_FLOAT, DATA_TYPE_CUSTOM]
|
|
),
|
|
vol.Optional(CONF_PRECISION, default=1): cv.positive_int,
|
|
vol.Optional(CONF_SCALE, default=1): vol.Coerce(float),
|
|
vol.Optional(CONF_SCAN_INTERVAL, default=DEFAULT_SCAN_INTERVAL): vol.All(
|
|
cv.time_period, lambda value: value.total_seconds()
|
|
),
|
|
vol.Optional(CONF_OFFSET, default=0): vol.Coerce(float),
|
|
vol.Optional(CONF_MAX_TEMP, default=35): cv.positive_int,
|
|
vol.Optional(CONF_MIN_TEMP, default=5): cv.positive_int,
|
|
vol.Optional(CONF_STEP, default=0.5): vol.Coerce(float),
|
|
vol.Optional(CONF_STRUCTURE, default=DEFAULT_STRUCTURE_PREFIX): cv.string,
|
|
vol.Optional(CONF_UNIT, default=DEFAULT_TEMP_UNIT): cv.string,
|
|
}
|
|
)
|
|
|
|
COVERS_SCHEMA = vol.All(
|
|
cv.has_at_least_one_key(CALL_TYPE_COIL, CONF_REGISTER),
|
|
vol.Schema(
|
|
{
|
|
vol.Required(CONF_NAME): cv.string,
|
|
vol.Optional(CONF_SCAN_INTERVAL, default=DEFAULT_SCAN_INTERVAL): vol.All(
|
|
cv.time_period, lambda value: value.total_seconds()
|
|
),
|
|
vol.Optional(CONF_DEVICE_CLASS): COVER_DEVICE_CLASSES_SCHEMA,
|
|
vol.Optional(CONF_SLAVE, default=DEFAULT_SLAVE): cv.positive_int,
|
|
vol.Optional(CONF_STATE_CLOSED, default=0): cv.positive_int,
|
|
vol.Optional(CONF_STATE_CLOSING, default=3): cv.positive_int,
|
|
vol.Optional(CONF_STATE_OPEN, default=1): cv.positive_int,
|
|
vol.Optional(CONF_STATE_OPENING, default=2): cv.positive_int,
|
|
vol.Optional(CONF_STATUS_REGISTER): cv.positive_int,
|
|
vol.Optional(
|
|
CONF_STATUS_REGISTER_TYPE,
|
|
default=CALL_TYPE_REGISTER_HOLDING,
|
|
): vol.In([CALL_TYPE_REGISTER_HOLDING, CALL_TYPE_REGISTER_INPUT]),
|
|
vol.Exclusive(CALL_TYPE_COIL, CONF_INPUT_TYPE): cv.positive_int,
|
|
vol.Exclusive(CONF_REGISTER, CONF_INPUT_TYPE): cv.positive_int,
|
|
}
|
|
),
|
|
)
|
|
|
|
SERIAL_SCHEMA = BASE_SCHEMA.extend(
|
|
{
|
|
vol.Required(CONF_BAUDRATE): cv.positive_int,
|
|
vol.Required(CONF_BYTESIZE): vol.Any(5, 6, 7, 8),
|
|
vol.Required(CONF_METHOD): vol.Any("rtu", "ascii"),
|
|
vol.Required(CONF_PORT): cv.string,
|
|
vol.Required(CONF_PARITY): vol.Any("E", "O", "N"),
|
|
vol.Required(CONF_STOPBITS): vol.Any(1, 2),
|
|
vol.Required(CONF_TYPE): "serial",
|
|
vol.Optional(CONF_TIMEOUT, default=3): cv.socket_timeout,
|
|
vol.Optional(CONF_CLIMATES): vol.All(cv.ensure_list, [CLIMATE_SCHEMA]),
|
|
vol.Optional(CONF_COVERS): vol.All(cv.ensure_list, [COVERS_SCHEMA]),
|
|
}
|
|
)
|
|
|
|
ETHERNET_SCHEMA = BASE_SCHEMA.extend(
|
|
{
|
|
vol.Required(CONF_HOST): cv.string,
|
|
vol.Required(CONF_PORT): cv.port,
|
|
vol.Required(CONF_TYPE): vol.Any("tcp", "udp", "rtuovertcp"),
|
|
vol.Optional(CONF_TIMEOUT, default=3): cv.socket_timeout,
|
|
vol.Optional(CONF_DELAY, default=0): cv.positive_int,
|
|
vol.Optional(CONF_CLIMATES): vol.All(cv.ensure_list, [CLIMATE_SCHEMA]),
|
|
vol.Optional(CONF_COVERS): vol.All(cv.ensure_list, [COVERS_SCHEMA]),
|
|
}
|
|
)
|
|
|
|
SERVICE_WRITE_REGISTER_SCHEMA = vol.Schema(
|
|
{
|
|
vol.Optional(ATTR_HUB, default=DEFAULT_HUB): cv.string,
|
|
vol.Required(ATTR_UNIT): cv.positive_int,
|
|
vol.Required(ATTR_ADDRESS): cv.positive_int,
|
|
vol.Required(ATTR_VALUE): vol.Any(
|
|
cv.positive_int, vol.All(cv.ensure_list, [cv.positive_int])
|
|
),
|
|
}
|
|
)
|
|
|
|
SERVICE_WRITE_COIL_SCHEMA = vol.Schema(
|
|
{
|
|
vol.Optional(ATTR_HUB, default=DEFAULT_HUB): cv.string,
|
|
vol.Required(ATTR_UNIT): cv.positive_int,
|
|
vol.Required(ATTR_ADDRESS): cv.positive_int,
|
|
vol.Required(ATTR_STATE): cv.boolean,
|
|
}
|
|
)
|
|
|
|
CONFIG_SCHEMA = vol.Schema(
|
|
{
|
|
DOMAIN: vol.All(
|
|
cv.ensure_list,
|
|
[
|
|
vol.Any(SERIAL_SCHEMA, ETHERNET_SCHEMA),
|
|
],
|
|
),
|
|
},
|
|
extra=vol.ALLOW_EXTRA,
|
|
)
|
|
|
|
|
|
def setup(hass, config):
|
|
"""Set up Modbus component."""
|
|
return modbus_setup(
|
|
hass, config, SERVICE_WRITE_REGISTER_SCHEMA, SERVICE_WRITE_COIL_SCHEMA
|
|
)
|