From 65b1aa4b84bb34da8aa42544439ae97f10539276 Mon Sep 17 00:00:00 2001 From: Bas Nijholt Date: Sun, 6 Sep 2020 11:27:53 +0200 Subject: [PATCH 01/13] start implementing profile settings, as suggested in https://github.com/claytonjn/hass-circadian_lighting/issues/91#issuecomment-647084406 --- .../circadian_lighting/__init__.py | 5 ++ custom_components/circadian_lighting/const.py | 42 +++++++++++ .../circadian_lighting/switch.py | 72 ++++++++----------- 3 files changed, 78 insertions(+), 41 deletions(-) create mode 100644 custom_components/circadian_lighting/const.py diff --git a/custom_components/circadian_lighting/__init__.py b/custom_components/circadian_lighting/__init__.py index 24b4fcb..48cb5f8 100755 --- a/custom_components/circadian_lighting/__init__.py +++ b/custom_components/circadian_lighting/__init__.py @@ -57,6 +57,8 @@ color_xy_to_hs, ) +from .const import _PROFILE_SCHEMA, CONF_PROFILE + _LOGGER = logging.getLogger(__name__) DOMAIN = "circadian_lighting" @@ -94,6 +96,9 @@ vol.Optional( ATTR_TRANSITION, default=DEFAULT_TRANSITION ): VALID_TRANSITION, + vol.Optional(CONF_PROFILE): vol.Schema( + {cv.string: vol.Schema(_PROFILE_SCHEMA)} + ), } ), }, diff --git a/custom_components/circadian_lighting/const.py b/custom_components/circadian_lighting/const.py new file mode 100644 index 0000000..9dab282 --- /dev/null +++ b/custom_components/circadian_lighting/const.py @@ -0,0 +1,42 @@ +import voluptuous as vol + +import homeassistant.helpers.config_validation as cv +from homeassistant.components.light import VALID_TRANSITION + +# Switch and profile settings +CONF_PROFILE = "profile" +CONF_DISABLE_BRIGHTNESS_ADJUST = "disable_brightness_adjust" +CONF_MIN_BRIGHT, DEFAULT_MIN_BRIGHT = "min_brightness", 1 +CONF_MAX_BRIGHT, DEFAULT_MAX_BRIGHT = "max_brightness", 100 +CONF_SLEEP_ENTITY = "sleep_entity" +CONF_SLEEP_STATE = "sleep_state" +CONF_SLEEP_CT, DEFAULT_SLEEP_CT = "sleep_colortemp", 1000 +CONF_SLEEP_BRIGHT, DEFAULT_SLEEP_BRIGHT = "sleep_brightness", 1 +CONF_DISABLE_ENTITY = "disable_entity" +CONF_DISABLE_STATE = "disable_state" +CONF_INITIAL_TRANSITION, DEFAULT_INITIAL_TRANSITION = "initial_transition", 1 +CONF_ONLY_ONCE = "only_once" + +_PROFILE_SCHEMA = { + vol.Optional(CONF_DISABLE_BRIGHTNESS_ADJUST, default=False): cv.boolean, + vol.Optional(CONF_MIN_BRIGHT, default=DEFAULT_MIN_BRIGHT): vol.All( + vol.Coerce(int), vol.Range(min=1, max=100) + ), + vol.Optional(CONF_MAX_BRIGHT, default=DEFAULT_MAX_BRIGHT): vol.All( + vol.Coerce(int), vol.Range(min=1, max=100) + ), + vol.Optional(CONF_SLEEP_ENTITY): cv.entity_id, + vol.Optional(CONF_SLEEP_STATE): vol.All(cv.ensure_list, [cv.string]), + vol.Optional(CONF_SLEEP_CT, default=DEFAULT_SLEEP_CT): vol.All( + vol.Coerce(int), vol.Range(min=1000, max=10000) + ), + vol.Optional(CONF_SLEEP_BRIGHT, default=DEFAULT_SLEEP_BRIGHT): vol.All( + vol.Coerce(int), vol.Range(min=1, max=100) + ), + vol.Optional(CONF_DISABLE_ENTITY): cv.entity_id, + vol.Optional(CONF_DISABLE_STATE): vol.All(cv.ensure_list, [cv.string]), + vol.Optional( + CONF_INITIAL_TRANSITION, default=DEFAULT_INITIAL_TRANSITION + ): VALID_TRANSITION, + vol.Optional(CONF_ONLY_ONCE, default=False): cv.boolean, +} diff --git a/custom_components/circadian_lighting/switch.py b/custom_components/circadian_lighting/switch.py index 7c5b6cc..70b2eb2 100755 --- a/custom_components/circadian_lighting/switch.py +++ b/custom_components/circadian_lighting/switch.py @@ -18,7 +18,7 @@ ATTR_XY_COLOR, ) from homeassistant.components.light import DOMAIN as LIGHT_DOMAIN -from homeassistant.components.light import VALID_TRANSITION, is_on +from homeassistant.components.light import is_on from homeassistant.components.switch import SwitchEntity from homeassistant.const import ( ATTR_ENTITY_ID, @@ -39,6 +39,21 @@ ) from . import CIRCADIAN_LIGHTING_UPDATE_TOPIC, DOMAIN +from .const import ( + _PROFILE_SCHEMA, + CONF_DISABLE_BRIGHTNESS_ADJUST, + CONF_DISABLE_ENTITY, + CONF_DISABLE_STATE, + CONF_INITIAL_TRANSITION, + CONF_MAX_BRIGHT, + CONF_MIN_BRIGHT, + CONF_ONLY_ONCE, + CONF_PROFILE, + CONF_SLEEP_BRIGHT, + CONF_SLEEP_CT, + CONF_SLEEP_ENTITY, + CONF_SLEEP_STATE, +) _LOGGER = logging.getLogger(__name__) @@ -48,17 +63,6 @@ CONF_LIGHTS_RGB = "lights_rgb" CONF_LIGHTS_XY = "lights_xy" CONF_LIGHTS_BRIGHT = "lights_brightness" -CONF_DISABLE_BRIGHTNESS_ADJUST = "disable_brightness_adjust" -CONF_MIN_BRIGHT, DEFAULT_MIN_BRIGHT = "min_brightness", 1 -CONF_MAX_BRIGHT, DEFAULT_MAX_BRIGHT = "max_brightness", 100 -CONF_SLEEP_ENTITY = "sleep_entity" -CONF_SLEEP_STATE = "sleep_state" -CONF_SLEEP_CT, DEFAULT_SLEEP_CT = "sleep_colortemp", 1000 -CONF_SLEEP_BRIGHT, DEFAULT_SLEEP_BRIGHT = "sleep_brightness", 1 -CONF_DISABLE_ENTITY = "disable_entity" -CONF_DISABLE_STATE = "disable_state" -CONF_INITIAL_TRANSITION, DEFAULT_INITIAL_TRANSITION = "initial_transition", 1 -CONF_ONLY_ONCE = "only_once" PLATFORM_SCHEMA = vol.Schema( { @@ -68,27 +72,7 @@ vol.Optional(CONF_LIGHTS_RGB): cv.entity_ids, vol.Optional(CONF_LIGHTS_XY): cv.entity_ids, vol.Optional(CONF_LIGHTS_BRIGHT): cv.entity_ids, - vol.Optional(CONF_DISABLE_BRIGHTNESS_ADJUST, default=False): cv.boolean, - vol.Optional(CONF_MIN_BRIGHT, default=DEFAULT_MIN_BRIGHT): vol.All( - vol.Coerce(int), vol.Range(min=1, max=100) - ), - vol.Optional(CONF_MAX_BRIGHT, default=DEFAULT_MAX_BRIGHT): vol.All( - vol.Coerce(int), vol.Range(min=1, max=100) - ), - vol.Optional(CONF_SLEEP_ENTITY): cv.entity_id, - vol.Optional(CONF_SLEEP_STATE): vol.All(cv.ensure_list, [cv.string]), - vol.Optional(CONF_SLEEP_CT, default=DEFAULT_SLEEP_CT): vol.All( - vol.Coerce(int), vol.Range(min=1000, max=10000) - ), - vol.Optional(CONF_SLEEP_BRIGHT, default=DEFAULT_SLEEP_BRIGHT): vol.All( - vol.Coerce(int), vol.Range(min=1, max=100) - ), - vol.Optional(CONF_DISABLE_ENTITY): cv.entity_id, - vol.Optional(CONF_DISABLE_STATE): vol.All(cv.ensure_list, [cv.string]), - vol.Optional( - CONF_INITIAL_TRANSITION, default=DEFAULT_INITIAL_TRANSITION - ): VALID_TRANSITION, - vol.Optional(CONF_ONLY_ONCE, default=False): cv.boolean, + **_PROFILE_SCHEMA, } ) @@ -97,14 +81,7 @@ def setup_platform(hass, config, add_devices, discovery_info=None): """Set up the Circadian Lighting switches.""" circadian_lighting = hass.data.get(DOMAIN) if circadian_lighting is not None: - switch = CircadianSwitch( - hass, - circadian_lighting, - name=config.get(CONF_NAME), - lights_ct=config.get(CONF_LIGHTS_CT, []), - lights_rgb=config.get(CONF_LIGHTS_RGB, []), - lights_xy=config.get(CONF_LIGHTS_XY, []), - lights_brightness=config.get(CONF_LIGHTS_BRIGHT, []), + switch_settings = dict( disable_brightness_adjust=config.get(CONF_DISABLE_BRIGHTNESS_ADJUST), min_brightness=config.get(CONF_MIN_BRIGHT), max_brightness=config.get(CONF_MAX_BRIGHT), @@ -117,6 +94,19 @@ def setup_platform(hass, config, add_devices, discovery_info=None): initial_transition=config.get(CONF_INITIAL_TRANSITION), only_once=config.get(CONF_ONLY_ONCE), ) + profile = config.get(CONF_PROFILE) + profile_settings = circadian_lighting._profiles.get(profile, {}) + settings = dict(switch_settings, **profile_settings) + switch = CircadianSwitch( + hass, + circadian_lighting, + name=config.get(CONF_NAME), + lights_ct=config.get(CONF_LIGHTS_CT, []), + lights_rgb=config.get(CONF_LIGHTS_RGB, []), + lights_xy=config.get(CONF_LIGHTS_XY, []), + lights_brightness=config.get(CONF_LIGHTS_BRIGHT, []), + **settings, + ) add_devices([switch]) return True From eb8da2e46b08c5060f105fbf8e8303604ea0992d Mon Sep 17 00:00:00 2001 From: Bas Nijholt Date: Sun, 6 Sep 2020 11:54:32 +0200 Subject: [PATCH 02/13] initial implementation of profiles --- custom_components/circadian_lighting/__init__.py | 8 ++++++-- custom_components/circadian_lighting/const.py | 1 + custom_components/circadian_lighting/switch.py | 1 + 3 files changed, 8 insertions(+), 2 deletions(-) diff --git a/custom_components/circadian_lighting/__init__.py b/custom_components/circadian_lighting/__init__.py index 48cb5f8..9784868 100755 --- a/custom_components/circadian_lighting/__init__.py +++ b/custom_components/circadian_lighting/__init__.py @@ -57,7 +57,7 @@ color_xy_to_hs, ) -from .const import _PROFILE_SCHEMA, CONF_PROFILE +from .const import _PROFILE_SCHEMA, CONF_PROFILES _LOGGER = logging.getLogger(__name__) @@ -96,7 +96,7 @@ vol.Optional( ATTR_TRANSITION, default=DEFAULT_TRANSITION ): VALID_TRANSITION, - vol.Optional(CONF_PROFILE): vol.Schema( + vol.Optional(CONF_PROFILES): vol.Schema( {cv.string: vol.Schema(_PROFILE_SCHEMA)} ), } @@ -122,6 +122,7 @@ def setup(hass, config): elevation=conf.get(CONF_ELEVATION, hass.config.elevation), interval=conf.get(CONF_INTERVAL), transition=conf.get(ATTR_TRANSITION), + profiles=conf.get(CONF_PROFILES, {}), ) load_platform(hass, "sensor", DOMAIN, {}, config) @@ -145,6 +146,7 @@ def __init__( elevation, interval, transition, + profiles, ): self.hass = hass self._min_colortemp = min_colortemp @@ -157,6 +159,8 @@ def __init__( self._longitude = longitude self._elevation = elevation self._transition = transition + self._profiles = profiles + _LOGGER.debug("profiles: %s", self._profiles) self._percent = self.calc_percent() self._colortemp = self.calc_colortemp() diff --git a/custom_components/circadian_lighting/const.py b/custom_components/circadian_lighting/const.py index 9dab282..1925334 100644 --- a/custom_components/circadian_lighting/const.py +++ b/custom_components/circadian_lighting/const.py @@ -5,6 +5,7 @@ # Switch and profile settings CONF_PROFILE = "profile" +CONF_PROFILES = "profiles" CONF_DISABLE_BRIGHTNESS_ADJUST = "disable_brightness_adjust" CONF_MIN_BRIGHT, DEFAULT_MIN_BRIGHT = "min_brightness", 1 CONF_MAX_BRIGHT, DEFAULT_MAX_BRIGHT = "max_brightness", 100 diff --git a/custom_components/circadian_lighting/switch.py b/custom_components/circadian_lighting/switch.py index 70b2eb2..f811763 100755 --- a/custom_components/circadian_lighting/switch.py +++ b/custom_components/circadian_lighting/switch.py @@ -72,6 +72,7 @@ vol.Optional(CONF_LIGHTS_RGB): cv.entity_ids, vol.Optional(CONF_LIGHTS_XY): cv.entity_ids, vol.Optional(CONF_LIGHTS_BRIGHT): cv.entity_ids, + vol.Optional(CONF_PROFILE): cv.string, **_PROFILE_SCHEMA, } ) From f6219de84f7977a7b89d7a21af977c4f6aa53695 Mon Sep 17 00:00:00 2001 From: Bas Nijholt Date: Mon, 7 Sep 2020 15:33:04 +0200 Subject: [PATCH 03/13] another attempt --- .../circadian_lighting/__init__.py | 43 ++++----- custom_components/circadian_lighting/const.py | 43 --------- .../circadian_lighting/switch.py | 89 ++++++++++++------- 3 files changed, 79 insertions(+), 96 deletions(-) delete mode 100644 custom_components/circadian_lighting/const.py diff --git a/custom_components/circadian_lighting/__init__.py b/custom_components/circadian_lighting/__init__.py index 9784868..dd65036 100755 --- a/custom_components/circadian_lighting/__init__.py +++ b/custom_components/circadian_lighting/__init__.py @@ -57,8 +57,6 @@ color_xy_to_hs, ) -from .const import _PROFILE_SCHEMA, CONF_PROFILES - _LOGGER = logging.getLogger(__name__) DOMAIN = "circadian_lighting" @@ -74,30 +72,35 @@ CONF_SUNRISE_TIME = "sunrise_time" CONF_SUNSET_TIME = "sunset_time" DEFAULT_TRANSITION = 60 +CONF_PROFILES = "profiles" + +_DOMAIN_SCHEMA = { + vol.Optional(CONF_MIN_CT, default=DEFAULT_MIN_CT): vol.All( + vol.Coerce(int), vol.Range(min=1000, max=10000) + ), + vol.Optional(CONF_MAX_CT, default=DEFAULT_MAX_CT): vol.All( + vol.Coerce(int), vol.Range(min=1000, max=10000) + ), + vol.Optional(CONF_SUNRISE_OFFSET): cv.time_period_str, + vol.Optional(CONF_SUNSET_OFFSET): cv.time_period_str, + vol.Optional(CONF_SUNRISE_TIME): cv.time, + vol.Optional(CONF_SUNSET_TIME): cv.time, + vol.Optional(CONF_LATITUDE): cv.latitude, + vol.Optional(CONF_LONGITUDE): cv.longitude, + vol.Optional(CONF_ELEVATION): float, + vol.Optional(CONF_INTERVAL, default=DEFAULT_INTERVAL): cv.time_period, + vol.Optional(ATTR_TRANSITION, default=DEFAULT_TRANSITION): VALID_TRANSITION, +} + +_DOMAIN_SCHEMA_NO_DEFAULTS = {type(k)(k): v for k, v in _DOMAIN_SCHEMA.items()} CONFIG_SCHEMA = vol.Schema( { DOMAIN: vol.Schema( { - vol.Optional(CONF_MIN_CT, default=DEFAULT_MIN_CT): vol.All( - vol.Coerce(int), vol.Range(min=1000, max=10000) - ), - vol.Optional(CONF_MAX_CT, default=DEFAULT_MAX_CT): vol.All( - vol.Coerce(int), vol.Range(min=1000, max=10000) - ), - vol.Optional(CONF_SUNRISE_OFFSET): cv.time_period_str, - vol.Optional(CONF_SUNSET_OFFSET): cv.time_period_str, - vol.Optional(CONF_SUNRISE_TIME): cv.time, - vol.Optional(CONF_SUNSET_TIME): cv.time, - vol.Optional(CONF_LATITUDE): cv.latitude, - vol.Optional(CONF_LONGITUDE): cv.longitude, - vol.Optional(CONF_ELEVATION): float, - vol.Optional(CONF_INTERVAL, default=DEFAULT_INTERVAL): cv.time_period, - vol.Optional( - ATTR_TRANSITION, default=DEFAULT_TRANSITION - ): VALID_TRANSITION, + **_DOMAIN_SCHEMA, vol.Optional(CONF_PROFILES): vol.Schema( - {cv.string: vol.Schema(_PROFILE_SCHEMA)} + {cv.string: vol.Schema(_DOMAIN_SCHEMA_NO_DEFAULTS)} ), } ), diff --git a/custom_components/circadian_lighting/const.py b/custom_components/circadian_lighting/const.py deleted file mode 100644 index 1925334..0000000 --- a/custom_components/circadian_lighting/const.py +++ /dev/null @@ -1,43 +0,0 @@ -import voluptuous as vol - -import homeassistant.helpers.config_validation as cv -from homeassistant.components.light import VALID_TRANSITION - -# Switch and profile settings -CONF_PROFILE = "profile" -CONF_PROFILES = "profiles" -CONF_DISABLE_BRIGHTNESS_ADJUST = "disable_brightness_adjust" -CONF_MIN_BRIGHT, DEFAULT_MIN_BRIGHT = "min_brightness", 1 -CONF_MAX_BRIGHT, DEFAULT_MAX_BRIGHT = "max_brightness", 100 -CONF_SLEEP_ENTITY = "sleep_entity" -CONF_SLEEP_STATE = "sleep_state" -CONF_SLEEP_CT, DEFAULT_SLEEP_CT = "sleep_colortemp", 1000 -CONF_SLEEP_BRIGHT, DEFAULT_SLEEP_BRIGHT = "sleep_brightness", 1 -CONF_DISABLE_ENTITY = "disable_entity" -CONF_DISABLE_STATE = "disable_state" -CONF_INITIAL_TRANSITION, DEFAULT_INITIAL_TRANSITION = "initial_transition", 1 -CONF_ONLY_ONCE = "only_once" - -_PROFILE_SCHEMA = { - vol.Optional(CONF_DISABLE_BRIGHTNESS_ADJUST, default=False): cv.boolean, - vol.Optional(CONF_MIN_BRIGHT, default=DEFAULT_MIN_BRIGHT): vol.All( - vol.Coerce(int), vol.Range(min=1, max=100) - ), - vol.Optional(CONF_MAX_BRIGHT, default=DEFAULT_MAX_BRIGHT): vol.All( - vol.Coerce(int), vol.Range(min=1, max=100) - ), - vol.Optional(CONF_SLEEP_ENTITY): cv.entity_id, - vol.Optional(CONF_SLEEP_STATE): vol.All(cv.ensure_list, [cv.string]), - vol.Optional(CONF_SLEEP_CT, default=DEFAULT_SLEEP_CT): vol.All( - vol.Coerce(int), vol.Range(min=1000, max=10000) - ), - vol.Optional(CONF_SLEEP_BRIGHT, default=DEFAULT_SLEEP_BRIGHT): vol.All( - vol.Coerce(int), vol.Range(min=1, max=100) - ), - vol.Optional(CONF_DISABLE_ENTITY): cv.entity_id, - vol.Optional(CONF_DISABLE_STATE): vol.All(cv.ensure_list, [cv.string]), - vol.Optional( - CONF_INITIAL_TRANSITION, default=DEFAULT_INITIAL_TRANSITION - ): VALID_TRANSITION, - vol.Optional(CONF_ONLY_ONCE, default=False): cv.boolean, -} diff --git a/custom_components/circadian_lighting/switch.py b/custom_components/circadian_lighting/switch.py index f811763..c1b33f9 100755 --- a/custom_components/circadian_lighting/switch.py +++ b/custom_components/circadian_lighting/switch.py @@ -18,7 +18,7 @@ ATTR_XY_COLOR, ) from homeassistant.components.light import DOMAIN as LIGHT_DOMAIN -from homeassistant.components.light import is_on +from homeassistant.components.light import VALID_TRANSITION, is_on from homeassistant.components.switch import SwitchEntity from homeassistant.const import ( ATTR_ENTITY_ID, @@ -39,21 +39,6 @@ ) from . import CIRCADIAN_LIGHTING_UPDATE_TOPIC, DOMAIN -from .const import ( - _PROFILE_SCHEMA, - CONF_DISABLE_BRIGHTNESS_ADJUST, - CONF_DISABLE_ENTITY, - CONF_DISABLE_STATE, - CONF_INITIAL_TRANSITION, - CONF_MAX_BRIGHT, - CONF_MIN_BRIGHT, - CONF_ONLY_ONCE, - CONF_PROFILE, - CONF_SLEEP_BRIGHT, - CONF_SLEEP_CT, - CONF_SLEEP_ENTITY, - CONF_SLEEP_STATE, -) _LOGGER = logging.getLogger(__name__) @@ -63,6 +48,18 @@ CONF_LIGHTS_RGB = "lights_rgb" CONF_LIGHTS_XY = "lights_xy" CONF_LIGHTS_BRIGHT = "lights_brightness" +CONF_DISABLE_BRIGHTNESS_ADJUST = "disable_brightness_adjust" +CONF_MIN_BRIGHT, DEFAULT_MIN_BRIGHT = "min_brightness", 1 +CONF_MAX_BRIGHT, DEFAULT_MAX_BRIGHT = "max_brightness", 100 +CONF_SLEEP_ENTITY = "sleep_entity" +CONF_SLEEP_STATE = "sleep_state" +CONF_SLEEP_CT, DEFAULT_SLEEP_CT = "sleep_colortemp", 1000 +CONF_SLEEP_BRIGHT, DEFAULT_SLEEP_BRIGHT = "sleep_brightness", 1 +CONF_DISABLE_ENTITY = "disable_entity" +CONF_DISABLE_STATE = "disable_state" +CONF_INITIAL_TRANSITION, DEFAULT_INITIAL_TRANSITION = "initial_transition", 1 +CONF_ONLY_ONCE = "only_once" +CONF_PROFILE = "profile" PLATFORM_SCHEMA = vol.Schema( { @@ -72,8 +69,28 @@ vol.Optional(CONF_LIGHTS_RGB): cv.entity_ids, vol.Optional(CONF_LIGHTS_XY): cv.entity_ids, vol.Optional(CONF_LIGHTS_BRIGHT): cv.entity_ids, + vol.Optional(CONF_DISABLE_BRIGHTNESS_ADJUST, default=False): cv.boolean, + vol.Optional(CONF_MIN_BRIGHT, default=DEFAULT_MIN_BRIGHT): vol.All( + vol.Coerce(int), vol.Range(min=1, max=100) + ), + vol.Optional(CONF_MAX_BRIGHT, default=DEFAULT_MAX_BRIGHT): vol.All( + vol.Coerce(int), vol.Range(min=1, max=100) + ), + vol.Optional(CONF_SLEEP_ENTITY): cv.entity_id, + vol.Optional(CONF_SLEEP_STATE): vol.All(cv.ensure_list, [cv.string]), + vol.Optional(CONF_SLEEP_CT, default=DEFAULT_SLEEP_CT): vol.All( + vol.Coerce(int), vol.Range(min=1000, max=10000) + ), + vol.Optional(CONF_SLEEP_BRIGHT, default=DEFAULT_SLEEP_BRIGHT): vol.All( + vol.Coerce(int), vol.Range(min=1, max=100) + ), + vol.Optional(CONF_DISABLE_ENTITY): cv.entity_id, + vol.Optional(CONF_DISABLE_STATE): vol.All(cv.ensure_list, [cv.string]), + vol.Optional( + CONF_INITIAL_TRANSITION, default=DEFAULT_INITIAL_TRANSITION + ): VALID_TRANSITION, + vol.Optional(CONF_ONLY_ONCE, default=False): cv.boolean, vol.Optional(CONF_PROFILE): cv.string, - **_PROFILE_SCHEMA, } ) @@ -82,7 +99,14 @@ def setup_platform(hass, config, add_devices, discovery_info=None): """Set up the Circadian Lighting switches.""" circadian_lighting = hass.data.get(DOMAIN) if circadian_lighting is not None: - switch_settings = dict( + switch = CircadianSwitch( + hass, + circadian_lighting, + name=config.get(CONF_NAME), + lights_ct=config.get(CONF_LIGHTS_CT, []), + lights_rgb=config.get(CONF_LIGHTS_RGB, []), + lights_xy=config.get(CONF_LIGHTS_XY, []), + lights_brightness=config.get(CONF_LIGHTS_BRIGHT, []), disable_brightness_adjust=config.get(CONF_DISABLE_BRIGHTNESS_ADJUST), min_brightness=config.get(CONF_MIN_BRIGHT), max_brightness=config.get(CONF_MAX_BRIGHT), @@ -94,19 +118,7 @@ def setup_platform(hass, config, add_devices, discovery_info=None): disable_state=config.get(CONF_DISABLE_STATE), initial_transition=config.get(CONF_INITIAL_TRANSITION), only_once=config.get(CONF_ONLY_ONCE), - ) - profile = config.get(CONF_PROFILE) - profile_settings = circadian_lighting._profiles.get(profile, {}) - settings = dict(switch_settings, **profile_settings) - switch = CircadianSwitch( - hass, - circadian_lighting, - name=config.get(CONF_NAME), - lights_ct=config.get(CONF_LIGHTS_CT, []), - lights_rgb=config.get(CONF_LIGHTS_RGB, []), - lights_xy=config.get(CONF_LIGHTS_XY, []), - lights_brightness=config.get(CONF_LIGHTS_BRIGHT, []), - **settings, + profile=config.get(CONF_PROFILE), ) add_devices([switch]) @@ -171,6 +183,7 @@ def __init__( disable_state, initial_transition, only_once, + profile, ): """Initialize the Circadian Lighting switch.""" self.hass = hass @@ -192,12 +205,22 @@ def __init__( self._disable_state = disable_state self._initial_transition = initial_transition self._only_once = only_once + self._profile = profile self._lights_types = dict(zip(lights_ct, repeat("ct"))) self._lights_types.update(zip(lights_rgb, repeat("rgb"))) self._lights_types.update(zip(lights_xy, repeat("xy"))) self._lights_types.update(zip(lights_brightness, repeat("brightness"))) self._lights = list(self._lights_types.keys()) + def from_profile(key): + default = getattr(self._circadian_lighting, key) + if self._profile is None: + return default + value = self._circadian_lighting._profiles.get(self._profile, {}).get(key) + if value is not None: + return value + return default + @property def entity_id(self): """Return the entity ID of the switch.""" @@ -278,7 +301,7 @@ def _is_sleep(self): def _color_temperature(self): return ( - self._circadian_lighting._colortemp + self.from_profile("_colortemp") if not self._is_sleep() else self._sleep_colortemp ) @@ -336,7 +359,7 @@ async def _adjust_lights(self, lights, transition): return if transition is None: - transition = self._circadian_lighting._transition + transition = self.from_profile("_transition") tasks = [] for light in lights: From fd1f2fdb66753d29bddc227fdaf5d0ead6155c11 Mon Sep 17 00:00:00 2001 From: Bas Nijholt Date: Mon, 7 Sep 2020 19:30:58 +0200 Subject: [PATCH 04/13] add option to add multiple profiles --- .../circadian_lighting/__init__.py | 100 ++++++++++-------- 1 file changed, 54 insertions(+), 46 deletions(-) diff --git a/custom_components/circadian_lighting/__init__.py b/custom_components/circadian_lighting/__init__.py index dd65036..db29483 100755 --- a/custom_components/circadian_lighting/__init__.py +++ b/custom_components/circadian_lighting/__init__.py @@ -27,6 +27,7 @@ lights to 2700K (warm white) until your hub goes into Night mode """ +from custom_components.circadian_lighting.switch import CONF_PROFILE import logging from datetime import timedelta @@ -72,61 +73,68 @@ CONF_SUNRISE_TIME = "sunrise_time" CONF_SUNSET_TIME = "sunset_time" DEFAULT_TRANSITION = 60 -CONF_PROFILES = "profiles" - -_DOMAIN_SCHEMA = { - vol.Optional(CONF_MIN_CT, default=DEFAULT_MIN_CT): vol.All( - vol.Coerce(int), vol.Range(min=1000, max=10000) - ), - vol.Optional(CONF_MAX_CT, default=DEFAULT_MAX_CT): vol.All( - vol.Coerce(int), vol.Range(min=1000, max=10000) - ), - vol.Optional(CONF_SUNRISE_OFFSET): cv.time_period_str, - vol.Optional(CONF_SUNSET_OFFSET): cv.time_period_str, - vol.Optional(CONF_SUNRISE_TIME): cv.time, - vol.Optional(CONF_SUNSET_TIME): cv.time, - vol.Optional(CONF_LATITUDE): cv.latitude, - vol.Optional(CONF_LONGITUDE): cv.longitude, - vol.Optional(CONF_ELEVATION): float, - vol.Optional(CONF_INTERVAL, default=DEFAULT_INTERVAL): cv.time_period, - vol.Optional(ATTR_TRANSITION, default=DEFAULT_TRANSITION): VALID_TRANSITION, -} - -_DOMAIN_SCHEMA_NO_DEFAULTS = {type(k)(k): v for k, v in _DOMAIN_SCHEMA.items()} +CONF_PROFILE, DEFAULT_PROFILE = "profile", "default" -CONFIG_SCHEMA = vol.Schema( +_DOMAIN_SCHEMA = vol.Schema( { - DOMAIN: vol.Schema( - { - **_DOMAIN_SCHEMA, - vol.Optional(CONF_PROFILES): vol.Schema( - {cv.string: vol.Schema(_DOMAIN_SCHEMA_NO_DEFAULTS)} - ), - } + vol.Optional(CONF_MIN_CT, default=DEFAULT_MIN_CT): vol.All( + vol.Coerce(int), vol.Range(min=1000, max=10000) + ), + vol.Optional(CONF_MAX_CT, default=DEFAULT_MAX_CT): vol.All( + vol.Coerce(int), vol.Range(min=1000, max=10000) ), - }, + vol.Optional(CONF_SUNRISE_OFFSET): cv.time_period_str, + vol.Optional(CONF_SUNSET_OFFSET): cv.time_period_str, + vol.Optional(CONF_SUNRISE_TIME): cv.time, + vol.Optional(CONF_SUNSET_TIME): cv.time, + vol.Optional(CONF_LATITUDE): cv.latitude, + vol.Optional(CONF_LONGITUDE): cv.longitude, + vol.Optional(CONF_ELEVATION): float, + vol.Optional(CONF_INTERVAL, default=DEFAULT_INTERVAL): cv.time_period, + vol.Optional(ATTR_TRANSITION, default=DEFAULT_TRANSITION): VALID_TRANSITION, + vol.Optional(CONF_PROFILE, default=DEFAULT_PROFILE): cv.string, + } +) + + +def _all_unique_profiles(value): + """Validate that each hub configured has a unique profiles.""" + hosts = [device[CONF_PROFILE] for device in value] + schema = vol.Schema(vol.Unique()) + schema(hosts) + return value + + +# _DOMAIN_SCHEMA_NO_DEFAULTS = {type(k)(k): v for k, v in _DOMAIN_SCHEMA.items()} + +CONFIG_SCHEMA = vol.Schema( + {DOMAIN: vol.All(cv.ensure_list, [_DOMAIN_SCHEMA], _all_unique_profiles)}, extra=vol.ALLOW_EXTRA, ) def setup(hass, config): """Set up the Circadian Lighting platform.""" - conf = config[DOMAIN] - hass.data[DOMAIN] = CircadianLighting( - hass, - min_colortemp=conf.get(CONF_MIN_CT), - max_colortemp=conf.get(CONF_MAX_CT), - sunrise_offset=conf.get(CONF_SUNRISE_OFFSET), - sunset_offset=conf.get(CONF_SUNSET_OFFSET), - sunrise_time=conf.get(CONF_SUNRISE_TIME), - sunset_time=conf.get(CONF_SUNSET_TIME), - latitude=conf.get(CONF_LATITUDE, hass.config.latitude), - longitude=conf.get(CONF_LONGITUDE, hass.config.longitude), - elevation=conf.get(CONF_ELEVATION, hass.config.elevation), - interval=conf.get(CONF_INTERVAL), - transition=conf.get(ATTR_TRANSITION), - profiles=conf.get(CONF_PROFILES, {}), - ) + if DOMAIN not in hass.data: + hass.data[DOMAIN] = {} + configs = config[DOMAIN] + for conf in configs: + profile = conf[CONF_PROFILE] + hass.data[DOMAIN][profile] = CircadianLighting( + hass, + min_colortemp=conf[CONF_MIN_CT], + max_colortemp=conf[CONF_MAX_CT], + sunrise_offset=conf.get(CONF_SUNRISE_OFFSET), + sunset_offset=conf.get(CONF_SUNSET_OFFSET), + sunrise_time=conf.get(CONF_SUNRISE_TIME), + sunset_time=conf.get(CONF_SUNSET_TIME), + latitude=conf.get(CONF_LATITUDE, hass.config.latitude), + longitude=conf.get(CONF_LONGITUDE, hass.config.longitude), + elevation=conf.get(CONF_ELEVATION, hass.config.elevation), + interval=conf[CONF_INTERVAL], + transition=conf[ATTR_TRANSITION], + profile=profile, + ) load_platform(hass, "sensor", DOMAIN, {}, config) return True From 90cbd2980eaea8030f55fcb5f162ab3cad95eb74 Mon Sep 17 00:00:00 2001 From: Bas Nijholt Date: Mon, 7 Sep 2020 19:33:32 +0200 Subject: [PATCH 05/13] profiles -> profile --- custom_components/circadian_lighting/__init__.py | 10 ++++------ 1 file changed, 4 insertions(+), 6 deletions(-) diff --git a/custom_components/circadian_lighting/__init__.py b/custom_components/circadian_lighting/__init__.py index db29483..aaa6cac 100755 --- a/custom_components/circadian_lighting/__init__.py +++ b/custom_components/circadian_lighting/__init__.py @@ -27,7 +27,6 @@ lights to 2700K (warm white) until your hub goes into Night mode """ -from custom_components.circadian_lighting.switch import CONF_PROFILE import logging from datetime import timedelta @@ -36,6 +35,7 @@ import homeassistant.helpers.config_validation as cv import homeassistant.util.dt as dt_util +from custom_components.circadian_lighting.switch import CONF_PROFILE from homeassistant.components.light import ATTR_TRANSITION, VALID_TRANSITION from homeassistant.const import ( CONF_ELEVATION, @@ -105,8 +105,6 @@ def _all_unique_profiles(value): return value -# _DOMAIN_SCHEMA_NO_DEFAULTS = {type(k)(k): v for k, v in _DOMAIN_SCHEMA.items()} - CONFIG_SCHEMA = vol.Schema( {DOMAIN: vol.All(cv.ensure_list, [_DOMAIN_SCHEMA], _all_unique_profiles)}, extra=vol.ALLOW_EXTRA, @@ -157,7 +155,7 @@ def __init__( elevation, interval, transition, - profiles, + profile, ): self.hass = hass self._min_colortemp = min_colortemp @@ -170,8 +168,8 @@ def __init__( self._longitude = longitude self._elevation = elevation self._transition = transition - self._profiles = profiles - _LOGGER.debug("profiles: %s", self._profiles) + self._profile = profile + _LOGGER.debug("profile: %s", self._profile) self._percent = self.calc_percent() self._colortemp = self.calc_colortemp() From db78ab2027d809fcc517abacb448548f0e3acf73 Mon Sep 17 00:00:00 2001 From: Bas Nijholt Date: Mon, 7 Sep 2020 19:50:42 +0200 Subject: [PATCH 06/13] setup sensor for default profile --- custom_components/circadian_lighting/sensor.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/custom_components/circadian_lighting/sensor.py b/custom_components/circadian_lighting/sensor.py index 35947f9..b98c026 100755 --- a/custom_components/circadian_lighting/sensor.py +++ b/custom_components/circadian_lighting/sensor.py @@ -6,14 +6,14 @@ from homeassistant.helpers.dispatcher import async_dispatcher_connect from homeassistant.helpers.entity import Entity -from . import CIRCADIAN_LIGHTING_UPDATE_TOPIC, DOMAIN +from . import CIRCADIAN_LIGHTING_UPDATE_TOPIC, DEFAULT_PROFILE, DOMAIN ICON = "mdi:theme-light-dark" def setup_platform(hass, config, add_devices, discovery_info=None): """Set up the Circadian Lighting sensor.""" - circadian_lighting = hass.data.get(DOMAIN) + circadian_lighting = hass.data.get(DOMAIN, {}).get(DEFAULT_PROFILE) if circadian_lighting is not None: sensor = CircadianSensor(hass, circadian_lighting) add_devices([sensor], True) From 4234be19ecc51af4230bf3d0bae85615161e0d51 Mon Sep 17 00:00:00 2001 From: Bas Nijholt Date: Mon, 7 Sep 2020 19:51:00 +0200 Subject: [PATCH 07/13] fix import --- custom_components/circadian_lighting/__init__.py | 1 - 1 file changed, 1 deletion(-) diff --git a/custom_components/circadian_lighting/__init__.py b/custom_components/circadian_lighting/__init__.py index aaa6cac..aafbd5e 100755 --- a/custom_components/circadian_lighting/__init__.py +++ b/custom_components/circadian_lighting/__init__.py @@ -35,7 +35,6 @@ import homeassistant.helpers.config_validation as cv import homeassistant.util.dt as dt_util -from custom_components.circadian_lighting.switch import CONF_PROFILE from homeassistant.components.light import ATTR_TRANSITION, VALID_TRANSITION from homeassistant.const import ( CONF_ELEVATION, From 5663a7b1a9fb94f51052ea925d80acc03fe29e92 Mon Sep 17 00:00:00 2001 From: Bas Nijholt Date: Mon, 7 Sep 2020 19:52:30 +0200 Subject: [PATCH 08/13] make switch use profile --- .../circadian_lighting/switch.py | 70 ++++++++----------- 1 file changed, 28 insertions(+), 42 deletions(-) diff --git a/custom_components/circadian_lighting/switch.py b/custom_components/circadian_lighting/switch.py index c1b33f9..c5a1755 100755 --- a/custom_components/circadian_lighting/switch.py +++ b/custom_components/circadian_lighting/switch.py @@ -38,7 +38,7 @@ color_xy_to_hs, ) -from . import CIRCADIAN_LIGHTING_UPDATE_TOPIC, DOMAIN +from . import CIRCADIAN_LIGHTING_UPDATE_TOPIC, DOMAIN, CONF_PROFILE, DEFAULT_PROFILE _LOGGER = logging.getLogger(__name__) @@ -59,7 +59,6 @@ CONF_DISABLE_STATE = "disable_state" CONF_INITIAL_TRANSITION, DEFAULT_INITIAL_TRANSITION = "initial_transition", 1 CONF_ONLY_ONCE = "only_once" -CONF_PROFILE = "profile" PLATFORM_SCHEMA = vol.Schema( { @@ -90,41 +89,37 @@ CONF_INITIAL_TRANSITION, default=DEFAULT_INITIAL_TRANSITION ): VALID_TRANSITION, vol.Optional(CONF_ONLY_ONCE, default=False): cv.boolean, - vol.Optional(CONF_PROFILE): cv.string, + vol.Optional(CONF_PROFILE, default=DEFAULT_PROFILE): cv.string, } ) def setup_platform(hass, config, add_devices, discovery_info=None): """Set up the Circadian Lighting switches.""" - circadian_lighting = hass.data.get(DOMAIN) - if circadian_lighting is not None: - switch = CircadianSwitch( - hass, - circadian_lighting, - name=config.get(CONF_NAME), - lights_ct=config.get(CONF_LIGHTS_CT, []), - lights_rgb=config.get(CONF_LIGHTS_RGB, []), - lights_xy=config.get(CONF_LIGHTS_XY, []), - lights_brightness=config.get(CONF_LIGHTS_BRIGHT, []), - disable_brightness_adjust=config.get(CONF_DISABLE_BRIGHTNESS_ADJUST), - min_brightness=config.get(CONF_MIN_BRIGHT), - max_brightness=config.get(CONF_MAX_BRIGHT), - sleep_entity=config.get(CONF_SLEEP_ENTITY), - sleep_state=config.get(CONF_SLEEP_STATE), - sleep_colortemp=config.get(CONF_SLEEP_CT), - sleep_brightness=config.get(CONF_SLEEP_BRIGHT), - disable_entity=config.get(CONF_DISABLE_ENTITY), - disable_state=config.get(CONF_DISABLE_STATE), - initial_transition=config.get(CONF_INITIAL_TRANSITION), - only_once=config.get(CONF_ONLY_ONCE), - profile=config.get(CONF_PROFILE), - ) - add_devices([switch]) - - return True - else: - return False + profile = config[CONF_PROFILE] + circadian_lighting = hass.data[DOMAIN][profile] + switch = CircadianSwitch( + hass, + circadian_lighting, + name=config[CONF_NAME], + lights_ct=config.get(CONF_LIGHTS_CT, []), + lights_rgb=config.get(CONF_LIGHTS_RGB, []), + lights_xy=config.get(CONF_LIGHTS_XY, []), + lights_brightness=config.get(CONF_LIGHTS_BRIGHT, []), + disable_brightness_adjust=config[CONF_DISABLE_BRIGHTNESS_ADJUST], + min_brightness=config[CONF_MIN_BRIGHT], + max_brightness=config[CONF_MAX_BRIGHT], + sleep_entity=config.get(CONF_SLEEP_ENTITY), + sleep_state=config.get(CONF_SLEEP_STATE), + sleep_colortemp=config[CONF_SLEEP_CT], + sleep_brightness=config[CONF_SLEEP_BRIGHT], + disable_entity=config.get(CONF_DISABLE_ENTITY), + disable_state=config.get(CONF_DISABLE_STATE), + initial_transition=config[CONF_INITIAL_TRANSITION], + only_once=config[CONF_ONLY_ONCE], + profile=profile, + ) + add_devices([switch]) def _difference_between_states(from_state, to_state): @@ -212,15 +207,6 @@ def __init__( self._lights_types.update(zip(lights_brightness, repeat("brightness"))) self._lights = list(self._lights_types.keys()) - def from_profile(key): - default = getattr(self._circadian_lighting, key) - if self._profile is None: - return default - value = self._circadian_lighting._profiles.get(self._profile, {}).get(key) - if value is not None: - return value - return default - @property def entity_id(self): """Return the entity ID of the switch.""" @@ -301,7 +287,7 @@ def _is_sleep(self): def _color_temperature(self): return ( - self.from_profile("_colortemp") + self._circadian_lighting._colortemp if not self._is_sleep() else self._sleep_colortemp ) @@ -359,7 +345,7 @@ async def _adjust_lights(self, lights, transition): return if transition is None: - transition = self.from_profile("_transition") + transition = self._circadian_lighting._transition tasks = [] for light in lights: From 31da53182f68390753eb3c577ab30b5acb78f06a Mon Sep 17 00:00:00 2001 From: Bas Nijholt Date: Mon, 7 Sep 2020 19:53:59 +0200 Subject: [PATCH 09/13] fix doc-string --- custom_components/circadian_lighting/__init__.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/custom_components/circadian_lighting/__init__.py b/custom_components/circadian_lighting/__init__.py index aafbd5e..903bb8e 100755 --- a/custom_components/circadian_lighting/__init__.py +++ b/custom_components/circadian_lighting/__init__.py @@ -97,7 +97,7 @@ def _all_unique_profiles(value): - """Validate that each hub configured has a unique profiles.""" + """Validate that all enties have a unique profile name.""" hosts = [device[CONF_PROFILE] for device in value] schema = vol.Schema(vol.Unique()) schema(hosts) From 32dea3aa51aa15ee22b65ae1f7306aad4049c835 Mon Sep 17 00:00:00 2001 From: Bas Nijholt Date: Mon, 7 Sep 2020 20:21:31 +0200 Subject: [PATCH 10/13] setup a sensor per profile --- .../circadian_lighting/sensor.py | 24 ++++++++----------- 1 file changed, 10 insertions(+), 14 deletions(-) diff --git a/custom_components/circadian_lighting/sensor.py b/custom_components/circadian_lighting/sensor.py index b98c026..4461fa6 100755 --- a/custom_components/circadian_lighting/sensor.py +++ b/custom_components/circadian_lighting/sensor.py @@ -13,20 +13,12 @@ def setup_platform(hass, config, add_devices, discovery_info=None): """Set up the Circadian Lighting sensor.""" - circadian_lighting = hass.data.get(DOMAIN, {}).get(DEFAULT_PROFILE) - if circadian_lighting is not None: - sensor = CircadianSensor(hass, circadian_lighting) - add_devices([sensor], True) - - def update(call=None): - """Update component.""" - circadian_lighting.update() - - service_name = "values_update" - hass.services.register(DOMAIN, service_name, update) - return True - else: - return False + sensors = [ + CircadianSensor(hass, circadian_lighting) + for circadian_lighting in hass.data[DOMAIN].values() + ] + add_devices(sensors, True) + return True class CircadianSensor(Entity): @@ -37,6 +29,10 @@ def __init__(self, hass, circadian_lighting): self._circadian_lighting = circadian_lighting self._name = "Circadian Values" self._entity_id = "sensor.circadian_values" + profile = circadian_lighting._profile + if profile != DEFAULT_PROFILE: + self._name += f" {profile}" + self._entity_id += f"_{profile.lower()}" self._unit_of_measurement = "%" self._icon = ICON From e31915c20b59c82bc8ed2db2fcc3ca4bf51db28e Mon Sep 17 00:00:00 2001 From: Bas Nijholt Date: Mon, 7 Sep 2020 20:24:32 +0200 Subject: [PATCH 11/13] switch doesn't need to have the profile as attribute --- custom_components/circadian_lighting/switch.py | 3 --- 1 file changed, 3 deletions(-) diff --git a/custom_components/circadian_lighting/switch.py b/custom_components/circadian_lighting/switch.py index c5a1755..62366ad 100755 --- a/custom_components/circadian_lighting/switch.py +++ b/custom_components/circadian_lighting/switch.py @@ -117,7 +117,6 @@ def setup_platform(hass, config, add_devices, discovery_info=None): disable_state=config.get(CONF_DISABLE_STATE), initial_transition=config[CONF_INITIAL_TRANSITION], only_once=config[CONF_ONLY_ONCE], - profile=profile, ) add_devices([switch]) @@ -178,7 +177,6 @@ def __init__( disable_state, initial_transition, only_once, - profile, ): """Initialize the Circadian Lighting switch.""" self.hass = hass @@ -200,7 +198,6 @@ def __init__( self._disable_state = disable_state self._initial_transition = initial_transition self._only_once = only_once - self._profile = profile self._lights_types = dict(zip(lights_ct, repeat("ct"))) self._lights_types.update(zip(lights_rgb, repeat("rgb"))) self._lights_types.update(zip(lights_xy, repeat("xy"))) From 2eea22b6da05468fbd8adcb9260d12ab516e85cf Mon Sep 17 00:00:00 2001 From: Bas Nijholt Date: Sat, 19 Sep 2020 11:19:09 +0200 Subject: [PATCH 12/13] construct 'today' dict differently --- .../circadian_lighting/__init__.py | 40 ++++++------------- 1 file changed, 13 insertions(+), 27 deletions(-) diff --git a/custom_components/circadian_lighting/__init__.py b/custom_components/circadian_lighting/__init__.py index 24b4fcb..46fbc9d 100755 --- a/custom_components/circadian_lighting/__init__.py +++ b/custom_components/circadian_lighting/__init__.py @@ -27,6 +27,7 @@ lights to 2700K (warm white) until your hub goes into Night mode """ +import bisect import logging from datetime import timedelta @@ -192,7 +193,7 @@ def _replace_time(self, date, key): microsecond=other_date.microsecond, ) - def get_sunrise_sunset(self, date): + def _get_sun_events(self, date): if self._manual_sunrise is not None and self._manual_sunset is not None: sunrise = self._replace_time(date, "sunrise") sunset = self._replace_time(date, "sunset") @@ -235,34 +236,19 @@ def get_sunrise_sunset(self, date): k: dt.astimezone(dt_util.UTC).timestamp() for k, dt in datetimes.items() } - def calc_percent(self): + def _relevant_events(self, now): + events = [] + for days in [-1, 0, 1]: + sun_events = self._get_sun_events(now + timedelta(days=days)) + events.extend(list(sun_events.items())) + events = sorted(events, key=lambda x: x[1]) + index_now = bisect.bisect([ts for _, ts in events], now.timestamp()) + return dict(events[index_now - 2 : index_now + 2]) + + def _calc_percent(self): now = dt_util.utcnow() now_ts = now.timestamp() - - today = self.get_sunrise_sunset(now) - if now_ts < today[SUN_EVENT_SUNRISE]: - # It's before sunrise (after midnight), because it's before - # sunrise (and after midnight) sunset must have happend yesterday. - yesterday = self.get_sunrise_sunset(now - timedelta(days=1)) - if ( - today[SUN_EVENT_MIDNIGHT] > today[SUN_EVENT_SUNSET] - and yesterday[SUN_EVENT_MIDNIGHT] > yesterday[SUN_EVENT_SUNSET] - ): - # Solar midnight is after sunset so use yesterdays's time - today[SUN_EVENT_MIDNIGHT] = yesterday[SUN_EVENT_MIDNIGHT] - today[SUN_EVENT_SUNSET] = yesterday[SUN_EVENT_SUNSET] - elif now_ts > today[SUN_EVENT_SUNSET]: - # It's after sunset (before midnight), because it's after sunset - # (and before midnight) sunrise should happen tomorrow. - tomorrow = self.get_sunrise_sunset(now + timedelta(days=1)) - if ( - today[SUN_EVENT_MIDNIGHT] < today[SUN_EVENT_SUNRISE] - and tomorrow[SUN_EVENT_MIDNIGHT] < tomorrow[SUN_EVENT_SUNRISE] - ): - # Solar midnight is before sunrise so use tomorrow's time - today[SUN_EVENT_MIDNIGHT] = tomorrow[SUN_EVENT_MIDNIGHT] - today[SUN_EVENT_SUNRISE] = tomorrow[SUN_EVENT_SUNRISE] - + today = self._relevant_events(now) # Figure out where we are in time so we know which half of the # parabola to calculate. We're generating a different # sunset-sunrise parabola for before and after solar midnight. From ef444cd941e335e7d130159b7ab26f7bb5b5ca03 Mon Sep 17 00:00:00 2001 From: Bas Nijholt Date: Mon, 21 Sep 2020 12:32:25 +0200 Subject: [PATCH 13/13] rename _calc_percent --- custom_components/circadian_lighting/__init__.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/custom_components/circadian_lighting/__init__.py b/custom_components/circadian_lighting/__init__.py index e396635..a59ea65 100755 --- a/custom_components/circadian_lighting/__init__.py +++ b/custom_components/circadian_lighting/__init__.py @@ -171,7 +171,7 @@ def __init__( self._profile = profile _LOGGER.debug("profile: %s", self._profile) - self._percent = self.calc_percent() + self._percent = self._calc_percent() self._colortemp = self.calc_colortemp() self._rgb_color = self.calc_rgb() self._xy_color = self.calc_xy() @@ -318,7 +318,7 @@ def calc_hs(self): async def update(self, _=None): """Update Circadian Values.""" - self._percent = self.calc_percent() + self._percent = self._calc_percent() self._colortemp = self.calc_colortemp() self._rgb_color = self.calc_rgb() self._xy_color = self.calc_xy()