221 lines
6.3 KiB
Python
221 lines
6.3 KiB
Python
"""Store constants."""
|
|
import voluptuous as vol
|
|
import re
|
|
import homeassistant.util.dt as dt_util
|
|
from homeassistant.helpers import config_validation as cv
|
|
from homeassistant.const import (
|
|
WEEKDAYS,
|
|
ATTR_ENTITY_ID,
|
|
SUN_EVENT_SUNRISE,
|
|
SUN_EVENT_SUNSET,
|
|
ATTR_SERVICE,
|
|
ATTR_SERVICE_DATA,
|
|
CONF_CONDITIONS,
|
|
CONF_ATTRIBUTE,
|
|
ATTR_NAME,
|
|
)
|
|
|
|
VERSION = "3.3.8"
|
|
|
|
DOMAIN = "scheduler"
|
|
|
|
SUN_ENTITY = "sun.sun"
|
|
|
|
DAY_TYPE_DAILY = "daily"
|
|
DAY_TYPE_WORKDAY = "workday"
|
|
DAY_TYPE_WEEKEND = "weekend"
|
|
|
|
WORKDAY_ENTITY = "binary_sensor.workday_sensor"
|
|
|
|
ATTR_SKIP_CONDITIONS = "skip_conditions"
|
|
ATTR_CONDITION_TYPE = "condition_type"
|
|
CONDITION_TYPE_AND = "and"
|
|
CONDITION_TYPE_OR = "or"
|
|
|
|
ATTR_MATCH_TYPE = "match_type"
|
|
MATCH_TYPE_EQUAL = "is"
|
|
MATCH_TYPE_UNEQUAL = "not"
|
|
MATCH_TYPE_BELOW = "below"
|
|
MATCH_TYPE_ABOVE = "above"
|
|
|
|
ATTR_TRACK_CONDITIONS = "track_conditions"
|
|
|
|
ATTR_REPEAT_TYPE = "repeat_type"
|
|
REPEAT_TYPE_REPEAT = "repeat"
|
|
REPEAT_TYPE_SINGLE = "single"
|
|
REPEAT_TYPE_PAUSE = "pause"
|
|
|
|
EVENT = "scheduler_updated"
|
|
|
|
SERVICE_REMOVE = "remove"
|
|
SERVICE_EDIT = "edit"
|
|
SERVICE_ADD = "add"
|
|
SERVICE_COPY = "copy"
|
|
SERVICE_DISABLE_ALL = "disable_all"
|
|
SERVICE_ENABLE_ALL = "enable_all"
|
|
|
|
OffsetTimePattern = re.compile(r"^([a-z]+)([-|\+]{1})([0-9:]+)$")
|
|
DatePattern = re.compile(r"^[0-9]+\-[0-9]+\-[0-9]+$")
|
|
|
|
ATTR_START = "start"
|
|
ATTR_STOP = "stop"
|
|
ATTR_TIMESLOTS = "timeslots"
|
|
ATTR_WEEKDAYS = "weekdays"
|
|
ATTR_ENABLED = "enabled"
|
|
ATTR_SCHEDULE_ID = "schedule_id"
|
|
ATTR_ACTIONS = "actions"
|
|
ATTR_VALUE = "value"
|
|
ATTR_TAGS = "tags"
|
|
ATTR_SCHEDULES = "schedules"
|
|
ATTR_START_DATE = "start_date"
|
|
ATTR_END_DATE = "end_date"
|
|
|
|
EVENT_TIMER_FINISHED = "scheduler_timer_finished"
|
|
EVENT_TIMER_UPDATED = "scheduler_timer_updated"
|
|
EVENT_ITEM_UPDATED = "scheduler_item_updated"
|
|
EVENT_ITEM_CREATED = "scheduler_item_created"
|
|
EVENT_ITEM_REMOVED = "scheduler_item_removed"
|
|
EVENT_STARTED = "scheduler_started"
|
|
EVENT_WORKDAY_SENSOR_UPDATED = "workday_sensor_updated"
|
|
|
|
STATE_INIT = "init"
|
|
STATE_READY = "ready"
|
|
STATE_COMPLETED = "completed"
|
|
|
|
|
|
def validate_time(time):
|
|
res = OffsetTimePattern.match(time)
|
|
if not res:
|
|
if dt_util.parse_time(time):
|
|
return time
|
|
else:
|
|
raise vol.Invalid("Invalid time entered: {}".format(time))
|
|
else:
|
|
if res.group(1) not in [SUN_EVENT_SUNRISE, SUN_EVENT_SUNSET]:
|
|
raise vol.Invalid("Invalid time entered: {}".format(time))
|
|
elif res.group(2) not in ["+", "-"]:
|
|
raise vol.Invalid("Invalid time entered: {}".format(time))
|
|
elif not dt_util.parse_time(res.group(3)):
|
|
raise vol.Invalid("Invalid time entered: {}".format(time))
|
|
else:
|
|
return time
|
|
|
|
|
|
def validate_date(value: str) -> str:
|
|
"""Input must be either none or a valid date."""
|
|
if value is None:
|
|
return None
|
|
date = dt_util.parse_date(value)
|
|
if date is None:
|
|
raise vol.Invalid("Invalid date entered: {}".format(value))
|
|
else:
|
|
return date.strftime("%Y-%m-%d")
|
|
|
|
|
|
CONDITION_SCHEMA = vol.Schema(
|
|
{
|
|
vol.Required(ATTR_ENTITY_ID): cv.entity_id,
|
|
vol.Required(ATTR_VALUE): vol.Any(int, float, str),
|
|
vol.Optional(CONF_ATTRIBUTE): cv.string,
|
|
vol.Required(ATTR_MATCH_TYPE): vol.In(
|
|
[MATCH_TYPE_EQUAL, MATCH_TYPE_UNEQUAL, MATCH_TYPE_BELOW, MATCH_TYPE_ABOVE]
|
|
),
|
|
}
|
|
)
|
|
|
|
ACTION_SCHEMA = vol.Schema(
|
|
{
|
|
vol.Optional(ATTR_ENTITY_ID): cv.entity_id,
|
|
vol.Required(ATTR_SERVICE): cv.entity_id,
|
|
vol.Optional(ATTR_SERVICE_DATA): dict,
|
|
}
|
|
)
|
|
|
|
TIMESLOT_SCHEMA = vol.Schema(
|
|
{
|
|
vol.Required(ATTR_START): validate_time,
|
|
vol.Optional(ATTR_STOP): validate_time,
|
|
vol.Optional(CONF_CONDITIONS): vol.All(
|
|
cv.ensure_list, vol.Length(min=1), [CONDITION_SCHEMA]
|
|
),
|
|
vol.Optional(ATTR_CONDITION_TYPE): vol.In(
|
|
[
|
|
CONDITION_TYPE_AND,
|
|
CONDITION_TYPE_OR,
|
|
]
|
|
),
|
|
vol.Optional(ATTR_TRACK_CONDITIONS): cv.boolean,
|
|
vol.Required(ATTR_ACTIONS): vol.All(
|
|
cv.ensure_list, vol.Length(min=1), [ACTION_SCHEMA]
|
|
),
|
|
}
|
|
)
|
|
|
|
ADD_SCHEDULE_SCHEMA = vol.Schema(
|
|
{
|
|
vol.Optional(ATTR_WEEKDAYS, default=[DAY_TYPE_DAILY]): vol.All(
|
|
cv.ensure_list,
|
|
vol.Unique(),
|
|
vol.Length(min=1),
|
|
[
|
|
vol.In(
|
|
WEEKDAYS
|
|
+ [
|
|
DAY_TYPE_WORKDAY,
|
|
DAY_TYPE_WEEKEND,
|
|
DAY_TYPE_DAILY,
|
|
]
|
|
)
|
|
],
|
|
),
|
|
vol.Optional(ATTR_START_DATE, default=None): validate_date,
|
|
vol.Optional(ATTR_END_DATE, default=None): validate_date,
|
|
vol.Required(ATTR_TIMESLOTS): vol.All(
|
|
cv.ensure_list, vol.Length(min=1), [TIMESLOT_SCHEMA]
|
|
),
|
|
vol.Required(ATTR_REPEAT_TYPE): vol.In(
|
|
[
|
|
REPEAT_TYPE_REPEAT,
|
|
REPEAT_TYPE_SINGLE,
|
|
REPEAT_TYPE_PAUSE,
|
|
]
|
|
),
|
|
vol.Optional(ATTR_NAME): vol.Any(cv.string, None),
|
|
vol.Optional(ATTR_TAGS): vol.All(cv.ensure_list, vol.Unique(), [cv.string]),
|
|
}
|
|
)
|
|
|
|
EDIT_SCHEDULE_SCHEMA = vol.Schema(
|
|
{
|
|
vol.Optional(ATTR_WEEKDAYS): vol.All(
|
|
cv.ensure_list,
|
|
vol.Unique(),
|
|
vol.Length(min=1),
|
|
[
|
|
vol.In(
|
|
WEEKDAYS
|
|
+ [
|
|
DAY_TYPE_WORKDAY,
|
|
DAY_TYPE_WEEKEND,
|
|
DAY_TYPE_DAILY,
|
|
]
|
|
)
|
|
],
|
|
),
|
|
vol.Optional(ATTR_START_DATE, default=None): validate_date,
|
|
vol.Optional(ATTR_END_DATE, default=None): validate_date,
|
|
vol.Optional(ATTR_TIMESLOTS): vol.All(
|
|
cv.ensure_list, vol.Length(min=1), [TIMESLOT_SCHEMA]
|
|
),
|
|
vol.Optional(ATTR_REPEAT_TYPE): vol.In(
|
|
[
|
|
REPEAT_TYPE_REPEAT,
|
|
REPEAT_TYPE_SINGLE,
|
|
REPEAT_TYPE_PAUSE,
|
|
]
|
|
),
|
|
vol.Optional(ATTR_NAME): vol.Any(cv.string, None),
|
|
vol.Optional(ATTR_TAGS): vol.All(cv.ensure_list, vol.Unique(), [cv.string]),
|
|
}
|
|
)
|