-
-
Notifications
You must be signed in to change notification settings - Fork 37.4k
Add adaptive_lighting component #40626
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Closed
Closed
Changes from all commits
Commits
Show all changes
165 commits
Select commit
Hold shift + click to select a range
2d805c7
Add adaptive_lighting component
basnijholt 1fe3c81
add a basic implemention to prevent lights from turning on when actua…
basnijholt ae9ea31
add 'disable_color_adjust' option after request on Reddit
basnijholt 37c33fd
cancel adjusting lights for at least the turn_off transition time
basnijholt f54db5a
fix pylint issues
basnijholt 6805c04
improve logging
basnijholt 9b5a6d1
light might take longer than specified turn_off 'transition', so wait…
basnijholt d8ef264
always ignore any event during a turn_off transition
basnijholt ba21692
ignore all files for coverage
basnijholt e0b37d0
reduce indentation level in _maybe_cancel
basnijholt b13aee9
listen to light.turn_on events
basnijholt 30d3066
lock lights while waiting to turn off
basnijholt 513b24d
partially address review comments
basnijholt 8dd7862
add TurnOnOffListener that is used among switches and wait until EVEN…
basnijholt 010580a
simplify maybe_cancel_adjusting to not overflow a light with calls
basnijholt e1cca6c
catch all turn_off events
basnijholt 5a7bf70
update with latest yaml settings
basnijholt 90867f2
always use color_temp over rgb
basnijholt 9fa6c70
fix tz issue when manually setting sunset/sunrise
basnijholt 0836819
add prefer_rgb_color
basnijholt 77eef65
cancel sleep task when turn_on is called
basnijholt 5c62069
fix issue where lights weren't updated when toggling the switch
basnijholt 378a774
do not return but call self._abort_if_unique_id_configured
basnijholt d8453ac
rename variables (sorry pylint)
basnijholt 766a1b4
styling
basnijholt c02faf9
sub/unsub trackers when loading/unloading and turning on/off
basnijholt ad61f35
fix turning on and off, delay setup listeners until HA start
basnijholt e02fb0e
define and use switch._unsub_trackers
basnijholt 4cdf404
do not use old settings when reloading config
basnijholt 5feb96e
simplify call to hass.config_entries.async_forward_entry_unload
basnijholt 1403b66
remove assert because it's possible that trackers haven't been set up…
basnijholt 80236f9
actually use the lock
basnijholt ea615e0
fix documentation url
basnijholt 9a7e102
udpate manifest.json
basnijholt 227d3c1
rename to adjust_brightness, adjust_color_temp, adjust_rgb_color
basnijholt 43d6b07
rename to adapt_brightness, adapt_color_temp, and adapt_rgb_color
basnijholt 704ad0a
rename on_lights_only -> turn_on_lights
basnijholt 02697f5
use adapt_brightness, adapt_color_temp, adapt_rgb_color in adaptive_l…
basnijholt 1203746
use _expand_light_groups in apply service
basnijholt d655dfe
remove turn on off listener
basnijholt 07e0ed7
rename trackers -> listeners
basnijholt afc5c64
setup_listeners only when turning on
basnijholt 20dcced
improve strings.json
basnijholt 357661b
do not set state before calling async_turn_on
basnijholt 415c3bb
add strings for adapt_color_temp and adapt_rgb_color
basnijholt 86f4ad1
add comments
basnijholt 66d6ce4
add strings for disable_entity/state, sleep_entity/state
basnijholt 21ff5b1
shorten initial_transition string
basnijholt 3a4a051
turn on switch upon adding to Home Assistant
basnijholt 3d0a208
reword sleep_entity's string
basnijholt 5735434
pass context, add type annotation, and fix several small bugs
basnijholt 2f5fb45
mark _update_attrs as callback
basnijholt 1e717cc
raise an exception instead of assert
basnijholt 82452e7
reorder and rename methods and keep Event objects in TurnOnOffListener
basnijholt 72335be
start implementing 'take_over_control' feature
basnijholt 6f66846
break out in _update_attrs_and_maybe_adapt_lights
basnijholt d61cc14
make supported_features into a function
basnijholt 0ed8320
extract light settings into SunLightSettings dataclass
basnijholt b0bed5c
add a sleep_mode switch and remove config options
basnijholt fa82753
add note in strings.json
basnijholt 52aad67
deprecate disable_entity and disable_state
basnijholt 30b6c0c
style
basnijholt 1b6432a
add 'unique_id'
basnijholt 3ca719b
uncomment unique_id because of exception:
basnijholt 759f585
implement "take_over_control" feature
basnijholt b294a8e
add async_will_remove_from_hass
basnijholt bf4e9e1
remove entity_id and use unique_id
basnijholt ebe60e4
set default manually_controlled[light]=False
basnijholt 79d9a40
use cv.ensure_list
basnijholt 3a933cd
use __getitem__
basnijholt 428395c
simplify conditional
basnijholt f5222e8
detect significant changes for lights that are changed outside of HA
basnijholt 1be93f1
add "detect_non_ha_changes" option
basnijholt d63872e
change order of options
basnijholt 0f87320
fix pylint issue
basnijholt 1599a28
avoid ZeroDivisionError
basnijholt df05877
update strings.json
basnijholt 1599a34
call self.turn_on_off_listener.reset directly
basnijholt 6e0b288
pass context to homeassistant.update_entity
basnijholt f6cd487
fix case where turn_off_event is None
basnijholt fadd945
print values in significant_change debug log
basnijholt 854a6d1
only show lights that can be controlled usefully
basnijholt 042c964
fix: if turn_off_event is None it has no data attr
basnijholt a7d51a6
register service after async_add_entities
basnijholt be8b17e
change order in OptionsFlow
basnijholt 6249bd5
add 'manually_controlled' attribute to the switch
basnijholt 249f811
implement suggestions by iMicknl and KTibow and add more type-annotat…
basnijholt 21491ed
use 'state_changed' events to check if states changed
basnijholt 6b77d61
reduce COLOR_TEMP_CHANGE to 20 (range is in mired not Kelvin)
basnijholt b27f80d
remove unused function abs_rel_diff
basnijholt 43d681f
listen to EVENT_HOMEASSISTANT_STARTED instead of EVENT_HOMEASSISTANT_…
basnijholt 3815859
pass unique identifiable contexts to solve bug
basnijholt d50abc4
make the contexts more identifiable
basnijholt 0e22b63
only log context.id
basnijholt 4e1c584
log the context.id
basnijholt ce4af77
improve readability
basnijholt 1b981e1
keep context_id shorter than 36 chars
basnijholt d53442a
add an extra check
basnijholt 5cf5d41
Simplify handling state changes with the same context ID
basnijholt 5dc3286
Return early in the function
basnijholt 4f0c96d
fix: pass Context instead of only the ID
basnijholt 5bcba1f
fix: pass Context instead of only the ID
basnijholt be0cfe0
only log context.id
basnijholt a1da04f
log all state change events even the ones that aren't saved
basnijholt 3999d40
compare to latest target state
basnijholt 54097a3
simplify if-elif
basnijholt 8c909d4
change order of options
basnijholt 5b70f7d
Use a different color metric to measure the distance between the colors
basnijholt 4de800c
fix strings.json
basnijholt 57bc163
do not directly mark a light as manually controlled
basnijholt 4f19cd6
fire 'adaptive_lighting_manually_controlled' event
basnijholt cb1754c
add service 'adaptive_lighting.not_manually_controlled'
basnijholt e7fb5b0
change 'not_manually_controlled' to 'set_manually_controlled' service
basnijholt 6cfe818
rename event_type to 'adaptive_lighting.manual_control'
basnijholt 312c641
rename 'manually_controlled' to 'manual_control' everywhere (because …
basnijholt 29cd165
fix bug where last_state_change wasn't updated if prev state was not …
basnijholt 59eb820
fix hassfest error
basnijholt 851b117
add tests/components/adaptive_lighting/test_config_flow.py
basnijholt caa568f
simplify tests/components/adaptive_lighting/test_config_flow.py
basnijholt 71a56fb
add tests/components/adaptive_lighting/test_init.py
basnijholt e9b972c
add tests/components/adaptive_lighting/test_switch.py
basnijholt c6b6393
pop after unload
basnijholt d7b04c7
test for different timezones and fix the problem with sunevents order
basnijholt 287db89
remove adaptive_lighting from .coveragerc
basnijholt f4948b1
simplify tests
basnijholt 6d8347b
test around sunrise too
basnijholt 039b020
use helper function setup_switch
basnijholt 872bd1c
add tests/components/adaptive_lighting/__init__.py
basnijholt a35dce9
Remove initial doc-string
basnijholt 045ef33
test light settings and manual control
basnijholt 31122a7
test that toggling switches resets manual control
basnijholt 0c0eff3
use legacy_patchable_time to fix failing tests
basnijholt 33524be
fix pylint issues
basnijholt e35e0b6
restore dt_util.DEFAULT_TIME_ZONE
basnijholt 9fe4d26
use a fixture to restore the timezone
basnijholt 778d24f
increase coverage to >90%
basnijholt da30a8b
add more tests
basnijholt f053860
increase config_flow.py test coverage to 100%
basnijholt 3ebf0e4
increase overal test coverage to >97%
basnijholt fa54aeb
use FakeLight implementation based on demo.light
basnijholt 7290e19
add SLEEP_MODE_SWITCH constant and clean up tests
basnijholt 1399760
add 'sun_position' attribute
basnijholt 2203995
use DemoLight for as long as it works
basnijholt 4732f4e
generalize AdaptiveSleepModeSwitch to SimpleSwitch
basnijholt 1b9451b
define a adapt_brightness and adapt_color switch
basnijholt bb18134
watch for color or brightness related data in light.turn_on
basnijholt e74eac2
no need to track the state of adapt_brightness and color switches
basnijholt ab796e7
add German translations and update strings
basnijholt d728ec0
fix initial state of SimpleSwitch
basnijholt ee6ba25
make sure that 'last_state is not None'
basnijholt 19b7651
add test-case to prevent the bug solved in prev commit
basnijholt d8d3c28
fix and test adaptive_lighting.apply
basnijholt 2a362ea
add Swedish translation
basnijholt 92bd891
support white_value and sync back https://github.com/basnijholt/adapt…
basnijholt f984c5e
use ATTR_SUPPORTED_FEATURES
basnijholt eebe687
if lights is not specified in set_manual_control, select all lights
basnijholt 14036c0
add separate_turn_on_commands option for MQTT lights
basnijholt 011cc3e
improve separate_turn_on_commands option
basnijholt eff9bcc
only adapt lights if switch is on and set_manual_control is called
basnijholt d0ed089
add switch entity_id to adaptive_lighting.manual_control event
basnijholt f1bee58
log fire adaptive_lighting.manual_control event
basnijholt 3874641
wait between turn_on commands for transition/2 if separate_turn_on_co…
basnijholt 42d5d53
deal with 'light.turn_on' with multiple lights, which appear as csv list
basnijholt afe8ce6
fix bug when resetting switch and it's off
basnijholt 5bf889a
separate_turn_on_commands fix when _split_service_data returns 1 item
basnijholt File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,90 @@ | ||
| """Adaptive Lighting integration in Home-Assistant.""" | ||
| import logging | ||
| from typing import Any, Dict | ||
|
|
||
| import voluptuous as vol | ||
|
|
||
| from homeassistant.config_entries import SOURCE_IMPORT, ConfigEntry | ||
| from homeassistant.const import CONF_SOURCE | ||
| from homeassistant.core import HomeAssistant | ||
| import homeassistant.helpers.config_validation as cv | ||
|
|
||
| from .const import ( | ||
| _DOMAIN_SCHEMA, | ||
| ATTR_TURN_ON_OFF_LISTENER, | ||
| CONF_NAME, | ||
| DOMAIN, | ||
| UNDO_UPDATE_LISTENER, | ||
| ) | ||
|
|
||
| _LOGGER = logging.getLogger(__name__) | ||
|
|
||
| PLATFORMS = ["switch"] | ||
|
|
||
|
|
||
| def _all_unique_names(value): | ||
| """Validate that all entities have a unique profile name.""" | ||
| hosts = [device[CONF_NAME] for device in value] | ||
| schema = vol.Schema(vol.Unique()) | ||
| schema(hosts) | ||
| return value | ||
|
|
||
|
|
||
| CONFIG_SCHEMA = vol.Schema( | ||
| {DOMAIN: vol.All(cv.ensure_list, [_DOMAIN_SCHEMA], _all_unique_names)}, | ||
| extra=vol.ALLOW_EXTRA, | ||
| ) | ||
|
|
||
|
|
||
| async def async_setup(hass: HomeAssistant, config: Dict[str, Any]): | ||
| """Import integration from config.""" | ||
|
|
||
| if DOMAIN in config: | ||
| for entry in config[DOMAIN]: | ||
| hass.async_create_task( | ||
| hass.config_entries.flow.async_init( | ||
| DOMAIN, context={CONF_SOURCE: SOURCE_IMPORT}, data=entry | ||
| ) | ||
| ) | ||
| return True | ||
|
|
||
|
|
||
| async def async_setup_entry(hass: HomeAssistant, config_entry: ConfigEntry): | ||
| """Set up the component.""" | ||
| data = hass.data.setdefault(DOMAIN, {}) | ||
|
|
||
| undo_listener = config_entry.add_update_listener(async_update_options) | ||
| data[config_entry.entry_id] = {UNDO_UPDATE_LISTENER: undo_listener} | ||
| for platform in PLATFORMS: | ||
| hass.async_create_task( | ||
| hass.config_entries.async_forward_entry_setup(config_entry, platform) | ||
| ) | ||
|
|
||
| return True | ||
|
|
||
|
|
||
| async def async_update_options(hass, config_entry: ConfigEntry): | ||
| """Update options.""" | ||
| await hass.config_entries.async_reload(config_entry.entry_id) | ||
|
|
||
|
|
||
| async def async_unload_entry(hass, config_entry: ConfigEntry) -> bool: | ||
| """Unload a config entry.""" | ||
| unload_ok = await hass.config_entries.async_forward_entry_unload( | ||
| config_entry, "switch" | ||
| ) | ||
| data = hass.data[DOMAIN] | ||
| data[config_entry.entry_id][UNDO_UPDATE_LISTENER]() | ||
| if unload_ok: | ||
| data.pop(config_entry.entry_id) | ||
|
|
||
| if len(data) == 1 and ATTR_TURN_ON_OFF_LISTENER in data: | ||
| # no more config_entries | ||
| turn_on_off_listener = data.pop(ATTR_TURN_ON_OFF_LISTENER) | ||
| turn_on_off_listener.remove_listener() | ||
| turn_on_off_listener.remove_listener2() | ||
|
|
||
| if not data: | ||
| hass.data.pop(DOMAIN) | ||
|
|
||
| return unload_ok | ||
109 changes: 109 additions & 0 deletions
109
homeassistant/components/adaptive_lighting/config_flow.py
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,109 @@ | ||
| """Config flow for Adaptive Lighting integration.""" | ||
| import logging | ||
|
|
||
| import voluptuous as vol | ||
|
|
||
| from homeassistant import config_entries | ||
| from homeassistant.const import CONF_NAME | ||
| from homeassistant.core import callback | ||
| import homeassistant.helpers.config_validation as cv | ||
|
|
||
| from .const import ( # pylint: disable=unused-import | ||
| CONF_LIGHTS, | ||
| DOMAIN, | ||
| EXTRA_VALIDATION, | ||
| NONE_STR, | ||
| VALIDATION_TUPLES, | ||
| ) | ||
| from .switch import _supported_features | ||
|
|
||
| _LOGGER = logging.getLogger(__name__) | ||
|
|
||
|
|
||
| class ConfigFlow(config_entries.ConfigFlow, domain=DOMAIN): | ||
| """Handle a config flow for Adaptive Lighting.""" | ||
|
|
||
| VERSION = 1 | ||
|
|
||
| async def async_step_user(self, user_input=None): | ||
| """Handle the initial step.""" | ||
| errors = {} | ||
|
|
||
| if user_input is not None: | ||
| await self.async_set_unique_id(user_input[CONF_NAME]) | ||
| self._abort_if_unique_id_configured() | ||
| return self.async_create_entry(title=user_input[CONF_NAME], data=user_input) | ||
|
|
||
| return self.async_show_form( | ||
| step_id="user", | ||
| data_schema=vol.Schema({vol.Required(CONF_NAME): str}), | ||
| errors=errors, | ||
| ) | ||
|
|
||
| async def async_step_import(self, user_input=None): | ||
| """Handle configuration by yaml file.""" | ||
| await self.async_set_unique_id(user_input[CONF_NAME]) | ||
| for entry in self._async_current_entries(): | ||
| if entry.unique_id == self.unique_id: | ||
| self.hass.config_entries.async_update_entry(entry, data=user_input) | ||
| self._abort_if_unique_id_configured() | ||
| return self.async_create_entry(title=user_input[CONF_NAME], data=user_input) | ||
|
|
||
| @staticmethod | ||
| @callback | ||
| def async_get_options_flow(config_entry): | ||
| """Get the options flow for this handler.""" | ||
| return OptionsFlowHandler(config_entry) | ||
|
|
||
|
|
||
| def validate_options(user_input, errors): | ||
| """Validate the options in the OptionsFlow. | ||
|
|
||
| This is an extra validation step because the validators | ||
| in `EXTRA_VALIDATION` cannot be serialized to json. | ||
| """ | ||
| for key, (validate, _) in EXTRA_VALIDATION.items(): | ||
| # these are unserializable validators | ||
| value = user_input.get(key) | ||
| try: | ||
| if value is not None and value != NONE_STR: | ||
| validate(value) | ||
| except vol.Invalid: | ||
| _LOGGER.exception("Configuration option %s=%s is incorrect", key, value) | ||
| errors["base"] = "option_error" | ||
|
|
||
|
|
||
| class OptionsFlowHandler(config_entries.OptionsFlow): | ||
| """Handle a option flow for Adaptive Lighting.""" | ||
|
|
||
| def __init__(self, config_entry: config_entries.ConfigEntry): | ||
| """Initialize options flow.""" | ||
| self.config_entry = config_entry | ||
|
|
||
| async def async_step_init(self, user_input=None): | ||
| """Handle options flow.""" | ||
| conf = self.config_entry | ||
| if conf.source == config_entries.SOURCE_IMPORT: | ||
| return self.async_show_form(step_id="init", data_schema=None) | ||
| errors = {} | ||
| if user_input is not None: | ||
| validate_options(user_input, errors) | ||
| if not errors: | ||
| return self.async_create_entry(title="", data=user_input) | ||
|
|
||
| all_lights = [ | ||
| light | ||
| for light in self.hass.states.async_entity_ids("light") | ||
| if _supported_features(self.hass, light) | ||
| ] | ||
| to_replace = {CONF_LIGHTS: cv.multi_select(sorted(all_lights))} | ||
|
|
||
| options_schema = {} | ||
| for name, default, validation in VALIDATION_TUPLES: | ||
| key = vol.Optional(name, default=conf.options.get(name, default)) | ||
| value = to_replace.get(name, validation) | ||
| options_schema[key] = value | ||
|
|
||
| return self.async_show_form( | ||
| step_id="init", data_schema=vol.Schema(options_schema), errors=errors | ||
| ) |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,127 @@ | ||
| """Constants for the Adaptive Lighting integration.""" | ||
| import voluptuous as vol | ||
|
|
||
| from homeassistant.components.light import VALID_TRANSITION | ||
| import homeassistant.helpers.config_validation as cv | ||
|
|
||
| ICON = "mdi:theme-light-dark" | ||
|
|
||
| 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_INITIAL_TRANSITION, DEFAULT_INITIAL_TRANSITION = "initial_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_SUNRISE_OFFSET, DEFAULT_SUNRISE_OFFSET = "sunrise_offset", 0 | ||
| CONF_SUNRISE_TIME = "sunrise_time" | ||
| CONF_SUNSET_OFFSET, DEFAULT_SUNSET_OFFSET = "sunset_offset", 0 | ||
| CONF_SUNSET_TIME = "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" | ||
|
|
||
| TURNING_OFF_DELAY = 5 | ||
|
|
||
|
|
||
| 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_INITIAL_TRANSITION, DEFAULT_INITIAL_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_COLOR_TEMP, DEFAULT_SLEEP_COLOR_TEMP, int_between(1000, 10000)), | ||
| (CONF_SUNRISE_TIME, NONE_STR, str), | ||
| (CONF_SUNRISE_OFFSET, DEFAULT_SUNRISE_OFFSET, int), | ||
| (CONF_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), | ||
| ] | ||
|
|
||
|
|
||
| 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_SUNSET_OFFSET: (cv.time_period, timedelta_as_int), | ||
| CONF_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 | ||
| } | ||
| ) |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,9 @@ | ||
| { | ||
| "domain": "adaptive_lighting", | ||
| "name": "Adaptive Lighting", | ||
| "documentation": "https://www.home-assistant.io/integrations/adaptive_lighting", | ||
| "config_flow": true, | ||
| "dependencies": [], | ||
| "codeowners": ["@basnijholt"], | ||
| "requirements": [] | ||
| } |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,36 @@ | ||
| apply: | ||
| description: Applies the current Adaptive Lighting settings to lights. | ||
| fields: | ||
| entity_id: | ||
| description: entity_id of the Adaptive Lighting switch. | ||
| example: switch.adaptive_lighting_default | ||
| lights: | ||
| description: entity_id(s) of lights. | ||
| example: light.bedroom_ceiling | ||
| transition: | ||
| description: Transition of the lights. | ||
| example: 10 | ||
| adapt_brightness: | ||
| description: "Adapt the 'brightness', default: true" | ||
| example: true | ||
| adapt_color: | ||
| description: "Adapt the color_temp/color_rgb, default: true" | ||
| example: true | ||
| prefer_rgb_color: | ||
| description: "Prefer to use color_rgb over color_temp if possible, default: false" | ||
| example: false | ||
| turn_on_lights: | ||
| description: "Turn on the lights that are off, default: false" | ||
| example: false | ||
| set_manual_control: | ||
| description: Mark whether a light is 'manually controlled'. | ||
| fields: | ||
| entity_id: | ||
| description: entity_id of the Adaptive Lighting switch. | ||
| example: switch.adaptive_lighting_default | ||
| manual_control: | ||
| description: "Whether to add ('true') or remove ('false') the light from the 'manual_control' list, default: true" | ||
| example: true | ||
| lights: | ||
| description: entity_id(s) of lights, if not specified, all lights in the switch are selected. | ||
| example: light.bedroom_ceiling |
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
Uh oh!
There was an error while loading. Please reload this page.