mirror of
https://github.com/basnijholt/adaptive-lighting.git
synced 2026-09-11 22:34:04 +02:00
* added #274 * attempt getSwitchFromLightId() * Update switch.py * changed from register_entity_service to hass.services.async_register * Update switch.py * Update switch.py * Update switch.py * Update switch.py * Update switch.py * Update switch.py * Update services.yaml * Update switch.py * test * test builds ready * target selector may not be possible with current syntax priority is backwards-compatibility as I know most people will smash that update button * expanded light groups * test builds ready * add feature #104 * Update custom_components/adaptive_lighting/switch.py Co-authored-by: Chris <firstof9@gmail.com> * Might as well type both. No reason not to. Co-authored-by: Chris <firstof9@gmail.com> * Might as well type both. No reason not to. Co-authored-by: Chris <firstof9@gmail.com> * Reformatted debug messages. Reimported ServiceCall as suggested * Multiple switches allowed again in services. Apparently this was possible before. With this change, the `lights` argument must not be passed with multiple switches, or the integration has no way of knowing what the user wants to do. Integration did not make this check in prior versions. Also reformatted the debug messages. Removed `automerge.yaml` (my apologies) * Reload config without restart. You can now reload any changes to the yaml file without restarting your home assistant. Should show a 'reload' button in your integrations page or you can call the homeassistant reload integration service call. See https://community.home-assistant.io/t/how-to-allow-custom-compontent-for-yaml-configuration-reloading/391190/4 * Use snake_case for function name 'parseServiceArgs' * Slight rephrase * Small style changes * Rephrased debug messages. Removed `integration_entities` as we rewrote the code from that function already in parse_service_args. Reference function now above parse_service_args. * removed: `these_switches = data = None` * Factor out _find_switch_with_lights * Rename function and add log statement * Remove pylint marker * Handle multiple switches found * Small changes * Rename _parse_service_args to _get_switches_from_service_call * Rephrase log messages * Add type hint --------- Co-authored-by: Chris <firstof9@gmail.com> Co-authored-by: Bas Nijholt <bas@nijho.lt>
169 lines
6.5 KiB
Python
169 lines
6.5 KiB
Python
"""Constants for the Adaptive Lighting integration."""
|
|
|
|
from homeassistant.components.light import VALID_TRANSITION
|
|
from homeassistant.helpers import selector
|
|
import homeassistant.helpers.config_validation as cv
|
|
import voluptuous as vol
|
|
|
|
ICON_MAIN = "mdi:theme-light-dark"
|
|
ICON_BRIGHTNESS = "mdi:brightness-4"
|
|
ICON_COLOR_TEMP = "mdi:sun-thermometer"
|
|
ICON_SLEEP = "mdi:sleep"
|
|
|
|
DOMAIN = "adaptive_lighting"
|
|
SUN_EVENT_NOON = "solar_noon"
|
|
SUN_EVENT_MIDNIGHT = "solar_midnight"
|
|
|
|
CONF_NAME, DEFAULT_NAME = "name", "default"
|
|
CONF_LIGHTS, DEFAULT_LIGHTS = "lights", []
|
|
CONF_DETECT_NON_HA_CHANGES, DEFAULT_DETECT_NON_HA_CHANGES = (
|
|
"detect_non_ha_changes",
|
|
False,
|
|
)
|
|
CONF_INCLUDE_CONFIG_IN_ATTRIBUTES, DEFAULT_INCLUDE_CONFIG_IN_ATTRIBUTES = (
|
|
"include_config_in_attributes",
|
|
False,
|
|
)
|
|
CONF_INITIAL_TRANSITION, DEFAULT_INITIAL_TRANSITION = "initial_transition", 1
|
|
CONF_SLEEP_TRANSITION, DEFAULT_SLEEP_TRANSITION = "sleep_transition", 1
|
|
CONF_INTERVAL, DEFAULT_INTERVAL = "interval", 90
|
|
CONF_MAX_BRIGHTNESS, DEFAULT_MAX_BRIGHTNESS = "max_brightness", 100
|
|
CONF_MAX_COLOR_TEMP, DEFAULT_MAX_COLOR_TEMP = "max_color_temp", 5500
|
|
CONF_MIN_BRIGHTNESS, DEFAULT_MIN_BRIGHTNESS = "min_brightness", 1
|
|
CONF_MIN_COLOR_TEMP, DEFAULT_MIN_COLOR_TEMP = "min_color_temp", 2000
|
|
CONF_ONLY_ONCE, DEFAULT_ONLY_ONCE = "only_once", False
|
|
CONF_PREFER_RGB_COLOR, DEFAULT_PREFER_RGB_COLOR = "prefer_rgb_color", False
|
|
CONF_SEPARATE_TURN_ON_COMMANDS, DEFAULT_SEPARATE_TURN_ON_COMMANDS = (
|
|
"separate_turn_on_commands",
|
|
False,
|
|
)
|
|
CONF_SLEEP_BRIGHTNESS, DEFAULT_SLEEP_BRIGHTNESS = "sleep_brightness", 1
|
|
CONF_SLEEP_COLOR_TEMP, DEFAULT_SLEEP_COLOR_TEMP = "sleep_color_temp", 1000
|
|
CONF_SLEEP_RGB_COLOR, DEFAULT_SLEEP_RGB_COLOR = "sleep_rgb_color", [255, 56, 0]
|
|
CONF_SLEEP_RGB_OR_COLOR_TEMP, DEFAULT_SLEEP_RGB_OR_COLOR_TEMP = (
|
|
"sleep_rgb_or_color_temp",
|
|
"color_temp",
|
|
)
|
|
CONF_SUNRISE_OFFSET, DEFAULT_SUNRISE_OFFSET = "sunrise_offset", 0
|
|
CONF_SUNRISE_TIME = "sunrise_time"
|
|
CONF_MAX_SUNRISE_TIME = "max_sunrise_time"
|
|
CONF_SUNSET_OFFSET, DEFAULT_SUNSET_OFFSET = "sunset_offset", 0
|
|
CONF_SUNSET_TIME = "sunset_time"
|
|
CONF_MIN_SUNSET_TIME = "min_sunset_time"
|
|
CONF_TAKE_OVER_CONTROL, DEFAULT_TAKE_OVER_CONTROL = "take_over_control", True
|
|
CONF_TRANSITION, DEFAULT_TRANSITION = "transition", 45
|
|
|
|
SLEEP_MODE_SWITCH = "sleep_mode_switch"
|
|
ADAPT_COLOR_SWITCH = "adapt_color_switch"
|
|
ADAPT_BRIGHTNESS_SWITCH = "adapt_brightness_switch"
|
|
ATTR_TURN_ON_OFF_LISTENER = "turn_on_off_listener"
|
|
UNDO_UPDATE_LISTENER = "undo_update_listener"
|
|
NONE_STR = "None"
|
|
ATTR_ADAPT_COLOR = "adapt_color"
|
|
ATTR_ADAPT_BRIGHTNESS = "adapt_brightness"
|
|
|
|
SERVICE_SET_MANUAL_CONTROL = "set_manual_control"
|
|
CONF_MANUAL_CONTROL = "manual_control"
|
|
SERVICE_APPLY = "apply"
|
|
CONF_TURN_ON_LIGHTS = "turn_on_lights"
|
|
|
|
CONF_ADAPT_DELAY, DEFAULT_ADAPT_DELAY = "adapt_delay", 0
|
|
TURNING_OFF_DELAY = 5
|
|
CONF_SEND_SPLIT_DELAY, DEFAULT_SEND_SPLIT_DELAY = "send_split_delay", 0
|
|
|
|
|
|
def int_between(min_int, max_int):
|
|
"""Return an integer between 'min_int' and 'max_int'."""
|
|
return vol.All(vol.Coerce(int), vol.Range(min=min_int, max=max_int))
|
|
|
|
|
|
VALIDATION_TUPLES = [
|
|
(CONF_LIGHTS, DEFAULT_LIGHTS, cv.entity_ids),
|
|
(CONF_PREFER_RGB_COLOR, DEFAULT_PREFER_RGB_COLOR, bool),
|
|
(CONF_INCLUDE_CONFIG_IN_ATTRIBUTES, DEFAULT_INCLUDE_CONFIG_IN_ATTRIBUTES, bool),
|
|
(CONF_INITIAL_TRANSITION, DEFAULT_INITIAL_TRANSITION, VALID_TRANSITION),
|
|
(CONF_SLEEP_TRANSITION, DEFAULT_SLEEP_TRANSITION, VALID_TRANSITION),
|
|
(CONF_TRANSITION, DEFAULT_TRANSITION, VALID_TRANSITION),
|
|
(CONF_INTERVAL, DEFAULT_INTERVAL, cv.positive_int),
|
|
(CONF_MIN_BRIGHTNESS, DEFAULT_MIN_BRIGHTNESS, int_between(1, 100)),
|
|
(CONF_MAX_BRIGHTNESS, DEFAULT_MAX_BRIGHTNESS, int_between(1, 100)),
|
|
(CONF_MIN_COLOR_TEMP, DEFAULT_MIN_COLOR_TEMP, int_between(1000, 10000)),
|
|
(CONF_MAX_COLOR_TEMP, DEFAULT_MAX_COLOR_TEMP, int_between(1000, 10000)),
|
|
(CONF_SLEEP_BRIGHTNESS, DEFAULT_SLEEP_BRIGHTNESS, int_between(1, 100)),
|
|
(
|
|
CONF_SLEEP_RGB_OR_COLOR_TEMP,
|
|
DEFAULT_SLEEP_RGB_OR_COLOR_TEMP,
|
|
selector.SelectSelector(
|
|
selector.SelectSelectorConfig(
|
|
options=["color_temp", "rgb_color"],
|
|
multiple=False,
|
|
mode=selector.SelectSelectorMode.DROPDOWN,
|
|
),
|
|
),
|
|
),
|
|
(CONF_SLEEP_COLOR_TEMP, DEFAULT_SLEEP_COLOR_TEMP, int_between(1000, 10000)),
|
|
(
|
|
CONF_SLEEP_RGB_COLOR,
|
|
DEFAULT_SLEEP_RGB_COLOR,
|
|
selector.ColorRGBSelector(selector.ColorRGBSelectorConfig()),
|
|
),
|
|
(CONF_SUNRISE_TIME, NONE_STR, str),
|
|
(CONF_MAX_SUNRISE_TIME, NONE_STR, str),
|
|
(CONF_SUNRISE_OFFSET, DEFAULT_SUNRISE_OFFSET, int),
|
|
(CONF_SUNSET_TIME, NONE_STR, str),
|
|
(CONF_MIN_SUNSET_TIME, NONE_STR, str),
|
|
(CONF_SUNSET_OFFSET, DEFAULT_SUNSET_OFFSET, int),
|
|
(CONF_ONLY_ONCE, DEFAULT_ONLY_ONCE, bool),
|
|
(CONF_TAKE_OVER_CONTROL, DEFAULT_TAKE_OVER_CONTROL, bool),
|
|
(CONF_DETECT_NON_HA_CHANGES, DEFAULT_DETECT_NON_HA_CHANGES, bool),
|
|
(CONF_SEPARATE_TURN_ON_COMMANDS, DEFAULT_SEPARATE_TURN_ON_COMMANDS, bool),
|
|
(CONF_SEND_SPLIT_DELAY, DEFAULT_SEND_SPLIT_DELAY, int_between(0, 10000)),
|
|
(CONF_ADAPT_DELAY, DEFAULT_ADAPT_DELAY, cv.positive_float),
|
|
]
|
|
|
|
|
|
def timedelta_as_int(value):
|
|
"""Convert a `datetime.timedelta` object to an integer.
|
|
|
|
This integer can be serialized to json but a timedelta cannot.
|
|
"""
|
|
return value.total_seconds()
|
|
|
|
|
|
# conf_option: (validator, coerce) tuples
|
|
# these validators cannot be serialized but can be serialized when coerced by coerce.
|
|
EXTRA_VALIDATION = {
|
|
CONF_INTERVAL: (cv.time_period, timedelta_as_int),
|
|
CONF_SUNRISE_OFFSET: (cv.time_period, timedelta_as_int),
|
|
CONF_SUNRISE_TIME: (cv.time, str),
|
|
CONF_MAX_SUNRISE_TIME: (cv.time, str),
|
|
CONF_SUNSET_OFFSET: (cv.time_period, timedelta_as_int),
|
|
CONF_SUNSET_TIME: (cv.time, str),
|
|
CONF_MIN_SUNSET_TIME: (cv.time, str),
|
|
}
|
|
|
|
|
|
def maybe_coerce(key, validation):
|
|
"""Coerce the validation into a json serializable type."""
|
|
validation, coerce = EXTRA_VALIDATION.get(key, (validation, None))
|
|
if coerce is not None:
|
|
return vol.All(validation, vol.Coerce(coerce))
|
|
return validation
|
|
|
|
|
|
def replace_none_str(value, replace_with=None):
|
|
"""Replace "None" -> replace_with."""
|
|
return value if value != NONE_STR else replace_with
|
|
|
|
|
|
_yaml_validation_tuples = [
|
|
(key, default, maybe_coerce(key, validation))
|
|
for key, default, validation in VALIDATION_TUPLES
|
|
] + [(CONF_NAME, DEFAULT_NAME, cv.string)]
|
|
|
|
_DOMAIN_SCHEMA = vol.Schema(
|
|
{
|
|
vol.Optional(key, default=replace_none_str(default, vol.UNDEFINED)): validation
|
|
for key, default, validation in _yaml_validation_tuples
|
|
}
|
|
)
|