Skip to content

Instantly share code, notes, and snippets.

@mrvanes
Last active October 16, 2018 19:47
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
Star You must be signed in to star a gist
Embed
What would you like to do?
"""
A Home Assistant (home-assistant.io) service to component lights that accept RGB, XY or MIREDS color commands.
Original Copyright (c) 2017 Alexandre Conde <xlcnd@outlook.com>
https://gist.github.com/xlcnd/01b2d8a28d9d77af901840072360a434
Edited by Martin van Es, October 2018
Licensed under MIT
INSTALL:
1. Create the file <config dir>/custom_components/circadian_lights.py and copy the code below to there.
2. In your <config dir>/configuration.yaml enter (adapt to your case):
circadian_lights:
min_kelvin: 2750
max_kelvin: 3500
lights:
- light.rgb_led_kitchen
- light.rgb_led_tv
- light.rgb_led_living_room
- light.xy_led_toillet
- light.temp_led_room1
- light.temp_led_room2
3. and add to the automation section:
- alias: 'Circadian Lights'
trigger:
platform: time
minutes: '/5'
seconds: 0
action:
service: circadian_lights.change_color
and voilá! Restart HA and you will have the sun in your house and night lights 'friendly' of your circadian cycle.
NOTE: The effect will only apply to lights that are on!
"""
import datetime
import logging
import voluptuous as vol
import homeassistant.helpers.config_validation as cv
from homeassistant.components.light import (
ATTR_PROFILE, ATTR_TRANSITION, ATTR_BRIGHTNESS, ATTR_COLOR_TEMP,
ATTR_RGB_COLOR, ATTR_XY_COLOR,
DOMAIN as DOMAIN_LIGHT)
from homeassistant.const import (
ATTR_ENTITY_ID, SERVICE_TURN_OFF, SERVICE_TURN_ON)
from homeassistant.core import callback
from homeassistant.components import light, sun
from homeassistant.helpers.sun import get_astral_event_next
from homeassistant.const import MATCH_ALL
from homeassistant.util.dt import as_utc, parse_time
from homeassistant.util.color import (color_temperature_to_rgb, color_RGB_to_xy,
color_temperature_kelvin_to_mired)
_LOGGER = logging.getLogger(__name__)
DOMAIN = 'circadian_lights'
DEPENDENCIES = ['light', 'sun']
SERVICE_CHANGE_COLOR = 'change_color'
CONF_MINK = 'min_kelvin'
CONF_MAXK = 'max_kelvin'
CONF_LIGHTS = 'lights'
#Warm point sunrise/sunset
KELVIN_MIN = 2750
#Cold point midday
KELVIN_MAX = 3500
CONFIG_SCHEMA = vol.Schema({
DOMAIN: vol.Schema({
vol.Optional(CONF_MINK, default=KELVIN_MIN): cv.positive_int,
vol.Optional(CONF_MAXK, default=KELVIN_MAX): cv.positive_int,
vol.Required(CONF_LIGHTS): cv.ensure_list,
})
}, extra=vol.ALLOW_EXTRA)
class Color(object):
"""Attributes for several color models."""
def __init__(self, value, kmin, kmax):
self.value = value
self.kelvins = kmin + (value * (kmax - kmin))
self.mireds = color_temperature_kelvin_to_mired(self.kelvins)
self.r, self.g, self.b = (min(int(c), 255) for c in color_temperature_to_rgb(self.kelvins))
self.x, self.y = color_RGB_to_xy(self.r, self.g, self.b)
def setup(hass, config):
"""Setup component circadian_lights."""
# Read config
kelvin_min = config[DOMAIN].get(CONF_MINK, KELVIN_MIN)
kelvin_max = config[DOMAIN].get(CONF_MAXK, KELVIN_MAX)
lights = config[DOMAIN].get(CONF_LIGHTS, MATCH_ALL) or []
_LOGGER.error('Circadian Min Kelvin: %s, Max Kelvin %s', kelvin_min, kelvin_max)
if not lights:
_LOGGER.error('Add light_ids to configuration under circadian_lights: %s', CONF_LIGHTS)
return False
def get_color():
"""Sunlight colors while day, Red for night."""
# See https://en.wikipedia.org/wiki/Color_temperature
# Get parameters
sunrise = as_utc(get_astral_event_next(hass, 'sunrise'))
sunset = as_utc(get_astral_event_next(hass, 'sunset'))
today = datetime.date.today()
now = as_utc(datetime.datetime.today())
# While is night
value = 0 # in Kelvins (rgb=RED)
if sunrise > sunset: # While is day
sunrise = sunrise - datetime.timedelta(days=1) # aprox for sunrise today
midday = sunrise + datetime.timedelta(seconds=(sunset - sunrise).total_seconds() / 2)
value = (now - sunrise) / (midday - sunrise)
if value > 1:
value = 2 - value
return Color(value, kelvin_min, kelvin_max)
def get_active_lights(lights):
"""Get the ids of active lights."""
ids = []
for light_id in lights:
if hass.states.get(light_id) is None:
_LOGGER.error('Light id %s could not be found in state machine', light_id)
continue
if light.is_on(hass, light_id):
ids.append(light_id)
return ids
def change_color(event):
"""Change color for each light (service)."""
color = get_color()
_LOGGER.info('value: %.2f, mireds: %s, Kelvin: %d',
color.value, color.mireds, color.kelvins)
light_ids = get_active_lights(lights)
if not light_ids:
return
for light_id in light_ids:
if light.is_on(hass, light_id):
_LOGGER.info('Changing color of %s', light_id)
hass.async_create_task(
hass.services.async_call(
DOMAIN_LIGHT, SERVICE_TURN_ON,
{
ATTR_ENTITY_ID: light_id,
ATTR_COLOR_TEMP: color.mireds,
#ATTR_RGB_COLOR: [color.r, color.g, color.b],
#ATTR_XY_COLOR: [color.x, color.y]
}
)
)
# Register service
hass.services.register(DOMAIN, SERVICE_CHANGE_COLOR, change_color)
return True
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment