diff --git a/homeassistant/components/knx/__init__.py b/homeassistant/components/knx/__init__.py index 8265ba42b72..b8feb010e29 100644 --- a/homeassistant/components/knx/__init__.py +++ b/homeassistant/components/knx/__init__.py @@ -47,6 +47,8 @@ from .schema import ( SensorSchema, SwitchSchema, WeatherSchema, + ga_validator, + ia_validator, ) _LOGGER = logging.getLogger(__name__) @@ -92,7 +94,7 @@ CONFIG_SCHEMA = vol.Schema( ), vol.Optional( CONF_KNX_INDIVIDUAL_ADDRESS, default=XKNX.DEFAULT_ADDRESS - ): cv.string, + ): ia_validator, vol.Optional( CONF_KNX_MCAST_GRP, default=DEFAULT_MCAST_GRP ): cv.string, @@ -146,7 +148,7 @@ CONFIG_SCHEMA = vol.Schema( SERVICE_KNX_SEND_SCHEMA = vol.Any( vol.Schema( { - vol.Required(CONF_ADDRESS): cv.string, + vol.Required(CONF_ADDRESS): ga_validator, vol.Required(SERVICE_KNX_ATTR_PAYLOAD): cv.match_all, vol.Required(SERVICE_KNX_ATTR_TYPE): vol.Any(int, float, str), } @@ -154,7 +156,7 @@ SERVICE_KNX_SEND_SCHEMA = vol.Any( vol.Schema( # without type given payload is treated as raw bytes { - vol.Required(CONF_ADDRESS): cv.string, + vol.Required(CONF_ADDRESS): ga_validator, vol.Required(SERVICE_KNX_ATTR_PAYLOAD): vol.Any( cv.positive_int, [cv.positive_int] ), @@ -166,14 +168,14 @@ SERVICE_KNX_READ_SCHEMA = vol.Schema( { vol.Required(CONF_ADDRESS): vol.All( cv.ensure_list, - [cv.string], + [ga_validator], ) } ) SERVICE_KNX_EVENT_REGISTER_SCHEMA = vol.Schema( { - vol.Required(CONF_ADDRESS): cv.string, + vol.Required(CONF_ADDRESS): ga_validator, vol.Optional(SERVICE_KNX_ATTR_REMOVE, default=False): cv.boolean, } ) @@ -187,7 +189,7 @@ SERVICE_KNX_EXPOSURE_REGISTER_SCHEMA = vol.Any( vol.Schema( # for removing only `address` is required { - vol.Required(CONF_ADDRESS): cv.string, + vol.Required(CONF_ADDRESS): ga_validator, vol.Required(SERVICE_KNX_ATTR_REMOVE): vol.All(cv.boolean, True), }, extra=vol.ALLOW_EXTRA, diff --git a/homeassistant/components/knx/schema.py b/homeassistant/components/knx/schema.py index 1a48d7945bd..08a8c62adc4 100644 --- a/homeassistant/components/knx/schema.py +++ b/homeassistant/components/knx/schema.py @@ -2,6 +2,7 @@ import voluptuous as vol from xknx.devices.climate import SetpointShiftMode from xknx.io import DEFAULT_MCAST_PORT +from xknx.telegram.address import GroupAddress, IndividualAddress from homeassistant.const import ( CONF_ADDRESS, @@ -24,6 +25,33 @@ from .const import ( ColorTempModes, ) +################## +# KNX VALIDATORS +################## + +ga_validator = vol.Any( + cv.matches_regex(GroupAddress.ADDRESS_RE), + vol.All(vol.Coerce(int), vol.Range(min=1, max=65535)), + msg="value does not match pattern for KNX group address '
//', '
/' or '' (eg.'1/2/3', '9/234', '123')", +) + +ia_validator = vol.Any( + cv.matches_regex(IndividualAddress.ADDRESS_RE), + vol.All(vol.Coerce(int), vol.Range(min=1, max=65535)), + msg="value does not match pattern for KNX individual address '..' (eg.'1.1.100')", +) + +sync_state_validator = vol.Any( + vol.All(vol.Coerce(int), vol.Range(min=2, max=1440)), + cv.boolean, + cv.matches_regex(r"^(init|expire|every)( \d*)?$"), +) + + +############## +# CONNECTION +############## + class ConnectionSchema: """Voluptuous schema for KNX connection.""" @@ -41,45 +69,9 @@ class ConnectionSchema: ROUTING_SCHEMA = vol.Maybe(vol.Schema({vol.Optional(CONF_KNX_LOCAL_IP): cv.string})) -class CoverSchema: - """Voluptuous schema for KNX covers.""" - - CONF_MOVE_LONG_ADDRESS = "move_long_address" - CONF_MOVE_SHORT_ADDRESS = "move_short_address" - CONF_STOP_ADDRESS = "stop_address" - CONF_POSITION_ADDRESS = "position_address" - CONF_POSITION_STATE_ADDRESS = "position_state_address" - CONF_ANGLE_ADDRESS = "angle_address" - CONF_ANGLE_STATE_ADDRESS = "angle_state_address" - CONF_TRAVELLING_TIME_DOWN = "travelling_time_down" - CONF_TRAVELLING_TIME_UP = "travelling_time_up" - CONF_INVERT_POSITION = "invert_position" - CONF_INVERT_ANGLE = "invert_angle" - - DEFAULT_TRAVEL_TIME = 25 - DEFAULT_NAME = "KNX Cover" - - SCHEMA = vol.Schema( - { - vol.Optional(CONF_NAME, default=DEFAULT_NAME): cv.string, - vol.Optional(CONF_MOVE_LONG_ADDRESS): cv.string, - vol.Optional(CONF_MOVE_SHORT_ADDRESS): cv.string, - vol.Optional(CONF_STOP_ADDRESS): cv.string, - vol.Optional(CONF_POSITION_ADDRESS): cv.string, - vol.Optional(CONF_POSITION_STATE_ADDRESS): cv.string, - vol.Optional(CONF_ANGLE_ADDRESS): cv.string, - vol.Optional(CONF_ANGLE_STATE_ADDRESS): cv.string, - vol.Optional( - CONF_TRAVELLING_TIME_DOWN, default=DEFAULT_TRAVEL_TIME - ): cv.positive_int, - vol.Optional( - CONF_TRAVELLING_TIME_UP, default=DEFAULT_TRAVEL_TIME - ): cv.positive_int, - vol.Optional(CONF_INVERT_POSITION, default=False): cv.boolean, - vol.Optional(CONF_INVERT_ANGLE, default=False): cv.boolean, - vol.Optional(CONF_DEVICE_CLASS): cv.string, - } - ) +############# +# PLATFORMS +############# class BinarySensorSchema: @@ -100,13 +92,9 @@ class BinarySensorSchema: vol.Schema( { vol.Optional(CONF_NAME, default=DEFAULT_NAME): cv.string, - vol.Optional(CONF_SYNC_STATE, default=True): vol.Any( - vol.All(vol.Coerce(int), vol.Range(min=2, max=1440)), - cv.boolean, - cv.string, - ), + vol.Optional(CONF_SYNC_STATE, default=True): sync_state_validator, vol.Optional(CONF_IGNORE_INTERNAL_STATE, default=False): cv.boolean, - vol.Required(CONF_STATE_ADDRESS): cv.string, + vol.Required(CONF_STATE_ADDRESS): ga_validator, vol.Optional(CONF_CONTEXT_TIMEOUT): vol.All( vol.Coerce(float), vol.Range(min=0, max=10) ), @@ -118,95 +106,6 @@ class BinarySensorSchema: ) -class LightSchema: - """Voluptuous schema for KNX lights.""" - - CONF_STATE_ADDRESS = CONF_STATE_ADDRESS - CONF_BRIGHTNESS_ADDRESS = "brightness_address" - CONF_BRIGHTNESS_STATE_ADDRESS = "brightness_state_address" - CONF_COLOR_ADDRESS = "color_address" - CONF_COLOR_STATE_ADDRESS = "color_state_address" - CONF_COLOR_TEMP_ADDRESS = "color_temperature_address" - CONF_COLOR_TEMP_STATE_ADDRESS = "color_temperature_state_address" - CONF_COLOR_TEMP_MODE = "color_temperature_mode" - CONF_RGBW_ADDRESS = "rgbw_address" - CONF_RGBW_STATE_ADDRESS = "rgbw_state_address" - CONF_MIN_KELVIN = "min_kelvin" - CONF_MAX_KELVIN = "max_kelvin" - - DEFAULT_NAME = "KNX Light" - DEFAULT_COLOR_TEMP_MODE = "absolute" - DEFAULT_MIN_KELVIN = 2700 # 370 mireds - DEFAULT_MAX_KELVIN = 6000 # 166 mireds - - CONF_INDIVIDUAL_COLORS = "individual_colors" - CONF_RED = "red" - CONF_GREEN = "green" - CONF_BLUE = "blue" - CONF_WHITE = "white" - - COLOR_SCHEMA = vol.Schema( - { - vol.Optional(CONF_ADDRESS): cv.string, - vol.Optional(CONF_STATE_ADDRESS): cv.string, - vol.Required(CONF_BRIGHTNESS_ADDRESS): cv.string, - vol.Optional(CONF_BRIGHTNESS_STATE_ADDRESS): cv.string, - } - ) - - SCHEMA = vol.All( - vol.Schema( - { - vol.Optional(CONF_ADDRESS): cv.string, - vol.Optional(CONF_NAME, default=DEFAULT_NAME): cv.string, - vol.Optional(CONF_STATE_ADDRESS): cv.string, - vol.Optional(CONF_BRIGHTNESS_ADDRESS): cv.string, - vol.Optional(CONF_BRIGHTNESS_STATE_ADDRESS): cv.string, - vol.Exclusive(CONF_INDIVIDUAL_COLORS, "color"): { - vol.Inclusive(CONF_RED, "colors"): COLOR_SCHEMA, - vol.Inclusive(CONF_GREEN, "colors"): COLOR_SCHEMA, - vol.Inclusive(CONF_BLUE, "colors"): COLOR_SCHEMA, - vol.Optional(CONF_WHITE): COLOR_SCHEMA, - }, - vol.Exclusive(CONF_COLOR_ADDRESS, "color"): cv.string, - vol.Optional(CONF_COLOR_STATE_ADDRESS): cv.string, - vol.Optional(CONF_COLOR_TEMP_ADDRESS): cv.string, - vol.Optional(CONF_COLOR_TEMP_STATE_ADDRESS): cv.string, - vol.Optional( - CONF_COLOR_TEMP_MODE, default=DEFAULT_COLOR_TEMP_MODE - ): vol.All(vol.Upper, cv.enum(ColorTempModes)), - vol.Exclusive(CONF_RGBW_ADDRESS, "color"): cv.string, - vol.Optional(CONF_RGBW_STATE_ADDRESS): cv.string, - vol.Optional(CONF_MIN_KELVIN, default=DEFAULT_MIN_KELVIN): vol.All( - vol.Coerce(int), vol.Range(min=1) - ), - vol.Optional(CONF_MAX_KELVIN, default=DEFAULT_MAX_KELVIN): vol.All( - vol.Coerce(int), vol.Range(min=1) - ), - } - ), - vol.Any( - # either global "address" or all addresses for individual colors are required - vol.Schema( - { - vol.Required(CONF_INDIVIDUAL_COLORS): { - vol.Required(CONF_RED): {vol.Required(CONF_ADDRESS): object}, - vol.Required(CONF_GREEN): {vol.Required(CONF_ADDRESS): object}, - vol.Required(CONF_BLUE): {vol.Required(CONF_ADDRESS): object}, - }, - }, - extra=vol.ALLOW_EXTRA, - ), - vol.Schema( - { - vol.Required(CONF_ADDRESS): object, - }, - extra=vol.ALLOW_EXTRA, - ), - ), - ) - - class ClimateSchema: """Voluptuous schema for KNX climate devices.""" @@ -266,25 +165,27 @@ class ClimateSchema: vol.Optional( CONF_TEMPERATURE_STEP, default=DEFAULT_TEMPERATURE_STEP ): vol.All(float, vol.Range(min=0, max=2)), - vol.Required(CONF_TEMPERATURE_ADDRESS): cv.string, - vol.Required(CONF_TARGET_TEMPERATURE_STATE_ADDRESS): cv.string, - vol.Optional(CONF_TARGET_TEMPERATURE_ADDRESS): cv.string, - vol.Optional(CONF_SETPOINT_SHIFT_ADDRESS): cv.string, - vol.Optional(CONF_SETPOINT_SHIFT_STATE_ADDRESS): cv.string, - vol.Optional(CONF_OPERATION_MODE_ADDRESS): cv.string, - vol.Optional(CONF_OPERATION_MODE_STATE_ADDRESS): cv.string, - vol.Optional(CONF_CONTROLLER_STATUS_ADDRESS): cv.string, - vol.Optional(CONF_CONTROLLER_STATUS_STATE_ADDRESS): cv.string, - vol.Optional(CONF_CONTROLLER_MODE_ADDRESS): cv.string, - vol.Optional(CONF_CONTROLLER_MODE_STATE_ADDRESS): cv.string, - vol.Optional(CONF_HEAT_COOL_ADDRESS): cv.string, - vol.Optional(CONF_HEAT_COOL_STATE_ADDRESS): cv.string, - vol.Optional(CONF_OPERATION_MODE_FROST_PROTECTION_ADDRESS): cv.string, - vol.Optional(CONF_OPERATION_MODE_NIGHT_ADDRESS): cv.string, - vol.Optional(CONF_OPERATION_MODE_COMFORT_ADDRESS): cv.string, - vol.Optional(CONF_OPERATION_MODE_STANDBY_ADDRESS): cv.string, - vol.Optional(CONF_ON_OFF_ADDRESS): cv.string, - vol.Optional(CONF_ON_OFF_STATE_ADDRESS): cv.string, + vol.Required(CONF_TEMPERATURE_ADDRESS): ga_validator, + vol.Required(CONF_TARGET_TEMPERATURE_STATE_ADDRESS): ga_validator, + vol.Optional(CONF_TARGET_TEMPERATURE_ADDRESS): ga_validator, + vol.Optional(CONF_SETPOINT_SHIFT_ADDRESS): ga_validator, + vol.Optional(CONF_SETPOINT_SHIFT_STATE_ADDRESS): ga_validator, + vol.Optional(CONF_OPERATION_MODE_ADDRESS): ga_validator, + vol.Optional(CONF_OPERATION_MODE_STATE_ADDRESS): ga_validator, + vol.Optional(CONF_CONTROLLER_STATUS_ADDRESS): ga_validator, + vol.Optional(CONF_CONTROLLER_STATUS_STATE_ADDRESS): ga_validator, + vol.Optional(CONF_CONTROLLER_MODE_ADDRESS): ga_validator, + vol.Optional(CONF_CONTROLLER_MODE_STATE_ADDRESS): ga_validator, + vol.Optional(CONF_HEAT_COOL_ADDRESS): ga_validator, + vol.Optional(CONF_HEAT_COOL_STATE_ADDRESS): ga_validator, + vol.Optional( + CONF_OPERATION_MODE_FROST_PROTECTION_ADDRESS + ): ga_validator, + vol.Optional(CONF_OPERATION_MODE_NIGHT_ADDRESS): ga_validator, + vol.Optional(CONF_OPERATION_MODE_COMFORT_ADDRESS): ga_validator, + vol.Optional(CONF_OPERATION_MODE_STANDBY_ADDRESS): ga_validator, + vol.Optional(CONF_ON_OFF_ADDRESS): ga_validator, + vol.Optional(CONF_ON_OFF_STATE_ADDRESS): ga_validator, vol.Optional( CONF_ON_OFF_INVERT, default=DEFAULT_ON_OFF_INVERT ): cv.boolean, @@ -304,19 +205,43 @@ class ClimateSchema: ) -class SwitchSchema: - """Voluptuous schema for KNX switches.""" +class CoverSchema: + """Voluptuous schema for KNX covers.""" - CONF_INVERT = CONF_INVERT - CONF_STATE_ADDRESS = CONF_STATE_ADDRESS + CONF_MOVE_LONG_ADDRESS = "move_long_address" + CONF_MOVE_SHORT_ADDRESS = "move_short_address" + CONF_STOP_ADDRESS = "stop_address" + CONF_POSITION_ADDRESS = "position_address" + CONF_POSITION_STATE_ADDRESS = "position_state_address" + CONF_ANGLE_ADDRESS = "angle_address" + CONF_ANGLE_STATE_ADDRESS = "angle_state_address" + CONF_TRAVELLING_TIME_DOWN = "travelling_time_down" + CONF_TRAVELLING_TIME_UP = "travelling_time_up" + CONF_INVERT_POSITION = "invert_position" + CONF_INVERT_ANGLE = "invert_angle" + + DEFAULT_TRAVEL_TIME = 25 + DEFAULT_NAME = "KNX Cover" - DEFAULT_NAME = "KNX Switch" SCHEMA = vol.Schema( { - vol.Required(CONF_ADDRESS): cv.string, vol.Optional(CONF_NAME, default=DEFAULT_NAME): cv.string, - vol.Optional(CONF_STATE_ADDRESS): cv.string, - vol.Optional(CONF_INVERT): cv.boolean, + vol.Optional(CONF_MOVE_LONG_ADDRESS): ga_validator, + vol.Optional(CONF_MOVE_SHORT_ADDRESS): ga_validator, + vol.Optional(CONF_STOP_ADDRESS): ga_validator, + vol.Optional(CONF_POSITION_ADDRESS): ga_validator, + vol.Optional(CONF_POSITION_STATE_ADDRESS): ga_validator, + vol.Optional(CONF_ANGLE_ADDRESS): ga_validator, + vol.Optional(CONF_ANGLE_STATE_ADDRESS): ga_validator, + vol.Optional( + CONF_TRAVELLING_TIME_DOWN, default=DEFAULT_TRAVEL_TIME + ): cv.positive_float, + vol.Optional( + CONF_TRAVELLING_TIME_UP, default=DEFAULT_TRAVEL_TIME + ): cv.positive_float, + vol.Optional(CONF_INVERT_POSITION, default=False): cv.boolean, + vol.Optional(CONF_INVERT_ANGLE, default=False): cv.boolean, + vol.Optional(CONF_DEVICE_CLASS): cv.string, } ) @@ -331,14 +256,125 @@ class ExposeSchema: SCHEMA = vol.Schema( { vol.Required(CONF_KNX_EXPOSE_TYPE): vol.Any(int, float, str), + vol.Required(CONF_ADDRESS): ga_validator, vol.Optional(CONF_ENTITY_ID): cv.entity_id, vol.Optional(CONF_KNX_EXPOSE_ATTRIBUTE): cv.string, vol.Optional(CONF_KNX_EXPOSE_DEFAULT): cv.match_all, - vol.Required(CONF_ADDRESS): cv.string, } ) +class FanSchema: + """Voluptuous schema for KNX fans.""" + + CONF_STATE_ADDRESS = CONF_STATE_ADDRESS + CONF_OSCILLATION_ADDRESS = "oscillation_address" + CONF_OSCILLATION_STATE_ADDRESS = "oscillation_state_address" + CONF_MAX_STEP = "max_step" + + DEFAULT_NAME = "KNX Fan" + + SCHEMA = vol.Schema( + { + vol.Optional(CONF_NAME, default=DEFAULT_NAME): cv.string, + vol.Required(CONF_ADDRESS): ga_validator, + vol.Optional(CONF_STATE_ADDRESS): ga_validator, + vol.Optional(CONF_OSCILLATION_ADDRESS): ga_validator, + vol.Optional(CONF_OSCILLATION_STATE_ADDRESS): ga_validator, + vol.Optional(CONF_MAX_STEP): cv.byte, + } + ) + + +class LightSchema: + """Voluptuous schema for KNX lights.""" + + CONF_STATE_ADDRESS = CONF_STATE_ADDRESS + CONF_BRIGHTNESS_ADDRESS = "brightness_address" + CONF_BRIGHTNESS_STATE_ADDRESS = "brightness_state_address" + CONF_COLOR_ADDRESS = "color_address" + CONF_COLOR_STATE_ADDRESS = "color_state_address" + CONF_COLOR_TEMP_ADDRESS = "color_temperature_address" + CONF_COLOR_TEMP_STATE_ADDRESS = "color_temperature_state_address" + CONF_COLOR_TEMP_MODE = "color_temperature_mode" + CONF_RGBW_ADDRESS = "rgbw_address" + CONF_RGBW_STATE_ADDRESS = "rgbw_state_address" + CONF_MIN_KELVIN = "min_kelvin" + CONF_MAX_KELVIN = "max_kelvin" + + DEFAULT_NAME = "KNX Light" + DEFAULT_COLOR_TEMP_MODE = "absolute" + DEFAULT_MIN_KELVIN = 2700 # 370 mireds + DEFAULT_MAX_KELVIN = 6000 # 166 mireds + + CONF_INDIVIDUAL_COLORS = "individual_colors" + CONF_RED = "red" + CONF_GREEN = "green" + CONF_BLUE = "blue" + CONF_WHITE = "white" + + COLOR_SCHEMA = vol.Schema( + { + vol.Optional(CONF_ADDRESS): ga_validator, + vol.Optional(CONF_STATE_ADDRESS): ga_validator, + vol.Required(CONF_BRIGHTNESS_ADDRESS): ga_validator, + vol.Optional(CONF_BRIGHTNESS_STATE_ADDRESS): ga_validator, + } + ) + + SCHEMA = vol.All( + vol.Schema( + { + vol.Optional(CONF_NAME, default=DEFAULT_NAME): cv.string, + vol.Optional(CONF_ADDRESS): ga_validator, + vol.Optional(CONF_STATE_ADDRESS): ga_validator, + vol.Optional(CONF_BRIGHTNESS_ADDRESS): ga_validator, + vol.Optional(CONF_BRIGHTNESS_STATE_ADDRESS): ga_validator, + vol.Exclusive(CONF_INDIVIDUAL_COLORS, "color"): { + vol.Inclusive(CONF_RED, "colors"): COLOR_SCHEMA, + vol.Inclusive(CONF_GREEN, "colors"): COLOR_SCHEMA, + vol.Inclusive(CONF_BLUE, "colors"): COLOR_SCHEMA, + vol.Optional(CONF_WHITE): COLOR_SCHEMA, + }, + vol.Exclusive(CONF_COLOR_ADDRESS, "color"): ga_validator, + vol.Optional(CONF_COLOR_STATE_ADDRESS): ga_validator, + vol.Optional(CONF_COLOR_TEMP_ADDRESS): ga_validator, + vol.Optional(CONF_COLOR_TEMP_STATE_ADDRESS): ga_validator, + vol.Optional( + CONF_COLOR_TEMP_MODE, default=DEFAULT_COLOR_TEMP_MODE + ): vol.All(vol.Upper, cv.enum(ColorTempModes)), + vol.Exclusive(CONF_RGBW_ADDRESS, "color"): ga_validator, + vol.Optional(CONF_RGBW_STATE_ADDRESS): ga_validator, + vol.Optional(CONF_MIN_KELVIN, default=DEFAULT_MIN_KELVIN): vol.All( + vol.Coerce(int), vol.Range(min=1) + ), + vol.Optional(CONF_MAX_KELVIN, default=DEFAULT_MAX_KELVIN): vol.All( + vol.Coerce(int), vol.Range(min=1) + ), + } + ), + vol.Any( + # either global "address" or all addresses for individual colors are required + vol.Schema( + { + vol.Required(CONF_INDIVIDUAL_COLORS): { + vol.Required(CONF_RED): {vol.Required(CONF_ADDRESS): object}, + vol.Required(CONF_GREEN): {vol.Required(CONF_ADDRESS): object}, + vol.Required(CONF_BLUE): {vol.Required(CONF_ADDRESS): object}, + }, + }, + extra=vol.ALLOW_EXTRA, + ), + vol.Schema( + { + vol.Required(CONF_ADDRESS): object, + }, + extra=vol.ALLOW_EXTRA, + ), + ), + ) + + class NotifySchema: """Voluptuous schema for KNX notifications.""" @@ -346,8 +382,23 @@ class NotifySchema: SCHEMA = vol.Schema( { - vol.Required(CONF_ADDRESS): cv.string, vol.Optional(CONF_NAME, default=DEFAULT_NAME): cv.string, + vol.Required(CONF_ADDRESS): ga_validator, + } + ) + + +class SceneSchema: + """Voluptuous schema for KNX scenes.""" + + CONF_SCENE_NUMBER = "scene_number" + + DEFAULT_NAME = "KNX SCENE" + SCHEMA = vol.Schema( + { + vol.Optional(CONF_NAME, default=DEFAULT_NAME): cv.string, + vol.Required(CONF_ADDRESS): ga_validator, + vol.Required(CONF_SCENE_NUMBER): cv.positive_int, } ) @@ -363,29 +414,27 @@ class SensorSchema: SCHEMA = vol.Schema( { vol.Optional(CONF_NAME, default=DEFAULT_NAME): cv.string, - vol.Optional(CONF_SYNC_STATE, default=True): vol.Any( - vol.All(vol.Coerce(int), vol.Range(min=2, max=1440)), - cv.boolean, - cv.string, - ), + vol.Optional(CONF_SYNC_STATE, default=True): sync_state_validator, vol.Optional(CONF_ALWAYS_CALLBACK, default=False): cv.boolean, - vol.Required(CONF_STATE_ADDRESS): cv.string, + vol.Required(CONF_STATE_ADDRESS): ga_validator, vol.Required(CONF_TYPE): vol.Any(int, float, str), } ) -class SceneSchema: - """Voluptuous schema for KNX scenes.""" +class SwitchSchema: + """Voluptuous schema for KNX switches.""" - CONF_SCENE_NUMBER = "scene_number" + CONF_INVERT = CONF_INVERT + CONF_STATE_ADDRESS = CONF_STATE_ADDRESS - DEFAULT_NAME = "KNX SCENE" + DEFAULT_NAME = "KNX Switch" SCHEMA = vol.Schema( { vol.Optional(CONF_NAME, default=DEFAULT_NAME): cv.string, - vol.Required(CONF_ADDRESS): cv.string, - vol.Required(CONF_SCENE_NUMBER): cv.positive_int, + vol.Required(CONF_ADDRESS): ga_validator, + vol.Optional(CONF_STATE_ADDRESS): ga_validator, + vol.Optional(CONF_INVERT): cv.boolean, } ) @@ -414,46 +463,20 @@ class WeatherSchema: SCHEMA = vol.Schema( { vol.Optional(CONF_NAME, default=DEFAULT_NAME): cv.string, - vol.Optional(CONF_SYNC_STATE, default=True): vol.Any( - vol.All(vol.Coerce(int), vol.Range(min=2, max=1440)), - cv.boolean, - cv.string, - ), + vol.Optional(CONF_SYNC_STATE, default=True): sync_state_validator, vol.Optional(CONF_KNX_CREATE_SENSORS, default=False): cv.boolean, - vol.Required(CONF_KNX_TEMPERATURE_ADDRESS): cv.string, - vol.Optional(CONF_KNX_BRIGHTNESS_SOUTH_ADDRESS): cv.string, - vol.Optional(CONF_KNX_BRIGHTNESS_EAST_ADDRESS): cv.string, - vol.Optional(CONF_KNX_BRIGHTNESS_WEST_ADDRESS): cv.string, - vol.Optional(CONF_KNX_BRIGHTNESS_NORTH_ADDRESS): cv.string, - vol.Optional(CONF_KNX_WIND_SPEED_ADDRESS): cv.string, - vol.Optional(CONF_KNX_WIND_BEARING_ADDRESS): cv.string, - vol.Optional(CONF_KNX_RAIN_ALARM_ADDRESS): cv.string, - vol.Optional(CONF_KNX_FROST_ALARM_ADDRESS): cv.string, - vol.Optional(CONF_KNX_WIND_ALARM_ADDRESS): cv.string, - vol.Optional(CONF_KNX_DAY_NIGHT_ADDRESS): cv.string, - vol.Optional(CONF_KNX_AIR_PRESSURE_ADDRESS): cv.string, - vol.Optional(CONF_KNX_HUMIDITY_ADDRESS): cv.string, - } - ) - - -class FanSchema: - """Voluptuous schema for KNX fans.""" - - CONF_STATE_ADDRESS = CONF_STATE_ADDRESS - CONF_OSCILLATION_ADDRESS = "oscillation_address" - CONF_OSCILLATION_STATE_ADDRESS = "oscillation_state_address" - CONF_MAX_STEP = "max_step" - - DEFAULT_NAME = "KNX Fan" - - SCHEMA = vol.Schema( - { - vol.Required(CONF_ADDRESS): cv.string, - vol.Optional(CONF_NAME, default=DEFAULT_NAME): cv.string, - vol.Optional(CONF_STATE_ADDRESS): cv.string, - vol.Optional(CONF_OSCILLATION_ADDRESS): cv.string, - vol.Optional(CONF_OSCILLATION_STATE_ADDRESS): cv.string, - vol.Optional(CONF_MAX_STEP): cv.byte, + vol.Required(CONF_KNX_TEMPERATURE_ADDRESS): ga_validator, + vol.Optional(CONF_KNX_BRIGHTNESS_SOUTH_ADDRESS): ga_validator, + vol.Optional(CONF_KNX_BRIGHTNESS_EAST_ADDRESS): ga_validator, + vol.Optional(CONF_KNX_BRIGHTNESS_WEST_ADDRESS): ga_validator, + vol.Optional(CONF_KNX_BRIGHTNESS_NORTH_ADDRESS): ga_validator, + vol.Optional(CONF_KNX_WIND_SPEED_ADDRESS): ga_validator, + vol.Optional(CONF_KNX_WIND_BEARING_ADDRESS): ga_validator, + vol.Optional(CONF_KNX_RAIN_ALARM_ADDRESS): ga_validator, + vol.Optional(CONF_KNX_FROST_ALARM_ADDRESS): ga_validator, + vol.Optional(CONF_KNX_WIND_ALARM_ADDRESS): ga_validator, + vol.Optional(CONF_KNX_DAY_NIGHT_ADDRESS): ga_validator, + vol.Optional(CONF_KNX_AIR_PRESSURE_ADDRESS): ga_validator, + vol.Optional(CONF_KNX_HUMIDITY_ADDRESS): ga_validator, } )