mirror of
https://github.com/basnijholt/adaptive-lighting.git
synced 2026-09-27 12:24:19 +02:00
112 lines
3.5 KiB
Python
Executable file
112 lines
3.5 KiB
Python
Executable file
"""
|
|
Adaptive Lighting Component for Home-Assistant.
|
|
|
|
This component calculates color temperature and brightness to synchronize
|
|
your color changing lights with perceived color temperature of the sky throughout
|
|
the day. This gives your environment a more natural feel, with cooler whites during
|
|
the midday and warmer tints near twilight and dawn.
|
|
|
|
In addition, the component sets your lights to a nice warm white at 1% in "Sleep" mode,
|
|
which is far brighter than starlight but won't reset your adaptive rhythm or break down
|
|
too much rhodopsin in your eyes.
|
|
|
|
Human circadian rhythms are heavily influenced by ambient light levels and
|
|
hues. Hormone production, brainwave activity, mood and wakefulness are
|
|
just some of the cognitive functions tied to cyclical natural light.
|
|
http://en.wikipedia.org/wiki/Zeitgeber
|
|
|
|
Here's some further reading:
|
|
|
|
http://www.cambridgeincolour.com/tutorials/sunrise-sunset-calculator.htm
|
|
http://en.wikipedia.org/wiki/Color_temperature
|
|
|
|
Technical notes: I had to make a lot of assumptions when writing this app
|
|
* There are no considerations for weather or altitude, but does use your
|
|
hub's location to calculate the sun position.
|
|
* 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 voluptuous as vol
|
|
|
|
import homeassistant.helpers.config_validation as cv
|
|
from homeassistant.config_entries import SOURCE_IMPORT, ConfigEntry
|
|
|
|
from .const import CONF_NAME, DOMAIN, UNDO_UPDATE_LISTENER, get_domain_schema
|
|
|
|
_LOGGER = logging.getLogger(__name__)
|
|
|
|
PLATFORMS = ["switch"]
|
|
|
|
|
|
def _all_unique_profiles(value):
|
|
"""Validate that all enties have a unique profile name."""
|
|
hosts = [device[CONF_NAME] for device in value]
|
|
schema = vol.Schema(vol.Unique())
|
|
schema(hosts)
|
|
return value
|
|
|
|
|
|
_DOMAIN_SCHEMA = get_domain_schema(yaml=True)
|
|
_LOGGER.error(_DOMAIN_SCHEMA)
|
|
CONFIG_SCHEMA = vol.Schema(
|
|
{
|
|
DOMAIN: vol.All(
|
|
cv.ensure_list, [vol.Schema(_DOMAIN_SCHEMA)], _all_unique_profiles
|
|
)
|
|
},
|
|
extra=vol.ALLOW_EXTRA,
|
|
)
|
|
|
|
|
|
async def async_setup(hass, config):
|
|
"""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={"source": SOURCE_IMPORT}, data=entry
|
|
)
|
|
)
|
|
return True
|
|
|
|
|
|
async def async_setup_entry(hass, config_entry: ConfigEntry):
|
|
"""Set up the component."""
|
|
hass.data.setdefault(DOMAIN, {})
|
|
|
|
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]()
|
|
|
|
if unload_ok:
|
|
hass.data[DOMAIN].pop(config_entry.entry_id)
|
|
|
|
return unload_ok
|