mirror of
https://github.com/basnijholt/adaptive-lighting.git
synced 2026-09-11 22:34:04 +02:00
commit working version but not with all options
This commit is contained in:
parent
8d8a409a20
commit
d63abb4d28
4 changed files with 147 additions and 100 deletions
|
|
@ -26,17 +26,18 @@ Technical notes: I had to make a lot of assumptions when writing this app
|
|||
* The component doesn't calculate a true "Blue Hour" -- it just sets the
|
||||
lights to 2700K (warm white) until your hub goes into Night mode
|
||||
"""
|
||||
|
||||
import asyncio
|
||||
import logging
|
||||
|
||||
import homeassistant.helpers.config_validation as cv
|
||||
import voluptuous as vol
|
||||
from homeassistant.components.light import VALID_TRANSITION
|
||||
from homeassistant.config_entries import SOURCE_IMPORT
|
||||
from homeassistant.config_entries import ENTRY_STATE_LOADED, SOURCE_IMPORT, ConfigEntry
|
||||
from homeassistant.const import CONF_NAME
|
||||
|
||||
from .const import (
|
||||
CONF_DISABLE_BRIGHTNESS_ADJUST,
|
||||
UNDO_UPDATE_LISTENER,
|
||||
CONF_DISABLE_ENTITY,
|
||||
CONF_DISABLE_STATE,
|
||||
CONF_INITIAL_TRANSITION,
|
||||
|
|
@ -77,78 +78,118 @@ from .const import (
|
|||
_LOGGER = logging.getLogger(__name__)
|
||||
|
||||
|
||||
CONFIG_SCHEMA = vol.Schema(
|
||||
{
|
||||
DOMAIN: vol.Schema(
|
||||
{
|
||||
vol.Required(CONF_NAME, default=DEFAULT_NAME): cv.string,
|
||||
vol.Optional(CONF_LIGHTS, default=DEFAULT_LIGHTS): cv.entity_ids,
|
||||
vol.Optional(
|
||||
CONF_DISABLE_BRIGHTNESS_ADJUST,
|
||||
default=DEFAULT_DISABLE_BRIGHTNESS_ADJUST,
|
||||
): cv.boolean,
|
||||
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_INTERVAL, default=DEFAULT_INTERVAL): cv.time_period,
|
||||
vol.Optional(
|
||||
CONF_MAX_BRIGHTNESS, default=DEFAULT_MAX_BRIGHTNESS
|
||||
): vol.All(vol.Coerce(int), vol.Range(min=1, max=100)),
|
||||
vol.Optional(
|
||||
CONF_MAX_COLOR_TEMP, default=DEFAULT_MAX_COLOR_TEMP
|
||||
): vol.All(vol.Coerce(int), vol.Range(min=1000, max=10000)),
|
||||
vol.Optional(
|
||||
CONF_MIN_BRIGHTNESS, default=DEFAULT_MIN_BRIGHTNESS
|
||||
): vol.All(vol.Coerce(int), vol.Range(min=1, max=100)),
|
||||
vol.Optional(
|
||||
CONF_MIN_COLOR_TEMP, default=DEFAULT_MIN_COLOR_TEMP
|
||||
): vol.All(vol.Coerce(int), vol.Range(min=1000, max=10000)),
|
||||
vol.Optional(CONF_ONLY_ONCE, default=DEFAULT_ONLY_ONCE): cv.boolean,
|
||||
vol.Optional(
|
||||
CONF_SLEEP_BRIGHTNESS, default=DEFAULT_SLEEP_BRIGHTNESS
|
||||
): vol.All(vol.Coerce(int), vol.Range(min=1, max=100)),
|
||||
vol.Optional(
|
||||
CONF_SLEEP_COLOR_TEMP, default=DEFAULT_SLEEP_COLOR_TEMP
|
||||
): vol.All(vol.Coerce(int), vol.Range(min=1000, max=10000)),
|
||||
vol.Optional(CONF_SLEEP_ENTITY): cv.entity_id,
|
||||
vol.Optional(CONF_SLEEP_STATE): vol.All(cv.ensure_list, [cv.string]),
|
||||
vol.Optional(
|
||||
CONF_SUNRISE_OFFSET, default=DEFAULT_SUNRISE_OFFSET
|
||||
): cv.time_period,
|
||||
vol.Optional(CONF_SUNRISE_TIME): cv.time,
|
||||
vol.Optional(
|
||||
CONF_SUNSET_OFFSET, default=DEFAULT_SUNSET_OFFSET
|
||||
): cv.time_period,
|
||||
vol.Optional(CONF_SUNSET_TIME): cv.time,
|
||||
vol.Optional(
|
||||
CONF_TRANSITION, default=DEFAULT_TRANSITION
|
||||
): VALID_TRANSITION,
|
||||
}
|
||||
)
|
||||
},
|
||||
extra=vol.ALLOW_EXTRA,
|
||||
)
|
||||
# CONFIG_SCHEMA = vol.Schema(
|
||||
# {
|
||||
# DOMAIN: vol.Schema(
|
||||
# {
|
||||
# vol.Required(CONF_NAME, default=DEFAULT_NAME): cv.string,
|
||||
# vol.Optional(CONF_LIGHTS, default=DEFAULT_LIGHTS): cv.entity_ids,
|
||||
# vol.Optional(
|
||||
# CONF_DISABLE_BRIGHTNESS_ADJUST,
|
||||
# default=DEFAULT_DISABLE_BRIGHTNESS_ADJUST,
|
||||
# ): cv.boolean,
|
||||
# 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_INTERVAL, default=DEFAULT_INTERVAL): cv.time_period,
|
||||
# vol.Optional(
|
||||
# CONF_MAX_BRIGHTNESS, default=DEFAULT_MAX_BRIGHTNESS
|
||||
# ): vol.All(vol.Coerce(int), vol.Range(min=1, max=100)),
|
||||
# vol.Optional(
|
||||
# CONF_MAX_COLOR_TEMP, default=DEFAULT_MAX_COLOR_TEMP
|
||||
# ): vol.All(vol.Coerce(int), vol.Range(min=1000, max=10000)),
|
||||
# vol.Optional(
|
||||
# CONF_MIN_BRIGHTNESS, default=DEFAULT_MIN_BRIGHTNESS
|
||||
# ): vol.All(vol.Coerce(int), vol.Range(min=1, max=100)),
|
||||
# vol.Optional(
|
||||
# CONF_MIN_COLOR_TEMP, default=DEFAULT_MIN_COLOR_TEMP
|
||||
# ): vol.All(vol.Coerce(int), vol.Range(min=1000, max=10000)),
|
||||
# vol.Optional(CONF_ONLY_ONCE, default=DEFAULT_ONLY_ONCE): cv.boolean,
|
||||
# vol.Optional(
|
||||
# CONF_SLEEP_BRIGHTNESS, default=DEFAULT_SLEEP_BRIGHTNESS
|
||||
# ): vol.All(vol.Coerce(int), vol.Range(min=1, max=100)),
|
||||
# vol.Optional(
|
||||
# CONF_SLEEP_COLOR_TEMP, default=DEFAULT_SLEEP_COLOR_TEMP
|
||||
# ): vol.All(vol.Coerce(int), vol.Range(min=1000, max=10000)),
|
||||
# vol.Optional(CONF_SLEEP_ENTITY): cv.entity_id,
|
||||
# vol.Optional(CONF_SLEEP_STATE): vol.All(cv.ensure_list, [cv.string]),
|
||||
# vol.Optional(
|
||||
# CONF_SUNRISE_OFFSET, default=DEFAULT_SUNRISE_OFFSET
|
||||
# ): cv.time_period,
|
||||
# vol.Optional(CONF_SUNRISE_TIME): cv.time,
|
||||
# vol.Optional(
|
||||
# CONF_SUNSET_OFFSET, default=DEFAULT_SUNSET_OFFSET
|
||||
# ): cv.time_period,
|
||||
# vol.Optional(CONF_SUNSET_TIME): cv.time,
|
||||
# vol.Optional(
|
||||
# CONF_TRANSITION, default=DEFAULT_TRANSITION
|
||||
# ): VALID_TRANSITION,
|
||||
# }
|
||||
# )
|
||||
# },
|
||||
# extra=vol.ALLOW_EXTRA,
|
||||
# )
|
||||
|
||||
PLATFORMS = ["switch"]
|
||||
|
||||
|
||||
async def async_setup(hass, config):
|
||||
"""Import integration from config."""
|
||||
|
||||
if DOMAIN in config:
|
||||
hass.async_create_task(
|
||||
hass.config_entries.flow.async_init(
|
||||
DOMAIN, context={"source": SOURCE_IMPORT}, data=config[DOMAIN]
|
||||
for entry in config[DOMAIN]:
|
||||
hass.async_create_task(
|
||||
hass.config_entries.flow.async_init(
|
||||
DOMAIN, context={"source": SOURCE_IMPORT}, data=entry
|
||||
)
|
||||
)
|
||||
)
|
||||
return True
|
||||
|
||||
|
||||
async def async_setup_entry(hass, config_entry):
|
||||
async def async_setup_entry(hass, config_entry: ConfigEntry):
|
||||
"""Set up the component."""
|
||||
hass.data.setdefault(DOMAIN, {})
|
||||
|
||||
hass.async_create_task(
|
||||
hass.config_entries.async_forward_entry_setup(config_entry, "switch")
|
||||
)
|
||||
undo_listener = config_entry.add_update_listener(async_update_options)
|
||||
hass.data[DOMAIN][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 = all(
|
||||
await asyncio.gather(
|
||||
*[
|
||||
hass.config_entries.async_forward_entry_unload(config_entry, platform)
|
||||
for platform in PLATFORMS
|
||||
]
|
||||
)
|
||||
)
|
||||
hass.data[DOMAIN][config_entry.entry_id][UNDO_UPDATE_LISTENER]()
|
||||
|
||||
# Exclude this config entry because its not unloaded yet
|
||||
if not any(
|
||||
entry.state == ENTRY_STATE_LOADED and entry.entry_id != config_entry.entry_id
|
||||
for entry in hass.config_entries.async_entries(DOMAIN)
|
||||
):
|
||||
hass.data[DOMAIN].pop(config_entry.entry_id)
|
||||
|
||||
if not hass.data[DOMAIN]:
|
||||
hass.data.pop(DOMAIN)
|
||||
|
||||
return unload_ok
|
||||
|
|
@ -37,6 +37,7 @@ from .const import ( # _convert_to_options_schema,
|
|||
DEFAULT_MAX_COLOR_TEMP,
|
||||
DEFAULT_MIN_BRIGHTNESS,
|
||||
DEFAULT_MIN_COLOR_TEMP,
|
||||
UNDO_UPDATE_LISTENER,
|
||||
DEFAULT_ONLY_ONCE,
|
||||
DEFAULT_SLEEP_BRIGHTNESS,
|
||||
DEFAULT_SLEEP_COLOR_TEMP,
|
||||
|
|
@ -121,34 +122,34 @@ class OptionsFlowHandler(config_entries.OptionsFlow):
|
|||
options_schema = vol.Schema(
|
||||
{
|
||||
vol.Optional(CONF_LIGHTS, default=lights): all_lights,
|
||||
# vol.Optional(
|
||||
# CONF_DISABLE_BRIGHTNESS_ADJUST, default=disable_brightness_adjust
|
||||
# ): bool,
|
||||
vol.Optional(
|
||||
CONF_DISABLE_BRIGHTNESS_ADJUST, default=disable_brightness_adjust
|
||||
): bool,
|
||||
# vol.Optional(CONF_DISABLE_ENTITY, default=disable_entity): str,
|
||||
# vol.Optional(CONF_DISABLE_STATE, default=disable_state): str,
|
||||
# vol.Optional(
|
||||
# CONF_INITIAL_TRANSITION, default=initial_transition
|
||||
# ): cv.positive_int,
|
||||
vol.Optional(
|
||||
CONF_INITIAL_TRANSITION, default=initial_transition
|
||||
): cv.positive_int,
|
||||
# vol.Optional(CONF_INTERVAL, default=interval): cv.positive_int,
|
||||
# vol.Optional(CONF_MAX_BRIGHTNESS, default=max_brightness): vol.All(
|
||||
# vol.Coerce(int), vol.Range(min=1, max=100)
|
||||
# ),
|
||||
# vol.Optional(CONF_MAX_COLOR_TEMP, default=max_color_temp): vol.All(
|
||||
# vol.Coerce(int), vol.Range(min=1000, max=10000)
|
||||
# ),
|
||||
# vol.Optional(CONF_MIN_BRIGHTNESS, default=min_brightness): vol.All(
|
||||
# vol.Coerce(int), vol.Range(min=1, max=100)
|
||||
# ),
|
||||
# vol.Optional(CONF_MIN_COLOR_TEMP, default=min_color_temp): vol.All(
|
||||
# vol.Coerce(int), vol.Range(min=1000, max=10000)
|
||||
# ),
|
||||
# vol.Optional(CONF_ONLY_ONCE, default=only_once): bool,
|
||||
# vol.Optional(CONF_SLEEP_BRIGHTNESS, default=sleep_brightness): vol.All(
|
||||
# vol.Coerce(int), vol.Range(min=1, max=100)
|
||||
# ),
|
||||
# vol.Optional(CONF_SLEEP_COLOR_TEMP, default=sleep_color_temp): vol.All(
|
||||
# vol.Coerce(int), vol.Range(min=1000, max=10000)
|
||||
# ),
|
||||
vol.Optional(CONF_MAX_BRIGHTNESS, default=max_brightness): vol.All(
|
||||
vol.Coerce(int), vol.Range(min=1, max=100)
|
||||
),
|
||||
vol.Optional(CONF_MAX_COLOR_TEMP, default=max_color_temp): vol.All(
|
||||
vol.Coerce(int), vol.Range(min=1000, max=10000)
|
||||
),
|
||||
vol.Optional(CONF_MIN_BRIGHTNESS, default=min_brightness): vol.All(
|
||||
vol.Coerce(int), vol.Range(min=1, max=100)
|
||||
),
|
||||
vol.Optional(CONF_MIN_COLOR_TEMP, default=min_color_temp): vol.All(
|
||||
vol.Coerce(int), vol.Range(min=1000, max=10000)
|
||||
),
|
||||
vol.Optional(CONF_ONLY_ONCE, default=only_once): bool,
|
||||
vol.Optional(CONF_SLEEP_BRIGHTNESS, default=sleep_brightness): vol.All(
|
||||
vol.Coerce(int), vol.Range(min=1, max=100)
|
||||
),
|
||||
vol.Optional(CONF_SLEEP_COLOR_TEMP, default=sleep_color_temp): vol.All(
|
||||
vol.Coerce(int), vol.Range(min=1000, max=10000)
|
||||
),
|
||||
# vol.Optional(CONF_SLEEP_ENTITY, default=sleep_entity): str,
|
||||
# vol.Optional(CONF_SLEEP_STATE, default=sleep_state): str,
|
||||
# vol.Optional(CONF_SUNRISE_OFFSET, default=sunrise_offset): int,
|
||||
|
|
|
|||
|
|
@ -1,5 +1,6 @@
|
|||
import voluptuous as vol
|
||||
|
||||
from datetime import timedelta
|
||||
import homeassistant.helpers.config_validation as cv
|
||||
from homeassistant.components.light import VALID_TRANSITION
|
||||
|
||||
|
|
@ -18,7 +19,7 @@ CONF_DISABLE_BRIGHTNESS_ADJUST, DEFAULT_DISABLE_BRIGHTNESS_ADJUST = (
|
|||
CONF_DISABLE_ENTITY = "disable_entity"
|
||||
CONF_DISABLE_STATE = "disable_state"
|
||||
CONF_INITIAL_TRANSITION, DEFAULT_INITIAL_TRANSITION = "initial_transition", 1
|
||||
CONF_INTERVAL, DEFAULT_INTERVAL = "interval", 90
|
||||
CONF_INTERVAL, DEFAULT_INTERVAL = "interval", timedelta(seconds=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
|
||||
|
|
@ -28,12 +29,13 @@ CONF_SLEEP_BRIGHTNESS, DEFAULT_SLEEP_BRIGHTNESS = "sleep_brightness", 1
|
|||
CONF_SLEEP_COLOR_TEMP, DEFAULT_SLEEP_COLOR_TEMP = "sleep_color_temp", 1000
|
||||
CONF_SLEEP_ENTITY = "sleep_entity"
|
||||
CONF_SLEEP_STATE = "sleep_state"
|
||||
CONF_SUNRISE_OFFSET, DEFAULT_SUNRISE_OFFSET = "sunrise_offset", 0
|
||||
CONF_SUNRISE_OFFSET, DEFAULT_SUNRISE_OFFSET = "sunrise_offset", timedelta(seconds=0)
|
||||
CONF_SUNRISE_TIME = "sunrise_time"
|
||||
CONF_SUNSET_OFFSET, DEFAULT_SUNSET_OFFSET = "sunset_offset", 0
|
||||
CONF_SUNSET_OFFSET, DEFAULT_SUNSET_OFFSET = "sunset_offset", timedelta(seconds=0)
|
||||
CONF_SUNSET_TIME = "sunset_time"
|
||||
CONF_TRANSITION, DEFAULT_TRANSITION = "transition", 60
|
||||
|
||||
UNDO_UPDATE_LISTENER = "undo_update_listener"
|
||||
|
||||
_COMMON_SCHEMA = {
|
||||
vol.Optional(CONF_LIGHTS, default=DEFAULT_LIGHTS): cv.entity_ids,
|
||||
|
|
|
|||
|
|
@ -1,3 +1,4 @@
|
|||
# CHECK OUT THE VIZIO COMPONENT!
|
||||
"""Adaptive Lighting Component for Home-Assistant."""
|
||||
|
||||
import asyncio
|
||||
|
|
@ -5,6 +6,8 @@ import bisect
|
|||
import logging
|
||||
from datetime import timedelta
|
||||
|
||||
import voluptuous as vol
|
||||
|
||||
import homeassistant.util.dt as dt_util
|
||||
from homeassistant.components.light import (
|
||||
ATTR_BRIGHTNESS_PCT,
|
||||
|
|
@ -46,6 +49,7 @@ from homeassistant.util.color import (
|
|||
from .const import (
|
||||
CONF_DISABLE_BRIGHTNESS_ADJUST,
|
||||
CONF_DISABLE_ENTITY,
|
||||
UNDO_UPDATE_LISTENER,
|
||||
CONF_DISABLE_STATE,
|
||||
CONF_INITIAL_TRANSITION,
|
||||
CONF_INTERVAL,
|
||||
|
|
@ -92,10 +96,10 @@ _SUPPORT_OPTS = {
|
|||
}
|
||||
|
||||
_ALLOWED_ORDERS = {
|
||||
("solar_sunrise", "solar_noon", "solar_sunset", "solar_midnight"),
|
||||
("solar_sunset", "solar_midnight", "solar_sunrise", "solar_noon"),
|
||||
("solar_midnight", "solar_sunrise", "solar_noon", "solar_sunset"),
|
||||
("solar_noon", "solar_sunset", "solar_midnight", "solar_sunrise"),
|
||||
(SUN_EVENT_SUNRISE, SUN_EVENT_NOON, SUN_EVENT_SUNSET, SUN_EVENT_MIDNIGHT),
|
||||
(SUN_EVENT_SUNSET, SUN_EVENT_MIDNIGHT, SUN_EVENT_SUNRISE, SUN_EVENT_NOON),
|
||||
(SUN_EVENT_MIDNIGHT, SUN_EVENT_SUNRISE, SUN_EVENT_NOON, SUN_EVENT_SUNSET),
|
||||
(SUN_EVENT_NOON, SUN_EVENT_SUNSET, SUN_EVENT_MIDNIGHT, SUN_EVENT_SUNRISE),
|
||||
}
|
||||
|
||||
|
||||
|
|
@ -111,7 +115,7 @@ async def async_setup_entry(hass, config_entry, async_add_entities):
|
|||
if DOMAIN not in hass.data:
|
||||
hass.data[DOMAIN] = {}
|
||||
hass.data[DOMAIN][name] = switch
|
||||
async_add_entities([switch])
|
||||
async_add_entities([switch], update_before_add=True)
|
||||
|
||||
|
||||
def _difference_between_states(from_state, to_state):
|
||||
|
|
@ -150,9 +154,7 @@ def _difference_between_states(from_state, to_state):
|
|||
class AdaptiveSwitch(SwitchEntity, RestoreEntity):
|
||||
"""Representation of a Adaptive Lighting switch."""
|
||||
|
||||
def __init__(
|
||||
self, hass, name, config_entry,
|
||||
):
|
||||
def __init__(self, hass, name, config_entry):
|
||||
"""Initialize the Adaptive Lighting switch."""
|
||||
self.hass = hass
|
||||
self._name = name
|
||||
|
|
@ -171,6 +173,7 @@ class AdaptiveSwitch(SwitchEntity, RestoreEntity):
|
|||
|
||||
# Set and unset tracker in async_turn_on and async_turn_off
|
||||
self.unsub_tracker = None
|
||||
_LOGGER.error(f"Setting up with {self._lights}: config_entry.data: {config_entry.data}, config_entry.options: {config_entry.options}")
|
||||
|
||||
@property
|
||||
def _lights(self):
|
||||
|
|
@ -431,7 +434,7 @@ class AdaptiveSwitch(SwitchEntity, RestoreEntity):
|
|||
# Check whether order is correct
|
||||
events = sorted(events, key=lambda x: x[1])
|
||||
events_names, _ = zip(*events)
|
||||
assert events_names in _ALLOWED_ORDERS
|
||||
assert events_names in _ALLOWED_ORDERS, events_names
|
||||
|
||||
return events
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue