Files
homeassistant_config/config/custom_components/irrigation_unlimited/schema.py
2024-05-31 09:39:52 +02:00

449 lines
14 KiB
Python

"""This module holds the vaious schemas"""
from datetime import datetime, date
import voluptuous as vol
from homeassistant.helpers import config_validation as cv
from homeassistant.const import (
CONF_ENTITY_ID,
CONF_AFTER,
CONF_BEFORE,
CONF_NAME,
CONF_WEEKDAY,
CONF_REPEAT,
CONF_DELAY,
CONF_FOR,
CONF_UNTIL,
)
from .const import (
CONF_ALLOW_MANUAL,
CONF_CLOCK,
CONF_ENABLED,
CONF_FINISH,
CONF_FIXED,
CONF_FUTURE_SPAN,
CONF_HISTORY,
CONF_HISTORY_REFRESH,
CONF_HISTORY_SPAN,
CONF_MAX_LOG_ENTRIES,
CONF_MAXIMUM,
CONF_MINIMUM,
CONF_MODE,
CONF_MONTH,
CONF_DAY,
CONF_ODD,
CONF_EVEN,
CONF_RENAME_ENTITIES,
CONF_RESULTS,
CONF_SHOW_LOG,
CONF_AUTOPLAY,
CONF_ANCHOR,
CONF_SPAN,
CONF_SYNC_SWITCHES,
CONF_SEER,
CONF_CONTROLLERS,
CONF_SCHEDULES,
CONF_ZONES,
CONF_DURATION,
CONF_SUN,
CONF_TIME,
CONF_PREAMBLE,
CONF_POSTAMBLE,
CONF_GRANULARITY,
CONF_TESTING,
CONF_SPEED,
CONF_TIMES,
CONF_START,
CONF_END,
MONTHS,
CONF_SHOW,
CONF_CONFIG,
CONF_TIMELINE,
CONF_CONTROLLER_ID,
CONF_ZONE_ID,
CONF_SEQUENCES,
CONF_ALL_ZONES_CONFIG,
CONF_REFRESH_INTERVAL,
CONF_OUTPUT_EVENTS,
CONF_CRON,
CONF_EVERY_N_DAYS,
CONF_START_N_DAYS,
CONF_CHECK_BACK,
CONF_RETRIES,
CONF_RESYNC,
CONF_STATE_ON,
CONF_STATE_OFF,
CONF_PERCENTAGE,
CONF_ACTUAL,
CONF_INCREASE,
CONF_DECREASE,
CONF_RESET,
CONF_SEQUENCE_ID,
CONF_STATES,
CONF_SCHEDULE_ID,
CONF_FROM,
CONF_VOLUME,
CONF_VOLUME_PRECISION,
CONF_VOLUME_SCALE,
CONF_FLOW_RATE_PRECISION,
CONF_FLOW_RATE_SCALE,
CONF_QUEUE,
CONF_QUEUE_MANUAL,
CONF_USER,
CONF_TOGGLE,
CONF_EXTENDED_CONFIG,
)
IU_ID = r"^[a-z0-9]+(_[a-z0-9]+)*$"
def _list_is_not_empty(value):
if value is None or len(value) < 1:
raise vol.Invalid("Must have at least one entry")
return value
def _parse_dd_mmm(value: str) -> date | None:
"""Convert a date string in dd mmm format to a date object."""
if isinstance(value, date):
return value
return datetime.strptime(value, "%d %b").date()
USER_SCHEMA = vol.Schema(
{},
extra=vol.ALLOW_EXTRA,
)
SHOW_SCHEMA = vol.Schema(
{
vol.Optional(CONF_CONFIG, False): cv.boolean,
vol.Optional(CONF_TIMELINE, False): cv.boolean,
}
)
SUN_SCHEMA = vol.Schema(
{
vol.Required(CONF_SUN): cv.sun_event,
vol.Optional(CONF_BEFORE): cv.positive_time_period,
vol.Optional(CONF_AFTER): cv.positive_time_period,
}
)
CRON_SCHEMA = vol.Schema(
{
vol.Required(CONF_CRON): cv.string,
}
)
EVERY_N_DAYS_SCHEMA = vol.Schema(
{
vol.Required(CONF_EVERY_N_DAYS): cv.positive_int,
vol.Required(CONF_START_N_DAYS): cv.date,
}
)
time_event = vol.Any(cv.time, SUN_SCHEMA, CRON_SCHEMA)
anchor_event = vol.Any(CONF_START, CONF_FINISH)
month_event = vol.All(cv.ensure_list, [vol.In(MONTHS)])
day_number = vol.All(vol.Coerce(int), vol.Range(min=0, max=31))
day_event = vol.Any(
CONF_ODD, CONF_EVEN, cv.ensure_list(day_number), EVERY_N_DAYS_SCHEMA
)
SCHEDULE_SCHEMA = vol.Schema(
{
vol.Required(CONF_TIME): time_event,
vol.Required(CONF_ANCHOR, default=CONF_START): anchor_event,
vol.Required(CONF_DURATION): cv.positive_time_period,
vol.Optional(CONF_NAME): cv.string,
vol.Optional(CONF_SCHEDULE_ID): cv.matches_regex(IU_ID),
vol.Optional(CONF_WEEKDAY): cv.weekdays,
vol.Optional(CONF_MONTH): month_event,
vol.Optional(CONF_DAY): day_event,
vol.Optional(CONF_ENABLED): cv.boolean,
vol.Inclusive(CONF_FROM, "span"): _parse_dd_mmm,
vol.Inclusive(CONF_UNTIL, "span"): _parse_dd_mmm,
}
)
SEQUENCE_SCHEDULE_SCHEMA = vol.Schema(
{
vol.Required(CONF_TIME): time_event,
vol.Required(CONF_ANCHOR, default=CONF_START): anchor_event,
vol.Optional(CONF_DURATION): cv.positive_time_period,
vol.Optional(CONF_NAME): cv.string,
vol.Optional(CONF_SCHEDULE_ID): cv.matches_regex(IU_ID),
vol.Optional(CONF_WEEKDAY): cv.weekdays,
vol.Optional(CONF_MONTH): month_event,
vol.Optional(CONF_DAY): day_event,
vol.Optional(CONF_ENABLED): cv.boolean,
vol.Inclusive(CONF_FROM, "span"): _parse_dd_mmm,
vol.Inclusive(CONF_UNTIL, "span"): _parse_dd_mmm,
}
)
LOAD_SCHEDULE_SCHEMA = vol.Schema(
{
vol.Required(CONF_SCHEDULE_ID): cv.matches_regex(IU_ID),
vol.Optional(CONF_TIME): time_event,
vol.Optional(CONF_ANCHOR): anchor_event,
vol.Optional(CONF_DURATION): cv.positive_time_period_template,
vol.Optional(CONF_NAME): cv.string,
vol.Optional(CONF_WEEKDAY): cv.weekdays,
vol.Optional(CONF_MONTH): month_event,
vol.Optional(CONF_DAY): day_event,
vol.Optional(CONF_ENABLED): cv.boolean,
vol.Inclusive(CONF_FROM, "span"): _parse_dd_mmm,
vol.Inclusive(CONF_UNTIL, "span"): _parse_dd_mmm,
}
)
CHECK_BACK_SCHEMA = vol.All(
cv.deprecated(CONF_STATE_ON),
cv.deprecated(CONF_STATE_OFF),
vol.Schema(
{
vol.Optional(CONF_STATES): vol.Any("none", "all", "on", "off"),
vol.Optional(CONF_DELAY): cv.positive_int,
vol.Optional(CONF_RETRIES): cv.positive_int,
vol.Optional(CONF_RESYNC): cv.boolean,
vol.Optional(CONF_STATE_ON): cv.string, # Deprecated
vol.Optional(CONF_STATE_OFF): cv.string, # Deprecated
vol.Optional(CONF_ENTITY_ID): cv.entity_id,
vol.Optional(CONF_TOGGLE): cv.boolean,
}
),
)
VOLUME_SCHEMA = vol.Schema(
{
vol.Required(CONF_ENTITY_ID): cv.entity_id,
vol.Optional(CONF_VOLUME_PRECISION): cv.positive_int,
vol.Optional(CONF_VOLUME_SCALE): cv.positive_float,
vol.Optional(CONF_FLOW_RATE_PRECISION): cv.positive_int,
vol.Optional(CONF_FLOW_RATE_SCALE): cv.positive_float,
}
)
ZONE_SCHEMA = vol.Schema(
{
vol.Optional(CONF_SCHEDULES): vol.All(cv.ensure_list, [SCHEDULE_SCHEMA]),
vol.Optional(CONF_ZONE_ID): cv.matches_regex(IU_ID),
vol.Optional(CONF_NAME): cv.string,
vol.Optional(CONF_ENTITY_ID): cv.entity_ids,
vol.Optional(CONF_ENABLED): cv.boolean,
vol.Optional(CONF_ALLOW_MANUAL): cv.boolean,
vol.Optional(CONF_MINIMUM): cv.positive_time_period,
vol.Optional(CONF_MAXIMUM): cv.positive_time_period,
vol.Optional(CONF_FUTURE_SPAN): cv.positive_int,
vol.Optional(CONF_SHOW): vol.All(SHOW_SCHEMA),
vol.Optional(CONF_CHECK_BACK): vol.All(CHECK_BACK_SCHEMA),
vol.Optional(CONF_VOLUME): vol.All(VOLUME_SCHEMA),
vol.Optional(CONF_DURATION): cv.positive_time_period_template,
vol.Optional(CONF_USER): vol.All(USER_SCHEMA),
}
)
ALL_ZONES_SCHEMA = vol.Schema(
{
vol.Optional(CONF_SHOW): vol.All(SHOW_SCHEMA),
vol.Optional(CONF_MINIMUM): cv.positive_time_period,
vol.Optional(CONF_MAXIMUM): cv.positive_time_period,
vol.Optional(CONF_FUTURE_SPAN): cv.positive_int,
vol.Optional(CONF_ALLOW_MANUAL): cv.boolean,
vol.Optional(CONF_CHECK_BACK): vol.All(CHECK_BACK_SCHEMA),
vol.Optional(CONF_VOLUME): vol.All(VOLUME_SCHEMA),
vol.Optional(CONF_DURATION): cv.positive_time_period_template,
vol.Optional(CONF_USER): vol.All(USER_SCHEMA),
}
)
SEQUENCE_ZONE_SCHEMA = vol.Schema(
{
vol.Required(CONF_ZONE_ID): vol.All(cv.ensure_list, [cv.string]),
vol.Optional(CONF_DELAY): cv.time_period,
vol.Optional(CONF_DURATION): cv.positive_time_period,
vol.Optional(CONF_REPEAT): cv.positive_int,
vol.Optional(CONF_ENABLED): cv.boolean,
vol.Optional(CONF_VOLUME): cv.positive_float,
}
)
SEQUENCE_SCHEMA = vol.Schema(
{
vol.Required(CONF_ZONES, default={}): vol.All(
cv.ensure_list, [SEQUENCE_ZONE_SCHEMA], _list_is_not_empty
),
vol.Optional(CONF_SCHEDULES): vol.All(
cv.ensure_list, [SEQUENCE_SCHEDULE_SCHEMA]
),
vol.Optional(CONF_NAME): cv.string,
vol.Optional(CONF_DELAY): cv.time_period,
vol.Optional(CONF_DURATION): cv.positive_time_period,
vol.Optional(CONF_REPEAT): cv.positive_int,
vol.Optional(CONF_ENABLED): cv.boolean,
}
)
CONTROLLER_SCHEMA = vol.Schema(
{
vol.Required(CONF_ZONES): vol.All(
cv.ensure_list, [ZONE_SCHEMA], _list_is_not_empty
),
vol.Optional(CONF_SEQUENCES): vol.All(
cv.ensure_list, [SEQUENCE_SCHEMA], _list_is_not_empty
),
vol.Optional(CONF_NAME): cv.string,
vol.Optional(CONF_CONTROLLER_ID): cv.matches_regex(IU_ID),
vol.Optional(CONF_ENTITY_ID): cv.entity_ids,
vol.Optional(CONF_PREAMBLE): cv.time_period,
vol.Optional(CONF_POSTAMBLE): cv.time_period,
vol.Optional(CONF_ENABLED): cv.boolean,
vol.Optional(CONF_ALL_ZONES_CONFIG): vol.All(ALL_ZONES_SCHEMA),
vol.Optional(CONF_QUEUE_MANUAL): cv.boolean,
vol.Optional(CONF_CHECK_BACK): vol.All(CHECK_BACK_SCHEMA),
vol.Optional(CONF_VOLUME): vol.All(VOLUME_SCHEMA),
vol.Optional(CONF_USER): vol.All(USER_SCHEMA),
}
)
HISTORY_SCHEMA = vol.Schema(
{
vol.Optional(CONF_ENABLED): cv.boolean,
vol.Optional(CONF_REFRESH_INTERVAL): cv.positive_int,
vol.Optional(CONF_SPAN): cv.positive_int,
}
)
clock_mode = vol.Any(CONF_FIXED, CONF_SEER)
CLOCK_SCHEMA = vol.Schema(
{
vol.Optional(CONF_MODE, default=CONF_SEER): clock_mode,
vol.Optional(CONF_SHOW_LOG, default=False): cv.boolean,
vol.Optional(CONF_MAX_LOG_ENTRIES): cv.positive_int,
}
)
TEST_RESULT_SCHEMA = vol.Schema(
{
vol.Required("t"): cv.datetime,
vol.Required("c"): cv.positive_int,
vol.Required("z"): cv.positive_int,
vol.Required("s"): cv.boolean,
}
)
TEST_TIME_SCHEMA = vol.Schema(
{
vol.Required(CONF_START): cv.datetime,
vol.Required(CONF_END): cv.datetime,
vol.Optional(CONF_NAME): cv.string,
vol.Optional(CONF_RESULTS): [TEST_RESULT_SCHEMA],
}
)
TEST_SCHEMA = vol.Schema(
{
vol.Optional(CONF_ENABLED): cv.boolean,
vol.Optional(CONF_SPEED): cv.positive_float,
vol.Optional(CONF_TIMES): [TEST_TIME_SCHEMA],
vol.Optional(CONF_OUTPUT_EVENTS): cv.boolean,
vol.Optional(CONF_SHOW_LOG): cv.boolean,
vol.Optional(CONF_AUTOPLAY): cv.boolean,
}
)
IRRIGATION_SCHEMA = vol.Schema(
{
vol.Required(CONF_CONTROLLERS, default={}): vol.All(
cv.ensure_list, [CONTROLLER_SCHEMA], _list_is_not_empty
),
vol.Optional(CONF_GRANULARITY): cv.positive_int,
vol.Optional(CONF_REFRESH_INTERVAL): cv.positive_int,
vol.Optional(CONF_HISTORY_SPAN): cv.positive_int,
vol.Optional(CONF_HISTORY_REFRESH): cv.positive_int,
vol.Optional(CONF_SYNC_SWITCHES): cv.boolean,
vol.Optional(CONF_RENAME_ENTITIES): cv.boolean,
vol.Optional(CONF_TESTING): TEST_SCHEMA,
vol.Optional(CONF_HISTORY): HISTORY_SCHEMA,
vol.Optional(CONF_CLOCK): CLOCK_SCHEMA,
vol.Optional(CONF_EXTENDED_CONFIG): cv.boolean,
}
)
positive_float_template = vol.Any(cv.positive_float, cv.template)
ENTITY_SCHEMA = {vol.Required(CONF_ENTITY_ID): cv.entity_id}
ENABLE_DISABLE_SCHEMA = {
vol.Required(CONF_ENTITY_ID): cv.entity_ids,
vol.Optional(CONF_ZONES): cv.ensure_list,
vol.Optional(CONF_SEQUENCE_ID): cv.positive_int,
}
TIME_ADJUST_SCHEMA = vol.All(
vol.Schema(
{
vol.Required(CONF_ENTITY_ID): cv.entity_ids,
vol.Exclusive(
CONF_ACTUAL, "adjust_method"
): cv.positive_time_period_template,
vol.Exclusive(CONF_PERCENTAGE, "adjust_method"): positive_float_template,
vol.Exclusive(
CONF_INCREASE, "adjust_method"
): cv.positive_time_period_template,
vol.Exclusive(
CONF_DECREASE, "adjust_method"
): cv.positive_time_period_template,
vol.Exclusive(CONF_RESET, "adjust_method"): None,
vol.Optional(CONF_MINIMUM): cv.positive_time_period_template,
vol.Optional(CONF_MAXIMUM): cv.positive_time_period_template,
vol.Optional(CONF_ZONES): cv.ensure_list,
vol.Optional(CONF_SEQUENCE_ID): cv.positive_int,
}
),
cv.has_at_least_one_key(
CONF_ACTUAL, CONF_PERCENTAGE, CONF_INCREASE, CONF_DECREASE, CONF_RESET
),
)
MANUAL_RUN_SCHEMA = {
vol.Required(CONF_ENTITY_ID): cv.entity_ids,
vol.Optional(CONF_TIME): cv.positive_time_period_template,
vol.Optional(CONF_DELAY): cv.time_period,
vol.Optional(CONF_QUEUE): cv.boolean,
vol.Optional(CONF_ZONES): cv.ensure_list,
vol.Optional(CONF_SEQUENCE_ID): cv.positive_int,
}
SUSPEND_SCHEMA = vol.All(
vol.Schema(
{
vol.Required(CONF_ENTITY_ID): cv.entity_ids,
vol.Exclusive(CONF_FOR, "time_method"): cv.positive_time_period_template,
vol.Exclusive(CONF_UNTIL, "time_method"): cv.datetime,
vol.Exclusive(CONF_RESET, "time_method"): None,
vol.Optional(CONF_ZONES): cv.ensure_list,
vol.Optional(CONF_SEQUENCE_ID): cv.positive_int,
}
),
cv.has_at_least_one_key(CONF_FOR, CONF_UNTIL, CONF_RESET),
)
CANCEL_SCHEMA = {
vol.Required(CONF_ENTITY_ID): cv.entity_ids,
vol.Optional(CONF_ZONES): cv.ensure_list,
vol.Optional(CONF_SEQUENCE_ID): cv.positive_int,
}
PAUSE_RESUME_SCHEMA = {
vol.Required(CONF_ENTITY_ID): cv.entity_ids,
vol.Optional(CONF_SEQUENCE_ID): cv.positive_int,
}
RELOAD_SERVICE_SCHEMA = vol.Schema({})